101 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			101 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===- IncludeFixerPlugin.cpp - clang-include-fixer as a clang plugin -----===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "../IncludeFixer.h"
 | |
| #include "../YamlSymbolIndex.h"
 | |
| #include "clang/Frontend/CompilerInstance.h"
 | |
| #include "clang/Frontend/FrontendPluginRegistry.h"
 | |
| #include "clang/Parse/ParseAST.h"
 | |
| #include "clang/Sema/Sema.h"
 | |
| #include "llvm/Support/Path.h"
 | |
| 
 | |
| namespace clang {
 | |
| namespace include_fixer {
 | |
| 
 | |
| /// The core include fixer plugin action. This just provides the AST consumer
 | |
| /// and command line flag parsing for using include fixer as a clang plugin.
 | |
| class ClangIncludeFixerPluginAction : public PluginASTAction {
 | |
|   /// ASTConsumer to keep the symbol index alive. We don't really need an
 | |
|   /// ASTConsumer for this plugin (everything is funneled on the side through
 | |
|   /// Sema) but we have to keep the symbol index alive until sema is done.
 | |
|   struct ASTConsumerManagerWrapper : public ASTConsumer {
 | |
|     ASTConsumerManagerWrapper(std::shared_ptr<SymbolIndexManager> SIM)
 | |
|         : SymbolIndexMgr(std::move(SIM)) {}
 | |
|     std::shared_ptr<SymbolIndexManager> SymbolIndexMgr;
 | |
|   };
 | |
| 
 | |
| public:
 | |
|   explicit ClangIncludeFixerPluginAction()
 | |
|       : SymbolIndexMgr(std::make_shared<SymbolIndexManager>()),
 | |
|         SemaSource(new IncludeFixerSemaSource(*SymbolIndexMgr,
 | |
|                                               /*MinimizeIncludePaths=*/true,
 | |
|                                               /*GenerateDiagnostics=*/true)) {}
 | |
| 
 | |
|   std::unique_ptr<clang::ASTConsumer>
 | |
|   CreateASTConsumer(clang::CompilerInstance &CI, StringRef InFile) override {
 | |
|     CI.setExternalSemaSource(SemaSource);
 | |
|     SemaSource->setFilePath(InFile);
 | |
|     SemaSource->setCompilerInstance(&CI);
 | |
|     return std::make_unique<ASTConsumerManagerWrapper>(SymbolIndexMgr);
 | |
|   }
 | |
| 
 | |
|   void ExecuteAction() override {} // Do nothing.
 | |
| 
 | |
|   bool ParseArgs(const CompilerInstance &CI,
 | |
|                  const std::vector<std::string> &Args) override {
 | |
|     StringRef DB = "yaml";
 | |
|     StringRef Input;
 | |
| 
 | |
|     // Parse the extra command line args.
 | |
|     // FIXME: This is very limited at the moment.
 | |
|     for (StringRef Arg : Args) {
 | |
|       if (Arg.startswith("-db="))
 | |
|         DB = Arg.substr(strlen("-db="));
 | |
|       else if (Arg.startswith("-input="))
 | |
|         Input = Arg.substr(strlen("-input="));
 | |
|     }
 | |
| 
 | |
|     std::string InputFile =
 | |
|         std::string(CI.getFrontendOpts().Inputs[0].getFile());
 | |
|     auto CreateYamlIdx = [=]() -> std::unique_ptr<include_fixer::SymbolIndex> {
 | |
|       llvm::ErrorOr<std::unique_ptr<include_fixer::YamlSymbolIndex>> SymbolIdx(
 | |
|           nullptr);
 | |
|       if (DB == "yaml") {
 | |
|         if (!Input.empty()) {
 | |
|           SymbolIdx = include_fixer::YamlSymbolIndex::createFromFile(Input);
 | |
|         } else {
 | |
|           // If we don't have any input file, look in the directory of the first
 | |
|           // file and its parents.
 | |
|           SmallString<128> AbsolutePath(tooling::getAbsolutePath(InputFile));
 | |
|           StringRef Directory = llvm::sys::path::parent_path(AbsolutePath);
 | |
|           SymbolIdx = include_fixer::YamlSymbolIndex::createFromDirectory(
 | |
|               Directory, "find_all_symbols_db.yaml");
 | |
|         }
 | |
|       }
 | |
|       return std::move(*SymbolIdx);
 | |
|     };
 | |
| 
 | |
|     SymbolIndexMgr->addSymbolIndex(std::move(CreateYamlIdx));
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
| private:
 | |
|   std::shared_ptr<SymbolIndexManager> SymbolIndexMgr;
 | |
|   IntrusiveRefCntPtr<IncludeFixerSemaSource> SemaSource;
 | |
| };
 | |
| } // namespace include_fixer
 | |
| } // namespace clang
 | |
| 
 | |
| // This anchor is used to force the linker to link in the generated object file
 | |
| // and thus register the include fixer plugin.
 | |
| volatile int ClangIncludeFixerPluginAnchorSource = 0;
 | |
| 
 | |
| static clang::FrontendPluginRegistry::Add<
 | |
|     clang::include_fixer::ClangIncludeFixerPluginAction>
 | |
|     X("clang-include-fixer", "clang-include-fixer");
 |