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