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