File indexing completed on 2024-05-12 04:38:05
0001 /* 0002 SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org> 0003 SPDX-FileCopyrightText: 2007-2009 David Nolden <david.nolden.kdevelop@art-master.de> 0004 0005 SPDX-License-Identifier: LGPL-2.0-only 0006 */ 0007 0008 #ifndef KDEVPLATFORM_TOPDUCONTEXT_H 0009 #define KDEVPLATFORM_TOPDUCONTEXT_H 0010 0011 #include "ducontext.h" 0012 #include <language/util/setrepository.h> 0013 #include <QMetaType> 0014 0015 template <class T> 0016 class QExplicitlySharedDataPointer; 0017 0018 namespace KDevelop { 0019 class IAstContainer; 0020 class QualifiedIdentifier; 0021 class DUChain; 0022 class ParsingEnvironmentFile; 0023 class TopDUContextData; 0024 class TopDUContextLocalPrivate; 0025 class IndexedTopDUContext; 0026 // class TopDUContextDynamicData; 0027 class Problem; 0028 class DeclarationChecker; 0029 class TopDUContext; 0030 0031 struct KDEVPLATFORMLANGUAGE_EXPORT RecursiveImportRepository 0032 { 0033 static Utils::BasicSetRepository* repository(); 0034 }; 0035 0036 ///Maps an imported top-context to a pair: 0037 ///1. The distance to the top-context, and 2. The next step towards the top-context 0038 ///in the chain. 0039 using RecursiveImports = QHash<const TopDUContext*, QPair<int, const TopDUContext*>>; 0040 0041 using TopDUContextPointer = DUChainPointer<TopDUContext>; 0042 0043 using ProblemPointer = QExplicitlySharedDataPointer<Problem>; 0044 0045 ///KDevelop can unload unused top-context at any time. To prevent unloading, 0046 ///keep a ReferencedTopDUContext. 0047 class KDEVPLATFORMLANGUAGE_EXPORT ReferencedTopDUContext 0048 { 0049 public: 0050 ReferencedTopDUContext(TopDUContext* context = nullptr); 0051 ReferencedTopDUContext(const ReferencedTopDUContext& rhs); 0052 ~ReferencedTopDUContext(); 0053 0054 ReferencedTopDUContext& operator=(const ReferencedTopDUContext& rhs); 0055 0056 inline TopDUContext* data() const 0057 { 0058 return m_topContext; 0059 } 0060 0061 inline operator TopDUContext*() const { 0062 return m_topContext; 0063 } 0064 0065 inline bool operator==(const ReferencedTopDUContext& rhs) const 0066 { 0067 return m_topContext == rhs.m_topContext; 0068 } 0069 0070 inline bool operator!=(const ReferencedTopDUContext& rhs) const 0071 { 0072 return m_topContext != rhs.m_topContext; 0073 } 0074 0075 inline TopDUContext* operator->() const 0076 { 0077 return m_topContext; 0078 } 0079 0080 inline uint hash() const 0081 { 0082 return ( uint )((( quint64 )m_topContext) * 37); 0083 } 0084 0085 private: 0086 TopDUContext* m_topContext; 0087 }; 0088 0089 /** 0090 * The top context in a definition-use chain for one source file. 0091 * 0092 * Implements SymbolTable lookups and locking for the chain. 0093 * 0094 * Contexts and Classes can only be found through TopDUContext if they are in the symbol table. 0095 * @see DUContext::setInSymbolTable, Declaration::setInSymbolTable 0096 * 0097 * \todo move the registration with DUChain here 0098 * 0099 * @warning Do not delete top-contexts directly, use DUChain::removeDocumentChain instead. 0100 */ 0101 class KDEVPLATFORMLANGUAGE_EXPORT TopDUContext 0102 : public DUContext 0103 { 0104 public: 0105 explicit TopDUContext(const IndexedString& url, const RangeInRevision& range, 0106 ParsingEnvironmentFile* file = nullptr); 0107 explicit TopDUContext(TopDUContextData& data); 0108 0109 TopDUContext& operator=(const TopDUContext& rhs) = delete; 0110 0111 TopDUContext* topContext() const override; 0112 0113 ///Returns an indexed representation of this top-context. Indexed representations stay valid even if the top-context is unloaded. 0114 IndexedTopDUContext indexed() const; 0115 0116 uint ownIndex() const; 0117 0118 IndexedString url() const override; 0119 0120 /** 0121 * @see ParsingEnvironmentFile 0122 * May return zero if no file was set. 0123 * */ 0124 QExplicitlySharedDataPointer<ParsingEnvironmentFile> parsingEnvironmentFile() const; 0125 0126 /// Returns true if this object is being deleted, otherwise false. 0127 bool deleting() const; 0128 0129 /// Returns true if this object is registered in the du-chain. If it is not, all sub-objects(context, declarations, etc.) can be changed 0130 bool inDUChain() const override; 0131 /// This flag is only used by DUChain, never change it from outside. 0132 void setInDuChain(bool); 0133 0134 /// Whether this top-context has a stored version on disk 0135 bool isOnDisk() const; 0136 0137 /** 0138 * Returns a list of all problems encountered while parsing this top-context. 0139 * Does not include the problems of imported contexts. 0140 * */ 0141 QList<ProblemPointer> problems() const; 0142 0143 /** 0144 * Add a parsing-problem to this context. 0145 * 0146 * \note you must be holding a write lock when you access this function. 0147 * */ 0148 void addProblem(const ProblemPointer& problem); 0149 0150 /** 0151 * Clear the list of problems 0152 * 0153 * \note you must be holding a write lock when you access this function. 0154 */ 0155 void clearProblems(); 0156 0157 /** 0158 * Set the list of problems, replacing all existing ones. 0159 * 0160 * \note you must be holding a write lock when you access this function. 0161 */ 0162 void setProblems(const QList<ProblemPointer>& pointers); 0163 0164 /** 0165 * Determine if this chain imports another chain recursively. 0166 * 0167 * This uses the imports-cache for speedup if it is available, thus it is not necessarily 100% correct 0168 * if the cache is not up-to-date. 0169 * 0170 * \note you must be holding a read but not a write chain lock when you access this function. 0171 */ 0172 bool imports(const DUContext* origin, const CursorInRevision& position) const override; 0173 0174 enum { 0175 Identity = 4 0176 }; 0177 0178 enum Feature : quint16 { 0179 ///Top-context features standard that can be requested from the duchain, and that are stored in the features() member. 0180 Empty = 0, //Only the top-context structure (imports etc.) is built, but no declarations and no contexts 0181 SimplifiedVisibleDeclarationsAndContexts = 2, //The top-context should only contain publicly simplified accessible declarations and contexts, without doing type look-up, 0182 //without extended information like function-argument declarations, etc., imported contexts can be parsed with 'Empty' features 0183 //This flag essentially leads to a ctags-like processing level. 0184 VisibleDeclarationsAndContexts = SimplifiedVisibleDeclarationsAndContexts + 4, //Default: The top-context should only contain publicly accessible declarations and contexts 0185 AllDeclarationsAndContexts = VisibleDeclarationsAndContexts + 8, //The top-context should also contain non-public declarations and contexts, but no uses 0186 AllDeclarationsContextsAndUses = 16 + AllDeclarationsAndContexts, //The top-context should contain uses and all declarations + contexts 0187 AST = 32, //Signalizes that the ast() should be filled 0188 AllDeclarationsContextsUsesAndAST = AST | AllDeclarationsContextsAndUses, //Convenience flag, combining AST and AllDeclarationsContextsAndUses 0189 0190 ///Additional update-flags that have a special meaning during updating, but are not set stored into a top-context 0191 Recursive = 64, //Request the given features on all recursively imported contexts. Only the features are applied recursively (including AST) 0192 ForceUpdate = 128, //Enforce updating the top-context 0193 ForceUpdateRecursive = ForceUpdate | 256, //Enforce updating the top-context and all its imports 0194 0195 ///You can define own language-dependent features behind this flag 0196 LastFeature = 512 0197 }; 0198 Q_DECLARE_FLAGS(Features, Feature) 0199 0200 ///Returns the currently active features of this top-context. The features will include AST if ast() is valid. 0201 Features features() const; 0202 ///Set the features of this top-context. These features are ignored: AST, ForceUpdate, and ForceUpdateRecursive. 0203 void setFeatures(Features); 0204 0205 /** 0206 * Retrieves or creates a local index that is to be used for referencing the given @param declaration 0207 * in local uses. Also registers this context as a user of the declaration. 0208 * @param create If this is false, only already registered indices will be returned. 0209 * If the declaration is not registered, std::numeric_limits<int>::max() is returned 0210 * 0211 * The duchain must be write-locked if create is true, else it must at least be read-locked. 0212 * */ 0213 int indexForUsedDeclaration(Declaration* declaration, bool create = true); 0214 0215 /** 0216 * Tries to retrieve the used declaration 0217 * @param declarationIndex The index of the declaration which have to be retrieved 0218 * */ 0219 Declaration* usedDeclarationForIndex(unsigned int declarationIndex) const; 0220 0221 /** 0222 * You can use this before you rebuild all uses. This does not affect any uses directly, 0223 * it only invalidates the mapping of declarationIndices to Declarations. 0224 * 0225 * usedDeclarationForIndex(..) must not be called until the use has gotten a new index through 0226 * indexForUsedDeclaration(..). 0227 * */ 0228 void clearUsedDeclarationIndices(); 0229 0230 /** 0231 * Recursively deletes all contained uses, declaration-indices, etc. 0232 */ 0233 void deleteUsesRecursively() override; 0234 0235 /** 0236 * Returns the AST Container, that contains the AST created during parsing. 0237 * This is only created if you request the AST feature for parsing. 0238 * It may be discarded at any time. Every update without the AST feature will discard it. 0239 * The actual contents is language-specific. 0240 * 0241 * @todo Figure out logic to get rid of AST when it is not needed/useful 0242 */ 0243 QExplicitlySharedDataPointer<IAstContainer> ast() const; 0244 0245 /** 0246 * Sets the AST Container. 0247 */ 0248 void setAst(const QExplicitlySharedDataPointer<IAstContainer>& ast); 0249 0250 /** 0251 * Utility function to clear the AST Container 0252 */ 0253 void clearAst(); 0254 0255 ///@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, 0256 ///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. 0257 ///When this top-context does not own its private data, the import is added locally only to this context, not into the shared data. 0258 void addImportedParentContext(DUContext* context, 0259 const CursorInRevision& position = CursorInRevision(), bool anonymous = false, 0260 bool temporary = false) override; 0261 ///Use this for mass-adding of imported contexts, it is faster than adding them individually. 0262 ///@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, 0263 ///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. 0264 ///When this top-context does not own its private data, the import is added locally only to this context, not into the shared data. 0265 virtual void addImportedParentContexts(const QVector<QPair<TopDUContext*, CursorInRevision>>& contexts, 0266 bool temporary = false); 0267 0268 ///When this top-context does not own its private data, the import is removed locally only from this context, not from the shared data. 0269 void removeImportedParentContext(DUContext* context) override; 0270 ///Use this for mass-removing of imported contexts, it is faster than removing them individually. 0271 ///When this top-context does not own its private data, the import is removed locally only from this context, not from the shared data. 0272 virtual void removeImportedParentContexts(const QList<TopDUContext*>& contexts); 0273 0274 ///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. 0275 void clearImportedParentContexts() override; 0276 0277 using IndexedRecursiveImports = Utils::StorableSet<IndexedTopDUContext, IndexedTopDUContextIndexConversion, RecursiveImportRepository, 0278 true>; 0279 0280 QVector<Import> importedParentContexts() const override; 0281 0282 QVector<DUContext*> importers() const override; 0283 0284 ///Returns all currently loade importers 0285 virtual QList<DUContext*> loadedImporters() const; 0286 0287 CursorInRevision importPosition(const DUContext* target) const override; 0288 0289 ///Returns the set of all recursively imported top-contexts. If import-caching is used, this returns the cached set. 0290 ///The list also contains this context itself. This set is used to determine declaration-visibility from within this top-context. 0291 const IndexedRecursiveImports& recursiveImportIndices() const; 0292 0293 /** 0294 * Updates the cache of recursive imports. When you call this, from that moment on the set returned by recursiveImportIndices() is fixed, until 0295 * you call it again to update them. If your language has a very complex often-changing import-structure, 0296 * like for example in the case of C++, it is recommended to call this during while parsing, instead of using 0297 * the expensive builtin implicit mechanism. 0298 * Note that if you use caching, you _must_ call this before you see any visibility-effect after adding imports. 0299 * 0300 * Using import-caching has another big advantage: A top-context can be loaded without loading all its imports. 0301 * 0302 * Note: This is relatively expensive since it requires loading all imported contexts. 0303 * 0304 * When this is called, the top-context must already be registered in the duchain. 0305 */ 0306 void updateImportsCache(); 0307 0308 bool usingImportsCache() const; 0309 0310 bool findDeclarationsInternal(const SearchItem::PtrList& identifiers, const CursorInRevision& position, 0311 const AbstractType::Ptr& dataType, DeclarationList& ret, const TopDUContext* source, 0312 SearchFlags flags, uint depth) const override; 0313 0314 protected: 0315 void setParsingEnvironmentFile(ParsingEnvironmentFile*); 0316 0317 /** 0318 * Does the same as DUContext::updateAliases, except that it uses the symbol-store, and processes the whole identifier. 0319 * @param canBeNamespace whether the searched identifier may be a namespace. 0320 * If this is true, namespace-aliasing is applied to the last elements of the identifiers. 0321 * */ 0322 template <class Acceptor> 0323 void applyAliases(const SearchItem::PtrList& identifiers, Acceptor& accept, const CursorInRevision& position, 0324 bool canBeNamespace) const; 0325 0326 protected: 0327 ~TopDUContext() override; 0328 0329 void clearFeaturesSatisfied(); 0330 void rebuildDynamicData(DUContext* parent, uint ownIndex) override; 0331 //Must be called after all imported top-contexts were loaded into the du-chain 0332 void rebuildDynamicImportStructure(); 0333 0334 struct AliasChainElement; 0335 struct FindDeclarationsAcceptor; 0336 struct DeclarationChecker; 0337 struct ApplyAliasesBuddyInfo; 0338 0339 template <class Acceptor> 0340 bool applyAliases(const QualifiedIdentifier& previous, const SearchItem::Ptr& identifier, Acceptor& acceptor, 0341 const CursorInRevision& position, bool canBeNamespace, ApplyAliasesBuddyInfo* buddy, 0342 uint recursionDepth) const; 0343 //Same as imports, without the slow access-check, for internal usage 0344 bool importsPrivate(const DUContext* origin, const CursorInRevision& position) const; 0345 DUCHAIN_DECLARE_DATA(TopDUContext) 0346 0347 ///Called by DUChain::removeDocumentChain to destroy this top-context. 0348 void deleteSelf(); 0349 0350 //Most of these classes need access to m_dynamicData 0351 friend class DUChain; 0352 friend class DUChainPrivate; 0353 friend class TopDUContextData; 0354 friend class TopDUContextLocalPrivate; 0355 friend class TopDUContextDynamicData; 0356 friend class Declaration; 0357 friend class DUContext; 0358 friend class Problem; 0359 friend class IndexedDeclaration; 0360 friend class IndexedDUContext; 0361 friend class LocalIndexedDeclaration; 0362 friend class LocalIndexedDUContext; 0363 friend class LocalIndexedProblem; 0364 friend class DeclarationId; 0365 friend class ParsingEnvironmentFile; 0366 0367 TopDUContextLocalPrivate* m_local; 0368 0369 class TopDUContextDynamicData* m_dynamicData; 0370 }; 0371 0372 /** 0373 * Returns all uses of the given declaration within this top-context and all sub-contexts 0374 * */ 0375 KDEVPLATFORMLANGUAGE_EXPORT QVector<RangeInRevision> allUses(TopDUContext* context, Declaration* declaration, 0376 bool noEmptyRanges = false); 0377 0378 inline uint qHash(const ReferencedTopDUContext& ctx) 0379 { 0380 return ctx.hash(); 0381 } 0382 0383 Q_DECLARE_OPERATORS_FOR_FLAGS(TopDUContext::Features) 0384 } 0385 0386 Q_DECLARE_TYPEINFO(KDevelop::ReferencedTopDUContext, Q_MOVABLE_TYPE); 0387 Q_DECLARE_METATYPE(KDevelop::ReferencedTopDUContext) 0388 0389 #endif // KDEVPLATFORM_TOPDUCONTEXT_H