Clang Project

clang_source_code/lib/Index/IndexingAction.cpp
1//===- IndexingAction.cpp - Frontend index action -------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "clang/Index/IndexingAction.h"
10#include "IndexingContext.h"
11#include "clang/Frontend/CompilerInstance.h"
12#include "clang/Frontend/FrontendAction.h"
13#include "clang/Frontend/MultiplexConsumer.h"
14#include "clang/Index/IndexDataConsumer.h"
15#include "clang/Lex/PPCallbacks.h"
16#include "clang/Lex/Preprocessor.h"
17#include "clang/Serialization/ASTReader.h"
18#include "llvm/ADT/STLExtras.h"
19#include <memory>
20
21using namespace clang;
22using namespace clang::index;
23
24bool IndexDataConsumer::handleDeclOccurence(const Decl *DSymbolRoleSet Roles,
25                                            ArrayRef<SymbolRelationRelations,
26                                            SourceLocation Loc,
27                                            ASTNodeInfo ASTNode) {
28  return true;
29}
30
31bool IndexDataConsumer::handleMacroOccurence(const IdentifierInfo *Name,
32                                             const MacroInfo *MI,
33                                             SymbolRoleSet Roles,
34                                             SourceLocation Loc) {
35  return true;
36}
37
38bool IndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD,
39                                              const Module *Mod,
40                                              SymbolRoleSet Roles,
41                                              SourceLocation Loc) {
42  return true;
43}
44
45namespace {
46
47class IndexASTConsumer : public ASTConsumer {
48  std::shared_ptr<PreprocessorPP;
49  std::shared_ptr<IndexingContextIndexCtx;
50
51public:
52  IndexASTConsumer(std::shared_ptr<PreprocessorPP,
53                   std::shared_ptr<IndexingContextIndexCtx)
54      : PP(std::move(PP)), IndexCtx(std::move(IndexCtx)) {}
55
56protected:
57  void Initialize(ASTContext &Context) override {
58    IndexCtx->setASTContext(Context);
59    IndexCtx->getDataConsumer().initialize(Context);
60    IndexCtx->getDataConsumer().setPreprocessor(PP);
61  }
62
63  bool HandleTopLevelDecl(DeclGroupRef DG) override {
64    return IndexCtx->indexDeclGroupRef(DG);
65  }
66
67  void HandleInterestingDecl(DeclGroupRef DG) override {
68    // Ignore deserialized decls.
69  }
70
71  void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
72    IndexCtx->indexDeclGroupRef(DG);
73  }
74
75  void HandleTranslationUnit(ASTContext &Ctx) override {
76  }
77};
78
79class IndexPPCallbacks : public PPCallbacks {
80  std::shared_ptr<IndexingContextIndexCtx;
81
82public:
83  IndexPPCallbacks(std::shared_ptr<IndexingContextIndexCtx)
84      : IndexCtx(std::move(IndexCtx)) {}
85
86  void MacroExpands(const Token &MacroNameTokconst MacroDefinition &MD,
87                    SourceRange Rangeconst MacroArgs *Args) override {
88    IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),
89                                   Range.getBegin(), *MD.getMacroInfo());
90  }
91
92  void MacroDefined(const Token &MacroNameTok,
93                    const MacroDirective *MD) override {
94    IndexCtx->handleMacroDefined(*MacroNameTok.getIdentifierInfo(),
95                                 MacroNameTok.getLocation(),
96                                 *MD->getMacroInfo());
97  }
98
99  void MacroUndefined(const Token &MacroNameTokconst MacroDefinition &MD,
100                      const MacroDirective *Undef) override {
101    if (!MD.getMacroInfo())  // Ignore noop #undef.
102      return;
103    IndexCtx->handleMacroUndefined(*MacroNameTok.getIdentifierInfo(),
104                                   MacroNameTok.getLocation(),
105                                   *MD.getMacroInfo());
106  }
107};
108
109class IndexActionBase {
110protected:
111  std::shared_ptr<IndexDataConsumerDataConsumer;
112  std::shared_ptr<IndexingContextIndexCtx;
113
114  IndexActionBase(std::shared_ptr<IndexDataConsumerdataConsumer,
115                  IndexingOptions Opts)
116      : DataConsumer(std::move(dataConsumer)),
117        IndexCtx(new IndexingContext(Opts, *DataConsumer)) {}
118
119  std::unique_ptr<IndexASTConsumer>
120  createIndexASTConsumer(CompilerInstance &CI) {
121    return llvm::make_unique<IndexASTConsumer>(CI.getPreprocessorPtr(),
122                                               IndexCtx);
123  }
124
125  std::unique_ptr<PPCallbackscreateIndexPPCallbacks() {
126    return llvm::make_unique<IndexPPCallbacks>(IndexCtx);
127  }
128
129  void finish() {
130    DataConsumer->finish();
131  }
132};
133
134class IndexAction : public ASTFrontendActionIndexActionBase {
135public:
136  IndexAction(std::shared_ptr<IndexDataConsumerDataConsumer,
137              IndexingOptions Opts)
138    : IndexActionBase(std::move(DataConsumer), Opts) {}
139
140protected:
141  std::unique_ptr<ASTConsumerCreateASTConsumer(CompilerInstance &CI,
142                                                 StringRef InFile) override {
143    return createIndexASTConsumer(CI);
144  }
145
146  bool BeginSourceFileAction(clang::CompilerInstance &CI) override {
147    CI.getPreprocessor().addPPCallbacks(createIndexPPCallbacks());
148    return true;
149  }
150
151  void EndSourceFileAction() override {
152    FrontendAction::EndSourceFileAction();
153    finish();
154  }
155};
156
157class WrappingIndexAction : public WrapperFrontendActionIndexActionBase {
158  bool IndexActionFailed = false;
159
160public:
161  WrappingIndexAction(std::unique_ptr<FrontendActionWrappedAction,
162                      std::shared_ptr<IndexDataConsumerDataConsumer,
163                      IndexingOptions Opts)
164    : WrapperFrontendAction(std::move(WrappedAction)),
165      IndexActionBase(std::move(DataConsumer), Opts) {}
166
167protected:
168  std::unique_ptr<ASTConsumerCreateASTConsumer(CompilerInstance &CI,
169                                                 StringRef InFile) override {
170    auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
171    if (!OtherConsumer) {
172      IndexActionFailed = true;
173      return nullptr;
174    }
175
176    std::vector<std::unique_ptr<ASTConsumer>> Consumers;
177    Consumers.push_back(std::move(OtherConsumer));
178    Consumers.push_back(createIndexASTConsumer(CI));
179    return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
180  }
181
182  bool BeginSourceFileAction(clang::CompilerInstance &CI) override {
183    WrapperFrontendAction::BeginSourceFileAction(CI);
184    CI.getPreprocessor().addPPCallbacks(createIndexPPCallbacks());
185    return true;
186  }
187
188  void EndSourceFileAction() override {
189    // Invoke wrapped action's method.
190    WrapperFrontendAction::EndSourceFileAction();
191    if (!IndexActionFailed)
192      finish();
193  }
194};
195
196// anonymous namespace
197
198std::unique_ptr<FrontendAction>
199index::createIndexingAction(std::shared_ptr<IndexDataConsumerDataConsumer,
200                            IndexingOptions Opts,
201                            std::unique_ptr<FrontendActionWrappedAction) {
202  if (WrappedAction)
203    return llvm::make_unique<WrappingIndexAction>(std::move(WrappedAction),
204                                                  std::move(DataConsumer),
205                                                  Opts);
206  return llvm::make_unique<IndexAction>(std::move(DataConsumer), Opts);
207}
208
209static bool topLevelDeclVisitor(void *contextconst Decl *D) {
210  IndexingContext &IndexCtx = *static_cast<IndexingContext*>(context);
211  return IndexCtx.indexTopLevelDecl(D);
212}
213
214static void indexTranslationUnit(ASTUnit &UnitIndexingContext &IndexCtx) {
215  Unit.visitLocalTopLevelDecls(&IndexCtxtopLevelDeclVisitor);
216}
217
218static void indexPreprocessorMacros(const Preprocessor &PP,
219                                    IndexDataConsumer &DataConsumer) {
220  for (const auto &M : PP.macros())
221    if (MacroDirective *MD = M.second.getLatest())
222      DataConsumer.handleMacroOccurence(
223          M.first, MD->getMacroInfo(),
224          static_cast<unsigned>(index::SymbolRole::Definition),
225          MD->getLocation());
226}
227
228void index::indexASTUnit(ASTUnit &UnitIndexDataConsumer &DataConsumer,
229                         IndexingOptions Opts) {
230  IndexingContext IndexCtx(OptsDataConsumer);
231  IndexCtx.setASTContext(Unit.getASTContext());
232  DataConsumer.initialize(Unit.getASTContext());
233  DataConsumer.setPreprocessor(Unit.getPreprocessorPtr());
234
235  if (Opts.IndexMacrosInPreprocessor)
236    indexPreprocessorMacros(Unit.getPreprocessor(), DataConsumer);
237  indexTranslationUnit(UnitIndexCtx);
238  DataConsumer.finish();
239}
240
241void index::indexTopLevelDecls(ASTContext &CtxPreprocessor &PP,
242                               ArrayRef<const Decl *> Decls,
243                               IndexDataConsumer &DataConsumer,
244                               IndexingOptions Opts) {
245  IndexingContext IndexCtx(OptsDataConsumer);
246  IndexCtx.setASTContext(Ctx);
247
248  DataConsumer.initialize(Ctx);
249
250  if (Opts.IndexMacrosInPreprocessor)
251    indexPreprocessorMacros(PPDataConsumer);
252
253  for (const Decl *D : Decls)
254    IndexCtx.indexTopLevelDecl(D);
255  DataConsumer.finish();
256}
257
258std::unique_ptr<PPCallbacks>
259index::indexMacrosCallback(IndexDataConsumer &ConsumerIndexingOptions Opts) {
260  return llvm::make_unique<IndexPPCallbacks>(
261      std::make_shared<IndexingContext>(Opts, Consumer));
262}
263
264void index::indexModuleFile(serialization::ModuleFile &ModASTReader &Reader,
265                            IndexDataConsumer &DataConsumer,
266                            IndexingOptions Opts) {
267  ASTContext &Ctx = Reader.getContext();
268  IndexingContext IndexCtx(OptsDataConsumer);
269  IndexCtx.setASTContext(Ctx);
270  DataConsumer.initialize(Ctx);
271
272  if (Opts.IndexMacrosInPreprocessor)
273    indexPreprocessorMacros(Reader.getPreprocessor(), DataConsumer);
274
275  for (const Decl *D : Reader.getModuleFileLevelDecls(Mod)) {
276    IndexCtx.indexTopLevelDecl(D);
277  }
278  DataConsumer.finish();
279}
280
clang::index::IndexDataConsumer::handleDeclOccurence
clang::index::IndexDataConsumer::handleMacroOccurence
clang::index::IndexDataConsumer::handleModuleOccurence