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
|
/* This file is part of KDevelop
Copyright 2006 Roberto Raggi <roberto@kdevelop.org>
Copyright 2006-2008 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 CONTEXTBUILDER_H
#define CONTEXTBUILDER_H
#include "default_visitor.h"
#include <QtCore/QSet>
#include "cppducontext.h"
#include <language/duchain/builders/abstractcontextbuilder.h>
#include <language/duchain/duchainpointer.h>
#include <language/duchain/duchainlock.h>
#include <language/duchain/identifier.h>
#include <language/duchain/ducontext.h>
#include <ksharedptr.h>
#include "cppduchainexport.h"
#include "cppeditorintegrator.h"
#include <language/duchain/classdeclaration.h>
#include "environmentmanager.h"
//Uncomment this to debug what happens to context ranges when new ones are inserted
//#define DEBUG_CONTEXT_RANGES
#include <name_compiler.h>
namespace KDevelop
{
class DUChain;
class DUChainBase;
class DUContext;
class TopDUContext;
}
class CppEditorIntegrator;
class ParseSession;
class NameCompiler;
namespace KTextEditor { class Range; }
namespace Cpp {
class EnvironmentFile;
typedef KSharedPtr<EnvironmentFile> EnvironmentFilePointer;
}
struct KDEVCPPDUCHAIN_EXPORT LineContextPair {
LineContextPair( KDevelop::TopDUContext* _context, int _sourceLine ) : context(_context), sourceLine(_sourceLine), temporary(false) {
}
ReferencedTopDUContext context;
int sourceLine;
bool temporary; //When this flag is set, the import will be added in a special way that is faster
};
typedef QList<LineContextPair> IncludeFileList;
///@return Whether @param context is contained as a context in @param lineContexts
bool KDEVCPPDUCHAIN_EXPORT containsContext( const QList<LineContextPair>& lineContexts, TopDUContext* context );
///@return Whether a context in @param lineContexts imports the context @param context
bool KDEVCPPDUCHAIN_EXPORT importsContext( const QList<LineContextPair>& lineContexts, TopDUContext* context );
///Removes @param context from the list
void KDEVCPPDUCHAIN_EXPORT removeContext( QList<LineContextPair>& lineContexts, TopDUContext* context );
class ContextBuilderBase : public KDevelop::AbstractContextBuilder<AST, NameAST>
{
};
/**
* A class which iterates the AST to identify contexts.
*/
class KDEVCPPDUCHAIN_EXPORT ContextBuilder: public ContextBuilderBase, protected DefaultVisitor
{
friend class IdentifierVerifier;
public:
ContextBuilder(ParseSession* session);
virtual ~ContextBuilder ();
/**
* Builds or updates a proxy-context that represents a content-context under a different environment.
* The top-context is guaranteed to import "content" as first import, eventually all imports are cleared.
* */
KDevelop::TopDUContext* buildProxyContextFromContent(Cpp::EnvironmentFilePointer file, const TopDUContextPointer& content, const TopDUContextPointer& updateContext);
/**
* Compile either a context-definition chain, or add uses to an existing
* chain.
*
* \param includes contexts to reference from the top context. The list may be changed by this function.
* \param removeOldImports Should old imports that are not in the includes-list be removed?
*/
KDevelop::ReferencedTopDUContext buildContexts(Cpp::EnvironmentFilePointer file, AST *node, IncludeFileList* includes = 0, const ReferencedTopDUContext& updateContext = ReferencedTopDUContext(), bool removeOldImports = true);
/**
* Build.an independent du-context based on a given parent-context. Such a context may be used for expression-parsing,
* but should be deleted as fast as possible because it keeps a reference to an independent context.
*
* Warning: the resulting context should be deleted some time. Before deleting it, the du-chain must be locked.
* Warning: The new context is added as a child to the parent-context.
* \param url A temporary url that can be used to identify this context @todo remove this
*
* \param parent Context that will be used as parent for this context
*/
// KDevelop::DUContext* buildSubContexts(const IndexedString& url, AST *node, KDevelop::DUContext* parent = 0);
//If this flag is enabled, only publically visible declarations/contexts are computed
void setOnlyComputeVisible(bool onlyVisible);
//If this flag is enabled, declarations and contexts are computed in a very simplified form (without types, without template- or function-contexts, etc.)
void setComputeSimplified(bool simplified);
//If this flag is set, the top-context will be empty, without any contexts or declarations
void setComputeEmpty(bool empty);
void setMapAst(bool mapAst);
CppEditorIntegrator* editor() {
return &m_editor;
}
protected:
QualifiedIdentifier identifierForNode(NameAST* id);
void identifierForNode(NameAST* id, QualifiedIdentifier& target);
virtual void startVisiting( AST* node );
virtual void setContextOnNode( AST* node, DUContext* ctx );
virtual DUContext* contextFromNode( AST* node );
virtual RangeInRevision editorFindRange( AST* fromRange, AST* toRange );
virtual RangeInRevision editorFindRangeForContext( AST* fromRange, AST* toRange );
virtual DUContext* newContext(const RangeInRevision& range);
/**
* Compile an identifier for the specified NameAST \a id.
*
* \note this reference will only be valid until the next time the function
* is called, so you need to create a copy (store as non-reference).
* @param typeSpecifier a pointer that will eventually be filled with a type-specifier that can be found in the name(for example the return-type of a cast-operator)
* @param target Place where the identifier will be written.
*/
void identifierForNode(NameAST* id, TypeSpecifierAST** typeSpecifier, QualifiedIdentifier& target);
virtual void addBaseType( KDevelop::BaseClassInstance base, BaseSpecifierAST *node );
///Open/close prefix contexts around the class specifier that make the qualified identifier
///of the class Declaration match, because Declarations have only unqualified names.
///The prefix-context will also import the context of the specific class-declaration, so the visibility matches.
///@param id should be the whole identifier. A prefix-context will only be created if it
///has more than 1 element.
void openPrefixContext(AST* ast, const QualifiedIdentifier& id, const CursorInRevision& pos);
void closePrefixContext(const QualifiedIdentifier& id);
//The returned context may be zero, while the identifier valid
QPair<DUContext*, QualifiedIdentifier> findPrefixContext(const QualifiedIdentifier& id, KDevelop::CursorInRevision pos);
// Split up visitors created for subclasses to use
/// Visits the type specifier and init declarator for a function.
virtual void visitFunctionDeclaration (FunctionDefinitionAST *);
virtual void visitPostSimpleDeclaration(SimpleDeclarationAST*);
virtual void visitTemplateDeclaration(TemplateDeclarationAST *);
// Normal overridden visitors
virtual void visitInitDeclarator(InitDeclaratorAST *node);
virtual void visitDeclarator(DeclaratorAST *node);
virtual void visitNamespace(NamespaceAST *);
virtual void visitEnumSpecifier(EnumSpecifierAST* node);
virtual void visitClassSpecifier(ClassSpecifierAST *);
virtual void visitTypedef(TypedefAST *);
virtual void visitFunctionDefinition(FunctionDefinitionAST *);
virtual void visitCompoundStatement(CompoundStatementAST *);
virtual void visitSimpleDeclaration(SimpleDeclarationAST *);
virtual void visitName(NameAST *);
virtual void visitUsing(UsingAST*);
virtual void visitExpressionOrDeclarationStatement(ExpressionOrDeclarationStatementAST*);
virtual void visitForStatement(ForStatementAST*);
virtual void visitIfStatement(IfStatementAST*);
virtual void visitSwitchStatement(SwitchStatementAST*);
virtual void visitDoStatement(DoStatementAST*);
virtual void visitTryBlockStatement(TryBlockStatementAST*);
virtual void visitCatchStatement(CatchStatementAST*);
virtual void createTypeForDeclarator(DeclaratorAST *node);
virtual void createTypeForInitializer(InitializerAST *node);
virtual void closeTypeForInitializer(InitializerAST *node);
virtual void closeTypeForDeclarator(DeclaratorAST *node);
virtual void visitParameterDeclarationClause(ParameterDeclarationClauseAST* node);
virtual void visitLambdaDeclarator(LambdaDeclaratorAST* node);
void queueImportedContext(DUContext* context) {
DUChainReadLocker lock(DUChain::lock());
m_importedParentContexts << DUContext::Import(context, currentContext());
}
virtual void setInSymbolTable(DUContext* context);
virtual void classContextOpened(ClassSpecifierAST *node, DUContext* context);
virtual void preVisitSimpleDeclaration(SimpleDeclarationAST *);
//DUChain must not be locked
void createUserProblem(AST* node, QString problem);
//Opens a context of size 0, starting at the given node
KDevelop::DUContext* openContextEmpty(AST* range, KDevelop::DUContext::ContextType type);
KDevelop::DUContext* openContextInternal(const KDevelop::RangeInRevision& range, KDevelop::DUContext::ContextType type, const KDevelop::QualifiedIdentifier& identifier);
bool createContextIfNeeded(AST* node, const QVector<KDevelop::DUContext::Import>& importedParentContexts);
bool createContextIfNeeded(AST* node, KDevelop::DUContext* importedParentContext);
void addImportedContexts();
int templateDeclarationDepth() const {
return m_templateDeclarationDepth;
}
// Variables
bool m_inFunctionDefinition;
CppEditorIntegrator m_editor;
NameCompiler m_nameCompiler;
int m_templateDeclarationDepth;
uint m_typeSpecifierWithoutInitDeclarators; //Start-token of the last opened type-specifier without init-declarators (Only filled in specific cases)
QualifiedIdentifier m_openingFunctionBody; //Identifier of the currently opened function body, or empty.
bool m_onlyComputeVisible;
bool m_onlyComputeSimplified;
bool m_computeEmpty;
#ifdef DEBUG_CONTEXT_RANGES
void checkRanges();
QHash<KDevelop::DUContext*, KDevelop::RangeInRevision> m_contextRanges;
#endif
QVector<KDevelop::DUContext::Import> m_importedParentContexts;
QStack< QVector<KDevelop::DUContext::Import> > m_tryParentContexts;
InitializerAST* m_currentInitializer;
/// AST - DUChain/Uses mapping variables
bool m_mapAst;
};
#endif // CONTEXTBUILDER_H
|