kde-extraapps/kdevplatform/language/duchain/declaration.h
2015-07-26 14:23:17 +03:00

586 lines
20 KiB
C++

/* This file is part of KDevelop
Copyright 2006 Hamish Rodda <rodda@kde.org>
Copyright 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de>
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 <QtCore/QList>
#include <QtCore/QMap>
#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 ForwardDeclaration;
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 {
Public /**< a public declaration */,
Protected /**< a protected declaration */,
Private /**< a private declaration */,
DefaultAccess /**<a declaration with default access; in java, only package-level access. */
};
/// Enumeration of the types of declarations
enum Kind {
Type /**< A type is declared, like a class-declaration or function-declaration, or a typedef("class MyClass {};") */,
Instance /**< An instance of a type is declared("MyClass m;") */,
NamespaceAlias/**< This is a namespace-alias. You can safely cast this object to NamespaceAliasDeclaration. */,
Alias, /**<This is an alias-declaration. You can safely cast this object to AliasDeclaration. */
Namespace, /**< Declaration of a namespace. */
Import /**< Declaration marks the Import of a file. */
};
/**
* Constructor.
*
* If \a parentContext is in the symbol table, the declaration will automatically
* be added into the symbol table.
*
* \param url url of the document where this occurred
* \param range range of the alias declaration's identifier
* \param parentContext context in which this declaration occurred
* */
Declaration(const RangeInRevision& range, DUContext* parentContext);
///Copy-constructor for cloning
Declaration(const Declaration& rhs);
/// Destructor
virtual ~Declaration();
/// Uses the given data
Declaration( DeclarationData & dd );
virtual TopDUContext* topContext() const;
/**
* Determine whether this declaration is a forward declaration.
*
* \returns true if this is a forward declaration, otherwise returns false.
*/
virtual bool isForwardDeclaration() const;
/**
* \returns this declaration as a forward declaration if it is one, otherwise null.
*/
ForwardDeclaration* toForwardDeclaration();
/**
* \returns this declaration as a forward declaration, if it is one, otherwise null.
*/
const ForwardDeclaration* toForwardDeclaration() const;
/**
* Determine whether this declaration is a function declaration.
*
* \returns true if this is a function declaration, otherwise returns false.
*/
virtual bool isFunctionDeclaration() const;
/**
* Determine whether this declaration is accessible through the du-chain.
* If it is, it cannot be edited without holding the du-chain write lock.
*
* \sa DUChain::lock()
* \sa DUChainWriteLocker
*
* \returns true if the Declaration is already inserted into a duchain.
*/
virtual bool inDUChain() const;
/**
* Determine whether this declaration is also a definition.
*
* \returns true if this declaration is also a definition, otherwise false.
*/
bool isDefinition() const;
/**
* Set whether this declaration is also a definition.
*
* \param dd set this to true if this declaration is also a definition, otherwise false.
*/
void setDeclarationIsDefinition(bool dd);
/**
* Determine if this declaration is a type-alias (in c++ typedef).
*
* \returns true if the declaration is a type alias, otherwise false.
*/
bool isTypeAlias() const;
/**
* Set whether this declaration is a type alias.
*
* \param typeAlias true if the declaration is a type alias, otherwise false.
*/
void setIsTypeAlias(bool typeAlias);
/**
* Determine whether the declaration is deprecated.
*/
bool isDeprecated() const;
/**
* Set whether the declaration is deprecated.
*
* \param final true if the declaration is deprecated, otherwise false.
*/
void setDeprecated(bool deprecated);
/**
* Changes whether this declaration must be direct in all cases or not.
*
* By default this is set to false.
*
* \param direct true to force direct, false otherwise.
*/
void setAlwaysForceDirect(bool direct);
/**
* Determine whether this declaration must always be direct.
*/
bool alwaysForceDirect() const;
/**
* Changes whether this declaration is "implicitly created".
*
* An implicit declaration is not declared in the class context,
* but written somewhere else outside.
*
* Declarations are by default not implicitly declared.
*
* \param _auto true for implicit, false for default behaviour
*/
void setAutoDeclaration(bool _auto);
/**
* Determine whether this declaration is implicitly created or not.
*/
bool isAutoDeclaration() const;
/**
* Changes whether this declaration is "explicitly deleted", i.e. not implicitly declared or accessible.
*
* \param deleted true for deleted, false for default behaviour
* */
void setExplicitlyDeleted(bool deleted);
/**
* Determine whether this declaration is "explicitly deleted" or not.
*/
bool isExplicitlyDeleted() const;
/**
* Retrieve the declaration which is specialized with the given
* \a specialization index as seen from \a topContext.
*
* \param specialization the specialization index (see DeclarationId)
* \param topContext the top context representing the perspective from which to specialize.
* if @p topContext is zero, only already existing specializations are returned,
* and if none exists, zero is returned.
* \param upDistance upwards distance in the context-structure of the
* given specialization-info. This allows specializing children.
*/
virtual Declaration* specialize(const IndexedInstantiationInformation& specialization,
const TopDUContext* topContext, int upDistance = 0);
/**
* Retrieve the context that is opened by this declaration, if one exists.
*
* For example, a class will have a declaration which is contained within the context in which
* it is declared, and a new context will be created to hold class members. This function returns
* that context.
* The declaration has to be part of the same top-context.
*
* \returns the internal context for this declaration
*/
DUContext * internalContext() const;
/**
* Set the internal \a context for this declaration.
*
* \param context the internal context
*/
void setInternalContext(DUContext* context);
/**
* Determine the logical internal context for the resolved form of this declaration.
*
* \li If this declaration has a definition, and the definition is resolved,
* it returns the internal context of the definition.
* \li If this declaration is a forward-declaration, the forward-declaration is
* resolved, it returns the internal context of the resolved declaration.
* \li If this is a type-alias, it returns the internal context of the actual type.
* \li Otherwise, it returns the same as internalContext().
*
* \param topContext Needed to resolve forward-declarations.
* \returns the resolved internal context, as described above
*/
virtual DUContext * logicalInternalContext(const TopDUContext* topContext) const;
/**
* This is a convenience function to determine the resolved declaration, if this is a forward declaration.
* Otherwise, it just returns this declaration.
* \param topContext Context within which to search for the resolved declaration.
* \returns the resolved declaration if one was found, otherwise this declaration.
* */
const Declaration* logicalDeclaration(const TopDUContext* topContext) const;
/// \copydoc
Declaration* logicalDeclaration(const TopDUContext* topContext);
/**
* Access the parent context of this declaration.
* \returns the parent context of this declaration.
*/
DUContext* context() const;
/**
* Set the context in which this declaration occurs.
*
* When setContext() is called, this declaration is inserted into the given context.
* You only need to be able to write this declaration. You do not need write-privileges
* for the context, because addDeclaration(..) works separately to that.
*
* If the given context is not in the symbol-table, or if the declaration is inserted anonymously,
* or if the context is zero, this declaration is removed from the symbol-table.
* Else it is added to the symbol table with the new scope. See TopDUContext for information
* about the symbol table.
*
* \param context New context which contains this declaration. The context must have a
* top-context if it is not zero.
* \param anonymous If this is set, this declaration will be added anonymously into the parent-context.
* This way it can never be found through any of the context's functions, and will
* not be deleted when the context is deleted, so it must be deleted from elsewhere.
*/
void setContext(DUContext* context, bool anonymous = false);
/**
* Convenience function to return this declaration's type dynamically casted to \a T.
*
* \returns this declaration's type as \a T, or null if there is no type or it is not of type \a T.
*/
template <class T>
TypePtr<T> type() const { return TypePtr<T>::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 <class T>
void setType(TypePtr<T> 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<IndexedString, QList<RangeInRevision> > 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<IndexedString, QList<SimpleRange> > 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 url document url in which this object is located.
* \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);
friend class DUContext;
friend class IndexedDeclaration;
friend class LocalIndexedDeclaration;
friend class TopDUContextDynamicData;
DUContext* m_context;
TopDUContext* m_topContext;
int m_indexInTopContext;
};
inline uint qHash(const IndexedDeclaration& decl) {
return decl.hash();
}
}
#endif // KDEVPLATFORM_DECLARATION_H
// kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on