-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathIndexer.cpp
More file actions
158 lines (143 loc) · 5.08 KB
/
Copy pathIndexer.cpp
File metadata and controls
158 lines (143 loc) · 5.08 KB
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
#include "clang/Tooling/Tooling.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include <iostream>
#include <vector>
#include <time.h>
#include "ClangScope.h"
#include "Indexer.h"
using namespace clang::tooling;
extern llvm::cl::opt<unsigned> LogLevel;
// FIXME: Don't want to have to grab this global Index pointer.
extern Indexer *Index;
IdentifierType GetIdentifierForDecl(clang::NamedDecl *d) {
if (clang::isa<clang::VarDecl>(d) || clang::isa<clang::FieldDecl>(d))
return Variable;
if (clang::isa<clang::FunctionDecl>(d) || clang::isa<clang::CXXMethodDecl>(d))
return Function;
if (clang::isa<clang::NamespaceDecl>(d))
return Namespace;
if (clang::isa<clang::TypeDecl>(d))
return Type;
if (clang::isa<clang::TypedefDecl>(d))
return Typedef;
if (clang::isa<clang::EnumConstantDecl>(d))
return Enum;
return IdentifierType_Max;
}
template <typename T> static ReferenceType DeclarationOrDefinition(T *d) {
return (d->isThisDeclarationADefinition()) ? Definition : Declaration;
}
struct IndexASTVisitor : clang::RecursiveASTVisitor<IndexASTVisitor> {
public:
IndexASTVisitor() {}
bool VisitVarDecl(clang::VarDecl *d) {
if (d->isLocalVarDecl() || clang::isa<clang::ParmVarDecl>(d))
return true; // Only want global decls
LOG(3, "VarDecl: " << d->getNameAsString() << std::endl);
Index->CrossRef.AddReference(d, DeclarationOrDefinition(d), Variable);
return true;
}
bool VisitFunctionDecl(clang::FunctionDecl *d) {
LOG(3, "FunctionDecl: " << d->getNameAsString() << std::endl);
Index->CrossRef.AddReference(d, DeclarationOrDefinition(d), Function);
return true;
}
bool VisitNamespaceDecl(clang::NamespaceDecl *d) {
LOG(3, "NamespaceDecl: " << d->getNameAsString() << std::endl);
Index->CrossRef.AddReference(d, Declaration, Namespace);
return true;
}
bool VisitTagDecl(clang::TagDecl *d) {
LOG(3, "TagDecl: " << d->getNameAsString() << std::endl);
Index->CrossRef.AddReference(d, DeclarationOrDefinition(d), Typedef);
return true;
}
bool VisitEnumConstantDecl(clang::EnumConstantDecl *d) {
LOG(3, "EnumConstantDecl: " << d->getNameAsString() << std::endl);
Index->CrossRef.AddReference(d, Definition, Enum);
return true;
}
bool VisitMemberExpr(clang::MemberExpr *e) {
clang::NamedDecl *d = e->getFoundDecl().getDecl();
if (clang::VarDecl *v = clang::dyn_cast<clang::VarDecl>(d)) {
if (v->isLocalVarDecl())
return true;
else if (clang::isa<clang::ParmVarDecl>(d))
return true;
}
IdentifierType Id = GetIdentifierForDecl(d);
if (Id == IdentifierType_Max)
return true;
LOG(3, "MemberRefExpr: " << d->getNameAsString() << std::endl);
Index->CrossRef.AddReference(d, e, Use, Id);
return true;
}
bool VisitDeclRefExpr(clang::DeclRefExpr *e) {
clang::NamedDecl *d = e->getDecl();
if (clang::VarDecl *v = clang::dyn_cast<clang::VarDecl>(d)) {
if (v->isLocalVarDecl())
return true;
else if (clang::isa<clang::ParmVarDecl>(d))
return true;
}
IdentifierType Id = GetIdentifierForDecl(d);
if (Id == IdentifierType_Max)
return true;
LOG(3, "DeclRefExpr: " << d->getNameAsString() << std::endl);
Index->CrossRef.AddReference(d, e, Use, Id);
return true;
}
};
class IndexASTConsumer : public clang::ASTConsumer {
public:
IndexASTConsumer(clang::CompilerInstance &ci) {}
virtual void Initialize(clang::ASTContext &Ctx) {}
virtual void HandleTranslationUnit(clang::ASTContext &Ctx) {
IndexASTVisitor v;
Index->CrossRef.SetSourceManager(&Ctx.getSourceManager());
v.TraverseDecl(Ctx.getTranslationUnitDecl());
}
};
class IndexASTAction : public clang::ASTFrontendAction {
public:
virtual clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &CI,
llvm::StringRef InFile) {
std::string FileName = InFile.str();
if (Index->CrossRef.SeenFile(FileName))
return 0;
std::string CmdLine; // The constructed commandline from the compilationdb
for (auto C : Index->CompilationDb->getCompileCommands(FileName))
for (auto S : C.CommandLine)
CmdLine += S + " ";
Index->CrossRef.StartNewFile(FileName, CmdLine);
return new IndexASTConsumer(CI);
}
};
Indexer::Indexer(std::string Path, CrossReference &CrossRef)
: CompilationDbPath(Path), CrossRef(CrossRef) {}
Indexer::~Indexer() {
delete CompilationDb;
}
// Opens the compilation database, and gets the file list.
bool Indexer::OpenCompilationDatabase() {
std::string Err;
CompilationDb =
CompilationDatabase::loadFromDirectory(CompilationDbPath, Err);
if (!CompilationDb) {
std::cerr << Err;
return false;
}
Files = CompilationDb->getAllFiles();
return true;
}
bool Indexer::Run() {
if (!OpenCompilationDatabase()) return false;
ClangTool Tool(*CompilationDb, Files);
bool result = Tool.run(newFrontendActionFactory<IndexASTAction>());
return result;
}