IndexSymbol.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. //===--- IndexSymbol.cpp - Types and functions for indexing symbols -------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "clang/Index/IndexSymbol.h"
  9. #include "clang/AST/DeclCXX.h"
  10. #include "clang/AST/DeclObjC.h"
  11. #include "clang/AST/DeclTemplate.h"
  12. #include "clang/AST/PrettyPrinter.h"
  13. #include "clang/Lex/MacroInfo.h"
  14. using namespace clang;
  15. using namespace clang::index;
  16. /// \returns true if \c D is a subclass of 'XCTestCase'.
  17. static bool isUnitTestCase(const ObjCInterfaceDecl *D) {
  18. if (!D)
  19. return false;
  20. while (const ObjCInterfaceDecl *SuperD = D->getSuperClass()) {
  21. if (SuperD->getName() == "XCTestCase")
  22. return true;
  23. D = SuperD;
  24. }
  25. return false;
  26. }
  27. /// \returns true if \c D is in a subclass of 'XCTestCase', returns void, has
  28. /// no parameters, and its name starts with 'test'.
  29. static bool isUnitTest(const ObjCMethodDecl *D) {
  30. if (!D->parameters().empty())
  31. return false;
  32. if (!D->getReturnType()->isVoidType())
  33. return false;
  34. if (!D->getSelector().getNameForSlot(0).startswith("test"))
  35. return false;
  36. return isUnitTestCase(D->getClassInterface());
  37. }
  38. static void checkForIBOutlets(const Decl *D, SymbolPropertySet &PropSet) {
  39. if (D->hasAttr<IBOutletAttr>()) {
  40. PropSet |= (SymbolPropertySet)SymbolProperty::IBAnnotated;
  41. } else if (D->hasAttr<IBOutletCollectionAttr>()) {
  42. PropSet |= (SymbolPropertySet)SymbolProperty::IBAnnotated;
  43. PropSet |= (SymbolPropertySet)SymbolProperty::IBOutletCollection;
  44. }
  45. }
  46. bool index::isFunctionLocalSymbol(const Decl *D) {
  47. assert(D);
  48. if (isa<ParmVarDecl>(D))
  49. return true;
  50. if (isa<ObjCTypeParamDecl>(D))
  51. return true;
  52. if (isa<UsingDirectiveDecl>(D))
  53. return false;
  54. if (!D->getParentFunctionOrMethod())
  55. return false;
  56. if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
  57. switch (ND->getFormalLinkage()) {
  58. case NoLinkage:
  59. case InternalLinkage:
  60. return true;
  61. case VisibleNoLinkage:
  62. case UniqueExternalLinkage:
  63. case ModuleInternalLinkage:
  64. llvm_unreachable("Not a sema linkage");
  65. case ModuleLinkage:
  66. case ExternalLinkage:
  67. return false;
  68. }
  69. }
  70. return true;
  71. }
  72. SymbolInfo index::getSymbolInfo(const Decl *D) {
  73. assert(D);
  74. SymbolInfo Info;
  75. Info.Kind = SymbolKind::Unknown;
  76. Info.SubKind = SymbolSubKind::None;
  77. Info.Properties = SymbolPropertySet();
  78. Info.Lang = SymbolLanguage::C;
  79. if (isFunctionLocalSymbol(D)) {
  80. Info.Properties |= (SymbolPropertySet)SymbolProperty::Local;
  81. }
  82. if (isa<ObjCProtocolDecl>(D->getDeclContext())) {
  83. Info.Properties |= (SymbolPropertySet)SymbolProperty::ProtocolInterface;
  84. }
  85. if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
  86. switch (TD->getTagKind()) {
  87. case TTK_Struct:
  88. Info.Kind = SymbolKind::Struct; break;
  89. case TTK_Union:
  90. Info.Kind = SymbolKind::Union; break;
  91. case TTK_Class:
  92. Info.Kind = SymbolKind::Class;
  93. Info.Lang = SymbolLanguage::CXX;
  94. break;
  95. case TTK_Interface:
  96. Info.Kind = SymbolKind::Protocol;
  97. Info.Lang = SymbolLanguage::CXX;
  98. break;
  99. case TTK_Enum:
  100. Info.Kind = SymbolKind::Enum; break;
  101. }
  102. if (const CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(D)) {
  103. if (!CXXRec->isCLike()) {
  104. Info.Lang = SymbolLanguage::CXX;
  105. if (CXXRec->getDescribedClassTemplate()) {
  106. Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
  107. }
  108. }
  109. }
  110. if (isa<ClassTemplatePartialSpecializationDecl>(D)) {
  111. Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
  112. Info.Properties |=
  113. (SymbolPropertySet)SymbolProperty::TemplatePartialSpecialization;
  114. } else if (isa<ClassTemplateSpecializationDecl>(D)) {
  115. Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
  116. Info.Properties |=
  117. (SymbolPropertySet)SymbolProperty::TemplateSpecialization;
  118. }
  119. } else if (auto *VD = dyn_cast<VarDecl>(D)) {
  120. Info.Kind = SymbolKind::Variable;
  121. if (isa<ParmVarDecl>(D)) {
  122. Info.Kind = SymbolKind::Parameter;
  123. } else if (isa<CXXRecordDecl>(D->getDeclContext())) {
  124. Info.Kind = SymbolKind::StaticProperty;
  125. Info.Lang = SymbolLanguage::CXX;
  126. }
  127. if (isa<VarTemplatePartialSpecializationDecl>(D)) {
  128. Info.Lang = SymbolLanguage::CXX;
  129. Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
  130. Info.Properties |=
  131. (SymbolPropertySet)SymbolProperty::TemplatePartialSpecialization;
  132. } else if (isa<VarTemplateSpecializationDecl>(D)) {
  133. Info.Lang = SymbolLanguage::CXX;
  134. Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
  135. Info.Properties |=
  136. (SymbolPropertySet)SymbolProperty::TemplateSpecialization;
  137. } else if (VD->getDescribedVarTemplate()) {
  138. Info.Lang = SymbolLanguage::CXX;
  139. Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
  140. }
  141. } else {
  142. switch (D->getKind()) {
  143. case Decl::Import:
  144. Info.Kind = SymbolKind::Module;
  145. break;
  146. case Decl::Typedef:
  147. Info.Kind = SymbolKind::TypeAlias; break; // Lang = C
  148. case Decl::Function:
  149. Info.Kind = SymbolKind::Function;
  150. break;
  151. case Decl::Field:
  152. Info.Kind = SymbolKind::Field;
  153. if (const CXXRecordDecl *
  154. CXXRec = dyn_cast<CXXRecordDecl>(D->getDeclContext())) {
  155. if (!CXXRec->isCLike())
  156. Info.Lang = SymbolLanguage::CXX;
  157. }
  158. break;
  159. case Decl::EnumConstant:
  160. Info.Kind = SymbolKind::EnumConstant; break;
  161. case Decl::ObjCInterface:
  162. case Decl::ObjCImplementation: {
  163. Info.Kind = SymbolKind::Class;
  164. Info.Lang = SymbolLanguage::ObjC;
  165. const ObjCInterfaceDecl *ClsD = dyn_cast<ObjCInterfaceDecl>(D);
  166. if (!ClsD)
  167. ClsD = cast<ObjCImplementationDecl>(D)->getClassInterface();
  168. if (isUnitTestCase(ClsD))
  169. Info.Properties |= (SymbolPropertySet)SymbolProperty::UnitTest;
  170. break;
  171. }
  172. case Decl::ObjCProtocol:
  173. Info.Kind = SymbolKind::Protocol;
  174. Info.Lang = SymbolLanguage::ObjC;
  175. break;
  176. case Decl::ObjCCategory:
  177. case Decl::ObjCCategoryImpl: {
  178. Info.Kind = SymbolKind::Extension;
  179. Info.Lang = SymbolLanguage::ObjC;
  180. const ObjCInterfaceDecl *ClsD = nullptr;
  181. if (auto *CatD = dyn_cast<ObjCCategoryDecl>(D))
  182. ClsD = CatD->getClassInterface();
  183. else
  184. ClsD = cast<ObjCCategoryImplDecl>(D)->getClassInterface();
  185. if (isUnitTestCase(ClsD))
  186. Info.Properties |= (SymbolPropertySet)SymbolProperty::UnitTest;
  187. break;
  188. }
  189. case Decl::ObjCMethod: {
  190. const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D);
  191. Info.Kind = MD->isInstanceMethod() ? SymbolKind::InstanceMethod : SymbolKind::ClassMethod;
  192. if (MD->isPropertyAccessor()) {
  193. if (MD->param_size())
  194. Info.SubKind = SymbolSubKind::AccessorSetter;
  195. else
  196. Info.SubKind = SymbolSubKind::AccessorGetter;
  197. }
  198. Info.Lang = SymbolLanguage::ObjC;
  199. if (isUnitTest(MD))
  200. Info.Properties |= (SymbolPropertySet)SymbolProperty::UnitTest;
  201. if (D->hasAttr<IBActionAttr>())
  202. Info.Properties |= (SymbolPropertySet)SymbolProperty::IBAnnotated;
  203. break;
  204. }
  205. case Decl::ObjCProperty:
  206. Info.Kind = SymbolKind::InstanceProperty;
  207. Info.Lang = SymbolLanguage::ObjC;
  208. checkForIBOutlets(D, Info.Properties);
  209. if (auto *Annot = D->getAttr<AnnotateAttr>()) {
  210. if (Annot->getAnnotation() == "gk_inspectable")
  211. Info.Properties |= (SymbolPropertySet)SymbolProperty::GKInspectable;
  212. }
  213. break;
  214. case Decl::ObjCIvar:
  215. Info.Kind = SymbolKind::Field;
  216. Info.Lang = SymbolLanguage::ObjC;
  217. checkForIBOutlets(D, Info.Properties);
  218. break;
  219. case Decl::Namespace:
  220. Info.Kind = SymbolKind::Namespace;
  221. Info.Lang = SymbolLanguage::CXX;
  222. break;
  223. case Decl::NamespaceAlias:
  224. Info.Kind = SymbolKind::NamespaceAlias;
  225. Info.Lang = SymbolLanguage::CXX;
  226. break;
  227. case Decl::CXXConstructor: {
  228. Info.Kind = SymbolKind::Constructor;
  229. Info.Lang = SymbolLanguage::CXX;
  230. auto *CD = cast<CXXConstructorDecl>(D);
  231. if (CD->isCopyConstructor())
  232. Info.SubKind = SymbolSubKind::CXXCopyConstructor;
  233. else if (CD->isMoveConstructor())
  234. Info.SubKind = SymbolSubKind::CXXMoveConstructor;
  235. break;
  236. }
  237. case Decl::CXXDestructor:
  238. Info.Kind = SymbolKind::Destructor;
  239. Info.Lang = SymbolLanguage::CXX;
  240. break;
  241. case Decl::CXXConversion:
  242. Info.Kind = SymbolKind::ConversionFunction;
  243. Info.Lang = SymbolLanguage::CXX;
  244. break;
  245. case Decl::CXXMethod: {
  246. const CXXMethodDecl *MD = cast<CXXMethodDecl>(D);
  247. if (MD->isStatic())
  248. Info.Kind = SymbolKind::StaticMethod;
  249. else
  250. Info.Kind = SymbolKind::InstanceMethod;
  251. Info.Lang = SymbolLanguage::CXX;
  252. break;
  253. }
  254. case Decl::ClassTemplate:
  255. Info.Kind = SymbolKind::Class;
  256. Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
  257. Info.Lang = SymbolLanguage::CXX;
  258. break;
  259. case Decl::FunctionTemplate:
  260. Info.Kind = SymbolKind::Function;
  261. Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
  262. Info.Lang = SymbolLanguage::CXX;
  263. if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(
  264. cast<FunctionTemplateDecl>(D)->getTemplatedDecl())) {
  265. if (isa<CXXConstructorDecl>(MD))
  266. Info.Kind = SymbolKind::Constructor;
  267. else if (isa<CXXDestructorDecl>(MD))
  268. Info.Kind = SymbolKind::Destructor;
  269. else if (isa<CXXConversionDecl>(MD))
  270. Info.Kind = SymbolKind::ConversionFunction;
  271. else {
  272. if (MD->isStatic())
  273. Info.Kind = SymbolKind::StaticMethod;
  274. else
  275. Info.Kind = SymbolKind::InstanceMethod;
  276. }
  277. }
  278. break;
  279. case Decl::TypeAliasTemplate:
  280. Info.Kind = SymbolKind::TypeAlias;
  281. Info.Lang = SymbolLanguage::CXX;
  282. Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
  283. break;
  284. case Decl::TypeAlias:
  285. Info.Kind = SymbolKind::TypeAlias;
  286. Info.Lang = SymbolLanguage::CXX;
  287. break;
  288. case Decl::UnresolvedUsingTypename:
  289. Info.Kind = SymbolKind::Using;
  290. Info.SubKind = SymbolSubKind::UsingTypename;
  291. Info.Lang = SymbolLanguage::CXX;
  292. Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
  293. break;
  294. case Decl::UnresolvedUsingValue:
  295. Info.Kind = SymbolKind::Using;
  296. Info.SubKind = SymbolSubKind::UsingValue;
  297. Info.Lang = SymbolLanguage::CXX;
  298. Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
  299. break;
  300. case Decl::Binding:
  301. Info.Kind = SymbolKind::Variable;
  302. Info.Lang = SymbolLanguage::CXX;
  303. break;
  304. default:
  305. break;
  306. }
  307. }
  308. if (Info.Kind == SymbolKind::Unknown)
  309. return Info;
  310. if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
  311. if (FD->getTemplatedKind() ==
  312. FunctionDecl::TK_FunctionTemplateSpecialization) {
  313. Info.Properties |= (SymbolPropertySet)SymbolProperty::Generic;
  314. Info.Properties |=
  315. (SymbolPropertySet)SymbolProperty::TemplateSpecialization;
  316. }
  317. }
  318. if (Info.Properties & (SymbolPropertySet)SymbolProperty::Generic)
  319. Info.Lang = SymbolLanguage::CXX;
  320. if (auto *attr = D->getExternalSourceSymbolAttr()) {
  321. if (attr->getLanguage() == "Swift")
  322. Info.Lang = SymbolLanguage::Swift;
  323. }
  324. return Info;
  325. }
  326. SymbolInfo index::getSymbolInfoForMacro(const MacroInfo &) {
  327. SymbolInfo Info;
  328. Info.Kind = SymbolKind::Macro;
  329. Info.SubKind = SymbolSubKind::None;
  330. Info.Properties = SymbolPropertySet();
  331. Info.Lang = SymbolLanguage::C;
  332. return Info;
  333. }
  334. bool index::applyForEachSymbolRoleInterruptible(SymbolRoleSet Roles,
  335. llvm::function_ref<bool(SymbolRole)> Fn) {
  336. #define APPLY_FOR_ROLE(Role) \
  337. if (Roles & (unsigned)SymbolRole::Role) \
  338. if (!Fn(SymbolRole::Role)) \
  339. return false;
  340. APPLY_FOR_ROLE(Declaration);
  341. APPLY_FOR_ROLE(Definition);
  342. APPLY_FOR_ROLE(Reference);
  343. APPLY_FOR_ROLE(Read);
  344. APPLY_FOR_ROLE(Write);
  345. APPLY_FOR_ROLE(Call);
  346. APPLY_FOR_ROLE(Dynamic);
  347. APPLY_FOR_ROLE(AddressOf);
  348. APPLY_FOR_ROLE(Implicit);
  349. APPLY_FOR_ROLE(Undefinition);
  350. APPLY_FOR_ROLE(RelationChildOf);
  351. APPLY_FOR_ROLE(RelationBaseOf);
  352. APPLY_FOR_ROLE(RelationOverrideOf);
  353. APPLY_FOR_ROLE(RelationReceivedBy);
  354. APPLY_FOR_ROLE(RelationCalledBy);
  355. APPLY_FOR_ROLE(RelationExtendedBy);
  356. APPLY_FOR_ROLE(RelationAccessorOf);
  357. APPLY_FOR_ROLE(RelationContainedBy);
  358. APPLY_FOR_ROLE(RelationIBTypeOf);
  359. APPLY_FOR_ROLE(RelationSpecializationOf);
  360. #undef APPLY_FOR_ROLE
  361. return true;
  362. }
  363. void index::applyForEachSymbolRole(SymbolRoleSet Roles,
  364. llvm::function_ref<void(SymbolRole)> Fn) {
  365. applyForEachSymbolRoleInterruptible(Roles, [&](SymbolRole r) -> bool {
  366. Fn(r);
  367. return true;
  368. });
  369. }
  370. void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) {
  371. bool VisitedOnce = false;
  372. applyForEachSymbolRole(Roles, [&](SymbolRole Role) {
  373. if (VisitedOnce)
  374. OS << ',';
  375. else
  376. VisitedOnce = true;
  377. switch (Role) {
  378. case SymbolRole::Declaration: OS << "Decl"; break;
  379. case SymbolRole::Definition: OS << "Def"; break;
  380. case SymbolRole::Reference: OS << "Ref"; break;
  381. case SymbolRole::Read: OS << "Read"; break;
  382. case SymbolRole::Write: OS << "Writ"; break;
  383. case SymbolRole::Call: OS << "Call"; break;
  384. case SymbolRole::Dynamic: OS << "Dyn"; break;
  385. case SymbolRole::AddressOf: OS << "Addr"; break;
  386. case SymbolRole::Implicit: OS << "Impl"; break;
  387. case SymbolRole::Undefinition: OS << "Undef"; break;
  388. case SymbolRole::RelationChildOf: OS << "RelChild"; break;
  389. case SymbolRole::RelationBaseOf: OS << "RelBase"; break;
  390. case SymbolRole::RelationOverrideOf: OS << "RelOver"; break;
  391. case SymbolRole::RelationReceivedBy: OS << "RelRec"; break;
  392. case SymbolRole::RelationCalledBy: OS << "RelCall"; break;
  393. case SymbolRole::RelationExtendedBy: OS << "RelExt"; break;
  394. case SymbolRole::RelationAccessorOf: OS << "RelAcc"; break;
  395. case SymbolRole::RelationContainedBy: OS << "RelCont"; break;
  396. case SymbolRole::RelationIBTypeOf: OS << "RelIBType"; break;
  397. case SymbolRole::RelationSpecializationOf: OS << "RelSpecialization"; break;
  398. }
  399. });
  400. }
  401. bool index::printSymbolName(const Decl *D, const LangOptions &LO,
  402. raw_ostream &OS) {
  403. if (auto *ND = dyn_cast<NamedDecl>(D)) {
  404. PrintingPolicy Policy(LO);
  405. // Forward references can have different template argument names. Suppress
  406. // the template argument names in constructors to make their name more
  407. // stable.
  408. Policy.SuppressTemplateArgsInCXXConstructors = true;
  409. DeclarationName DeclName = ND->getDeclName();
  410. if (DeclName.isEmpty())
  411. return true;
  412. DeclName.print(OS, Policy);
  413. return false;
  414. } else {
  415. return true;
  416. }
  417. }
  418. StringRef index::getSymbolKindString(SymbolKind K) {
  419. switch (K) {
  420. case SymbolKind::Unknown: return "<unknown>";
  421. case SymbolKind::Module: return "module";
  422. case SymbolKind::Namespace: return "namespace";
  423. case SymbolKind::NamespaceAlias: return "namespace-alias";
  424. case SymbolKind::Macro: return "macro";
  425. case SymbolKind::Enum: return "enum";
  426. case SymbolKind::Struct: return "struct";
  427. case SymbolKind::Class: return "class";
  428. case SymbolKind::Protocol: return "protocol";
  429. case SymbolKind::Extension: return "extension";
  430. case SymbolKind::Union: return "union";
  431. case SymbolKind::TypeAlias: return "type-alias";
  432. case SymbolKind::Function: return "function";
  433. case SymbolKind::Variable: return "variable";
  434. case SymbolKind::Field: return "field";
  435. case SymbolKind::EnumConstant: return "enumerator";
  436. case SymbolKind::InstanceMethod: return "instance-method";
  437. case SymbolKind::ClassMethod: return "class-method";
  438. case SymbolKind::StaticMethod: return "static-method";
  439. case SymbolKind::InstanceProperty: return "instance-property";
  440. case SymbolKind::ClassProperty: return "class-property";
  441. case SymbolKind::StaticProperty: return "static-property";
  442. case SymbolKind::Constructor: return "constructor";
  443. case SymbolKind::Destructor: return "destructor";
  444. case SymbolKind::ConversionFunction: return "coversion-func";
  445. case SymbolKind::Parameter: return "param";
  446. case SymbolKind::Using: return "using";
  447. }
  448. llvm_unreachable("invalid symbol kind");
  449. }
  450. StringRef index::getSymbolSubKindString(SymbolSubKind K) {
  451. switch (K) {
  452. case SymbolSubKind::None: return "<none>";
  453. case SymbolSubKind::CXXCopyConstructor: return "cxx-copy-ctor";
  454. case SymbolSubKind::CXXMoveConstructor: return "cxx-move-ctor";
  455. case SymbolSubKind::AccessorGetter: return "acc-get";
  456. case SymbolSubKind::AccessorSetter: return "acc-set";
  457. case SymbolSubKind::UsingTypename: return "using-typename";
  458. case SymbolSubKind::UsingValue: return "using-value";
  459. }
  460. llvm_unreachable("invalid symbol subkind");
  461. }
  462. StringRef index::getSymbolLanguageString(SymbolLanguage K) {
  463. switch (K) {
  464. case SymbolLanguage::C: return "C";
  465. case SymbolLanguage::ObjC: return "ObjC";
  466. case SymbolLanguage::CXX: return "C++";
  467. case SymbolLanguage::Swift: return "Swift";
  468. }
  469. llvm_unreachable("invalid symbol language kind");
  470. }
  471. void index::applyForEachSymbolProperty(SymbolPropertySet Props,
  472. llvm::function_ref<void(SymbolProperty)> Fn) {
  473. #define APPLY_FOR_PROPERTY(K) \
  474. if (Props & (SymbolPropertySet)SymbolProperty::K) \
  475. Fn(SymbolProperty::K)
  476. APPLY_FOR_PROPERTY(Generic);
  477. APPLY_FOR_PROPERTY(TemplatePartialSpecialization);
  478. APPLY_FOR_PROPERTY(TemplateSpecialization);
  479. APPLY_FOR_PROPERTY(UnitTest);
  480. APPLY_FOR_PROPERTY(IBAnnotated);
  481. APPLY_FOR_PROPERTY(IBOutletCollection);
  482. APPLY_FOR_PROPERTY(GKInspectable);
  483. APPLY_FOR_PROPERTY(Local);
  484. APPLY_FOR_PROPERTY(ProtocolInterface);
  485. #undef APPLY_FOR_PROPERTY
  486. }
  487. void index::printSymbolProperties(SymbolPropertySet Props, raw_ostream &OS) {
  488. bool VisitedOnce = false;
  489. applyForEachSymbolProperty(Props, [&](SymbolProperty Prop) {
  490. if (VisitedOnce)
  491. OS << ',';
  492. else
  493. VisitedOnce = true;
  494. switch (Prop) {
  495. case SymbolProperty::Generic: OS << "Gen"; break;
  496. case SymbolProperty::TemplatePartialSpecialization: OS << "TPS"; break;
  497. case SymbolProperty::TemplateSpecialization: OS << "TS"; break;
  498. case SymbolProperty::UnitTest: OS << "test"; break;
  499. case SymbolProperty::IBAnnotated: OS << "IB"; break;
  500. case SymbolProperty::IBOutletCollection: OS << "IBColl"; break;
  501. case SymbolProperty::GKInspectable: OS << "GKI"; break;
  502. case SymbolProperty::Local: OS << "local"; break;
  503. case SymbolProperty::ProtocolInterface: OS << "protocol"; break;
  504. }
  505. });
  506. }