blob: 0003b6143f910043fb34f0e35ddcd7a0f8816511 [file] [log] [blame]
Benjamin Kramercd2494e92016-11-17 15:16:05 +00001//===- IncludeFixerPlugin.cpp - clang-include-fixer as a clang plugin -----===//
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 "../IncludeFixer.h"
11#include "../YamlSymbolIndex.h"
12#include "clang/Frontend/CompilerInstance.h"
13#include "clang/Frontend/FrontendPluginRegistry.h"
14#include "clang/Parse/ParseAST.h"
15#include "clang/Sema/Sema.h"
16#include "llvm/Support/Path.h"
17
18namespace clang {
19namespace include_fixer {
20
21/// The core include fixer plugin action. This just provides the AST consumer
22/// and command line flag parsing for using include fixer as a clang plugin.
23class ClangIncludeFixerPluginAction : public PluginASTAction {
24 /// ASTConsumer to keep the symbol index alive. We don't really need an
25 /// ASTConsumer for this plugin (everything is funneled on the side through
26 /// Sema) but we have to keep the symbol index alive until sema is done.
27 struct ASTConsumerManagerWrapper : public ASTConsumer {
28 ASTConsumerManagerWrapper(std::shared_ptr<SymbolIndexManager> SIM)
29 : SymbolIndexMgr(std::move(SIM)) {}
30 std::shared_ptr<SymbolIndexManager> SymbolIndexMgr;
31 };
32
33public:
34 explicit ClangIncludeFixerPluginAction()
35 : SymbolIndexMgr(std::make_shared<SymbolIndexManager>()),
36 SemaSource(new IncludeFixerSemaSource(*SymbolIndexMgr,
37 /*MinimizeIncludePaths=*/true,
38 /*GenerateDiagnostics=*/true)) {}
39
40 std::unique_ptr<clang::ASTConsumer>
41 CreateASTConsumer(clang::CompilerInstance &CI, StringRef InFile) override {
42 CI.setExternalSemaSource(SemaSource);
43 SemaSource->setFilePath(InFile);
44 SemaSource->setCompilerInstance(&CI);
45 return llvm::make_unique<ASTConsumerManagerWrapper>(SymbolIndexMgr);
46 }
47
48 void ExecuteAction() override {} // Do nothing.
49
50 bool ParseArgs(const CompilerInstance &CI,
51 const std::vector<std::string> &Args) override {
52 StringRef DB = "yaml";
53 StringRef Input;
54
55 // Parse the extra command line args.
56 // FIXME: This is very limited at the moment.
57 for (StringRef Arg : Args) {
58 if (Arg.startswith("-db="))
59 DB = Arg.substr(strlen("-db="));
60 else if (Arg.startswith("-input="))
61 Input = Arg.substr(strlen("-input="));
62 }
63
64 llvm::ErrorOr<std::unique_ptr<include_fixer::YamlSymbolIndex>> SymbolIdx(
65 nullptr);
66 if (DB == "yaml") {
67 if (!Input.empty()) {
68 SymbolIdx = include_fixer::YamlSymbolIndex::createFromFile(Input);
69 } else {
70 // If we don't have any input file, look in the directory of the first
71 // file and its parents.
72 const FrontendOptions &FO = CI.getFrontendOpts();
73 SmallString<128> AbsolutePath(
74 tooling::getAbsolutePath(FO.Inputs[0].getFile()));
75 StringRef Directory = llvm::sys::path::parent_path(AbsolutePath);
76 SymbolIdx = include_fixer::YamlSymbolIndex::createFromDirectory(
77 Directory, "find_all_symbols_db.yaml");
78 }
79 }
80 SymbolIndexMgr->addSymbolIndex(std::move(*SymbolIdx));
81 return true;
82 }
83
84private:
85 std::shared_ptr<SymbolIndexManager> SymbolIndexMgr;
86 IntrusiveRefCntPtr<IncludeFixerSemaSource> SemaSource;
87};
88} // namespace include_fixer
89} // namespace clang
90
91// This anchor is used to force the linker to link in the generated object file
92// and thus register the include fixer plugin.
93volatile int ClangIncludeFixerPluginAnchorSource = 0;
94
95static clang::FrontendPluginRegistry::Add<
96 clang::include_fixer::ClangIncludeFixerPluginAction>
97 X("clang-include-fixer", "clang-include-fixer");