1 //===- IndexingAction.cpp - Frontend index action -------------------------===// 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/IndexingAction.h" 11 #include "clang/Index/IndexDataConsumer.h" 12 #include "IndexingContext.h" 13 #include "clang/Frontend/FrontendAction.h" 14 #include "clang/Frontend/MultiplexConsumer.h" 15 #include "clang/Lex/Preprocessor.h" 16 17 using namespace clang; 18 using namespace clang::index; 19 20 void IndexDataConsumer::_anchor() {} 21 22 bool IndexDataConsumer::handleDeclOccurence(const Decl *D, SymbolRoleSet Roles, 23 ArrayRef<SymbolRelation> Relations, 24 FileID FID, unsigned Offset, 25 ASTNodeInfo ASTNode) { 26 return true; 27 } 28 29 bool IndexDataConsumer::handleMacroOccurence(const IdentifierInfo *Name, 30 const MacroInfo *MI, SymbolRoleSet Roles, 31 FileID FID, unsigned Offset) { 32 return true; 33 } 34 35 bool IndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD, 36 SymbolRoleSet Roles, 37 FileID FID, unsigned Offset) { 38 return true; 39 } 40 41 namespace { 42 43 class IndexASTConsumer : public ASTConsumer { 44 IndexingContext &IndexCtx; 45 46 public: 47 IndexASTConsumer(IndexingContext &IndexCtx) 48 : IndexCtx(IndexCtx) {} 49 50 protected: 51 void Initialize(ASTContext &Context) override { 52 IndexCtx.setASTContext(Context); 53 IndexCtx.getDataConsumer().initialize(Context); 54 } 55 56 bool HandleTopLevelDecl(DeclGroupRef DG) override { 57 return IndexCtx.indexDeclGroupRef(DG); 58 } 59 60 void HandleInterestingDecl(DeclGroupRef DG) override { 61 // Ignore deserialized decls. 62 } 63 64 void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override { 65 IndexCtx.indexDeclGroupRef(DG); 66 } 67 68 void HandleTranslationUnit(ASTContext &Ctx) override { 69 } 70 }; 71 72 class IndexActionBase { 73 protected: 74 std::shared_ptr<IndexDataConsumer> DataConsumer; 75 IndexingContext IndexCtx; 76 77 IndexActionBase(std::shared_ptr<IndexDataConsumer> dataConsumer, 78 IndexingOptions Opts) 79 : DataConsumer(std::move(dataConsumer)), 80 IndexCtx(Opts, *DataConsumer) {} 81 82 std::unique_ptr<IndexASTConsumer> createIndexASTConsumer() { 83 return llvm::make_unique<IndexASTConsumer>(IndexCtx); 84 } 85 86 void finish() { 87 DataConsumer->finish(); 88 } 89 }; 90 91 class IndexAction : public ASTFrontendAction, IndexActionBase { 92 public: 93 IndexAction(std::shared_ptr<IndexDataConsumer> DataConsumer, 94 IndexingOptions Opts) 95 : IndexActionBase(std::move(DataConsumer), Opts) {} 96 97 protected: 98 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, 99 StringRef InFile) override { 100 return createIndexASTConsumer(); 101 } 102 103 void EndSourceFileAction() override { 104 FrontendAction::EndSourceFileAction(); 105 finish(); 106 } 107 }; 108 109 class WrappingIndexAction : public WrapperFrontendAction, IndexActionBase { 110 bool IndexActionFailed = false; 111 112 public: 113 WrappingIndexAction(std::unique_ptr<FrontendAction> WrappedAction, 114 std::shared_ptr<IndexDataConsumer> DataConsumer, 115 IndexingOptions Opts) 116 : WrapperFrontendAction(std::move(WrappedAction)), 117 IndexActionBase(std::move(DataConsumer), Opts) {} 118 119 protected: 120 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, 121 StringRef InFile) override; 122 void EndSourceFileAction() override; 123 }; 124 125 } // anonymous namespace 126 127 void WrappingIndexAction::EndSourceFileAction() { 128 // Invoke wrapped action's method. 129 WrapperFrontendAction::EndSourceFileAction(); 130 if (!IndexActionFailed) 131 finish(); 132 } 133 134 std::unique_ptr<ASTConsumer> 135 WrappingIndexAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { 136 auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile); 137 if (!OtherConsumer) { 138 IndexActionFailed = true; 139 return nullptr; 140 } 141 142 std::vector<std::unique_ptr<ASTConsumer>> Consumers; 143 Consumers.push_back(std::move(OtherConsumer)); 144 Consumers.push_back(createIndexASTConsumer()); 145 return llvm::make_unique<MultiplexConsumer>(std::move(Consumers)); 146 } 147 148 std::unique_ptr<FrontendAction> 149 index::createIndexingAction(std::shared_ptr<IndexDataConsumer> DataConsumer, 150 IndexingOptions Opts, 151 std::unique_ptr<FrontendAction> WrappedAction) { 152 if (WrappedAction) 153 return llvm::make_unique<WrappingIndexAction>(std::move(WrappedAction), 154 std::move(DataConsumer), 155 Opts); 156 return llvm::make_unique<IndexAction>(std::move(DataConsumer), Opts); 157 } 158 159 160 static bool topLevelDeclVisitor(void *context, const Decl *D) { 161 IndexingContext &IndexCtx = *static_cast<IndexingContext*>(context); 162 return IndexCtx.indexTopLevelDecl(D); 163 } 164 165 static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx) { 166 Unit.visitLocalTopLevelDecls(&IndexCtx, topLevelDeclVisitor); 167 } 168 169 void index::indexASTUnit(ASTUnit &Unit, 170 std::shared_ptr<IndexDataConsumer> DataConsumer, 171 IndexingOptions Opts) { 172 IndexingContext IndexCtx(Opts, *DataConsumer); 173 IndexCtx.setASTContext(Unit.getASTContext()); 174 DataConsumer->initialize(Unit.getASTContext()); 175 indexTranslationUnit(Unit, IndexCtx); 176 } 177