IndexingAction.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. //===- IndexingAction.cpp - Frontend index action -------------------------===//
  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/IndexingAction.h"
  9. #include "IndexingContext.h"
  10. #include "clang/Frontend/CompilerInstance.h"
  11. #include "clang/Frontend/FrontendAction.h"
  12. #include "clang/Frontend/MultiplexConsumer.h"
  13. #include "clang/Index/IndexDataConsumer.h"
  14. #include "clang/Lex/PPCallbacks.h"
  15. #include "clang/Lex/Preprocessor.h"
  16. #include "clang/Serialization/ASTReader.h"
  17. #include "llvm/ADT/STLExtras.h"
  18. #include <memory>
  19. using namespace clang;
  20. using namespace clang::index;
  21. namespace {
  22. class IndexPPCallbacks final : public PPCallbacks {
  23. std::shared_ptr<IndexingContext> IndexCtx;
  24. public:
  25. IndexPPCallbacks(std::shared_ptr<IndexingContext> IndexCtx)
  26. : IndexCtx(std::move(IndexCtx)) {}
  27. void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
  28. SourceRange Range, const MacroArgs *Args) override {
  29. IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),
  30. Range.getBegin(), *MD.getMacroInfo());
  31. }
  32. void MacroDefined(const Token &MacroNameTok,
  33. const MacroDirective *MD) override {
  34. IndexCtx->handleMacroDefined(*MacroNameTok.getIdentifierInfo(),
  35. MacroNameTok.getLocation(),
  36. *MD->getMacroInfo());
  37. }
  38. void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD,
  39. const MacroDirective *Undef) override {
  40. if (!MD.getMacroInfo()) // Ignore noop #undef.
  41. return;
  42. IndexCtx->handleMacroUndefined(*MacroNameTok.getIdentifierInfo(),
  43. MacroNameTok.getLocation(),
  44. *MD.getMacroInfo());
  45. }
  46. };
  47. class IndexASTConsumer final : public ASTConsumer {
  48. std::shared_ptr<IndexDataConsumer> DataConsumer;
  49. std::shared_ptr<IndexingContext> IndexCtx;
  50. std::shared_ptr<Preprocessor> PP;
  51. std::function<bool(const Decl *)> ShouldSkipFunctionBody;
  52. public:
  53. IndexASTConsumer(std::shared_ptr<IndexDataConsumer> DataConsumer,
  54. const IndexingOptions &Opts,
  55. std::shared_ptr<Preprocessor> PP,
  56. std::function<bool(const Decl *)> ShouldSkipFunctionBody)
  57. : DataConsumer(std::move(DataConsumer)),
  58. IndexCtx(new IndexingContext(Opts, *this->DataConsumer)),
  59. PP(std::move(PP)),
  60. ShouldSkipFunctionBody(std::move(ShouldSkipFunctionBody)) {
  61. assert(this->DataConsumer != nullptr);
  62. assert(this->PP != nullptr);
  63. }
  64. protected:
  65. void Initialize(ASTContext &Context) override {
  66. IndexCtx->setASTContext(Context);
  67. IndexCtx->getDataConsumer().initialize(Context);
  68. IndexCtx->getDataConsumer().setPreprocessor(PP);
  69. PP->addPPCallbacks(std::make_unique<IndexPPCallbacks>(IndexCtx));
  70. }
  71. bool HandleTopLevelDecl(DeclGroupRef DG) override {
  72. return IndexCtx->indexDeclGroupRef(DG);
  73. }
  74. void HandleInterestingDecl(DeclGroupRef DG) override {
  75. // Ignore deserialized decls.
  76. }
  77. void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
  78. IndexCtx->indexDeclGroupRef(DG);
  79. }
  80. void HandleTranslationUnit(ASTContext &Ctx) override {
  81. DataConsumer->finish();
  82. }
  83. bool shouldSkipFunctionBody(Decl *D) override {
  84. return ShouldSkipFunctionBody(D);
  85. }
  86. };
  87. class IndexAction final : public ASTFrontendAction {
  88. std::shared_ptr<IndexDataConsumer> DataConsumer;
  89. IndexingOptions Opts;
  90. public:
  91. IndexAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
  92. const IndexingOptions &Opts)
  93. : DataConsumer(std::move(DataConsumer)), Opts(Opts) {
  94. assert(this->DataConsumer != nullptr);
  95. }
  96. protected:
  97. std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
  98. StringRef InFile) override {
  99. return std::make_unique<IndexASTConsumer>(
  100. DataConsumer, Opts, CI.getPreprocessorPtr(),
  101. /*ShouldSkipFunctionBody=*/[](const Decl *) { return false; });
  102. }
  103. };
  104. } // anonymous namespace
  105. std::unique_ptr<ASTConsumer> index::createIndexingASTConsumer(
  106. std::shared_ptr<IndexDataConsumer> DataConsumer,
  107. const IndexingOptions &Opts, std::shared_ptr<Preprocessor> PP,
  108. std::function<bool(const Decl *)> ShouldSkipFunctionBody) {
  109. return std::make_unique<IndexASTConsumer>(DataConsumer, Opts, PP,
  110. ShouldSkipFunctionBody);
  111. }
  112. std::unique_ptr<FrontendAction>
  113. index::createIndexingAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
  114. const IndexingOptions &Opts) {
  115. assert(DataConsumer != nullptr);
  116. return std::make_unique<IndexAction>(std::move(DataConsumer), Opts);
  117. }
  118. static bool topLevelDeclVisitor(void *context, const Decl *D) {
  119. IndexingContext &IndexCtx = *static_cast<IndexingContext*>(context);
  120. return IndexCtx.indexTopLevelDecl(D);
  121. }
  122. static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx) {
  123. Unit.visitLocalTopLevelDecls(&IndexCtx, topLevelDeclVisitor);
  124. }
  125. static void indexPreprocessorMacros(const Preprocessor &PP,
  126. IndexDataConsumer &DataConsumer) {
  127. for (const auto &M : PP.macros())
  128. if (MacroDirective *MD = M.second.getLatest())
  129. DataConsumer.handleMacroOccurence(
  130. M.first, MD->getMacroInfo(),
  131. static_cast<unsigned>(index::SymbolRole::Definition),
  132. MD->getLocation());
  133. }
  134. void index::indexASTUnit(ASTUnit &Unit, IndexDataConsumer &DataConsumer,
  135. IndexingOptions Opts) {
  136. IndexingContext IndexCtx(Opts, DataConsumer);
  137. IndexCtx.setASTContext(Unit.getASTContext());
  138. DataConsumer.initialize(Unit.getASTContext());
  139. DataConsumer.setPreprocessor(Unit.getPreprocessorPtr());
  140. if (Opts.IndexMacrosInPreprocessor)
  141. indexPreprocessorMacros(Unit.getPreprocessor(), DataConsumer);
  142. indexTranslationUnit(Unit, IndexCtx);
  143. DataConsumer.finish();
  144. }
  145. void index::indexTopLevelDecls(ASTContext &Ctx, Preprocessor &PP,
  146. ArrayRef<const Decl *> Decls,
  147. IndexDataConsumer &DataConsumer,
  148. IndexingOptions Opts) {
  149. IndexingContext IndexCtx(Opts, DataConsumer);
  150. IndexCtx.setASTContext(Ctx);
  151. DataConsumer.initialize(Ctx);
  152. if (Opts.IndexMacrosInPreprocessor)
  153. indexPreprocessorMacros(PP, DataConsumer);
  154. for (const Decl *D : Decls)
  155. IndexCtx.indexTopLevelDecl(D);
  156. DataConsumer.finish();
  157. }
  158. std::unique_ptr<PPCallbacks>
  159. index::indexMacrosCallback(IndexDataConsumer &Consumer, IndexingOptions Opts) {
  160. return std::make_unique<IndexPPCallbacks>(
  161. std::make_shared<IndexingContext>(Opts, Consumer));
  162. }
  163. void index::indexModuleFile(serialization::ModuleFile &Mod, ASTReader &Reader,
  164. IndexDataConsumer &DataConsumer,
  165. IndexingOptions Opts) {
  166. ASTContext &Ctx = Reader.getContext();
  167. IndexingContext IndexCtx(Opts, DataConsumer);
  168. IndexCtx.setASTContext(Ctx);
  169. DataConsumer.initialize(Ctx);
  170. if (Opts.IndexMacrosInPreprocessor)
  171. indexPreprocessorMacros(Reader.getPreprocessor(), DataConsumer);
  172. for (const Decl *D : Reader.getModuleFileLevelDecls(Mod)) {
  173. IndexCtx.indexTopLevelDecl(D);
  174. }
  175. DataConsumer.finish();
  176. }