File indexing completed on 2024-05-12 04:38:03

0001 /*
0002     SPDX-FileCopyrightText: 2007 David Nolden <david.nolden.kdevelop@art-master.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-only
0005 */
0006 
0007 #ifndef KDEVPLATFORM_PARSINGENVIRONMENT_H
0008 #define KDEVPLATFORM_PARSINGENVIRONMENT_H
0009 
0010 #include <serialization/indexedstring.h>
0011 
0012 #include <language/languageexport.h>
0013 #include "duchainbase.h"
0014 #include "topducontext.h"
0015 #include <language/editor/modificationrevisionset.h>
0016 
0017 namespace KDevelop {
0018 /**
0019  * Just an enumeration of a few parsing-environment types.
0020  * Enumerate a few possible future parsing-environment types.
0021  * A parsing-environment could also have a type not in this enumeration,
0022  * the only important thing is that it's unique for the type.
0023  *
0024  * The type is needed to match ParsingEnvironment, ParsingEnvironmentFile, and ParsingEnvironmentManager together so they fit.
0025  * For example the c++-versions would have their specific type.
0026  *
0027  * The type must be unique(no other language may have the same type),
0028  * and the type must be persistent.(it must be same after restarting kdevelop)
0029  *
0030  * */
0031 enum ParsingEnvironmentType
0032 {
0033     StandardParsingEnvironment /**< a basic standard parsing environment */,
0034     CppParsingEnvironment /**< a C++ parsing environment */,
0035     PythonParsingEnvironment /**< a python parsing environment */,
0036     CMakeParsingEnvironment /**< a CMake parsing environment */,
0037     CSharpParsingEnvironment /**< a CSharp parsing environment */,
0038     JavaParsingEnvironment /**< a JAva parsing environment */,
0039     RubyParsingEnvironment /**< a Ruby parsing environment */,
0040     PhpParsingEnvironment    /**< a PHP parsing environment */
0041 };
0042 
0043 ///Internal
0044 struct StaticParsingEnvironmentData
0045 {
0046     TopDUContext::IndexedRecursiveImports simplifiedVisibleDeclarationsSatisfied;
0047     TopDUContext::IndexedRecursiveImports visibleDeclarationsSatisfied;
0048     TopDUContext::IndexedRecursiveImports allDeclarationsSatisfied;
0049     TopDUContext::IndexedRecursiveImports allDeclarationsAndUsesSatisfied;
0050     TopDUContext::IndexedRecursiveImports ASTSatisfied;
0051 };
0052 
0053 /**
0054  * Use this as base-class to define new parsing-environments.
0055  *
0056  * Parsing-environments are needed for languages that create different
0057  * parsing-results depending on the environment. For example in c++,
0058  * the environment mainly consists of macros. The include-path can
0059  * be considered to be a part of the parsing-environment too, because
0060  * different files may be included using another include-path.
0061  *
0062  * The classes have to use the serialization scheme from the duchain.
0063  * Each class must be registered using REGISTER_DUCHAIN_ITEM with a unique id.
0064  *
0065  * \warning Access to this class must be serialized through du-chain locking
0066  * */
0067 class KDEVPLATFORMLANGUAGE_EXPORT ParsingEnvironment
0068 {
0069 public:
0070     ParsingEnvironment();
0071     virtual ~ParsingEnvironment();
0072 
0073     ///@see ParsingEnvironmentType
0074     virtual int type() const;
0075 };
0076 
0077 ///The data class used for storing. Use this as base-class of your custom data classes for classes derived from
0078 ///ParsingEnvironmentFile
0079 class KDEVPLATFORMLANGUAGE_EXPORT ParsingEnvironmentFileData
0080     : public DUChainBaseData
0081 {
0082 public:
0083     bool m_isProxyContext = false;
0084     TopDUContext::Features m_features = TopDUContext::VisibleDeclarationsAndContexts;
0085     KDevelop::ModificationRevision m_modificationTime;
0086     ModificationRevisionSet m_allModificationRevisions;
0087     KDevelop::IndexedString m_url;
0088     KDevelop::IndexedTopDUContext m_topContext;
0089     IndexedString m_language;
0090 
0091     ///If this is not empty, it means that the cache is used instead of the implicit structure.
0092     TopDUContext::IndexedRecursiveImports m_importsCache;
0093 };
0094 
0095 using ParsingEnvironmentFilePointer = QExplicitlySharedDataPointer<ParsingEnvironmentFile>;
0096 
0097 /**
0098  * This represents all information about a specific parsed file that is needed
0099  * to match the file to a parsing-environment.
0100  *
0101  * It is QSharedData because it is embedded into top-du-contexts and at the same time
0102  * references may be held by ParsingEnvironmentManager.
0103  *
0104  * \warning Access to this class must be serialized through du-chain locking
0105  * */
0106 class KDEVPLATFORMLANGUAGE_EXPORT ParsingEnvironmentFile
0107     : public DUChainBase
0108     , public QSharedData
0109 {
0110 public:
0111     ~ParsingEnvironmentFile() override;
0112     explicit ParsingEnvironmentFile(const IndexedString& url);
0113     ParsingEnvironmentFile(ParsingEnvironmentFileData& data, const IndexedString& url);
0114     explicit ParsingEnvironmentFile(ParsingEnvironmentFileData& data);
0115 
0116     ParsingEnvironmentFile& operator=(const ParsingEnvironmentFile& rhs) = delete;
0117 
0118     ///@see ParsingEnvironmentType
0119     virtual int type() const;
0120 
0121     ///Should return whether this file matches into the given environment. The default-implementation always returns true.
0122     virtual bool matchEnvironment(const ParsingEnvironment* environment) const;
0123 
0124     ///Convenience-function that returns the top-context
0125     TopDUContext* topContext() const override;
0126 
0127     KDevelop::IndexedTopDUContext indexedTopContext() const;
0128 
0129     KDevelop::IndexedString url() const override;
0130 
0131     ///Can additionally use language-specific information to decide whether the top-context that has this data attached needs to be reparsed.
0132     ///The standard-implementation checks the modification-time of this file stored using setModificationRevision, and all other modification-times
0133     ///stored with addModificationRevision(..).
0134     virtual bool needsUpdate(const ParsingEnvironment* environment = nullptr) const;
0135 
0136     /**
0137      * A language-specific flag used by C++ to mark one context as a proxy of another.
0138      * If this flag is set on a context, the first imported context should be used for any computations
0139      * like searches, listing, etc. instead of using this context.
0140      *
0141      * The problems should be stored within the proxy-contexts, and optionally there may be
0142      * any count of imported proxy-contexts imported behind the content-context(This can be used for tracking problems)
0143      *
0144      * Note: This flag does not directly change the behavior of the language-independent du-chain.
0145      */
0146     bool isProxyContext() const;
0147 
0148     ///Sets the flag
0149     void setIsProxyContext(bool);
0150 
0151     ///The features of the attached top-context. They are automatically replicated here by the top-context, so they
0152     ///are accessible even without the top-context loaded.
0153     TopDUContext::Features features() const;
0154 
0155     ///Returns the parsing-environment information of all importers of the coupled TopDUContext. This is more efficient than
0156     ///loading the top-context and finding out, because when a top-context is loaded, also all its recursive imports are loaded
0157     QList<QExplicitlySharedDataPointer<ParsingEnvironmentFile>> importers() const;
0158 
0159     ///Returns the parsing-environment information of all imports of the coupled TopDUContext. This is more efficient than
0160     ///loading the top-context and finding out
0161     QList<QExplicitlySharedDataPointer<ParsingEnvironmentFile>> imports() const;
0162 
0163     ///Returns true if this top-context satisfies at least the given minimum features.
0164     ///If there is static minimum features set up in ParseJob, this also checks against those.
0165     ///Features like "ForceUpdate" are treated specially.
0166     ///@p minimumFeatures The features that must be satisfied. May be an arbitrary combination of features.
0167     bool featuresSatisfied(TopDUContext::Features minimumFeatures) const;
0168 
0169     ///Should return a correctly filled ModificationRevision of the source it was created from.
0170     void setModificationRevision(const KDevelop::ModificationRevision& rev);
0171 
0172     KDevelop::ModificationRevision modificationRevision() const;
0173 
0174     ///Clears the modification times of all dependencies
0175     void clearModificationRevisions();
0176 
0177     void addModificationRevision(const IndexedString& url, const ModificationRevision& revision);
0178 
0179     const ModificationRevisionSet& allModificationRevisions() const;
0180 
0181     void addModificationRevisions(const ModificationRevisionSet&);
0182 
0183     /// Returns the language for this top-context. If the string is empty, the language is unknown.
0184     IndexedString language() const;
0185 
0186     /// If the recursive imports of the attached TopDUContext are cached, this returns the cached imports.
0187     /// This works without loading the top-context.
0188     const TopDUContext::IndexedRecursiveImports& importsCache() const;
0189 
0190     ///Sets the language for this top-context. Each top-context should get the language assigned that can by used
0191     ///in order to load the language using ILanguageController.
0192     void setLanguage(const IndexedString& language);
0193 
0194     enum {
0195         Identity = 11
0196     };
0197 
0198     DUCHAIN_DECLARE_DATA(ParsingEnvironmentFile)
0199 
0200 private:
0201     friend class TopDUContext;
0202     friend class DUChainPrivate;
0203     static StaticParsingEnvironmentData* m_staticData;
0204     ///The features are managed by TopDUContext. They are set to TopDUContext::Empty when the top-context is persistently destroyed,
0205     ///so the persistent feature-satisfaction cache can be cleared.
0206     void setFeatures(TopDUContext::Features);
0207     void setTopContext(KDevelop::IndexedTopDUContext context);
0208     bool featuresMatch(KDevelop::TopDUContext::Features minimumFeatures,
0209                        QSet<const KDevelop::ParsingEnvironmentFile*>& checked) const;
0210     void setImportsCache(const TopDUContext::IndexedRecursiveImports&);
0211 };
0212 
0213 // TODO: why is this needed/what is it supposed to print? just the pointer value?
0214 inline QDebug operator<<(QDebug s, const QExplicitlySharedDataPointer<ParsingEnvironmentFile>& p)
0215 {
0216     s.nospace() << p->url();
0217     return s.space();
0218 }
0219 }
0220 
0221 #endif