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