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