src: added optional indexer AST logging
* removed old AstVisitor * added new implementation called CxxAstVisitor * added CxxVerboseAstVisitor that may wrap the CxxAstVisitor to log the AST while visiting * added the same structure for the Java visitors * removed all the logs that were fired when recording stuff * Added UI setting for verbose indexer logging. * implemented AST name obfuscation for Java and Cxx * unified test visitors for Java and Cxx * implemented recording using directive decl * removed most of the old onXxxParsed methods
This commit is contained in:
@@ -1,10 +1,18 @@
|
||||
#include "data/parser/cxx/ASTConsumer.h"
|
||||
|
||||
#include "data/parser/ParserClient.h"
|
||||
#include "data/parser/cxx/CxxAstVisitor.h"
|
||||
#include "data/parser/cxx/CxxVerboseAstVisitor.h"
|
||||
#include "settings/ApplicationSettings.h"
|
||||
|
||||
ASTConsumer::ASTConsumer(clang::ASTContext* context, clang::Preprocessor* preprocessor, ParserClient* client, FileRegister* fileRegister)
|
||||
: m_visitor(context, preprocessor, client, fileRegister)
|
||||
{
|
||||
if (ApplicationSettings::getInstance()->getVerboseInderxerLoggingEnabled())
|
||||
{
|
||||
m_visitor = std::make_shared<CxxVerboseAstVisitor>(context, preprocessor, client, fileRegister);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_visitor = std::make_shared<CxxAstVisitor>(context, preprocessor, client, fileRegister);
|
||||
}
|
||||
}
|
||||
|
||||
ASTConsumer::~ASTConsumer()
|
||||
@@ -13,5 +21,5 @@ ASTConsumer::~ASTConsumer()
|
||||
|
||||
void ASTConsumer::HandleTranslationUnit(clang::ASTContext& context)
|
||||
{
|
||||
m_visitor.indexDecl(context.getTranslationUnitDecl());
|
||||
m_visitor->indexDecl(context.getTranslationUnitDecl());
|
||||
}
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
#include "clang/AST/ASTConsumer.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
|
||||
#include "utility/file/FileRegister.h"
|
||||
|
||||
#include "data/parser/cxx/ASTVisitor.h"
|
||||
class CxxAstVisitor;
|
||||
class FileRegister;
|
||||
class ParserClient;
|
||||
|
||||
class ASTConsumer
|
||||
: public clang::ASTConsumer
|
||||
@@ -18,7 +19,7 @@ public:
|
||||
virtual void HandleTranslationUnit(clang::ASTContext& context);
|
||||
|
||||
private:
|
||||
ASTVisitor m_visitor;
|
||||
std::shared_ptr<CxxAstVisitor> m_visitor;
|
||||
};
|
||||
|
||||
#endif // AST_CONSUMER_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,248 +0,0 @@
|
||||
#ifndef AST_VISITOR_H
|
||||
#define AST_VISITOR_H
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include <clang/AST/RecursiveASTVisitor.h>
|
||||
#include <clang/Basic/SourceLocation.h>
|
||||
#include <clang/Basic/SourceManager.h>
|
||||
|
||||
#include "data/parser/ParserClient.h"
|
||||
#include "data/parser/SymbolKind.h"
|
||||
#include "utility/file/FileRegister.h"
|
||||
#include "utility/messaging/MessageInterruptTasksCounter.h"
|
||||
#include "utility/Cache.h"
|
||||
|
||||
class ASTVisitor
|
||||
: clang::RecursiveASTVisitor<ASTVisitor>
|
||||
{
|
||||
public:
|
||||
typedef Cache<const clang::NamedDecl*, NameHierarchy> DeclNameCache;
|
||||
typedef Cache<const clang::Type*, NameHierarchy> TypeNameCache;
|
||||
|
||||
class ContextNameGenerator
|
||||
{
|
||||
public:
|
||||
virtual ~ContextNameGenerator() {}
|
||||
virtual NameHierarchy getName() const = 0;
|
||||
};
|
||||
|
||||
class ContextDeclNameGenerator: public ContextNameGenerator
|
||||
{
|
||||
public:
|
||||
ContextDeclNameGenerator(const clang::NamedDecl* decl, std::shared_ptr<DeclNameCache> nameCache)
|
||||
: m_decl(decl)
|
||||
, m_nameCache(nameCache)
|
||||
{}
|
||||
|
||||
virtual ~ContextDeclNameGenerator() {}
|
||||
|
||||
virtual NameHierarchy getName() const
|
||||
{
|
||||
return m_nameCache->getValue(m_decl);
|
||||
}
|
||||
|
||||
private:
|
||||
const clang::NamedDecl* m_decl;
|
||||
std::shared_ptr<DeclNameCache> m_nameCache;
|
||||
};
|
||||
|
||||
class ContextTypeNameGenerator: public ContextNameGenerator
|
||||
{
|
||||
public:
|
||||
ContextTypeNameGenerator(const clang::Type* type, std::shared_ptr<TypeNameCache> nameCache)
|
||||
: m_type(type)
|
||||
, m_nameCache(nameCache)
|
||||
{}
|
||||
|
||||
virtual ~ContextTypeNameGenerator() {}
|
||||
|
||||
virtual NameHierarchy getName() const
|
||||
{
|
||||
return m_nameCache->getValue(m_type);
|
||||
}
|
||||
|
||||
private:
|
||||
const clang::Type* m_type;
|
||||
std::shared_ptr<TypeNameCache> m_nameCache;
|
||||
};
|
||||
|
||||
ASTVisitor(clang::ASTContext* context, clang::Preprocessor* preprocessor, ParserClient* client, FileRegister* fileRegister);
|
||||
virtual ~ASTVisitor();
|
||||
|
||||
// Left for debugging purposes. Uncomment to see a colored ast-dump of the parsed file.
|
||||
virtual bool VisitTranslationUnitDecl(clang::TranslationUnitDecl* decl);
|
||||
|
||||
|
||||
void indexDecl(clang::Decl *d) { TraverseDecl(d); }
|
||||
|
||||
private:
|
||||
typedef clang::RecursiveASTVisitor<ASTVisitor> base;
|
||||
friend class clang::RecursiveASTVisitor<ASTVisitor>;
|
||||
|
||||
// XXX: The CF_Read flag is useful mostly for lvalues -- for rvalues, we
|
||||
// don't set the CF_Read flag, but the rvalue is assumed to be read anyway.
|
||||
|
||||
enum ContextFlags {
|
||||
CF_Called = 0x1, // the value is read only to be called
|
||||
CF_Read = 0x2, // the value is read for any other use
|
||||
CF_AddressTaken = 0x4, // the gl-value's address escapes
|
||||
CF_Assigned = 0x8, // the gl-value is assigned to
|
||||
CF_Modified = 0x10 // the gl-value is updated (i.e. compound assignment)
|
||||
};
|
||||
|
||||
enum RefType : int {
|
||||
RT_AddressTaken,
|
||||
RT_Assigned,
|
||||
RT_BaseClass,
|
||||
RT_Called,
|
||||
RT_Declaration,
|
||||
RT_DefinedTest,
|
||||
RT_Definition,
|
||||
RT_Expansion,
|
||||
RT_Included,
|
||||
RT_Initialized,
|
||||
RT_Modified,
|
||||
RT_NamespaceAlias,
|
||||
RT_Other,
|
||||
RT_Qualifier,
|
||||
RT_Read,
|
||||
RT_Reference,
|
||||
RT_TemplateArgument,
|
||||
RT_TemplateDefaultArgument,
|
||||
RT_TemplateSpecialization,
|
||||
RT_Undefinition,
|
||||
RT_Using,
|
||||
RT_UsingDirective,
|
||||
RT_Max
|
||||
};
|
||||
|
||||
typedef unsigned int Context;
|
||||
|
||||
clang::ASTContext* m_context;
|
||||
clang::Preprocessor* m_preprocessor;
|
||||
ParserClient* m_client;
|
||||
FileRegister* m_fileRegister;
|
||||
|
||||
Context m_thisContext;
|
||||
Context m_childContext;
|
||||
RefType m_typeContext;
|
||||
|
||||
// Misc routines
|
||||
bool shouldVisitTemplateInstantiations() const { return true; }
|
||||
bool shouldVisitImplicitCode() const { return true; }
|
||||
|
||||
// Dispatcher routines
|
||||
bool TraverseStmt(clang::Stmt *stmt);
|
||||
bool TraverseType(clang::QualType t);
|
||||
bool TraverseTypeLoc(clang::TypeLoc tl);
|
||||
bool TraverseDecl(clang::Decl *d);
|
||||
bool TraverseLambdaExpr(clang::LambdaExpr* e);
|
||||
bool TraverseFunctionDecl(clang::FunctionDecl* d);
|
||||
bool TraverseTypedefDecl(clang::TypedefDecl *d);
|
||||
bool TraverseTypeAliasDecl(clang::TypeAliasDecl *d);
|
||||
bool TraverseFieldDecl(clang::FieldDecl *d);
|
||||
bool TraverseVarDecl(clang::VarDecl *d);
|
||||
bool TraverseClassTemplateDecl(clang::ClassTemplateDecl* d);
|
||||
bool TraverseFunctionTemplateDecl(clang::FunctionTemplateDecl* d);
|
||||
bool TraverseTemplateTypeParmDecl(clang::TemplateTypeParmDecl* d);
|
||||
bool TraverseTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl* d);
|
||||
bool TraverseClassTemplatePartialSpecializationDecl(clang::ClassTemplatePartialSpecializationDecl* d);
|
||||
bool TraverseDeclRefExpr(clang::DeclRefExpr* e);
|
||||
bool TraverseTemplateSpecializationTypeLoc(clang::TemplateSpecializationTypeLoc loc);
|
||||
bool TraverseUnresolvedLookupExpr(clang::UnresolvedLookupExpr* e);
|
||||
bool TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc);
|
||||
|
||||
// Expression context propagation
|
||||
bool TraverseCallExpr(clang::CallExpr *e) { return TraverseCallCommon(e); }
|
||||
bool TraverseCXXMemberCallExpr(clang::CXXMemberCallExpr *e) { return TraverseCallCommon(e); }
|
||||
bool TraverseCXXOperatorCallExpr(clang::CXXOperatorCallExpr *e) { return TraverseCallCommon(e); }
|
||||
bool TraverseBinComma(clang::BinaryOperator *s);
|
||||
bool TraverseBinAssign(clang::BinaryOperator *e) { return TraverseAssignCommon(e, CF_Assigned); }
|
||||
#define OPERATOR(NAME) bool TraverseBin##NAME##Assign(clang::CompoundAssignOperator *e) { return TraverseAssignCommon(e, CF_Modified); }
|
||||
OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub)
|
||||
OPERATOR(Shl) OPERATOR(Shr) OPERATOR(And) OPERATOR(Or) OPERATOR(Xor)
|
||||
#undef OPERATOR
|
||||
bool VisitParenExpr(clang::ParenExpr *e) { m_childContext = m_thisContext; return true; }
|
||||
bool VisitCastExpr(clang::CastExpr *e);
|
||||
bool VisitUnaryAddrOf(clang::UnaryOperator *e);
|
||||
bool VisitUnaryDeref(clang::UnaryOperator *e);
|
||||
bool VisitDeclStmt(clang::DeclStmt *s);
|
||||
bool VisitReturnStmt(clang::ReturnStmt *s);
|
||||
bool VisitVarDecl(clang::VarDecl *d);
|
||||
bool VisitInitListExpr(clang::InitListExpr *e);
|
||||
bool TraverseConstructorInitializer(clang::CXXCtorInitializer *init);
|
||||
bool TraverseCallCommon(clang::CallExpr *call);
|
||||
bool TraverseAssignCommon(clang::BinaryOperator *e, ContextFlags lhsFlag);
|
||||
|
||||
// Expression reference recording
|
||||
bool VisitLambdaExpr(clang::LambdaExpr* e);
|
||||
bool VisitMemberExpr(clang::MemberExpr *e);
|
||||
bool VisitDeclRefExpr(clang::DeclRefExpr *e);
|
||||
bool VisitCXXConstructExpr(clang::CXXConstructExpr *e);
|
||||
void RecordDeclRefExpr(clang::NamedDecl *d, clang::SourceLocation loc, clang::Expr *e, Context context);
|
||||
|
||||
// NestedNameSpecifier handling
|
||||
bool TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc qualifier);
|
||||
|
||||
// Declaration and TypeLoc handling
|
||||
void traverseDeclContextHelper(clang::DeclContext *d);
|
||||
bool TraverseCXXRecordDecl(clang::CXXRecordDecl *d);
|
||||
bool TraverseNamespaceAliasDecl(clang::NamespaceAliasDecl *d);
|
||||
bool TraverseClassTemplateSpecializationDecl(
|
||||
clang::ClassTemplateSpecializationDecl *d);
|
||||
void templateParameterListsHelper(clang::DeclaratorDecl *d);
|
||||
bool VisitDecl(clang::Decl *d);
|
||||
bool VisitTypeLoc(clang::TypeLoc tl);
|
||||
|
||||
// Reference recording
|
||||
ParseLocation getDeclRefRange(
|
||||
clang::NamedDecl *decl,
|
||||
clang::SourceLocation loc);
|
||||
|
||||
void RecordTypeRef(
|
||||
const clang::Type* type,
|
||||
clang::SourceLocation beginLoc,
|
||||
RefType refType,
|
||||
SymbolKind symbolType = SYMBOL_KIND_MAX);
|
||||
|
||||
void RecordDeclRef(
|
||||
clang::NamedDecl *d,
|
||||
clang::SourceLocation beginLoc,
|
||||
RefType refType,
|
||||
SymbolKind symbolType = SYMBOL_KIND_MAX);
|
||||
|
||||
bool isImplicit(clang::Decl* d) const;
|
||||
|
||||
bool isLocatedInUnparsedProjectFile(clang::SourceLocation loc);
|
||||
bool isLocatedInProjectFile(clang::SourceLocation loc);
|
||||
|
||||
AccessKind convertAccessType(clang::AccessSpecifier access) const;
|
||||
ParserClient::AbstractionType getAbstractionType(const clang::CXXMethodDecl* methodDecl) const;
|
||||
ParseLocation getParseLocationOfRecordBody(clang::RecordDecl* decl) const;
|
||||
ParseLocation getParseLocationOfFunctionBody(const clang::FunctionDecl* decl) const;
|
||||
ParseLocation getParseLocation(const clang::SourceRange& sourceRange) const;
|
||||
|
||||
NameHierarchy getContextName() const;
|
||||
|
||||
struct FileIdHash {
|
||||
size_t operator()(clang::FileID fileID) const {
|
||||
return fileID.getHashValue();
|
||||
}
|
||||
};
|
||||
|
||||
std::unordered_map<const clang::FileID, bool, FileIdHash> m_inUnparsedProjectFileMap;
|
||||
std::unordered_map<const clang::FileID, bool, FileIdHash> m_inProjectFileMap;
|
||||
|
||||
std::shared_ptr<ContextNameGenerator> m_contextNameGenerator;
|
||||
std::shared_ptr<ContextNameGenerator> m_childContextNameGenerator; // TODO: rename templateArgumentContextNameGenerator
|
||||
|
||||
std::shared_ptr<DeclNameCache> m_declNameCache;
|
||||
std::shared_ptr<TypeNameCache> m_typeNameCache;
|
||||
|
||||
AccessKind m_contextAccess;
|
||||
MessageInterruptTasksCounter m_interruptCounter;
|
||||
};
|
||||
|
||||
#endif // AST_VISITOR_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,161 @@
|
||||
#ifndef CXX_AST_VISITOR_H
|
||||
#define CXX_AST_VISITOR_H
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include <clang/AST/RecursiveASTVisitor.h>
|
||||
|
||||
#include "data/parser/cxx/CxxContext.h"
|
||||
#include "data/parser/AccessKind.h"
|
||||
#include "data/parser/ReferenceKind.h"
|
||||
#include "data/parser/SymbolKind.h"
|
||||
#include "utility/messaging/MessageInterruptTasksCounter.h"
|
||||
#include "utility/Cache.h"
|
||||
|
||||
class ParserClient;
|
||||
struct ParseLocation;
|
||||
class FileRegister;
|
||||
|
||||
// methods are called in this order:
|
||||
// TraverseDecl()
|
||||
// `- TraverseFunctionDecl()
|
||||
// |- WalkUpFromFunctionDecl()
|
||||
// | |- WalkUpFromNamedDecl()
|
||||
// | | |- WalkUpFromDecl()
|
||||
// | | | `- VisitDecl()
|
||||
// | | `- VisitNamedDecl()
|
||||
// | `- VisitFunctionDecl()
|
||||
// `- TraverseChildNodes()
|
||||
|
||||
class ScopedContextKindSetter
|
||||
{
|
||||
public:
|
||||
ScopedContextKindSetter(const ReferenceKind refKind, std::vector<ReferenceKind>* stack)
|
||||
: m_stack(stack)
|
||||
{
|
||||
m_stack->push_back(refKind);
|
||||
}
|
||||
|
||||
~ScopedContextKindSetter()
|
||||
{
|
||||
m_stack->pop_back();
|
||||
}
|
||||
private:
|
||||
std::vector<ReferenceKind>* m_stack;
|
||||
};
|
||||
|
||||
class CxxAstVisitor: public clang::RecursiveASTVisitor<CxxAstVisitor>
|
||||
{
|
||||
public:
|
||||
CxxAstVisitor(clang::ASTContext* astContext, clang::Preprocessor* preprocessor, ParserClient* client, FileRegister* fileRegister);
|
||||
virtual ~CxxAstVisitor();
|
||||
|
||||
// Indexing entry point
|
||||
void indexDecl(clang::Decl *d);
|
||||
|
||||
// Visitor options
|
||||
virtual bool shouldVisitTemplateInstantiations() const;
|
||||
virtual bool shouldVisitImplicitCode() const;
|
||||
|
||||
// Traversal methods. These specify how to traverse the AST and record context info.
|
||||
virtual bool TraverseDecl(clang::Decl *d);
|
||||
virtual bool TraverseTypeLoc(clang::TypeLoc tl);
|
||||
virtual bool TraverseType(clang::QualType t);
|
||||
virtual bool TraverseStmt(clang::Stmt *stmt);
|
||||
|
||||
virtual bool TraverseCXXRecordDecl(clang::CXXRecordDecl *d);
|
||||
virtual bool TraverseTemplateTypeParmDecl(clang::TemplateTypeParmDecl* d);
|
||||
virtual bool TraverseTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl* d);
|
||||
virtual bool TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc loc);
|
||||
virtual bool TraverseConstructorInitializer(clang::CXXCtorInitializer* init);
|
||||
virtual bool TraverseCallExpr(clang::CallExpr* s);
|
||||
virtual bool TraverseCXXMemberCallExpr(clang::CXXMemberCallExpr* s);
|
||||
virtual bool TraverseCXXOperatorCallExpr(clang::CXXOperatorCallExpr* s);
|
||||
virtual bool TraverseCXXConstructExpr(clang::CXXConstructExpr* s);
|
||||
virtual bool TraverseCXXTemporaryObjectExpr(clang::CXXTemporaryObjectExpr* s);
|
||||
virtual bool TraverseLambdaExpr(clang::LambdaExpr* s);
|
||||
virtual bool TraverseFunctionDecl(clang::FunctionDecl* d);
|
||||
virtual bool TraverseClassTemplateSpecializationDecl(clang::ClassTemplateSpecializationDecl *d);
|
||||
virtual bool TraverseClassTemplatePartialSpecializationDecl(clang::ClassTemplatePartialSpecializationDecl* d);
|
||||
virtual bool TraverseDeclRefExpr(clang::DeclRefExpr* s);
|
||||
virtual bool TraverseTemplateSpecializationTypeLoc(clang::TemplateSpecializationTypeLoc loc);
|
||||
virtual bool TraverseUnresolvedLookupExpr(clang::UnresolvedLookupExpr* s);
|
||||
virtual bool TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc);;
|
||||
void traverseDeclContextHelper(clang::DeclContext *d);
|
||||
bool TraverseCallCommon(clang::CallExpr* s);
|
||||
|
||||
// Visitor methods. These actually record stuff and store it in the database.
|
||||
virtual bool VisitTagDecl(clang::TagDecl* d);
|
||||
virtual bool VisitClassTemplateSpecializationDecl(clang::ClassTemplateSpecializationDecl* d);
|
||||
virtual bool VisitFunctionDecl(clang::FunctionDecl* d);
|
||||
virtual bool VisitCXXMethodDecl(clang::CXXMethodDecl* d);
|
||||
virtual bool VisitVarDecl(clang::VarDecl* d);
|
||||
virtual bool VisitFieldDecl(clang::FieldDecl* d);
|
||||
virtual bool VisitTypedefDecl(clang::TypedefDecl* d);
|
||||
virtual bool VisitTypeAliasDecl(clang::TypeAliasDecl* d);
|
||||
virtual bool VisitNamespaceDecl(clang::NamespaceDecl* d);
|
||||
virtual bool VisitNamespaceAliasDecl(clang::NamespaceAliasDecl* d);
|
||||
virtual bool VisitEnumConstantDecl(clang::EnumConstantDecl* d);
|
||||
virtual bool VisitUsingDirectiveDecl(clang::UsingDirectiveDecl* d);
|
||||
virtual bool VisitUsingDecl(clang::UsingDecl* d);
|
||||
virtual bool VisitNonTypeTemplateParmDecl(clang::NonTypeTemplateParmDecl* d);
|
||||
virtual bool VisitTemplateTypeParmDecl(clang::TemplateTypeParmDecl* d);
|
||||
virtual bool VisitTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl* d);
|
||||
|
||||
virtual bool VisitTypeLoc(clang::TypeLoc tl);
|
||||
|
||||
virtual bool VisitDeclRefExpr(clang::DeclRefExpr* s);
|
||||
virtual bool VisitMemberExpr(clang::MemberExpr* s);
|
||||
virtual bool VisitCXXConstructExpr(clang::CXXConstructExpr* s);
|
||||
virtual bool VisitLambdaExpr(clang::LambdaExpr* s);
|
||||
virtual bool VisitConstructorInitializer(clang::CXXCtorInitializer* init);
|
||||
|
||||
protected:
|
||||
// General helpers
|
||||
bool isImplicit(clang::Decl* d) const;
|
||||
bool shouldVisitDecl(clang::Decl* d);
|
||||
bool isLocatedInUnparsedProjectFile(clang::SourceLocation loc);
|
||||
bool isLocatedInProjectFile(clang::SourceLocation loc);
|
||||
|
||||
ParseLocation getParseLocationOfTagDeclBody(clang::TagDecl* decl) const;
|
||||
ParseLocation getParseLocationOfFunctionBody(const clang::FunctionDecl* decl) const;
|
||||
ParseLocation getParseLocation(const clang::SourceLocation& loc) const;
|
||||
ParseLocation getParseLocation(const clang::SourceRange& sourceRange) const;
|
||||
AccessKind convertAccessSpecifier(clang::AccessSpecifier access) const;
|
||||
SymbolKind convertTagKind(clang::TagTypeKind tagKind);
|
||||
|
||||
private:
|
||||
typedef clang::RecursiveASTVisitor<CxxAstVisitor> base;
|
||||
|
||||
NameHierarchy getContextName(const int skip = 0) const;
|
||||
bool checkIgnoresTypeLoc(const clang::TypeLoc& tl);
|
||||
|
||||
struct FileIdHash
|
||||
{
|
||||
size_t operator()(clang::FileID fileID) const
|
||||
{
|
||||
return fileID.getHashValue();
|
||||
}
|
||||
};
|
||||
|
||||
clang::ASTContext* m_astContext;
|
||||
clang::Preprocessor* m_preprocessor;
|
||||
ParserClient* m_client;
|
||||
FileRegister* m_fileRegister;
|
||||
|
||||
MessageInterruptTasksCounter m_interruptCounter;
|
||||
|
||||
ReferenceKind m_typeRefContext;
|
||||
ReferenceKind m_declRefContext;
|
||||
std::vector<std::shared_ptr<CxxContext>> m_contextStack;
|
||||
std::shared_ptr<CxxContext> m_templateArgumentContext;
|
||||
|
||||
std::shared_ptr<DeclNameCache> m_declNameCache;
|
||||
std::shared_ptr<TypeNameCache> m_typeNameCache;
|
||||
std::unordered_map<const clang::FileID, bool, FileIdHash> m_inUnparsedProjectFileMap;
|
||||
std::unordered_map<const clang::FileID, bool, FileIdHash> m_inProjectFileMap;
|
||||
};
|
||||
|
||||
#endif // CXX_AST_VISITOR_H
|
||||
@@ -0,0 +1,35 @@
|
||||
#include "data/parser/cxx/CxxContext.h"
|
||||
|
||||
CxxContext::~CxxContext()
|
||||
{
|
||||
}
|
||||
|
||||
CxxContextDecl::CxxContextDecl(const clang::NamedDecl* decl, std::shared_ptr<DeclNameCache> nameCache)
|
||||
: m_decl(decl)
|
||||
, m_nameCache(nameCache)
|
||||
{
|
||||
}
|
||||
|
||||
CxxContextDecl::~CxxContextDecl()
|
||||
{
|
||||
}
|
||||
|
||||
NameHierarchy CxxContextDecl::getName()
|
||||
{
|
||||
return m_nameCache->getValue(m_decl);
|
||||
}
|
||||
|
||||
CxxContextType::CxxContextType(const clang::Type* type, std::shared_ptr<TypeNameCache> nameCache)
|
||||
: m_type(type)
|
||||
, m_nameCache(nameCache)
|
||||
{
|
||||
}
|
||||
|
||||
CxxContextType::~CxxContextType()
|
||||
{
|
||||
}
|
||||
|
||||
NameHierarchy CxxContextType::getName()
|
||||
{
|
||||
return m_nameCache->getValue(m_type);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef CXX_CONTEXT_H
|
||||
#define CXX_CONTEXT_H
|
||||
|
||||
#include <clang/AST/Decl.h>
|
||||
|
||||
#include "data/name/NameHierarchy.h"
|
||||
#include "utility/Cache.h"
|
||||
|
||||
typedef Cache<const clang::NamedDecl*, NameHierarchy> DeclNameCache;
|
||||
typedef Cache<const clang::Type*, NameHierarchy> TypeNameCache;
|
||||
|
||||
class CxxContext
|
||||
{
|
||||
public:
|
||||
virtual ~CxxContext();
|
||||
virtual NameHierarchy getName() = 0;
|
||||
};
|
||||
|
||||
class CxxContextDecl: public CxxContext
|
||||
{
|
||||
public:
|
||||
CxxContextDecl(const clang::NamedDecl* decl, std::shared_ptr<DeclNameCache> nameCache);
|
||||
virtual ~CxxContextDecl();
|
||||
virtual NameHierarchy getName();
|
||||
|
||||
private:
|
||||
const clang::NamedDecl* m_decl;
|
||||
std::shared_ptr<DeclNameCache> m_nameCache;
|
||||
};
|
||||
|
||||
class CxxContextType: public CxxContext
|
||||
{
|
||||
public:
|
||||
CxxContextType(const clang::Type* type, std::shared_ptr<TypeNameCache> nameCache);
|
||||
virtual ~CxxContextType();
|
||||
virtual NameHierarchy getName();
|
||||
|
||||
private:
|
||||
const clang::Type* m_type;
|
||||
std::shared_ptr<TypeNameCache> m_nameCache;
|
||||
};
|
||||
|
||||
#endif // CXX_CONTEXT_H
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
#include "data/parser/cxx/CxxVerboseAstVisitor.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <clang/Basic/SourceLocation.h>
|
||||
#include <clang/Basic/SourceManager.h>
|
||||
|
||||
#include "data/parser/ParseLocation.h"
|
||||
#include "data/parser/ParserClient.h"
|
||||
#include "utility/file/FileRegister.h"
|
||||
|
||||
#include "utility/logging/logging.h"
|
||||
#include "utility/ScopedSwitcher.h"
|
||||
|
||||
CxxVerboseAstVisitor::CxxVerboseAstVisitor(clang::ASTContext* context, clang::Preprocessor* preprocessor, ParserClient* client, FileRegister* fileRegister)
|
||||
: base(context, preprocessor, client, fileRegister)
|
||||
, m_indentation(0)
|
||||
{
|
||||
}
|
||||
|
||||
CxxVerboseAstVisitor::~CxxVerboseAstVisitor()
|
||||
{
|
||||
}
|
||||
|
||||
bool CxxVerboseAstVisitor::TraverseDecl(clang::Decl *d)
|
||||
{
|
||||
if (d)
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << getIndentString() << d->getDeclKindName() << "Decl";
|
||||
if (clang::NamedDecl *namedDecl = clang::dyn_cast_or_null<clang::NamedDecl>(d))
|
||||
{
|
||||
stream << " [" << obfuscateName(namedDecl->getNameAsString()) << "]";
|
||||
}
|
||||
|
||||
ParseLocation loc = getParseLocation(d->getSourceRange());
|
||||
stream << " <" << loc.startLineNumber << ":" << loc.startColumnNumber << ", " << loc.endLineNumber << ":" << loc.endColumnNumber << ">";
|
||||
|
||||
LOG_INFO_STREAM_BARE(<< "Indexer - " << stream.str());
|
||||
|
||||
{
|
||||
ScopedSwitcher<unsigned int> switcher(m_indentation, m_indentation + 1);
|
||||
return base::TraverseDecl(d);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CxxVerboseAstVisitor::TraverseStmt(clang::Stmt *stmt)
|
||||
{
|
||||
if (stmt)
|
||||
{
|
||||
ParseLocation loc = getParseLocation(stmt->getSourceRange());
|
||||
LOG_INFO_STREAM_BARE(
|
||||
<< "Indexer - "
|
||||
<< getIndentString() << stmt->getStmtClassName()
|
||||
<< " <" << loc.startLineNumber << ":" << loc.startColumnNumber
|
||||
<< ", " << loc.endLineNumber << ":" << loc.endColumnNumber << ">"
|
||||
);
|
||||
|
||||
{
|
||||
ScopedSwitcher<unsigned int> switcher(m_indentation, m_indentation + 1);
|
||||
return base::TraverseStmt(stmt);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CxxVerboseAstVisitor::TraverseType(clang::QualType t)
|
||||
{
|
||||
LOG_INFO_STREAM_BARE(<< "Indexer - " << getIndentString() << t->getTypeClassName() << "Type");
|
||||
{
|
||||
ScopedSwitcher<unsigned int> switcher(m_indentation, m_indentation + 1);
|
||||
return base::TraverseType(t);
|
||||
}
|
||||
}
|
||||
|
||||
bool CxxVerboseAstVisitor::TraverseTypeLoc(clang::TypeLoc tl)
|
||||
{
|
||||
ParseLocation loc = getParseLocation(tl.getSourceRange());
|
||||
LOG_INFO_STREAM_BARE(
|
||||
<< "Indexer - "
|
||||
<< getIndentString() << typeLocClassToString(tl)
|
||||
<< "TypeLoc <" << loc.startLineNumber << ":" << loc.startColumnNumber
|
||||
<< ", " << loc.endLineNumber << ":" << loc.endColumnNumber << ">"
|
||||
);
|
||||
{
|
||||
ScopedSwitcher<unsigned int> switcher(m_indentation, m_indentation + 1);
|
||||
return base::TraverseTypeLoc(tl);
|
||||
}
|
||||
}
|
||||
|
||||
std::string CxxVerboseAstVisitor::getIndentString() const
|
||||
{
|
||||
std::string indentString = "";
|
||||
for (unsigned int i = 0; i < m_indentation; i++)
|
||||
{
|
||||
indentString += "| ";
|
||||
}
|
||||
return indentString;
|
||||
}
|
||||
|
||||
std::string CxxVerboseAstVisitor::obfuscateName(const std::string& name) const
|
||||
{
|
||||
if (name.length() <= 2)
|
||||
{
|
||||
return name;
|
||||
}
|
||||
return name.substr(0, 1) + ".." + name.substr(name.length() - 1);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#ifndef CXX_VERBOSE_AST_VISITOR_H
|
||||
#define CXX_VERBOSE_AST_VISITOR_H
|
||||
|
||||
#include "clang/AST/TypeLoc.h"
|
||||
|
||||
#include "data/parser/cxx/CxxAstVisitor.h"
|
||||
|
||||
class ParserClient;
|
||||
class FileRegister;
|
||||
|
||||
class CxxVerboseAstVisitor: public CxxAstVisitor
|
||||
{
|
||||
public:
|
||||
CxxVerboseAstVisitor(clang::ASTContext* context, clang::Preprocessor* preprocessor, ParserClient* client, FileRegister* fileRegister);
|
||||
virtual ~CxxVerboseAstVisitor();
|
||||
|
||||
private:
|
||||
typedef CxxAstVisitor base;
|
||||
|
||||
virtual bool TraverseDecl(clang::Decl *d);
|
||||
virtual bool TraverseStmt(clang::Stmt *stmt);
|
||||
virtual bool TraverseType(clang::QualType t);
|
||||
virtual bool TraverseTypeLoc(clang::TypeLoc tl);
|
||||
|
||||
std::string getIndentString() const;
|
||||
std::string obfuscateName(const std::string& name) const;
|
||||
|
||||
std::string typeLocClassToString(clang::TypeLoc tl) const
|
||||
{
|
||||
switch(tl.getTypeLocClass())
|
||||
{
|
||||
#define STRINGIFY(X) #X
|
||||
#define ABSTRACT_TYPE(Class, Base)
|
||||
#define TYPE(Class, Base) \
|
||||
case clang::TypeLoc::Class: \
|
||||
return STRINGIFY(Class);
|
||||
#include "clang/AST/TypeNodes.def"
|
||||
case clang::TypeLoc::TypeLocClass::Qualified:
|
||||
return "Qualified";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
unsigned int m_indentation;
|
||||
};
|
||||
|
||||
#endif // CXX_VERBOSE_AST_VISITOR_H
|
||||
@@ -55,10 +55,18 @@ void PreprocessorCallbacks::InclusionDirective(
|
||||
FilePath includedFilePath = FilePath(fileEntry->getName()).canonical();
|
||||
if (m_fileRegister->hasFilePath(includedFilePath))
|
||||
{
|
||||
m_client->onFileIncludeParsed(
|
||||
getParseLocation(fileNameRange.getAsRange()),
|
||||
m_fileRegister->getFileInfo(m_currentPath),
|
||||
m_fileRegister->getFileInfo(includedFilePath)
|
||||
|
||||
NameHierarchy referencedNameHierarchy;
|
||||
referencedNameHierarchy.push(std::make_shared<NameElement>(includedFilePath.fileName()));
|
||||
|
||||
NameHierarchy contextNameHierarchy;
|
||||
contextNameHierarchy.push(std::make_shared<NameElement>(m_currentPath.fileName()));
|
||||
|
||||
m_client->recordReference(
|
||||
REFERENCE_INCLUDE,
|
||||
referencedNameHierarchy,
|
||||
contextNameHierarchy,
|
||||
getParseLocation(fileNameRange.getAsRange())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -77,8 +85,12 @@ void PreprocessorCallbacks::MacroDefined(const clang::Token& macroNameToken, con
|
||||
NameHierarchy nameHierarchy;
|
||||
nameHierarchy.push(std::make_shared<NameElement>(macroNameToken.getIdentifierInfo()->getName().str()));
|
||||
|
||||
m_client->onMacroDefineParsed(
|
||||
getParseLocation(macroNameToken), nameHierarchy, getParseLocation(macroDirective->getMacroInfo()));
|
||||
m_client->recordSymbol(
|
||||
nameHierarchy,
|
||||
SYMBOL_MACRO,
|
||||
getParseLocation(macroNameToken),
|
||||
getParseLocation(macroDirective->getMacroInfo())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,10 +128,20 @@ void PreprocessorCallbacks::onMacroUsage(const clang::Token& macroNameToken)
|
||||
{
|
||||
if (!m_currentPath.empty())
|
||||
{
|
||||
NameHierarchy nameHierarchy;
|
||||
nameHierarchy.push(std::make_shared<NameElement>(macroNameToken.getIdentifierInfo()->getName().str()));
|
||||
const ParseLocation loc = getParseLocation(macroNameToken);
|
||||
|
||||
m_client->onMacroExpandParsed(getParseLocation(macroNameToken), nameHierarchy);
|
||||
NameHierarchy referencedNameHierarchy;
|
||||
referencedNameHierarchy.push(std::make_shared<NameElement>(macroNameToken.getIdentifierInfo()->getName().str()));
|
||||
|
||||
NameHierarchy contextNameHierarchy;
|
||||
contextNameHierarchy.push(std::make_shared<NameElement>(loc.filePath.fileName()));
|
||||
|
||||
m_client->recordReference(
|
||||
REFERENCE_MACRO_USAGE,
|
||||
referencedNameHierarchy,
|
||||
contextNameHierarchy,
|
||||
loc
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user