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