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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_INCLUDEFIXER_H 10 #define LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_INCLUDEFIXER_H 11 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 21 namespace clang { 22 23 class CompilerInvocation; 24 class DiagnosticConsumer; 25 class FileManager; 26 class PCHContainerOperations; 27 28 namespace include_fixer { 29 30 class IncludeFixerActionFactory : public clang::tooling::ToolAction { 31 public: 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 bool 44 runInvocation(std::shared_ptr<clang::CompilerInvocation> Invocation, 45 clang::FileManager *Files, 46 std::shared_ptr<clang::PCHContainerOperations> PCHContainerOps, 47 clang::DiagnosticConsumer *Diagnostics) override; 48 49 private: 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 no 60 /// clang-format config file was found. 61 std::string FallbackStyle; 62 }; 63 64 /// Create replacements, which are generated by clang-format, for the 65 /// missing header and missing qualifiers insertions. The function uses the 66 /// first header for insertion. 67 /// 68 /// \param Code The source code. 69 /// \param Context The context which contains all information for creating 70 /// clang-include-fixer replacements. 71 /// \param Style clang-format style being used. 72 /// \param AddQualifiers Whether we should add qualifiers to all instances of 73 /// an unidentified symbol. 74 /// 75 /// \return Formatted replacements for inserting, sorting headers and adding 76 /// qualifiers on success; otherwise, an llvm::Error carrying llvm::StringError 77 /// is returned. 78 llvm::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 an 84 /// IncludeFixerContext. 85 class IncludeFixerSemaSource : public clang::ExternalSemaSource { 86 public: IncludeFixerSemaSource(SymbolIndexManager & SymbolIndexMgr,bool MinimizeIncludePaths,bool GenerateDiagnostics)87 explicit IncludeFixerSemaSource(SymbolIndexManager &SymbolIndexMgr, 88 bool MinimizeIncludePaths, 89 bool GenerateDiagnostics) 90 : SymbolIndexMgr(SymbolIndexMgr), 91 MinimizeIncludePaths(MinimizeIncludePaths), 92 GenerateDiagnostics(GenerateDiagnostics) {} 93 setCompilerInstance(CompilerInstance * CI)94 void setCompilerInstance(CompilerInstance *CI) { this->CI = CI; } setFilePath(StringRef FilePath)95 void setFilePath(StringRef FilePath) { 96 this->FilePath = std::string(FilePath); 97 } 98 99 /// Callback for incomplete types. If we encounter a forward declaration we 100 /// 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 much 105 /// 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. getMatchedSymbols()125 ArrayRef<find_all_symbols::SymbolInfo> getMatchedSymbols() const { 126 return MatchedSymbols; 127 } 128 129 private: 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 first 143 /// discovered identifier to avoid getting caught in results from error 144 /// 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_fixer 157 } // namespace clang 158 159 #endif // LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_INCLUDEFIXER_H 160