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