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