blob: 097aaf0721f30b3150731975052af5d4d2e9022c [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;
Argyrios Kyrtzidisf2142cb2016-04-22 07:21:04 +000023 Info.SubKinds = SymbolSubKindSet();
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000024 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:
Ben Langmuir443913f2016-03-25 17:01:59 +000033 Info.Kind = SymbolKind::Class;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000034 Info.Lang = SymbolLanguage::CXX;
35 break;
36 case TTK_Interface:
Ben Langmuir443913f2016-03-25 17:01:59 +000037 Info.Kind = SymbolKind::Protocol;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000038 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)) {
Argyrios Kyrtzidisf2142cb2016-04-22 07:21:04 +000049 Info.SubKinds |= (unsigned)SymbolSubKind::Generic;
50 Info.SubKinds |= (unsigned)SymbolSubKind::TemplatePartialSpecialization;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000051 } else if (isa<ClassTemplateSpecializationDecl>(D)) {
Argyrios Kyrtzidisf2142cb2016-04-22 07:21:04 +000052 Info.SubKinds |= (unsigned)SymbolSubKind::Generic;
53 Info.SubKinds |= (unsigned)SymbolSubKind::TemplateSpecialization;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000054 }
55
56 } else {
57 switch (D->getKind()) {
Argyrios Kyrtzidis113387e2016-02-29 07:56:07 +000058 case Decl::Import:
59 Info.Kind = SymbolKind::Module;
60 break;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000061 case Decl::Typedef:
Ben Langmuir443913f2016-03-25 17:01:59 +000062 Info.Kind = SymbolKind::TypeAlias; break; // Lang = C
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000063 case Decl::Function:
64 Info.Kind = SymbolKind::Function;
65 break;
66 case Decl::ParmVar:
67 Info.Kind = SymbolKind::Variable;
68 break;
69 case Decl::Var:
70 Info.Kind = SymbolKind::Variable;
71 if (isa<CXXRecordDecl>(D->getDeclContext())) {
Ben Langmuir443913f2016-03-25 17:01:59 +000072 Info.Kind = SymbolKind::StaticProperty;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000073 Info.Lang = SymbolLanguage::CXX;
74 }
75 break;
76 case Decl::Field:
77 Info.Kind = SymbolKind::Field;
78 if (const CXXRecordDecl *
79 CXXRec = dyn_cast<CXXRecordDecl>(D->getDeclContext())) {
80 if (!CXXRec->isCLike())
81 Info.Lang = SymbolLanguage::CXX;
82 }
83 break;
84 case Decl::EnumConstant:
85 Info.Kind = SymbolKind::EnumConstant; break;
86 case Decl::ObjCInterface:
87 case Decl::ObjCImplementation:
Ben Langmuir443913f2016-03-25 17:01:59 +000088 Info.Kind = SymbolKind::Class;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000089 Info.Lang = SymbolLanguage::ObjC;
90 break;
91 case Decl::ObjCProtocol:
Ben Langmuir443913f2016-03-25 17:01:59 +000092 Info.Kind = SymbolKind::Protocol;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000093 Info.Lang = SymbolLanguage::ObjC;
94 break;
95 case Decl::ObjCCategory:
96 case Decl::ObjCCategoryImpl:
Ben Langmuir443913f2016-03-25 17:01:59 +000097 Info.Kind = SymbolKind::Extension;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000098 Info.Lang = SymbolLanguage::ObjC;
99 break;
100 case Decl::ObjCMethod:
101 if (cast<ObjCMethodDecl>(D)->isInstanceMethod())
Ben Langmuir443913f2016-03-25 17:01:59 +0000102 Info.Kind = SymbolKind::InstanceMethod;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000103 else
Ben Langmuir443913f2016-03-25 17:01:59 +0000104 Info.Kind = SymbolKind::ClassMethod;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000105 Info.Lang = SymbolLanguage::ObjC;
106 break;
107 case Decl::ObjCProperty:
Ben Langmuir443913f2016-03-25 17:01:59 +0000108 Info.Kind = SymbolKind::InstanceProperty;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000109 Info.Lang = SymbolLanguage::ObjC;
110 break;
111 case Decl::ObjCIvar:
Ben Langmuir443913f2016-03-25 17:01:59 +0000112 Info.Kind = SymbolKind::Field;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000113 Info.Lang = SymbolLanguage::ObjC;
114 break;
115 case Decl::Namespace:
Ben Langmuir443913f2016-03-25 17:01:59 +0000116 Info.Kind = SymbolKind::Namespace;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000117 Info.Lang = SymbolLanguage::CXX;
118 break;
119 case Decl::NamespaceAlias:
Ben Langmuir443913f2016-03-25 17:01:59 +0000120 Info.Kind = SymbolKind::NamespaceAlias;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000121 Info.Lang = SymbolLanguage::CXX;
122 break;
123 case Decl::CXXConstructor:
Ben Langmuir443913f2016-03-25 17:01:59 +0000124 Info.Kind = SymbolKind::Constructor;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000125 Info.Lang = SymbolLanguage::CXX;
126 break;
127 case Decl::CXXDestructor:
Ben Langmuir443913f2016-03-25 17:01:59 +0000128 Info.Kind = SymbolKind::Destructor;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000129 Info.Lang = SymbolLanguage::CXX;
130 break;
131 case Decl::CXXConversion:
Ben Langmuir443913f2016-03-25 17:01:59 +0000132 Info.Kind = SymbolKind::ConversionFunction;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000133 Info.Lang = SymbolLanguage::CXX;
134 break;
135 case Decl::CXXMethod: {
136 const CXXMethodDecl *MD = cast<CXXMethodDecl>(D);
137 if (MD->isStatic())
Ben Langmuir443913f2016-03-25 17:01:59 +0000138 Info.Kind = SymbolKind::StaticMethod;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000139 else
Ben Langmuir443913f2016-03-25 17:01:59 +0000140 Info.Kind = SymbolKind::InstanceMethod;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000141 Info.Lang = SymbolLanguage::CXX;
142 break;
143 }
144 case Decl::ClassTemplate:
Ben Langmuir443913f2016-03-25 17:01:59 +0000145 Info.Kind = SymbolKind::Class;
Argyrios Kyrtzidisf2142cb2016-04-22 07:21:04 +0000146 Info.SubKinds |= (unsigned)SymbolSubKind::Generic;
Ben Langmuir443913f2016-03-25 17:01:59 +0000147 Info.Lang = SymbolLanguage::CXX;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000148 break;
149 case Decl::FunctionTemplate:
150 Info.Kind = SymbolKind::Function;
Argyrios Kyrtzidisf2142cb2016-04-22 07:21:04 +0000151 Info.SubKinds |= (unsigned)SymbolSubKind::Generic;
Ben Langmuir443913f2016-03-25 17:01:59 +0000152 Info.Lang = SymbolLanguage::CXX;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000153 if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(
154 cast<FunctionTemplateDecl>(D)->getTemplatedDecl())) {
155 if (isa<CXXConstructorDecl>(MD))
Ben Langmuir443913f2016-03-25 17:01:59 +0000156 Info.Kind = SymbolKind::Constructor;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000157 else if (isa<CXXDestructorDecl>(MD))
Ben Langmuir443913f2016-03-25 17:01:59 +0000158 Info.Kind = SymbolKind::Destructor;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000159 else if (isa<CXXConversionDecl>(MD))
Ben Langmuir443913f2016-03-25 17:01:59 +0000160 Info.Kind = SymbolKind::ConversionFunction;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000161 else {
162 if (MD->isStatic())
Ben Langmuir443913f2016-03-25 17:01:59 +0000163 Info.Kind = SymbolKind::StaticMethod;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000164 else
Ben Langmuir443913f2016-03-25 17:01:59 +0000165 Info.Kind = SymbolKind::InstanceMethod;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000166 }
167 }
168 break;
169 case Decl::TypeAliasTemplate:
Ben Langmuir443913f2016-03-25 17:01:59 +0000170 Info.Kind = SymbolKind::TypeAlias;
171 Info.Lang = SymbolLanguage::CXX;
Argyrios Kyrtzidisf2142cb2016-04-22 07:21:04 +0000172 Info.SubKinds |= (unsigned)SymbolSubKind::Generic;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000173 break;
174 case Decl::TypeAlias:
Ben Langmuir443913f2016-03-25 17:01:59 +0000175 Info.Kind = SymbolKind::TypeAlias;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000176 Info.Lang = SymbolLanguage::CXX;
177 break;
178 default:
179 break;
180 }
181 }
182
183 if (Info.Kind == SymbolKind::Unknown)
184 return Info;
185
186 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
187 if (FD->getTemplatedKind() ==
Argyrios Kyrtzidisf2142cb2016-04-22 07:21:04 +0000188 FunctionDecl::TK_FunctionTemplateSpecialization) {
189 Info.SubKinds |= (unsigned)SymbolSubKind::Generic;
190 Info.SubKinds |= (unsigned)SymbolSubKind::TemplateSpecialization;
191 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000192 }
193
Argyrios Kyrtzidisf2142cb2016-04-22 07:21:04 +0000194 if (Info.SubKinds & (unsigned)SymbolSubKind::Generic)
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000195 Info.Lang = SymbolLanguage::CXX;
196
197 return Info;
198}
Argyrios Kyrtzidis6fdcb9c2016-02-14 06:39:11 +0000199
200void index::applyForEachSymbolRole(SymbolRoleSet Roles,
201 llvm::function_ref<void(SymbolRole)> Fn) {
202#define APPLY_FOR_ROLE(Role) \
203 if (Roles & (unsigned)SymbolRole::Role) \
204 Fn(SymbolRole::Role)
205
206 APPLY_FOR_ROLE(Declaration);
207 APPLY_FOR_ROLE(Definition);
208 APPLY_FOR_ROLE(Reference);
209 APPLY_FOR_ROLE(Read);
210 APPLY_FOR_ROLE(Write);
211 APPLY_FOR_ROLE(Call);
212 APPLY_FOR_ROLE(Dynamic);
213 APPLY_FOR_ROLE(AddressOf);
214 APPLY_FOR_ROLE(Implicit);
215 APPLY_FOR_ROLE(RelationChildOf);
216 APPLY_FOR_ROLE(RelationBaseOf);
217 APPLY_FOR_ROLE(RelationOverrideOf);
218 APPLY_FOR_ROLE(RelationReceivedBy);
Argyrios Kyrtzidisa8b51c12016-02-29 07:56:00 +0000219 APPLY_FOR_ROLE(RelationCalledBy);
Argyrios Kyrtzidis6fdcb9c2016-02-14 06:39:11 +0000220
221#undef APPLY_FOR_ROLE
222}
223
224void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) {
225 bool VisitedOnce = false;
226 applyForEachSymbolRole(Roles, [&](SymbolRole Role) {
227 if (VisitedOnce)
Argyrios Kyrtzidisd97ec182016-02-29 07:55:51 +0000228 OS << ',';
Argyrios Kyrtzidis6fdcb9c2016-02-14 06:39:11 +0000229 else
230 VisitedOnce = true;
231 switch (Role) {
232 case SymbolRole::Declaration: OS << "Decl"; break;
233 case SymbolRole::Definition: OS << "Def"; break;
234 case SymbolRole::Reference: OS << "Ref"; break;
235 case SymbolRole::Read: OS << "Read"; break;
236 case SymbolRole::Write: OS << "Writ"; break;
237 case SymbolRole::Call: OS << "Call"; break;
238 case SymbolRole::Dynamic: OS << "Dyn"; break;
239 case SymbolRole::AddressOf: OS << "Addr"; break;
240 case SymbolRole::Implicit: OS << "Impl"; break;
241 case SymbolRole::RelationChildOf: OS << "RelChild"; break;
242 case SymbolRole::RelationBaseOf: OS << "RelBase"; break;
243 case SymbolRole::RelationOverrideOf: OS << "RelOver"; break;
244 case SymbolRole::RelationReceivedBy: OS << "RelRec"; break;
Argyrios Kyrtzidisa8b51c12016-02-29 07:56:00 +0000245 case SymbolRole::RelationCalledBy: OS << "RelCall"; break;
Argyrios Kyrtzidis6fdcb9c2016-02-14 06:39:11 +0000246 }
247 });
248}
249
Argyrios Kyrtzidisd5719082016-02-15 01:32:36 +0000250bool index::printSymbolName(const Decl *D, const LangOptions &LO,
251 raw_ostream &OS) {
252 if (auto *ND = dyn_cast<NamedDecl>(D)) {
253 PrintingPolicy Policy(LO);
254 // Forward references can have different template argument names. Suppress
255 // the template argument names in constructors to make their name more
256 // stable.
257 Policy.SuppressTemplateArgsInCXXConstructors = true;
258 DeclarationName DeclName = ND->getDeclName();
259 if (DeclName.isEmpty())
260 return true;
261 DeclName.print(OS, Policy);
262 return false;
263 } else {
264 return true;
265 }
266}
267
Argyrios Kyrtzidis6fdcb9c2016-02-14 06:39:11 +0000268StringRef index::getSymbolKindString(SymbolKind K) {
269 switch (K) {
270 case SymbolKind::Unknown: return "<unknown>";
271 case SymbolKind::Module: return "module";
Ben Langmuir443913f2016-03-25 17:01:59 +0000272 case SymbolKind::Namespace: return "namespace";
273 case SymbolKind::NamespaceAlias: return "namespace-alias";
Argyrios Kyrtzidis6fdcb9c2016-02-14 06:39:11 +0000274 case SymbolKind::Macro: return "macro";
275 case SymbolKind::Enum: return "enum";
276 case SymbolKind::Struct: return "struct";
Ben Langmuir443913f2016-03-25 17:01:59 +0000277 case SymbolKind::Class: return "class";
278 case SymbolKind::Protocol: return "protocol";
279 case SymbolKind::Extension: return "extension";
Argyrios Kyrtzidis6fdcb9c2016-02-14 06:39:11 +0000280 case SymbolKind::Union: return "union";
Ben Langmuir443913f2016-03-25 17:01:59 +0000281 case SymbolKind::TypeAlias: return "type-alias";
Argyrios Kyrtzidis6fdcb9c2016-02-14 06:39:11 +0000282 case SymbolKind::Function: return "function";
283 case SymbolKind::Variable: return "variable";
284 case SymbolKind::Field: return "field";
285 case SymbolKind::EnumConstant: return "enumerator";
Ben Langmuir443913f2016-03-25 17:01:59 +0000286 case SymbolKind::InstanceMethod: return "instance-method";
287 case SymbolKind::ClassMethod: return "class-method";
288 case SymbolKind::StaticMethod: return "static-method";
289 case SymbolKind::InstanceProperty: return "instance-property";
290 case SymbolKind::ClassProperty: return "class-property";
291 case SymbolKind::StaticProperty: return "static-property";
292 case SymbolKind::Constructor: return "constructor";
293 case SymbolKind::Destructor: return "destructor";
294 case SymbolKind::ConversionFunction: return "coversion-func";
Argyrios Kyrtzidis6fdcb9c2016-02-14 06:39:11 +0000295 }
Saleem Abdulrasool9b0ac332016-02-15 00:36:52 +0000296 llvm_unreachable("invalid symbol kind");
Argyrios Kyrtzidis6fdcb9c2016-02-14 06:39:11 +0000297}
298
Argyrios Kyrtzidis6fdcb9c2016-02-14 06:39:11 +0000299StringRef index::getSymbolLanguageString(SymbolLanguage K) {
300 switch (K) {
301 case SymbolLanguage::C: return "C";
302 case SymbolLanguage::ObjC: return "ObjC";
303 case SymbolLanguage::CXX: return "C++";
304 }
Saleem Abdulrasool9b0ac332016-02-15 00:36:52 +0000305 llvm_unreachable("invalid symbol language kind");
Argyrios Kyrtzidis6fdcb9c2016-02-14 06:39:11 +0000306}
Argyrios Kyrtzidisf2142cb2016-04-22 07:21:04 +0000307
308void index::applyForEachSymbolSubKind(SymbolSubKindSet SubKinds,
309 llvm::function_ref<void(SymbolSubKind)> Fn) {
310#define APPLY_FOR_SUBKIND(K) \
311 if (SubKinds & (unsigned)SymbolSubKind::K) \
312 Fn(SymbolSubKind::K)
313
314 APPLY_FOR_SUBKIND(Generic);
315 APPLY_FOR_SUBKIND(TemplatePartialSpecialization);
316 APPLY_FOR_SUBKIND(TemplateSpecialization);
317
318#undef APPLY_FOR_SUBKIND
319}
320
321void index::printSymbolSubKinds(SymbolSubKindSet SubKinds, raw_ostream &OS) {
322 bool VisitedOnce = false;
323 applyForEachSymbolSubKind(SubKinds, [&](SymbolSubKind SubKind) {
324 if (VisitedOnce)
325 OS << ',';
326 else
327 VisitedOnce = true;
328 switch (SubKind) {
329 case SymbolSubKind::Generic: OS << "Gen"; break;
330 case SymbolSubKind::TemplatePartialSpecialization: OS << "TPS"; break;
331 case SymbolSubKind::TemplateSpecialization: OS << "TS"; break;
332 }
333 });
334}