1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | #include "clang/Index/IndexSymbol.h" |
10 | #include "clang/AST/DeclCXX.h" |
11 | #include "clang/AST/DeclObjC.h" |
12 | #include "clang/AST/DeclTemplate.h" |
13 | #include "clang/AST/PrettyPrinter.h" |
14 | #include "clang/Lex/MacroInfo.h" |
15 | |
16 | using namespace clang; |
17 | using namespace clang::index; |
18 | |
19 | |
20 | static bool isUnitTestCase(const ObjCInterfaceDecl *D) { |
21 | if (!D) |
22 | return false; |
23 | while (const ObjCInterfaceDecl *SuperD = D->getSuperClass()) { |
24 | if (SuperD->getName() == "XCTestCase") |
25 | return true; |
26 | D = SuperD; |
27 | } |
28 | return false; |
29 | } |
30 | |
31 | |
32 | |
33 | static bool isUnitTest(const ObjCMethodDecl *D) { |
34 | if (!D->parameters().empty()) |
35 | return false; |
36 | if (!D->getReturnType()->isVoidType()) |
37 | return false; |
38 | if (!D->getSelector().getNameForSlot(0).startswith("test")) |
39 | return false; |
40 | return isUnitTestCase(D->getClassInterface()); |
41 | } |
42 | |
43 | static void checkForIBOutlets(const Decl *D, SymbolPropertySet &PropSet) { |
44 | if (D->hasAttr<IBOutletAttr>()) { |
45 | PropSet |= (SymbolPropertySet)SymbolProperty::IBAnnotated; |
46 | } else if (D->hasAttr<IBOutletCollectionAttr>()) { |
47 | PropSet |= (SymbolPropertySet)SymbolProperty::IBAnnotated; |
48 | PropSet |= (SymbolPropertySet)SymbolProperty::IBOutletCollection; |
49 | } |
50 | } |
51 | |
52 | bool index::isFunctionLocalSymbol(const Decl *D) { |
53 | assert(D); |
54 | |
55 | if (isa<ParmVarDecl>(D)) |
56 | return true; |
57 | |
58 | if (isa<ObjCTypeParamDecl>(D)) |
59 | return true; |
60 | |
61 | if (isa<UsingDirectiveDecl>(D)) |
62 | return false; |
63 | if (!D->getParentFunctionOrMethod()) |
64 | return false; |
65 | |
66 | if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) { |
67 | switch (ND->getFormalLinkage()) { |
68 | case NoLinkage: |
69 | case InternalLinkage: |
70 | return true; |
71 | case VisibleNoLinkage: |
72 | case UniqueExternalLinkage: |
73 | case ModuleInternalLinkage: |
74 | llvm_unreachable("Not a sema linkage"); |
75 | case ModuleLinkage: |
76 | case ExternalLinkage: |
77 | return false; |
78 | } |
79 | } |
80 | |
81 | return true; |
82 | } |
83 | |
84 | SymbolInfo index::getSymbolInfo(const Decl *D) { |
85 | assert(D); |
86 | SymbolInfo Info; |
87 | Info.Kind = SymbolKind::Unknown; |
88 | Info.SubKind = SymbolSubKind::None; |
89 | Info.Properties = SymbolPropertySet(); |
90 | Info.Lang = SymbolLanguage::C; |
91 | |
92 | if (isFunctionLocalSymbol(D)) { |
93 | Info.Properties |= (SymbolPropertySet)SymbolProperty::Local; |
94 | } |
95 | if (isa<ObjCProtocolDecl>(D->getDeclContext())) { |
96 | Info.Properties |= (SymbolPropertySet)SymbolProperty::ProtocolInterface; |
97 | } |
98 | |
99 | if (const TagDecl *TD = dyn_cast<TagDecl>(D)) { |
100 | switch (TD->getTagKind()) { |
101 | case TTK_Struct: |
102 | Info.Kind = SymbolKind::Struct; break; |
103 | case TTK_Union: |
104 | Info.Kind = SymbolKind::Union; break; |
105 | case TTK_Class: |
106 | Info.Kind = SymbolKind::Class; |
107 | Info.Lang = SymbolLanguage::CXX; |
108 | break; |
109 | case TTK_Interface: |
110 | Info.Kind = SymbolKind::Protocol; |
111 | Info.Lang = SymbolLanguage::CXX; |
112 | break; |
113 | case TTK_Enum: |
114 | Info.Kind = SymbolKind::Enum; break; |
115 | } |
116 | |
117 | if (const CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(D)) { |
118 | if (!CXXRec->isCLike()) { |
119 | Info.Lang = SymbolLanguage::CXX; |
120 | if (CXXRec->getDescribedClassTemplate()) { |
121 | Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; |
122 | } |
123 | } |
124 | } |
125 | |
126 | if (isa<ClassTemplatePartialSpecializationDecl>(D)) { |
127 | Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; |
128 | Info.Properties |= |
129 | (SymbolPropertySet)SymbolProperty::TemplatePartialSpecialization; |
130 | } else if (isa<ClassTemplateSpecializationDecl>(D)) { |
131 | Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; |
132 | Info.Properties |= |
133 | (SymbolPropertySet)SymbolProperty::TemplateSpecialization; |
134 | } |
135 | |
136 | } else if (auto *VD = dyn_cast<VarDecl>(D)) { |
137 | Info.Kind = SymbolKind::Variable; |
138 | if (isa<ParmVarDecl>(D)) { |
139 | Info.Kind = SymbolKind::Parameter; |
140 | } else if (isa<CXXRecordDecl>(D->getDeclContext())) { |
141 | Info.Kind = SymbolKind::StaticProperty; |
142 | Info.Lang = SymbolLanguage::CXX; |
143 | } |
144 | |
145 | if (isa<VarTemplatePartialSpecializationDecl>(D)) { |
146 | Info.Lang = SymbolLanguage::CXX; |
147 | Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; |
148 | Info.Properties |= |
149 | (SymbolPropertySet)SymbolProperty::TemplatePartialSpecialization; |
150 | } else if (isa<VarTemplateSpecializationDecl>(D)) { |
151 | Info.Lang = SymbolLanguage::CXX; |
152 | Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; |
153 | Info.Properties |= |
154 | (SymbolPropertySet)SymbolProperty::TemplateSpecialization; |
155 | } else if (VD->getDescribedVarTemplate()) { |
156 | Info.Lang = SymbolLanguage::CXX; |
157 | Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; |
158 | } |
159 | |
160 | } else { |
161 | switch (D->getKind()) { |
162 | case Decl::Import: |
163 | Info.Kind = SymbolKind::Module; |
164 | break; |
165 | case Decl::Typedef: |
166 | Info.Kind = SymbolKind::TypeAlias; break; |
167 | case Decl::Function: |
168 | Info.Kind = SymbolKind::Function; |
169 | break; |
170 | case Decl::Field: |
171 | Info.Kind = SymbolKind::Field; |
172 | if (const CXXRecordDecl * |
173 | CXXRec = dyn_cast<CXXRecordDecl>(D->getDeclContext())) { |
174 | if (!CXXRec->isCLike()) |
175 | Info.Lang = SymbolLanguage::CXX; |
176 | } |
177 | break; |
178 | case Decl::EnumConstant: |
179 | Info.Kind = SymbolKind::EnumConstant; break; |
180 | case Decl::ObjCInterface: |
181 | case Decl::ObjCImplementation: { |
182 | Info.Kind = SymbolKind::Class; |
183 | Info.Lang = SymbolLanguage::ObjC; |
184 | const ObjCInterfaceDecl *ClsD = dyn_cast<ObjCInterfaceDecl>(D); |
185 | if (!ClsD) |
186 | ClsD = cast<ObjCImplementationDecl>(D)->getClassInterface(); |
187 | if (isUnitTestCase(ClsD)) |
188 | Info.Properties |= (SymbolPropertySet)SymbolProperty::UnitTest; |
189 | break; |
190 | } |
191 | case Decl::ObjCProtocol: |
192 | Info.Kind = SymbolKind::Protocol; |
193 | Info.Lang = SymbolLanguage::ObjC; |
194 | break; |
195 | case Decl::ObjCCategory: |
196 | case Decl::ObjCCategoryImpl: { |
197 | Info.Kind = SymbolKind::Extension; |
198 | Info.Lang = SymbolLanguage::ObjC; |
199 | const ObjCInterfaceDecl *ClsD = nullptr; |
200 | if (auto *CatD = dyn_cast<ObjCCategoryDecl>(D)) |
201 | ClsD = CatD->getClassInterface(); |
202 | else |
203 | ClsD = cast<ObjCCategoryImplDecl>(D)->getClassInterface(); |
204 | if (isUnitTestCase(ClsD)) |
205 | Info.Properties |= (SymbolPropertySet)SymbolProperty::UnitTest; |
206 | break; |
207 | } |
208 | case Decl::ObjCMethod: { |
209 | const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D); |
210 | Info.Kind = MD->isInstanceMethod() ? SymbolKind::InstanceMethod : SymbolKind::ClassMethod; |
211 | if (MD->isPropertyAccessor()) { |
212 | if (MD->param_size()) |
213 | Info.SubKind = SymbolSubKind::AccessorSetter; |
214 | else |
215 | Info.SubKind = SymbolSubKind::AccessorGetter; |
216 | } |
217 | Info.Lang = SymbolLanguage::ObjC; |
218 | if (isUnitTest(MD)) |
219 | Info.Properties |= (SymbolPropertySet)SymbolProperty::UnitTest; |
220 | if (D->hasAttr<IBActionAttr>()) |
221 | Info.Properties |= (SymbolPropertySet)SymbolProperty::IBAnnotated; |
222 | break; |
223 | } |
224 | case Decl::ObjCProperty: |
225 | Info.Kind = SymbolKind::InstanceProperty; |
226 | Info.Lang = SymbolLanguage::ObjC; |
227 | checkForIBOutlets(D, Info.Properties); |
228 | if (auto *Annot = D->getAttr<AnnotateAttr>()) { |
229 | if (Annot->getAnnotation() == "gk_inspectable") |
230 | Info.Properties |= (SymbolPropertySet)SymbolProperty::GKInspectable; |
231 | } |
232 | break; |
233 | case Decl::ObjCIvar: |
234 | Info.Kind = SymbolKind::Field; |
235 | Info.Lang = SymbolLanguage::ObjC; |
236 | checkForIBOutlets(D, Info.Properties); |
237 | break; |
238 | case Decl::Namespace: |
239 | Info.Kind = SymbolKind::Namespace; |
240 | Info.Lang = SymbolLanguage::CXX; |
241 | break; |
242 | case Decl::NamespaceAlias: |
243 | Info.Kind = SymbolKind::NamespaceAlias; |
244 | Info.Lang = SymbolLanguage::CXX; |
245 | break; |
246 | case Decl::CXXConstructor: { |
247 | Info.Kind = SymbolKind::Constructor; |
248 | Info.Lang = SymbolLanguage::CXX; |
249 | auto *CD = cast<CXXConstructorDecl>(D); |
250 | if (CD->isCopyConstructor()) |
251 | Info.SubKind = SymbolSubKind::CXXCopyConstructor; |
252 | else if (CD->isMoveConstructor()) |
253 | Info.SubKind = SymbolSubKind::CXXMoveConstructor; |
254 | break; |
255 | } |
256 | case Decl::CXXDestructor: |
257 | Info.Kind = SymbolKind::Destructor; |
258 | Info.Lang = SymbolLanguage::CXX; |
259 | break; |
260 | case Decl::CXXConversion: |
261 | Info.Kind = SymbolKind::ConversionFunction; |
262 | Info.Lang = SymbolLanguage::CXX; |
263 | break; |
264 | case Decl::CXXMethod: { |
265 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(D); |
266 | if (MD->isStatic()) |
267 | Info.Kind = SymbolKind::StaticMethod; |
268 | else |
269 | Info.Kind = SymbolKind::InstanceMethod; |
270 | Info.Lang = SymbolLanguage::CXX; |
271 | break; |
272 | } |
273 | case Decl::ClassTemplate: |
274 | Info.Kind = SymbolKind::Class; |
275 | Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; |
276 | Info.Lang = SymbolLanguage::CXX; |
277 | break; |
278 | case Decl::FunctionTemplate: |
279 | Info.Kind = SymbolKind::Function; |
280 | Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; |
281 | Info.Lang = SymbolLanguage::CXX; |
282 | if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>( |
283 | cast<FunctionTemplateDecl>(D)->getTemplatedDecl())) { |
284 | if (isa<CXXConstructorDecl>(MD)) |
285 | Info.Kind = SymbolKind::Constructor; |
286 | else if (isa<CXXDestructorDecl>(MD)) |
287 | Info.Kind = SymbolKind::Destructor; |
288 | else if (isa<CXXConversionDecl>(MD)) |
289 | Info.Kind = SymbolKind::ConversionFunction; |
290 | else { |
291 | if (MD->isStatic()) |
292 | Info.Kind = SymbolKind::StaticMethod; |
293 | else |
294 | Info.Kind = SymbolKind::InstanceMethod; |
295 | } |
296 | } |
297 | break; |
298 | case Decl::TypeAliasTemplate: |
299 | Info.Kind = SymbolKind::TypeAlias; |
300 | Info.Lang = SymbolLanguage::CXX; |
301 | Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; |
302 | break; |
303 | case Decl::TypeAlias: |
304 | Info.Kind = SymbolKind::TypeAlias; |
305 | Info.Lang = SymbolLanguage::CXX; |
306 | break; |
307 | case Decl::UnresolvedUsingTypename: |
308 | Info.Kind = SymbolKind::Using; |
309 | Info.SubKind = SymbolSubKind::UsingTypename; |
310 | Info.Lang = SymbolLanguage::CXX; |
311 | Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; |
312 | break; |
313 | case Decl::UnresolvedUsingValue: |
314 | Info.Kind = SymbolKind::Using; |
315 | Info.SubKind = SymbolSubKind::UsingValue; |
316 | Info.Lang = SymbolLanguage::CXX; |
317 | Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; |
318 | break; |
319 | case Decl::Using: |
320 | Info.Kind = SymbolKind::Using; |
321 | Info.Lang = SymbolLanguage::CXX; |
322 | break; |
323 | case Decl::Binding: |
324 | Info.Kind = SymbolKind::Variable; |
325 | Info.Lang = SymbolLanguage::CXX; |
326 | break; |
327 | case Decl::MSProperty: |
328 | Info.Kind = SymbolKind::InstanceProperty; |
329 | if (const CXXRecordDecl *CXXRec = |
330 | dyn_cast<CXXRecordDecl>(D->getDeclContext())) { |
331 | if (!CXXRec->isCLike()) |
332 | Info.Lang = SymbolLanguage::CXX; |
333 | } |
334 | break; |
335 | default: |
336 | break; |
337 | } |
338 | } |
339 | |
340 | if (Info.Kind == SymbolKind::Unknown) |
341 | return Info; |
342 | |
343 | if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { |
344 | if (FD->getTemplatedKind() == |
345 | FunctionDecl::TK_FunctionTemplateSpecialization) { |
346 | Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; |
347 | Info.Properties |= |
348 | (SymbolPropertySet)SymbolProperty::TemplateSpecialization; |
349 | } |
350 | } |
351 | |
352 | if (Info.Properties & (SymbolPropertySet)SymbolProperty::Generic) |
353 | Info.Lang = SymbolLanguage::CXX; |
354 | |
355 | if (auto *attr = D->getExternalSourceSymbolAttr()) { |
356 | if (attr->getLanguage() == "Swift") |
357 | Info.Lang = SymbolLanguage::Swift; |
358 | } |
359 | |
360 | return Info; |
361 | } |
362 | |
363 | SymbolInfo index::getSymbolInfoForMacro(const MacroInfo &) { |
364 | SymbolInfo Info; |
365 | Info.Kind = SymbolKind::Macro; |
366 | Info.SubKind = SymbolSubKind::None; |
367 | Info.Properties = SymbolPropertySet(); |
368 | Info.Lang = SymbolLanguage::C; |
369 | return Info; |
370 | } |
371 | |
372 | bool index::applyForEachSymbolRoleInterruptible(SymbolRoleSet Roles, |
373 | llvm::function_ref<bool(SymbolRole)> Fn) { |
374 | #define APPLY_FOR_ROLE(Role) \ |
375 | if (Roles & (unsigned)SymbolRole::Role) \ |
376 | if (!Fn(SymbolRole::Role)) \ |
377 | return false; |
378 | |
379 | APPLY_FOR_ROLE(Declaration); |
380 | APPLY_FOR_ROLE(Definition); |
381 | APPLY_FOR_ROLE(Reference); |
382 | APPLY_FOR_ROLE(Read); |
383 | APPLY_FOR_ROLE(Write); |
384 | APPLY_FOR_ROLE(Call); |
385 | APPLY_FOR_ROLE(Dynamic); |
386 | APPLY_FOR_ROLE(AddressOf); |
387 | APPLY_FOR_ROLE(Implicit); |
388 | APPLY_FOR_ROLE(Undefinition); |
389 | APPLY_FOR_ROLE(RelationChildOf); |
390 | APPLY_FOR_ROLE(RelationBaseOf); |
391 | APPLY_FOR_ROLE(RelationOverrideOf); |
392 | APPLY_FOR_ROLE(RelationReceivedBy); |
393 | APPLY_FOR_ROLE(RelationCalledBy); |
394 | APPLY_FOR_ROLE(RelationExtendedBy); |
395 | APPLY_FOR_ROLE(RelationAccessorOf); |
396 | APPLY_FOR_ROLE(RelationContainedBy); |
397 | APPLY_FOR_ROLE(RelationIBTypeOf); |
398 | APPLY_FOR_ROLE(RelationSpecializationOf); |
399 | APPLY_FOR_ROLE(NameReference); |
400 | |
401 | #undef APPLY_FOR_ROLE |
402 | |
403 | return true; |
404 | } |
405 | |
406 | void index::applyForEachSymbolRole(SymbolRoleSet Roles, |
407 | llvm::function_ref<void(SymbolRole)> Fn) { |
408 | applyForEachSymbolRoleInterruptible(Roles, [&](SymbolRole r) -> bool { |
409 | Fn(r); |
410 | return true; |
411 | }); |
412 | } |
413 | |
414 | void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) { |
415 | bool VisitedOnce = false; |
416 | applyForEachSymbolRole(Roles, [&](SymbolRole Role) { |
417 | if (VisitedOnce) |
418 | OS << ','; |
419 | else |
420 | VisitedOnce = true; |
421 | switch (Role) { |
422 | case SymbolRole::Declaration: OS << "Decl"; break; |
423 | case SymbolRole::Definition: OS << "Def"; break; |
424 | case SymbolRole::Reference: OS << "Ref"; break; |
425 | case SymbolRole::Read: OS << "Read"; break; |
426 | case SymbolRole::Write: OS << "Writ"; break; |
427 | case SymbolRole::Call: OS << "Call"; break; |
428 | case SymbolRole::Dynamic: OS << "Dyn"; break; |
429 | case SymbolRole::AddressOf: OS << "Addr"; break; |
430 | case SymbolRole::Implicit: OS << "Impl"; break; |
431 | case SymbolRole::Undefinition: OS << "Undef"; break; |
432 | case SymbolRole::RelationChildOf: OS << "RelChild"; break; |
433 | case SymbolRole::RelationBaseOf: OS << "RelBase"; break; |
434 | case SymbolRole::RelationOverrideOf: OS << "RelOver"; break; |
435 | case SymbolRole::RelationReceivedBy: OS << "RelRec"; break; |
436 | case SymbolRole::RelationCalledBy: OS << "RelCall"; break; |
437 | case SymbolRole::RelationExtendedBy: OS << "RelExt"; break; |
438 | case SymbolRole::RelationAccessorOf: OS << "RelAcc"; break; |
439 | case SymbolRole::RelationContainedBy: OS << "RelCont"; break; |
440 | case SymbolRole::RelationIBTypeOf: OS << "RelIBType"; break; |
441 | case SymbolRole::RelationSpecializationOf: OS << "RelSpecialization"; break; |
442 | case SymbolRole::NameReference: OS << "NameReference"; break; |
443 | } |
444 | }); |
445 | } |
446 | |
447 | bool index::printSymbolName(const Decl *D, const LangOptions &LO, |
448 | raw_ostream &OS) { |
449 | if (auto *ND = dyn_cast<NamedDecl>(D)) { |
450 | PrintingPolicy Policy(LO); |
451 | |
452 | |
453 | |
454 | Policy.SuppressTemplateArgsInCXXConstructors = true; |
455 | DeclarationName DeclName = ND->getDeclName(); |
456 | if (DeclName.isEmpty()) |
457 | return true; |
458 | DeclName.print(OS, Policy); |
459 | return false; |
460 | } else { |
461 | return true; |
462 | } |
463 | } |
464 | |
465 | StringRef index::getSymbolKindString(SymbolKind K) { |
466 | switch (K) { |
467 | case SymbolKind::Unknown: return "<unknown>"; |
468 | case SymbolKind::Module: return "module"; |
469 | case SymbolKind::Namespace: return "namespace"; |
470 | case SymbolKind::NamespaceAlias: return "namespace-alias"; |
471 | case SymbolKind::Macro: return "macro"; |
472 | case SymbolKind::Enum: return "enum"; |
473 | case SymbolKind::Struct: return "struct"; |
474 | case SymbolKind::Class: return "class"; |
475 | case SymbolKind::Protocol: return "protocol"; |
476 | case SymbolKind::Extension: return "extension"; |
477 | case SymbolKind::Union: return "union"; |
478 | case SymbolKind::TypeAlias: return "type-alias"; |
479 | case SymbolKind::Function: return "function"; |
480 | case SymbolKind::Variable: return "variable"; |
481 | case SymbolKind::Field: return "field"; |
482 | case SymbolKind::EnumConstant: return "enumerator"; |
483 | case SymbolKind::InstanceMethod: return "instance-method"; |
484 | case SymbolKind::ClassMethod: return "class-method"; |
485 | case SymbolKind::StaticMethod: return "static-method"; |
486 | case SymbolKind::InstanceProperty: return "instance-property"; |
487 | case SymbolKind::ClassProperty: return "class-property"; |
488 | case SymbolKind::StaticProperty: return "static-property"; |
489 | case SymbolKind::Constructor: return "constructor"; |
490 | case SymbolKind::Destructor: return "destructor"; |
491 | case SymbolKind::ConversionFunction: return "coversion-func"; |
492 | case SymbolKind::Parameter: return "param"; |
493 | case SymbolKind::Using: return "using"; |
494 | } |
495 | llvm_unreachable("invalid symbol kind"); |
496 | } |
497 | |
498 | StringRef index::getSymbolSubKindString(SymbolSubKind K) { |
499 | switch (K) { |
500 | case SymbolSubKind::None: return "<none>"; |
501 | case SymbolSubKind::CXXCopyConstructor: return "cxx-copy-ctor"; |
502 | case SymbolSubKind::CXXMoveConstructor: return "cxx-move-ctor"; |
503 | case SymbolSubKind::AccessorGetter: return "acc-get"; |
504 | case SymbolSubKind::AccessorSetter: return "acc-set"; |
505 | case SymbolSubKind::UsingTypename: return "using-typename"; |
506 | case SymbolSubKind::UsingValue: return "using-value"; |
507 | } |
508 | llvm_unreachable("invalid symbol subkind"); |
509 | } |
510 | |
511 | StringRef index::getSymbolLanguageString(SymbolLanguage K) { |
512 | switch (K) { |
513 | case SymbolLanguage::C: return "C"; |
514 | case SymbolLanguage::ObjC: return "ObjC"; |
515 | case SymbolLanguage::CXX: return "C++"; |
516 | case SymbolLanguage::Swift: return "Swift"; |
517 | } |
518 | llvm_unreachable("invalid symbol language kind"); |
519 | } |
520 | |
521 | void index::applyForEachSymbolProperty(SymbolPropertySet Props, |
522 | llvm::function_ref<void(SymbolProperty)> Fn) { |
523 | #define APPLY_FOR_PROPERTY(K) \ |
524 | if (Props & (SymbolPropertySet)SymbolProperty::K) \ |
525 | Fn(SymbolProperty::K) |
526 | |
527 | APPLY_FOR_PROPERTY(Generic); |
528 | APPLY_FOR_PROPERTY(TemplatePartialSpecialization); |
529 | APPLY_FOR_PROPERTY(TemplateSpecialization); |
530 | APPLY_FOR_PROPERTY(UnitTest); |
531 | APPLY_FOR_PROPERTY(IBAnnotated); |
532 | APPLY_FOR_PROPERTY(IBOutletCollection); |
533 | APPLY_FOR_PROPERTY(GKInspectable); |
534 | APPLY_FOR_PROPERTY(Local); |
535 | APPLY_FOR_PROPERTY(ProtocolInterface); |
536 | |
537 | #undef APPLY_FOR_PROPERTY |
538 | } |
539 | |
540 | void index::printSymbolProperties(SymbolPropertySet Props, raw_ostream &OS) { |
541 | bool VisitedOnce = false; |
542 | applyForEachSymbolProperty(Props, [&](SymbolProperty Prop) { |
543 | if (VisitedOnce) |
544 | OS << ','; |
545 | else |
546 | VisitedOnce = true; |
547 | switch (Prop) { |
548 | case SymbolProperty::Generic: OS << "Gen"; break; |
549 | case SymbolProperty::TemplatePartialSpecialization: OS << "TPS"; break; |
550 | case SymbolProperty::TemplateSpecialization: OS << "TS"; break; |
551 | case SymbolProperty::UnitTest: OS << "test"; break; |
552 | case SymbolProperty::IBAnnotated: OS << "IB"; break; |
553 | case SymbolProperty::IBOutletCollection: OS << "IBColl"; break; |
554 | case SymbolProperty::GKInspectable: OS << "GKI"; break; |
555 | case SymbolProperty::Local: OS << "local"; break; |
556 | case SymbolProperty::ProtocolInterface: OS << "protocol"; break; |
557 | } |
558 | }); |
559 | } |
560 | |