blob: 010ccd42a4a184a9ef3a9c9eb92cccae4e6c842f [file] [log] [blame]
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +00001//===--- IndexSymbol.cpp - Types and functions for indexing symbols -------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "clang/Index/IndexSymbol.h"
11#include "clang/AST/DeclCXX.h"
12#include "clang/AST/DeclObjC.h"
13#include "clang/AST/DeclTemplate.h"
Argyrios Kyrtzidisd5719082016-02-15 01:32:36 +000014#include "clang/AST/PrettyPrinter.h"
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000015
16using namespace clang;
17using namespace clang::index;
18
19SymbolInfo index::getSymbolInfo(const Decl *D) {
20 assert(D);
21 SymbolInfo Info;
22 Info.Kind = SymbolKind::Unknown;
23 Info.TemplateKind = SymbolCXXTemplateKind::NonTemplate;
24 Info.Lang = SymbolLanguage::C;
25
26 if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
27 switch (TD->getTagKind()) {
28 case TTK_Struct:
29 Info.Kind = SymbolKind::Struct; break;
30 case TTK_Union:
31 Info.Kind = SymbolKind::Union; break;
32 case TTK_Class:
33 Info.Kind = SymbolKind::CXXClass;
34 Info.Lang = SymbolLanguage::CXX;
35 break;
36 case TTK_Interface:
37 Info.Kind = SymbolKind::CXXInterface;
38 Info.Lang = SymbolLanguage::CXX;
39 break;
40 case TTK_Enum:
41 Info.Kind = SymbolKind::Enum; break;
42 }
43
44 if (const CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(D))
45 if (!CXXRec->isCLike())
46 Info.Lang = SymbolLanguage::CXX;
47
48 if (isa<ClassTemplatePartialSpecializationDecl>(D)) {
49 Info.TemplateKind = SymbolCXXTemplateKind::TemplatePartialSpecialization;
50 } else if (isa<ClassTemplateSpecializationDecl>(D)) {
51 Info.TemplateKind = SymbolCXXTemplateKind::TemplateSpecialization;
52 }
53
54 } else {
55 switch (D->getKind()) {
56 case Decl::Typedef:
57 Info.Kind = SymbolKind::Typedef; break;
58 case Decl::Function:
59 Info.Kind = SymbolKind::Function;
60 break;
61 case Decl::ParmVar:
62 Info.Kind = SymbolKind::Variable;
63 break;
64 case Decl::Var:
65 Info.Kind = SymbolKind::Variable;
66 if (isa<CXXRecordDecl>(D->getDeclContext())) {
67 Info.Kind = SymbolKind::CXXStaticVariable;
68 Info.Lang = SymbolLanguage::CXX;
69 }
70 break;
71 case Decl::Field:
72 Info.Kind = SymbolKind::Field;
73 if (const CXXRecordDecl *
74 CXXRec = dyn_cast<CXXRecordDecl>(D->getDeclContext())) {
75 if (!CXXRec->isCLike())
76 Info.Lang = SymbolLanguage::CXX;
77 }
78 break;
79 case Decl::EnumConstant:
80 Info.Kind = SymbolKind::EnumConstant; break;
81 case Decl::ObjCInterface:
82 case Decl::ObjCImplementation:
83 Info.Kind = SymbolKind::ObjCClass;
84 Info.Lang = SymbolLanguage::ObjC;
85 break;
86 case Decl::ObjCProtocol:
87 Info.Kind = SymbolKind::ObjCProtocol;
88 Info.Lang = SymbolLanguage::ObjC;
89 break;
90 case Decl::ObjCCategory:
91 case Decl::ObjCCategoryImpl:
92 Info.Kind = SymbolKind::ObjCCategory;
93 Info.Lang = SymbolLanguage::ObjC;
94 break;
95 case Decl::ObjCMethod:
96 if (cast<ObjCMethodDecl>(D)->isInstanceMethod())
97 Info.Kind = SymbolKind::ObjCInstanceMethod;
98 else
99 Info.Kind = SymbolKind::ObjCClassMethod;
100 Info.Lang = SymbolLanguage::ObjC;
101 break;
102 case Decl::ObjCProperty:
103 Info.Kind = SymbolKind::ObjCProperty;
104 Info.Lang = SymbolLanguage::ObjC;
105 break;
106 case Decl::ObjCIvar:
107 Info.Kind = SymbolKind::ObjCIvar;
108 Info.Lang = SymbolLanguage::ObjC;
109 break;
110 case Decl::Namespace:
111 Info.Kind = SymbolKind::CXXNamespace;
112 Info.Lang = SymbolLanguage::CXX;
113 break;
114 case Decl::NamespaceAlias:
115 Info.Kind = SymbolKind::CXXNamespaceAlias;
116 Info.Lang = SymbolLanguage::CXX;
117 break;
118 case Decl::CXXConstructor:
119 Info.Kind = SymbolKind::CXXConstructor;
120 Info.Lang = SymbolLanguage::CXX;
121 break;
122 case Decl::CXXDestructor:
123 Info.Kind = SymbolKind::CXXDestructor;
124 Info.Lang = SymbolLanguage::CXX;
125 break;
126 case Decl::CXXConversion:
127 Info.Kind = SymbolKind::CXXConversionFunction;
128 Info.Lang = SymbolLanguage::CXX;
129 break;
130 case Decl::CXXMethod: {
131 const CXXMethodDecl *MD = cast<CXXMethodDecl>(D);
132 if (MD->isStatic())
133 Info.Kind = SymbolKind::CXXStaticMethod;
134 else
135 Info.Kind = SymbolKind::CXXInstanceMethod;
136 Info.Lang = SymbolLanguage::CXX;
137 break;
138 }
139 case Decl::ClassTemplate:
140 Info.Kind = SymbolKind::CXXClass;
141 Info.TemplateKind = SymbolCXXTemplateKind::Template;
142 break;
143 case Decl::FunctionTemplate:
144 Info.Kind = SymbolKind::Function;
145 Info.TemplateKind = SymbolCXXTemplateKind::Template;
146 if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(
147 cast<FunctionTemplateDecl>(D)->getTemplatedDecl())) {
148 if (isa<CXXConstructorDecl>(MD))
149 Info.Kind = SymbolKind::CXXConstructor;
150 else if (isa<CXXDestructorDecl>(MD))
151 Info.Kind = SymbolKind::CXXDestructor;
152 else if (isa<CXXConversionDecl>(MD))
153 Info.Kind = SymbolKind::CXXConversionFunction;
154 else {
155 if (MD->isStatic())
156 Info.Kind = SymbolKind::CXXStaticMethod;
157 else
158 Info.Kind = SymbolKind::CXXInstanceMethod;
159 }
160 }
161 break;
162 case Decl::TypeAliasTemplate:
163 Info.Kind = SymbolKind::CXXTypeAlias;
164 Info.TemplateKind = SymbolCXXTemplateKind::Template;
165 break;
166 case Decl::TypeAlias:
167 Info.Kind = SymbolKind::CXXTypeAlias;
168 Info.Lang = SymbolLanguage::CXX;
169 break;
170 default:
171 break;
172 }
173 }
174
175 if (Info.Kind == SymbolKind::Unknown)
176 return Info;
177
178 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
179 if (FD->getTemplatedKind() ==
180 FunctionDecl::TK_FunctionTemplateSpecialization)
181 Info.TemplateKind = SymbolCXXTemplateKind::TemplateSpecialization;
182 }
183
184 if (Info.TemplateKind != SymbolCXXTemplateKind::NonTemplate)
185 Info.Lang = SymbolLanguage::CXX;
186
187 return Info;
188}
Argyrios Kyrtzidis6fdcb9c2016-02-14 06:39:11 +0000189
190void index::applyForEachSymbolRole(SymbolRoleSet Roles,
191 llvm::function_ref<void(SymbolRole)> Fn) {
192#define APPLY_FOR_ROLE(Role) \
193 if (Roles & (unsigned)SymbolRole::Role) \
194 Fn(SymbolRole::Role)
195
196 APPLY_FOR_ROLE(Declaration);
197 APPLY_FOR_ROLE(Definition);
198 APPLY_FOR_ROLE(Reference);
199 APPLY_FOR_ROLE(Read);
200 APPLY_FOR_ROLE(Write);
201 APPLY_FOR_ROLE(Call);
202 APPLY_FOR_ROLE(Dynamic);
203 APPLY_FOR_ROLE(AddressOf);
204 APPLY_FOR_ROLE(Implicit);
205 APPLY_FOR_ROLE(RelationChildOf);
206 APPLY_FOR_ROLE(RelationBaseOf);
207 APPLY_FOR_ROLE(RelationOverrideOf);
208 APPLY_FOR_ROLE(RelationReceivedBy);
209
210#undef APPLY_FOR_ROLE
211}
212
213void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) {
214 bool VisitedOnce = false;
215 applyForEachSymbolRole(Roles, [&](SymbolRole Role) {
216 if (VisitedOnce)
217 OS << '/';
218 else
219 VisitedOnce = true;
220 switch (Role) {
221 case SymbolRole::Declaration: OS << "Decl"; break;
222 case SymbolRole::Definition: OS << "Def"; break;
223 case SymbolRole::Reference: OS << "Ref"; break;
224 case SymbolRole::Read: OS << "Read"; break;
225 case SymbolRole::Write: OS << "Writ"; break;
226 case SymbolRole::Call: OS << "Call"; break;
227 case SymbolRole::Dynamic: OS << "Dyn"; break;
228 case SymbolRole::AddressOf: OS << "Addr"; break;
229 case SymbolRole::Implicit: OS << "Impl"; break;
230 case SymbolRole::RelationChildOf: OS << "RelChild"; break;
231 case SymbolRole::RelationBaseOf: OS << "RelBase"; break;
232 case SymbolRole::RelationOverrideOf: OS << "RelOver"; break;
233 case SymbolRole::RelationReceivedBy: OS << "RelRec"; break;
234 }
235 });
236}
237
Argyrios Kyrtzidisd5719082016-02-15 01:32:36 +0000238bool index::printSymbolName(const Decl *D, const LangOptions &LO,
239 raw_ostream &OS) {
240 if (auto *ND = dyn_cast<NamedDecl>(D)) {
241 PrintingPolicy Policy(LO);
242 // Forward references can have different template argument names. Suppress
243 // the template argument names in constructors to make their name more
244 // stable.
245 Policy.SuppressTemplateArgsInCXXConstructors = true;
246 DeclarationName DeclName = ND->getDeclName();
247 if (DeclName.isEmpty())
248 return true;
249 DeclName.print(OS, Policy);
250 return false;
251 } else {
252 return true;
253 }
254}
255
Argyrios Kyrtzidis6fdcb9c2016-02-14 06:39:11 +0000256StringRef index::getSymbolKindString(SymbolKind K) {
257 switch (K) {
258 case SymbolKind::Unknown: return "<unknown>";
259 case SymbolKind::Module: return "module";
260 case SymbolKind::Macro: return "macro";
261 case SymbolKind::Enum: return "enum";
262 case SymbolKind::Struct: return "struct";
263 case SymbolKind::Union: return "union";
264 case SymbolKind::Typedef: return "typedef";
265 case SymbolKind::Function: return "function";
266 case SymbolKind::Variable: return "variable";
267 case SymbolKind::Field: return "field";
268 case SymbolKind::EnumConstant: return "enumerator";
269 case SymbolKind::ObjCClass: return "objc-class";
270 case SymbolKind::ObjCProtocol: return "objc-protocol";
271 case SymbolKind::ObjCCategory: return "objc-category";
272 case SymbolKind::ObjCInstanceMethod: return "objc-instance-method";
273 case SymbolKind::ObjCClassMethod: return "objc-class-method";
274 case SymbolKind::ObjCProperty: return "objc-property";
275 case SymbolKind::ObjCIvar: return "objc-ivar";
276 case SymbolKind::CXXClass: return "c++-class";
277 case SymbolKind::CXXNamespace: return "namespace";
278 case SymbolKind::CXXNamespaceAlias: return "namespace-alias";
279 case SymbolKind::CXXStaticVariable: return "c++-static-var";
280 case SymbolKind::CXXStaticMethod: return "c++-static-method";
281 case SymbolKind::CXXInstanceMethod: return "c++-instance-method";
282 case SymbolKind::CXXConstructor: return "constructor";
283 case SymbolKind::CXXDestructor: return "destructor";
284 case SymbolKind::CXXConversionFunction: return "coversion-func";
285 case SymbolKind::CXXTypeAlias: return "type-alias";
286 case SymbolKind::CXXInterface: return "c++-__interface";
287 }
Saleem Abdulrasool9b0ac332016-02-15 00:36:52 +0000288 llvm_unreachable("invalid symbol kind");
Argyrios Kyrtzidis6fdcb9c2016-02-14 06:39:11 +0000289}
290
291StringRef index::getTemplateKindStr(SymbolCXXTemplateKind TK) {
292 switch (TK) {
293 case SymbolCXXTemplateKind::NonTemplate: return "NT";
294 case SymbolCXXTemplateKind::Template : return "T";
295 case SymbolCXXTemplateKind::TemplatePartialSpecialization : return "TPS";
296 case SymbolCXXTemplateKind::TemplateSpecialization: return "TS";
297 }
Saleem Abdulrasool9b0ac332016-02-15 00:36:52 +0000298 llvm_unreachable("invalid template kind");
Argyrios Kyrtzidis6fdcb9c2016-02-14 06:39:11 +0000299}
300
301StringRef index::getSymbolLanguageString(SymbolLanguage K) {
302 switch (K) {
303 case SymbolLanguage::C: return "C";
304 case SymbolLanguage::ObjC: return "ObjC";
305 case SymbolLanguage::CXX: return "C++";
306 }
Saleem Abdulrasool9b0ac332016-02-15 00:36:52 +0000307 llvm_unreachable("invalid symbol language kind");
Argyrios Kyrtzidis6fdcb9c2016-02-14 06:39:11 +0000308}