diff --git a/debugger/breakpoint/breakpointmodel.h b/debugger/breakpoint/breakpointmodel.h index 983a72142..fd42eee96 100644 --- a/debugger/breakpoint/breakpointmodel.h +++ b/debugger/breakpoint/breakpointmodel.h @@ -1,202 +1,202 @@ /* This file is part of the KDE project Copyright (C) 2002 Matthias Hoelzer-Kluepfel Copyright (C) 2002 John Firebaugh Copyright (C) 2007 Hamish Rodda This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, see . */ #ifndef KDEVPLATFORM_BREAKPOINTMODEL_H #define KDEVPLATFORM_BREAKPOINTMODEL_H #include #include #include "breakpoint.h" class QUrl; namespace KParts { class Part; } namespace KTextEditor { class Cursor; } namespace KDevelop { class IDocument; class Breakpoint; class KDEVPLATFORMDEBUGGER_EXPORT BreakpointModel : public QAbstractTableModel { Q_OBJECT public: enum Column { /** * Whether the breakpoint is active or not (settable by user): value is Qt::Checked * or Qt::Unchecked. */ EnableColumn, /** * Synchronization state of the breakpoint (not settable by user): value is one of the * BreakpointState enum values. */ StateColumn, /** * Kind/type of breakpoint (never changes): value is one of the BreakpointKind * enum values. */ KindColumn, /** * Location of the breakpoint (modifiable by user); value is a string describing the * location; note that the formatting of retrieved data can be affected by a custom * BreakpointRole. */ LocationColumn, /** * Condition for conditional breakpoints (modifiable by user). */ ConditionColumn, /** * The number of times this breakpoint has been hit (cannot be modified by the user). */ HitCountColumn, /** * How many hits of the breakpoint will be ignored before the breakpoint actually stops * the program (can be modified by the user and is updated by the debugger backend). */ IgnoreHitsColumn, NumColumns }; enum ColumnFlag { EnableColumnFlag = 1 << EnableColumn, StateColumnFlag = 1 << StateColumn, KindColumnFlag = 1 << KindColumn, LocationColumnFlag = 1 << LocationColumn, ConditionColumnFlag = 1 << ConditionColumn, HitCountColumnFlag = 1 << HitCountColumn, IgnoreHitsColumnFlag = 1 << IgnoreHitsColumn }; Q_DECLARE_FLAGS(ColumnFlags, ColumnFlag) explicit BreakpointModel(QObject* parent); virtual ~BreakpointModel(); QVariant headerData(int section, Qt::Orientation orientation, int role) const override; Qt::ItemFlags flags(const QModelIndex &index) const override; QModelIndex breakpointIndex(Breakpoint *b, int column); - virtual bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override; - virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; - virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override; + bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; ///Note: to retrieve the full path use Breakpoint::LocationRole, Qt::DisplayRole returns only a file's name - virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; void toggleBreakpoint(const QUrl &url, const KTextEditor::Cursor& cursor); KDevelop::Breakpoint* addCodeBreakpoint(); KDevelop::Breakpoint* addCodeBreakpoint(const QUrl& location, int line); KDevelop::Breakpoint* addCodeBreakpoint(const QString& expression); KDevelop::Breakpoint* addWatchpoint(); KDevelop::Breakpoint* addWatchpoint(const QString& expression); KDevelop::Breakpoint* addReadWatchpoint(); KDevelop::Breakpoint* addReadWatchpoint(const QString& expression); KDevelop::Breakpoint* addAccessWatchpoint(); KDevelop::Breakpoint* addAccessWatchpoint(const QString& expression); Breakpoint *breakpoint(int row); QList breakpoints() const; Q_SIGNALS: void error(int row, const QString& errorText); void hit(int row); public Q_SLOTS: void save(); void load(); private: enum MarkType { BreakpointMark = KTextEditor::MarkInterface::BreakpointActive, ReachedBreakpointMark = KTextEditor::MarkInterface::BreakpointReached, DisabledBreakpointMark = KTextEditor::MarkInterface::BreakpointDisabled, PendingBreakpointMark = KTextEditor::MarkInterface::markType08, AllBreakpointMarks = BreakpointMark | ReachedBreakpointMark | DisabledBreakpointMark | PendingBreakpointMark }; private Q_SLOTS: void updateMarks(); void slotPartAdded(KParts::Part* part); /** * Called by the TextEditor interface when the marks have changed position * because the user has added or removed source. * In here we figure out if we need to reset the breakpoints due to * these source changes. */ void markChanged(KTextEditor::Document *document, KTextEditor::Mark mark, KTextEditor::MarkInterface::MarkChangeAction action); void textDocumentCreated(KDevelop::IDocument*); void documentSaved(KDevelop::IDocument*); void aboutToDeleteMovingInterfaceContent(KTextEditor::Document *document); void markContextMenuRequested( KTextEditor::Document* document, KTextEditor::Mark mark, const QPoint &pos, bool& handled ); private: static const QPixmap* breakpointPixmap(); static const QPixmap* pendingBreakpointPixmap(); static const QPixmap* reachedBreakpointPixmap(); static const QPixmap* disabledBreakpointPixmap(); private: friend class Breakpoint; friend class IBreakpointController; void updateState(int row, Breakpoint::BreakpointState state); void updateHitCount(int row, int hitCount); void updateErrorText(int row, const QString& errorText); void notifyHit(int row); void registerBreakpoint(Breakpoint* breakpoint); void scheduleSave(); void reportChange(Breakpoint *breakpoint, Breakpoint::Column column); uint breakpointType(Breakpoint *breakpoint); Breakpoint *breakpoint(const QUrl& url, int line); bool m_dirty = false; bool m_dontUpdateMarks; QList m_breakpoints; }; } Q_DECLARE_OPERATORS_FOR_FLAGS(KDevelop::BreakpointModel::ColumnFlags) #endif diff --git a/documentation/documentationfindwidget.h b/documentation/documentationfindwidget.h index cb800f5c9..9355c2257 100644 --- a/documentation/documentationfindwidget.h +++ b/documentation/documentationfindwidget.h @@ -1,61 +1,61 @@ /* * This file is part of KDevelop * Copyright 2010 Aleix Pol Gonzalez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_DOCUMENTATIONFINDWIDGET_H #define KDEVPLATFORM_DOCUMENTATIONFINDWIDGET_H #include #include "documentationexport.h" namespace Ui { class FindWidget; } namespace KDevelop { class KDEVPLATFORMDOCUMENTATION_EXPORT DocumentationFindWidget : public QWidget { Q_OBJECT public: enum FindOption { Next = 1, Previous = 2, MatchCase = 4 }; Q_DECLARE_FLAGS(FindOptions, FindOption); explicit DocumentationFindWidget(QWidget* parent = nullptr); virtual ~DocumentationFindWidget(); - virtual void showEvent ( QShowEvent* ) override; + void showEvent ( QShowEvent* ) override; private Q_SLOTS: void startSearch(); void searchNext(); void searchPrevious(); Q_SIGNALS: void newSearch(const QString& text, KDevelop::DocumentationFindWidget::FindOptions); private: Ui::FindWidget* m_ui; }; } #endif // KDEVPLATFORM_DOCUMENTATIONFINDWIDGET_H diff --git a/interfaces/context.h b/interfaces/context.h index 39faeaead..3a82b3642 100644 --- a/interfaces/context.h +++ b/interfaces/context.h @@ -1,212 +1,212 @@ /* This file is part of KDevelop Copyright 2001-2002 Matthias Hoelzer-Kluepfel Copyright 2001-2002 Bernd Gehrmann Copyright 2001 Sandy Meier Copyright 2002 Daniel Engelschalt Copyright 2002 Simon Hausmann Copyright 2002-2003 Roberto Raggi Copyright 2003 Mario Scalas Copyright 2003 Harald Fernengel Copyright 2003,2006 Hamish Rodda Copyright 2004 Alexander Dymo Copyright 2006 Adam Treat Copyright 2007 Andreas Pakulat This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_CONTEXT_H #define KDEVPLATFORM_CONTEXT_H #include "interfacesexport.h" #include #include #include template class QList; namespace KDevelop { class ProjectBaseItem; /** Base class for every context. Think of a Context-based class as "useful information associated with a context menu". When a context menu with a certain "context" associated appears, the platform's PluginController requests all plugins to return a list of QActions* they want to add to the context menu and a QString that should be used as the submenu entry. For example, a SVN plugin could add "commit" and "update" actions to the context menu of a document in a submenu called "Subversion". The plugin that originally gets the contextmenu event shouldn't add its own actions directly to the menu but instead use the same mechanism. How to show a context menu from a plugin: -# Create a QMenu in context menu event handler: @code QMenu menu(this); @endcode -# Create a context: @code FileContext context(list). @endcode -# Query for plugins: @code @code QList extensions = ICore::self()->pluginController()->queryPluginsForContextMenuExtensions( context ); @endcode -# Populate the menu: @code ContextMenuExtension::populateMenu(menu, extensions); @endcode -# Show the popup menu: @code menu.exec(mapToGlobal(pos)); @endcode How to fill a context menu from a plugin: -# Implement the @code contextMenuExtension(Context*) @endcode function in your plugin class. -# Depending on the context fill the returned ContextMenuExtension with actions:\n @code ContextMenuExtension ext; if (context->hasType(Context::EditorContext)) { ext.addAction(ContextMenuExtension::EditorGroup, new QAction(...)); } else if context->hasType(Context::FileContext)) { ext.addAction(ContextMenuExtension::FileGroup, new QAction(...)); ... } return ext; @endcode */ class KDEVPLATFORMINTERFACES_EXPORT Context { public: /**Destructor.*/ virtual ~Context(); /**Pre-defined context types. More may be added so it is possible to add custom contexts. We reserve enum values until 1000 (yeah, it is one thousand ) for kdevplatform official context types.*/ enum Type { FileContext, /** urls() const = 0; /**@return The type of this Context, so clients can discriminate between different file contexts.*/ bool hasType( int type ) const; protected: /**Constructor.*/ Context(); private: class ContextPrivate* const d; Q_DISABLE_COPY(Context) }; /** A context for the a list of selected urls. */ class KDEVPLATFORMINTERFACES_EXPORT FileContext : public Context { public: /**Builds the file context using a @ref QList @param urls The list of selected url.*/ explicit FileContext( const QList &urls ); /**Destructor.*/ virtual ~FileContext(); - virtual int type() const override; + int type() const override; /**@return A reference to the selected URLs.*/ - virtual QList urls() const override; + QList urls() const override; private: class FileContextPrivate* const d; Q_DISABLE_COPY(FileContext) }; /** A context for ProjectItem's. */ class KDEVPLATFORMINTERFACES_EXPORT ProjectItemContext : public Context { public: /**Builds the context. @param items The items to build the context from.*/ explicit ProjectItemContext( const QList &items ); /**Destructor.*/ virtual ~ProjectItemContext(); - virtual int type() const override; + int type() const override; /** * @return The project model items for the selected items. */ QList items() const; private: class ProjectItemContextPrivate* const d; Q_DISABLE_COPY(ProjectItemContext) }; /** * Context menu to open files with custom applications. */ class KDEVPLATFORMINTERFACES_EXPORT OpenWithContext : public Context { public: /** * @p url The files to open. * @p mimeType The mime type of said file. */ OpenWithContext(const QList& urls, const QMimeType& mimeType); virtual ~OpenWithContext(); /** * @return Context::OpenWithContext */ - virtual int type() const override; + int type() const override; /** * @return The files to open. */ - virtual QList urls() const override; + QList urls() const override; /** * @return The mimetype of the url to open. */ QMimeType mimeType() const; private: class OpenWithContextPrivate* const d; Q_DISABLE_COPY(OpenWithContext) }; } #endif diff --git a/language/codecompletion/normaldeclarationcompletionitem.h b/language/codecompletion/normaldeclarationcompletionitem.h index e632daa01..c8a169292 100644 --- a/language/codecompletion/normaldeclarationcompletionitem.h +++ b/language/codecompletion/normaldeclarationcompletionitem.h @@ -1,66 +1,66 @@ /* * KDevelop Generic Code Completion Support * * Copyright 2007-2008 David Nolden * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_NORMALDECLARATIONCOMPLETIONITEM_H #define KDEVPLATFORM_NORMALDECLARATIONCOMPLETIONITEM_H #include "codecompletionitem.h" #include namespace KDevelop { class KDEVPLATFORMLANGUAGE_EXPORT NormalDeclarationCompletionItem : public CompletionTreeItem { public: explicit NormalDeclarationCompletionItem(KDevelop::DeclarationPointer decl = KDevelop::DeclarationPointer(), QExplicitlySharedDataPointer context=QExplicitlySharedDataPointer(), int inheritanceDepth = 0); - virtual KDevelop::DeclarationPointer declaration() const override; + KDevelop::DeclarationPointer declaration() const override; QExplicitlySharedDataPointer completionContext() const; - virtual int inheritanceDepth() const override; - virtual int argumentHintDepth() const override; + int inheritanceDepth() const override; + int argumentHintDepth() const override; QVariant data(const QModelIndex& index, int role, const KDevelop::CodeCompletionModel* model) const override; void execute(KTextEditor::View* document, const KTextEditor::Range& word) override; protected: virtual QString declarationName() const; virtual QWidget* createExpandingWidget(const KDevelop::CodeCompletionModel* model) const; virtual bool createsExpandingWidget() const; virtual QString shortenedTypeString(KDevelop::DeclarationPointer decl, int desiredTypeLength) const; /** * Called after execute, you may insert additional chars for this declaration (eg. parens) * Default implementation does nothing */ virtual void executed(KTextEditor::View* view, const KTextEditor::Range& word); QExplicitlySharedDataPointer m_completionContext; KDevelop::DeclarationPointer m_declaration; int m_inheritanceDepth; //Inheritance-depth: 0 for local functions(within no class), 1 for within local class, 1000+ for global items. static const int normalBestMatchesCount; static const bool shortenArgumentHintReturnValues; static const int maximumArgumentHintReturnValueLength; static const int desiredTypeLength; }; } #endif diff --git a/language/codegen/archivetemplateloader.h b/language/codegen/archivetemplateloader.h index 897c6e5f2..c724038c7 100644 --- a/language/codegen/archivetemplateloader.h +++ b/language/codegen/archivetemplateloader.h @@ -1,74 +1,74 @@ /* This file is part of KDevelop Copyright 2012 Miha Čančula This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_ARCHIVETEMPLATELOADER_H #define KDEVPLATFORM_ARCHIVETEMPLATELOADER_H #include class KArchiveDirectory; namespace KDevelop { class ArchiveTemplateLocation; class ArchiveTemplateLoader : public Grantlee::AbstractTemplateLoader { public: static ArchiveTemplateLoader* self(); virtual ~ArchiveTemplateLoader(); - virtual bool canLoadTemplate(const QString& name) const override; - virtual Grantlee::Template loadByName(const QString& name, const Grantlee::Engine* engine) const override; + bool canLoadTemplate(const QString& name) const override; + Grantlee::Template loadByName(const QString& name, const Grantlee::Engine* engine) const override; - virtual QPair getMediaUri(const QString& fileName) const override; + QPair getMediaUri(const QString& fileName) const override; protected: friend class ArchiveTemplateLocation; void addLocation(ArchiveTemplateLocation* location); void removeLocation(ArchiveTemplateLocation* location); private: Q_DISABLE_COPY(ArchiveTemplateLoader) ArchiveTemplateLoader(); class ArchiveTemplateLoaderPrivate* const d; }; /** * RAII class that should be used to add KArchiveDirectory locations to the engine. * * Adds the archive @p directory to the list of places searched for templates * during the lifetime of the created ArchiveTemplateLocation class. */ class ArchiveTemplateLocation { public: explicit ArchiveTemplateLocation(const KArchiveDirectory* directory); ~ArchiveTemplateLocation(); bool hasTemplate(const QString& name) const; QString templateContents(const QString& name) const; private: const KArchiveDirectory* m_directory; }; } #endif // KDEVPLATFORM_ARCHIVETEMPLATELOADER_H diff --git a/language/duchain/aliasdeclaration.h b/language/duchain/aliasdeclaration.h index 75cfd992e..8dc5daa8b 100644 --- a/language/duchain/aliasdeclaration.h +++ b/language/duchain/aliasdeclaration.h @@ -1,95 +1,95 @@ /* This file is part of KDevelop Copyright 2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_ALIASDECLARATION_H #define KDEVPLATFORM_ALIASDECLARATION_H #include "classmemberdeclaration.h" #include "classmemberdeclarationdata.h" #include "duchainpointer.h" #include "declarationdata.h" namespace KDevelop { class KDEVPLATFORMLANGUAGE_EXPORT AliasDeclarationData : public ClassMemberDeclarationData { public: AliasDeclarationData() {} AliasDeclarationData( const AliasDeclarationData& rhs ) : ClassMemberDeclarationData( rhs ) , m_aliasedDeclaration(rhs.m_aliasedDeclaration) { } IndexedDeclaration m_aliasedDeclaration; }; /** * An alias declaration maps one declaration to another. * While searching in the duchain, an AliasDeclaration is transparently * replaced by its aliased declaration. */ class KDEVPLATFORMLANGUAGE_EXPORT AliasDeclaration : public ClassMemberDeclaration { public: /// Copy constructor \param rhs declaration to copy AliasDeclaration(const AliasDeclaration& rhs); /** * Constructs an AliasDeclaration. The default value for isNamespaceAlias is true. * * \param range range of the alias declaration's identifier * \param context context in which this declaration occurred */ AliasDeclaration(const RangeInRevision& range, DUContext* context); explicit AliasDeclaration(AliasDeclarationData& data); /// Destructor virtual ~AliasDeclaration(); /** * An AliasDeclaration cannot have a type, so setAbstractType does nothing here. * * \param type ignored type */ - virtual void setAbstractType(AbstractType::Ptr type) override; + void setAbstractType(AbstractType::Ptr type) override; /** * Set the declaration that is aliased by this declaration. * * \param decl the declaration that this declaration references */ void setAliasedDeclaration(const IndexedDeclaration& decl); /** * Access the declaration that is aliased by this declaration. * * \returns the aliased declaration */ IndexedDeclaration aliasedDeclaration() const; - virtual QString toString() const override; + QString toString() const override; enum { Identity = 6 }; private: - virtual Declaration* clonePrivate() const override; + Declaration* clonePrivate() const override; DUCHAIN_DECLARE_DATA(AliasDeclaration) }; } #endif // KDEVPLATFORM_FUNCTIONDECLARATION_H diff --git a/language/duchain/classdeclaration.h b/language/duchain/classdeclaration.h index 457cff69a..636946c24 100644 --- a/language/duchain/classdeclaration.h +++ b/language/duchain/classdeclaration.h @@ -1,140 +1,140 @@ /* This file is part of KDevelop Copyright 2008 David Nolden Copyright 2009 Lior Mualem This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_CLASSDECLARATION_H #define KDEVPLATFORM_CLASSDECLARATION_H #include #include #include #include namespace KDevelop { class DUContext; class TopDUContext; } namespace KDevelop { struct KDEVPLATFORMLANGUAGE_EXPORT BaseClassInstance { KDevelop::IndexedType baseClass; //May either be StructureType, or DelayedType KDevelop::Declaration::AccessPolicy access; bool virtualInheritance; }; KDEVPLATFORMLANGUAGE_EXPORT DECLARE_LIST_MEMBER_HASH(ClassDeclarationData, baseClasses, BaseClassInstance) class KDEVPLATFORMLANGUAGE_EXPORT ClassDeclarationData : public KDevelop::ClassMemberDeclarationData { public: enum ClassType { Class, Struct, Union, Interface, Trait }; enum ClassModifier { Final, Abstract, None }; ClassDeclarationData() : m_classType(Class), m_classModifier(None) { initializeAppendedLists(); } ~ClassDeclarationData() { freeAppendedLists(); } ClassDeclarationData(const ClassDeclarationData& rhs) : KDevelop::ClassMemberDeclarationData(rhs) { initializeAppendedLists(); copyListsFrom(rhs); m_classType = rhs.m_classType; m_classModifier = rhs.m_classModifier; } /// Type of the class (struct, class, etc.) ClassType m_classType; /// Modifier of the class (final, abstract, etc.) ClassModifier m_classModifier; START_APPENDED_LISTS_BASE(ClassDeclarationData, KDevelop::ClassMemberDeclarationData); APPENDED_LIST_FIRST(ClassDeclarationData, BaseClassInstance, baseClasses); END_APPENDED_LISTS(ClassDeclarationData, baseClasses); }; /** * Represents a single template-parameter definition */ class KDEVPLATFORMLANGUAGE_EXPORT ClassDeclaration : public KDevelop::ClassMemberDeclaration { public: ClassDeclaration(const ClassDeclaration& rhs); explicit ClassDeclaration(ClassDeclarationData& data); ClassDeclaration(const KDevelop::RangeInRevision& range, KDevelop::DUContext* context); ClassDeclaration(ClassDeclarationData& data, const KDevelop::RangeInRevision& range, KDevelop::DUContext* context); ~ClassDeclaration(); void clearBaseClasses(); ///Count of base-classes uint baseClassesSize() const; ///The types this class is based on const BaseClassInstance* baseClasses() const; void addBaseClass(const BaseClassInstance& klass); //Replaces the n'th base-class with the given one. The replaced base-class must have existed. void replaceBaseClass(uint n, const BaseClassInstance& klass); /**Returns whether base is a public base-class of this class * @param baseConversionLevels If nonzero, this will count the distance of the classes. * */ bool isPublicBaseClass( ClassDeclaration* base, const KDevelop::TopDUContext* topContext, int* baseConversionLevels = nullptr ) const; QString toString() const override; void setClassType(ClassDeclarationData::ClassType type); ClassDeclarationData::ClassType classType() const; void setClassModifier(ClassDeclarationData::ClassModifier modifier); ClassDeclarationData::ClassModifier classModifier() const; enum { Identity = 17 }; private: - virtual KDevelop::Declaration* clonePrivate() const override; + KDevelop::Declaration* clonePrivate() const override; DUCHAIN_DECLARE_DATA(ClassDeclaration) }; } Q_DECLARE_TYPEINFO(KDevelop::BaseClassInstance, Q_MOVABLE_TYPE); #endif // KDEVPLATFORM_CLASSDECLARATION_H diff --git a/language/duchain/classfunctiondeclaration.h b/language/duchain/classfunctiondeclaration.h index 4ed1ea67c..3cae23f75 100644 --- a/language/duchain/classfunctiondeclaration.h +++ b/language/duchain/classfunctiondeclaration.h @@ -1,124 +1,124 @@ /* This file is part of KDevelop Copyright 2002-2005 Roberto Raggi Copyright 2006 Adam Treat Copyright 2006 Hamish Rodda Copyright 2007-2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_CLASSFUNCTIONDECLARATION_H #define KDEVPLATFORM_CLASSFUNCTIONDECLARATION_H #include "classmemberdeclaration.h" #include "abstractfunctiondeclaration.h" #include "classmemberdeclarationdata.h" namespace KDevelop { enum ClassFunctionFlags { FunctionFlagNormal = 0, FunctionSignalFlag = 1 << 1, FunctionSlotFlag = 1 << 2, AbstractFunctionFlag = 1 << 3, FinalFunctionFlag = 1 << 4 }; KDEVPLATFORMLANGUAGE_EXPORT DECLARE_LIST_MEMBER_HASH(ClassFunctionDeclarationData, m_defaultParameters, IndexedString) class KDEVPLATFORMLANGUAGE_EXPORT ClassFunctionDeclarationData : public ClassMemberDeclarationData, public AbstractFunctionDeclarationData { public: ClassFunctionDeclarationData() { initializeAppendedLists(); m_functionFlags = FunctionFlagNormal; } ClassFunctionDeclarationData( const ClassFunctionDeclarationData& rhs ) : ClassMemberDeclarationData( rhs ), AbstractFunctionDeclarationData(rhs) { initializeAppendedLists(); copyListsFrom(rhs); m_functionFlags = rhs.m_functionFlags; } ~ClassFunctionDeclarationData() { freeAppendedLists(); } ClassFunctionFlags m_functionFlags; START_APPENDED_LISTS_BASE(ClassFunctionDeclarationData, ClassMemberDeclarationData); APPENDED_LIST_FIRST(ClassFunctionDeclarationData, IndexedString, m_defaultParameters); END_APPENDED_LISTS(ClassFunctionDeclarationData, m_defaultParameters); }; /** * Represents a single variable definition in a definition-use chain. */ typedef MergeAbstractFunctionDeclaration ClassFunctionDeclarationBase; class KDEVPLATFORMLANGUAGE_EXPORT ClassFunctionDeclaration : public ClassFunctionDeclarationBase { public: ClassFunctionDeclaration(const RangeInRevision& range, DUContext* context); ClassFunctionDeclaration(ClassFunctionDeclarationData& data, const RangeInRevision& range, DUContext* context); explicit ClassFunctionDeclaration(ClassFunctionDeclarationData& data); ~ClassFunctionDeclaration(); ///Whether this function is a signal, for example a C++ Qt signal bool isSignal() const; void setIsSignal(bool); ///Whether this function is a slot, for example a C++ Qt slot bool isSlot() const; void setIsSlot(bool); ///Whether this function is abstract bool isAbstract() const; void setIsAbstract(bool); ///Whether this function is final bool isFinal() const; void setIsFinal(bool); virtual bool isConstructor() const; virtual bool isDestructor() const; bool isConversionFunction() const; bool isFunctionDeclaration() const override; - virtual QString toString() const override; + QString toString() const override; - virtual void setAbstractType(AbstractType::Ptr type) override; + void setAbstractType(AbstractType::Ptr type) override; - virtual Declaration* clonePrivate() const override; + Declaration* clonePrivate() const override; - virtual uint additionalIdentity() const override; + uint additionalIdentity() const override; - virtual const IndexedString* defaultParameters() const override; - virtual unsigned int defaultParametersSize() const override; - virtual void addDefaultParameter(const IndexedString& str) override; - virtual void clearDefaultParameters() override; + const IndexedString* defaultParameters() const override; + unsigned int defaultParametersSize() const override; + void addDefaultParameter(const IndexedString& str) override; + void clearDefaultParameters() override; enum { Identity = 14 }; protected: ClassFunctionDeclaration(const ClassFunctionDeclaration& rhs); private: DUCHAIN_DECLARE_DATA(ClassFunctionDeclaration) }; } #endif // KDEVPLATFORM_CLASSFUNCTIONDECLARATION_H diff --git a/language/duchain/classmemberdeclaration.h b/language/duchain/classmemberdeclaration.h index fd052bcae..38ebac49d 100644 --- a/language/duchain/classmemberdeclaration.h +++ b/language/duchain/classmemberdeclaration.h @@ -1,107 +1,107 @@ /* This file is part of KDevelop Copyright 2002-2005 Roberto Raggi Copyright 2006 Adam Treat Copyright 2006 Hamish Rodda Copyright 2007-2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_CLASSMEMBERDECLARATION_H #define KDEVPLATFORM_CLASSMEMBERDECLARATION_H #include "declaration.h" namespace KDevelop { class ClassMemberDeclarationData; /** * Represents a single class member definition in a definition-use chain. */ class KDEVPLATFORMLANGUAGE_EXPORT ClassMemberDeclaration : public Declaration { public: ClassMemberDeclaration(const ClassMemberDeclaration& rhs); ClassMemberDeclaration(const RangeInRevision& range, DUContext* context); explicit ClassMemberDeclaration(ClassMemberDeclarationData& dd); ~ClassMemberDeclaration(); AccessPolicy accessPolicy() const; void setAccessPolicy(AccessPolicy accessPolicy); enum StorageSpecifier { StaticSpecifier = 0x1 /**< indicates static member */, AutoSpecifier = 0x2 /**< indicates automatic determination of member access */, FriendSpecifier = 0x4 /**< indicates friend member */, ExternSpecifier = 0x8 /**< indicates external declaration */, RegisterSpecifier = 0x10 /**< indicates register */, MutableSpecifier = 0x20 /**< indicates a mutable member */, FinalSpecifier = 0x40 /**< indicates a final declaration */, NativeSpecifier = 0x80, SynchronizedSpecifier = 0x100, StrictFPSpecifier = 0x200, AbstractSpecifier = 0x400 }; Q_DECLARE_FLAGS(StorageSpecifiers, StorageSpecifier) void setStorageSpecifiers(StorageSpecifiers specifiers); bool isStatic() const; void setStatic(bool isStatic); bool isAuto() const; void setAuto(bool isAuto); bool isFriend() const; void setFriend(bool isFriend); bool isRegister() const; void setRegister(bool isRegister); bool isExtern() const; void setExtern(bool isExtern); bool isMutable() const; void setMutable(bool isMutable); bool isNative() const; void setNative(bool native); bool isSynchronized() const; void setSynchronized(bool synchronized); bool isStrictFP() const; void setStrictFP(bool strictFP); bool isAbstract() const; void setAbstract(bool abstract); enum { Identity = 9 }; protected: ClassMemberDeclaration(ClassMemberDeclarationData& dd, const RangeInRevision& range); DUCHAIN_DECLARE_DATA(ClassMemberDeclaration) private: - virtual Declaration* clonePrivate() const override; + Declaration* clonePrivate() const override; }; } Q_DECLARE_OPERATORS_FOR_FLAGS(KDevelop::ClassMemberDeclaration::StorageSpecifiers) #endif // KDEVPLATFORM_CLASSMEMBERDECLARATION_H diff --git a/language/duchain/declaration.h b/language/duchain/declaration.h index 7f6d1a04d..34542b9d5 100644 --- a/language/duchain/declaration.h +++ b/language/duchain/declaration.h @@ -1,570 +1,570 @@ /* This file is part of KDevelop Copyright 2006 Hamish Rodda Copyright 2007-2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_DECLARATION_H #define KDEVPLATFORM_DECLARATION_H #include #include #include "types/abstracttype.h" #include "duchainbase.h" #include "instantiationinformation.h" #include "identifier.h" #include "indexeddeclaration.h" class QByteArray; namespace KDevelop { class AbstractType; class DUContext; class IndexedString; class DeclarationData; class DeclarationId; class Declaration; class IndexedTopDUContext; class TopDUContext; /** * \short Represents a single declaration in a definition-use chain. * * \note A du-context can be freely edited as long as it's parent-context is zero. * In the moment the parent-context is set, the context may only be edited when it * is allowed to edited it's top-level context (@see TopLevelContext::inDUChain()) */ class KDEVPLATFORMLANGUAGE_EXPORT Declaration : public DUChainBase { public: /// Access types enum AccessPolicy : quint8 { Public /**< a public declaration */, Protected /**< a protected declaration */, Private /**< a private declaration */, DefaultAccess /** TypePtr type() const { return TypePtr::dynamicCast(abstractType()); } /** * Access this declaration's type. * * \note You should not compare or permanently store instances of AbstractType::Ptr. Use IndexedType instead. * \returns this declaration's type, or null if none has been assigned. */ AbstractType::Ptr abstractType() const; /** * Set this declaration's type. * * \param type the type to assign. */ template void setType(TypePtr type) { setAbstractType(AbstractType::Ptr::staticCast(type)); } /** * Set this declaration's \a type. * * \param type this declaration's new type. */ virtual void setAbstractType(AbstractType::Ptr type); /** * Return an indexed form of this declaration's type. * Should be preferred, this is the fastest way, and the correct way for doing equality-comparsion. * * \returns the declaration's type. */ IndexedType indexedType() const; /** * Set this declaration's \a identifier. * * \param identifier this declaration's new identifier */ void setIdentifier(const Identifier& identifier); /** * Access this declaration's \a identifier. * * \returns this declaration's identifier. */ Identifier identifier() const; /** * Access this declaration's \a identifier. * * \return this declaration's identifier in indexed form. This is faster than identifier(), because it * equals the internal representation. Use this for example to do equality-comparison. */ const IndexedIdentifier& indexedIdentifier() const; /** * Determine the global qualified identifier of this declaration. * * \note This function is expensive, equalQualifiedIdentifier() is preferred if you * just want to compare equality. */ QualifiedIdentifier qualifiedIdentifier() const; /** * Compares the qualified identifier of this declaration with the other one, without needing to compute it. * This is more efficient than comparing the results of qualifiedIdentifier(). * * \param rhs declaration to compare identifiers with * \returns true if the identifiers are equal, otherwise false. */ bool equalQualifiedIdentifier(const Declaration* rhs) const; /** * Returns the kind of this declaration. @see Kind */ Kind kind() const; /** * Set the kind. * * \param kind new kind */ void setKind(Kind kind); /** * Returns the comment associated to this declaration in the source-code, * or an invalid string if there is none. * * Stored in utf-8 encoding. */ QByteArray comment() const; /** * Sets the comment for this declaration. * * @note Should be utf-8 encoded. */ void setComment(const QByteArray& str); /** * Sets the comment for this declaration. */ void setComment(const QString& str); /** * Access whether this declaration is in the symbol table. * * \returns true if this declaration is in the symbol table, otherwise false. */ bool inSymbolTable() const; /** * Adds or removes this declaration to/from the symbol table. * * \param inSymbolTable true to add this declaration to the symbol table, false to remove it. */ virtual void setInSymbolTable(bool inSymbolTable); /** * Equivalence operator. * * \param other Other declaration to compare. * \returns true if the declarations are equal, otherwise false. */ bool operator==(const Declaration& other) const; /** * Determine this declaration as a string. \returns this declaration as a string. */ virtual QString toString() const; /** * Returns a map of files to use-ranges. * * The key of the returned map is an url of a file. The value * is a list with all use-ranges of this declaration in that file. * * \note The ranges are in the documents local revision, * use \c DUChainUtils::transformFromRevision or \c usesCurrentRevision() * * \note The uses are unique, no 2 uses are returend that have the same range within the same file. * * \note This is a non-trivial operation and hence expensive. */ QMap > uses() const; /** * Determines whether the declaration has any uses or not. * * Cheaper than calling uses(). */ bool hasUses() const; /** * Returns a map of files to use-ranges. * * The key of the returned map is an url of a file. The value * is a list with all use-ranges of this declaration in that file. * * \note The uses are unique, no 2 uses are returend that have the same range within the same file. * * \warning This must be called only from within the foreground, or with the foreground lock locked. * * \note This is a non-trivial operation and hence expensive. */ QMap > usesCurrentRevision() const; /** * This hash-value should differentiate between multiple different * declarations that have the same qualifiedIdentifier, but should have a different * identity, and thus own Definitions and own Uses assigned. * * Affected by function-arguments, whether this is a template-declaration, etc.. */ virtual uint additionalIdentity() const; /** * TODO document * */ virtual IndexedInstantiationInformation specialization() const; /** * \see DeclarationId * * \param forceDirect When this is true, the DeclarationId is force to be direct, * and can be resolved without a symbol-table and top-context. * The same goes for Declarations that have \c alwaysForceDirect() * set to true. */ virtual DeclarationId id(bool forceDirect = false) const; /** * Returns an index that uniquely identifies this declaration within its surrounding top-context. * * That index can be passed to \c TopDUContext::declarationFromIndex(index) to get the declaration. * This is only valid when the declaration is not a specialization (\c specialization() returns 0), * and if it is not anonymous in its context. * * \note for this to be valid, allocateOwnIndex() must have been called first. * \note the highest big of the index is always zero! * \returns the index of the declaration within its TopDUContext. */ uint ownIndex() const; /** * Whether this declaration has been inserted anonymously into its parent-context */ bool isAnonymous() const; /** * Clear the index for this declaration in the top context that was allocated with allocateOwnIndex(). */ void clearOwnIndex(); /** * Create an index to this declaration from the topContext(). Needed to be able to retrieve ownIndex(). */ void allocateOwnIndex(); /** * Returns a clone of this declaration, with the difference that the returned declaration * has no context set, i.e. \c context() returns zero. * * The declaration will not be registered anywhere, so you must care about its deletion. * * This declaration's text-range will be referenced from the clone, so the clone must not * live longer than the original. */ Declaration* clone() const; /** * Signalized that among multiple possible specializations, this one should be used in the UI from now on. * * Currently mainly used in C++ for template support. The default-implementation registers the current * specialization of this declaration to SpecializationStore if it is nonzero. */ virtual void activateSpecialization(); enum { Identity = 7 }; protected: /** * Constructor for copy constructors in subclasses. * * \param dd data to copy. * \param range text range which this object covers. */ Declaration( DeclarationData & dd, const RangeInRevision& range ); /** * Returns true if this declaration is being currently destroyed persistently, * which means that it should eventually deregister itself from persistent storage facilities. * * Only call this from destructors. */ bool persistentlyDestroying() const; DUCHAIN_DECLARE_DATA(Declaration) private: /** * Sub-classes should implement this and should copy as much information into the clone as possible without breaking the du-chain. * Sub-classes should also implement a public copy-constructor that can be used for cloning by sub-classes. * * \note You do not have to implement this for your language if you are not going to use it(the du-chain itself does not and should not depend on it). * */ virtual Declaration* clonePrivate() const; void updateCodeModel(); void rebuildDynamicData(DUContext* parent, uint ownIndex) override; friend class DUContext; friend class IndexedDeclaration; friend class LocalIndexedDeclaration; friend class TopDUContextDynamicData; DUContext* m_context; TopDUContext* m_topContext; int m_indexInTopContext; }; } #endif // KDEVPLATFORM_DECLARATION_H diff --git a/language/duchain/forwarddeclaration.h b/language/duchain/forwarddeclaration.h index 4fec0b2ff..3dbecba7a 100644 --- a/language/duchain/forwarddeclaration.h +++ b/language/duchain/forwarddeclaration.h @@ -1,91 +1,91 @@ /* This file is part of KDevelop Copyright 2006-2008 Hamish Rodda Copyright 2007-2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_FORWARDDECLARATION_H #define KDEVPLATFORM_FORWARDDECLARATION_H #include "declaration.h" #include "declarationdata.h" namespace KDevelop { class KDEVPLATFORMLANGUAGE_EXPORT ForwardDeclarationData : public DeclarationData { public: ForwardDeclarationData() { } ForwardDeclarationData( const ForwardDeclarationData& rhs ) : DeclarationData( rhs ) { } }; /** * Represents a forward declaration */ class KDEVPLATFORMLANGUAGE_EXPORT ForwardDeclaration : public Declaration { public: /** * Constructor. * * If \a context is in the symbol table, the declaration will automatically be added into the symbol table. * * \param range range of the alias declaration's identifier * \param context context in which this declaration occurred * */ ForwardDeclaration(const RangeInRevision& range, DUContext* context); explicit ForwardDeclaration(ForwardDeclarationData& data); ///Copy-constructor for cloning ForwardDeclaration(const ForwardDeclaration& rhs); /// Destructor. virtual ~ForwardDeclaration(); - virtual bool isForwardDeclaration() const override; + bool isForwardDeclaration() const override; /** * Resolved the forward-declaration using the given import-trace. * The topcontext is needed for correct functionality, and may only be * zero when the declaration is resolved starting from the top-context * the forward-declaration is contained in. * * If this forward-declaration has a type assigned that is not derived from ForwardDeclarationType, * and that is derived from IdentifiedType, the declaration of that type is returned here. * */ virtual Declaration* resolve(const TopDUContext* topContext) const; - virtual DUContext * logicalInternalContext(const TopDUContext* topContext) const override; + DUContext * logicalInternalContext(const TopDUContext* topContext) const override; - virtual QString toString() const override; + QString toString() const override; enum { Identity = 10 }; typedef Declaration BaseClass; private: - virtual Declaration* clonePrivate() const override; + Declaration* clonePrivate() const override; DUCHAIN_DECLARE_DATA(ForwardDeclaration) }; } #endif // KDEVPLATFORM_DECLARATION_H diff --git a/language/duchain/functiondeclaration.h b/language/duchain/functiondeclaration.h index 12755766f..c360d5774 100644 --- a/language/duchain/functiondeclaration.h +++ b/language/duchain/functiondeclaration.h @@ -1,93 +1,93 @@ /* This file is part of KDevelop Copyright 2002-2005 Roberto Raggi Copyright 2006 Adam Treat Copyright 2006-2007 Hamish Rodda Copyright 2007-2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_FUNCTIONDECLARATION_H #define KDEVPLATFORM_FUNCTIONDECLARATION_H #include "declaration.h" #include "abstractfunctiondeclaration.h" #include "declarationdata.h" namespace KDevelop { KDEVPLATFORMLANGUAGE_EXPORT DECLARE_LIST_MEMBER_HASH(FunctionDeclarationData, m_defaultParameters, IndexedString) class KDEVPLATFORMLANGUAGE_EXPORT FunctionDeclarationData : public DeclarationData, public AbstractFunctionDeclarationData { public: FunctionDeclarationData() { initializeAppendedLists(); } FunctionDeclarationData( const FunctionDeclarationData& rhs ) :DeclarationData( rhs ), AbstractFunctionDeclarationData(rhs) { initializeAppendedLists(); copyListsFrom(rhs); } ~FunctionDeclarationData() { freeAppendedLists(); } START_APPENDED_LISTS_BASE(FunctionDeclarationData, DeclarationData); APPENDED_LIST_FIRST(FunctionDeclarationData, IndexedString, m_defaultParameters); END_APPENDED_LISTS(FunctionDeclarationData, m_defaultParameters); }; /** * Represents a single variable definition in a definition-use chain. */ typedef MergeAbstractFunctionDeclaration FunctionDeclarationBase; class KDEVPLATFORMLANGUAGE_EXPORT FunctionDeclaration : public FunctionDeclarationBase { public: FunctionDeclaration(const FunctionDeclaration& rhs); FunctionDeclaration(const RangeInRevision& range, DUContext* context); explicit FunctionDeclaration(FunctionDeclarationData& data); FunctionDeclaration(FunctionDeclarationData& data, const KDevelop::RangeInRevision&); virtual ~FunctionDeclaration(); - virtual void setAbstractType(AbstractType::Ptr type) override; + void setAbstractType(AbstractType::Ptr type) override; - virtual QString toString() const override; + QString toString() const override; - virtual bool isFunctionDeclaration() const override; + bool isFunctionDeclaration() const override; - virtual uint additionalIdentity() const override; + uint additionalIdentity() const override; - virtual const IndexedString* defaultParameters() const override; - virtual unsigned int defaultParametersSize() const override; - virtual void addDefaultParameter(const IndexedString& str) override; - virtual void clearDefaultParameters() override; + const IndexedString* defaultParameters() const override; + unsigned int defaultParametersSize() const override; + void addDefaultParameter(const IndexedString& str) override; + void clearDefaultParameters() override; enum { Identity = 12 }; typedef Declaration Base; private: - virtual Declaration* clonePrivate() const override; + Declaration* clonePrivate() const override; DUCHAIN_DECLARE_DATA(FunctionDeclaration) }; } #endif // KDEVPLATFORM_FUNCTIONDECLARATION_H diff --git a/language/duchain/functiondefinition.h b/language/duchain/functiondefinition.h index faaeaad81..56d10e672 100644 --- a/language/duchain/functiondefinition.h +++ b/language/duchain/functiondefinition.h @@ -1,74 +1,74 @@ /* This file is part of KDevelop Copyright 2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_CLASSFUNCTIONDEFINITION_H #define KDEVPLATFORM_CLASSFUNCTIONDEFINITION_H #include "functiondeclaration.h" #include using namespace KDevelop; namespace KDevelop { class KDEVPLATFORMLANGUAGE_EXPORT FunctionDefinitionData : public FunctionDeclarationData { public: //Holds the declaration id for this definition, if this is a definition with separate declaration DeclarationId m_declaration; }; ///A FunctionDefinition represents a function-definition that is assigned to a separate function-declaration. ///It allows mapping from definition to declaration and from declaration to definition. class KDEVPLATFORMLANGUAGE_EXPORT FunctionDefinition : public FunctionDeclaration { public: FunctionDefinition(const RangeInRevision& range, DUContext* context); explicit FunctionDefinition(FunctionDefinitionData& data); ~FunctionDefinition(); /** * Find the declaration for this definition, if one exists. * * @param topContext the top-context from which to search * \returns the declaration matching this definition, otherwise null if no matching declaration has been found. * */ Declaration* declaration(const TopDUContext* topContext = nullptr) const; ///Returns true if a Declaration has been assigned to this Definition bool hasDeclaration() const; ///Attaches this definition to the given declaration persistently. void setDeclaration(Declaration* declaration); enum { Identity = 21 }; /** * Find the definition for the given declaration, if one exists. * * \returns the definition matching this declaration, otherwise null if no matching definition has been found. * */ static FunctionDefinition* definition(const Declaration* decl); protected: FunctionDefinition (const FunctionDefinition& rhs); private: - virtual Declaration* clonePrivate() const override; + Declaration* clonePrivate() const override; DUCHAIN_DECLARE_DATA(FunctionDefinition) }; } #endif diff --git a/language/duchain/namespacealiasdeclaration.h b/language/duchain/namespacealiasdeclaration.h index f72d144bb..67a0f82d7 100644 --- a/language/duchain/namespacealiasdeclaration.h +++ b/language/duchain/namespacealiasdeclaration.h @@ -1,87 +1,87 @@ /* This file is part of KDevelop Copyright 2007 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_NAMESPACEALIASDECLARATION_H #define KDEVPLATFORM_NAMESPACEALIASDECLARATION_H #include "declaration.h" #include "declarationdata.h" namespace KDevelop { class KDEVPLATFORMLANGUAGE_EXPORT NamespaceAliasDeclarationData : public DeclarationData { public: NamespaceAliasDeclarationData() {} NamespaceAliasDeclarationData( const NamespaceAliasDeclarationData& rhs ) : DeclarationData( rhs ) , m_importIdentifier(rhs.m_importIdentifier) { } IndexedQualifiedIdentifier m_importIdentifier; //The identifier that was imported }; /** * A class which represents a "using namespace" statement, or a "namespace A = B" statement. * * This class is used by the duchain search process to transparently transform the search according to * namespace aliases and namespace imports. * * A namespace import declaration must have an identifier that equals globalImportIdentifier. * * If the identifier of the declaration does not equal globalImportIdentifier, then the declaration * represents a namespace alias, where the name of the alias equals the declaration. In that case, * the declaration is additionally added to the persistent symbol table with its real scope and globalAliasIdentifer * appended, to allow an efficient lookup. */ class KDEVPLATFORMLANGUAGE_EXPORT NamespaceAliasDeclaration : public Declaration { public: NamespaceAliasDeclaration(const NamespaceAliasDeclaration& rhs); NamespaceAliasDeclaration(const RangeInRevision& range, DUContext* context); explicit NamespaceAliasDeclaration(NamespaceAliasDeclarationData& data); virtual ~NamespaceAliasDeclaration(); ///A NamespaceAliasDeclaration cannot have a type, so setAbstractType does nothing here. - virtual void setAbstractType(AbstractType::Ptr type) override; + void setAbstractType(AbstractType::Ptr type) override; /**The identifier that was imported.*/ QualifiedIdentifier importIdentifier() const; /** * The identifier must be absolute (Resolve it before setting it!) * Although the identifier is global, the explicitlyGlobal() member must not be set */ void setImportIdentifier(const QualifiedIdentifier& id); - virtual void setInSymbolTable(bool inSymbolTable) override; + void setInSymbolTable(bool inSymbolTable) override; enum { Identity = 13 }; typedef Declaration BaseClass; - virtual QString toString() const override; + QString toString() const override; private: void unregisterAliasIdentifier(); void registerAliasIdentifier(); - virtual Declaration* clonePrivate() const override; + Declaration* clonePrivate() const override; DUCHAIN_DECLARE_DATA(NamespaceAliasDeclaration) }; } #endif // KDEVPLATFORM_NAMESPACEALIASDECLARATION_H diff --git a/language/duchain/problem.h b/language/duchain/problem.h index 4a5162a5e..3a98f8dca 100644 --- a/language/duchain/problem.h +++ b/language/duchain/problem.h @@ -1,265 +1,265 @@ /* This file is part of KDevelop Copyright 2007 Hamish Rodda This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_PROBLEM_H #define KDEVPLATFORM_PROBLEM_H #include #include "../editor/documentrange.h" #include #include "duchainbase.h" #include #include "indexedtopducontext.h" #include #include namespace KDevelop { class IAssistant; class Problem; using ProblemPointer = QExplicitlySharedDataPointer; /** * Represents a problem only by its index within the top-context * * Fixme: share code with the other LocalIndexed* classes */ class KDEVPLATFORMLANGUAGE_EXPORT LocalIndexedProblem { public: LocalIndexedProblem(const ProblemPointer& problem, const TopDUContext* top); explicit LocalIndexedProblem(uint index = 0) : m_index(index) {} /** * \note Duchain must be read locked */ ProblemPointer data(const TopDUContext* top) const; bool operator==(const LocalIndexedProblem& rhs) const { return m_index == rhs.m_index; } bool isValid() const { return m_index; } /** * Index of the Declaration within the top context */ uint localIndex() const { return m_index; } private: uint m_index; }; KDEVPLATFORMLANGUAGE_EXPORT DECLARE_LIST_MEMBER_HASH(ProblemData, diagnostics, LocalIndexedProblem) class KDEVPLATFORMLANGUAGE_EXPORT ProblemData : public DUChainBaseData { public: ProblemData() : source(IProblem::Unknown) , severity(IProblem::Error) , finalLocationMode(IProblem::Range) { initializeAppendedLists(); } ProblemData(const ProblemData& rhs) : DUChainBaseData(rhs) , source(rhs.source) , severity(rhs.severity) , url(rhs.url) , description(rhs.description) , explanation(rhs.explanation) , finalLocationMode(IProblem::Range) { initializeAppendedLists(); copyListsFrom(rhs); } ~ProblemData() { freeAppendedLists(); } IProblem::Source source; IProblem::Severity severity; IndexedString url; IndexedString description; IndexedString explanation; IProblem::FinalLocationMode finalLocationMode; START_APPENDED_LISTS_BASE(ProblemData, DUChainBaseData); APPENDED_LIST_FIRST(ProblemData, LocalIndexedProblem, diagnostics); END_APPENDED_LISTS(ProblemData, diagnostics); }; /** * An object representing a problem in preprocessing, parsing, definition-use chain compilation, etc. * * You should always use ProblemPointer, because Problem may be subclassed. * The subclass would be lost while copying. * * @warning Access to problems must be serialized through DUChainLock. */ class KDEVPLATFORMLANGUAGE_EXPORT Problem : public DUChainBase, public IProblem { public: using Ptr = QExplicitlySharedDataPointer; Problem(); explicit Problem(ProblemData& data); ~Problem(); Source source() const override; void setSource(IProblem::Source source) override; /** * Returns a string version of the problem source */ QString sourceString() const override; TopDUContext* topContext() const override; KDevelop::IndexedString url() const override; /** * Location where this problem occurred * @warning Must only be called from the foreground * */ DocumentRange finalLocation() const override; void setFinalLocation(const DocumentRange& location) override; FinalLocationMode finalLocationMode() const override; void setFinalLocationMode(FinalLocationMode mode) override; /** * Returns child diagnostics of this particular problem * * Example: * @code * void foo(unsigned int); * void foo(const char*); * int main() { foo(0); } * @endcode * * => foo(0) is ambigous. This will give us a ProblemPointer pointing to 'foo(0)'. * * Additionally, @p diagnostics may return the two locations to the ambiguous overloads, * with descriptions such as 'test.cpp:1: candidate : ...' */ void clearDiagnostics() override; QVector diagnostics() const override; void setDiagnostics(const QVector &diagnostics) override; void addDiagnostic(const IProblem::Ptr &diagnostic) override; /** * A brief description of the problem. */ QString description() const override; void setDescription(const QString& description) override; /** * A (detailed) explanation of why the problem occurred. */ QString explanation() const override; void setExplanation(const QString& explanation) override; /** * Get the severity of this problem. * This is used for example to decide for a highlighting color. * * @see setSeverity() */ Severity severity() const override; /** * Set the severity of this problem. */ void setSeverity(Severity severity) override; /** * Returns a string representation of the severity. */ QString severityString() const override; /** * If this problem can be solved, this may return an assistant for the solution. */ - virtual QExplicitlySharedDataPointer solutionAssistant() const override; + QExplicitlySharedDataPointer solutionAssistant() const override; enum { Identity = 15 }; /** * Returns a string representation of this problem, useful for debugging. */ virtual QString toString() const; private: void rebuildDynamicData(DUContext* parent, uint ownIndex) override; Q_DISABLE_COPY(Problem) DUCHAIN_DECLARE_DATA(Problem) friend class TopDUContext; friend class TopDUContextDynamicData; friend class LocalIndexedProblem; //BEGIN dynamic data TopDUContextPointer m_topContext; mutable QList m_diagnostics; uint m_indexInTopContext; //END dynamic data }; class KDEVPLATFORMLANGUAGE_EXPORT StaticAssistantProblem : public KDevelop::Problem { public: KDevelop::IAssistant::Ptr solutionAssistant() const override { return m_solution; } void setSolutionAssistant(KDevelop::IAssistant::Ptr p) { m_solution = p; } private: KDevelop::IAssistant::Ptr m_solution; }; } Q_DECLARE_TYPEINFO(KDevelop::LocalIndexedProblem, Q_MOVABLE_TYPE); KDEVPLATFORMLANGUAGE_EXPORT QDebug operator<<(QDebug s, const KDevelop::Problem& problem); KDEVPLATFORMLANGUAGE_EXPORT QDebug operator<<(QDebug s, const KDevelop::ProblemPointer& problem); #endif // KDEVPLATFORM_PROBLEM_H diff --git a/language/duchain/topducontext.h b/language/duchain/topducontext.h index 71591ab58..c35c21fe6 100644 --- a/language/duchain/topducontext.h +++ b/language/duchain/topducontext.h @@ -1,376 +1,376 @@ /* This file is part of KDevelop Copyright 2006 Hamish Rodda Copyright 2007-2009 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_TOPDUCONTEXT_H #define KDEVPLATFORM_TOPDUCONTEXT_H #include "ducontext.h" #include #include template< class T > class QExplicitlySharedDataPointer; namespace KDevelop { class IAstContainer; class QualifiedIdentifier; class DUChain; class ParsingEnvironmentFile; class TopDUContextData; class TopDUContextLocalPrivate; class IndexedTopDUContext; // class TopDUContextDynamicData; class Problem; class DeclarationChecker; class TopDUContext; struct KDEVPLATFORMLANGUAGE_EXPORT RecursiveImportRepository { static Utils::BasicSetRepository* repository(); }; ///Maps an imported top-context to a pair: ///1. The distance to the top-context, and 2. The next step towards the top-context ///in the chain. typedef QHash > RecursiveImports; typedef DUChainPointer TopDUContextPointer; typedef QExplicitlySharedDataPointer ProblemPointer; ///KDevelop can unload unused top-context at any time. To prevent unloading, ///keep a ReferencedTopDUContext. class KDEVPLATFORMLANGUAGE_EXPORT ReferencedTopDUContext { public: ReferencedTopDUContext(TopDUContext* context = nullptr); ReferencedTopDUContext(const ReferencedTopDUContext& rhs); ~ReferencedTopDUContext(); ReferencedTopDUContext& operator=(const ReferencedTopDUContext& rhs); inline TopDUContext* data() const { return m_topContext; } inline operator TopDUContext*() const { return m_topContext; } inline bool operator==(const ReferencedTopDUContext& rhs) const { return m_topContext == rhs.m_topContext; } inline bool operator!=(const ReferencedTopDUContext& rhs) const { return m_topContext != rhs.m_topContext; } inline TopDUContext* operator->() const { return m_topContext; } inline uint hash() const { return (uint)(((quint64)m_topContext) * 37); } private: TopDUContext* m_topContext; }; /** * The top context in a definition-use chain for one source file. * * Implements SymbolTable lookups and locking for the chain. * * Contexts and Classes can only be found through TopDUContext if they are in the symbol table. * @see DUContext::setInSymbolTable, Declaration::setInSymbolTable * * \todo move the registration with DUChain here * * @warning Do not delete top-contexts directly, use DUChain::removeDocumentChain instead. */ class KDEVPLATFORMLANGUAGE_EXPORT TopDUContext : public DUContext { public: explicit TopDUContext(const IndexedString& url, const RangeInRevision& range, ParsingEnvironmentFile* file = nullptr); explicit TopDUContext(TopDUContextData& data); TopDUContext* topContext() const override; ///Returns an indexed representation of this top-context. Indexed representations stay valid even if the top-context is unloaded. IndexedTopDUContext indexed() const; uint ownIndex() const; IndexedString url() const override; /** * @see ParsingEnvironmentFile * May return zero if no file was set. * */ QExplicitlySharedDataPointer parsingEnvironmentFile() const; /// Returns true if this object is being deleted, otherwise false. bool deleting() const; /// Returns true if this object is registered in the du-chain. If it is not, all sub-objects(context, declarations, etc.) can be changed - virtual bool inDUChain() const override; + bool inDUChain() const override; /// This flag is only used by DUChain, never change it from outside. void setInDuChain(bool); /// Whether this top-context has a stored version on disk bool isOnDisk() const; /** * Returns a list of all problems encountered while parsing this top-context. * Does not include the problems of imported contexts. * */ QList problems() const; /** * Add a parsing-problem to this context. * * \note you must be holding a write lock when you access this function. * */ void addProblem(const ProblemPointer& problem); /** * Clear the list of problems * * \note you must be holding a write lock when you access this function. */ void clearProblems(); /** * Set the list of problems, replacing all existing ones. * * \note you must be holding a write lock when you access this function. */ void setProblems(const QList& pointers); /** * Determine if this chain imports another chain recursively. * * This uses the imports-cache for speedup if it is available, thus it is not necessarily 100% correct * if the cache is not up-to-date. * * \note you must be holding a read but not a write chain lock when you access this function. */ - virtual bool imports(const DUContext* origin, const CursorInRevision& position) const override; + bool imports(const DUContext* origin, const CursorInRevision& position) const override; enum { Identity = 4 }; enum Features : quint16 { ///Top-context features standard that can be requested from the duchain, and that are stored in the features() member. Empty = 0, //Only the top-context structure (imports etc.) is built, but no declarations and no contexts SimplifiedVisibleDeclarationsAndContexts = 2, //The top-context should only contain publically simplified accessible declarations and contexts, without doing type look-up, //without extended information like function-argument declarations, etc., imported contexts can be parsed with 'Empty' features //This flag essentially leads to a ctags-like processing level. VisibleDeclarationsAndContexts = SimplifiedVisibleDeclarationsAndContexts + 4, //Default: The top-context should only contain publically accessible declarations and contexts AllDeclarationsAndContexts = VisibleDeclarationsAndContexts + 8, //The top-context should also contain non-public declarations and contexts, but no uses AllDeclarationsContextsAndUses = 16 + AllDeclarationsAndContexts, //The top-context should contain uses and all declarations + contexts AST = 32, //Signalizes that the ast() should be filled AllDeclarationsContextsUsesAndAST = AST | AllDeclarationsContextsAndUses, //Convenience flag, combining AST and AllDeclarationsContextsAndUses ///Additional update-flags that have a special meaning during updating, but are not set stored into a top-context Recursive = 64, //Request the given features on all recursively imported contexts. Only the features are applied recursively (including AST) ForceUpdate = 128, //Enforce updating the top-context ForceUpdateRecursive = ForceUpdate | 256, //Enforce updating the top-context and all its imports ///You can define own language-dependent features behind this flag LastFeature = 512 }; ///Returns the currently active features of this top-context. The features will include AST if ast() is valid. Features features() const; ///Set the features of this top-context. These features are ignored: AST, ForceUpdate, and ForceUpdateRecursive. void setFeatures(Features); /** * Retrieves or creates a local index that is to be used for referencing the given @param declaration * in local uses. Also registers this context as a user of the declaration. * @param create If this is false, only already registered indices will be returned. * If the declaration is not registered, std::numeric_limits::max() is returned * * The duchain must be write-locked if create is true, else it must at least be read-locked. * */ int indexForUsedDeclaration(Declaration* declaration, bool create = true); /** * Tries to retrieve the used declaration * @param declarationIndex The index of the declaration which have to be retrieved * */ Declaration* usedDeclarationForIndex(unsigned int declarationIndex) const; /** * You can use this before you rebuild all uses. This does not affect any uses directly, * it only invalidates the mapping of declarationIndices to Declarations. * * usedDeclarationForIndex(..) must not be called until the use has gotten a new index through * indexForUsedDeclaration(..). * */ void clearUsedDeclarationIndices(); /** * Recursively deletes all contained uses, declaration-indices, etc. */ - virtual void deleteUsesRecursively() override; + void deleteUsesRecursively() override; /** * Returns the AST Container, that contains the AST created during parsing. * This is only created if you request the AST feature for parsing. * It may be discarded at any time. Every update without the AST feature will discard it. * The actual contents is language-specific. * * @todo Figure out logic to get rid of AST when it is not needed/useful */ QExplicitlySharedDataPointer ast() const; /** * Sets the AST Container. */ void setAst(QExplicitlySharedDataPointer ast); /** * Utility function to clear the AST Container */ void clearAst(); ///@param temporary If this is true, importers of this context will not be notified of the new imports. This greatly increases performance while removing the context, ///but creates in inconsistent import-structure. Therefore it is only suitable for temporary imports. These imports will not be visible from contexts that import this one. ///When this top-context does not own its private data, the import is added locally only to this context, not into the shared data. - virtual void addImportedParentContext(DUContext* context, const CursorInRevision& position = CursorInRevision(), bool anonymous=false, bool temporary=false) override; + void addImportedParentContext(DUContext* context, const CursorInRevision& position = CursorInRevision(), bool anonymous=false, bool temporary=false) override; ///Use this for mass-adding of imported contexts, it is faster than adding them individually. ///@param temporary If this is true, importers of this context will not be notified of the new imports. This greatly increases performance while removing the context, ///but creates in inconsistent import-structure. Therefore it is only suitable for temporary imports. These imports will not be visible from contexts that import this one. ///When this top-context does not own its private data, the import is added locally only to this context, not into the shared data. virtual void addImportedParentContexts(const QList >& contexts, bool temporary=false); ///When this top-context does not own its private data, the import is removed locally only from this context, not from the shared data. - virtual void removeImportedParentContext(DUContext* context) override; + void removeImportedParentContext(DUContext* context) override; ///Use this for mass-removing of imported contexts, it is faster than removing them individually. ///When this top-context does not own its private data, the import is removed locally only from this context, not from the shared data. virtual void removeImportedParentContexts(const QList& contexts); ///When this top-context does not own its private data, only the local imports of this context are removed, not those from the shared data. - virtual void clearImportedParentContexts() override; + void clearImportedParentContexts() override; typedef Utils::StorableSet IndexedRecursiveImports; - virtual QVector importedParentContexts() const override; + QVector importedParentContexts() const override; - virtual QVector importers() const override; + QVector importers() const override; ///Returns all currently loade importers virtual QList loadedImporters() const; - virtual CursorInRevision importPosition(const DUContext* target) const override; + CursorInRevision importPosition(const DUContext* target) const override; ///Returns the set of all recursively imported top-contexts. If import-caching is used, this returns the cached set. ///The list also contains this context itself. This set is used to determine declaration-visibility from within this top-context. const IndexedRecursiveImports& recursiveImportIndices() const; /** * Updates the cache of recursive imports. When you call this, from that moment on the set returned by recursiveImportIndices() is fixed, until * you call it again to update them. If your language has a very complex often-changing import-structure, * like for example in the case of C++, it is recommended to call this during while parsing, instead of using * the expensive builtin implicit mechanism. * Note that if you use caching, you _must_ call this before you see any visibility-effect after adding imports. * * Using import-caching has another big advantage: A top-context can be loaded without loading all its imports. * * Note: This is relatively expensive since it requires loading all imported contexts. * * When this is called, the top-context must already be registered in the duchain. */ void updateImportsCache(); bool usingImportsCache() const; - virtual bool findDeclarationsInternal(const SearchItem::PtrList& identifiers, const CursorInRevision& position, const AbstractType::Ptr& dataType, DeclarationList& ret, const TopDUContext* source, SearchFlags flags, uint depth) const override; + bool findDeclarationsInternal(const SearchItem::PtrList& identifiers, const CursorInRevision& position, const AbstractType::Ptr& dataType, DeclarationList& ret, const TopDUContext* source, SearchFlags flags, uint depth) const override; protected: void setParsingEnvironmentFile(ParsingEnvironmentFile*); /** * Does the same as DUContext::updateAliases, except that it uses the symbol-store, and processes the whole identifier. * @param canBeNamespace whether the searched identifier may be a namespace. * If this is true, namespace-aliasing is applied to the last elements of the identifiers. * */ template void applyAliases( const SearchItem::PtrList& identifiers, Acceptor& accept, const CursorInRevision& position, bool canBeNamespace ) const; protected: virtual ~TopDUContext(); void clearFeaturesSatisfied(); void rebuildDynamicData(DUContext* parent, uint ownIndex) override; //Must be called after all imported top-contexts were loaded into the du-chain void rebuildDynamicImportStructure(); struct AliasChainElement; struct FindDeclarationsAcceptor; struct DeclarationChecker; struct ApplyAliasesBuddyInfo; template bool applyAliases( const QualifiedIdentifier& previous, const SearchItem::Ptr& identifier, Acceptor& acceptor, const CursorInRevision& position, bool canBeNamespace, ApplyAliasesBuddyInfo* buddy, uint recursionDepth ) const; //Same as imports, without the slow access-check, for internal usage bool importsPrivate(const DUContext * origin, const CursorInRevision& position) const; DUCHAIN_DECLARE_DATA(TopDUContext) ///Called by DUChain::removeDocumentChain to destroy this top-context. void deleteSelf(); //Most of these classes need access to m_dynamicData friend class DUChain; friend class DUChainPrivate; friend class TopDUContextData; friend class TopDUContextLocalPrivate; friend class TopDUContextDynamicData; friend class Declaration; friend class DUContext; friend class Problem; friend class IndexedDeclaration; friend class IndexedDUContext; friend class LocalIndexedDeclaration; friend class LocalIndexedDUContext; friend class LocalIndexedProblem; friend class DeclarationId; friend class ParsingEnvironmentFile; TopDUContextLocalPrivate* m_local; class TopDUContextDynamicData* m_dynamicData; }; /** * Returns all uses of the given declaration within this top-context and all sub-contexts * */ KDEVPLATFORMLANGUAGE_EXPORT QList allUses(TopDUContext* context, Declaration* declaration, bool noEmptyRanges = false); inline uint qHash(const ReferencedTopDUContext& ctx) { return ctx.hash(); } } Q_DECLARE_METATYPE(KDevelop::ReferencedTopDUContext) #endif // KDEVPLATFORM_TOPDUCONTEXT_H diff --git a/language/duchain/types/arraytype.h b/language/duchain/types/arraytype.h index d842a090d..5b82a53a9 100644 --- a/language/duchain/types/arraytype.h +++ b/language/duchain/types/arraytype.h @@ -1,108 +1,108 @@ /* This file is part of KDevelop Copyright 2006 Roberto Raggi Copyright 2006-2008 Hamish Rodda Copyright 2007-2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_ARRAYTYPE_H #define KDEVPLATFORM_ARRAYTYPE_H #include "abstracttype.h" namespace KDevelop { class ArrayTypeData; class KDEVPLATFORMLANGUAGE_EXPORT ArrayType : public AbstractType { public: typedef TypePtr Ptr; /// Default constructor ArrayType(); /// Copy constructor. \param rhs type to copy ArrayType(const ArrayType& rhs); /// Constructor using raw data. \param data internal data. explicit ArrayType(ArrayTypeData& data); /// Destructor virtual ~ArrayType(); - virtual AbstractType* clone() const override; + AbstractType* clone() const override; - virtual bool equals(const AbstractType* rhs) const override; + bool equals(const AbstractType* rhs) const override; /** * Retrieve the dimension of this array type. Multiple-dimensioned * arrays will have another array type as their elementType(). * * \returns the dimension of the array, or zero if the array is dimensionless (eg. int[]) */ int dimension () const; /** * Set this array type's dimension. * If @p dimension is zero, the array is considered dimensionless (eg. int[]). * * \param dimension new dimension, set to zero for a dimensionless type (eg. int[]) */ void setDimension(int dimension); /** * Retrieve the element type of the array, e.g. "int" for int[3]. * * \returns the element type. */ AbstractType::Ptr elementType () const; /** * Set the element type of the array, e.g. "int" for int[3]. * * \returns the element type. */ void setElementType(AbstractType::Ptr type); - virtual QString toString() const override; + QString toString() const override; - virtual uint hash() const override; + uint hash() const override; - virtual WhichType whichType() const override; + WhichType whichType() const override; - virtual void exchangeTypes( TypeExchanger* exchanger ) override; + void exchangeTypes( TypeExchanger* exchanger ) override; enum { Identity = 7 }; typedef ArrayTypeData Data; protected: - virtual void accept0 (TypeVisitor *v) const override; + void accept0 (TypeVisitor *v) const override; TYPE_DECLARE_DATA(ArrayType) }; template<> inline ArrayType* fastCast(AbstractType* from) { if(!from || from->whichType() != AbstractType::TypeArray) return nullptr; else return static_cast(from); } } #endif // KDEVPLATFORM_TYPESYSTEM_H diff --git a/language/duchain/types/constantintegraltype.h b/language/duchain/types/constantintegraltype.h index 033e4281b..0270c3e48 100644 --- a/language/duchain/types/constantintegraltype.h +++ b/language/duchain/types/constantintegraltype.h @@ -1,121 +1,121 @@ /* This file is part of KDevelop Copyright 2002-2005 Roberto Raggi Copyright 2006 Adam Treat Copyright 2006-2008 Hamish Rodda Copyright 2007-2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_CONSTANTINTEGRALTYPE_H #define KDEVPLATFORM_CONSTANTINTEGRALTYPE_H #include "integraltype.h" #include "typesystemdata.h" namespace KDevelop { template T constant_value(const qint64* realval) { T value; memcpy(&value, realval, sizeof(T)); return value; } class KDEVPLATFORMLANGUAGE_EXPORT ConstantIntegralType : public IntegralType { public: ConstantIntegralType(const ConstantIntegralType& rhs); explicit ConstantIntegralType(ConstantIntegralTypeData& data); explicit ConstantIntegralType(uint type = TypeNone); typedef TypePtr Ptr; /**The types and modifiers are not changed! * The values are casted internally to the local representation, so you can lose precision. * */ template void setValue(ValueType value) { if(AbstractType::modifiers() & UnsignedModifier) setValueInternal(value); else if(IntegralType::dataType() == TypeFloat) setValueInternal(value); else if(IntegralType::dataType() == TypeDouble) setValueInternal(value); else setValueInternal(value); } /** * For booleans, the value is 1 for true, and 0 for false. * All signed values should be retrieved and set through value(), * * */ template ValueType value() const { if(modifiers() & UnsignedModifier) { return constant_value(&d_func()->m_value); } else if(dataType() == TypeFloat) { return constant_value(&d_func()->m_value); } else if(dataType() == TypeDouble) { return constant_value(&d_func()->m_value); } else { return constant_value(&d_func()->m_value); } } qint64 plainValue() const; - virtual QString toString() const override; + QString toString() const override; QString valueAsString() const; - virtual bool equals(const KDevelop::AbstractType* rhs) const override; + bool equals(const KDevelop::AbstractType* rhs) const override; - virtual KDevelop::AbstractType* clone() const override; + KDevelop::AbstractType* clone() const override; - virtual uint hash() const override; + uint hash() const override; enum { Identity = 14 }; typedef ConstantIntegralTypeData Data; protected: TYPE_DECLARE_DATA(ConstantIntegralType); private: //Sets the value without casting template void setValueInternal(ValueType value); }; template<> inline ConstantIntegralType* fastCast(AbstractType* from) { if(!from || from->whichType() != KDevelop::AbstractType::TypeIntegral) return nullptr; else return dynamic_cast(from); } } #endif // KDEVPLATFORM_CONSTANTINTEGRALTYPE_H diff --git a/language/duchain/types/containertypes.h b/language/duchain/types/containertypes.h index f5b28e8a6..c1dd20f1b 100644 --- a/language/duchain/types/containertypes.h +++ b/language/duchain/types/containertypes.h @@ -1,213 +1,213 @@ /** * This file is part of KDevelop * Copyright (C) 2011-2014 Sven Brauch * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this program. If not, see . **/ #ifndef KDEVPLATFORM_CONTAINER_TYPES_H #define KDEVPLATFORM_CONTAINER_TYPES_H #include "structuretype.h" #include "typesystemdata.h" #include "typeutils.h" #include "../duchainlock.h" #include namespace KDevelop { class KDEVPLATFORMLANGUAGE_EXPORT ListTypeData : public KDevelop::StructureTypeData { public: ListTypeData() : KDevelop::StructureTypeData() , m_contentType() { } ListTypeData(const ListTypeData& rhs) : KDevelop::StructureTypeData(rhs) , m_contentType(rhs.m_contentType) { } explicit ListTypeData(const KDevelop::StructureTypeData& rhs) : KDevelop::StructureTypeData(rhs) , m_contentType() { } IndexedType m_contentType; }; /** * @brief Represents a list-like object which can have a content type. * * Example for Python: * # in the file describing the built-in list type * class List: # (1) * pass * * # in the user's code: * a = [] # (2) * a.append(3) # (3) * * This type class can be used to determine the type of a as "list of int" as follows: * (1) When creating the type for the List class, * create a ListType instead of a structure type. * (Your language plugin somehow needs to know * which classes are list-like; Python does this * through special comments for the class) * (2) Set the type of a to the type declared by the * List class, as usual. * (3) Call * \code * static_cast(a->abstractType())->addContentType(int_type) * \endcode * (Your language plugin needs to know which methods * add their argument's content to the type's content; * Python does this through special comments for the method) */ class KDEVPLATFORMLANGUAGE_EXPORT ListType : public KDevelop::StructureType { public: typedef TypePtr Ptr; ListType(); ListType(const ListType& rhs); explicit ListType(StructureTypeData& data); /** * @brief Adds @p typeToAdd to the content type of this list. * * If the list currently has no type, it is set to this type. * If @p typeToAdd equals this list's content type, or is a useless type * nothing happens. * Otherwise, the type of the list becomes an unsure type of the previous * and @p typeToAdd. * * Pass your language's UnsureType as a template parameter, as it will eventually * need to be instantiated. * * @param typeToAdd The new type the list's contents can possibly be of. */ template void addContentType(AbstractType::Ptr typeToAdd) { auto newContentType = TypeUtils::mergeTypes(contentType().abstractType(), typeToAdd); DUChainWriteLocker lock; d_func_dynamic()->m_contentType = IndexedType(newContentType); } /** * @brief Replaces this list's content type by @p newType. */ void replaceContentType(AbstractType::Ptr newType); /** * @brief Get this lists's content type. */ IndexedType contentType() const; /** * @brief Return only the container type, not the content type in a string. */ QString containerToString() const; /** * @brief Formats this type (base type and content type) in a string. */ - virtual QString toString() const override; + QString toString() const override; - virtual AbstractType* clone() const override; - virtual uint hash() const override; - virtual bool equals(const AbstractType* rhs) const override; + AbstractType* clone() const override; + uint hash() const override; + bool equals(const AbstractType* rhs) const override; enum { Identity = 58 }; typedef ListTypeData Data; typedef KDevelop::StructureType BaseType; protected: TYPE_DECLARE_DATA(ListType); }; class KDEVPLATFORMLANGUAGE_EXPORT MapTypeData : public ListTypeData { public: MapTypeData() : ListTypeData() , m_keyType() { } MapTypeData(const MapTypeData& rhs) : ListTypeData(rhs) , m_keyType(rhs.m_keyType) { } explicit MapTypeData(const ListTypeData& rhs) : ListTypeData(rhs) , m_keyType() { } IndexedType m_keyType; }; /** * @brief Represents a hashmap-like object which can have a key and a content type. * * @see ListType * This works the same as ListType, except that you can also track the object's key type. */ class KDEVPLATFORMLANGUAGE_EXPORT MapType : public ListType { public: typedef TypePtr Ptr; MapType(); MapType(const MapType& rhs); explicit MapType(ListTypeData& data); /** * @brief Add @p typeToAdd to this map's key type. * Behaves like addContentType, except that it modifies the key type instead. */ template void addKeyType(AbstractType::Ptr typeToAdd) { auto newKeyType = TypeUtils::mergeTypes(keyType().abstractType(), typeToAdd); DUChainWriteLocker lock; d_func_dynamic()->m_keyType = IndexedType(newKeyType); } /** * @brief Set this map's key type to @p newType. */ void replaceKeyType(AbstractType::Ptr newType); /** * @brief Get this map's key type. */ IndexedType keyType() const; /** * @brief Formats this type (base type and key+content type) in a string. */ - virtual QString toString() const override; + QString toString() const override; - virtual AbstractType* clone() const override; - virtual uint hash() const override; - virtual bool equals(const AbstractType* rhs) const override; + AbstractType* clone() const override; + uint hash() const override; + bool equals(const AbstractType* rhs) const override; enum { Identity = 57 }; typedef MapTypeData Data; typedef KDevelop::StructureType BaseType; protected: TYPE_DECLARE_DATA(MapType); }; } // namespace KDevelop #endif // KDEVPLATFORM_CONTAINER_TYPES_H // kate: space-indent on; indent-width 4 diff --git a/language/duchain/types/delayedtype.h b/language/duchain/types/delayedtype.h index 4f943e2ac..940232eb3 100644 --- a/language/duchain/types/delayedtype.h +++ b/language/duchain/types/delayedtype.h @@ -1,107 +1,107 @@ /* This file is part of KDevelop Copyright 2006 Roberto Raggi Copyright 2006-2008 Hamish Rodda Copyright 2007-2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_DELAYEDTYPE_H #define KDEVPLATFORM_DELAYEDTYPE_H #include "abstracttype.h" #include "../identifier.h" namespace KDevelop { class DelayedTypeData; /** * \short A type which has not yet been resolved. * * Delayed types can be used for any types that cannot be resolved in the moment they are encountered. * They can be used for example in template-classes, or to store the names of unresolved types. * In a template-class, many types can not be evaluated at the time they are used, because they depend on unknown template-parameters. * Delayed types store the way the type would be searched, and can be used to find the type once the template-paremeters have values. * */ class KDEVPLATFORMLANGUAGE_EXPORT DelayedType : public KDevelop::AbstractType { public: typedef TypePtr Ptr; /// An enumeration of enum Kind : quint8 { Delayed /**< The type should be resolved later. This is the default. */, Unresolved /**< The type could not be resolved */ }; /// Default constructor DelayedType(); /// Copy constructor. \param rhs type to copy DelayedType(const DelayedType& rhs); /// Constructor using raw data. \param data internal data. explicit DelayedType(DelayedTypeData& data); /// Destructor virtual ~DelayedType(); /** * Access the type identifier which this type represents. * * \returns the type identifier. */ KDevelop::IndexedTypeIdentifier identifier() const; /** * Set the type identifier which this type represents. * * \param identifier the type identifier. */ void setIdentifier(const KDevelop::IndexedTypeIdentifier& identifier); - virtual QString toString() const override; + QString toString() const override; - virtual AbstractType* clone() const override; + AbstractType* clone() const override; - virtual bool equals(const AbstractType* rhs) const override; + bool equals(const AbstractType* rhs) const override; Kind kind() const; void setKind(Kind kind); - virtual uint hash() const override; + uint hash() const override; - virtual WhichType whichType() const override; + WhichType whichType() const override; enum { Identity = 8 }; typedef DelayedTypeData Data; protected: - virtual void accept0 (KDevelop::TypeVisitor *v) const override ; + void accept0 (KDevelop::TypeVisitor *v) const override ; TYPE_DECLARE_DATA(DelayedType) }; template<> inline DelayedType* fastCast(AbstractType* from) { if(!from || from->whichType() != AbstractType::TypeDelayed) return nullptr; else return static_cast(from); } } #endif diff --git a/language/duchain/types/enumerationtype.h b/language/duchain/types/enumerationtype.h index d4374bbda..59adf0a2b 100644 --- a/language/duchain/types/enumerationtype.h +++ b/language/duchain/types/enumerationtype.h @@ -1,76 +1,76 @@ /* This file is part of KDevelop Copyright 2002-2005 Roberto Raggi Copyright 2006 Adam Treat Copyright 2006-2008 Hamish Rodda Copyright 2007-2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_ENUMERATIONTYPE_H #define KDEVPLATFORM_ENUMERATIONTYPE_H #include "integraltype.h" #include "identifiedtype.h" namespace KDevelop { typedef KDevelop::MergeIdentifiedType EnumerationTypeBase; typedef EnumerationTypeBase::Data EnumerationTypeData; class KDEVPLATFORMLANGUAGE_EXPORT EnumerationType : public EnumerationTypeBase { public: EnumerationType(); EnumerationType(const EnumerationType& rhs); explicit EnumerationType(EnumerationTypeData& data); typedef TypePtr Ptr; - virtual uint hash() const override; + uint hash() const override; - virtual KDevelop::AbstractType* clone() const override; + KDevelop::AbstractType* clone() const override; - virtual bool equals(const KDevelop::AbstractType* rhs) const override; + bool equals(const KDevelop::AbstractType* rhs) const override; - virtual QString toString() const override; + QString toString() const override; - virtual WhichType whichType() const override; + WhichType whichType() const override; enum { Identity = 21 }; typedef EnumerationTypeData Data; protected: TYPE_DECLARE_DATA(EnumerationType); }; template<> inline EnumerationType* fastCast(AbstractType* from) { if(!from || from->whichType() != KDevelop::AbstractType::TypeEnumeration) return nullptr; else return static_cast(from); } } #endif // KDEVPLATFORM_ENUMERATIONTYPE_H diff --git a/language/duchain/types/enumeratortype.h b/language/duchain/types/enumeratortype.h index b7d4a4571..387147136 100644 --- a/language/duchain/types/enumeratortype.h +++ b/language/duchain/types/enumeratortype.h @@ -1,78 +1,78 @@ /* This file is part of KDevelop Copyright 2002-2005 Roberto Raggi Copyright 2006 Adam Treat Copyright 2006-2008 Hamish Rodda Copyright 2007-2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_ENUMERATORTYPE_H #define KDEVPLATFORM_ENUMERATORTYPE_H #include "identifiedtype.h" #include "constantintegraltype.h" namespace KDevelop { typedef KDevelop::MergeIdentifiedType EnumeratorTypeBase; typedef EnumeratorTypeBase::Data EnumeratorTypeData; //The same as EnumerationType, with the difference that here the value is also known class KDEVPLATFORMLANGUAGE_EXPORT EnumeratorType : public EnumeratorTypeBase { public: EnumeratorType(const EnumeratorType& rhs); explicit EnumeratorType(EnumeratorTypeData& data); EnumeratorType(); typedef TypePtr Ptr; - virtual bool equals(const KDevelop::AbstractType* rhs) const override; + bool equals(const KDevelop::AbstractType* rhs) const override; - virtual KDevelop::AbstractType* clone() const override; + KDevelop::AbstractType* clone() const override; - virtual uint hash() const override; + uint hash() const override; - virtual WhichType whichType() const override; + WhichType whichType() const override; - virtual QString toString() const override; + QString toString() const override; enum { Identity = 20 }; typedef EnumeratorTypeData Data; protected: TYPE_DECLARE_DATA(EnumeratorType); }; template<> inline EnumeratorType* fastCast(AbstractType* from) { if(!from || from->whichType() != KDevelop::AbstractType::TypeEnumerator) return nullptr; else return static_cast(from); } } #endif // KDEVPLATFORM_ENUMERATORTYPE_H diff --git a/language/duchain/types/functiontype.h b/language/duchain/types/functiontype.h index 46f6a2a99..ac5d4d3b5 100644 --- a/language/duchain/types/functiontype.h +++ b/language/duchain/types/functiontype.h @@ -1,149 +1,149 @@ /* This file is part of KDevelop Copyright 2006 Roberto Raggi Copyright 2006-2008 Hamish Rodda Copyright 2007-2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_FUNCTIONTYPE_H #define KDEVPLATFORM_FUNCTIONTYPE_H #include "abstracttype.h" namespace KDevelop { class FunctionTypeData; /** * \short A type representing function types. * * A FunctionType is represents the type of a function. It provides access * to the return type, and number and types of the arguments. */ class KDEVPLATFORMLANGUAGE_EXPORT FunctionType : public AbstractType { public: typedef TypePtr Ptr; /// An enumeration of sections of the function signature that can be returned. enum SignaturePart { SignatureWhole /**< When this is given to toString(..), a string link "RETURNTYPE (ARGTYPE1, ARGTYPE1, ..)" is returned */, SignatureReturn /**< When this is given, only a string that represents the return-type is returned */, SignatureArguments /**< When this is given, a string that represents the arguments like "(ARGTYPE1, ARGTYPE1, ..)" * is returend. This does _not_ include a trailing "const" if the function is constant */ }; /// Default constructor FunctionType(); /// Copy constructor. \param rhs type to copy FunctionType(const FunctionType& rhs); /// Constructor using raw data. \param data internal data. explicit FunctionType(FunctionTypeData& data); /// Destructor ~FunctionType(); /** * Retrieve the return type of the function. * * \returns the return type. */ AbstractType::Ptr returnType () const; /** * Sets the return type of the function. * * \param returnType the return type. */ void setReturnType(AbstractType::Ptr returnType); /** * Retrieve the list of types of the function's arguments. * * \returns the argument types. */ QList arguments () const; /** * Returns the same arguemtns as arguments(), but without converting them to a QList. * This is much faster, and should be preferred for very tight loops when the performance counts. * \return an array that contains the arguments. For the count of arguments, call indexedArgumentsSize */ const IndexedType* indexedArguments() const; /** * Returns the size of the array returned by indexedArguments(). This is much faster than working with arguments(). */ uint indexedArgumentsSize() const; /** * Add an argument to the function, specifying what type it takes. * * \param argument the argument's type * \param index where to insert the argument; the default "-1" will insert it at the end of the list */ void addArgument(AbstractType::Ptr argument, int index = -1); /** * Remove the argument with number i from the function. * * \param i index (starting from 0 with the first argument) to remove */ void removeArgument(int i); - virtual AbstractType* clone() const override; + AbstractType* clone() const override; - virtual bool equals(const AbstractType* rhs) const override; + bool equals(const AbstractType* rhs) const override; - virtual QString toString() const override; + QString toString() const override; /** * This function creates a string that represents the requested part of * this function's signature. * * \param sigPart part of the signature requested. * \returns the signature as text. */ virtual QString partToString( SignaturePart sigPart ) const; - virtual uint hash() const override; + uint hash() const override; - virtual WhichType whichType() const override; + WhichType whichType() const override; - virtual void exchangeTypes( TypeExchanger* exchanger ) override; + void exchangeTypes( TypeExchanger* exchanger ) override; enum { Identity = 5 }; typedef FunctionTypeData Data; protected: - virtual void accept0 (TypeVisitor *v) const override; + void accept0 (TypeVisitor *v) const override; TYPE_DECLARE_DATA(FunctionType) }; template<> inline FunctionType* fastCast(AbstractType* from) { if(!from || from->whichType() != AbstractType::TypeFunction) return nullptr; else return static_cast(from); } } #endif diff --git a/language/duchain/types/integraltype.h b/language/duchain/types/integraltype.h index 3632c5b24..5b20139bc 100644 --- a/language/duchain/types/integraltype.h +++ b/language/duchain/types/integraltype.h @@ -1,128 +1,128 @@ /* This file is part of KDevelop Copyright 2006 Roberto Raggi Copyright 2006-2008 Hamish Rodda Copyright 2007-2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_INTEGRALTYPE_H #define KDEVPLATFORM_INTEGRALTYPE_H #include "abstracttype.h" #include "typesystemdata.h" namespace KDevelop { class IntegralTypeData; class IndexedString; /** * \short A type representing inbuilt data types. * * IntegralType is used to represent types which are native to a programming languge, * such as (e.g.) int, float, double, char, bool etc. */ class KDEVPLATFORMLANGUAGE_EXPORT IntegralType: public AbstractType { public: typedef TypePtr Ptr; /** * Enumeration of frequently used integral types. * If your language has another integral type not listed here, * you can create custom types staring from TypeLanguageSpecific. */ enum CommonIntegralTypes { TypeVoid, TypeNone, TypeNull, TypeChar, TypeBoolean, TypeByte, TypeSbyte, TypeShort, TypeInt, TypeLong, TypeFloat, TypeDouble, TypeWchar_t, TypeString, TypeMixed, TypeChar16_t, TypeChar32_t, TypeLanguageSpecific = 200 }; /// Default constructor explicit IntegralType(uint type = TypeNone); /// Copy constructor. \param rhs type to copy IntegralType(const IntegralType& rhs); /// Constructor using raw data. \param data internal data. explicit IntegralType(IntegralTypeData& data); /// Destructor virtual ~IntegralType(); /** * Access the integral type * * \returns the type's modifiers. */ uint dataType() const; /** * Set the type's data type. * * \param dataType data type of this type. */ void setDataType(uint dataType); /** * TODO: think of a way to make @c toString work properly for custom data types * right now you need to create a custom type and overload it... */ - virtual QString toString() const override; + QString toString() const override; - virtual uint hash() const override; + uint hash() const override; - virtual WhichType whichType() const override; + WhichType whichType() const override; - virtual AbstractType* clone() const override; + AbstractType* clone() const override; - virtual bool equals(const AbstractType* rhs) const override; + bool equals(const AbstractType* rhs) const override; enum { Identity = 2 }; typedef IntegralTypeData Data; protected: - virtual void accept0 (TypeVisitor *v) const override; + void accept0 (TypeVisitor *v) const override; TYPE_DECLARE_DATA(IntegralType) }; template<> inline IntegralType* fastCast(AbstractType* from) { if(!from || from->whichType() != AbstractType::TypeIntegral) return nullptr; else return static_cast(from); } } #endif diff --git a/language/duchain/types/pointertype.h b/language/duchain/types/pointertype.h index 8f2d1a149..2f4c09aa8 100644 --- a/language/duchain/types/pointertype.h +++ b/language/duchain/types/pointertype.h @@ -1,98 +1,98 @@ /* This file is part of KDevelop Copyright 2006 Roberto Raggi Copyright 2006-2008 Hamish Rodda Copyright 2007-2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_POINTERTYPE_H #define KDEVPLATFORM_POINTERTYPE_H #include "abstracttype.h" namespace KDevelop { class PointerTypeData; /** * \short A type representing pointer types. * * PointerType is used to represent types which hold a pointer to a location * in memory. */ class KDEVPLATFORMLANGUAGE_EXPORT PointerType: public AbstractType { public: typedef TypePtr Ptr; /// Default constructor PointerType (); /// Copy constructor. \param rhs type to copy PointerType(const PointerType& rhs); /// Constructor using raw data. \param data internal data. explicit PointerType(PointerTypeData& data); /// Destructor virtual ~PointerType(); /** * Sets the base type of the pointer, ie. what type of data the pointer points to. * * \param type the base type. */ void setBaseType(AbstractType::Ptr type); /** * Retrieve the base type of the pointer, ie. what type of data the pointer points to. * * \returns the base type. */ AbstractType::Ptr baseType () const; - virtual QString toString() const override; + QString toString() const override; - virtual uint hash() const override; + uint hash() const override; - virtual WhichType whichType() const override; + WhichType whichType() const override; - virtual AbstractType* clone() const override; + AbstractType* clone() const override; - virtual bool equals(const AbstractType* rhs) const override; + bool equals(const AbstractType* rhs) const override; - virtual void exchangeTypes( TypeExchanger* exchanger ) override; + void exchangeTypes( TypeExchanger* exchanger ) override; enum { Identity = 3 }; typedef PointerTypeData Data; protected: - virtual void accept0 (TypeVisitor *v) const override; + void accept0 (TypeVisitor *v) const override; TYPE_DECLARE_DATA(PointerType) }; template<> inline PointerType* fastCast(AbstractType* from) { if(!from || from->whichType() != AbstractType::TypePointer) return nullptr; else return static_cast(from); } } #endif diff --git a/language/duchain/types/referencetype.h b/language/duchain/types/referencetype.h index 9f4bcc794..8ff02c8f4 100644 --- a/language/duchain/types/referencetype.h +++ b/language/duchain/types/referencetype.h @@ -1,112 +1,112 @@ /* This file is part of KDevelop Copyright 2006 Roberto Raggi Copyright 2006-2008 Hamish Rodda Copyright 2007-2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_REFERENCETYPE_H #define KDEVPLATFORM_REFERENCETYPE_H #include "abstracttype.h" namespace KDevelop { class ReferenceTypeData; /** * \short A type representing reference types. * * ReferenceType is used to represent types which hold a reference to a * variable. */ class KDEVPLATFORMLANGUAGE_EXPORT ReferenceType: public AbstractType { public: typedef TypePtr Ptr; /// Default constructor ReferenceType (); /// Copy constructor. \param rhs type to copy ReferenceType (const ReferenceType& rhs); /// Constructor using raw data. \param data internal data. explicit ReferenceType(ReferenceTypeData& data); /// Destructor virtual ~ReferenceType(); /** * Retrieve the referenced type, ie. what type of data this type references. * * \returns the base type. */ AbstractType::Ptr baseType () const; /** * Sets the referenced type, ie. what type of data this type references. * * \param baseType the base type. */ void setBaseType(AbstractType::Ptr baseType); /** * Checks whether this type is an rvalue- or lvalue-reference type. * * \returns true for rvalue-references, false for lvalue-references */ bool isRValue() const; /** * Sets whether this type is an rvalue- or lvalue-reference type. * * \param isRValue true for rvalue-references, false for lvalue-references */ void setIsRValue(bool isRValue); - virtual QString toString() const override; + QString toString() const override; - virtual uint hash() const override; + uint hash() const override; - virtual WhichType whichType() const override; + WhichType whichType() const override; - virtual AbstractType* clone() const override; + AbstractType* clone() const override; - virtual bool equals(const AbstractType* rhs) const override; + bool equals(const AbstractType* rhs) const override; - virtual void exchangeTypes( TypeExchanger* exchanger ) override; + void exchangeTypes( TypeExchanger* exchanger ) override; enum { Identity = 4 }; typedef ReferenceTypeData Data; protected: - virtual void accept0 (TypeVisitor *v) const override; + void accept0 (TypeVisitor *v) const override; TYPE_DECLARE_DATA(ReferenceType) }; template<> inline ReferenceType* fastCast(AbstractType* from) { if(!from || from->whichType() != AbstractType::TypeReference) return nullptr; else return static_cast(from); } } #endif // KDEVPLATFORM_TYPESYSTEM_H diff --git a/language/duchain/types/structuretype.h b/language/duchain/types/structuretype.h index 231f02a22..a6dfcb930 100644 --- a/language/duchain/types/structuretype.h +++ b/language/duchain/types/structuretype.h @@ -1,87 +1,87 @@ /* This file is part of KDevelop Copyright 2006 Roberto Raggi Copyright 2006-2008 Hamish Rodda This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_STRUCTURETYPE_H #define KDEVPLATFORM_STRUCTURETYPE_H #include "abstracttype.h" #include "identifiedtype.h" #include "typesystemdata.h" namespace KDevelop { class StructureTypeData; typedef MergeIdentifiedType StructureTypeBase; /** * \short A type representing structure types. * * StructureType represents all structures, including classes, * interfaces, etc. */ class KDEVPLATFORMLANGUAGE_EXPORT StructureType : public StructureTypeBase { public: typedef TypePtr Ptr; /// Default constructor StructureType(); /// Copy constructor. \param rhs type to copy StructureType(const StructureType& rhs); /// Constructor using raw data. \param data internal data. explicit StructureType(StructureTypeData& data); /// Destructor virtual ~StructureType(); - virtual AbstractType* clone() const override; + AbstractType* clone() const override; - virtual bool equals(const AbstractType* rhs) const override; + bool equals(const AbstractType* rhs) const override; - virtual QString toString() const override; + QString toString() const override; - virtual uint hash() const override; + uint hash() const override; - virtual WhichType whichType() const override; + WhichType whichType() const override; //virtual void exchangeTypes(KDevelop::TypeExchanger*); enum { Identity = 6 }; typedef StructureTypeData Data; protected: - virtual void accept0 (TypeVisitor *v) const override; + void accept0 (TypeVisitor *v) const override; TYPE_DECLARE_DATA(StructureType) }; template<> inline StructureType* fastCast(AbstractType* from) { if(!from || from->whichType() != AbstractType::TypeStructure) return nullptr; else return static_cast(from); } } #endif diff --git a/language/duchain/types/typealiastype.h b/language/duchain/types/typealiastype.h index 207724fc7..eeba0c5b1 100644 --- a/language/duchain/types/typealiastype.h +++ b/language/duchain/types/typealiastype.h @@ -1,86 +1,86 @@ /* Copyright 2009 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_TYPEALIASTYPE_H #define KDEVPLATFORM_TYPEALIASTYPE_H #include "abstracttype.h" #include "identifiedtype.h" #include "typeregister.h" #include namespace KDevelop { class TypeAliasTypeData; typedef MergeIdentifiedType TypeAliasTypeBase; class KDEVPLATFORMLANGUAGE_EXPORT TypeAliasType : public TypeAliasTypeBase { public: typedef TypePtr Ptr; TypeAliasType(const TypeAliasType& rhs) : TypeAliasTypeBase(copyData(*rhs.d_func())) { } explicit TypeAliasType(TypeAliasTypeData& data) : TypeAliasTypeBase(data) { } TypeAliasType() : TypeAliasTypeBase(createData()) { } KDevelop::AbstractType::Ptr type() const; void setType(KDevelop::AbstractType::Ptr type); - virtual uint hash() const override; + uint hash() const override; - virtual QString toString() const override; + QString toString() const override; // virtual QString mangled() const; - virtual void exchangeTypes(KDevelop::TypeExchanger* exchanger) override; + void exchangeTypes(KDevelop::TypeExchanger* exchanger) override; - virtual KDevelop::AbstractType* clone() const override; + KDevelop::AbstractType* clone() const override; - virtual bool equals(const KDevelop::AbstractType* rhs) const override; + bool equals(const KDevelop::AbstractType* rhs) const override; - virtual KDevelop::AbstractType::WhichType whichType() const override; + KDevelop::AbstractType::WhichType whichType() const override; enum { Identity = 9 }; typedef TypeAliasTypeData Data; protected: TYPE_DECLARE_DATA(TypeAliasType); - virtual void accept0 (KDevelop::TypeVisitor *v) const override; + void accept0 (KDevelop::TypeVisitor *v) const override; }; template<> inline TypeAliasType* fastCast(AbstractType* from) { if(!from || from->whichType() != AbstractType::TypeIntegral) return nullptr; else return static_cast(from); } } #endif // KDEVPLATFORM_TYPEALIASTYPE_H diff --git a/language/duchain/types/typesystem.h b/language/duchain/types/typesystem.h index 392548296..2457f5f93 100644 --- a/language/duchain/types/typesystem.h +++ b/language/duchain/types/typesystem.h @@ -1,130 +1,130 @@ /* This file is part of KDevelop Copyright 2006 Roberto Raggi Copyright 2006-2008 Hamish Rodda Copyright 2007-2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_TYPESYSTEM_H #define KDEVPLATFORM_TYPESYSTEM_H #include #include #include "typepointer.h" #include "../identifier.h" #include "abstracttype.h" namespace KDevelop { class AbstractTypeDataRequest; class AbstractType; class IntegralType; class PointerType; class ReferenceType; class FunctionType; class StructureType; class ArrayType; class TypeExchanger; class KDEVPLATFORMLANGUAGE_EXPORT TypeVisitor { public: virtual ~TypeVisitor (); virtual bool preVisit (const AbstractType *) = 0; virtual void postVisit (const AbstractType *) = 0; ///Return whether sub-types should be visited(same for the other visit functions) virtual bool visit(const AbstractType*) = 0; virtual void visit (const IntegralType *) = 0; virtual bool visit (const PointerType *) = 0; virtual void endVisit (const PointerType *) = 0; virtual bool visit (const ReferenceType *) = 0; virtual void endVisit (const ReferenceType *) = 0; virtual bool visit (const FunctionType *) = 0; virtual void endVisit (const FunctionType *) = 0; virtual bool visit (const StructureType *) = 0; virtual void endVisit (const StructureType *) = 0; virtual bool visit (const ArrayType *) = 0; virtual void endVisit (const ArrayType *) = 0; }; class KDEVPLATFORMLANGUAGE_EXPORT SimpleTypeVisitor : public TypeVisitor { public: /// When using SimpleTypeVisitor, the visit taking an AbstractType is the only function /// you must override to collect all types. using TypeVisitor::visit; - virtual bool preVisit (const AbstractType *) override ; - virtual void postVisit (const AbstractType *) override ; + bool preVisit (const AbstractType *) override ; + void postVisit (const AbstractType *) override ; - virtual void visit (const IntegralType *) override ; + void visit (const IntegralType *) override ; - virtual bool visit (const PointerType *) override ; - virtual void endVisit (const PointerType *) override ; + bool visit (const PointerType *) override ; + void endVisit (const PointerType *) override ; - virtual bool visit (const ReferenceType *) override ; - virtual void endVisit (const ReferenceType *) override ; + bool visit (const ReferenceType *) override ; + void endVisit (const ReferenceType *) override ; - virtual bool visit (const FunctionType *) override ; - virtual void endVisit (const FunctionType *) override ; + bool visit (const FunctionType *) override ; + void endVisit (const FunctionType *) override ; - virtual bool visit (const StructureType *) override ; - virtual void endVisit (const StructureType *) override ; + bool visit (const StructureType *) override ; + void endVisit (const StructureType *) override ; - virtual bool visit (const ArrayType *) override ; - virtual void endVisit (const ArrayType *) override ; + bool visit (const ArrayType *) override ; + void endVisit (const ArrayType *) override ; }; /** * A class that can be used to walk through all types that are references from one type, and exchange them with other types. * Examples for such types: Base-classes of a class, function-argument types of a function, etc. * */ class KDEVPLATFORMLANGUAGE_EXPORT TypeExchanger { public: virtual ~TypeExchanger() { } /** * By default should return the given type, and can return another type that the given should be replaced with. * Types should allow replacing all their held types using this from within their exchangeTypes function. * The default-implementation recurses the exchange, so should be called from within the derived implementation if that is wished. * */ virtual AbstractType::Ptr exchange( const AbstractType::Ptr& ); }; ///A simple type-exchanger that replaces one type with another class KDEVPLATFORMLANGUAGE_EXPORT SimpleTypeExchanger : public TypeExchanger { public: SimpleTypeExchanger(AbstractType::Ptr replace, AbstractType::Ptr replaceWith); - virtual AbstractType::Ptr exchange( const AbstractType::Ptr& ) override ; + AbstractType::Ptr exchange( const AbstractType::Ptr& ) override ; private: AbstractType::Ptr m_replace, m_replaceWith; }; } #endif // KDEVPLATFORM_TYPESYSTEM_H diff --git a/language/duchain/types/unsuretype.h b/language/duchain/types/unsuretype.h index 356ca8059..811f4eedf 100644 --- a/language/duchain/types/unsuretype.h +++ b/language/duchain/types/unsuretype.h @@ -1,90 +1,90 @@ /* Copyright 2009 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_UNSURETYPE_H #define KDEVPLATFORM_UNSURETYPE_H #include "abstracttype.h" #include "typesystemdata.h" #include "../appendedlist.h" #include namespace KDevelop { KDEVPLATFORMLANGUAGE_EXPORT DECLARE_LIST_MEMBER_HASH(UnsureTypeData, m_types, IndexedType) struct KDEVPLATFORMLANGUAGE_EXPORT UnsureTypeData : public AbstractTypeData { UnsureTypeData() { initializeAppendedLists(m_dynamic); } ~UnsureTypeData() { freeAppendedLists(); } UnsureTypeData(const UnsureTypeData& rhs) : AbstractTypeData(rhs){ initializeAppendedLists(m_dynamic); copyListsFrom(rhs); } START_APPENDED_LISTS_BASE(UnsureTypeData, AbstractTypeData) APPENDED_LIST_FIRST(UnsureTypeData, IndexedType, m_types) END_APPENDED_LISTS(UnsureTypeData, m_types) }; class KDEVPLATFORMLANGUAGE_EXPORT UnsureType : public AbstractType { public: typedef TypePtr Ptr; UnsureType(const UnsureType& rhs); UnsureType(); explicit UnsureType(UnsureTypeData& data); - virtual KDevelop::AbstractType* clone() const override; - virtual QString toString() const override; - virtual bool equals(const KDevelop::AbstractType* rhs) const override; - virtual uint hash() const override; - virtual KDevelop::AbstractType::WhichType whichType() const override; - virtual void exchangeTypes(KDevelop::TypeExchanger* exchanger) override; + KDevelop::AbstractType* clone() const override; + QString toString() const override; + bool equals(const KDevelop::AbstractType* rhs) const override; + uint hash() const override; + KDevelop::AbstractType::WhichType whichType() const override; + void exchangeTypes(KDevelop::TypeExchanger* exchanger) override; virtual void addType(IndexedType type); virtual void removeType(IndexedType type); ///Array of represented types. You can conveniently iterate it using the FOREACH_FUNCTION macro, ///or just access them using indices const IndexedType* types() const; ///Count of types accessible through types() uint typesSize() const; enum { Identity = 39 }; typedef KDevelop::AbstractType BaseType; typedef UnsureTypeData Data; protected: TYPE_DECLARE_DATA(UnsureType) - virtual void accept0(KDevelop::TypeVisitor* v) const override; + void accept0(KDevelop::TypeVisitor* v) const override; }; } #endif // KDEVPLATFORM_UNSURETYPE_H diff --git a/language/interfaces/codecontext.h b/language/interfaces/codecontext.h index 91776dbe8..e2dc1977e 100644 --- a/language/interfaces/codecontext.h +++ b/language/interfaces/codecontext.h @@ -1,114 +1,114 @@ /* This file is part of KDevelop Copyright 2001-2002 Matthias Hoelzer-Kluepfel Copyright 2001-2002 Bernd Gehrmann Copyright 2001 Sandy Meier Copyright 2002 Daniel Engelschalt Copyright 2002 Simon Hausmann Copyright 2002-2003 Roberto Raggi Copyright 2003 Mario Scalas Copyright 2003 Harald Fernengel Copyright 2003,2006-2007 Hamish Rodda Copyright 2004 Alexander Dymo Copyright 2006 Adam Treat Copyright 2007 Andreas Pakulat This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_CODECONTEXT_H #define KDEVPLATFORM_CODECONTEXT_H #include #include #include #include namespace KTextEditor { class View; } namespace KDevelop { class IndexedDeclaration; class IndexedDUContext; /** * A context that represents DUContexts. Before using this, first try casting to DeclarationContext, and use that if possible. */ class KDEVPLATFORMLANGUAGE_EXPORT DUContextContext : public Context { public: explicit DUContextContext(const IndexedDUContext& context); virtual ~DUContextContext(); ///Returns the represented DUContext IndexedDUContext context() const; int type() const override; - virtual QList urls() const override; + QList urls() const override; protected: void setContext(IndexedDUContext context); private: class Private; Private *d; Q_DISABLE_COPY(DUContextContext) }; /** A context for definition-use chain objects. */ class KDEVPLATFORMLANGUAGE_EXPORT DeclarationContext: public DUContextContext { public: /**Builds the context. * @param declaration The represented declaration. * @param use If this context represents the use of a declaration, this should contain the exact use range. * @param context If this represents a use, then this should be the context * surrounding the use. Else it should be the context surrounding the declaration. */ explicit DeclarationContext(const IndexedDeclaration& declaration, const DocumentRange& use = DocumentRange::invalid(), const IndexedDUContext& context = IndexedDUContext()); ///Computes the items under the cursor DeclarationContext(KTextEditor::View* view, const KTextEditor::Cursor& position); /**Destructor.*/ virtual ~DeclarationContext(); /// Returns the type of this context. - virtual int type() const override; + int type() const override; ///The referenced declaration IndexedDeclaration declaration() const; ///If this code-context represents the use of a declaration, then this contains the exact position+range ///of that use. declaration() returnes the used declaration, and context() the context ///that surrounds the use. DocumentRange use() const; private: class Private; Private *d; Q_DISABLE_COPY(DeclarationContext) }; } #endif diff --git a/language/interfaces/editorcontext.h b/language/interfaces/editorcontext.h index 8155bc81c..49105ce06 100644 --- a/language/interfaces/editorcontext.h +++ b/language/interfaces/editorcontext.h @@ -1,82 +1,82 @@ /* This file is part of KDevelop Copyright 2006 Adam Treat Copyright 2007 Andreas Pakulat Copyright 2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_EDITORCONTEXT_H #define KDEVPLATFORM_EDITORCONTEXT_H #include "codecontext.h" namespace KTextEditor { class View; class Cursor; } class QUrl; namespace KDevelop { /**A context for the KTextEditor.*/ class KDEVPLATFORMLANGUAGE_EXPORT EditorContext: public DeclarationContext { public: /** * Builds a context for a KTextEditor part. * @param view The view for the editor context. * @param position The cursor position. */ EditorContext( KTextEditor::View* view, const KTextEditor::Cursor& position ); /**Destructor.*/ virtual ~EditorContext(); - virtual int type() const override; + int type() const override; /**@return The url for the file which this context was invoked for.*/ QUrl url() const; QList urls() const override; /**@return The cursor position.*/ KTextEditor::Cursor position() const; /**@return A QString with the content of the line which this context was invoked for.*/ QString currentLine() const; /**@return A QString containing the word near to the cursor when this context object was created.*/ QString currentWord() const; /** * Returns the associated view. */ KTextEditor::View* view() const; private: class EditorContextPrivate* const d; EditorContext( const EditorContext & ); EditorContext &operator=( const EditorContext & ); }; } #endif diff --git a/language/util/setrepository.h b/language/util/setrepository.h index a36738f43..303e0b133 100644 --- a/language/util/setrepository.h +++ b/language/util/setrepository.h @@ -1,478 +1,478 @@ /*************************************************************************** Copyright 2007 David Nolden ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_SETREPOSITORY_H #define KDEVPLATFORM_SETREPOSITORY_H #include "basicsetrepository.h" #include #include #include /** * This header defines convenience-class that allow handling set-repositories using the represented higher-level objects instead * of indices to them. * */ namespace Utils { /** * Use this class to conveniently iterate over the items in a set. * @tparam T The type the indices will be converted to * @tparam Conversion Should be a class that has a toIndex member function that takes an object of type T as parameter, and returns an index, * and a toItem member function that takes an index, and returns an item of type T. * */ template class ConvenientIterator : public Conversion { public: ConvenientIterator(Set::Iterator it=Set::Iterator()) : m_it(it) { } ConvenientIterator(const Set& set) : m_it(set.iterator()) { } operator bool() const { return m_it; } ConvenientIterator& operator++() { ++m_it; return *this; } T operator*() const { return Conversion::toItem(*m_it); } uint index() const { return *m_it; } private: Set::Iterator m_it; }; struct DummyLocker { }; template struct IdentityConversion { static T toIndex(const T& t) { return t; } static T toItem(const T& t) { return t; } }; ///This is a virtual set-node that allows conveniently iterating through the tree-structure, ///accessing the contained items directly, and accessing the ranges. template class VirtualSetNode { public: inline VirtualSetNode(const SetNodeData* data = 0) : m_data(data) { } inline bool isValid() const { return (bool)m_data; } ///If this returns false, a left and a right node are available. ///If this returns true, this node represents a single item, that can be retrieved by calling item() or operator*. inline bool isFinalNode() const { return m_data->leftNode() == 0; } inline T firstItem() const { return Conversion::toItem(start()); } inline T lastItem() const { return Conversion::toItem(end()-1); } inline T operator*() const { return Conversion::toItem(start()); } inline VirtualSetNode leftChild() const { if(m_data->leftNode()) return StaticRepository::repository()->nodeFromIndex(m_data->leftNode()); else return nullptr; } inline VirtualSetNode rightChild() const { if(m_data->rightNode()) return StaticRepository::repository()->nodeFromIndex(m_data->rightNode()); else return nullptr; } ///Returns the start of this node's range. If this is a final node, the length of the range is 1. inline uint start() const { return m_data->start(); } ///Returns the end of this node's range. inline uint end() const { return m_data->end(); } private: const SetNodeData* m_data; }; template class StorableSet : public Conversion { public: typedef VirtualSetNode Node; StorableSet(const StorableSet& rhs) : m_setIndex(rhs.m_setIndex) { StaticAccessLocker lock; Q_UNUSED(lock); if(doReferenceCounting) set().staticRef(); } StorableSet(const std::set& indices) { StaticAccessLocker lock; Q_UNUSED(lock); m_setIndex = StaticRepository::repository()->createSet(indices).setIndex(); if(doReferenceCounting) set().staticRef(); } StorableSet() : m_setIndex(0) { } ~StorableSet() { StaticAccessLocker lock; Q_UNUSED(lock); if(doReferenceCounting) set().staticUnref(); } void insert(const T& t) { insertIndex(Conversion::toIndex(t)); } bool isEmpty() const { return m_setIndex == 0; } uint count() const { return set().count(); } void insertIndex(uint index) { StaticAccessLocker lock; Q_UNUSED(lock); Set set(m_setIndex, StaticRepository::repository()); Set oldSet(set); Set addedSet = StaticRepository::repository()->createSet(index); if(doReferenceCounting) addedSet.staticRef(); set += addedSet; m_setIndex = set.setIndex(); if(doReferenceCounting) { set.staticRef(); oldSet.staticUnref(); addedSet.staticUnref(); } } void remove(const T& t) { removeIndex(Conversion::toIndex(t)); } void removeIndex(uint index) { StaticAccessLocker lock; Q_UNUSED(lock); Set set(m_setIndex, StaticRepository::repository()); Set oldSet(set); Set removedSet = StaticRepository::repository()->createSet(index); if(doReferenceCounting) { removedSet.staticRef(); } set -= removedSet; m_setIndex = set.setIndex(); if(doReferenceCounting) { set.staticRef(); oldSet.staticUnref(); removedSet.staticUnref(); } } Set set() const { return Set(m_setIndex, StaticRepository::repository()); } bool contains(const T& item) const { return containsIndex(Conversion::toIndex(item)); } bool containsIndex(uint index) const { StaticAccessLocker lock; Q_UNUSED(lock); Set set(m_setIndex, StaticRepository::repository()); return set.contains(index); } StorableSet& operator +=(const StorableSet& rhs) { StaticAccessLocker lock; Q_UNUSED(lock); Set set(m_setIndex, StaticRepository::repository()); Set oldSet(set); Set otherSet(rhs.m_setIndex, StaticRepository::repository()); set += otherSet; m_setIndex = set.setIndex(); if(doReferenceCounting) { set.staticRef(); oldSet.staticUnref(); } return *this; } StorableSet& operator -=(const StorableSet& rhs) { StaticAccessLocker lock; Q_UNUSED(lock); Set set(m_setIndex, StaticRepository::repository()); Set oldSet(set); Set otherSet(rhs.m_setIndex, StaticRepository::repository()); set -= otherSet; m_setIndex = set.setIndex(); if(doReferenceCounting) { set.staticRef(); oldSet.staticUnref(); } return *this; } StorableSet& operator &=(const StorableSet& rhs) { StaticAccessLocker lock; Q_UNUSED(lock); Set set(m_setIndex, StaticRepository::repository()); Set oldSet(set); Set otherSet(rhs.m_setIndex, StaticRepository::repository()); set &= otherSet; m_setIndex = set.setIndex(); if(doReferenceCounting) { set.staticRef(); oldSet.staticUnref(); } return *this; } StorableSet& operator=(const StorableSet& rhs) { StaticAccessLocker lock; Q_UNUSED(lock); if(doReferenceCounting) set().staticUnref(); m_setIndex = rhs.m_setIndex; if(doReferenceCounting) set().staticRef(); return *this; } StorableSet operator +(const StorableSet& rhs) const { StorableSet ret(*this); ret += rhs; return ret; } StorableSet operator -(const StorableSet& rhs) const { StorableSet ret(*this); ret -= rhs; return ret; } StorableSet operator &(const StorableSet& rhs) const { StorableSet ret(*this); ret &= rhs; return ret; } bool operator==(const StorableSet& rhs) const { return m_setIndex == rhs.m_setIndex; } typedef ConvenientIterator Iterator; Iterator iterator() const { return ConvenientIterator(set()); } Node node() const { return Node(StaticRepository::repository()->nodeFromIndex(m_setIndex)); } uint setIndex() const { return m_setIndex; } private: uint m_setIndex; }; template uint qHash(const StorableSet& set) { return set.setIndex(); } /** This is a helper-class that helps inserting a bunch of items into a set without caring about grouping them together. * * It creates a much better tree-structure if many items are inserted at one time, and this class helps doing that in * cases where there is no better choice then storing a temporary list of items and inserting them all at once. * * This set will then care about really inserting them into the repository once the real set is requested. * * @todo eventually make this unnecessary * * @tparam T Should be the type that should be dealt * @tparam Conversion Should be a class that has a toIndex member function that takes an object of type T as parameter, and returns an index, * and a toItem member function that takes an index, and returns an item of type T. **/ template class LazySet : public Conversion { public: /** @param rep The repository the set should belong/belongs to * @param lockBeforeAccess If this is nonzero, the given mutex will be locked before each modification to the repository. * @param basicSet If this is explicitly given, the given set will be used as base. However it will not be changed. * * @warning Watch for deadlocks, never use this class while the mutex given through lockBeforeAccess is locked */ LazySet(BasicSetRepository* rep, QMutex* lockBeforeAccess = 0, const Set& basicSet = Set()) : m_rep(rep), m_set(basicSet), m_lockBeforeAccess(lockBeforeAccess) { } void insert(const T& t) { if(!m_temporaryRemoveIndices.empty()) apply(); m_temporaryIndices.insert(Conversion::toIndex(t)); } void insertIndex(uint index) { if(!m_temporaryRemoveIndices.empty()) apply(); m_temporaryIndices.insert(index); } void remove(const T& t) { if(!m_temporaryIndices.empty()) apply(); m_temporaryRemoveIndices.insert(Conversion::toIndex(t)); } ///Returns the set this LazySet represents. When this is called, the set is constructed in the repository. Set set() const { apply(); return m_set; } ///@warning this is expensive, because the set is constructed bool contains(const T& item) const { QMutexLocker l(m_lockBeforeAccess); uint index = Conversion::toIndex(item); if( m_temporaryRemoveIndices.empty() ) { //Simplification without creating the set if(m_temporaryIndices.find(index) != m_temporaryIndices.end()) return true; return m_set.contains(index); } return set().contains(index); } LazySet& operator +=(const Set& set) { if(!m_temporaryRemoveIndices.empty()) apply(); QMutexLocker l(m_lockBeforeAccess); m_set += set; return *this; } LazySet& operator -=(const Set& set) { if(!m_temporaryIndices.empty()) apply(); QMutexLocker l(m_lockBeforeAccess); m_set -= set; return *this; } LazySet operator +(const Set& set) const { apply(); QMutexLocker l(m_lockBeforeAccess); Set ret = m_set + set; return LazySet(m_rep, m_lockBeforeAccess, ret); } LazySet operator -(const Set& set) const { apply(); QMutexLocker l(m_lockBeforeAccess); Set ret = m_set - set; return LazySet(m_rep, m_lockBeforeAccess, ret); } void clear() { QMutexLocker l(m_lockBeforeAccess); m_set = Set(); m_temporaryIndices.clear(); m_temporaryRemoveIndices.clear(); } ConvenientIterator iterator() const { apply(); return ConvenientIterator(set()); } private: void apply() const { if(!m_temporaryIndices.empty()) { QMutexLocker l(m_lockBeforeAccess); Set tempSet = m_rep->createSet(m_temporaryIndices); m_temporaryIndices.clear(); m_set += tempSet; } if(!m_temporaryRemoveIndices.empty()) { QMutexLocker l(m_lockBeforeAccess); Set tempSet = m_rep->createSet(m_temporaryRemoveIndices); m_temporaryRemoveIndices.clear(); m_set -= tempSet; } } BasicSetRepository* m_rep; mutable Set m_set; QMutex* m_lockBeforeAccess; typedef std::set IndexList; mutable IndexList m_temporaryIndices; mutable IndexList m_temporaryRemoveIndices; }; ///Persistent repository that manages string-sets, also correctly increasing the string reference-counts as needed struct KDEVPLATFORMLANGUAGE_EXPORT StringSetRepository : public Utils::BasicSetRepository { StringSetRepository(QString name); - virtual void itemRemovedFromSets(uint index) override; - virtual void itemAddedToSets(uint index) override; + void itemRemovedFromSets(uint index) override; + void itemAddedToSets(uint index) override; }; } #endif diff --git a/outputview/outputfilteringstrategies.h b/outputview/outputfilteringstrategies.h index df27e7853..4dca61df8 100644 --- a/outputview/outputfilteringstrategies.h +++ b/outputview/outputfilteringstrategies.h @@ -1,125 +1,125 @@ /* This file is part of KDevelop Copyright (C) 2012 Morten Danielsen Volden mvolden2@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef KDEVPLATFORM_OUTPUTFILTERINGSTRATEGIES_H #define KDEVPLATFORM_OUTPUTFILTERINGSTRATEGIES_H /** * @file This file contains Concrete strategies for filtering output * in KDevelop output model. I.e. classes that inherit from ifilterstrategy. * New filtering strategies should be added here */ #include "ifilterstrategy.h" #include #include #include #include #include namespace KDevelop { struct CompilerFilterStrategyPrivate; /** * This filter strategy is for not applying any filtering at all. Implementation of the * interface methods are basically noops **/ class KDEVPLATFORMOUTPUTVIEW_EXPORT NoFilterStrategy : public IFilterStrategy { public: NoFilterStrategy(); - virtual FilteredItem errorInLine(const QString& line) override; + FilteredItem errorInLine(const QString& line) override; - virtual FilteredItem actionInLine(const QString& line) override; + FilteredItem actionInLine(const QString& line) override; }; /** * This filter stategy checks if a given line contains output * that is defined as an error (or an action) from a compiler. **/ class KDEVPLATFORMOUTPUTVIEW_EXPORT CompilerFilterStrategy : public IFilterStrategy { public: CompilerFilterStrategy(const QUrl& buildDir); virtual ~CompilerFilterStrategy(); - virtual FilteredItem errorInLine(const QString& line) override; + FilteredItem errorInLine(const QString& line) override; - virtual FilteredItem actionInLine(const QString& line) override; + FilteredItem actionInLine(const QString& line) override; QVector getCurrentDirs(); private: CompilerFilterStrategyPrivate* const d; }; /** * This filter stategy filters out errors (no actions) from Python and PHP scripts. **/ class KDEVPLATFORMOUTPUTVIEW_EXPORT ScriptErrorFilterStrategy : public IFilterStrategy { public: ScriptErrorFilterStrategy(); - virtual FilteredItem errorInLine(const QString& line) override; + FilteredItem errorInLine(const QString& line) override; - virtual FilteredItem actionInLine(const QString& line) override; + FilteredItem actionInLine(const QString& line) override; }; /** * This filter strategy filters out errors (no actions) from runtime debug output of native applications * * This is especially useful for runtime output of Qt applications, for example lines such as: * "ASSERT: "errors().isEmpty()" in file /tmp/foo/bar.cpp", line 49" */ class KDEVPLATFORMOUTPUTVIEW_EXPORT NativeAppErrorFilterStrategy : public IFilterStrategy { public: NativeAppErrorFilterStrategy(); - virtual FilteredItem errorInLine(const QString& line) override; - virtual FilteredItem actionInLine(const QString& line) override; + FilteredItem errorInLine(const QString& line) override; + FilteredItem actionInLine(const QString& line) override; }; /** * This filter stategy filters out errors (no actions) from Static code analysis tools (Cppcheck,) **/ class KDEVPLATFORMOUTPUTVIEW_EXPORT StaticAnalysisFilterStrategy : public IFilterStrategy { public: StaticAnalysisFilterStrategy(); - virtual FilteredItem errorInLine(const QString& line) override; + FilteredItem errorInLine(const QString& line) override; - virtual FilteredItem actionInLine(const QString& line) override; + FilteredItem actionInLine(const QString& line) override; }; } // namespace KDevelop #endif // KDEVPLATFORM_OUTPUTFILTERINGSTRATEGIES_H diff --git a/plugins/filetemplates/defaultcreateclasshelper.h b/plugins/filetemplates/defaultcreateclasshelper.h index 98a3cdd17..ee12f7d86 100644 --- a/plugins/filetemplates/defaultcreateclasshelper.h +++ b/plugins/filetemplates/defaultcreateclasshelper.h @@ -1,46 +1,46 @@ /* This file is part of KDevelop Copyright 2012 Miha Čančula This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_PLUGIN_DEFAULTCREATECLASSHELPER_H #define KDEVPLATFORM_PLUGIN_DEFAULTCREATECLASSHELPER_H #include /** * A default class creation helper. * * This is used when no custom helper is supplied by the language plugin. */ class DefaultCreateClassHelper : public KDevelop::ICreateClassHelper { public: DefaultCreateClassHelper(); virtual ~DefaultCreateClassHelper(); /** * @return a new @c TemplateClassGenerator. */ - virtual KDevelop::TemplateClassGenerator* createGenerator(const QUrl& baseUrl) override; + KDevelop::TemplateClassGenerator* createGenerator(const QUrl& baseUrl) override; /** * @return an empty list of methods. */ - virtual QList< KDevelop::DeclarationPointer > defaultMethods(const QString& name) const override; + QList< KDevelop::DeclarationPointer > defaultMethods(const QString& name) const override; }; #endif // KDEVPLATFORM_PLUGIN_DEFAULTCREATECLASSHELPER_H diff --git a/plugins/patchreview/patchreview.h b/plugins/patchreview/patchreview.h index d5520f632..92090e124 100644 --- a/plugins/patchreview/patchreview.h +++ b/plugins/patchreview/patchreview.h @@ -1,144 +1,144 @@ /*************************************************************************** Copyright 2006 David Nolden ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_PATCHREVIEW_H #define KDEVPLATFORM_PLUGIN_PATCHREVIEW_H #include #include #include #include #include class PatchHighlighter; class PatchReviewToolViewFactory; class QTimer; namespace KDevelop { class IDocument; } namespace Sublime { class Area; } namespace Diff2 { class KompareModelList; class DiffModel; } namespace Kompare { struct Info; } class DiffSettings; class PatchReviewPlugin; class PatchReviewPlugin : public KDevelop::IPlugin, public KDevelop::IPatchReview, public KDevelop::ILanguageSupport { Q_OBJECT Q_INTERFACES( KDevelop::IPatchReview ) Q_INTERFACES( KDevelop::ILanguageSupport ) public : explicit PatchReviewPlugin( QObject *parent, const QVariantList & = QVariantList() ); ~PatchReviewPlugin() override; void unload() override; KDevelop::IPatchSource::Ptr patch() const { return m_patch; } Diff2::KompareModelList* modelList() const { return m_modelList.data(); } - virtual QString name() const override { + QString name() const override { return "diff"; } - virtual KDevelop::ParseJob *createParseJob(const KDevelop::IndexedString &) override { + KDevelop::ParseJob *createParseJob(const KDevelop::IndexedString &) override { return nullptr; } void seekHunk( bool forwards, const QUrl& file = QUrl() ); void setPatch( KDevelop::IPatchSource* patch ); void startReview( KDevelop::IPatchSource* patch, ReviewMode mode ) override; void finishReview( QList< QUrl > selection ); QUrl urlForFileModel( const Diff2::DiffModel* model ); QAction* finishReviewAction() const { return m_finishReview; } KDevelop::ContextMenuExtension contextMenuExtension( KDevelop::Context* context ) override; Q_SIGNALS: void startingNewReview(); void patchChanged(); public Q_SLOTS : //Does parts of the review-starting that are problematic to do directly in startReview, as they may open dialogs etc. void updateReview(); void cancelReview(); void clearPatch( QObject* patch ); void notifyPatchChanged(); void highlightPatch(); void updateKompareModel(); void forceUpdate(); void areaChanged(Sublime::Area* area); void executeFileReviewAction(); private Q_SLOTS : void documentClosed( KDevelop::IDocument* ); void textDocumentCreated( KDevelop::IDocument* ); void documentSaved( KDevelop::IDocument* ); void closeReview(); private: void switchToEmptyReviewArea(); /// Makes sure that this working set is active only in the @p area, and that its name starts with "review". void setUniqueEmptyWorkingSet(Sublime::Area* area); void addHighlighting( const QUrl& file, KDevelop::IDocument* document = nullptr ); void removeHighlighting( const QUrl& file = QUrl() ); KDevelop::IPatchSource::Ptr m_patch; QTimer* m_updateKompareTimer; PatchReviewToolViewFactory* m_factory; QAction* m_finishReview; #if 0 void determineState(); #endif QPointer< DiffSettings > m_diffSettings; QScopedPointer< Kompare::Info > m_kompareInfo; QScopedPointer< Diff2::KompareModelList > m_modelList; uint m_depth = 0; // depth of the patch represented by m_modelList typedef QMap< QUrl, QPointer< PatchHighlighter > > HighlightMap; HighlightMap m_highlighters; friend class PatchReviewToolView; // to access slot exporterSelected(); }; #endif // kate: space-indent on; indent-width 2; tab-width 2; replace-tabs on diff --git a/plugins/projectfilter/projectfilter.h b/plugins/projectfilter/projectfilter.h index d4a76a23e..8ce449152 100644 --- a/plugins/projectfilter/projectfilter.h +++ b/plugins/projectfilter/projectfilter.h @@ -1,54 +1,54 @@ /* This file is part of KDevelop Copyright 2013 Milian Wolff This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef PROJECTFILTER_H #define PROJECTFILTER_H #include #include #include #include "filter.h" namespace KDevelop { class IProject; class ProjectFilter : public IProjectFilter { public: ProjectFilter(const IProject* const project, const Filters& filters); virtual ~ProjectFilter(); - virtual bool isValid(const Path& path, bool isFolder) const override; + bool isValid(const Path& path, bool isFolder) const override; private: QString makeRelative(const Path& path) const; Filters m_filters; Path m_projectFile; Path m_project; }; } #endif // PROJECTFILTER_H diff --git a/plugins/quickopen/expandingtree/expandingtree.h b/plugins/quickopen/expandingtree/expandingtree.h index 264be3414..e8b032f4d 100644 --- a/plugins/quickopen/expandingtree/expandingtree.h +++ b/plugins/quickopen/expandingtree/expandingtree.h @@ -1,46 +1,46 @@ /* This file is part of the KDE libraries and the Kate part. * * Copyright (C) 2007 David Nolden * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_PLUGIN_EXPANDINGTREE_H #define KDEVPLATFORM_PLUGIN_EXPANDINGTREE_H #include #include //A tree that allows drawing additional information class ExpandingTree : public QTreeView { Q_OBJECT public: explicit ExpandingTree(QWidget* parent); enum CustomRoles { ProjectPathRole = Qt::UserRole + 5000 }; protected: - virtual void drawRow ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const override; - virtual int sizeHintForColumn ( int column ) const override; + void drawRow ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const override; + int sizeHintForColumn ( int column ) const override; void drawBranches(QPainter* painter, const QRect& rect, const QModelIndex& index) const override; private: mutable QTextDocument m_drawText; }; #endif // KDEVPLATFORM_PLUGIN_EXPANDINGTREE_H diff --git a/plugins/quickopen/expandingtree/expandingwidgetmodel.h b/plugins/quickopen/expandingtree/expandingwidgetmodel.h index 76fa009d3..bc9311369 100644 --- a/plugins/quickopen/expandingtree/expandingwidgetmodel.h +++ b/plugins/quickopen/expandingtree/expandingwidgetmodel.h @@ -1,161 +1,161 @@ /* This file is part of the KDE libraries and the Kate part. * * Copyright (C) 2007 David Nolden * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_PLUGIN_EXPANDING_WIDGET_MODEL_H #define KDEVPLATFORM_PLUGIN_EXPANDING_WIDGET_MODEL_H #include #include #include #include #include class KWidget; class QTreeView; class QTextEdit; /** * Cares about expanding/un-expanding items in a tree-view together with ExpandingDelegate */ class ExpandingWidgetModel : public QAbstractTableModel { Q_OBJECT public: explicit ExpandingWidgetModel( QWidget* parent ); virtual ~ExpandingWidgetModel(); enum ExpandingType { NotExpandable=0, Expandable, Expanded }; ///The following three are convenience-functions for the current item that could be replaced by the later ones ///@return whether the current item can be expanded bool canExpandCurrentItem() const; ///@return whether the current item can be collapsed bool canCollapseCurrentItem() const; ///Expand/collapse the current item void setCurrentItemExpanded( bool ); void clearMatchQualities(); ///Unexpand all rows and clear all cached information about them(this includes deleting the expanding-widgets) void clearExpanding(); ///@return whether the row given through index is expandable bool isExpandable(const QModelIndex& index) const; enum ExpansionType { NotExpanded = 0, ExpandDownwards, //The additional(expanded) information is shown UNDER the original information ExpandUpwards //The additional(expanded) information is shown ABOVE the original information }; ///Returns whether the given index is currently partially expanded. Does not do any other checks like calling models for data. ExpansionType isPartiallyExpanded(const QModelIndex& index) const; ///@return whether row is currently expanded bool isExpanded(const QModelIndex & row) const; ///Change the expand-state of the row given through index. The display will be updated. void setExpanded(QModelIndex index, bool expanded); ///Returns the total height added through all open expanding-widgets int expandingWidgetsHeight() const; ///@return the expanding-widget for the given row, if available. Expanding-widgets are in best case available for all expanded rows. ///This does not return the partially-expand widget. QWidget* expandingWidget(const QModelIndex & row) const; ///Amount by which the height of a row increases when it is partially expanded int partiallyExpandWidgetHeight() const; /** * Notifies underlying models that the item was selected, collapses any previous partially expanded line, * checks whether this line should be partially expanded, and eventually does it. * Does nothing when nothing needs to be done. * Does NOT show the expanding-widget. That is done immediately when painting by ExpandingDelegate, * to reduce flickering. @see showPartialExpandWidget() * @param row The row * */ /// virtual void rowSelected(const QModelIndex & row); ///Returns the rectangle for the partially expanded part of the given row QRect partialExpandRect(const QModelIndex & row) const; QString partialExpandText(const QModelIndex & row) const; ///Places and shows the expanding-widget for the given row, if it should be visible and is valid. ///Also shows the partial-expanding-widget when it should be visible. void placeExpandingWidget(const QModelIndex & row); virtual QTreeView* treeView() const = 0; ///Should return true if the given row should be painted like a contained item(as opposed to label-rows etc.) virtual bool indexIsItem(const QModelIndex& index) const = 0; ///Does not request data from index, this only returns local data like highlighting for expanded rows and similar - virtual QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const override; + QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const override; ///Returns the first row that is currently partially expanded. QModelIndex partiallyExpandedRow() const; ///Returns the match-color for the given index, or zero if match-quality could not be computed. uint matchColor(const QModelIndex& index) const; public slots: ///Place or hides all expanding-widgets to the correct positions. Should be called after the view was scrolled. void placeExpandingWidgets(); protected: /** * @return the context-match quality from 0 to 10 if it could be determined, else -1 * */ virtual int contextMatchQuality(const QModelIndex & index) const = 0; //Makes sure m_expandedIcon and m_collapsedIcon are loaded void cacheIcons() const; static QIcon m_expandedIcon; static QIcon m_collapsedIcon; //Does not update the view void partiallyUnExpand(const QModelIndex& index); //Finds out the basic height of the row represented by the given index. Basic means without respecting any expansion. int basicRowHeight( const QModelIndex& index ) const; private: QMap m_partiallyExpanded; // Store expanding-widgets and cache whether items can be expanded mutable QMap m_expandState; QMap< QModelIndex, QPointer > m_expandingWidgets; //Map rows to their expanding-widgets QMap< QModelIndex, int > m_contextMatchQualities; //Map rows to their context-match qualities(undefined if unknown, else 0 to 10). Not used yet, eventually remove. }; /** * Helper-function to merge custom-highlighting variant-lists. * * @param strings A list of strings that should be merged * @param highlights One variant-list for highlighting, as described in the kde header ktextedtor/codecompletionmodel.h * @param gapBetweenStrings How many signs are inserted between 2 strings? * */ QList mergeCustomHighlighting( QStringList strings, QList highlights, int gapBetweenStrings = 0 ); #endif diff --git a/plugins/subversion/kdevsvnplugin.h b/plugins/subversion/kdevsvnplugin.h index 2d6559b81..6f92acea9 100644 --- a/plugins/subversion/kdevsvnplugin.h +++ b/plugins/subversion/kdevsvnplugin.h @@ -1,159 +1,159 @@ /*************************************************************************** * Copyright 2007 Dukju Ahn * * Copyright 2008 Andreas Pakulat * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_KDEVSVNPLUGIN_H #define KDEVPLATFORM_PLUGIN_KDEVSVNPLUGIN_H #include #include #include #include class QMenu; class QUrl; class SvnStatusHolder; class QTemporaryDir; class SvnCommitDialog; namespace ThreadWeaver { class Queue; } namespace KDevelop { class VcsCommitDialog; class ContextMenuExtension; class VcsPluginHelper; } class KDevSvnPlugin: public KDevelop::IPlugin, public KDevelop::ICentralizedVersionControl { Q_OBJECT Q_INTERFACES(KDevelop::IBasicVersionControl KDevelop::ICentralizedVersionControl) public: explicit KDevSvnPlugin(QObject *parent, const QVariantList & = QVariantList()); virtual ~KDevSvnPlugin(); - virtual QString name() const override; - virtual KDevelop::VcsImportMetadataWidget* createImportMetadataWidget(QWidget* parent) override; + QString name() const override; + KDevelop::VcsImportMetadataWidget* createImportMetadataWidget(QWidget* parent) override; // Begin: KDevelop::IBasicVersionControl bool isVersionControlled(const QUrl &localLocation) override; KDevelop::VcsJob* repositoryLocation(const QUrl &localLocation) override; KDevelop::VcsJob* status(const QList& localLocations, KDevelop::IBasicVersionControl::RecursionMode recursion = KDevelop::IBasicVersionControl::Recursive) override; KDevelop::VcsJob* add(const QList& localLocations, KDevelop::IBasicVersionControl::RecursionMode recursion = KDevelop::IBasicVersionControl::Recursive) override; KDevelop::VcsJob* remove(const QList& localLocations) override; KDevelop::VcsJob* copy(const QUrl &localLocationSrc, const QUrl &localLocationDstn) override; KDevelop::VcsJob* move(const QUrl &localLocationSrc, const QUrl &localLocationDst) override; KDevelop::VcsJob* revert(const QList& localLocations, KDevelop::IBasicVersionControl::RecursionMode recursion = KDevelop::IBasicVersionControl::Recursive) override; KDevelop::VcsJob* update(const QList& localLocations, const KDevelop::VcsRevision& rev, KDevelop::IBasicVersionControl::RecursionMode recursion = KDevelop::IBasicVersionControl::Recursive) override; KDevelop::VcsJob* commit(const QString& message, const QList& localLocations, KDevelop::IBasicVersionControl::RecursionMode recursion = KDevelop::IBasicVersionControl::Recursive) override; KDevelop::VcsJob* diff(const QUrl &fileOrDirectory, const KDevelop::VcsRevision& srcRevision, const KDevelop::VcsRevision& dstRevision, KDevelop::VcsDiff::Type = KDevelop::VcsDiff::DiffUnified, KDevelop::IBasicVersionControl::RecursionMode recursion = KDevelop::IBasicVersionControl::Recursive) override; /** * Retrieves a diff between the two locations at the given revisions * * The diff is in unified diff format for text files by default */ KDevelop::VcsJob* diff2(const KDevelop::VcsLocation& localOrRepoLocationSrc, const KDevelop::VcsLocation& localOrRepoLocationDst, const KDevelop::VcsRevision& srcRevision, const KDevelop::VcsRevision& dstRevision, KDevelop::VcsDiff::Type = KDevelop::VcsDiff::DiffDontCare, KDevelop::IBasicVersionControl::RecursionMode = KDevelop::IBasicVersionControl::Recursive); KDevelop::VcsJob* log(const QUrl &localLocation, const KDevelop::VcsRevision& rev, unsigned long limit) override; KDevelop::VcsJob* log(const QUrl &localLocation, const KDevelop::VcsRevision& rev, const KDevelop::VcsRevision& limit) override; KDevelop::VcsJob* annotate(const QUrl &localLocation, const KDevelop::VcsRevision& rev) override; KDevelop::VcsJob* merge(const KDevelop::VcsLocation& localOrRepoLocationSrc, const KDevelop::VcsLocation& localOrRepoLocationDst, const KDevelop::VcsRevision& srcRevision, const KDevelop::VcsRevision& dstRevision, const QUrl &localLocation); KDevelop::VcsJob* resolve(const QList& localLocations, KDevelop::IBasicVersionControl::RecursionMode recursion) override; KDevelop::VcsLocationWidget* vcsLocation(QWidget* parent) const override; // End: KDevelop::IBasicVersionControl // Begin: KDevelop::ICentralizedVersionControl KDevelop::VcsJob* import(const QString & commitMessage, const QUrl &sourceDirectory, const KDevelop::VcsLocation & destinationRepository) override; KDevelop::VcsJob* createWorkingCopy(const KDevelop::VcsLocation & sourceRepository, const QUrl &destinationDirectory, KDevelop::IBasicVersionControl::RecursionMode recursion = KDevelop::IBasicVersionControl::Recursive) override; KDevelop::VcsJob* edit(const QUrl &localLocation) override; KDevelop::VcsJob* unedit(const QUrl &localLocation) override; KDevelop::VcsJob* localRevision(const QUrl &localLocation, KDevelop::VcsRevision::RevisionType) override; // End: KDevelop::ICentralizedVersionControl KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context*) override; ThreadWeaver::Queue* jobQueue() const; public Q_SLOTS: // invoked by context-menu void ctxInfo(); void ctxStatus(); void ctxCopy(); void ctxMove(); void ctxCat(); void ctxImport(); void ctxCheckout(); private: QScopedPointer m_common; QAction* copy_action; QAction* move_action; ThreadWeaver::Queue* m_jobQueue; }; #endif diff --git a/project/projectutils.h b/project/projectutils.h index 6876b2cdc..1ac0f4843 100644 --- a/project/projectutils.h +++ b/project/projectutils.h @@ -1,62 +1,62 @@ /* Copyright (C) 2011 David Nolden This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef KDEVPLATFORM_PROJECTUTILS_H #define KDEVPLATFORM_PROJECTUTILS_H #include "projectexport.h" #include #include class QMenu; namespace KDevelop { class ProjectBaseItem; class ProjectFileItem; // TODO: Move to own header? Rename to ProjectItemContext and remove original from context.h? class KDEVPLATFORMPROJECT_EXPORT ProjectItemContextImpl : public ProjectItemContext { public: explicit ProjectItemContextImpl(const QList& items); - virtual QList urls() const override; + QList urls() const override; private: Q_DISABLE_COPY(ProjectItemContextImpl) }; /** * Adds menu entries for all parent folders of the given item, each containing all the project * items for the folder, at the end of the given menu. * */ KDEVPLATFORMPROJECT_EXPORT void populateParentItemsMenu( ProjectBaseItem* item, QMenu* menu ); /** * Returns all the files that have @p projectItem as ancestor */ KDEVPLATFORMPROJECT_EXPORT QList allFiles(ProjectBaseItem* projectItem); } #endif // KDEVPLATFORM_PROJECTUTILS_H diff --git a/serialization/itemrepository.h b/serialization/itemrepository.h index 05c74e6c3..1803bbcad 100644 --- a/serialization/itemrepository.h +++ b/serialization/itemrepository.h @@ -1,2251 +1,2251 @@ /* Copyright 2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_ITEMREPOSITORY_H #define KDEVPLATFORM_ITEMREPOSITORY_H #include #include #include #include #include #include "referencecounting.h" #include "abstractitemrepository.h" #include "repositorymanager.h" #include "itemrepositoryregistry.h" //#define DEBUG_MONSTERBUCKETS // #define DEBUG_ITEMREPOSITORY_LOADING // #define ifDebugInfiniteRecursion(x) x #define ifDebugInfiniteRecursion(x) // #define ifDebugLostSpace(x) x #define ifDebugLostSpace(x) // #define DEBUG_INCORRECT_DELETE //Makes sure that all items stay reachable through the basic hash // #define DEBUG_ITEM_REACHABILITY ///@todo Dynamic bucket hash size #ifdef DEBUG_ITEM_REACHABILITY #define ENSURE_REACHABLE(bucket) Q_ASSERT(allItemsReachable(bucket)); #define IF_ENSURE_REACHABLE(x) x #else #define ENSURE_REACHABLE(bucket) #define IF_ENSURE_REACHABLE(x) #endif #define ITEMREPOSITORY_USE_MMAP_LOADING //Assertion macro that prevents warnings if debugging is disabled //Only use it to verify values, it should not call any functions, since else the function will even be called in release mode #ifdef QT_NO_DEBUG #define VERIFY(X) if(!(X)) {qWarning() << "Failed to verify expression" << #X;} #else #define VERIFY(X) Q_ASSERT(X) #endif ///When this is uncommented, a 64-bit test-value is written behind the area an item is allowed to write into before ///createItem(..) is called, and an assertion triggers when it was changed during createItem(), which means createItem wrote too long. ///The problem: This temporarily overwrites valid data in the following item, so it will cause serious problems if that data is accessed ///during the call to createItem(). // #define DEBUG_WRITING_EXTENTS class TestItemRepository; namespace KDevelop { /** * This file implements a generic bucket-based indexing repository, that can be used for example to index strings. * * All you need to do is define your item type that you want to store into the repository, and create a request item * similar to ExampleItemRequest that compares and fills the defined item type. * * For example the string repository uses "unsigned short" as item-type, uses that actual value to store the length of the string, * and uses the space behind to store the actual string content. * * @see AbstractItemRepository * @see ItemRepository * * @see ExampleItem * @see ExampleItemRequest * * @see typerepository.h * @see stringrepository.h * @see indexedstring.h */ enum { ItemRepositoryBucketSize = 1<<16, ItemRepositoryBucketLimit = 1<<16 }; /** * Buckets are the memory-units that are used to store the data in an ItemRepository. * * About monster buckets: Normally a bucket has a size of 64kb, but when an item is * allocated that is larger than that, a "monster bucket" is allocated, which spans the * space of multiple buckets. */ template class Bucket { public: enum { AdditionalSpacePerItem = 2 }; enum { ObjectMapSize = ((ItemRepositoryBucketSize / ItemRequest::AverageSize) * 3) / 2 + 1, MaxFreeItemsForHide = 0, //When less than this count of free items in one buckets is reached, the bucket is removed from the global list of buckets with free items MaxFreeSizeForHide = fixedItemSize ? fixedItemSize : 0, //Only when the largest free size is smaller then this, the bucket is taken from the free list MinFreeItemsForReuse = 10,//When this count of free items in one bucket is reached, consider re-assigning them to new requests MinFreeSizeForReuse = ItemRepositoryBucketSize/20 //When the largest free item is bigger then this, the bucket is automatically added to the free list }; enum { NextBucketHashSize = ObjectMapSize, //Affects the average count of bucket-chains that need to be walked in ItemRepository::index. Must be a multiple of ObjectMapSize DataSize = sizeof(char) + sizeof(unsigned int) * 3 + ItemRepositoryBucketSize + sizeof(short unsigned int) * (ObjectMapSize + NextBucketHashSize + 1) }; enum { CheckStart = 0xff00ff1, CheckEnd = 0xfafcfb }; Bucket() : m_monsterBucketExtent(0) , m_available(0) , m_data(nullptr) , m_mappedData(nullptr) , m_objectMap(nullptr) , m_largestFreeItem(0) , m_freeItemCount(0) , m_nextBucketHash(nullptr) , m_dirty(false) , m_changed(false) , m_lastUsed(0) { } ~Bucket() { if(m_data != m_mappedData) { delete[] m_data; delete[] m_nextBucketHash; delete[] m_objectMap; } } void initialize(int monsterBucketExtent) { if(!m_data) { m_monsterBucketExtent = monsterBucketExtent; m_available = ItemRepositoryBucketSize; m_data = new char[ItemRepositoryBucketSize + monsterBucketExtent * DataSize]; memset(m_data, 0, (ItemRepositoryBucketSize + monsterBucketExtent * DataSize) * sizeof(char)); //The bigger we make the map, the lower the probability of a clash(and thus bad performance). However it increases memory usage. m_objectMap = new short unsigned int[ObjectMapSize]; memset(m_objectMap, 0, ObjectMapSize * sizeof(short unsigned int)); m_nextBucketHash = new short unsigned int[NextBucketHashSize]; memset(m_nextBucketHash, 0, NextBucketHashSize * sizeof(short unsigned int)); m_changed = true; m_dirty = false; m_lastUsed = 0; } } template void readValue(char*& from, T& to) { to = *reinterpret_cast(from); from += sizeof(T); } void initializeFromMap(char* current) { if(!m_data) { char* start = current; readValue(current, m_monsterBucketExtent); Q_ASSERT(current - start == 4); readValue(current, m_available); m_objectMap = reinterpret_cast(current); current += sizeof(short unsigned int) * ObjectMapSize; m_nextBucketHash = reinterpret_cast(current); current += sizeof(short unsigned int) * NextBucketHashSize; readValue(current, m_largestFreeItem); readValue(current, m_freeItemCount); readValue(current, m_dirty); m_data = current; m_mappedData = current; m_changed = false; m_lastUsed = 0; VERIFY(current - start == (DataSize - ItemRepositoryBucketSize)); } } void store(QFile* file, size_t offset) { if(!m_data) return; if(static_cast(file->size()) < offset + (1+m_monsterBucketExtent)*DataSize) file->resize(offset + (1+m_monsterBucketExtent)*DataSize); file->seek(offset); file->write((char*)&m_monsterBucketExtent, sizeof(unsigned int)); file->write((char*)&m_available, sizeof(unsigned int)); file->write((char*)m_objectMap, sizeof(short unsigned int) * ObjectMapSize); file->write((char*)m_nextBucketHash, sizeof(short unsigned int) * NextBucketHashSize); file->write((char*)&m_largestFreeItem, sizeof(short unsigned int)); file->write((char*)&m_freeItemCount, sizeof(unsigned int)); file->write((char*)&m_dirty, sizeof(bool)); file->write(m_data, ItemRepositoryBucketSize + m_monsterBucketExtent * DataSize); if(static_cast(file->pos()) != offset + (1+m_monsterBucketExtent)*DataSize) { KMessageBox::error(nullptr, i18n("Failed writing to %1, probably the disk is full", file->fileName())); abort(); } m_changed = false; #ifdef DEBUG_ITEMREPOSITORY_LOADING { file->flush(); file->seek(offset); uint available, freeItemCount, monsterBucketExtent; short unsigned int largestFree; bool dirty; short unsigned int* m = new short unsigned int[ObjectMapSize]; short unsigned int* h = new short unsigned int[NextBucketHashSize]; file->read((char*)&monsterBucketExtent, sizeof(unsigned int)); char* d = new char[ItemRepositoryBucketSize + monsterBucketExtent * DataSize]; file->read((char*)&available, sizeof(unsigned int)); file->read((char*)m, sizeof(short unsigned int) * ObjectMapSize); file->read((char*)h, sizeof(short unsigned int) * NextBucketHashSize); file->read((char*)&largestFree, sizeof(short unsigned int)); file->read((char*)&freeItemCount, sizeof(unsigned int)); file->read((char*)&dirty, sizeof(bool)); file->read(d, ItemRepositoryBucketSize); Q_ASSERT(monsterBucketExtent == m_monsterBucketExtent); Q_ASSERT(available == m_available); Q_ASSERT(memcmp(d, m_data, ItemRepositoryBucketSize + monsterBucketExtent * DataSize) == 0); Q_ASSERT(memcmp(m, m_objectMap, sizeof(short unsigned int) * ObjectMapSize) == 0); Q_ASSERT(memcmp(h, m_nextBucketHash, sizeof(short unsigned int) * NextBucketHashSize) == 0); Q_ASSERT(m_largestFreeItem == largestFree); Q_ASSERT(m_freeItemCount == freeItemCount); Q_ASSERT(m_dirty == dirty); Q_ASSERT(static_cast(file->pos()) == offset + DataSize + m_monsterBucketExtent * DataSize); delete[] d; delete[] m; delete[] h; } #endif } inline char* data() { return m_data; } inline uint dataSize() const { return ItemRepositoryBucketSize + m_monsterBucketExtent * DataSize; } //Tries to find the index this item has in this bucket, or returns zero if the item isn't there yet. unsigned short findIndex(const ItemRequest& request) const { m_lastUsed = 0; unsigned short localHash = request.hash() % ObjectMapSize; unsigned short index = m_objectMap[localHash]; unsigned short follower = 0; //Walk the chain of items with the same local hash while(index && (follower = followerIndex(index)) && !(request.equals(itemFromIndex(index)))) index = follower; if(index && request.equals(itemFromIndex(index))) { return index; //We have found the item } return 0; } //Tries to get the index within this bucket, or returns zero. Will put the item into the bucket if there is room. //Created indices will never begin with 0xffff____, so you can use that index-range for own purposes. unsigned short index(const ItemRequest& request, unsigned int itemSize) { m_lastUsed = 0; unsigned short localHash = request.hash() % ObjectMapSize; unsigned short index = m_objectMap[localHash]; unsigned short insertedAt = 0; unsigned short follower = 0; //Walk the chain of items with the same local hash while(index && (follower = followerIndex(index)) && !(request.equals(itemFromIndex(index)))) index = follower; if(index && request.equals(itemFromIndex(index))) return index; //We have found the item ifDebugLostSpace( Q_ASSERT(!lostSpace()); ) prepareChange(); unsigned int totalSize = itemSize + AdditionalSpacePerItem; if(m_monsterBucketExtent) { ///This is a monster-bucket. Other rules are applied here. Only one item can be allocated, and that must be bigger than the bucket data Q_ASSERT(totalSize > ItemRepositoryBucketSize); Q_ASSERT(m_available); m_available = 0; insertedAt = AdditionalSpacePerItem; setFollowerIndex(insertedAt, 0); Q_ASSERT(m_objectMap[localHash] == 0); m_objectMap[localHash] = insertedAt; if(markForReferenceCounting) enableDUChainReferenceCounting(m_data, dataSize()); request.createItem(reinterpret_cast(m_data + insertedAt)); if(markForReferenceCounting) disableDUChainReferenceCounting(m_data); return insertedAt; } //The second condition is needed, else we can get problems with zero-length items and an overflow in insertedAt to zero if(totalSize > m_available || (!itemSize && totalSize == m_available)) { //Try finding the smallest freed item that can hold the data unsigned short currentIndex = m_largestFreeItem; unsigned short previousIndex = 0; unsigned short freeChunkSize = 0; ///@todo Achieve this without full iteration while(currentIndex && freeSize(currentIndex) > itemSize) { unsigned short follower = followerIndex(currentIndex); if(follower && freeSize(follower) >= itemSize) { //The item also fits into the smaller follower, so use that one previousIndex = currentIndex; currentIndex = follower; }else{ //The item fits into currentIndex, but not into the follower. So use currentIndex freeChunkSize = freeSize(currentIndex) - itemSize; //We need 2 bytes to store the free size if(freeChunkSize != 0 && freeChunkSize < AdditionalSpacePerItem+2) { //we can not manage the resulting free chunk as a separate item, so we cannot use this position. //Just pick the biggest free item, because there we can be sure that //either we can manage the split, or we cannot do anything at all in this bucket. freeChunkSize = freeSize(m_largestFreeItem) - itemSize; if(freeChunkSize == 0 || freeChunkSize >= AdditionalSpacePerItem+2) { previousIndex = 0; currentIndex = m_largestFreeItem; }else{ currentIndex = 0; } } break; } } if(!currentIndex || freeSize(currentIndex) < (totalSize-AdditionalSpacePerItem)) return 0; if(previousIndex) setFollowerIndex(previousIndex, followerIndex(currentIndex)); else m_largestFreeItem = followerIndex(currentIndex); --m_freeItemCount; //Took one free item out of the chain ifDebugLostSpace( Q_ASSERT((uint)lostSpace() == (uint)(freeSize(currentIndex) + AdditionalSpacePerItem)); ) if(freeChunkSize) { Q_ASSERT(freeChunkSize >= AdditionalSpacePerItem+2); unsigned short freeItemSize = freeChunkSize - AdditionalSpacePerItem; unsigned short freeItemPosition; //Insert the resulting free chunk into the list of free items, so we don't lose it if(isBehindFreeSpace(currentIndex)) { //Create the free item at the beginning of currentIndex, so it can be merged with the free space in front freeItemPosition = currentIndex; currentIndex += freeItemSize + AdditionalSpacePerItem; }else{ //Create the free item behind currentIndex freeItemPosition = currentIndex + itemSize + AdditionalSpacePerItem; } setFreeSize(freeItemPosition, freeItemSize); insertFreeItem(freeItemPosition); } insertedAt = currentIndex; Q_ASSERT((bool)m_freeItemCount == (bool)m_largestFreeItem); }else{ //We have to insert the item insertedAt = ItemRepositoryBucketSize - m_available; insertedAt += AdditionalSpacePerItem; //Room for the prepended follower-index m_available -= totalSize; } ifDebugLostSpace( Q_ASSERT(lostSpace() == totalSize); ) Q_ASSERT(!index || !followerIndex(index)); Q_ASSERT(!m_objectMap[localHash] || index); if(index) setFollowerIndex(index, insertedAt); setFollowerIndex(insertedAt, 0); if(m_objectMap[localHash] == 0) m_objectMap[localHash] = insertedAt; #ifdef DEBUG_CREATEITEM_EXTENTS char* borderBehind = m_data + insertedAt + (totalSize-AdditionalSpacePerItem); quint64 oldValueBehind = 0; if(m_available >= 8) { oldValueBehind = *(quint64*)borderBehind; *((quint64*)borderBehind) = 0xfafafafafafafafaLLU; } #endif //Last thing we do, because createItem may recursively do even more transformation of the repository if(markForReferenceCounting) enableDUChainReferenceCounting(m_data, dataSize()); request.createItem(reinterpret_cast(m_data + insertedAt)); if(markForReferenceCounting) disableDUChainReferenceCounting(m_data); #ifdef DEBUG_CREATEITEM_EXTENTS if(m_available >= 8) { //If this assertion triggers, then the item writes a bigger range than it advertised in Q_ASSERT(*((quint64*)borderBehind) == 0xfafafafafafafafaLLU); *((quint64*)borderBehind) = oldValueBehind; } #endif Q_ASSERT(itemFromIndex(insertedAt)->hash() == request.hash()); Q_ASSERT(itemFromIndex(insertedAt)->itemSize() == itemSize); ifDebugLostSpace( if(lostSpace()) qDebug() << "lost space:" << lostSpace(); Q_ASSERT(!lostSpace()); ) return insertedAt; } ///@param modulo Returns whether this bucket contains an item with (hash % modulo) == (item.hash % modulo) /// The default-parameter is the size of the next-bucket hash that is used by setNextBucketForHash and nextBucketForHash ///@note modulo MUST be a multiple of ObjectMapSize, because (b-a) | (x * h1) => (b-a) | h2, where a|b means a is a multiple of b. /// This this allows efficiently computing the clashes using the local object map hash. bool hasClashingItem(uint hash, uint modulo) { Q_ASSERT(modulo % ObjectMapSize == 0); m_lastUsed = 0; uint hashMod = hash % modulo; unsigned short localHash = hash % ObjectMapSize; unsigned short currentIndex = m_objectMap[localHash]; if(currentIndex == 0) return false; while(currentIndex) { uint currentHash = itemFromIndex(currentIndex)->hash(); Q_ASSERT(currentHash % ObjectMapSize == localHash); if(currentHash % modulo == hashMod) return true; //Clash currentIndex = followerIndex(currentIndex); } return false; } void countFollowerIndexLengths(uint& usedSlots, uint& lengths, uint& slotCount, uint& longestInBucketFollowerChain) { for(uint a = 0; a < ObjectMapSize; ++a) { unsigned short currentIndex = m_objectMap[a]; ++slotCount; uint length = 0; if(currentIndex) { ++usedSlots; while(currentIndex) { ++length; ++lengths; currentIndex = followerIndex(currentIndex); } if(length > longestInBucketFollowerChain) { // qDebug() << "follower-chain at" << a << ":" << length; longestInBucketFollowerChain = length; } } } } //Returns whether the given item is reachabe within this bucket, through its hash. bool itemReachable(const Item* item, uint hash) const { unsigned short localHash = hash % ObjectMapSize; unsigned short currentIndex = m_objectMap[localHash]; while(currentIndex) { if(itemFromIndex(currentIndex) == item) return true; currentIndex = followerIndex(currentIndex); } return false; } template void deleteItem(unsigned short index, unsigned int hash, Repository& repository) { ifDebugLostSpace( Q_ASSERT(!lostSpace()); ) m_lastUsed = 0; prepareChange(); unsigned int size = itemFromIndex(index)->itemSize(); //Step 1: Remove the item from the data-structures that allow finding it: m_objectMap unsigned short localHash = hash % ObjectMapSize; unsigned short currentIndex = m_objectMap[localHash]; unsigned short previousIndex = 0; //Fix the follower-link by setting the follower of the previous item to the next one, or updating m_objectMap while(currentIndex != index) { previousIndex = currentIndex; currentIndex = followerIndex(currentIndex); //If this assertion triggers, the deleted item was not registered under the given hash Q_ASSERT(currentIndex); } Q_ASSERT(currentIndex == index); if(!previousIndex) //The item was directly in the object map m_objectMap[localHash] = followerIndex(index); else setFollowerIndex(previousIndex, followerIndex(index)); Item* item = const_cast(itemFromIndex(index)); if(markForReferenceCounting) enableDUChainReferenceCounting(m_data, dataSize()); ItemRequest::destroy(item, repository); if(markForReferenceCounting) disableDUChainReferenceCounting(m_data); memset(item, 0, size); //For debugging, so we notice the data is wrong if(m_monsterBucketExtent) { ///This is a monster-bucket. Make it completely empty again. Q_ASSERT(!m_available); m_available = ItemRepositoryBucketSize; //Items are always inserted into monster-buckets at a fixed position Q_ASSERT(currentIndex == AdditionalSpacePerItem); Q_ASSERT(m_objectMap[localHash] == 0); }else{ ///Put the space into the free-set setFreeSize(index, size); //Try merging the created free item to other free items around, else add it into the free list insertFreeItem(index); if(m_freeItemCount == 1 && freeSize(m_largestFreeItem) + m_available == ItemRepositoryBucketSize) { //Everything has been deleted, there is only free space left. Make the bucket empty again, //so it can later also be used as a monster-bucket. m_available = ItemRepositoryBucketSize; m_freeItemCount = 0; m_largestFreeItem = 0; } } Q_ASSERT((bool)m_freeItemCount == (bool)m_largestFreeItem); ifDebugLostSpace( Q_ASSERT(!lostSpace()); ) #ifdef DEBUG_INCORRECT_DELETE //Make sure the item cannot be found any more { unsigned short localHash = hash % ObjectMapSize; unsigned short currentIndex = m_objectMap[localHash]; while(currentIndex && currentIndex != index) { previousIndex = currentIndex; currentIndex = followerIndex(currentIndex); } Q_ASSERT(!currentIndex); //The item must not be found } #endif // Q_ASSERT(canAllocateItem(size)); } ///@warning The returned item may be in write-protected memory, so never try doing a const_cast and changing some data /// If you need to change something, use dynamicItemFromIndex ///@warning When using multi-threading, mutex() must be locked as long as you use the returned data inline const Item* itemFromIndex(unsigned short index) const { m_lastUsed = 0; return reinterpret_cast(m_data+index); } bool isEmpty() const { return m_available == ItemRepositoryBucketSize; } ///Returns true if this bucket has no nextBucketForHash links bool noNextBuckets() const { for(int a = 0; a < NextBucketHashSize; ++a) if(m_nextBucketHash[a]) return false; return true; } uint available() const { return m_available; } uint usedMemory() const { return ItemRepositoryBucketSize - m_available; } template bool visitAllItems(Visitor& visitor) const { m_lastUsed = 0; for(uint a = 0; a < ObjectMapSize; ++a) { uint currentIndex = m_objectMap[a]; while(currentIndex) { //Get the follower early, so there is no problems when the current //index is removed if(!visitor(reinterpret_cast(m_data+currentIndex))) return false; currentIndex = followerIndex(currentIndex); } } return true; } ///Returns whether something was changed template int finalCleanup(Repository& repository) { int changed = 0; while(m_dirty) { m_dirty = false; for(uint a = 0; a < ObjectMapSize; ++a) { uint currentIndex = m_objectMap[a]; while(currentIndex) { //Get the follower early, so there is no problems when the current //index is removed const Item* item = reinterpret_cast(m_data+currentIndex); if(!ItemRequest::persistent(item)) { changed += item->itemSize(); deleteItem(currentIndex, item->hash(), repository); m_dirty = true; //Set to dirty so we re-iterate break; } currentIndex = followerIndex(currentIndex); } } } return changed; } unsigned short nextBucketForHash(uint hash) const { m_lastUsed = 0; return m_nextBucketHash[hash % NextBucketHashSize]; } void setNextBucketForHash(unsigned int hash, unsigned short bucket) { m_lastUsed = 0; prepareChange(); m_nextBucketHash[hash % NextBucketHashSize] = bucket; } uint freeItemCount() const { return m_freeItemCount; } short unsigned int totalFreeItemsSize() const { short unsigned int ret = 0; short unsigned int currentIndex = m_largestFreeItem; while(currentIndex) { ret += freeSize(currentIndex); currentIndex = followerIndex(currentIndex); } return ret; } //Size of the largest item that could be inserted into this bucket short unsigned int largestFreeSize() const { short unsigned int ret = 0; if(m_largestFreeItem) ret = freeSize(m_largestFreeItem); if(m_available > (uint)(AdditionalSpacePerItem + (uint)ret)) { ret = m_available - AdditionalSpacePerItem; Q_ASSERT(ret == (m_available - AdditionalSpacePerItem)); } return ret; } bool canAllocateItem(unsigned int size) const { short unsigned int currentIndex = m_largestFreeItem; while(currentIndex) { short unsigned int currentFree = freeSize(currentIndex); if(currentFree < size) return false; //Either we need an exact match, or 2 additional bytes to manage the resulting gap if(size == currentFree || currentFree - size >= AdditionalSpacePerItem + 2) return true; currentIndex = followerIndex(currentIndex); } return false; } void tick() const { ++m_lastUsed; } //How many ticks ago the item was last used int lastUsed() const { return m_lastUsed; } //Whether this bucket was changed since it was last stored bool changed() const { return m_changed; } void prepareChange() { m_changed = true; m_dirty = true; makeDataPrivate(); } bool dirty() const { return m_dirty; } ///Returns the count of following buckets that were merged onto this buckets data array int monsterBucketExtent() const { return m_monsterBucketExtent; } //Counts together the space that is neither accessible through m_objectMap nor through the free items uint lostSpace() { if(m_monsterBucketExtent) return 0; uint need = ItemRepositoryBucketSize - m_available; uint found = 0; for(uint a = 0; a < ObjectMapSize; ++a) { uint currentIndex = m_objectMap[a]; while(currentIndex) { found += reinterpret_cast(m_data+currentIndex)->itemSize() + AdditionalSpacePerItem; currentIndex = followerIndex(currentIndex); } } uint currentIndex = m_largestFreeItem; while(currentIndex) { found += freeSize(currentIndex) + AdditionalSpacePerItem; currentIndex = followerIndex(currentIndex); } return need-found; } private: void makeDataPrivate() { if(m_mappedData == m_data) { short unsigned int* oldObjectMap = m_objectMap; short unsigned int* oldNextBucketHash = m_nextBucketHash; m_data = new char[ItemRepositoryBucketSize + m_monsterBucketExtent * DataSize]; m_objectMap = new short unsigned int[ObjectMapSize]; m_nextBucketHash = new short unsigned int[NextBucketHashSize]; memcpy(m_data, m_mappedData, ItemRepositoryBucketSize + m_monsterBucketExtent * DataSize); memcpy(m_objectMap, oldObjectMap, ObjectMapSize * sizeof(short unsigned int)); memcpy(m_nextBucketHash, oldNextBucketHash, NextBucketHashSize * sizeof(short unsigned int)); } } ///Merges the given index item, which must have a freeSize() set, to surrounding free items, and inserts the result. ///The given index itself should not be in the free items chain yet. ///Returns whether the item was inserted somewhere. void insertFreeItem(unsigned short index) { //If the item-size is fixed, we don't need to do any management. Just keep a list of free items. Items of other size will never be requested. if(!fixedItemSize) { unsigned short currentIndex = m_largestFreeItem; unsigned short previousIndex = 0; while(currentIndex) { Q_ASSERT(currentIndex != index); #ifndef QT_NO_DEBUG unsigned short currentFreeSize = freeSize(currentIndex); #endif ///@todo Achieve this without iterating through all items in the bucket(This is very slow) //Merge behind index if(currentIndex == index + freeSize(index) + AdditionalSpacePerItem) { //Remove currentIndex from the free chain, since it's merged backwards into index if(previousIndex && followerIndex(currentIndex)) Q_ASSERT(freeSize(previousIndex) >= freeSize(followerIndex(currentIndex))); if(previousIndex) setFollowerIndex(previousIndex, followerIndex(currentIndex)); else m_largestFreeItem = followerIndex(currentIndex); --m_freeItemCount; //One was removed //currentIndex is directly behind index, touching its space. Merge them. setFreeSize(index, freeSize(index) + AdditionalSpacePerItem + freeSize(currentIndex)); //Recurse to do even more merging insertFreeItem(index); return; } //Merge before index if(index == currentIndex + freeSize(currentIndex) + AdditionalSpacePerItem) { if(previousIndex && followerIndex(currentIndex)) Q_ASSERT(freeSize(previousIndex) >= freeSize(followerIndex(currentIndex))); //Remove currentIndex from the free chain, since insertFreeItem wants //it not to be in the chain, and it will be inserted in another place if(previousIndex) setFollowerIndex(previousIndex, followerIndex(currentIndex)); else m_largestFreeItem = followerIndex(currentIndex); --m_freeItemCount; //One was removed //index is directly behind currentIndex, touching its space. Merge them. setFreeSize(currentIndex, freeSize(currentIndex) + AdditionalSpacePerItem + freeSize(index)); //Recurse to do even more merging insertFreeItem(currentIndex); return; } previousIndex = currentIndex; currentIndex = followerIndex(currentIndex); #ifndef QT_NO_DEBUG if(currentIndex) Q_ASSERT(freeSize(currentIndex) <= currentFreeSize); #endif } } insertToFreeChain(index); } ///Only inserts the item in the correct position into the free chain. index must not be in the chain yet. void insertToFreeChain(unsigned short index) { if(!fixedItemSize) { ///@todo Use some kind of tree to find the correct position in the chain(This is very slow) //Insert the free item into the chain opened by m_largestFreeItem unsigned short currentIndex = m_largestFreeItem; unsigned short previousIndex = 0; unsigned short size = freeSize(index); while(currentIndex && freeSize(currentIndex) > size) { Q_ASSERT(currentIndex != index); //must not be in the chain yet previousIndex = currentIndex; currentIndex = followerIndex(currentIndex); } if(currentIndex) Q_ASSERT(freeSize(currentIndex) <= size); setFollowerIndex(index, currentIndex); if(previousIndex) { Q_ASSERT(freeSize(previousIndex) >= size); setFollowerIndex(previousIndex, index); } else //This item is larger than all already registered free items, or there are none. m_largestFreeItem = index; }else{ Q_ASSERT(freeSize(index) == fixedItemSize); //When all items have the same size, just prepent to the front. setFollowerIndex(index, m_largestFreeItem); m_largestFreeItem = index; } ++m_freeItemCount; } ///Returns true if the given index is right behind free space, and thus can be merged to the free space. bool isBehindFreeSpace(unsigned short index) const { ///@todo Without iteration! unsigned short currentIndex = m_largestFreeItem; while(currentIndex) { if(index == currentIndex + freeSize(currentIndex) + AdditionalSpacePerItem) return true; currentIndex = followerIndex(currentIndex); } return false; } ///@param index the index of an item @return The index of the next item in the chain of items with a same local hash, or zero inline unsigned short followerIndex(unsigned short index) const { Q_ASSERT(index >= 2); return *reinterpret_cast(m_data+(index-2)); } void setFollowerIndex(unsigned short index, unsigned short follower) { Q_ASSERT(index >= 2); *reinterpret_cast(m_data+(index-2)) = follower; } // Only returns the current value if the item is actually free inline unsigned short freeSize(unsigned short index) const { return *reinterpret_cast(m_data+index); } //Convenience function to set the free-size, only for freed items void setFreeSize(unsigned short index, unsigned short size) { *reinterpret_cast(m_data+index) = size; } int m_monsterBucketExtent; //If this is a monster-bucket, this contains the count of follower-buckets that belong to this one unsigned int m_available; char* m_data; //Structure of the data: (2 byte), (item.size() byte) char* m_mappedData; //Read-only memory-mapped data. If this equals m_data, m_data must not be written short unsigned int* m_objectMap; //Points to the first object in m_data with (hash % ObjectMapSize) == index. Points to the item itself, so subtract 1 to get the pointer to the next item with same local hash. short unsigned int m_largestFreeItem; //Points to the largest item that is currently marked as free, or zero. That one points to the next largest one through followerIndex unsigned int m_freeItemCount; unsigned short* m_nextBucketHash; bool m_dirty; //Whether the data was changed since the last finalCleanup bool m_changed; //Whether this bucket was changed since it was last stored to disk mutable int m_lastUsed; //How many ticks ago this bucket was last accessed }; template struct Locker { //This is a dummy that does nothing template Locker(const T& /*t*/) { } }; template<> struct Locker { Locker(QMutex* mutex) : m_mutex(mutex) { m_mutex->lock(); } ~Locker() { m_mutex->unlock(); } QMutex* m_mutex; }; ///This object needs to be kept alive as long as you change the contents of an item ///stored in the repository. It is needed to correctly track the reference counting ///within disk-storage. ///@warning You can not freely copy this around, when you create a copy, the copy source /// becomes invalid template class DynamicItem { public: DynamicItem(Item* i, void* start, uint size) : m_item(i), m_start(start) { if(markForReferenceCounting) enableDUChainReferenceCounting(m_start, size); // qDebug() << "enabling" << i << "to" << (void*)(((char*)i)+size); } ~DynamicItem() { if(m_start) { // qDebug() << "destructor-disabling" << m_item; if(markForReferenceCounting) disableDUChainReferenceCounting(m_start); } } DynamicItem(const DynamicItem& rhs) : m_item(rhs.m_item), m_start(rhs.m_start) { // qDebug() << "stealing" << m_item; Q_ASSERT(rhs.m_start); rhs.m_start = nullptr; } Item* operator->() { return m_item; } Item* m_item; private: mutable void* m_start; DynamicItem& operator=(const DynamicItem&); }; ///@tparam Item See ExampleItem ///@tparam ItemRequest See ExampleReqestItem ///@tparam fixedItemSize When this is true, all inserted items must have the same size. /// This greatly simplifies and speeds up the task of managing free items within the buckets. ///@tparam markForReferenceCounting Whether the data within the repository should be marked for reference-counting. /// This costs a bit of performance, but must be enabled if there may be data in the repository /// that does on-disk reference counting, like IndexedString, IndexedIdentifier, etc. ///@tparam threadSafe Whether class access should be thread-safe. Disabling this is dangerous when you do multi-threading. /// You have to make sure that mutex() is locked whenever the repository is accessed. template class ItemRepository : public AbstractItemRepository { typedef Locker ThisLocker; typedef Bucket MyBucket; enum { //Must be a multiple of Bucket::ObjectMapSize, so Bucket::hasClashingItem can be computed //Must also be a multiple of Bucket::NextBucketHashSize, for the same reason.(Currently those are same) bucketHashSize = (targetBucketHashSize / MyBucket::ObjectMapSize) * MyBucket::ObjectMapSize }; enum { BucketStartOffset = sizeof(uint) * 7 + sizeof(short unsigned int) * bucketHashSize //Position in the data where the bucket array starts }; public: ///@param registry May be zero, then the repository will not be registered at all. Else, the repository will register itself to that registry. /// If this is zero, you have to care about storing the data using store() and/or close() by yourself. It does not happen automatically. /// For the global standard registry, the storing/loading is triggered from within duchain, so you don't need to care about it. ItemRepository(const QString& repositoryName, ItemRepositoryRegistry* registry = &globalItemRepositoryRegistry(), uint repositoryVersion = 1, AbstractRepositoryManager* manager = nullptr) : m_ownMutex(QMutex::Recursive) , m_mutex(&m_ownMutex) , m_repositoryName(repositoryName) , m_registry(registry) , m_file(nullptr) , m_dynamicFile(nullptr) , m_repositoryVersion(repositoryVersion) , m_manager(manager) { m_unloadingEnabled = true; m_metaDataChanged = true; m_buckets.resize(10); m_buckets.fill(nullptr); memset(m_firstBucketForHash, 0, bucketHashSize * sizeof(short unsigned int)); m_statBucketHashClashes = m_statItemCount = 0; m_currentBucket = 1; //Skip the first bucket, we won't use it so we have the zero indices for special purposes if(m_registry) m_registry->registerRepository(this, m_manager); } ~ItemRepository() { if(m_registry) m_registry->unRegisterRepository(this); close(); } ///Unloading of buckets is enabled by default. Use this to disable it. When unloading is enabled, the data ///gotten from must only itemFromIndex must not be used for a long time. void setUnloadingEnabled(bool enabled) { m_unloadingEnabled = enabled; } ///Returns the index for the given item. If the item is not in the repository yet, it is inserted. ///The index can never be zero. Zero is reserved for your own usage as invalid ///@param request Item to retrieve the index from unsigned int index(const ItemRequest& request) { ThisLocker lock(m_mutex); const uint hash = request.hash(); const uint size = request.itemSize(); // Bucket indexes tracked while walking the bucket chain for this request hash unsigned short bucketInChainWithSpace = 0; unsigned short lastBucketWalked = 0; const ushort foundIndexInBucket = walkBucketChain(hash, [&](ushort bucketIdx, const MyBucket* bucketPtr) { lastBucketWalked = bucketIdx; const ushort found = bucketPtr->findIndex(request); if (!found && !bucketInChainWithSpace && bucketPtr->canAllocateItem(size)) { bucketInChainWithSpace = bucketIdx; } return found; }); if (foundIndexInBucket) { // 'request' is already present, return the existing index return createIndex(lastBucketWalked, foundIndexInBucket); } /* * Disclaimer: Writer of comment != writer of code, believe with caution * * Requested item does not yet exist. Need to find a place to put it... * * First choice is to place it in an existing bucket in the chain for the request hash * Second choice is to find an existing bucket anywhere with enough space * Otherwise use m_currentBucket (the latest unused bucket) * * If the chosen bucket fails to allocate the item, merge buckets to create a monster (dragon?) * * Finally, if the first option failed or the selected bucket failed to allocate, add the * bucket which the item ended up in to the chain of buckets for the request's hash */ m_metaDataChanged = true; const bool pickedBucketInChain = bucketInChainWithSpace; int useBucket = bucketInChainWithSpace; int reOrderFreeSpaceBucketIndex = -1; if (!pickedBucketInChain) { //Try finding an existing bucket with deleted space to store the data into for(int a = 0; a < m_freeSpaceBuckets.size(); ++a) { MyBucket* bucketPtr = bucketForIndex(m_freeSpaceBuckets[a]); Q_ASSERT(bucketPtr->largestFreeSize()); if(bucketPtr->canAllocateItem(size)) { //The item fits into the bucket. useBucket = m_freeSpaceBuckets[a]; reOrderFreeSpaceBucketIndex = a; break; } } if (!useBucket) { useBucket = m_currentBucket; } } else { reOrderFreeSpaceBucketIndex = m_freeSpaceBuckets.indexOf(useBucket); } //The item isn't in the repository yet, find a new bucket for it while(1) { if(useBucket >= m_buckets.size()) { if(m_buckets.size() >= 0xfffe) { //We have reserved the last bucket index 0xffff for special purposes //the repository has overflown. qWarning() << "Found no room for an item in" << m_repositoryName << "size of the item:" << request.itemSize(); return 0; }else{ //Allocate new buckets m_buckets.resize(m_buckets.size() + 10); } } MyBucket* bucketPtr = m_buckets.at(useBucket); if(!bucketPtr) { initializeBucket(useBucket); bucketPtr = m_buckets.at(useBucket); } ENSURE_REACHABLE(useBucket); Q_ASSERT_X(!bucketPtr->findIndex(request), Q_FUNC_INFO, "found item in unexpected bucket, ensure your ItemRequest::equals method is correct. Note: For custom AbstractType's e.g. ensure you have a proper equals() override"); unsigned short indexInBucket = bucketPtr->index(request, size); //If we could not allocate the item in an empty bucket, then we need to create a monster-bucket that //can hold the data. if(bucketPtr->isEmpty() && !indexInBucket) { ///@todo Move this compound statement into an own function uint totalSize = size + MyBucket::AdditionalSpacePerItem; Q_ASSERT((totalSize > ItemRepositoryBucketSize)); useBucket = 0; //The item did not fit in, we need a monster-bucket(Merge consecutive buckets) ///Step one: Search whether we can merge multiple empty buckets in the free-list into one monster-bucket int rangeStart = -1; int rangeEnd = -1; for(int a = 0; a < m_freeSpaceBuckets.size(); ++a) { MyBucket* bucketPtr = bucketForIndex(m_freeSpaceBuckets[a]); if(bucketPtr->isEmpty()) { //This bucket is a candidate for monster-bucket merging int index = (int)m_freeSpaceBuckets[a]; if(rangeEnd != index) { rangeStart = index; rangeEnd = index+1; }else{ ++rangeEnd; } if(rangeStart != rangeEnd) { uint extent = rangeEnd - rangeStart - 1; uint totalAvailableSpace = bucketForIndex(rangeStart)->available() + MyBucket::DataSize * (rangeEnd - rangeStart - 1); if(totalAvailableSpace > totalSize) { Q_ASSERT(extent); ///We can merge these buckets into one monster-bucket that can hold the data Q_ASSERT((uint)m_freeSpaceBuckets[a-extent] == (uint)rangeStart); m_freeSpaceBuckets.remove(a-extent, extent+1); useBucket = rangeStart; convertMonsterBucket(rangeStart, extent); break; } } } } if(!useBucket) { //Create a new monster-bucket at the end of the data int needMonsterExtent = (totalSize - ItemRepositoryBucketSize) / MyBucket::DataSize + 1; Q_ASSERT(needMonsterExtent); if(m_currentBucket + needMonsterExtent + 1 > m_buckets.size()) { m_buckets.resize(m_buckets.size() + 10 + needMonsterExtent + 1); } useBucket = m_currentBucket; convertMonsterBucket(useBucket, needMonsterExtent); m_currentBucket += 1 + needMonsterExtent; Q_ASSERT(m_currentBucket < ItemRepositoryBucketLimit); Q_ASSERT(m_buckets[m_currentBucket - 1 - needMonsterExtent] && m_buckets[m_currentBucket - 1 - needMonsterExtent]->monsterBucketExtent() == needMonsterExtent); } Q_ASSERT(useBucket); bucketPtr = bucketForIndex(useBucket); indexInBucket = bucketPtr->index(request, size); Q_ASSERT(indexInBucket); } if(indexInBucket) { ++m_statItemCount; const int previousBucketNumber = lastBucketWalked; unsigned short* const bucketHashPosition = m_firstBucketForHash + (hash % bucketHashSize); if(!(*bucketHashPosition)) { Q_ASSERT(!previousBucketNumber); (*bucketHashPosition) = useBucket; ENSURE_REACHABLE(useBucket); } else if(!pickedBucketInChain && previousBucketNumber && previousBucketNumber != useBucket) { //Should happen rarely ++m_statBucketHashClashes; ///Debug: Detect infinite recursion ifDebugInfiniteRecursion(Q_ASSERT(walkBucketLinks(*bucketHashPosition, hash, previousBucketNumber));) //Find the position where the paths of useBucket and *bucketHashPosition intersect, and insert useBucket //there. That way, we don't create loops. QPair intersect = hashChainIntersection(*bucketHashPosition, useBucket, hash); Q_ASSERT(m_buckets[previousBucketNumber]->nextBucketForHash(hash) == 0); if(!intersect.second) { ifDebugInfiniteRecursion(Q_ASSERT(!walkBucketLinks(*bucketHashPosition, hash, useBucket));) ifDebugInfiniteRecursion(Q_ASSERT(!walkBucketLinks(useBucket, hash, previousBucketNumber));) Q_ASSERT(m_buckets[previousBucketNumber]->nextBucketForHash(hash) == 0); m_buckets[previousBucketNumber]->setNextBucketForHash(hash, useBucket); ENSURE_REACHABLE(useBucket); ENSURE_REACHABLE(previousBucketNumber); ifDebugInfiniteRecursion(Q_ASSERT(walkBucketLinks(*bucketHashPosition, hash, useBucket));) } else if(intersect.first) { ifDebugInfiniteRecursion(Q_ASSERT(bucketForIndex(intersect.first)->nextBucketForHash(hash) == intersect.second);) ifDebugInfiniteRecursion(Q_ASSERT(!walkBucketLinks(*bucketHashPosition, hash, useBucket));) ifDebugInfiniteRecursion(Q_ASSERT(walkBucketLinks(*bucketHashPosition, hash, intersect.second));) ifDebugInfiniteRecursion(Q_ASSERT(walkBucketLinks(*bucketHashPosition, hash, intersect.first));) ifDebugInfiniteRecursion(Q_ASSERT(bucketForIndex(intersect.first)->nextBucketForHash(hash) == intersect.second);) ifDebugInfiniteRecursion(Q_ASSERT(walkBucketLinks(useBucket, hash, intersect.second));) ifDebugInfiniteRecursion(Q_ASSERT(!walkBucketLinks(useBucket, hash, intersect.first));) bucketForIndex(intersect.first)->setNextBucketForHash(hash, useBucket); ENSURE_REACHABLE(useBucket); ENSURE_REACHABLE(intersect.second); ifDebugInfiniteRecursion(Q_ASSERT(walkBucketLinks(*bucketHashPosition, hash, useBucket));) ifDebugInfiniteRecursion(Q_ASSERT(walkBucketLinks(*bucketHashPosition, hash, intersect.second));) } else { //State: intersect.first == 0 && intersect.second != 0. This means that whole compleet //chain opened by *bucketHashPosition with the hash-value is also following useBucket, //so useBucket can just be inserted at the top ifDebugInfiniteRecursion(Q_ASSERT(!walkBucketLinks(*bucketHashPosition, hash, useBucket));) ifDebugInfiniteRecursion(Q_ASSERT(walkBucketLinks(useBucket, hash, *bucketHashPosition));) unsigned short oldStart = *bucketHashPosition; *bucketHashPosition = useBucket; ENSURE_REACHABLE(useBucket); ENSURE_REACHABLE(oldStart); Q_UNUSED(oldStart); } } if(reOrderFreeSpaceBucketIndex != -1) updateFreeSpaceOrder(reOrderFreeSpaceBucketIndex); return createIndex(useBucket, indexInBucket); }else{ //This should never happen when we picked a bucket for re-use Q_ASSERT(!pickedBucketInChain); Q_ASSERT(reOrderFreeSpaceBucketIndex == -1); Q_ASSERT(useBucket == m_currentBucket); if(!bucketForIndex(useBucket)->isEmpty()) putIntoFreeList(useBucket, bucketPtr); ++m_currentBucket; Q_ASSERT(m_currentBucket < ItemRepositoryBucketLimit); useBucket = m_currentBucket; } } //We haven't found a bucket that already contains the item, so append it to the current bucket qWarning() << "Found no bucket for an item in" << m_repositoryName; return 0; } ///Returns zero if the item is not in the repository yet unsigned int findIndex(const ItemRequest& request) { ThisLocker lock(m_mutex); return walkBucketChain(request.hash(), [this, &request](ushort bucketIdx, const MyBucket* bucketPtr) { const ushort indexInBucket = bucketPtr->findIndex(request); return indexInBucket ? createIndex(bucketIdx, indexInBucket) : 0u; }); } ///Deletes the item from the repository. void deleteItem(unsigned int index) { verifyIndex(index); ThisLocker lock(m_mutex); m_metaDataChanged = true; const uint hash = itemFromIndex(index)->hash(); const ushort bucket = (index >> 16); //Apart from removing the item itself, we may have to recreate the nextBucketForHash link, so we need the previous bucket MyBucket* previousBucketPtr = nullptr; MyBucket* const bucketPtr = walkBucketChain(hash, [bucket, &previousBucketPtr](ushort bucketIdx, MyBucket* bucketPtr) -> MyBucket* { if (bucket != bucketIdx) { previousBucketPtr = bucketPtr; return nullptr; } return bucketPtr; // found bucket, stop looking }); //Make sure the index was reachable through the hash chain Q_ASSERT(bucketPtr); --m_statItemCount; bucketPtr->deleteItem(index, hash, *this); /** * Now check whether the link root/previousBucketNumber -> bucket is still needed. */ if (!previousBucketPtr) { // This bucket is linked in the m_firstBucketForHash array, find the next clashing bucket in the chain // There may be items in the chain that clash only with MyBucket::NextBucketHashSize, skipped here m_firstBucketForHash[hash % bucketHashSize] = walkBucketChain(hash, [hash](ushort bucketIdx, MyBucket *bucketPtr){ if (bucketPtr->hasClashingItem(hash, bucketHashSize)) { return bucketIdx; } return static_cast(0); }); } else if(!bucketPtr->hasClashingItem(hash, MyBucket::NextBucketHashSize)) { // TODO: Skip clashing items reachable from m_firstBucketForHash // (see note in usePermissiveModuloWhenRemovingClashLinks() test) ENSURE_REACHABLE(bucket); previousBucketPtr->setNextBucketForHash(hash, bucketPtr->nextBucketForHash(hash)); Q_ASSERT(m_buckets[bucketPtr->nextBucketForHash(hash)] != previousBucketPtr); } ENSURE_REACHABLE(bucket); if(bucketPtr->monsterBucketExtent()) { //Convert the monster-bucket back to multiple normal buckets, and put them into the free list uint newBuckets = bucketPtr->monsterBucketExtent()+1; Q_ASSERT(bucketPtr->isEmpty()); if (!previousBucketPtr) { // see https://bugs.kde.org/show_bug.cgi?id=272408 // the monster bucket will be deleted and new smaller ones created // the next bucket for this hash is invalid anyways as done above // but calling the below unconditionally leads to other issues... bucketPtr->setNextBucketForHash(hash, 0); } convertMonsterBucket(bucket, 0); for(uint created = bucket; created < bucket + newBuckets; ++created) { putIntoFreeList(created, bucketForIndex(created)); #ifdef DEBUG_MONSTERBUCKETS Q_ASSERT(m_freeSpaceBuckets.indexOf(created) != -1); #endif } }else{ putIntoFreeList(bucket, bucketPtr); } } typedef DynamicItem MyDynamicItem; ///This returns an editable version of the item. @warning: Never change an entry that affects the hash, ///or the equals(..) function. That would completely destroy the consistency. ///@param index The index. It must be valid(match an existing item), and nonzero. ///@warning If you use this, make sure you lock mutex() before calling, /// and hold it until you're ready using/changing the data.. MyDynamicItem dynamicItemFromIndex(unsigned int index) { verifyIndex(index); ThisLocker lock(m_mutex); unsigned short bucket = (index >> 16); MyBucket* bucketPtr = m_buckets.at(bucket); if(!bucketPtr) { initializeBucket(bucket); bucketPtr = m_buckets.at(bucket); } bucketPtr->prepareChange(); unsigned short indexInBucket = index & 0xffff; return MyDynamicItem(const_cast(bucketPtr->itemFromIndex(indexInBucket)), bucketPtr->data(), bucketPtr->dataSize()); } ///This returns an editable version of the item. @warning: Never change an entry that affects the hash, ///or the equals(..) function. That would completely destroy the consistency. ///@param index The index. It must be valid(match an existing item), and nonzero. ///@warning If you use this, make sure you lock mutex() before calling, /// and hold it until you're ready using/changing the data.. ///@warning If you change contained complex items that depend on reference-counting, you /// must use dynamicItemFromIndex(..) instead of dynamicItemFromIndexSimple(..) Item* dynamicItemFromIndexSimple(unsigned int index) { verifyIndex(index); ThisLocker lock(m_mutex); unsigned short bucket = (index >> 16); MyBucket* bucketPtr = m_buckets.at(bucket); if(!bucketPtr) { initializeBucket(bucket); bucketPtr = m_buckets.at(bucket); } bucketPtr->prepareChange(); unsigned short indexInBucket = index & 0xffff; return const_cast(bucketPtr->itemFromIndex(indexInBucket)); } ///@param index The index. It must be valid(match an existing item), and nonzero. const Item* itemFromIndex(unsigned int index) const { verifyIndex(index); ThisLocker lock(m_mutex); unsigned short bucket = (index >> 16); const MyBucket* bucketPtr = m_buckets.at(bucket); if(!bucketPtr) { initializeBucket(bucket); bucketPtr = m_buckets.at(bucket); } unsigned short indexInBucket = index & 0xffff; return bucketPtr->itemFromIndex(indexInBucket); } struct Statistics { Statistics() : loadedBuckets(-1), currentBucket(-1), usedMemory(-1), loadedMonsterBuckets(-1), usedSpaceForBuckets(-1), freeSpaceInBuckets(-1), lostSpace(-1), freeUnreachableSpace(-1), hashClashedItems(-1), totalItems(-1), hashSize(-1), hashUse(-1), averageInBucketHashSize(-1), averageInBucketUsedSlotCount(-1), averageInBucketSlotChainLength(-1), longestInBucketChain(-1), longestNextBucketChain(-1), totalBucketFollowerSlots(-1), averageNextBucketForHashSequenceLength(-1) { } uint loadedBuckets; uint currentBucket; uint usedMemory; uint loadedMonsterBuckets; uint usedSpaceForBuckets; uint freeSpaceInBuckets; uint lostSpace; uint freeUnreachableSpace; uint hashClashedItems; uint totalItems; uint emptyBuckets; uint hashSize; //How big the hash is uint hashUse; //How many slots in the hash are used uint averageInBucketHashSize; uint averageInBucketUsedSlotCount; float averageInBucketSlotChainLength; uint longestInBucketChain; uint longestNextBucketChain; uint totalBucketFollowerSlots; //Total count of used slots in the nextBucketForHash structure float averageNextBucketForHashSequenceLength; //Average sequence length of a nextBucketForHash sequence(If not empty) QString print() const { QString ret; ret += QStringLiteral("loaded buckets: %1 current bucket: %2 used memory: %3 loaded monster buckets: %4").arg(loadedBuckets).arg(currentBucket).arg(usedMemory).arg(loadedMonsterBuckets); ret += QStringLiteral("\nbucket hash clashed items: %1 total items: %2").arg(hashClashedItems).arg(totalItems); ret += QStringLiteral("\nused space for buckets: %1 free space in buckets: %2 lost space: %3").arg(usedSpaceForBuckets).arg(freeSpaceInBuckets).arg(lostSpace); ret += QStringLiteral("\nfree unreachable space: %1 empty buckets: %2").arg(freeUnreachableSpace).arg(emptyBuckets); ret += QStringLiteral("\nhash size: %1 hash slots used: %2").arg(hashSize).arg(hashUse); ret += QStringLiteral("\naverage in-bucket hash size: %1 average in-bucket used hash slot count: %2 average in-bucket slot chain length: %3 longest in-bucket follower chain: %4").arg(averageInBucketHashSize).arg(averageInBucketUsedSlotCount).arg(averageInBucketSlotChainLength).arg(longestInBucketChain); ret += QStringLiteral("\ntotal count of used next-bucket-for-hash slots: %1 average next-bucket-for-hash sequence length: %2 longest next-bucket chain: %3").arg(totalBucketFollowerSlots).arg(averageNextBucketForHashSequenceLength).arg(longestNextBucketChain); return ret; } operator QString() const { return print(); } }; QString printStatistics() const override { return statistics().print(); } Statistics statistics() const { Statistics ret; uint loadedBuckets = 0; for(int a = 0; a < m_buckets.size(); ++a) if(m_buckets[a]) ++loadedBuckets; #ifdef DEBUG_MONSTERBUCKETS for(int a = 0; a < m_freeSpaceBuckets.size(); ++a) { if(a > 0) { uint prev = a-1; uint prevLargestFree = bucketForIndex(m_freeSpaceBuckets[prev])->largestFreeSize(); uint largestFree = bucketForIndex(m_freeSpaceBuckets[a])->largestFreeSize(); Q_ASSERT( (prevLargestFree < largestFree) || (prevLargestFree == largestFree && m_freeSpaceBuckets[prev] < m_freeSpaceBuckets[a]) ); } } #endif ret.hashSize = bucketHashSize; ret.hashUse = 0; for(uint a = 0; a < bucketHashSize; ++a) if(m_firstBucketForHash[a]) ++ret.hashUse; ret.emptyBuckets = 0; uint loadedMonsterBuckets = 0; for(int a = 0; a < m_buckets.size(); ++a) if(m_buckets[a] && m_buckets[a]->monsterBucketExtent()) loadedMonsterBuckets += m_buckets[a]->monsterBucketExtent()+1; uint usedBucketSpace = MyBucket::DataSize * m_currentBucket; uint freeBucketSpace = 0, freeUnreachableSpace = 0; uint lostSpace = 0; //Should be zero, else something is wrong uint totalInBucketHashSize = 0, totalInBucketUsedSlotCount = 0, totalInBucketChainLengths = 0; uint bucketCount = 0; ret.totalBucketFollowerSlots = 0; ret.averageNextBucketForHashSequenceLength = 0; ret.longestNextBucketChain = 0; ret.longestInBucketChain = 0; for(int a = 1; a < m_currentBucket+1; ++a) { MyBucket* bucket = bucketForIndex(a); if(bucket) { ++bucketCount; bucket->countFollowerIndexLengths(totalInBucketUsedSlotCount, totalInBucketChainLengths, totalInBucketHashSize, ret.longestInBucketChain); for(uint aa = 0; aa < MyBucket::NextBucketHashSize; ++aa) { uint length = 0; uint next = bucket->nextBucketForHash(aa); if(next) { ++ret.totalBucketFollowerSlots; while(next) { ++length; ++ret.averageNextBucketForHashSequenceLength; next = bucketForIndex(next)->nextBucketForHash(aa); } } if(length > ret.longestNextBucketChain) { // qDebug() << "next-bucket-chain in" << a << aa << ":" << length; ret.longestNextBucketChain = length; } } uint bucketFreeSpace = bucket->totalFreeItemsSize() + bucket->available(); freeBucketSpace += bucketFreeSpace; if(m_freeSpaceBuckets.indexOf(a) == -1) freeUnreachableSpace += bucketFreeSpace; if(bucket->isEmpty()) { ++ret.emptyBuckets; Q_ASSERT(!bucket->monsterBucketExtent()); #ifdef DEBUG_MONSTERBUCKETS Q_ASSERT(m_freeSpaceBuckets.contains(a)); #endif } lostSpace += bucket->lostSpace(); a += bucket->monsterBucketExtent(); } } if(ret.totalBucketFollowerSlots) ret.averageNextBucketForHashSequenceLength /= ret.totalBucketFollowerSlots; ret.loadedBuckets = loadedBuckets; ret.currentBucket = m_currentBucket; ret.usedMemory = usedMemory(); ret.loadedMonsterBuckets = loadedMonsterBuckets; ret.hashClashedItems = m_statBucketHashClashes; ret.totalItems = m_statItemCount; ret.usedSpaceForBuckets = usedBucketSpace; ret.freeSpaceInBuckets = freeBucketSpace; ret.lostSpace = lostSpace; ret.freeUnreachableSpace = freeUnreachableSpace; ret.averageInBucketHashSize = totalInBucketHashSize / bucketCount; ret.averageInBucketUsedSlotCount = totalInBucketUsedSlotCount / bucketCount; ret.averageInBucketSlotChainLength = float(totalInBucketChainLengths) / totalInBucketUsedSlotCount; //If m_statBucketHashClashes is high, the bucket-hash needs to be bigger return ret; } uint usedMemory() const { uint used = 0; for(int a = 0; a < m_buckets.size(); ++a) { if(m_buckets[a]) { used += m_buckets[a]->usedMemory(); } } return used; } ///This can be used to safely iterate through all items in the repository ///@param visitor Should be an instance of a class that has a bool operator()(const Item*) member function, /// that returns whether more items are wanted. ///@param onlyInMemory If this is true, only items are visited that are currently in memory. template void visitAllItems(Visitor& visitor, bool onlyInMemory = false) const { ThisLocker lock(m_mutex); for(int a = 1; a <= m_currentBucket; ++a) { if(!onlyInMemory || m_buckets.at(a)) { if(bucketForIndex(a) && !bucketForIndex(a)->visitAllItems(visitor)) return; } } } ///Synchronizes the state on disk to the one in memory, and does some memory-management. ///Should be called on a regular basis. Can be called centrally from the global item repository registry. - virtual void store() override { + void store() override { QMutexLocker lock(m_mutex); if(m_file) { if(!m_file->open( QFile::ReadWrite ) || !m_dynamicFile->open( QFile::ReadWrite )) { qFatal("cannot re-open repository file for storing"); return; } for(int a = 0; a < m_buckets.size(); ++a) { if(m_buckets[a]) { if(m_buckets[a]->changed()) { storeBucket(a); } if(m_unloadingEnabled) { const int unloadAfterTicks = 2; if(m_buckets[a]->lastUsed() > unloadAfterTicks) { delete m_buckets[a]; m_buckets[a] = nullptr; }else{ m_buckets[a]->tick(); } } } } if(m_metaDataChanged) { Q_ASSERT(m_dynamicFile); m_file->seek(0); m_file->write((char*)&m_repositoryVersion, sizeof(uint)); uint hashSize = bucketHashSize; m_file->write((char*)&hashSize, sizeof(uint)); uint itemRepositoryVersion = staticItemRepositoryVersion(); m_file->write((char*)&itemRepositoryVersion, sizeof(uint)); m_file->write((char*)&m_statBucketHashClashes, sizeof(uint)); m_file->write((char*)&m_statItemCount, sizeof(uint)); const uint bucketCount = static_cast(m_buckets.size()); m_file->write((char*)&bucketCount, sizeof(uint)); m_file->write((char*)&m_currentBucket, sizeof(uint)); m_file->write((char*)m_firstBucketForHash, sizeof(short unsigned int) * bucketHashSize); Q_ASSERT(m_file->pos() == BucketStartOffset); m_dynamicFile->seek(0); const uint freeSpaceBucketsSize = static_cast(m_freeSpaceBuckets.size()); m_dynamicFile->write((char*)&freeSpaceBucketsSize, sizeof(uint)); m_dynamicFile->write((char*)m_freeSpaceBuckets.data(), sizeof(uint) * freeSpaceBucketsSize); } //To protect us from inconsistency due to crashes. flush() is not enough. We need to close. m_file->close(); m_dynamicFile->close(); Q_ASSERT(!m_file->isOpen()); Q_ASSERT(!m_dynamicFile->isOpen()); } } ///This mutex is used for the thread-safe locking when threadSafe is true. Even if threadSafe is false, it is ///always locked before storing to or loading from disk. ///@warning If threadSafe is false, and you sometimes call store() from within another thread(As happens in duchain), /// you must always make sure that this mutex is locked before you access this repository. /// Else you will get crashes and inconsistencies. /// In KDevelop This means: Make sure you _always_ lock this mutex before accessing the repository. QMutex* mutex() const { return m_mutex; } ///With this, you can replace the internal mutex with another one. void setMutex(QMutex* mutex) { m_mutex = mutex; } - virtual QString repositoryName() const override { + QString repositoryName() const override { return m_repositoryName; } private: uint createIndex(ushort bucketIndex, ushort indexInBucket) { //Combine the index in the bucket, and the bucket number into one index const uint index = (bucketIndex << 16) + indexInBucket; verifyIndex(index); return index; } /** * Walks through all buckets clashing with @p hash * * Will return the value returned by the lambda, returning early if truthy */ template auto walkBucketChain(unsigned int hash, const Visitor& visitor) const -> decltype(visitor(0, nullptr)) { unsigned short bucketIndex = m_firstBucketForHash[hash % bucketHashSize]; while (bucketIndex) { auto* bucketPtr = m_buckets.at(bucketIndex); if (!bucketPtr) { initializeBucket(bucketIndex); bucketPtr = m_buckets.at(bucketIndex); } if (auto visitResult = visitor(bucketIndex, bucketPtr)) { return visitResult; } bucketIndex = bucketPtr->nextBucketForHash(hash); } return {}; } ///Makes sure the order within m_freeSpaceBuckets is correct, after largestFreeSize has been changed for m_freeSpaceBuckets[index]. ///If too few space is free within the given bucket, it is removed from m_freeSpaceBuckets. void updateFreeSpaceOrder(uint index) { m_metaDataChanged = true; unsigned int* freeSpaceBuckets = m_freeSpaceBuckets.data(); Q_ASSERT(index < static_cast(m_freeSpaceBuckets.size())); MyBucket* bucketPtr = bucketForIndex(freeSpaceBuckets[index]); unsigned short largestFreeSize = bucketPtr->largestFreeSize(); if(largestFreeSize == 0 || (bucketPtr->freeItemCount() <= MyBucket::MaxFreeItemsForHide && largestFreeSize <= MyBucket::MaxFreeSizeForHide)) { //Remove the item from freeSpaceBuckets m_freeSpaceBuckets.remove(index); }else{ while(1) { int prev = index-1; int next = index+1; if(prev >= 0 && (bucketForIndex(freeSpaceBuckets[prev])->largestFreeSize() > largestFreeSize || (bucketForIndex(freeSpaceBuckets[prev])->largestFreeSize() == largestFreeSize && freeSpaceBuckets[index] < freeSpaceBuckets[prev])) ) { //This item should be behind the successor, either because it has a lower largestFreeSize, or because the index is lower uint oldPrevValue = freeSpaceBuckets[prev]; freeSpaceBuckets[prev] = freeSpaceBuckets[index]; freeSpaceBuckets[index] = oldPrevValue; index = prev; }else if(next < m_freeSpaceBuckets.size() && (bucketForIndex(freeSpaceBuckets[next])->largestFreeSize() < largestFreeSize || (bucketForIndex(freeSpaceBuckets[next])->largestFreeSize() == largestFreeSize && freeSpaceBuckets[index] > freeSpaceBuckets[next]))) { //This item should be behind the successor, either because it has a higher largestFreeSize, or because the index is higher uint oldNextValue = freeSpaceBuckets[next]; freeSpaceBuckets[next] = freeSpaceBuckets[index]; freeSpaceBuckets[index] = oldNextValue; index = next; }else { break; } } } } ///Does conversion from monster-bucket to normal bucket and from normal bucket to monster-bucket ///The bucket @param bucketNumber must already be loaded and empty. the "extent" buckets behind must also be loaded, ///and also be empty. ///The created buckets are not registered anywhere. When converting from monster-bucket to normal bucket, ///oldExtent+1 normal buckets are created, that must be registered somewhere. ///@warning During conversion, all the touched buckets are deleted and re-created ///@param extent When this is zero, the bucket is converted from monster-bucket to normal bucket. /// When it is nonzero, it is converted to a monster-bucket. MyBucket* convertMonsterBucket(int bucketNumber, int extent) { Q_ASSERT(bucketNumber); MyBucket* bucketPtr = m_buckets.at(bucketNumber); if(!bucketPtr) { initializeBucket(bucketNumber); bucketPtr = m_buckets.at(bucketNumber); } if(extent) { //Convert to monster-bucket #ifdef DEBUG_MONSTERBUCKETS for(int index = bucketNumber; index < bucketNumber + 1 + extent; ++index) { Q_ASSERT(bucketPtr->isEmpty()); Q_ASSERT(!bucketPtr->monsterBucketExtent()); Q_ASSERT(m_freeSpaceBuckets.indexOf(index) == -1); } #endif for(int index = bucketNumber; index < bucketNumber + 1 + extent; ++index) deleteBucket(index); m_buckets[bucketNumber] = new MyBucket(); m_buckets[bucketNumber]->initialize(extent); #ifdef DEBUG_MONSTERBUCKETS for(uint index = bucketNumber+1; index < bucketNumber + 1 + extent; ++index) { Q_ASSERT(!m_buckets[index]); } #endif }else{ Q_ASSERT(bucketPtr->monsterBucketExtent()); Q_ASSERT(bucketPtr->isEmpty()); const int oldExtent = bucketPtr->monsterBucketExtent(); deleteBucket(bucketNumber); //Delete the monster-bucket for(int index = bucketNumber; index < bucketNumber + 1 + oldExtent; ++index) { Q_ASSERT(!m_buckets[index]); m_buckets[index] = new MyBucket(); m_buckets[index]->initialize(0); Q_ASSERT(!m_buckets[index]->monsterBucketExtent()); } } return m_buckets[bucketNumber]; } MyBucket* bucketForIndex(short unsigned int index) const { MyBucket* bucketPtr = m_buckets.at(index); if(!bucketPtr) { initializeBucket(index); bucketPtr = m_buckets.at(index); } return bucketPtr; } - virtual bool open(const QString& path) override { + bool open(const QString& path) override { QMutexLocker lock(m_mutex); close(); //qDebug() << "opening repository" << m_repositoryName << "at" << path; QDir dir(path); m_file = new QFile(dir.absoluteFilePath( m_repositoryName )); m_dynamicFile = new QFile(dir.absoluteFilePath( m_repositoryName + QLatin1String("_dynamic") )); if(!m_file->open( QFile::ReadWrite ) || !m_dynamicFile->open( QFile::ReadWrite ) ) { delete m_file; m_file = nullptr; delete m_dynamicFile; m_dynamicFile = nullptr; return false; } m_metaDataChanged = true; if(m_file->size() == 0) { m_file->resize(0); m_file->write((char*)&m_repositoryVersion, sizeof(uint)); uint hashSize = bucketHashSize; m_file->write((char*)&hashSize, sizeof(uint)); uint itemRepositoryVersion = staticItemRepositoryVersion(); m_file->write((char*)&itemRepositoryVersion, sizeof(uint)); m_statBucketHashClashes = m_statItemCount = 0; m_file->write((char*)&m_statBucketHashClashes, sizeof(uint)); m_file->write((char*)&m_statItemCount, sizeof(uint)); m_buckets.resize(10); m_buckets.fill(nullptr); uint bucketCount = m_buckets.size(); m_file->write((char*)&bucketCount, sizeof(uint)); memset(m_firstBucketForHash, 0, bucketHashSize * sizeof(short unsigned int)); m_currentBucket = 1; //Skip the first bucket, we won't use it so we have the zero indices for special purposes m_file->write((char*)&m_currentBucket, sizeof(uint)); m_file->write((char*)m_firstBucketForHash, sizeof(short unsigned int) * bucketHashSize); //We have completely initialized the file now if(m_file->pos() != BucketStartOffset) { KMessageBox::error(nullptr, i18n("Failed writing to %1, probably the disk is full", m_file->fileName())); abort(); } const uint freeSpaceBucketsSize = 0; m_dynamicFile->write((char*)&freeSpaceBucketsSize, sizeof(uint)); m_freeSpaceBuckets.clear(); }else{ m_file->close(); bool res = m_file->open( QFile::ReadOnly ); //Re-open in read-only mode, so we create a read-only m_fileMap VERIFY(res); //Check that the version is correct uint storedVersion = 0, hashSize = 0, itemRepositoryVersion = 0; m_file->read((char*)&storedVersion, sizeof(uint)); m_file->read((char*)&hashSize, sizeof(uint)); m_file->read((char*)&itemRepositoryVersion, sizeof(uint)); m_file->read((char*)&m_statBucketHashClashes, sizeof(uint)); m_file->read((char*)&m_statItemCount, sizeof(uint)); if(storedVersion != m_repositoryVersion || hashSize != bucketHashSize || itemRepositoryVersion != staticItemRepositoryVersion()) { qDebug() << "repository" << m_repositoryName << "version mismatch in" << m_file->fileName() << ", stored: version " << storedVersion << "hashsize" << hashSize << "repository-version" << itemRepositoryVersion << " current: version" << m_repositoryVersion << "hashsize" << bucketHashSize << "repository-version" << staticItemRepositoryVersion(); delete m_file; m_file = nullptr; delete m_dynamicFile; m_dynamicFile = nullptr; return false; } m_metaDataChanged = false; uint bucketCount = 0; m_file->read((char*)&bucketCount, sizeof(uint)); m_buckets.resize(bucketCount); m_file->read((char*)&m_currentBucket, sizeof(uint)); m_file->read((char*)m_firstBucketForHash, sizeof(short unsigned int) * bucketHashSize); Q_ASSERT(m_file->pos() == BucketStartOffset); uint freeSpaceBucketsSize = 0; m_dynamicFile->read((char*)&freeSpaceBucketsSize, sizeof(uint)); m_freeSpaceBuckets.resize(freeSpaceBucketsSize); m_dynamicFile->read((char*)m_freeSpaceBuckets.data(), sizeof(uint) * freeSpaceBucketsSize); } m_fileMapSize = 0; m_fileMap = nullptr; #ifdef ITEMREPOSITORY_USE_MMAP_LOADING if(m_file->size() > BucketStartOffset){ m_fileMap = m_file->map(BucketStartOffset, m_file->size() - BucketStartOffset); Q_ASSERT(m_file->isOpen()); Q_ASSERT(m_file->size() >= BucketStartOffset); if(m_fileMap){ m_fileMapSize = m_file->size() - BucketStartOffset; }else{ qWarning() << "mapping" << m_file->fileName() << "FAILED!"; } } #endif //To protect us from inconsistency due to crashes. flush() is not enough. m_file->close(); m_dynamicFile->close(); return true; } ///@warning by default, this does not store the current state to disk. - virtual void close(bool doStore = false) override { + void close(bool doStore = false) override { if(doStore) store(); if(m_file) m_file->close(); delete m_file; m_file = nullptr; m_fileMap = nullptr; m_fileMapSize = 0; if(m_dynamicFile) m_dynamicFile->close(); delete m_dynamicFile; m_dynamicFile = nullptr; qDeleteAll(m_buckets); m_buckets.clear(); memset(m_firstBucketForHash, 0, bucketHashSize * sizeof(short unsigned int)); } struct AllItemsReachableVisitor { AllItemsReachableVisitor(ItemRepository* rep) : repository(rep) { } bool operator()(const Item* item) { return repository->itemReachable(item); } ItemRepository* repository; }; //Returns whether the given item is reachable through its hash bool itemReachable(const Item* item) const { const uint hash = item->hash(); return walkBucketChain(hash, [=](ushort /*bucketIndex*/, const MyBucket* bucketPtr) { return bucketPtr->itemReachable(item, hash); }); } //Returns true if all items in the given bucket are reachable through their hashes bool allItemsReachable(unsigned short bucket) { if(!bucket) return true; MyBucket* bucketPtr = bucketForIndex(bucket); AllItemsReachableVisitor visitor(this); return bucketPtr->visitAllItems(visitor); } - virtual int finalCleanup() override { + int finalCleanup() override { ThisLocker lock(m_mutex); int changed = 0; for(int a = 1; a <= m_currentBucket; ++a) { MyBucket* bucket = bucketForIndex(a); if(bucket && bucket->dirty()) { ///@todo Faster dirty check, without loading bucket changed += bucket->finalCleanup(*this); } a += bucket->monsterBucketExtent(); //Skip buckets that are attached as tail to monster-buckets } return changed; } inline void initializeBucket(int bucketNumber) const { Q_ASSERT(bucketNumber); #ifdef DEBUG_MONSTERBUCKETS for(uint offset = 1; offset < 5; ++offset) { int test = bucketNumber - offset; if(test >= 0 && m_buckets[test]) { Q_ASSERT(m_buckets[test]->monsterBucketExtent() < offset); } } #endif if(!m_buckets[bucketNumber]) { m_buckets[bucketNumber] = new MyBucket(); bool doMMapLoading = (bool)m_fileMap; uint offset = ((bucketNumber-1) * MyBucket::DataSize); if(m_file && offset < m_fileMapSize && doMMapLoading && *reinterpret_cast(m_fileMap + offset) == 0) { // qDebug() << "loading bucket mmap:" << bucketNumber; m_buckets[bucketNumber]->initializeFromMap(reinterpret_cast(m_fileMap + offset)); } else if(m_file) { //Either memory-mapping is disabled, or the item is not in the existing memory-map, //so we have to load it the classical way. bool res = m_file->open( QFile::ReadOnly ); if(offset + BucketStartOffset < m_file->size()) { VERIFY(res); offset += BucketStartOffset; m_file->seek(offset); uint monsterBucketExtent; m_file->read((char*)(&monsterBucketExtent), sizeof(unsigned int));; m_file->seek(offset); ///FIXME: use the data here instead of copying it again in prepareChange QByteArray data = m_file->read((1+monsterBucketExtent) * MyBucket::DataSize); m_buckets[bucketNumber]->initializeFromMap(data.data()); m_buckets[bucketNumber]->prepareChange(); }else{ m_buckets[bucketNumber]->initialize(0); } m_file->close(); }else{ m_buckets[bucketNumber]->initialize(0); } }else{ m_buckets[bucketNumber]->initialize(0); } } ///Can only be called on empty buckets void deleteBucket(int bucketNumber) { Q_ASSERT(bucketForIndex(bucketNumber)->isEmpty()); Q_ASSERT(bucketForIndex(bucketNumber)->noNextBuckets()); delete m_buckets[bucketNumber]; m_buckets[bucketNumber] = nullptr; } //m_file must be opened void storeBucket(int bucketNumber) const { if(m_file && m_buckets[bucketNumber]) { m_buckets[bucketNumber]->store(m_file, BucketStartOffset + (bucketNumber-1) * MyBucket::DataSize); } } ///Returns whether @param mustFindBucket was found ///If mustFindBucket is zero, the whole chain is just walked. This is good for debugging for infinite recursion. bool walkBucketLinks(uint checkBucket, uint hash, uint mustFindBucket = 0) const { bool found = false; while(checkBucket) { if(checkBucket == mustFindBucket) found = true; checkBucket = bucketForIndex(checkBucket)->nextBucketForHash(hash); } return found || (mustFindBucket == 0); } ///Computes the bucket where the chains opened by the buckets @param mainHead and @param intersectorHead ///with hash @param hash meet each other. ///@return QPair hashChainIntersection(uint mainHead, uint intersectorHead, uint hash) const { uint previous = 0; uint current = mainHead; while(current) { ///@todo Make this more efficient if(walkBucketLinks(intersectorHead, hash, current)) return qMakePair(previous, current); previous = current; current = bucketForIndex(current)->nextBucketForHash(hash); } return qMakePair(0u, 0u); } void putIntoFreeList(unsigned short bucket, MyBucket* bucketPtr) { Q_ASSERT(!bucketPtr->monsterBucketExtent()); int indexInFree = m_freeSpaceBuckets.indexOf(bucket); if(indexInFree == -1 && (bucketPtr->freeItemCount() >= MyBucket::MinFreeItemsForReuse || bucketPtr->largestFreeSize() >= MyBucket::MinFreeSizeForReuse)) { //Add the bucket to the list of buckets from where to re-assign free space //We only do it when a specific threshold of empty items is reached, because that way items can stay "somewhat" semantically ordered. Q_ASSERT(bucketPtr->largestFreeSize()); int insertPos; for(insertPos = 0; insertPos < m_freeSpaceBuckets.size(); ++insertPos) { if(bucketForIndex(m_freeSpaceBuckets[insertPos])->largestFreeSize() > bucketPtr->largestFreeSize()) break; } m_freeSpaceBuckets.insert(insertPos, bucket); updateFreeSpaceOrder(insertPos); }else if(indexInFree != -1) { ///Re-order so the order in m_freeSpaceBuckets is correct(sorted by largest free item size) updateFreeSpaceOrder(indexInFree); } #ifdef DEBUG_MONSTERBUCKETS if(bucketPtr->isEmpty()) { Q_ASSERT(m_freeSpaceBuckets.contains(bucket)); } #endif } void verifyIndex(uint index) const { // We don't use zero indices Q_ASSERT(index); int bucket = (index >> 16); // nor zero buckets Q_ASSERT(bucket); Q_ASSERT_X(bucket < m_buckets.size(), Q_FUNC_INFO, qPrintable(QStringLiteral("index %1 gives invalid bucket number %2, current count is: %3") .arg(index) .arg(bucket) .arg(m_buckets.size()))); // don't trigger compile warnings in release mode Q_UNUSED(bucket); Q_UNUSED(index); } bool m_metaDataChanged; mutable QMutex m_ownMutex; mutable QMutex* m_mutex; QString m_repositoryName; mutable int m_currentBucket; //List of buckets that have free space available that can be assigned. Sorted by size: Smallest space first. Second order sorting: Bucket index QVector m_freeSpaceBuckets; mutable QVector m_buckets; uint m_statBucketHashClashes, m_statItemCount; //Maps hash-values modulo 1< * * Copyright 2007 Kris Wong * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef KDEVPLATFORM_CORE_H #define KDEVPLATFORM_CORE_H #include "shellexport.h" #include class KAboutData; namespace KDevelop { class UiController; class PluginController; class ProjectController; class LanguageController; class PartController; class DocumentController; class RunController; class SessionController; class CorePrivate; class SourceFormatterController; class ProgressManager; class SelectionController; class DocumentationController; class DebugController; class WorkingSetController; class TestController; class KDEVPLATFORMSHELL_EXPORT Core: public ICore { Q_OBJECT public: enum Setup { Default=0, NoUi=1 }; static QString version(); /** Initialize the core of the kdevplatform application * returns false if the initialization fails, which may happen * if the same session is already active in another instance * * @param splash the splashscreen instance that shows the startup progress (may be 0) * @param mode the mode in which to run * @param session the name or uuid of the session to be loaded * */ static bool initialize(QObject* splash = nullptr, Setup mode=Default, const QString& session = {} ); /** * \brief Provide access an instance of Core */ static Core *self(); virtual ~Core(); - virtual IUiController *uiController() override; - virtual IPluginController *pluginController() override; - virtual IProjectController *projectController() override; - virtual ILanguageController *languageController() override; - virtual IPartController *partController() override; - virtual IDocumentController *documentController() override; - virtual IRunController *runController() override; - virtual ISourceFormatterController* sourceFormatterController() override; - virtual ISelectionController* selectionController() override; - virtual IDocumentationController* documentationController() override; - virtual IDebugController* debugController() override; - virtual ITestController* testController() override; - virtual ISession *activeSession() override; - virtual ISessionLock::Ptr activeSessionLock() override; - - virtual KAboutData aboutData() const override; + IUiController *uiController() override; + IPluginController *pluginController() override; + IProjectController *projectController() override; + ILanguageController *languageController() override; + IPartController *partController() override; + IDocumentController *documentController() override; + IRunController *runController() override; + ISourceFormatterController* sourceFormatterController() override; + ISelectionController* selectionController() override; + IDocumentationController* documentationController() override; + IDebugController* debugController() override; + ITestController* testController() override; + ISession *activeSession() override; + ISessionLock::Ptr activeSessionLock() override; + + KAboutData aboutData() const override; /// The following methods may only be used within the shell. UiController *uiControllerInternal(); PluginController *pluginControllerInternal(); ProjectController *projectControllerInternal(); LanguageController *languageControllerInternal(); PartController *partControllerInternal(); DocumentController *documentControllerInternal(); RunController *runControllerInternal(); DocumentationController *documentationControllerInternal(); DebugController *debugControllerInternal(); WorkingSetController* workingSetControllerInternal(); SourceFormatterController* sourceFormatterControllerInternal(); TestController* testControllerInternal(); /// @internal SessionController *sessionController(); /// @internal ProgressManager *progressController(); void cleanup(); - virtual bool shuttingDown() const override; + bool shuttingDown() const override; Core::Setup setupFlags() const; public slots: void shutdown(); signals: void startupProgress(int percent); protected: friend class CorePrivate; Core( KDevelop::CorePrivate* dd, QObject* parent = nullptr ); KDevelop::CorePrivate *d; static Core *m_self; private: Core(QObject *parent = nullptr); }; } #endif diff --git a/shell/problem.h b/shell/problem.h index 4f20d3b05..61c4c0a68 100644 --- a/shell/problem.h +++ b/shell/problem.h @@ -1,98 +1,98 @@ /* * Copyright 2015 Laszlo Kis-Adam * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef PROBLEM_H #define PROBLEM_H #include #include #include #include #include struct DetectedProblemPrivate; namespace KDevelop { /** * @brief Represents a problem as one unit with the IProblem interface so can be used with anything that can handle IProblem. * * You should have it wrapped in an IProblem::Ptr which is a shared pointer for it. * It is basically a mirror of DUChain's Problem class. * However that class is strongly coupled with DUChain's internals due to DUChain's needs (special serialization). * * Usage example: * @code * IProblem::Ptr problem(new DetectedProblem()); * problem->setSource(IProblem::Plugin); * problem->setSeverity(IProblem::Error); * problem->setDescription(QStringLiteral("Error message")); * problem->setExplanation(QStringLiteral("Error explanation")); * * DocumentRange range; * range.document = IndexedString("/path/to/source/file"); * range.setBothLines(1337); * range.setBothColumns(12); * problem->setFinalLocation(range); * @endcode * */ class KDEVPLATFORMSHELL_EXPORT DetectedProblem : public IProblem { public: DetectedProblem(); virtual ~DetectedProblem(); Source source() const override; void setSource(Source source) override; QString sourceString() const override; DocumentRange finalLocation() const override; void setFinalLocation(const DocumentRange& location) override; FinalLocationMode finalLocationMode() const override; void setFinalLocationMode(FinalLocationMode mode) override; QString description() const override; void setDescription(const QString& description) override; QString explanation() const override; void setExplanation(const QString& explanation) override; Severity severity() const override; void setSeverity(Severity severity) override; QString severityString() const override; QVector diagnostics() const override; void setDiagnostics(const QVector &diagnostics) override; void addDiagnostic(const Ptr &diagnostic) override; void clearDiagnostics() override; - virtual QExplicitlySharedDataPointer solutionAssistant() const override; + QExplicitlySharedDataPointer solutionAssistant() const override; private: QScopedPointer d; }; } #endif diff --git a/shell/sessionlock.h b/shell/sessionlock.h index 35fc89d01..c42374df7 100644 --- a/shell/sessionlock.h +++ b/shell/sessionlock.h @@ -1,68 +1,68 @@ /* * This file is part of KDevelop * Copyright 2013 Milian Wolff * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #ifndef SESSIONLOCK_H #define SESSIONLOCK_H #include #include namespace KDevelop { struct SessionRunInfo; struct TryLockSessionResult; class SessionLock : public ISessionLock { public: /** * \copydoc SessionController::tryLockSession * * @param doLocking whether to actually try to lock or whether to only get * information about whether the session could be locked */ static TryLockSessionResult tryLockSession(const QString& sessionId, bool doLocking); /** * \copydoc SessionController::handleLockedSession */ static QString handleLockedSession( const QString& sessionName, const QString& sessionId, const SessionRunInfo& runInfo ); - virtual QString id() override; + QString id() override; virtual ~SessionLock(); /** * Release the lock file and remove the session directory from disk. */ void removeFromDisk(); private: SessionLock(const QString& sessionId, const QSharedPointer& lockFile); QString m_sessionId; QSharedPointer m_lockFile; }; } #endif // SESSIONLOCK_H diff --git a/tests/autotestshell.h b/tests/autotestshell.h index c626453a2..7c2d106f0 100644 --- a/tests/autotestshell.h +++ b/tests/autotestshell.h @@ -1,81 +1,81 @@ /*************************************************************************** * Copyright 2008 Harald Fernengel * * Copyright 2013 Milian Wolff * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef KDEVPLATFORM_AUTOTESTSHELL_H #define KDEVPLATFORM_AUTOTESTSHELL_H #include #include "testsexport.h" #include #include /* This is a dummy shell for unit tests. It basically does nothing :) You can initialize it in initTestCase() to get a minimal shell to run your autotests. Example of a minimal KDevPlatform unit test: void Mytest::initTestCase() { AutoTestShell::init(); TestCore::initialize(); } */ namespace KDevelop { class KDEVPLATFORMTESTS_EXPORT AutoTestShell : public KDevelop::ShellExtension { public: AutoTestShell(const QStringList& plugins); QString xmlFile() override { return QString(); } - virtual QString binaryPath() override { return QString(); }; + QString binaryPath() override { return QString(); }; QString defaultProfile() { return QStringLiteral("kdevtest"); } KDevelop::AreaParams defaultArea() override { KDevelop::AreaParams params; params.name = QStringLiteral("test"); params.title = QStringLiteral("Test"); return params; } QString projectFileExtension() override { return QString(); } QString projectFileDescription() override { return QString(); } QStringList defaultPlugins() override { return m_plugins; } /** * Initialize the AutoTestShell and set the global instance. * * @p plugins A list of default global plugins which should be loaded. * By default, all global plugins are loaded. */ static void init(const QStringList& plugins = QStringList()); private: QStringList m_plugins; }; } #endif diff --git a/tests/json/declarationvalidator.h b/tests/json/declarationvalidator.h index ce9c079f1..778c9ca93 100644 --- a/tests/json/declarationvalidator.h +++ b/tests/json/declarationvalidator.h @@ -1,44 +1,44 @@ /* This file is part of KDevelop Copyright 2012 Olivier de Gaalon This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_DECLARATIONVALIDATOR_H #define KDEVPLATFORM_DECLARATIONVALIDATOR_H #include #include "language/duchain/ducontext.h" namespace KDevelop { class DeclarationValidatorPrivate; class KDEVPLATFORMTESTS_EXPORT DeclarationValidator : public DUChainVisitor { public: DeclarationValidator(); virtual ~DeclarationValidator(); virtual bool testsPassed(); - virtual void visit(DUContext*) override; - virtual void visit(Declaration *declaration) override; + void visit(DUContext*) override; + void visit(Declaration *declaration) override; private: Q_DISABLE_COPY(DeclarationValidator) const QScopedPointer d; }; } #endif //KDEVPLATFORM_DECLARATIONVALIDATOR_H \ No newline at end of file