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::Class; 34 Info.Lang = SymbolLanguage::CXX; 35 break; 36 case TTK_Interface: 37 Info.Kind = SymbolKind::Protocol; 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::Import: 57 Info.Kind = SymbolKind::Module; 58 break; 59 case Decl::Typedef: 60 Info.Kind = SymbolKind::TypeAlias; break; // Lang = C 61 case Decl::Function: 62 Info.Kind = SymbolKind::Function; 63 break; 64 case Decl::ParmVar: 65 Info.Kind = SymbolKind::Variable; 66 break; 67 case Decl::Var: 68 Info.Kind = SymbolKind::Variable; 69 if (isa<CXXRecordDecl>(D->getDeclContext())) { 70 Info.Kind = SymbolKind::StaticProperty; 71 Info.Lang = SymbolLanguage::CXX; 72 } 73 break; 74 case Decl::Field: 75 Info.Kind = SymbolKind::Field; 76 if (const CXXRecordDecl * 77 CXXRec = dyn_cast<CXXRecordDecl>(D->getDeclContext())) { 78 if (!CXXRec->isCLike()) 79 Info.Lang = SymbolLanguage::CXX; 80 } 81 break; 82 case Decl::EnumConstant: 83 Info.Kind = SymbolKind::EnumConstant; break; 84 case Decl::ObjCInterface: 85 case Decl::ObjCImplementation: 86 Info.Kind = SymbolKind::Class; 87 Info.Lang = SymbolLanguage::ObjC; 88 break; 89 case Decl::ObjCProtocol: 90 Info.Kind = SymbolKind::Protocol; 91 Info.Lang = SymbolLanguage::ObjC; 92 break; 93 case Decl::ObjCCategory: 94 case Decl::ObjCCategoryImpl: 95 Info.Kind = SymbolKind::Extension; 96 Info.Lang = SymbolLanguage::ObjC; 97 break; 98 case Decl::ObjCMethod: 99 if (cast<ObjCMethodDecl>(D)->isInstanceMethod()) 100 Info.Kind = SymbolKind::InstanceMethod; 101 else 102 Info.Kind = SymbolKind::ClassMethod; 103 Info.Lang = SymbolLanguage::ObjC; 104 break; 105 case Decl::ObjCProperty: 106 Info.Kind = SymbolKind::InstanceProperty; 107 Info.Lang = SymbolLanguage::ObjC; 108 break; 109 case Decl::ObjCIvar: 110 Info.Kind = SymbolKind::Field; 111 Info.Lang = SymbolLanguage::ObjC; 112 break; 113 case Decl::Namespace: 114 Info.Kind = SymbolKind::Namespace; 115 Info.Lang = SymbolLanguage::CXX; 116 break; 117 case Decl::NamespaceAlias: 118 Info.Kind = SymbolKind::NamespaceAlias; 119 Info.Lang = SymbolLanguage::CXX; 120 break; 121 case Decl::CXXConstructor: 122 Info.Kind = SymbolKind::Constructor; 123 Info.Lang = SymbolLanguage::CXX; 124 break; 125 case Decl::CXXDestructor: 126 Info.Kind = SymbolKind::Destructor; 127 Info.Lang = SymbolLanguage::CXX; 128 break; 129 case Decl::CXXConversion: 130 Info.Kind = SymbolKind::ConversionFunction; 131 Info.Lang = SymbolLanguage::CXX; 132 break; 133 case Decl::CXXMethod: { 134 const CXXMethodDecl *MD = cast<CXXMethodDecl>(D); 135 if (MD->isStatic()) 136 Info.Kind = SymbolKind::StaticMethod; 137 else 138 Info.Kind = SymbolKind::InstanceMethod; 139 Info.Lang = SymbolLanguage::CXX; 140 break; 141 } 142 case Decl::ClassTemplate: 143 Info.Kind = SymbolKind::Class; 144 Info.TemplateKind = SymbolCXXTemplateKind::Template; 145 Info.Lang = SymbolLanguage::CXX; 146 break; 147 case Decl::FunctionTemplate: 148 Info.Kind = SymbolKind::Function; 149 Info.TemplateKind = SymbolCXXTemplateKind::Template; 150 Info.Lang = SymbolLanguage::CXX; 151 if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>( 152 cast<FunctionTemplateDecl>(D)->getTemplatedDecl())) { 153 if (isa<CXXConstructorDecl>(MD)) 154 Info.Kind = SymbolKind::Constructor; 155 else if (isa<CXXDestructorDecl>(MD)) 156 Info.Kind = SymbolKind::Destructor; 157 else if (isa<CXXConversionDecl>(MD)) 158 Info.Kind = SymbolKind::ConversionFunction; 159 else { 160 if (MD->isStatic()) 161 Info.Kind = SymbolKind::StaticMethod; 162 else 163 Info.Kind = SymbolKind::InstanceMethod; 164 } 165 } 166 break; 167 case Decl::TypeAliasTemplate: 168 Info.Kind = SymbolKind::TypeAlias; 169 Info.Lang = SymbolLanguage::CXX; 170 Info.TemplateKind = SymbolCXXTemplateKind::Template; 171 break; 172 case Decl::TypeAlias: 173 Info.Kind = SymbolKind::TypeAlias; 174 Info.Lang = SymbolLanguage::CXX; 175 break; 176 default: 177 break; 178 } 179 } 180 181 if (Info.Kind == SymbolKind::Unknown) 182 return Info; 183 184 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 185 if (FD->getTemplatedKind() == 186 FunctionDecl::TK_FunctionTemplateSpecialization) 187 Info.TemplateKind = SymbolCXXTemplateKind::TemplateSpecialization; 188 } 189 190 if (Info.TemplateKind != SymbolCXXTemplateKind::NonTemplate) 191 Info.Lang = SymbolLanguage::CXX; 192 193 return Info; 194 } 195 196 void index::applyForEachSymbolRole(SymbolRoleSet Roles, 197 llvm::function_ref<void(SymbolRole)> Fn) { 198 #define APPLY_FOR_ROLE(Role) \ 199 if (Roles & (unsigned)SymbolRole::Role) \ 200 Fn(SymbolRole::Role) 201 202 APPLY_FOR_ROLE(Declaration); 203 APPLY_FOR_ROLE(Definition); 204 APPLY_FOR_ROLE(Reference); 205 APPLY_FOR_ROLE(Read); 206 APPLY_FOR_ROLE(Write); 207 APPLY_FOR_ROLE(Call); 208 APPLY_FOR_ROLE(Dynamic); 209 APPLY_FOR_ROLE(AddressOf); 210 APPLY_FOR_ROLE(Implicit); 211 APPLY_FOR_ROLE(RelationChildOf); 212 APPLY_FOR_ROLE(RelationBaseOf); 213 APPLY_FOR_ROLE(RelationOverrideOf); 214 APPLY_FOR_ROLE(RelationReceivedBy); 215 APPLY_FOR_ROLE(RelationCalledBy); 216 217 #undef APPLY_FOR_ROLE 218 } 219 220 void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) { 221 bool VisitedOnce = false; 222 applyForEachSymbolRole(Roles, [&](SymbolRole Role) { 223 if (VisitedOnce) 224 OS << ','; 225 else 226 VisitedOnce = true; 227 switch (Role) { 228 case SymbolRole::Declaration: OS << "Decl"; break; 229 case SymbolRole::Definition: OS << "Def"; break; 230 case SymbolRole::Reference: OS << "Ref"; break; 231 case SymbolRole::Read: OS << "Read"; break; 232 case SymbolRole::Write: OS << "Writ"; break; 233 case SymbolRole::Call: OS << "Call"; break; 234 case SymbolRole::Dynamic: OS << "Dyn"; break; 235 case SymbolRole::AddressOf: OS << "Addr"; break; 236 case SymbolRole::Implicit: OS << "Impl"; break; 237 case SymbolRole::RelationChildOf: OS << "RelChild"; break; 238 case SymbolRole::RelationBaseOf: OS << "RelBase"; break; 239 case SymbolRole::RelationOverrideOf: OS << "RelOver"; break; 240 case SymbolRole::RelationReceivedBy: OS << "RelRec"; break; 241 case SymbolRole::RelationCalledBy: OS << "RelCall"; break; 242 } 243 }); 244 } 245 246 bool index::printSymbolName(const Decl *D, const LangOptions &LO, 247 raw_ostream &OS) { 248 if (auto *ND = dyn_cast<NamedDecl>(D)) { 249 PrintingPolicy Policy(LO); 250 // Forward references can have different template argument names. Suppress 251 // the template argument names in constructors to make their name more 252 // stable. 253 Policy.SuppressTemplateArgsInCXXConstructors = true; 254 DeclarationName DeclName = ND->getDeclName(); 255 if (DeclName.isEmpty()) 256 return true; 257 DeclName.print(OS, Policy); 258 return false; 259 } else { 260 return true; 261 } 262 } 263 264 StringRef index::getSymbolKindString(SymbolKind K) { 265 switch (K) { 266 case SymbolKind::Unknown: return "<unknown>"; 267 case SymbolKind::Module: return "module"; 268 case SymbolKind::Namespace: return "namespace"; 269 case SymbolKind::NamespaceAlias: return "namespace-alias"; 270 case SymbolKind::Macro: return "macro"; 271 case SymbolKind::Enum: return "enum"; 272 case SymbolKind::Struct: return "struct"; 273 case SymbolKind::Class: return "class"; 274 case SymbolKind::Protocol: return "protocol"; 275 case SymbolKind::Extension: return "extension"; 276 case SymbolKind::Union: return "union"; 277 case SymbolKind::TypeAlias: return "type-alias"; 278 case SymbolKind::Function: return "function"; 279 case SymbolKind::Variable: return "variable"; 280 case SymbolKind::Field: return "field"; 281 case SymbolKind::EnumConstant: return "enumerator"; 282 case SymbolKind::InstanceMethod: return "instance-method"; 283 case SymbolKind::ClassMethod: return "class-method"; 284 case SymbolKind::StaticMethod: return "static-method"; 285 case SymbolKind::InstanceProperty: return "instance-property"; 286 case SymbolKind::ClassProperty: return "class-property"; 287 case SymbolKind::StaticProperty: return "static-property"; 288 case SymbolKind::Constructor: return "constructor"; 289 case SymbolKind::Destructor: return "destructor"; 290 case SymbolKind::ConversionFunction: return "coversion-func"; 291 } 292 llvm_unreachable("invalid symbol kind"); 293 } 294 295 StringRef index::getTemplateKindStr(SymbolCXXTemplateKind TK) { 296 switch (TK) { 297 case SymbolCXXTemplateKind::NonTemplate: return "NT"; 298 case SymbolCXXTemplateKind::Template : return "T"; 299 case SymbolCXXTemplateKind::TemplatePartialSpecialization : return "TPS"; 300 case SymbolCXXTemplateKind::TemplateSpecialization: return "TS"; 301 } 302 llvm_unreachable("invalid template kind"); 303 } 304 305 StringRef index::getSymbolLanguageString(SymbolLanguage K) { 306 switch (K) { 307 case SymbolLanguage::C: return "C"; 308 case SymbolLanguage::ObjC: return "ObjC"; 309 case SymbolLanguage::CXX: return "C++"; 310 } 311 llvm_unreachable("invalid symbol language kind"); 312 } 313