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