xref: /aosp_15_r20/external/clang/lib/Index/IndexingAction.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
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  
_anchor()20  void IndexDataConsumer::_anchor() {}
21  
handleDeclOccurence(const Decl * D,SymbolRoleSet Roles,ArrayRef<SymbolRelation> Relations,FileID FID,unsigned Offset,ASTNodeInfo ASTNode)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  
handleMacroOccurence(const IdentifierInfo * Name,const MacroInfo * MI,SymbolRoleSet Roles,FileID FID,unsigned Offset)29  bool IndexDataConsumer::handleMacroOccurence(const IdentifierInfo *Name,
30                                               const MacroInfo *MI, SymbolRoleSet Roles,
31                                               FileID FID, unsigned Offset) {
32    return true;
33  }
34  
handleModuleOccurence(const ImportDecl * ImportD,SymbolRoleSet Roles,FileID FID,unsigned Offset)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:
IndexASTConsumer(IndexingContext & IndexCtx)47    IndexASTConsumer(IndexingContext &IndexCtx)
48      : IndexCtx(IndexCtx) {}
49  
50  protected:
Initialize(ASTContext & Context)51    void Initialize(ASTContext &Context) override {
52      IndexCtx.setASTContext(Context);
53      IndexCtx.getDataConsumer().initialize(Context);
54    }
55  
HandleTopLevelDecl(DeclGroupRef DG)56    bool HandleTopLevelDecl(DeclGroupRef DG) override {
57      return IndexCtx.indexDeclGroupRef(DG);
58    }
59  
HandleInterestingDecl(DeclGroupRef DG)60    void HandleInterestingDecl(DeclGroupRef DG) override {
61      // Ignore deserialized decls.
62    }
63  
HandleTopLevelDeclInObjCContainer(DeclGroupRef DG)64    void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
65      IndexCtx.indexDeclGroupRef(DG);
66    }
67  
HandleTranslationUnit(ASTContext & Ctx)68    void HandleTranslationUnit(ASTContext &Ctx) override {
69    }
70  };
71  
72  class IndexActionBase {
73  protected:
74    std::shared_ptr<IndexDataConsumer> DataConsumer;
75    IndexingContext IndexCtx;
76  
IndexActionBase(std::shared_ptr<IndexDataConsumer> dataConsumer,IndexingOptions Opts)77    IndexActionBase(std::shared_ptr<IndexDataConsumer> dataConsumer,
78                    IndexingOptions Opts)
79      : DataConsumer(std::move(dataConsumer)),
80        IndexCtx(Opts, *DataConsumer) {}
81  
createIndexASTConsumer()82    std::unique_ptr<IndexASTConsumer> createIndexASTConsumer() {
83      return llvm::make_unique<IndexASTConsumer>(IndexCtx);
84    }
85  
finish()86    void finish() {
87      DataConsumer->finish();
88    }
89  };
90  
91  class IndexAction : public ASTFrontendAction, IndexActionBase {
92  public:
IndexAction(std::shared_ptr<IndexDataConsumer> DataConsumer,IndexingOptions Opts)93    IndexAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
94                IndexingOptions Opts)
95      : IndexActionBase(std::move(DataConsumer), Opts) {}
96  
97  protected:
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)98    std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
99                                                   StringRef InFile) override {
100      return createIndexASTConsumer();
101    }
102  
EndSourceFileAction()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:
WrappingIndexAction(std::unique_ptr<FrontendAction> WrappedAction,std::shared_ptr<IndexDataConsumer> DataConsumer,IndexingOptions Opts)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  
EndSourceFileAction()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>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)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>
createIndexingAction(std::shared_ptr<IndexDataConsumer> DataConsumer,IndexingOptions Opts,std::unique_ptr<FrontendAction> WrappedAction)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  
topLevelDeclVisitor(void * context,const Decl * D)160  static bool topLevelDeclVisitor(void *context, const Decl *D) {
161    IndexingContext &IndexCtx = *static_cast<IndexingContext*>(context);
162    return IndexCtx.indexTopLevelDecl(D);
163  }
164  
indexTranslationUnit(ASTUnit & Unit,IndexingContext & IndexCtx)165  static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx) {
166    Unit.visitLocalTopLevelDecls(&IndexCtx, topLevelDeclVisitor);
167  }
168  
indexASTUnit(ASTUnit & Unit,std::shared_ptr<IndexDataConsumer> DataConsumer,IndexingOptions Opts)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