160 lines · c
1//===-- IncludeFixer.h - Include inserter -----------------------*- C++ -*-===//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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_INCLUDEFIXER_H10#define LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_INCLUDEFIXER_H11 12#include "IncludeFixerContext.h"13#include "SymbolIndexManager.h"14#include "clang/Format/Format.h"15#include "clang/Sema/ExternalSemaSource.h"16#include "clang/Tooling/Core/Replacement.h"17#include "clang/Tooling/Tooling.h"18#include <memory>19#include <vector>20 21namespace clang {22 23class CompilerInvocation;24class DiagnosticConsumer;25class FileManager;26class PCHContainerOperations;27 28namespace include_fixer {29 30class IncludeFixerActionFactory : public clang::tooling::ToolAction {31public:32 /// \param SymbolIndexMgr A source for matching symbols to header files.33 /// \param Contexts The contexts for the symbols being queried.34 /// \param StyleName Fallback style for reformatting.35 /// \param MinimizeIncludePaths whether inserted include paths are optimized.36 IncludeFixerActionFactory(SymbolIndexManager &SymbolIndexMgr,37 std::vector<IncludeFixerContext> &Contexts,38 StringRef StyleName,39 bool MinimizeIncludePaths = true);40 41 ~IncludeFixerActionFactory() override;42 43 bool44 runInvocation(std::shared_ptr<clang::CompilerInvocation> Invocation,45 clang::FileManager *Files,46 std::shared_ptr<clang::PCHContainerOperations> PCHContainerOps,47 clang::DiagnosticConsumer *Diagnostics) override;48 49private:50 /// The client to use to find cross-references.51 SymbolIndexManager &SymbolIndexMgr;52 53 /// Multiple contexts for files being processed.54 std::vector<IncludeFixerContext> &Contexts;55 56 /// Whether inserted include paths should be optimized.57 bool MinimizeIncludePaths;58 59 /// The fallback format style for formatting after insertion if no60 /// clang-format config file was found.61 std::string FallbackStyle;62};63 64/// Create replacements, which are generated by clang-format, for the65/// missing header and missing qualifiers insertions. The function uses the66/// first header for insertion.67///68/// \param Code The source code.69/// \param Context The context which contains all information for creating70/// clang-include-fixer replacements.71/// \param Style clang-format style being used.72/// \param AddQualifiers Whether we should add qualifiers to all instances of73/// an unidentified symbol.74///75/// \return Formatted replacements for inserting, sorting headers and adding76/// qualifiers on success; otherwise, an llvm::Error carrying llvm::StringError77/// is returned.78llvm::Expected<tooling::Replacements> createIncludeFixerReplacements(79 StringRef Code, const IncludeFixerContext &Context,80 const format::FormatStyle &Style = format::getLLVMStyle(),81 bool AddQualifiers = true);82 83/// Handles callbacks from sema, does the include lookup and turns it into an84/// IncludeFixerContext.85class IncludeFixerSemaSource : public clang::ExternalSemaSource {86public:87 explicit IncludeFixerSemaSource(SymbolIndexManager &SymbolIndexMgr,88 bool MinimizeIncludePaths,89 bool GenerateDiagnostics)90 : SymbolIndexMgr(SymbolIndexMgr),91 MinimizeIncludePaths(MinimizeIncludePaths),92 GenerateDiagnostics(GenerateDiagnostics) {}93 94 void setCompilerInstance(CompilerInstance *CI) { this->CI = CI; }95 void setFilePath(StringRef FilePath) {96 this->FilePath = std::string(FilePath);97 }98 99 /// Callback for incomplete types. If we encounter a forward declaration we100 /// have the fully qualified name ready. Just query that.101 bool MaybeDiagnoseMissingCompleteType(clang::SourceLocation Loc,102 clang::QualType T) override;103 104 /// Callback for unknown identifiers. Try to piece together as much105 /// qualification as we can get and do a query.106 clang::TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,107 int LookupKind, Scope *S, CXXScopeSpec *SS,108 CorrectionCandidateCallback &CCC,109 DeclContext *MemberContext,110 bool EnteringContext,111 const ObjCObjectPointerType *OPT) override;112 113 /// Get the minimal include for a given path.114 std::string minimizeInclude(StringRef Include,115 const clang::SourceManager &SourceManager,116 clang::HeaderSearch &HeaderSearch) const;117 118 /// Get the include fixer context for the queried symbol.119 IncludeFixerContext getIncludeFixerContext(120 const clang::SourceManager &SourceManager,121 clang::HeaderSearch &HeaderSearch,122 ArrayRef<find_all_symbols::SymbolInfo> MatchedSymbols) const;123 124 /// Get the global matched symbols.125 ArrayRef<find_all_symbols::SymbolInfo> getMatchedSymbols() const {126 return MatchedSymbols;127 }128 129private:130 /// Query the database for a given identifier.131 std::vector<find_all_symbols::SymbolInfo>132 query(StringRef Query, StringRef ScopedQualifiers, tooling::Range Range);133 134 CompilerInstance *CI;135 136 /// The client to use to find cross-references.137 SymbolIndexManager &SymbolIndexMgr;138 139 /// The information of the symbols being queried.140 std::vector<IncludeFixerContext::QuerySymbolInfo> QuerySymbolInfos;141 142 /// All symbol candidates which match QuerySymbol. We only include the first143 /// discovered identifier to avoid getting caught in results from error144 /// recovery.145 std::vector<find_all_symbols::SymbolInfo> MatchedSymbols;146 147 /// The file path to the file being processed.148 std::string FilePath;149 150 /// Whether we should use the smallest possible include path.151 bool MinimizeIncludePaths = true;152 153 /// Whether we should generate diagnostics with fixits for missing symbols.154 bool GenerateDiagnostics = false;155};156} // namespace include_fixer157} // namespace clang158 159#endif // LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_INCLUDEFIXER_H160