Line data Source code
1 : //===--- CodeComplete.h ------------------------------------------*- C++-*-===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // Code completion provides suggestions for what the user might type next.
11 : // After "std::string S; S." we might suggest members of std::string.
12 : // Signature help describes the parameters of a function as you type them.
13 : //
14 : //===----------------------------------------------------------------------===//
15 :
16 : #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CODECOMPLETE_H
17 : #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CODECOMPLETE_H
18 :
19 : #include "ClangdUnit.h"
20 : #include "Headers.h"
21 : #include "Logger.h"
22 : #include "Path.h"
23 : #include "Protocol.h"
24 : #include "index/Index.h"
25 : #include "clang/Frontend/PrecompiledPreamble.h"
26 : #include "clang/Sema/CodeCompleteConsumer.h"
27 : #include "clang/Sema/CodeCompleteOptions.h"
28 : #include "clang/Tooling/CompilationDatabase.h"
29 : #include "llvm/ADT/Optional.h"
30 : #include "llvm/ADT/SmallVector.h"
31 : #include "llvm/ADT/StringRef.h"
32 : #include "llvm/Support/Error.h"
33 : #include <future>
34 :
35 : namespace clang {
36 : class NamedDecl;
37 : class PCHContainerOperations;
38 : namespace clangd {
39 :
40 0 : struct CodeCompleteOptions {
41 : /// Returns options that can be passed to clang's completion engine.
42 : clang::CodeCompleteOptions getClangCompleteOpts() const;
43 :
44 : /// When true, completion items will contain expandable code snippets in
45 : /// completion (e.g. `return ${1:expression}` or `foo(${1:int a}, ${2:int
46 : /// b})).
47 : bool EnableSnippets = false;
48 :
49 : /// Add code patterns to completion results.
50 : /// If EnableSnippets is false, this options is ignored and code patterns will
51 : /// always be omitted.
52 : bool IncludeCodePatterns = true;
53 :
54 : /// Add macros to code completion results.
55 : bool IncludeMacros = true;
56 :
57 : /// Add comments to code completion results, if available.
58 : bool IncludeComments = true;
59 :
60 : /// Include results that are not legal completions in the current context.
61 : /// For example, private members are usually inaccessible.
62 : bool IncludeIneligibleResults = false;
63 :
64 : /// Combine overloads into a single completion item where possible.
65 : bool BundleOverloads = false;
66 :
67 : /// Limit the number of results returned (0 means no limit).
68 : /// If more results are available, we set CompletionList.isIncomplete.
69 : size_t Limit = 0;
70 :
71 : /// A visual indicator to prepend to the completion label to indicate whether
72 : /// completion result would trigger an #include insertion or not.
73 : struct IncludeInsertionIndicator {
74 : std::string Insert = "•";
75 : std::string NoInsert = " ";
76 : } IncludeIndicator;
77 :
78 : /// Expose origins of completion items in the label (for debugging).
79 : bool ShowOrigins = false;
80 :
81 : /// If set to true, this will send an asynchronous speculative index request,
82 : /// based on the index request for the last code completion on the same file
83 : /// and the filter text typed before the cursor, before sema code completion
84 : /// is invoked. This can reduce the code completion latency (by roughly
85 : /// latency of sema code completion) if the speculative request is the same as
86 : /// the one generated for the ongoing code completion from sema. As a sequence
87 : /// of code completions often have the same scopes and proximity paths etc,
88 : /// this should be effective for a number of code completions.
89 : bool SpeculativeIndexRequest = false;
90 :
91 : // Populated internally by clangd, do not set.
92 : /// If `Index` is set, it is used to augment the code completion
93 : /// results.
94 : /// FIXME(ioeric): we might want a better way to pass the index around inside
95 : /// clangd.
96 : const SymbolIndex *Index = nullptr;
97 :
98 : /// Include completions that require small corrections, e.g. change '.' to
99 : /// '->' on member access etc.
100 : bool IncludeFixIts = false;
101 :
102 : /// Whether to generate snippets for function arguments on code-completion.
103 : /// Needs snippets to be enabled as well.
104 : bool EnableFunctionArgSnippets = true;
105 :
106 : /// Whether to include index symbols that are not defined in the scopes
107 : /// visible from the code completion point. This applies in contexts without
108 : /// explicit scope qualifiers.
109 : ///
110 : /// Such completions can insert scope qualifiers.
111 : bool AllScopes = false;
112 : };
113 :
114 : // Semi-structured representation of a code-complete suggestion for our C++ API.
115 : // We don't use the LSP structures here (unlike most features) as we want
116 : // to expose more data to allow for more precise testing and evaluation.
117 : struct CodeCompletion {
118 : // The unqualified name of the symbol or other completion item.
119 : std::string Name;
120 : // The scope qualifier for the symbol name. e.g. "ns1::ns2::"
121 : // Empty for non-symbol completions. Not inserted, but may be displayed.
122 : std::string Scope;
123 : // Text that must be inserted before the name, and displayed (e.g. base::).
124 : std::string RequiredQualifier;
125 : // Details to be displayed following the name. Not inserted.
126 : std::string Signature;
127 : // Text to be inserted following the name, in snippet format.
128 : std::string SnippetSuffix;
129 : // Type to be displayed for this completion.
130 : std::string ReturnType;
131 : std::string Documentation;
132 : CompletionItemKind Kind = CompletionItemKind::Missing;
133 : // This completion item may represent several symbols that can be inserted in
134 : // the same way, such as function overloads. In this case BundleSize > 1, and
135 : // the following fields are summaries:
136 : // - Signature is e.g. "(...)" for functions.
137 : // - SnippetSuffix is similarly e.g. "(${0})".
138 : // - ReturnType may be empty
139 : // - Documentation may be from one symbol, or a combination of several
140 : // Other fields should apply equally to all bundled completions.
141 : unsigned BundleSize = 1;
142 : SymbolOrigin Origin = SymbolOrigin::Unknown;
143 :
144 0 : struct IncludeCandidate {
145 : // The header through which this symbol could be included.
146 : // Quoted string as expected by an #include directive, e.g. "<memory>".
147 : // Empty for non-symbol completions, or when not known.
148 : std::string Header;
149 : // Present if Header should be inserted to use this item.
150 : llvm::Optional<TextEdit> Insertion;
151 : };
152 : // All possible include headers ranked by preference. By default, the first
153 : // include is used.
154 : // If we've bundled together overloads that have different sets of includes,
155 : // thse includes may not be accurate for all of them.
156 : llvm::SmallVector<IncludeCandidate, 1> Includes;
157 :
158 : /// Holds information about small corrections that needs to be done. Like
159 : /// converting '->' to '.' on member access.
160 : std::vector<TextEdit> FixIts;
161 :
162 : /// Holds the range of the token we are going to replace with this completion.
163 : Range CompletionTokenRange;
164 :
165 : // Scores are used to rank completion items.
166 : struct Scores {
167 : // The score that items are ranked by.
168 : float Total = 0.f;
169 :
170 : // The finalScore with the fuzzy name match score excluded.
171 : // When filtering client-side, editors should calculate the new fuzzy score,
172 : // whose scale is 0-1 (with 1 = prefix match, special case 2 = exact match),
173 : // and recompute finalScore = fuzzyScore * symbolScore.
174 : float ExcludingName = 0.f;
175 :
176 : // Component scores that contributed to the final score:
177 :
178 : // Quality describes how important we think this candidate is,
179 : // independent of the query.
180 : // e.g. symbols with lots of incoming references have higher quality.
181 : float Quality = 0.f;
182 : // Relevance describes how well this candidate matched the query.
183 : // e.g. symbols from nearby files have higher relevance.
184 : float Relevance = 0.f;
185 : };
186 : Scores Score;
187 :
188 : /// Indicates if this item is deprecated.
189 : bool Deprecated = false;
190 :
191 : // Serialize this to an LSP completion item. This is a lossy operation.
192 : CompletionItem render(const CodeCompleteOptions &) const;
193 : };
194 : raw_ostream &operator<<(raw_ostream &, const CodeCompletion &);
195 0 : struct CodeCompleteResult {
196 : std::vector<CodeCompletion> Completions;
197 : bool HasMore = false;
198 : CodeCompletionContext::Kind Context = CodeCompletionContext::CCC_Other;
199 : };
200 : raw_ostream &operator<<(raw_ostream &, const CodeCompleteResult &);
201 :
202 : /// A speculative and asynchronous fuzzy find index request (based on cached
203 : /// request) that can be sent before parsing sema. This would reduce completion
204 : /// latency if the speculation succeeds.
205 : struct SpeculativeFuzzyFind {
206 : /// A cached request from past code completions.
207 : /// Set by caller of `codeComplete()`.
208 : llvm::Optional<FuzzyFindRequest> CachedReq;
209 : /// The actual request used by `codeComplete()`.
210 : /// Set by `codeComplete()`. This can be used by callers to update cache.
211 : llvm::Optional<FuzzyFindRequest> NewReq;
212 : /// The result is consumed by `codeComplete()` if speculation succeeded.
213 : /// NOTE: the destructor will wait for the async call to finish.
214 : std::future<SymbolSlab> Result;
215 : };
216 :
217 : /// Get code completions at a specified \p Pos in \p FileName.
218 : /// If \p SpecFuzzyFind is set, a speculative and asynchronous fuzzy find index
219 : /// request (based on cached request) will be run before parsing sema. In case
220 : /// the speculative result is used by code completion (e.g. speculation failed),
221 : /// the speculative result is not consumed, and `SpecFuzzyFind` is only
222 : /// destroyed when the async request finishes.
223 : CodeCompleteResult codeComplete(PathRef FileName,
224 : const tooling::CompileCommand &Command,
225 : const PreambleData *Preamble,
226 : StringRef Contents, Position Pos,
227 : IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
228 : std::shared_ptr<PCHContainerOperations> PCHs,
229 : CodeCompleteOptions Opts,
230 : SpeculativeFuzzyFind *SpecFuzzyFind = nullptr);
231 :
232 : /// Get signature help at a specified \p Pos in \p FileName.
233 : SignatureHelp signatureHelp(PathRef FileName,
234 : const tooling::CompileCommand &Command,
235 : const PreambleData *Preamble, StringRef Contents,
236 : Position Pos,
237 : IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
238 : std::shared_ptr<PCHContainerOperations> PCHs,
239 : const SymbolIndex *Index);
240 :
241 : // For index-based completion, we only consider:
242 : // * symbols in namespaces or translation unit scopes (e.g. no class
243 : // members, no locals)
244 : // * enum constants in unscoped enum decl (e.g. "red" in "enum {red};")
245 : // * primary templates (no specializations)
246 : // For the other cases, we let Clang do the completion because it does not
247 : // need any non-local information and it will be much better at following
248 : // lookup rules. Other symbols still appear in the index for other purposes,
249 : // like workspace/symbols or textDocument/definition, but are not used for code
250 : // completion.
251 : bool isIndexedForCodeCompletion(const NamedDecl &ND, ASTContext &ASTCtx);
252 :
253 : /// Retrives a speculative code completion filter text before the cursor.
254 : /// Exposed for testing only.
255 : llvm::Expected<llvm::StringRef>
256 : speculateCompletionFilter(llvm::StringRef Content, Position Pos);
257 :
258 : } // namespace clangd
259 : } // namespace clang
260 :
261 : #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_CODECOMPLETE_H
|