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