1//===--- CodeComplete.h ------------------------------------------*- 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// Code completion provides suggestions for what the user might type next.
10// After "std::string S; S." we might suggest members of std::string.
11// Signature help describes the parameters of a function as you type them.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CODECOMPLETE_H
16#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CODECOMPLETE_H
17
18#include "ASTSignals.h"
19#include "Compiler.h"
20#include "Protocol.h"
21#include "Quality.h"
22#include "index/Index.h"
23#include "index/Symbol.h"
24#include "index/SymbolOrigin.h"
25#include "support/Markup.h"
26#include "support/Path.h"
27#include "clang/Sema/CodeCompleteConsumer.h"
28#include "clang/Sema/CodeCompleteOptions.h"
29#include "llvm/ADT/SmallVector.h"
30#include "llvm/ADT/StringRef.h"
31#include <functional>
32#include <future>
33#include <optional>
34#include <utility>
35
36namespace clang {
37class NamedDecl;
38namespace clangd {
39struct PreambleData;
40struct CodeCompletion;
41
42struct CodeCompleteOptions {
43 /// Returns options that can be passed to clang's completion engine.
44 clang::CodeCompleteOptions getClangCompleteOpts() const;
45
46 /// When true, completion items will contain expandable code snippets in
47 /// completion (e.g. `return ${1:expression}` or `foo(${1:int a}, ${2:int
48 /// b})).
49 bool EnableSnippets = false;
50
51 /// Include results that are not legal completions in the current context.
52 /// For example, private members are usually inaccessible.
53 bool IncludeIneligibleResults = false;
54
55 /// Combine overloads into a single completion item where possible.
56 /// If none, the implementation may choose an appropriate behavior.
57 /// (In practice, ClangdLSPServer enables bundling if the client claims
58 /// to supports signature help).
59 std::optional<bool> BundleOverloads;
60
61 /// Limit the number of results returned (0 means no limit).
62 /// If more results are available, we set CompletionList.isIncomplete.
63 size_t Limit = 0;
64
65 /// Whether to present doc comments as plain-text or markdown.
66 MarkupKind DocumentationFormat = MarkupKind::PlainText;
67
68 enum IncludeInsertion {
69 IWYU,
70 NeverInsert,
71 } InsertIncludes = IncludeInsertion::IWYU;
72
73 /// Whether include insertions for Objective-C code should use #import instead
74 /// of #include.
75 bool ImportInsertions = false;
76
77 /// A visual indicator to prepend to the completion label to indicate whether
78 /// completion result would trigger an #include insertion or not.
79 struct IncludeInsertionIndicator {
80 std::string Insert = "•";
81 std::string NoInsert = " ";
82 } IncludeIndicator;
83
84 /// Expose origins of completion items in the label (for debugging).
85 bool ShowOrigins = false;
86
87 // Populated internally by clangd, do not set.
88 /// If `Index` is set, it is used to augment the code completion
89 /// results.
90 /// FIXME(ioeric): we might want a better way to pass the index around inside
91 /// clangd.
92 const SymbolIndex *Index = nullptr;
93
94 const ASTSignals *MainFileSignals = nullptr;
95 /// Include completions that require small corrections, e.g. change '.' to
96 /// '->' on member access etc.
97 bool IncludeFixIts = false;
98
99 /// Whether to generate snippets for function arguments on code-completion.
100 /// Needs snippets to be enabled as well.
101 bool EnableFunctionArgSnippets = true;
102
103 /// Whether to include index symbols that are not defined in the scopes
104 /// visible from the code completion point. This applies in contexts without
105 /// explicit scope qualifiers.
106 ///
107 /// Such completions can insert scope qualifiers.
108 bool AllScopes = false;
109
110 /// Whether to use the clang parser, or fallback to text-based completion
111 /// (using identifiers in the current file and symbol indexes).
112 enum CodeCompletionParse {
113 /// Block until we can run the parser (e.g. preamble is built).
114 /// Return an error if this fails.
115 AlwaysParse,
116 /// Run the parser if inputs (preamble) are ready.
117 /// Otherwise, use text-based completion.
118 ParseIfReady,
119 /// Always use text-based completion.
120 NeverParse,
121 } RunParser = ParseIfReady;
122
123 /// Callback invoked on all CompletionCandidate after they are scored and
124 /// before they are ranked (by -Score). Thus the results are yielded in
125 /// arbitrary order.
126 ///
127 /// This callbacks allows capturing various internal structures used by clangd
128 /// during code completion. Eg: Symbol quality and relevance signals.
129 std::function<void(const CodeCompletion &, const SymbolQualitySignals &,
130 const SymbolRelevanceSignals &, float Score)>
131 RecordCCResult;
132
133 /// Model to use for ranking code completion candidates.
134 enum CodeCompletionRankingModel {
135 Heuristics,
136 DecisionForest,
137 };
138 static const CodeCompletionRankingModel DefaultRankingModel;
139 CodeCompletionRankingModel RankingModel = DefaultRankingModel;
140
141 /// Callback used to score a CompletionCandidate if DecisionForest ranking
142 /// model is enabled.
143 /// This allows us to inject experimental models and compare them with
144 /// baseline model using A/B testing.
145 std::function<DecisionForestScores(
146 const SymbolQualitySignals &, const SymbolRelevanceSignals &, float Base)>
147 DecisionForestScorer = &evaluateDecisionForest;
148 /// Weight for combining NameMatch and Prediction of DecisionForest.
149 /// CompletionScore is NameMatch * pow(Base, Prediction).
150 /// The optimal value of Base largely depends on the semantics of the model
151 /// and prediction score (e.g. algorithm used during training, number of
152 /// trees, etc.). Usually if the range of Prediction is [-20, 20] then a Base
153 /// in [1.2, 1.7] works fine.
154 /// Semantics: E.g. For Base = 1.3, if the Prediction score reduces by 2.6
155 /// points then completion score reduces by 50% or 1.3^(-2.6).
156 float DecisionForestBase = 1.3f;
157};
158
159// Semi-structured representation of a code-complete suggestion for our C++ API.
160// We don't use the LSP structures here (unlike most features) as we want
161// to expose more data to allow for more precise testing and evaluation.
162struct CodeCompletion {
163 // The unqualified name of the symbol or other completion item.
164 std::string Name;
165 // The name of the symbol for filtering and sorting purposes. Typically the
166 // same as `Name`, but may be different e.g. for ObjC methods, `Name` is the
167 // first selector fragment but the `FilterText` is the entire selector.
168 std::string FilterText;
169 // The scope qualifier for the symbol name. e.g. "ns1::ns2::"
170 // Empty for non-symbol completions. Not inserted, but may be displayed.
171 std::string Scope;
172 // Text that must be inserted before the name, and displayed (e.g. base::).
173 std::string RequiredQualifier;
174 // Details to be displayed following the name. Not inserted.
175 std::string Signature;
176 // Text to be inserted following the name, in snippet format.
177 std::string SnippetSuffix;
178 // Type to be displayed for this completion.
179 std::string ReturnType;
180 // The parsed documentation comment.
181 std::optional<markup::Document> Documentation;
182 CompletionItemKind Kind = CompletionItemKind::Missing;
183 // This completion item may represent several symbols that can be inserted in
184 // the same way, such as function overloads. In this case BundleSize > 1, and
185 // the following fields are summaries:
186 // - Signature is e.g. "(...)" for functions.
187 // - SnippetSuffix is similarly e.g. "(${0})".
188 // - ReturnType may be empty
189 // - Documentation may be from one symbol, or a combination of several
190 // Other fields should apply equally to all bundled completions.
191 unsigned BundleSize = 1;
192 SymbolOrigin Origin = SymbolOrigin::Unknown;
193
194 struct IncludeCandidate {
195 // The header through which this symbol could be included.
196 // Quoted string as expected by an #include directive, e.g. "<memory>".
197 // Empty for non-symbol completions, or when not known.
198 std::string Header;
199 // Present if Header should be inserted to use this item.
200 std::optional<TextEdit> Insertion;
201 };
202 // All possible include headers ranked by preference. By default, the first
203 // include is used.
204 // If we've bundled together overloads that have different sets of includes,
205 // thse includes may not be accurate for all of them.
206 llvm::SmallVector<IncludeCandidate, 1> Includes;
207
208 /// Holds information about small corrections that needs to be done. Like
209 /// converting '->' to '.' on member access.
210 std::vector<TextEdit> FixIts;
211
212 /// Holds the range of the token we are going to replace with this completion.
213 Range CompletionTokenRange;
214
215 // Scores are used to rank completion items.
216 struct Scores {
217 // The score that items are ranked by.
218 float Total = 0.f;
219
220 // The finalScore with the fuzzy name match score excluded.
221 // When filtering client-side, editors should calculate the new fuzzy score,
222 // whose scale is 0-1 (with 1 = prefix match, special case 2 = exact match),
223 // and recompute finalScore = fuzzyScore * symbolScore.
224 float ExcludingName = 0.f;
225
226 // Component scores that contributed to the final score:
227
228 // Quality describes how important we think this candidate is,
229 // independent of the query.
230 // e.g. symbols with lots of incoming references have higher quality.
231 float Quality = 0.f;
232 // Relevance describes how well this candidate matched the query.
233 // e.g. symbols from nearby files have higher relevance.
234 float Relevance = 0.f;
235 };
236 Scores Score;
237
238 /// Indicates if this item is deprecated.
239 bool Deprecated = false;
240
241 // Serialize this to an LSP completion item. This is a lossy operation.
242 CompletionItem render(const CodeCompleteOptions &) const;
243};
244raw_ostream &operator<<(raw_ostream &, const CodeCompletion &);
245struct CodeCompleteResult {
246 std::vector<CodeCompletion> Completions;
247 bool HasMore = false;
248 CodeCompletionContext::Kind Context = CodeCompletionContext::CCC_Other;
249 // The text that is being directly completed.
250 // Example: foo.pb^ -> foo.push_back()
251 // ~~
252 // Typically matches the textEdit.range of Completions, but not guaranteed to.
253 std::optional<Range> CompletionRange;
254 // Usually the source will be parsed with a real C++ parser.
255 // But heuristics may be used instead if e.g. the preamble is not ready.
256 bool RanParser = true;
257};
258raw_ostream &operator<<(raw_ostream &, const CodeCompleteResult &);
259
260/// A speculative and asynchronous fuzzy find index request (based on cached
261/// request) that can be sent before parsing sema. This would reduce completion
262/// latency if the speculation succeeds.
263struct SpeculativeFuzzyFind {
264 /// A cached request from past code completions.
265 /// Set by caller of `codeComplete()`.
266 std::optional<FuzzyFindRequest> CachedReq;
267 /// The actual request used by `codeComplete()`.
268 /// Set by `codeComplete()`. This can be used by callers to update cache.
269 std::optional<FuzzyFindRequest> NewReq;
270 /// The result is consumed by `codeComplete()` if speculation succeeded.
271 /// NOTE: the destructor will wait for the async call to finish.
272 std::future<std::pair<bool /*Incomplete*/, SymbolSlab>> Result;
273};
274
275/// Gets code completions at a specified \p Pos in \p FileName.
276///
277/// If \p Preamble is nullptr, this runs code completion without compiling the
278/// code.
279///
280/// If \p SpecFuzzyFind is set, a speculative and asynchronous fuzzy find index
281/// request (based on cached request) will be run before parsing sema. In case
282/// the speculative result is used by code completion (e.g. speculation failed),
283/// the speculative result is not consumed, and `SpecFuzzyFind` is only
284/// destroyed when the async request finishes.
285CodeCompleteResult codeComplete(PathRef FileName, Position Pos,
286 const PreambleData *Preamble,
287 const ParseInputs &ParseInput,
288 CodeCompleteOptions Opts,
289 SpeculativeFuzzyFind *SpecFuzzyFind = nullptr);
290
291/// Get signature help at a specified \p Pos in \p FileName.
292SignatureHelp signatureHelp(PathRef FileName, Position Pos,
293 const PreambleData &Preamble,
294 const ParseInputs &ParseInput,
295 MarkupKind DocumentationFormat);
296
297// For index-based completion, we only consider:
298// * symbols in namespaces or translation unit scopes (e.g. no class
299// members, no locals)
300// * enum constants (both scoped and unscoped)
301// * primary templates (no specializations)
302// For the other cases, we let Clang do the completion because it does not
303// need any non-local information and it will be much better at following
304// lookup rules. Other symbols still appear in the index for other purposes,
305// like workspace/symbols or textDocument/definition, but are not used for code
306// completion.
307bool isIndexedForCodeCompletion(const NamedDecl &ND, ASTContext &ASTCtx);
308
309// Text immediately before the completion point that should be completed.
310// This is heuristically derived from the source code, and is used when:
311// - semantic analysis fails
312// - semantic analysis may be slow, and we speculatively query the index
313struct CompletionPrefix {
314 // The unqualified partial name.
315 // If there is none, begin() == end() == completion position.
316 llvm::StringRef Name;
317 // The spelled scope qualifier, such as Foo::.
318 // If there is none, begin() == end() == Name.begin().
319 llvm::StringRef Qualifier;
320};
321// Heuristically parses before Offset to determine what should be completed.
322CompletionPrefix guessCompletionPrefix(llvm::StringRef Content,
323 unsigned Offset);
324
325// Whether it makes sense to complete at the point based on typed characters.
326// For instance, we implicitly trigger at `a->^` but not at `a>^`.
327bool allowImplicitCompletion(llvm::StringRef Content, unsigned Offset);
328
329} // namespace clangd
330} // namespace clang
331
332#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_CODECOMPLETE_H
333

source code of clang-tools-extra/clangd/CodeComplete.h