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