1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
|
/*
SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org>
SPDX-FileCopyrightText: 2007-2009 David Nolden <david.nolden.kdevelop@art-master.de>
SPDX-License-Identifier: LGPL-2.0-only
*/
#ifndef KDEVPLATFORM_TOPDUCONTEXT_H
#define KDEVPLATFORM_TOPDUCONTEXT_H
#include "ducontext.h"
#include <language/util/setrepository.h>
#include <QMetaType>
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.
using RecursiveImports = QHash<const TopDUContext*, QPair<int, const TopDUContext*>>;
using TopDUContextPointer = DUChainPointer<TopDUContext>;
using ProblemPointer = QExplicitlySharedDataPointer<Problem>;
///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& operator=(const TopDUContext& rhs) = delete;
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> 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
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<ProblemPointer> 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<ProblemPointer>& 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.
*/
bool imports(const DUContext* origin, const CursorInRevision& position) const override;
enum {
Identity = 4
};
enum Feature : 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
};
Q_DECLARE_FLAGS(Features, Feature)
///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<int>::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.
*/
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<IAstContainer> ast() const;
/**
* Sets the AST Container.
*/
void setAst(const QExplicitlySharedDataPointer<IAstContainer>& 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.
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 QVector<QPair<TopDUContext*, CursorInRevision>>& 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.
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<TopDUContext*>& 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.
void clearImportedParentContexts() override;
using IndexedRecursiveImports = Utils::StorableSet<IndexedTopDUContext, IndexedTopDUContextIndexConversion, RecursiveImportRepository,
true>;
QVector<Import> importedParentContexts() const override;
QVector<DUContext*> importers() const override;
///Returns all currently loade importers
virtual QList<DUContext*> loadedImporters() const;
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;
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 <class Acceptor>
void applyAliases(const SearchItem::PtrList& identifiers, Acceptor& accept, const CursorInRevision& position,
bool canBeNamespace) const;
protected:
~TopDUContext() override;
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 <class Acceptor>
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 QVector<RangeInRevision> allUses(TopDUContext* context, Declaration* declaration,
bool noEmptyRanges = false);
inline uint qHash(const ReferencedTopDUContext& ctx)
{
return ctx.hash();
}
Q_DECLARE_OPERATORS_FOR_FLAGS(TopDUContext::Features)
}
Q_DECLARE_TYPEINFO(KDevelop::ReferencedTopDUContext, Q_MOVABLE_TYPE);
Q_DECLARE_METATYPE(KDevelop::ReferencedTopDUContext)
#endif // KDEVPLATFORM_TOPDUCONTEXT_H
|