10b57cec5SDimitry Andric //===--- IndexSymbol.cpp - Types and functions for indexing symbols -------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "clang/Index/IndexSymbol.h" 10480093f4SDimitry Andric #include "clang/AST/Attr.h" 110b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h" 120b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h" 130b57cec5SDimitry Andric #include "clang/AST/DeclTemplate.h" 140b57cec5SDimitry Andric #include "clang/AST/PrettyPrinter.h" 150b57cec5SDimitry Andric #include "clang/Lex/MacroInfo.h" 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric using namespace clang; 180b57cec5SDimitry Andric using namespace clang::index; 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric /// \returns true if \c D is a subclass of 'XCTestCase'. 210b57cec5SDimitry Andric static bool isUnitTestCase(const ObjCInterfaceDecl *D) { 220b57cec5SDimitry Andric if (!D) 230b57cec5SDimitry Andric return false; 240b57cec5SDimitry Andric while (const ObjCInterfaceDecl *SuperD = D->getSuperClass()) { 250b57cec5SDimitry Andric if (SuperD->getName() == "XCTestCase") 260b57cec5SDimitry Andric return true; 270b57cec5SDimitry Andric D = SuperD; 280b57cec5SDimitry Andric } 290b57cec5SDimitry Andric return false; 300b57cec5SDimitry Andric } 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric /// \returns true if \c D is in a subclass of 'XCTestCase', returns void, has 330b57cec5SDimitry Andric /// no parameters, and its name starts with 'test'. 340b57cec5SDimitry Andric static bool isUnitTest(const ObjCMethodDecl *D) { 350b57cec5SDimitry Andric if (!D->parameters().empty()) 360b57cec5SDimitry Andric return false; 370b57cec5SDimitry Andric if (!D->getReturnType()->isVoidType()) 380b57cec5SDimitry Andric return false; 390b57cec5SDimitry Andric if (!D->getSelector().getNameForSlot(0).startswith("test")) 400b57cec5SDimitry Andric return false; 410b57cec5SDimitry Andric return isUnitTestCase(D->getClassInterface()); 420b57cec5SDimitry Andric } 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric static void checkForIBOutlets(const Decl *D, SymbolPropertySet &PropSet) { 450b57cec5SDimitry Andric if (D->hasAttr<IBOutletAttr>()) { 460b57cec5SDimitry Andric PropSet |= (SymbolPropertySet)SymbolProperty::IBAnnotated; 470b57cec5SDimitry Andric } else if (D->hasAttr<IBOutletCollectionAttr>()) { 480b57cec5SDimitry Andric PropSet |= (SymbolPropertySet)SymbolProperty::IBAnnotated; 490b57cec5SDimitry Andric PropSet |= (SymbolPropertySet)SymbolProperty::IBOutletCollection; 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric } 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric bool index::isFunctionLocalSymbol(const Decl *D) { 540b57cec5SDimitry Andric assert(D); 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric if (isa<ParmVarDecl>(D)) 570b57cec5SDimitry Andric return true; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric if (isa<ObjCTypeParamDecl>(D)) 600b57cec5SDimitry Andric return true; 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric if (isa<UsingDirectiveDecl>(D)) 630b57cec5SDimitry Andric return false; 640b57cec5SDimitry Andric if (!D->getParentFunctionOrMethod()) 650b57cec5SDimitry Andric return false; 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) { 680b57cec5SDimitry Andric switch (ND->getFormalLinkage()) { 690b57cec5SDimitry Andric case NoLinkage: 700b57cec5SDimitry Andric case InternalLinkage: 710b57cec5SDimitry Andric return true; 720b57cec5SDimitry Andric case VisibleNoLinkage: 730b57cec5SDimitry Andric case UniqueExternalLinkage: 740b57cec5SDimitry Andric case ModuleInternalLinkage: 750b57cec5SDimitry Andric llvm_unreachable("Not a sema linkage"); 760b57cec5SDimitry Andric case ModuleLinkage: 770b57cec5SDimitry Andric case ExternalLinkage: 780b57cec5SDimitry Andric return false; 790b57cec5SDimitry Andric } 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric return true; 830b57cec5SDimitry Andric } 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric SymbolInfo index::getSymbolInfo(const Decl *D) { 860b57cec5SDimitry Andric assert(D); 870b57cec5SDimitry Andric SymbolInfo Info; 880b57cec5SDimitry Andric Info.Kind = SymbolKind::Unknown; 890b57cec5SDimitry Andric Info.SubKind = SymbolSubKind::None; 900b57cec5SDimitry Andric Info.Properties = SymbolPropertySet(); 910b57cec5SDimitry Andric Info.Lang = SymbolLanguage::C; 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric if (isFunctionLocalSymbol(D)) { 940b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Local; 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric if (isa<ObjCProtocolDecl>(D->getDeclContext())) { 970b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::ProtocolInterface; 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric if (auto *VT = dyn_cast<VarTemplateDecl>(D)) { 1010b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; 1020b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 1030b57cec5SDimitry Andric // All other fields are filled from the templated decl. 1040b57cec5SDimitry Andric D = VT->getTemplatedDecl(); 1050b57cec5SDimitry Andric } 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric if (const TagDecl *TD = dyn_cast<TagDecl>(D)) { 1080b57cec5SDimitry Andric switch (TD->getTagKind()) { 1090b57cec5SDimitry Andric case TTK_Struct: 1100b57cec5SDimitry Andric Info.Kind = SymbolKind::Struct; break; 1110b57cec5SDimitry Andric case TTK_Union: 1120b57cec5SDimitry Andric Info.Kind = SymbolKind::Union; break; 1130b57cec5SDimitry Andric case TTK_Class: 1140b57cec5SDimitry Andric Info.Kind = SymbolKind::Class; 1150b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 1160b57cec5SDimitry Andric break; 1170b57cec5SDimitry Andric case TTK_Interface: 1180b57cec5SDimitry Andric Info.Kind = SymbolKind::Protocol; 1190b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 1200b57cec5SDimitry Andric break; 1210b57cec5SDimitry Andric case TTK_Enum: 1220b57cec5SDimitry Andric Info.Kind = SymbolKind::Enum; break; 1230b57cec5SDimitry Andric } 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric if (const CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(D)) { 1260b57cec5SDimitry Andric if (!CXXRec->isCLike()) { 1270b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 1280b57cec5SDimitry Andric if (CXXRec->getDescribedClassTemplate()) { 1290b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric } 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric if (isa<ClassTemplatePartialSpecializationDecl>(D)) { 1350b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; 1360b57cec5SDimitry Andric Info.Properties |= 1370b57cec5SDimitry Andric (SymbolPropertySet)SymbolProperty::TemplatePartialSpecialization; 1380b57cec5SDimitry Andric } else if (isa<ClassTemplateSpecializationDecl>(D)) { 1390b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; 1400b57cec5SDimitry Andric Info.Properties |= 1410b57cec5SDimitry Andric (SymbolPropertySet)SymbolProperty::TemplateSpecialization; 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric } else if (auto *VD = dyn_cast<VarDecl>(D)) { 1450b57cec5SDimitry Andric Info.Kind = SymbolKind::Variable; 1460b57cec5SDimitry Andric if (isa<ParmVarDecl>(D)) { 1470b57cec5SDimitry Andric Info.Kind = SymbolKind::Parameter; 1480b57cec5SDimitry Andric } else if (isa<CXXRecordDecl>(D->getDeclContext())) { 1490b57cec5SDimitry Andric Info.Kind = SymbolKind::StaticProperty; 1500b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric if (isa<VarTemplatePartialSpecializationDecl>(D)) { 1540b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 1550b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; 1560b57cec5SDimitry Andric Info.Properties |= 1570b57cec5SDimitry Andric (SymbolPropertySet)SymbolProperty::TemplatePartialSpecialization; 1580b57cec5SDimitry Andric } else if (isa<VarTemplateSpecializationDecl>(D)) { 1590b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 1600b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; 1610b57cec5SDimitry Andric Info.Properties |= 1620b57cec5SDimitry Andric (SymbolPropertySet)SymbolProperty::TemplateSpecialization; 1630b57cec5SDimitry Andric } else if (VD->getDescribedVarTemplate()) { 1640b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 1650b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric } else { 1690b57cec5SDimitry Andric switch (D->getKind()) { 1700b57cec5SDimitry Andric case Decl::Import: 1710b57cec5SDimitry Andric Info.Kind = SymbolKind::Module; 1720b57cec5SDimitry Andric break; 1730b57cec5SDimitry Andric case Decl::Typedef: 1740b57cec5SDimitry Andric Info.Kind = SymbolKind::TypeAlias; break; // Lang = C 1750b57cec5SDimitry Andric case Decl::Function: 1760b57cec5SDimitry Andric Info.Kind = SymbolKind::Function; 1770b57cec5SDimitry Andric break; 1780b57cec5SDimitry Andric case Decl::Field: 1790b57cec5SDimitry Andric case Decl::IndirectField: 1800b57cec5SDimitry Andric Info.Kind = SymbolKind::Field; 1810b57cec5SDimitry Andric if (const CXXRecordDecl * 1820b57cec5SDimitry Andric CXXRec = dyn_cast<CXXRecordDecl>(D->getDeclContext())) { 1830b57cec5SDimitry Andric if (!CXXRec->isCLike()) 1840b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric break; 1870b57cec5SDimitry Andric case Decl::EnumConstant: 1880b57cec5SDimitry Andric Info.Kind = SymbolKind::EnumConstant; break; 1890b57cec5SDimitry Andric case Decl::ObjCInterface: 1900b57cec5SDimitry Andric case Decl::ObjCImplementation: { 1910b57cec5SDimitry Andric Info.Kind = SymbolKind::Class; 1920b57cec5SDimitry Andric Info.Lang = SymbolLanguage::ObjC; 1930b57cec5SDimitry Andric const ObjCInterfaceDecl *ClsD = dyn_cast<ObjCInterfaceDecl>(D); 1940b57cec5SDimitry Andric if (!ClsD) 1950b57cec5SDimitry Andric ClsD = cast<ObjCImplementationDecl>(D)->getClassInterface(); 1960b57cec5SDimitry Andric if (isUnitTestCase(ClsD)) 1970b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::UnitTest; 1980b57cec5SDimitry Andric break; 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric case Decl::ObjCProtocol: 2010b57cec5SDimitry Andric Info.Kind = SymbolKind::Protocol; 2020b57cec5SDimitry Andric Info.Lang = SymbolLanguage::ObjC; 2030b57cec5SDimitry Andric break; 2040b57cec5SDimitry Andric case Decl::ObjCCategory: 2050b57cec5SDimitry Andric case Decl::ObjCCategoryImpl: { 2060b57cec5SDimitry Andric Info.Kind = SymbolKind::Extension; 2070b57cec5SDimitry Andric Info.Lang = SymbolLanguage::ObjC; 2080b57cec5SDimitry Andric const ObjCInterfaceDecl *ClsD = nullptr; 2090b57cec5SDimitry Andric if (auto *CatD = dyn_cast<ObjCCategoryDecl>(D)) 2100b57cec5SDimitry Andric ClsD = CatD->getClassInterface(); 2110b57cec5SDimitry Andric else 2120b57cec5SDimitry Andric ClsD = cast<ObjCCategoryImplDecl>(D)->getClassInterface(); 2130b57cec5SDimitry Andric if (isUnitTestCase(ClsD)) 2140b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::UnitTest; 2150b57cec5SDimitry Andric break; 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric case Decl::ObjCMethod: { 2180b57cec5SDimitry Andric const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D); 2190b57cec5SDimitry Andric Info.Kind = MD->isInstanceMethod() ? SymbolKind::InstanceMethod : SymbolKind::ClassMethod; 2200b57cec5SDimitry Andric if (MD->isPropertyAccessor()) { 2210b57cec5SDimitry Andric if (MD->param_size()) 2220b57cec5SDimitry Andric Info.SubKind = SymbolSubKind::AccessorSetter; 2230b57cec5SDimitry Andric else 2240b57cec5SDimitry Andric Info.SubKind = SymbolSubKind::AccessorGetter; 2250b57cec5SDimitry Andric } 2260b57cec5SDimitry Andric Info.Lang = SymbolLanguage::ObjC; 2270b57cec5SDimitry Andric if (isUnitTest(MD)) 2280b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::UnitTest; 2290b57cec5SDimitry Andric if (D->hasAttr<IBActionAttr>()) 2300b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::IBAnnotated; 2310b57cec5SDimitry Andric break; 2320b57cec5SDimitry Andric } 2330b57cec5SDimitry Andric case Decl::ObjCProperty: 2340b57cec5SDimitry Andric Info.Kind = SymbolKind::InstanceProperty; 2350b57cec5SDimitry Andric Info.Lang = SymbolLanguage::ObjC; 2360b57cec5SDimitry Andric checkForIBOutlets(D, Info.Properties); 2370b57cec5SDimitry Andric if (auto *Annot = D->getAttr<AnnotateAttr>()) { 2380b57cec5SDimitry Andric if (Annot->getAnnotation() == "gk_inspectable") 2390b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::GKInspectable; 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric break; 2420b57cec5SDimitry Andric case Decl::ObjCIvar: 2430b57cec5SDimitry Andric Info.Kind = SymbolKind::Field; 2440b57cec5SDimitry Andric Info.Lang = SymbolLanguage::ObjC; 2450b57cec5SDimitry Andric checkForIBOutlets(D, Info.Properties); 2460b57cec5SDimitry Andric break; 2470b57cec5SDimitry Andric case Decl::Namespace: 2480b57cec5SDimitry Andric Info.Kind = SymbolKind::Namespace; 2490b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 2500b57cec5SDimitry Andric break; 2510b57cec5SDimitry Andric case Decl::NamespaceAlias: 2520b57cec5SDimitry Andric Info.Kind = SymbolKind::NamespaceAlias; 2530b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 2540b57cec5SDimitry Andric break; 2550b57cec5SDimitry Andric case Decl::CXXConstructor: { 2560b57cec5SDimitry Andric Info.Kind = SymbolKind::Constructor; 2570b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 2580b57cec5SDimitry Andric auto *CD = cast<CXXConstructorDecl>(D); 2590b57cec5SDimitry Andric if (CD->isCopyConstructor()) 2600b57cec5SDimitry Andric Info.SubKind = SymbolSubKind::CXXCopyConstructor; 2610b57cec5SDimitry Andric else if (CD->isMoveConstructor()) 2620b57cec5SDimitry Andric Info.SubKind = SymbolSubKind::CXXMoveConstructor; 2630b57cec5SDimitry Andric break; 2640b57cec5SDimitry Andric } 2650b57cec5SDimitry Andric case Decl::CXXDestructor: 2660b57cec5SDimitry Andric Info.Kind = SymbolKind::Destructor; 2670b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 2680b57cec5SDimitry Andric break; 2690b57cec5SDimitry Andric case Decl::CXXConversion: 2700b57cec5SDimitry Andric Info.Kind = SymbolKind::ConversionFunction; 2710b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 2720b57cec5SDimitry Andric break; 2730b57cec5SDimitry Andric case Decl::CXXMethod: { 2740b57cec5SDimitry Andric const CXXMethodDecl *MD = cast<CXXMethodDecl>(D); 2750b57cec5SDimitry Andric if (MD->isStatic()) 2760b57cec5SDimitry Andric Info.Kind = SymbolKind::StaticMethod; 2770b57cec5SDimitry Andric else 2780b57cec5SDimitry Andric Info.Kind = SymbolKind::InstanceMethod; 2790b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 2800b57cec5SDimitry Andric break; 2810b57cec5SDimitry Andric } 2820b57cec5SDimitry Andric case Decl::ClassTemplate: 2830b57cec5SDimitry Andric Info.Kind = SymbolKind::Class; 2840b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; 2850b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 2860b57cec5SDimitry Andric break; 2870b57cec5SDimitry Andric case Decl::FunctionTemplate: 2880b57cec5SDimitry Andric Info.Kind = SymbolKind::Function; 2890b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; 2900b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 2910b57cec5SDimitry Andric if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>( 2920b57cec5SDimitry Andric cast<FunctionTemplateDecl>(D)->getTemplatedDecl())) { 2930b57cec5SDimitry Andric if (isa<CXXConstructorDecl>(MD)) 2940b57cec5SDimitry Andric Info.Kind = SymbolKind::Constructor; 2950b57cec5SDimitry Andric else if (isa<CXXDestructorDecl>(MD)) 2960b57cec5SDimitry Andric Info.Kind = SymbolKind::Destructor; 2970b57cec5SDimitry Andric else if (isa<CXXConversionDecl>(MD)) 2980b57cec5SDimitry Andric Info.Kind = SymbolKind::ConversionFunction; 2990b57cec5SDimitry Andric else { 3000b57cec5SDimitry Andric if (MD->isStatic()) 3010b57cec5SDimitry Andric Info.Kind = SymbolKind::StaticMethod; 3020b57cec5SDimitry Andric else 3030b57cec5SDimitry Andric Info.Kind = SymbolKind::InstanceMethod; 3040b57cec5SDimitry Andric } 3050b57cec5SDimitry Andric } 3060b57cec5SDimitry Andric break; 3070b57cec5SDimitry Andric case Decl::TypeAliasTemplate: 3080b57cec5SDimitry Andric Info.Kind = SymbolKind::TypeAlias; 3090b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 3100b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; 3110b57cec5SDimitry Andric break; 3120b57cec5SDimitry Andric case Decl::TypeAlias: 3130b57cec5SDimitry Andric Info.Kind = SymbolKind::TypeAlias; 3140b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 3150b57cec5SDimitry Andric break; 3160b57cec5SDimitry Andric case Decl::UnresolvedUsingTypename: 3170b57cec5SDimitry Andric Info.Kind = SymbolKind::Using; 3180b57cec5SDimitry Andric Info.SubKind = SymbolSubKind::UsingTypename; 3190b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 3200b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; 3210b57cec5SDimitry Andric break; 3220b57cec5SDimitry Andric case Decl::UnresolvedUsingValue: 3230b57cec5SDimitry Andric Info.Kind = SymbolKind::Using; 3240b57cec5SDimitry Andric Info.SubKind = SymbolSubKind::UsingValue; 3250b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 3260b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; 3270b57cec5SDimitry Andric break; 3280b57cec5SDimitry Andric case Decl::Using: 3290b57cec5SDimitry Andric Info.Kind = SymbolKind::Using; 3300b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 3310b57cec5SDimitry Andric break; 332*fe6060f1SDimitry Andric case Decl::UsingEnum: 333*fe6060f1SDimitry Andric Info.Kind = SymbolKind::Using; 334*fe6060f1SDimitry Andric Info.Lang = SymbolLanguage::CXX; 335*fe6060f1SDimitry Andric Info.SubKind = SymbolSubKind::UsingEnum; 336*fe6060f1SDimitry Andric break; 3370b57cec5SDimitry Andric case Decl::Binding: 3380b57cec5SDimitry Andric Info.Kind = SymbolKind::Variable; 3390b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 3400b57cec5SDimitry Andric break; 3410b57cec5SDimitry Andric case Decl::MSProperty: 3420b57cec5SDimitry Andric Info.Kind = SymbolKind::InstanceProperty; 3430b57cec5SDimitry Andric if (const CXXRecordDecl *CXXRec = 3440b57cec5SDimitry Andric dyn_cast<CXXRecordDecl>(D->getDeclContext())) { 3450b57cec5SDimitry Andric if (!CXXRec->isCLike()) 3460b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 3470b57cec5SDimitry Andric } 3480b57cec5SDimitry Andric break; 3490b57cec5SDimitry Andric case Decl::ClassTemplatePartialSpecialization: 3500b57cec5SDimitry Andric case Decl::ClassScopeFunctionSpecialization: 3510b57cec5SDimitry Andric case Decl::ClassTemplateSpecialization: 3520b57cec5SDimitry Andric case Decl::CXXRecord: 3530b57cec5SDimitry Andric case Decl::Enum: 3540b57cec5SDimitry Andric case Decl::Record: 3550b57cec5SDimitry Andric llvm_unreachable("records handled before"); 3560b57cec5SDimitry Andric break; 3570b57cec5SDimitry Andric case Decl::VarTemplateSpecialization: 3580b57cec5SDimitry Andric case Decl::VarTemplatePartialSpecialization: 3590b57cec5SDimitry Andric case Decl::ImplicitParam: 3600b57cec5SDimitry Andric case Decl::ParmVar: 3610b57cec5SDimitry Andric case Decl::Var: 3620b57cec5SDimitry Andric case Decl::VarTemplate: 3630b57cec5SDimitry Andric llvm_unreachable("variables handled before"); 3640b57cec5SDimitry Andric break; 3655ffd83dbSDimitry Andric case Decl::TemplateTypeParm: 3665ffd83dbSDimitry Andric Info.Kind = SymbolKind::TemplateTypeParm; 3675ffd83dbSDimitry Andric break; 3685ffd83dbSDimitry Andric case Decl::TemplateTemplateParm: 3695ffd83dbSDimitry Andric Info.Kind = SymbolKind::TemplateTemplateParm; 3705ffd83dbSDimitry Andric break; 3715ffd83dbSDimitry Andric case Decl::NonTypeTemplateParm: 3725ffd83dbSDimitry Andric Info.Kind = SymbolKind::NonTypeTemplateParm; 3735ffd83dbSDimitry Andric break; 3740b57cec5SDimitry Andric // Other decls get the 'unknown' kind. 3750b57cec5SDimitry Andric default: 3760b57cec5SDimitry Andric break; 3770b57cec5SDimitry Andric } 3780b57cec5SDimitry Andric } 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric if (Info.Kind == SymbolKind::Unknown) 3810b57cec5SDimitry Andric return Info; 3820b57cec5SDimitry Andric 3830b57cec5SDimitry Andric if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 3840b57cec5SDimitry Andric if (FD->getTemplatedKind() == 3850b57cec5SDimitry Andric FunctionDecl::TK_FunctionTemplateSpecialization) { 3860b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic; 3870b57cec5SDimitry Andric Info.Properties |= 3880b57cec5SDimitry Andric (SymbolPropertySet)SymbolProperty::TemplateSpecialization; 3890b57cec5SDimitry Andric } 3900b57cec5SDimitry Andric } 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric if (Info.Properties & (SymbolPropertySet)SymbolProperty::Generic) 3930b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX; 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric if (auto *attr = D->getExternalSourceSymbolAttr()) { 3960b57cec5SDimitry Andric if (attr->getLanguage() == "Swift") 3970b57cec5SDimitry Andric Info.Lang = SymbolLanguage::Swift; 3980b57cec5SDimitry Andric } 3990b57cec5SDimitry Andric 4000b57cec5SDimitry Andric return Info; 4010b57cec5SDimitry Andric } 4020b57cec5SDimitry Andric 4030b57cec5SDimitry Andric SymbolInfo index::getSymbolInfoForMacro(const MacroInfo &) { 4040b57cec5SDimitry Andric SymbolInfo Info; 4050b57cec5SDimitry Andric Info.Kind = SymbolKind::Macro; 4060b57cec5SDimitry Andric Info.SubKind = SymbolSubKind::None; 4070b57cec5SDimitry Andric Info.Properties = SymbolPropertySet(); 4080b57cec5SDimitry Andric Info.Lang = SymbolLanguage::C; 4090b57cec5SDimitry Andric return Info; 4100b57cec5SDimitry Andric } 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric bool index::applyForEachSymbolRoleInterruptible(SymbolRoleSet Roles, 4130b57cec5SDimitry Andric llvm::function_ref<bool(SymbolRole)> Fn) { 4140b57cec5SDimitry Andric #define APPLY_FOR_ROLE(Role) \ 4150b57cec5SDimitry Andric if (Roles & (unsigned)SymbolRole::Role) \ 4160b57cec5SDimitry Andric if (!Fn(SymbolRole::Role)) \ 4170b57cec5SDimitry Andric return false; 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric APPLY_FOR_ROLE(Declaration); 4200b57cec5SDimitry Andric APPLY_FOR_ROLE(Definition); 4210b57cec5SDimitry Andric APPLY_FOR_ROLE(Reference); 4220b57cec5SDimitry Andric APPLY_FOR_ROLE(Read); 4230b57cec5SDimitry Andric APPLY_FOR_ROLE(Write); 4240b57cec5SDimitry Andric APPLY_FOR_ROLE(Call); 4250b57cec5SDimitry Andric APPLY_FOR_ROLE(Dynamic); 4260b57cec5SDimitry Andric APPLY_FOR_ROLE(AddressOf); 4270b57cec5SDimitry Andric APPLY_FOR_ROLE(Implicit); 4280b57cec5SDimitry Andric APPLY_FOR_ROLE(Undefinition); 4290b57cec5SDimitry Andric APPLY_FOR_ROLE(RelationChildOf); 4300b57cec5SDimitry Andric APPLY_FOR_ROLE(RelationBaseOf); 4310b57cec5SDimitry Andric APPLY_FOR_ROLE(RelationOverrideOf); 4320b57cec5SDimitry Andric APPLY_FOR_ROLE(RelationReceivedBy); 4330b57cec5SDimitry Andric APPLY_FOR_ROLE(RelationCalledBy); 4340b57cec5SDimitry Andric APPLY_FOR_ROLE(RelationExtendedBy); 4350b57cec5SDimitry Andric APPLY_FOR_ROLE(RelationAccessorOf); 4360b57cec5SDimitry Andric APPLY_FOR_ROLE(RelationContainedBy); 4370b57cec5SDimitry Andric APPLY_FOR_ROLE(RelationIBTypeOf); 4380b57cec5SDimitry Andric APPLY_FOR_ROLE(RelationSpecializationOf); 4390b57cec5SDimitry Andric APPLY_FOR_ROLE(NameReference); 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric #undef APPLY_FOR_ROLE 4420b57cec5SDimitry Andric 4430b57cec5SDimitry Andric return true; 4440b57cec5SDimitry Andric } 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric void index::applyForEachSymbolRole(SymbolRoleSet Roles, 4470b57cec5SDimitry Andric llvm::function_ref<void(SymbolRole)> Fn) { 4480b57cec5SDimitry Andric applyForEachSymbolRoleInterruptible(Roles, [&](SymbolRole r) -> bool { 4490b57cec5SDimitry Andric Fn(r); 4500b57cec5SDimitry Andric return true; 4510b57cec5SDimitry Andric }); 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) { 4550b57cec5SDimitry Andric bool VisitedOnce = false; 4560b57cec5SDimitry Andric applyForEachSymbolRole(Roles, [&](SymbolRole Role) { 4570b57cec5SDimitry Andric if (VisitedOnce) 4580b57cec5SDimitry Andric OS << ','; 4590b57cec5SDimitry Andric else 4600b57cec5SDimitry Andric VisitedOnce = true; 4610b57cec5SDimitry Andric switch (Role) { 4620b57cec5SDimitry Andric case SymbolRole::Declaration: OS << "Decl"; break; 4630b57cec5SDimitry Andric case SymbolRole::Definition: OS << "Def"; break; 4640b57cec5SDimitry Andric case SymbolRole::Reference: OS << "Ref"; break; 4650b57cec5SDimitry Andric case SymbolRole::Read: OS << "Read"; break; 4660b57cec5SDimitry Andric case SymbolRole::Write: OS << "Writ"; break; 4670b57cec5SDimitry Andric case SymbolRole::Call: OS << "Call"; break; 4680b57cec5SDimitry Andric case SymbolRole::Dynamic: OS << "Dyn"; break; 4690b57cec5SDimitry Andric case SymbolRole::AddressOf: OS << "Addr"; break; 4700b57cec5SDimitry Andric case SymbolRole::Implicit: OS << "Impl"; break; 4710b57cec5SDimitry Andric case SymbolRole::Undefinition: OS << "Undef"; break; 4720b57cec5SDimitry Andric case SymbolRole::RelationChildOf: OS << "RelChild"; break; 4730b57cec5SDimitry Andric case SymbolRole::RelationBaseOf: OS << "RelBase"; break; 4740b57cec5SDimitry Andric case SymbolRole::RelationOverrideOf: OS << "RelOver"; break; 4750b57cec5SDimitry Andric case SymbolRole::RelationReceivedBy: OS << "RelRec"; break; 4760b57cec5SDimitry Andric case SymbolRole::RelationCalledBy: OS << "RelCall"; break; 4770b57cec5SDimitry Andric case SymbolRole::RelationExtendedBy: OS << "RelExt"; break; 4780b57cec5SDimitry Andric case SymbolRole::RelationAccessorOf: OS << "RelAcc"; break; 4790b57cec5SDimitry Andric case SymbolRole::RelationContainedBy: OS << "RelCont"; break; 4800b57cec5SDimitry Andric case SymbolRole::RelationIBTypeOf: OS << "RelIBType"; break; 4810b57cec5SDimitry Andric case SymbolRole::RelationSpecializationOf: OS << "RelSpecialization"; break; 4820b57cec5SDimitry Andric case SymbolRole::NameReference: OS << "NameReference"; break; 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric }); 4850b57cec5SDimitry Andric } 4860b57cec5SDimitry Andric 4870b57cec5SDimitry Andric bool index::printSymbolName(const Decl *D, const LangOptions &LO, 4880b57cec5SDimitry Andric raw_ostream &OS) { 4890b57cec5SDimitry Andric if (auto *ND = dyn_cast<NamedDecl>(D)) { 4900b57cec5SDimitry Andric PrintingPolicy Policy(LO); 4910b57cec5SDimitry Andric // Forward references can have different template argument names. Suppress 4920b57cec5SDimitry Andric // the template argument names in constructors to make their name more 4930b57cec5SDimitry Andric // stable. 4940b57cec5SDimitry Andric Policy.SuppressTemplateArgsInCXXConstructors = true; 4950b57cec5SDimitry Andric DeclarationName DeclName = ND->getDeclName(); 4960b57cec5SDimitry Andric if (DeclName.isEmpty()) 4970b57cec5SDimitry Andric return true; 4980b57cec5SDimitry Andric DeclName.print(OS, Policy); 4990b57cec5SDimitry Andric return false; 5000b57cec5SDimitry Andric } else { 5010b57cec5SDimitry Andric return true; 5020b57cec5SDimitry Andric } 5030b57cec5SDimitry Andric } 5040b57cec5SDimitry Andric 5050b57cec5SDimitry Andric StringRef index::getSymbolKindString(SymbolKind K) { 5060b57cec5SDimitry Andric switch (K) { 5070b57cec5SDimitry Andric case SymbolKind::Unknown: return "<unknown>"; 5080b57cec5SDimitry Andric case SymbolKind::Module: return "module"; 5090b57cec5SDimitry Andric case SymbolKind::Namespace: return "namespace"; 5100b57cec5SDimitry Andric case SymbolKind::NamespaceAlias: return "namespace-alias"; 5110b57cec5SDimitry Andric case SymbolKind::Macro: return "macro"; 5120b57cec5SDimitry Andric case SymbolKind::Enum: return "enum"; 5130b57cec5SDimitry Andric case SymbolKind::Struct: return "struct"; 5140b57cec5SDimitry Andric case SymbolKind::Class: return "class"; 5150b57cec5SDimitry Andric case SymbolKind::Protocol: return "protocol"; 5160b57cec5SDimitry Andric case SymbolKind::Extension: return "extension"; 5170b57cec5SDimitry Andric case SymbolKind::Union: return "union"; 5180b57cec5SDimitry Andric case SymbolKind::TypeAlias: return "type-alias"; 5190b57cec5SDimitry Andric case SymbolKind::Function: return "function"; 5200b57cec5SDimitry Andric case SymbolKind::Variable: return "variable"; 5210b57cec5SDimitry Andric case SymbolKind::Field: return "field"; 5220b57cec5SDimitry Andric case SymbolKind::EnumConstant: return "enumerator"; 5230b57cec5SDimitry Andric case SymbolKind::InstanceMethod: return "instance-method"; 5240b57cec5SDimitry Andric case SymbolKind::ClassMethod: return "class-method"; 5250b57cec5SDimitry Andric case SymbolKind::StaticMethod: return "static-method"; 5260b57cec5SDimitry Andric case SymbolKind::InstanceProperty: return "instance-property"; 5270b57cec5SDimitry Andric case SymbolKind::ClassProperty: return "class-property"; 5280b57cec5SDimitry Andric case SymbolKind::StaticProperty: return "static-property"; 5290b57cec5SDimitry Andric case SymbolKind::Constructor: return "constructor"; 5300b57cec5SDimitry Andric case SymbolKind::Destructor: return "destructor"; 531a7dea167SDimitry Andric case SymbolKind::ConversionFunction: return "conversion-func"; 5320b57cec5SDimitry Andric case SymbolKind::Parameter: return "param"; 5330b57cec5SDimitry Andric case SymbolKind::Using: return "using"; 5345ffd83dbSDimitry Andric case SymbolKind::TemplateTypeParm: return "template-type-param"; 5355ffd83dbSDimitry Andric case SymbolKind::TemplateTemplateParm: return "template-template-param"; 5365ffd83dbSDimitry Andric case SymbolKind::NonTypeTemplateParm: return "non-type-template-param"; 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric llvm_unreachable("invalid symbol kind"); 5390b57cec5SDimitry Andric } 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric StringRef index::getSymbolSubKindString(SymbolSubKind K) { 5420b57cec5SDimitry Andric switch (K) { 5430b57cec5SDimitry Andric case SymbolSubKind::None: return "<none>"; 5440b57cec5SDimitry Andric case SymbolSubKind::CXXCopyConstructor: return "cxx-copy-ctor"; 5450b57cec5SDimitry Andric case SymbolSubKind::CXXMoveConstructor: return "cxx-move-ctor"; 5460b57cec5SDimitry Andric case SymbolSubKind::AccessorGetter: return "acc-get"; 5470b57cec5SDimitry Andric case SymbolSubKind::AccessorSetter: return "acc-set"; 5480b57cec5SDimitry Andric case SymbolSubKind::UsingTypename: return "using-typename"; 5490b57cec5SDimitry Andric case SymbolSubKind::UsingValue: return "using-value"; 550*fe6060f1SDimitry Andric case SymbolSubKind::UsingEnum: 551*fe6060f1SDimitry Andric return "using-enum"; 5520b57cec5SDimitry Andric } 5530b57cec5SDimitry Andric llvm_unreachable("invalid symbol subkind"); 5540b57cec5SDimitry Andric } 5550b57cec5SDimitry Andric 5560b57cec5SDimitry Andric StringRef index::getSymbolLanguageString(SymbolLanguage K) { 5570b57cec5SDimitry Andric switch (K) { 5580b57cec5SDimitry Andric case SymbolLanguage::C: return "C"; 5590b57cec5SDimitry Andric case SymbolLanguage::ObjC: return "ObjC"; 5600b57cec5SDimitry Andric case SymbolLanguage::CXX: return "C++"; 5610b57cec5SDimitry Andric case SymbolLanguage::Swift: return "Swift"; 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric llvm_unreachable("invalid symbol language kind"); 5640b57cec5SDimitry Andric } 5650b57cec5SDimitry Andric 5660b57cec5SDimitry Andric void index::applyForEachSymbolProperty(SymbolPropertySet Props, 5670b57cec5SDimitry Andric llvm::function_ref<void(SymbolProperty)> Fn) { 5680b57cec5SDimitry Andric #define APPLY_FOR_PROPERTY(K) \ 5690b57cec5SDimitry Andric if (Props & (SymbolPropertySet)SymbolProperty::K) \ 5700b57cec5SDimitry Andric Fn(SymbolProperty::K) 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andric APPLY_FOR_PROPERTY(Generic); 5730b57cec5SDimitry Andric APPLY_FOR_PROPERTY(TemplatePartialSpecialization); 5740b57cec5SDimitry Andric APPLY_FOR_PROPERTY(TemplateSpecialization); 5750b57cec5SDimitry Andric APPLY_FOR_PROPERTY(UnitTest); 5760b57cec5SDimitry Andric APPLY_FOR_PROPERTY(IBAnnotated); 5770b57cec5SDimitry Andric APPLY_FOR_PROPERTY(IBOutletCollection); 5780b57cec5SDimitry Andric APPLY_FOR_PROPERTY(GKInspectable); 5790b57cec5SDimitry Andric APPLY_FOR_PROPERTY(Local); 5800b57cec5SDimitry Andric APPLY_FOR_PROPERTY(ProtocolInterface); 5810b57cec5SDimitry Andric 5820b57cec5SDimitry Andric #undef APPLY_FOR_PROPERTY 5830b57cec5SDimitry Andric } 5840b57cec5SDimitry Andric 5850b57cec5SDimitry Andric void index::printSymbolProperties(SymbolPropertySet Props, raw_ostream &OS) { 5860b57cec5SDimitry Andric bool VisitedOnce = false; 5870b57cec5SDimitry Andric applyForEachSymbolProperty(Props, [&](SymbolProperty Prop) { 5880b57cec5SDimitry Andric if (VisitedOnce) 5890b57cec5SDimitry Andric OS << ','; 5900b57cec5SDimitry Andric else 5910b57cec5SDimitry Andric VisitedOnce = true; 5920b57cec5SDimitry Andric switch (Prop) { 5930b57cec5SDimitry Andric case SymbolProperty::Generic: OS << "Gen"; break; 5940b57cec5SDimitry Andric case SymbolProperty::TemplatePartialSpecialization: OS << "TPS"; break; 5950b57cec5SDimitry Andric case SymbolProperty::TemplateSpecialization: OS << "TS"; break; 5960b57cec5SDimitry Andric case SymbolProperty::UnitTest: OS << "test"; break; 5970b57cec5SDimitry Andric case SymbolProperty::IBAnnotated: OS << "IB"; break; 5980b57cec5SDimitry Andric case SymbolProperty::IBOutletCollection: OS << "IBColl"; break; 5990b57cec5SDimitry Andric case SymbolProperty::GKInspectable: OS << "GKI"; break; 6000b57cec5SDimitry Andric case SymbolProperty::Local: OS << "local"; break; 6010b57cec5SDimitry Andric case SymbolProperty::ProtocolInterface: OS << "protocol"; break; 6020b57cec5SDimitry Andric } 6030b57cec5SDimitry Andric }); 6040b57cec5SDimitry Andric } 605