1 //===--- IndexSymbol.cpp - Types and functions for indexing symbols -------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "clang/Index/IndexSymbol.h" 11 #include "clang/AST/DeclCXX.h" 12 #include "clang/AST/DeclObjC.h" 13 #include "clang/AST/DeclTemplate.h" 14 #include "clang/AST/PrettyPrinter.h" 15 16 using namespace clang; 17 using namespace clang::index; 18 19 SymbolInfo index::getSymbolInfo(const Decl *D) { 20 assert(D); 21 SymbolInfo Info; 22 Info.Kind = SymbolKind::Unknown; 23 Info.TemplateKind = SymbolCXXTemplateKind::NonTemplate; 24 Info.Lang = SymbolLanguage::C; 25 26 if (const TagDecl *TD = dyn_cast<TagDecl>(D)) { 27 switch (TD->getTagKind()) { 28 case TTK_Struct: 29 Info.Kind = SymbolKind::Struct; break; 30 case TTK_Union: 31 Info.Kind = SymbolKind::Union; break; 32 case TTK_Class: 33 Info.Kind = SymbolKind::CXXClass; 34 Info.Lang = SymbolLanguage::CXX; 35 break; 36 case TTK_Interface: 37 Info.Kind = SymbolKind::CXXInterface; 38 Info.Lang = SymbolLanguage::CXX; 39 break; 40 case TTK_Enum: 41 Info.Kind = SymbolKind::Enum; break; 42 } 43 44 if (const CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(D)) 45 if (!CXXRec->isCLike()) 46 Info.Lang = SymbolLanguage::CXX; 47 48 if (isa<ClassTemplatePartialSpecializationDecl>(D)) { 49 Info.TemplateKind = SymbolCXXTemplateKind::TemplatePartialSpecialization; 50 } else if (isa<ClassTemplateSpecializationDecl>(D)) { 51 Info.TemplateKind = SymbolCXXTemplateKind::TemplateSpecialization; 52 } 53 54 } else { 55 switch (D->getKind()) { 56 case Decl::Typedef: 57 Info.Kind = SymbolKind::Typedef; break; 58 case Decl::Function: 59 Info.Kind = SymbolKind::Function; 60 break; 61 case Decl::ParmVar: 62 Info.Kind = SymbolKind::Variable; 63 break; 64 case Decl::Var: 65 Info.Kind = SymbolKind::Variable; 66 if (isa<CXXRecordDecl>(D->getDeclContext())) { 67 Info.Kind = SymbolKind::CXXStaticVariable; 68 Info.Lang = SymbolLanguage::CXX; 69 } 70 break; 71 case Decl::Field: 72 Info.Kind = SymbolKind::Field; 73 if (const CXXRecordDecl * 74 CXXRec = dyn_cast<CXXRecordDecl>(D->getDeclContext())) { 75 if (!CXXRec->isCLike()) 76 Info.Lang = SymbolLanguage::CXX; 77 } 78 break; 79 case Decl::EnumConstant: 80 Info.Kind = SymbolKind::EnumConstant; break; 81 case Decl::ObjCInterface: 82 case Decl::ObjCImplementation: 83 Info.Kind = SymbolKind::ObjCClass; 84 Info.Lang = SymbolLanguage::ObjC; 85 break; 86 case Decl::ObjCProtocol: 87 Info.Kind = SymbolKind::ObjCProtocol; 88 Info.Lang = SymbolLanguage::ObjC; 89 break; 90 case Decl::ObjCCategory: 91 case Decl::ObjCCategoryImpl: 92 Info.Kind = SymbolKind::ObjCCategory; 93 Info.Lang = SymbolLanguage::ObjC; 94 break; 95 case Decl::ObjCMethod: 96 if (cast<ObjCMethodDecl>(D)->isInstanceMethod()) 97 Info.Kind = SymbolKind::ObjCInstanceMethod; 98 else 99 Info.Kind = SymbolKind::ObjCClassMethod; 100 Info.Lang = SymbolLanguage::ObjC; 101 break; 102 case Decl::ObjCProperty: 103 Info.Kind = SymbolKind::ObjCProperty; 104 Info.Lang = SymbolLanguage::ObjC; 105 break; 106 case Decl::ObjCIvar: 107 Info.Kind = SymbolKind::ObjCIvar; 108 Info.Lang = SymbolLanguage::ObjC; 109 break; 110 case Decl::Namespace: 111 Info.Kind = SymbolKind::CXXNamespace; 112 Info.Lang = SymbolLanguage::CXX; 113 break; 114 case Decl::NamespaceAlias: 115 Info.Kind = SymbolKind::CXXNamespaceAlias; 116 Info.Lang = SymbolLanguage::CXX; 117 break; 118 case Decl::CXXConstructor: 119 Info.Kind = SymbolKind::CXXConstructor; 120 Info.Lang = SymbolLanguage::CXX; 121 break; 122 case Decl::CXXDestructor: 123 Info.Kind = SymbolKind::CXXDestructor; 124 Info.Lang = SymbolLanguage::CXX; 125 break; 126 case Decl::CXXConversion: 127 Info.Kind = SymbolKind::CXXConversionFunction; 128 Info.Lang = SymbolLanguage::CXX; 129 break; 130 case Decl::CXXMethod: { 131 const CXXMethodDecl *MD = cast<CXXMethodDecl>(D); 132 if (MD->isStatic()) 133 Info.Kind = SymbolKind::CXXStaticMethod; 134 else 135 Info.Kind = SymbolKind::CXXInstanceMethod; 136 Info.Lang = SymbolLanguage::CXX; 137 break; 138 } 139 case Decl::ClassTemplate: 140 Info.Kind = SymbolKind::CXXClass; 141 Info.TemplateKind = SymbolCXXTemplateKind::Template; 142 break; 143 case Decl::FunctionTemplate: 144 Info.Kind = SymbolKind::Function; 145 Info.TemplateKind = SymbolCXXTemplateKind::Template; 146 if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>( 147 cast<FunctionTemplateDecl>(D)->getTemplatedDecl())) { 148 if (isa<CXXConstructorDecl>(MD)) 149 Info.Kind = SymbolKind::CXXConstructor; 150 else if (isa<CXXDestructorDecl>(MD)) 151 Info.Kind = SymbolKind::CXXDestructor; 152 else if (isa<CXXConversionDecl>(MD)) 153 Info.Kind = SymbolKind::CXXConversionFunction; 154 else { 155 if (MD->isStatic()) 156 Info.Kind = SymbolKind::CXXStaticMethod; 157 else 158 Info.Kind = SymbolKind::CXXInstanceMethod; 159 } 160 } 161 break; 162 case Decl::TypeAliasTemplate: 163 Info.Kind = SymbolKind::CXXTypeAlias; 164 Info.TemplateKind = SymbolCXXTemplateKind::Template; 165 break; 166 case Decl::TypeAlias: 167 Info.Kind = SymbolKind::CXXTypeAlias; 168 Info.Lang = SymbolLanguage::CXX; 169 break; 170 default: 171 break; 172 } 173 } 174 175 if (Info.Kind == SymbolKind::Unknown) 176 return Info; 177 178 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 179 if (FD->getTemplatedKind() == 180 FunctionDecl::TK_FunctionTemplateSpecialization) 181 Info.TemplateKind = SymbolCXXTemplateKind::TemplateSpecialization; 182 } 183 184 if (Info.TemplateKind != SymbolCXXTemplateKind::NonTemplate) 185 Info.Lang = SymbolLanguage::CXX; 186 187 return Info; 188 } 189 190 void index::applyForEachSymbolRole(SymbolRoleSet Roles, 191 llvm::function_ref<void(SymbolRole)> Fn) { 192 #define APPLY_FOR_ROLE(Role) \ 193 if (Roles & (unsigned)SymbolRole::Role) \ 194 Fn(SymbolRole::Role) 195 196 APPLY_FOR_ROLE(Declaration); 197 APPLY_FOR_ROLE(Definition); 198 APPLY_FOR_ROLE(Reference); 199 APPLY_FOR_ROLE(Read); 200 APPLY_FOR_ROLE(Write); 201 APPLY_FOR_ROLE(Call); 202 APPLY_FOR_ROLE(Dynamic); 203 APPLY_FOR_ROLE(AddressOf); 204 APPLY_FOR_ROLE(Implicit); 205 APPLY_FOR_ROLE(RelationChildOf); 206 APPLY_FOR_ROLE(RelationBaseOf); 207 APPLY_FOR_ROLE(RelationOverrideOf); 208 APPLY_FOR_ROLE(RelationReceivedBy); 209 210 #undef APPLY_FOR_ROLE 211 } 212 213 void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) { 214 bool VisitedOnce = false; 215 applyForEachSymbolRole(Roles, [&](SymbolRole Role) { 216 if (VisitedOnce) 217 OS << '/'; 218 else 219 VisitedOnce = true; 220 switch (Role) { 221 case SymbolRole::Declaration: OS << "Decl"; break; 222 case SymbolRole::Definition: OS << "Def"; break; 223 case SymbolRole::Reference: OS << "Ref"; break; 224 case SymbolRole::Read: OS << "Read"; break; 225 case SymbolRole::Write: OS << "Writ"; break; 226 case SymbolRole::Call: OS << "Call"; break; 227 case SymbolRole::Dynamic: OS << "Dyn"; break; 228 case SymbolRole::AddressOf: OS << "Addr"; break; 229 case SymbolRole::Implicit: OS << "Impl"; break; 230 case SymbolRole::RelationChildOf: OS << "RelChild"; break; 231 case SymbolRole::RelationBaseOf: OS << "RelBase"; break; 232 case SymbolRole::RelationOverrideOf: OS << "RelOver"; break; 233 case SymbolRole::RelationReceivedBy: OS << "RelRec"; break; 234 } 235 }); 236 } 237 238 bool index::printSymbolName(const Decl *D, const LangOptions &LO, 239 raw_ostream &OS) { 240 if (auto *ND = dyn_cast<NamedDecl>(D)) { 241 PrintingPolicy Policy(LO); 242 // Forward references can have different template argument names. Suppress 243 // the template argument names in constructors to make their name more 244 // stable. 245 Policy.SuppressTemplateArgsInCXXConstructors = true; 246 DeclarationName DeclName = ND->getDeclName(); 247 if (DeclName.isEmpty()) 248 return true; 249 DeclName.print(OS, Policy); 250 return false; 251 } else { 252 return true; 253 } 254 } 255 256 StringRef index::getSymbolKindString(SymbolKind K) { 257 switch (K) { 258 case SymbolKind::Unknown: return "<unknown>"; 259 case SymbolKind::Module: return "module"; 260 case SymbolKind::Macro: return "macro"; 261 case SymbolKind::Enum: return "enum"; 262 case SymbolKind::Struct: return "struct"; 263 case SymbolKind::Union: return "union"; 264 case SymbolKind::Typedef: return "typedef"; 265 case SymbolKind::Function: return "function"; 266 case SymbolKind::Variable: return "variable"; 267 case SymbolKind::Field: return "field"; 268 case SymbolKind::EnumConstant: return "enumerator"; 269 case SymbolKind::ObjCClass: return "objc-class"; 270 case SymbolKind::ObjCProtocol: return "objc-protocol"; 271 case SymbolKind::ObjCCategory: return "objc-category"; 272 case SymbolKind::ObjCInstanceMethod: return "objc-instance-method"; 273 case SymbolKind::ObjCClassMethod: return "objc-class-method"; 274 case SymbolKind::ObjCProperty: return "objc-property"; 275 case SymbolKind::ObjCIvar: return "objc-ivar"; 276 case SymbolKind::CXXClass: return "c++-class"; 277 case SymbolKind::CXXNamespace: return "namespace"; 278 case SymbolKind::CXXNamespaceAlias: return "namespace-alias"; 279 case SymbolKind::CXXStaticVariable: return "c++-static-var"; 280 case SymbolKind::CXXStaticMethod: return "c++-static-method"; 281 case SymbolKind::CXXInstanceMethod: return "c++-instance-method"; 282 case SymbolKind::CXXConstructor: return "constructor"; 283 case SymbolKind::CXXDestructor: return "destructor"; 284 case SymbolKind::CXXConversionFunction: return "coversion-func"; 285 case SymbolKind::CXXTypeAlias: return "type-alias"; 286 case SymbolKind::CXXInterface: return "c++-__interface"; 287 } 288 llvm_unreachable("invalid symbol kind"); 289 } 290 291 StringRef index::getTemplateKindStr(SymbolCXXTemplateKind TK) { 292 switch (TK) { 293 case SymbolCXXTemplateKind::NonTemplate: return "NT"; 294 case SymbolCXXTemplateKind::Template : return "T"; 295 case SymbolCXXTemplateKind::TemplatePartialSpecialization : return "TPS"; 296 case SymbolCXXTemplateKind::TemplateSpecialization: return "TS"; 297 } 298 llvm_unreachable("invalid template kind"); 299 } 300 301 StringRef index::getSymbolLanguageString(SymbolLanguage K) { 302 switch (K) { 303 case SymbolLanguage::C: return "C"; 304 case SymbolLanguage::ObjC: return "ObjC"; 305 case SymbolLanguage::CXX: return "C++"; 306 } 307 llvm_unreachable("invalid symbol language kind"); 308 } 309