xref: /freebsd/contrib/llvm-project/clang/lib/Index/IndexSymbol.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
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