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 |
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: |
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 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 (StringRef Include, |
115 | const clang::SourceManager &SourceManager, |
116 | clang::HeaderSearch &) const; |
117 | |
118 | /// Get the include fixer context for the queried symbol. |
119 | IncludeFixerContext ( |
120 | const clang::SourceManager &SourceManager, |
121 | clang::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 | |
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 | |