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
|
/*
SPDX-FileCopyrightText: 2007 David Nolden <david.nolden.kdevelop@art-master.de>
SPDX-License-Identifier: LGPL-2.0-only
*/
#ifndef KDEVPLATFORM_PARSINGENVIRONMENT_H
#define KDEVPLATFORM_PARSINGENVIRONMENT_H
#include <serialization/indexedstring.h>
#include <language/languageexport.h>
#include "duchainbase.h"
#include "topducontext.h"
#include <language/editor/modificationrevisionset.h>
namespace KDevelop {
/**
* Just an enumeration of a few parsing-environment types.
* Enumerate a few possible future parsing-environment types.
* A parsing-environment could also have a type not in this enumeration,
* the only important thing is that it's unique for the type.
*
* The type is needed to match ParsingEnvironment, ParsingEnvironmentFile, and ParsingEnvironmentManager together so they fit.
* For example the c++-versions would have their specific type.
*
* The type must be unique(no other language may have the same type),
* and the type must be persistent.(it must be same after restarting kdevelop)
*
* */
enum ParsingEnvironmentType
{
StandardParsingEnvironment /**< a basic standard parsing environment */,
CppParsingEnvironment /**< a C++ parsing environment */,
PythonParsingEnvironment /**< a python parsing environment */,
CMakeParsingEnvironment /**< a CMake parsing environment */,
CSharpParsingEnvironment /**< a CSharp parsing environment */,
JavaParsingEnvironment /**< a JAva parsing environment */,
RubyParsingEnvironment /**< a Ruby parsing environment */,
PhpParsingEnvironment /**< a PHP parsing environment */
};
///Internal
struct StaticParsingEnvironmentData
{
TopDUContext::IndexedRecursiveImports simplifiedVisibleDeclarationsSatisfied;
TopDUContext::IndexedRecursiveImports visibleDeclarationsSatisfied;
TopDUContext::IndexedRecursiveImports allDeclarationsSatisfied;
TopDUContext::IndexedRecursiveImports allDeclarationsAndUsesSatisfied;
TopDUContext::IndexedRecursiveImports ASTSatisfied;
};
/**
* Use this as base-class to define new parsing-environments.
*
* Parsing-environments are needed for languages that create different
* parsing-results depending on the environment. For example in c++,
* the environment mainly consists of macros. The include-path can
* be considered to be a part of the parsing-environment too, because
* different files may be included using another include-path.
*
* The classes have to use the serialization scheme from the duchain.
* Each class must be registered using REGISTER_DUCHAIN_ITEM with a unique id.
*
* \warning Access to this class must be serialized through du-chain locking
* */
class KDEVPLATFORMLANGUAGE_EXPORT ParsingEnvironment
{
public:
ParsingEnvironment();
virtual ~ParsingEnvironment();
///@see ParsingEnvironmentType
virtual int type() const;
};
///The data class used for storing. Use this as base-class of your custom data classes for classes derived from
///ParsingEnvironmentFile
class KDEVPLATFORMLANGUAGE_EXPORT ParsingEnvironmentFileData
: public DUChainBaseData
{
public:
bool m_isProxyContext = false;
TopDUContext::Features m_features = TopDUContext::VisibleDeclarationsAndContexts;
KDevelop::ModificationRevision m_modificationTime;
ModificationRevisionSet m_allModificationRevisions;
KDevelop::IndexedString m_url;
KDevelop::IndexedTopDUContext m_topContext;
IndexedString m_language;
///If this is not empty, it means that the cache is used instead of the implicit structure.
TopDUContext::IndexedRecursiveImports m_importsCache;
};
using ParsingEnvironmentFilePointer = QExplicitlySharedDataPointer<ParsingEnvironmentFile>;
/**
* This represents all information about a specific parsed file that is needed
* to match the file to a parsing-environment.
*
* It is QSharedData because it is embedded into top-du-contexts and at the same time
* references may be held by ParsingEnvironmentManager.
*
* \warning Access to this class must be serialized through du-chain locking
* */
class KDEVPLATFORMLANGUAGE_EXPORT ParsingEnvironmentFile
: public DUChainBase
, public QSharedData
{
public:
~ParsingEnvironmentFile() override;
explicit ParsingEnvironmentFile(const IndexedString& url);
ParsingEnvironmentFile(ParsingEnvironmentFileData& data, const IndexedString& url);
explicit ParsingEnvironmentFile(ParsingEnvironmentFileData& data);
ParsingEnvironmentFile& operator=(const ParsingEnvironmentFile& rhs) = delete;
///@see ParsingEnvironmentType
virtual int type() const;
///Should return whether this file matches into the given environment. The default-implementation always returns true.
virtual bool matchEnvironment(const ParsingEnvironment* environment) const;
///Convenience-function that returns the top-context
TopDUContext* topContext() const override;
KDevelop::IndexedTopDUContext indexedTopContext() const;
KDevelop::IndexedString url() const override;
///Can additionally use language-specific information to decide whether the top-context that has this data attached needs to be reparsed.
///The standard-implementation checks the modification-time of this file stored using setModificationRevision, and all other modification-times
///stored with addModificationRevision(..).
virtual bool needsUpdate(const ParsingEnvironment* environment = nullptr) const;
/**
* A language-specific flag used by C++ to mark one context as a proxy of another.
* If this flag is set on a context, the first imported context should be used for any computations
* like searches, listing, etc. instead of using this context.
*
* The problems should be stored within the proxy-contexts, and optionally there may be
* any count of imported proxy-contexts imported behind the content-context(This can be used for tracking problems)
*
* Note: This flag does not directly change the behavior of the language-independent du-chain.
*/
bool isProxyContext() const;
///Sets the flag
void setIsProxyContext(bool);
///The features of the attached top-context. They are automatically replicated here by the top-context, so they
///are accessible even without the top-context loaded.
TopDUContext::Features features() const;
///Returns the parsing-environment information of all importers of the coupled TopDUContext. This is more efficient than
///loading the top-context and finding out, because when a top-context is loaded, also all its recursive imports are loaded
QList<QExplicitlySharedDataPointer<ParsingEnvironmentFile>> importers() const;
///Returns the parsing-environment information of all imports of the coupled TopDUContext. This is more efficient than
///loading the top-context and finding out
QList<QExplicitlySharedDataPointer<ParsingEnvironmentFile>> imports() const;
///Returns true if this top-context satisfies at least the given minimum features.
///If there is static minimum features set up in ParseJob, this also checks against those.
///Features like "ForceUpdate" are treated specially.
///@p minimumFeatures The features that must be satisfied. May be an arbitrary combination of features.
bool featuresSatisfied(TopDUContext::Features minimumFeatures) const;
///Should return a correctly filled ModificationRevision of the source it was created from.
void setModificationRevision(const KDevelop::ModificationRevision& rev);
KDevelop::ModificationRevision modificationRevision() const;
///Clears the modification times of all dependencies
void clearModificationRevisions();
void addModificationRevision(const IndexedString& url, const ModificationRevision& revision);
const ModificationRevisionSet& allModificationRevisions() const;
void addModificationRevisions(const ModificationRevisionSet&);
/// Returns the language for this top-context. If the string is empty, the language is unknown.
IndexedString language() const;
/// If the recursive imports of the attached TopDUContext are cached, this returns the cached imports.
/// This works without loading the top-context.
const TopDUContext::IndexedRecursiveImports& importsCache() const;
///Sets the language for this top-context. Each top-context should get the language assigned that can by used
///in order to load the language using ILanguageController.
void setLanguage(const IndexedString& language);
enum {
Identity = 11
};
DUCHAIN_DECLARE_DATA(ParsingEnvironmentFile)
private:
friend class TopDUContext;
friend class DUChainPrivate;
static StaticParsingEnvironmentData* m_staticData;
///The features are managed by TopDUContext. They are set to TopDUContext::Empty when the top-context is persistently destroyed,
///so the persistent feature-satisfaction cache can be cleared.
void setFeatures(TopDUContext::Features);
void setTopContext(KDevelop::IndexedTopDUContext context);
bool featuresMatch(KDevelop::TopDUContext::Features minimumFeatures,
QSet<const KDevelop::ParsingEnvironmentFile*>& checked) const;
void setImportsCache(const TopDUContext::IndexedRecursiveImports&);
};
// TODO: why is this needed/what is it supposed to print? just the pointer value?
inline QDebug operator<<(QDebug s, const QExplicitlySharedDataPointer<ParsingEnvironmentFile>& p)
{
s.nospace() << p->url();
return s.space();
}
}
#endif
|