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