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'.
isUnitTestCase(const ObjCInterfaceDecl * D)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'.
isUnitTest(const ObjCMethodDecl * D)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;
395f757f3fSDimitry Andric if (!D->getSelector().getNameForSlot(0).starts_with("test"))
400b57cec5SDimitry Andric return false;
410b57cec5SDimitry Andric return isUnitTestCase(D->getClassInterface());
420b57cec5SDimitry Andric }
430b57cec5SDimitry Andric
checkForIBOutlets(const Decl * D,SymbolPropertySet & PropSet)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
isFunctionLocalSymbol(const Decl * D)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()) {
695f757f3fSDimitry Andric case Linkage::Invalid:
705f757f3fSDimitry Andric llvm_unreachable("Linkage hasn't been computed!");
715f757f3fSDimitry Andric case Linkage::None:
725f757f3fSDimitry Andric case Linkage::Internal:
730b57cec5SDimitry Andric return true;
745f757f3fSDimitry Andric case Linkage::VisibleNone:
755f757f3fSDimitry Andric case Linkage::UniqueExternal:
760b57cec5SDimitry Andric llvm_unreachable("Not a sema linkage");
775f757f3fSDimitry Andric case Linkage::Module:
785f757f3fSDimitry Andric case Linkage::External:
790b57cec5SDimitry Andric return false;
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric }
820b57cec5SDimitry Andric
830b57cec5SDimitry Andric return true;
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric
getSymbolInfo(const Decl * D)860b57cec5SDimitry Andric SymbolInfo index::getSymbolInfo(const Decl *D) {
870b57cec5SDimitry Andric assert(D);
880b57cec5SDimitry Andric SymbolInfo Info;
890b57cec5SDimitry Andric Info.Kind = SymbolKind::Unknown;
900b57cec5SDimitry Andric Info.SubKind = SymbolSubKind::None;
910b57cec5SDimitry Andric Info.Properties = SymbolPropertySet();
920b57cec5SDimitry Andric Info.Lang = SymbolLanguage::C;
930b57cec5SDimitry Andric
940b57cec5SDimitry Andric if (isFunctionLocalSymbol(D)) {
950b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Local;
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric if (isa<ObjCProtocolDecl>(D->getDeclContext())) {
980b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::ProtocolInterface;
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric
1010b57cec5SDimitry Andric if (auto *VT = dyn_cast<VarTemplateDecl>(D)) {
1020b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
1030b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
1040b57cec5SDimitry Andric // All other fields are filled from the templated decl.
1050b57cec5SDimitry Andric D = VT->getTemplatedDecl();
1060b57cec5SDimitry Andric }
1070b57cec5SDimitry Andric
1080b57cec5SDimitry Andric if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
1090b57cec5SDimitry Andric switch (TD->getTagKind()) {
1105f757f3fSDimitry Andric case TagTypeKind::Struct:
1110b57cec5SDimitry Andric Info.Kind = SymbolKind::Struct; break;
1125f757f3fSDimitry Andric case TagTypeKind::Union:
1130b57cec5SDimitry Andric Info.Kind = SymbolKind::Union; break;
1145f757f3fSDimitry Andric case TagTypeKind::Class:
1150b57cec5SDimitry Andric Info.Kind = SymbolKind::Class;
1160b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
1170b57cec5SDimitry Andric break;
1185f757f3fSDimitry Andric case TagTypeKind::Interface:
1190b57cec5SDimitry Andric Info.Kind = SymbolKind::Protocol;
1200b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
1210b57cec5SDimitry Andric break;
1225f757f3fSDimitry Andric case TagTypeKind::Enum:
1230b57cec5SDimitry Andric Info.Kind = SymbolKind::Enum; break;
1240b57cec5SDimitry Andric }
1250b57cec5SDimitry Andric
1260b57cec5SDimitry Andric if (const CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(D)) {
1270b57cec5SDimitry Andric if (!CXXRec->isCLike()) {
1280b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
1290b57cec5SDimitry Andric if (CXXRec->getDescribedClassTemplate()) {
1300b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric }
1340b57cec5SDimitry Andric
1350b57cec5SDimitry Andric if (isa<ClassTemplatePartialSpecializationDecl>(D)) {
1360b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
1370b57cec5SDimitry Andric Info.Properties |=
1380b57cec5SDimitry Andric (SymbolPropertySet)SymbolProperty::TemplatePartialSpecialization;
1390b57cec5SDimitry Andric } else if (isa<ClassTemplateSpecializationDecl>(D)) {
1400b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
1410b57cec5SDimitry Andric Info.Properties |=
1420b57cec5SDimitry Andric (SymbolPropertySet)SymbolProperty::TemplateSpecialization;
1430b57cec5SDimitry Andric }
1440b57cec5SDimitry Andric
1450b57cec5SDimitry Andric } else if (auto *VD = dyn_cast<VarDecl>(D)) {
1460b57cec5SDimitry Andric Info.Kind = SymbolKind::Variable;
1470b57cec5SDimitry Andric if (isa<ParmVarDecl>(D)) {
1480b57cec5SDimitry Andric Info.Kind = SymbolKind::Parameter;
1490b57cec5SDimitry Andric } else if (isa<CXXRecordDecl>(D->getDeclContext())) {
1500b57cec5SDimitry Andric Info.Kind = SymbolKind::StaticProperty;
1510b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric
1540b57cec5SDimitry Andric if (isa<VarTemplatePartialSpecializationDecl>(D)) {
1550b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
1560b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
1570b57cec5SDimitry Andric Info.Properties |=
1580b57cec5SDimitry Andric (SymbolPropertySet)SymbolProperty::TemplatePartialSpecialization;
1590b57cec5SDimitry Andric } else if (isa<VarTemplateSpecializationDecl>(D)) {
1600b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
1610b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
1620b57cec5SDimitry Andric Info.Properties |=
1630b57cec5SDimitry Andric (SymbolPropertySet)SymbolProperty::TemplateSpecialization;
1640b57cec5SDimitry Andric } else if (VD->getDescribedVarTemplate()) {
1650b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
1660b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric
1690b57cec5SDimitry Andric } else {
1700b57cec5SDimitry Andric switch (D->getKind()) {
1710b57cec5SDimitry Andric case Decl::Import:
1720b57cec5SDimitry Andric Info.Kind = SymbolKind::Module;
1730b57cec5SDimitry Andric break;
1740b57cec5SDimitry Andric case Decl::Typedef:
1750b57cec5SDimitry Andric Info.Kind = SymbolKind::TypeAlias; break; // Lang = C
1760b57cec5SDimitry Andric case Decl::Function:
1770b57cec5SDimitry Andric Info.Kind = SymbolKind::Function;
1780b57cec5SDimitry Andric break;
1790b57cec5SDimitry Andric case Decl::Field:
1800b57cec5SDimitry Andric case Decl::IndirectField:
1810b57cec5SDimitry Andric Info.Kind = SymbolKind::Field;
1820b57cec5SDimitry Andric if (const CXXRecordDecl *
1830b57cec5SDimitry Andric CXXRec = dyn_cast<CXXRecordDecl>(D->getDeclContext())) {
1840b57cec5SDimitry Andric if (!CXXRec->isCLike())
1850b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
1860b57cec5SDimitry Andric }
1870b57cec5SDimitry Andric break;
1880b57cec5SDimitry Andric case Decl::EnumConstant:
1890b57cec5SDimitry Andric Info.Kind = SymbolKind::EnumConstant; break;
1900b57cec5SDimitry Andric case Decl::ObjCInterface:
1910b57cec5SDimitry Andric case Decl::ObjCImplementation: {
1920b57cec5SDimitry Andric Info.Kind = SymbolKind::Class;
1930b57cec5SDimitry Andric Info.Lang = SymbolLanguage::ObjC;
1940b57cec5SDimitry Andric const ObjCInterfaceDecl *ClsD = dyn_cast<ObjCInterfaceDecl>(D);
1950b57cec5SDimitry Andric if (!ClsD)
1960b57cec5SDimitry Andric ClsD = cast<ObjCImplementationDecl>(D)->getClassInterface();
1970b57cec5SDimitry Andric if (isUnitTestCase(ClsD))
1980b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::UnitTest;
1990b57cec5SDimitry Andric break;
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric case Decl::ObjCProtocol:
2020b57cec5SDimitry Andric Info.Kind = SymbolKind::Protocol;
2030b57cec5SDimitry Andric Info.Lang = SymbolLanguage::ObjC;
2040b57cec5SDimitry Andric break;
2050b57cec5SDimitry Andric case Decl::ObjCCategory:
2060b57cec5SDimitry Andric case Decl::ObjCCategoryImpl: {
2070b57cec5SDimitry Andric Info.Kind = SymbolKind::Extension;
2080b57cec5SDimitry Andric Info.Lang = SymbolLanguage::ObjC;
2090b57cec5SDimitry Andric const ObjCInterfaceDecl *ClsD = nullptr;
2100b57cec5SDimitry Andric if (auto *CatD = dyn_cast<ObjCCategoryDecl>(D))
2110b57cec5SDimitry Andric ClsD = CatD->getClassInterface();
2120b57cec5SDimitry Andric else
2130b57cec5SDimitry Andric ClsD = cast<ObjCCategoryImplDecl>(D)->getClassInterface();
2140b57cec5SDimitry Andric if (isUnitTestCase(ClsD))
2150b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::UnitTest;
2160b57cec5SDimitry Andric break;
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric case Decl::ObjCMethod: {
2190b57cec5SDimitry Andric const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D);
2200b57cec5SDimitry Andric Info.Kind = MD->isInstanceMethod() ? SymbolKind::InstanceMethod : SymbolKind::ClassMethod;
2210b57cec5SDimitry Andric if (MD->isPropertyAccessor()) {
2220b57cec5SDimitry Andric if (MD->param_size())
2230b57cec5SDimitry Andric Info.SubKind = SymbolSubKind::AccessorSetter;
2240b57cec5SDimitry Andric else
2250b57cec5SDimitry Andric Info.SubKind = SymbolSubKind::AccessorGetter;
2260b57cec5SDimitry Andric }
2270b57cec5SDimitry Andric Info.Lang = SymbolLanguage::ObjC;
2280b57cec5SDimitry Andric if (isUnitTest(MD))
2290b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::UnitTest;
2300b57cec5SDimitry Andric if (D->hasAttr<IBActionAttr>())
2310b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::IBAnnotated;
2320b57cec5SDimitry Andric break;
2330b57cec5SDimitry Andric }
2340b57cec5SDimitry Andric case Decl::ObjCProperty:
2350b57cec5SDimitry Andric Info.Kind = SymbolKind::InstanceProperty;
2360b57cec5SDimitry Andric Info.Lang = SymbolLanguage::ObjC;
2370b57cec5SDimitry Andric checkForIBOutlets(D, Info.Properties);
2380b57cec5SDimitry Andric if (auto *Annot = D->getAttr<AnnotateAttr>()) {
2390b57cec5SDimitry Andric if (Annot->getAnnotation() == "gk_inspectable")
2400b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::GKInspectable;
2410b57cec5SDimitry Andric }
2420b57cec5SDimitry Andric break;
2430b57cec5SDimitry Andric case Decl::ObjCIvar:
2440b57cec5SDimitry Andric Info.Kind = SymbolKind::Field;
2450b57cec5SDimitry Andric Info.Lang = SymbolLanguage::ObjC;
2460b57cec5SDimitry Andric checkForIBOutlets(D, Info.Properties);
2470b57cec5SDimitry Andric break;
2480b57cec5SDimitry Andric case Decl::Namespace:
2490b57cec5SDimitry Andric Info.Kind = SymbolKind::Namespace;
2500b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
2510b57cec5SDimitry Andric break;
2520b57cec5SDimitry Andric case Decl::NamespaceAlias:
2530b57cec5SDimitry Andric Info.Kind = SymbolKind::NamespaceAlias;
2540b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
2550b57cec5SDimitry Andric break;
2560b57cec5SDimitry Andric case Decl::CXXConstructor: {
2570b57cec5SDimitry Andric Info.Kind = SymbolKind::Constructor;
2580b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
2590b57cec5SDimitry Andric auto *CD = cast<CXXConstructorDecl>(D);
2600b57cec5SDimitry Andric if (CD->isCopyConstructor())
2610b57cec5SDimitry Andric Info.SubKind = SymbolSubKind::CXXCopyConstructor;
2620b57cec5SDimitry Andric else if (CD->isMoveConstructor())
2630b57cec5SDimitry Andric Info.SubKind = SymbolSubKind::CXXMoveConstructor;
2640b57cec5SDimitry Andric break;
2650b57cec5SDimitry Andric }
2660b57cec5SDimitry Andric case Decl::CXXDestructor:
2670b57cec5SDimitry Andric Info.Kind = SymbolKind::Destructor;
2680b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
2690b57cec5SDimitry Andric break;
2700b57cec5SDimitry Andric case Decl::CXXConversion:
2710b57cec5SDimitry Andric Info.Kind = SymbolKind::ConversionFunction;
2720b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
2730b57cec5SDimitry Andric break;
2740b57cec5SDimitry Andric case Decl::CXXMethod: {
2750b57cec5SDimitry Andric const CXXMethodDecl *MD = cast<CXXMethodDecl>(D);
2760b57cec5SDimitry Andric if (MD->isStatic())
2770b57cec5SDimitry Andric Info.Kind = SymbolKind::StaticMethod;
2780b57cec5SDimitry Andric else
2790b57cec5SDimitry Andric Info.Kind = SymbolKind::InstanceMethod;
2800b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
2810b57cec5SDimitry Andric break;
2820b57cec5SDimitry Andric }
2830b57cec5SDimitry Andric case Decl::ClassTemplate:
2840b57cec5SDimitry Andric Info.Kind = SymbolKind::Class;
2850b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
2860b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
2870b57cec5SDimitry Andric break;
2880b57cec5SDimitry Andric case Decl::FunctionTemplate:
2890b57cec5SDimitry Andric Info.Kind = SymbolKind::Function;
2900b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
2910b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
2920b57cec5SDimitry Andric if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(
2930b57cec5SDimitry Andric cast<FunctionTemplateDecl>(D)->getTemplatedDecl())) {
2940b57cec5SDimitry Andric if (isa<CXXConstructorDecl>(MD))
2950b57cec5SDimitry Andric Info.Kind = SymbolKind::Constructor;
2960b57cec5SDimitry Andric else if (isa<CXXDestructorDecl>(MD))
2970b57cec5SDimitry Andric Info.Kind = SymbolKind::Destructor;
2980b57cec5SDimitry Andric else if (isa<CXXConversionDecl>(MD))
2990b57cec5SDimitry Andric Info.Kind = SymbolKind::ConversionFunction;
3000b57cec5SDimitry Andric else {
3010b57cec5SDimitry Andric if (MD->isStatic())
3020b57cec5SDimitry Andric Info.Kind = SymbolKind::StaticMethod;
3030b57cec5SDimitry Andric else
3040b57cec5SDimitry Andric Info.Kind = SymbolKind::InstanceMethod;
3050b57cec5SDimitry Andric }
3060b57cec5SDimitry Andric }
3070b57cec5SDimitry Andric break;
3080b57cec5SDimitry Andric case Decl::TypeAliasTemplate:
3090b57cec5SDimitry Andric Info.Kind = SymbolKind::TypeAlias;
3100b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
3110b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
3120b57cec5SDimitry Andric break;
3130b57cec5SDimitry Andric case Decl::TypeAlias:
3140b57cec5SDimitry Andric Info.Kind = SymbolKind::TypeAlias;
3150b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
3160b57cec5SDimitry Andric break;
3170b57cec5SDimitry Andric case Decl::UnresolvedUsingTypename:
3180b57cec5SDimitry Andric Info.Kind = SymbolKind::Using;
3190b57cec5SDimitry Andric Info.SubKind = SymbolSubKind::UsingTypename;
3200b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
3210b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
3220b57cec5SDimitry Andric break;
3230b57cec5SDimitry Andric case Decl::UnresolvedUsingValue:
3240b57cec5SDimitry Andric Info.Kind = SymbolKind::Using;
3250b57cec5SDimitry Andric Info.SubKind = SymbolSubKind::UsingValue;
3260b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
3270b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
3280b57cec5SDimitry Andric break;
3290b57cec5SDimitry Andric case Decl::Using:
3300b57cec5SDimitry Andric Info.Kind = SymbolKind::Using;
3310b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
3320b57cec5SDimitry Andric break;
333fe6060f1SDimitry Andric case Decl::UsingEnum:
334fe6060f1SDimitry Andric Info.Kind = SymbolKind::Using;
335fe6060f1SDimitry Andric Info.Lang = SymbolLanguage::CXX;
336fe6060f1SDimitry Andric Info.SubKind = SymbolSubKind::UsingEnum;
337fe6060f1SDimitry Andric break;
3380b57cec5SDimitry Andric case Decl::Binding:
3390b57cec5SDimitry Andric Info.Kind = SymbolKind::Variable;
3400b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
3410b57cec5SDimitry Andric break;
3420b57cec5SDimitry Andric case Decl::MSProperty:
3430b57cec5SDimitry Andric Info.Kind = SymbolKind::InstanceProperty;
3440b57cec5SDimitry Andric if (const CXXRecordDecl *CXXRec =
3450b57cec5SDimitry Andric dyn_cast<CXXRecordDecl>(D->getDeclContext())) {
3460b57cec5SDimitry Andric if (!CXXRec->isCLike())
3470b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
3480b57cec5SDimitry Andric }
3490b57cec5SDimitry Andric break;
3500b57cec5SDimitry Andric case Decl::ClassTemplatePartialSpecialization:
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;
37481ad6265SDimitry Andric case Decl::Concept:
37581ad6265SDimitry Andric Info.Kind = SymbolKind::Concept;
37681ad6265SDimitry Andric break;
3770b57cec5SDimitry Andric // Other decls get the 'unknown' kind.
3780b57cec5SDimitry Andric default:
3790b57cec5SDimitry Andric break;
3800b57cec5SDimitry Andric }
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric
3830b57cec5SDimitry Andric if (Info.Kind == SymbolKind::Unknown)
3840b57cec5SDimitry Andric return Info;
3850b57cec5SDimitry Andric
3860b57cec5SDimitry Andric if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
3870b57cec5SDimitry Andric if (FD->getTemplatedKind() ==
3880b57cec5SDimitry Andric FunctionDecl::TK_FunctionTemplateSpecialization) {
3890b57cec5SDimitry Andric Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
3900b57cec5SDimitry Andric Info.Properties |=
3910b57cec5SDimitry Andric (SymbolPropertySet)SymbolProperty::TemplateSpecialization;
3920b57cec5SDimitry Andric }
3930b57cec5SDimitry Andric }
3940b57cec5SDimitry Andric
3950b57cec5SDimitry Andric if (Info.Properties & (SymbolPropertySet)SymbolProperty::Generic)
3960b57cec5SDimitry Andric Info.Lang = SymbolLanguage::CXX;
3970b57cec5SDimitry Andric
3980b57cec5SDimitry Andric if (auto *attr = D->getExternalSourceSymbolAttr()) {
3990b57cec5SDimitry Andric if (attr->getLanguage() == "Swift")
4000b57cec5SDimitry Andric Info.Lang = SymbolLanguage::Swift;
4010b57cec5SDimitry Andric }
4020b57cec5SDimitry Andric
4030b57cec5SDimitry Andric return Info;
4040b57cec5SDimitry Andric }
4050b57cec5SDimitry Andric
getSymbolInfoForMacro(const MacroInfo &)4060b57cec5SDimitry Andric SymbolInfo index::getSymbolInfoForMacro(const MacroInfo &) {
4070b57cec5SDimitry Andric SymbolInfo Info;
4080b57cec5SDimitry Andric Info.Kind = SymbolKind::Macro;
4090b57cec5SDimitry Andric Info.SubKind = SymbolSubKind::None;
4100b57cec5SDimitry Andric Info.Properties = SymbolPropertySet();
4110b57cec5SDimitry Andric Info.Lang = SymbolLanguage::C;
4120b57cec5SDimitry Andric return Info;
4130b57cec5SDimitry Andric }
4140b57cec5SDimitry Andric
applyForEachSymbolRoleInterruptible(SymbolRoleSet Roles,llvm::function_ref<bool (SymbolRole)> Fn)4150b57cec5SDimitry Andric bool index::applyForEachSymbolRoleInterruptible(SymbolRoleSet Roles,
4160b57cec5SDimitry Andric llvm::function_ref<bool(SymbolRole)> Fn) {
4170b57cec5SDimitry Andric #define APPLY_FOR_ROLE(Role) \
4180b57cec5SDimitry Andric if (Roles & (unsigned)SymbolRole::Role) \
4190b57cec5SDimitry Andric if (!Fn(SymbolRole::Role)) \
4200b57cec5SDimitry Andric return false;
4210b57cec5SDimitry Andric
4220b57cec5SDimitry Andric APPLY_FOR_ROLE(Declaration);
4230b57cec5SDimitry Andric APPLY_FOR_ROLE(Definition);
4240b57cec5SDimitry Andric APPLY_FOR_ROLE(Reference);
4250b57cec5SDimitry Andric APPLY_FOR_ROLE(Read);
4260b57cec5SDimitry Andric APPLY_FOR_ROLE(Write);
4270b57cec5SDimitry Andric APPLY_FOR_ROLE(Call);
4280b57cec5SDimitry Andric APPLY_FOR_ROLE(Dynamic);
4290b57cec5SDimitry Andric APPLY_FOR_ROLE(AddressOf);
4300b57cec5SDimitry Andric APPLY_FOR_ROLE(Implicit);
4310b57cec5SDimitry Andric APPLY_FOR_ROLE(Undefinition);
4320b57cec5SDimitry Andric APPLY_FOR_ROLE(RelationChildOf);
4330b57cec5SDimitry Andric APPLY_FOR_ROLE(RelationBaseOf);
4340b57cec5SDimitry Andric APPLY_FOR_ROLE(RelationOverrideOf);
4350b57cec5SDimitry Andric APPLY_FOR_ROLE(RelationReceivedBy);
4360b57cec5SDimitry Andric APPLY_FOR_ROLE(RelationCalledBy);
4370b57cec5SDimitry Andric APPLY_FOR_ROLE(RelationExtendedBy);
4380b57cec5SDimitry Andric APPLY_FOR_ROLE(RelationAccessorOf);
4390b57cec5SDimitry Andric APPLY_FOR_ROLE(RelationContainedBy);
4400b57cec5SDimitry Andric APPLY_FOR_ROLE(RelationIBTypeOf);
4410b57cec5SDimitry Andric APPLY_FOR_ROLE(RelationSpecializationOf);
4420b57cec5SDimitry Andric APPLY_FOR_ROLE(NameReference);
4430b57cec5SDimitry Andric
4440b57cec5SDimitry Andric #undef APPLY_FOR_ROLE
4450b57cec5SDimitry Andric
4460b57cec5SDimitry Andric return true;
4470b57cec5SDimitry Andric }
4480b57cec5SDimitry Andric
applyForEachSymbolRole(SymbolRoleSet Roles,llvm::function_ref<void (SymbolRole)> Fn)4490b57cec5SDimitry Andric void index::applyForEachSymbolRole(SymbolRoleSet Roles,
4500b57cec5SDimitry Andric llvm::function_ref<void(SymbolRole)> Fn) {
4510b57cec5SDimitry Andric applyForEachSymbolRoleInterruptible(Roles, [&](SymbolRole r) -> bool {
4520b57cec5SDimitry Andric Fn(r);
4530b57cec5SDimitry Andric return true;
4540b57cec5SDimitry Andric });
4550b57cec5SDimitry Andric }
4560b57cec5SDimitry Andric
printSymbolRoles(SymbolRoleSet Roles,raw_ostream & OS)4570b57cec5SDimitry Andric void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) {
4580b57cec5SDimitry Andric bool VisitedOnce = false;
4590b57cec5SDimitry Andric applyForEachSymbolRole(Roles, [&](SymbolRole Role) {
4600b57cec5SDimitry Andric if (VisitedOnce)
4610b57cec5SDimitry Andric OS << ',';
4620b57cec5SDimitry Andric else
4630b57cec5SDimitry Andric VisitedOnce = true;
4640b57cec5SDimitry Andric switch (Role) {
4650b57cec5SDimitry Andric case SymbolRole::Declaration: OS << "Decl"; break;
4660b57cec5SDimitry Andric case SymbolRole::Definition: OS << "Def"; break;
4670b57cec5SDimitry Andric case SymbolRole::Reference: OS << "Ref"; break;
4680b57cec5SDimitry Andric case SymbolRole::Read: OS << "Read"; break;
4690b57cec5SDimitry Andric case SymbolRole::Write: OS << "Writ"; break;
4700b57cec5SDimitry Andric case SymbolRole::Call: OS << "Call"; break;
4710b57cec5SDimitry Andric case SymbolRole::Dynamic: OS << "Dyn"; break;
4720b57cec5SDimitry Andric case SymbolRole::AddressOf: OS << "Addr"; break;
4730b57cec5SDimitry Andric case SymbolRole::Implicit: OS << "Impl"; break;
4740b57cec5SDimitry Andric case SymbolRole::Undefinition: OS << "Undef"; break;
4750b57cec5SDimitry Andric case SymbolRole::RelationChildOf: OS << "RelChild"; break;
4760b57cec5SDimitry Andric case SymbolRole::RelationBaseOf: OS << "RelBase"; break;
4770b57cec5SDimitry Andric case SymbolRole::RelationOverrideOf: OS << "RelOver"; break;
4780b57cec5SDimitry Andric case SymbolRole::RelationReceivedBy: OS << "RelRec"; break;
4790b57cec5SDimitry Andric case SymbolRole::RelationCalledBy: OS << "RelCall"; break;
4800b57cec5SDimitry Andric case SymbolRole::RelationExtendedBy: OS << "RelExt"; break;
4810b57cec5SDimitry Andric case SymbolRole::RelationAccessorOf: OS << "RelAcc"; break;
4820b57cec5SDimitry Andric case SymbolRole::RelationContainedBy: OS << "RelCont"; break;
4830b57cec5SDimitry Andric case SymbolRole::RelationIBTypeOf: OS << "RelIBType"; break;
4840b57cec5SDimitry Andric case SymbolRole::RelationSpecializationOf: OS << "RelSpecialization"; break;
4850b57cec5SDimitry Andric case SymbolRole::NameReference: OS << "NameReference"; break;
4860b57cec5SDimitry Andric }
4870b57cec5SDimitry Andric });
4880b57cec5SDimitry Andric }
4890b57cec5SDimitry Andric
printSymbolName(const Decl * D,const LangOptions & LO,raw_ostream & OS)4900b57cec5SDimitry Andric bool index::printSymbolName(const Decl *D, const LangOptions &LO,
4910b57cec5SDimitry Andric raw_ostream &OS) {
4920b57cec5SDimitry Andric if (auto *ND = dyn_cast<NamedDecl>(D)) {
4930b57cec5SDimitry Andric PrintingPolicy Policy(LO);
4940b57cec5SDimitry Andric // Forward references can have different template argument names. Suppress
4950b57cec5SDimitry Andric // the template argument names in constructors to make their name more
4960b57cec5SDimitry Andric // stable.
4970b57cec5SDimitry Andric Policy.SuppressTemplateArgsInCXXConstructors = true;
4980b57cec5SDimitry Andric DeclarationName DeclName = ND->getDeclName();
4990b57cec5SDimitry Andric if (DeclName.isEmpty())
5000b57cec5SDimitry Andric return true;
5010b57cec5SDimitry Andric DeclName.print(OS, Policy);
5020b57cec5SDimitry Andric return false;
5030b57cec5SDimitry Andric } else {
5040b57cec5SDimitry Andric return true;
5050b57cec5SDimitry Andric }
5060b57cec5SDimitry Andric }
5070b57cec5SDimitry Andric
getSymbolKindString(SymbolKind K)5080b57cec5SDimitry Andric StringRef index::getSymbolKindString(SymbolKind K) {
5090b57cec5SDimitry Andric switch (K) {
5100b57cec5SDimitry Andric case SymbolKind::Unknown: return "<unknown>";
5110b57cec5SDimitry Andric case SymbolKind::Module: return "module";
5120b57cec5SDimitry Andric case SymbolKind::Namespace: return "namespace";
5130b57cec5SDimitry Andric case SymbolKind::NamespaceAlias: return "namespace-alias";
5140b57cec5SDimitry Andric case SymbolKind::Macro: return "macro";
5150b57cec5SDimitry Andric case SymbolKind::Enum: return "enum";
5160b57cec5SDimitry Andric case SymbolKind::Struct: return "struct";
5170b57cec5SDimitry Andric case SymbolKind::Class: return "class";
5180b57cec5SDimitry Andric case SymbolKind::Protocol: return "protocol";
5190b57cec5SDimitry Andric case SymbolKind::Extension: return "extension";
5200b57cec5SDimitry Andric case SymbolKind::Union: return "union";
5210b57cec5SDimitry Andric case SymbolKind::TypeAlias: return "type-alias";
5220b57cec5SDimitry Andric case SymbolKind::Function: return "function";
5230b57cec5SDimitry Andric case SymbolKind::Variable: return "variable";
5240b57cec5SDimitry Andric case SymbolKind::Field: return "field";
5250b57cec5SDimitry Andric case SymbolKind::EnumConstant: return "enumerator";
5260b57cec5SDimitry Andric case SymbolKind::InstanceMethod: return "instance-method";
5270b57cec5SDimitry Andric case SymbolKind::ClassMethod: return "class-method";
5280b57cec5SDimitry Andric case SymbolKind::StaticMethod: return "static-method";
5290b57cec5SDimitry Andric case SymbolKind::InstanceProperty: return "instance-property";
5300b57cec5SDimitry Andric case SymbolKind::ClassProperty: return "class-property";
5310b57cec5SDimitry Andric case SymbolKind::StaticProperty: return "static-property";
5320b57cec5SDimitry Andric case SymbolKind::Constructor: return "constructor";
5330b57cec5SDimitry Andric case SymbolKind::Destructor: return "destructor";
534a7dea167SDimitry Andric case SymbolKind::ConversionFunction: return "conversion-func";
5350b57cec5SDimitry Andric case SymbolKind::Parameter: return "param";
5360b57cec5SDimitry Andric case SymbolKind::Using: return "using";
5375ffd83dbSDimitry Andric case SymbolKind::TemplateTypeParm: return "template-type-param";
5385ffd83dbSDimitry Andric case SymbolKind::TemplateTemplateParm: return "template-template-param";
5395ffd83dbSDimitry Andric case SymbolKind::NonTypeTemplateParm: return "non-type-template-param";
54081ad6265SDimitry Andric case SymbolKind::Concept:
54181ad6265SDimitry Andric return "concept";
5420b57cec5SDimitry Andric }
5430b57cec5SDimitry Andric llvm_unreachable("invalid symbol kind");
5440b57cec5SDimitry Andric }
5450b57cec5SDimitry Andric
getSymbolSubKindString(SymbolSubKind K)5460b57cec5SDimitry Andric StringRef index::getSymbolSubKindString(SymbolSubKind K) {
5470b57cec5SDimitry Andric switch (K) {
5480b57cec5SDimitry Andric case SymbolSubKind::None: return "<none>";
5490b57cec5SDimitry Andric case SymbolSubKind::CXXCopyConstructor: return "cxx-copy-ctor";
5500b57cec5SDimitry Andric case SymbolSubKind::CXXMoveConstructor: return "cxx-move-ctor";
5510b57cec5SDimitry Andric case SymbolSubKind::AccessorGetter: return "acc-get";
5520b57cec5SDimitry Andric case SymbolSubKind::AccessorSetter: return "acc-set";
5530b57cec5SDimitry Andric case SymbolSubKind::UsingTypename: return "using-typename";
5540b57cec5SDimitry Andric case SymbolSubKind::UsingValue: return "using-value";
555*0fca6ea1SDimitry Andric case SymbolSubKind::UsingEnum: return "using-enum";
5560b57cec5SDimitry Andric }
5570b57cec5SDimitry Andric llvm_unreachable("invalid symbol subkind");
5580b57cec5SDimitry Andric }
5590b57cec5SDimitry Andric
getSymbolLanguageString(SymbolLanguage K)5600b57cec5SDimitry Andric StringRef index::getSymbolLanguageString(SymbolLanguage K) {
5610b57cec5SDimitry Andric switch (K) {
5620b57cec5SDimitry Andric case SymbolLanguage::C: return "C";
5630b57cec5SDimitry Andric case SymbolLanguage::ObjC: return "ObjC";
5640b57cec5SDimitry Andric case SymbolLanguage::CXX: return "C++";
5650b57cec5SDimitry Andric case SymbolLanguage::Swift: return "Swift";
5660b57cec5SDimitry Andric }
5670b57cec5SDimitry Andric llvm_unreachable("invalid symbol language kind");
5680b57cec5SDimitry Andric }
5690b57cec5SDimitry Andric
applyForEachSymbolProperty(SymbolPropertySet Props,llvm::function_ref<void (SymbolProperty)> Fn)5700b57cec5SDimitry Andric void index::applyForEachSymbolProperty(SymbolPropertySet Props,
5710b57cec5SDimitry Andric llvm::function_ref<void(SymbolProperty)> Fn) {
5720b57cec5SDimitry Andric #define APPLY_FOR_PROPERTY(K) \
5730b57cec5SDimitry Andric if (Props & (SymbolPropertySet)SymbolProperty::K) \
5740b57cec5SDimitry Andric Fn(SymbolProperty::K)
5750b57cec5SDimitry Andric
5760b57cec5SDimitry Andric APPLY_FOR_PROPERTY(Generic);
5770b57cec5SDimitry Andric APPLY_FOR_PROPERTY(TemplatePartialSpecialization);
5780b57cec5SDimitry Andric APPLY_FOR_PROPERTY(TemplateSpecialization);
5790b57cec5SDimitry Andric APPLY_FOR_PROPERTY(UnitTest);
5800b57cec5SDimitry Andric APPLY_FOR_PROPERTY(IBAnnotated);
5810b57cec5SDimitry Andric APPLY_FOR_PROPERTY(IBOutletCollection);
5820b57cec5SDimitry Andric APPLY_FOR_PROPERTY(GKInspectable);
5830b57cec5SDimitry Andric APPLY_FOR_PROPERTY(Local);
5840b57cec5SDimitry Andric APPLY_FOR_PROPERTY(ProtocolInterface);
5850b57cec5SDimitry Andric
5860b57cec5SDimitry Andric #undef APPLY_FOR_PROPERTY
5870b57cec5SDimitry Andric }
5880b57cec5SDimitry Andric
printSymbolProperties(SymbolPropertySet Props,raw_ostream & OS)5890b57cec5SDimitry Andric void index::printSymbolProperties(SymbolPropertySet Props, raw_ostream &OS) {
5900b57cec5SDimitry Andric bool VisitedOnce = false;
5910b57cec5SDimitry Andric applyForEachSymbolProperty(Props, [&](SymbolProperty Prop) {
5920b57cec5SDimitry Andric if (VisitedOnce)
5930b57cec5SDimitry Andric OS << ',';
5940b57cec5SDimitry Andric else
5950b57cec5SDimitry Andric VisitedOnce = true;
5960b57cec5SDimitry Andric switch (Prop) {
5970b57cec5SDimitry Andric case SymbolProperty::Generic: OS << "Gen"; break;
5980b57cec5SDimitry Andric case SymbolProperty::TemplatePartialSpecialization: OS << "TPS"; break;
5990b57cec5SDimitry Andric case SymbolProperty::TemplateSpecialization: OS << "TS"; break;
6000b57cec5SDimitry Andric case SymbolProperty::UnitTest: OS << "test"; break;
6010b57cec5SDimitry Andric case SymbolProperty::IBAnnotated: OS << "IB"; break;
6020b57cec5SDimitry Andric case SymbolProperty::IBOutletCollection: OS << "IBColl"; break;
6030b57cec5SDimitry Andric case SymbolProperty::GKInspectable: OS << "GKI"; break;
6040b57cec5SDimitry Andric case SymbolProperty::Local: OS << "local"; break;
6050b57cec5SDimitry Andric case SymbolProperty::ProtocolInterface: OS << "protocol"; break;
6060b57cec5SDimitry Andric }
6070b57cec5SDimitry Andric });
6080b57cec5SDimitry Andric }
609