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