2503 lines · cpp
1//===--- CodeComplete.cpp ----------------------------------------*- 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-exception6//7//===----------------------------------------------------------------------===//8//9// Code completion has several moving parts:10// - AST-based completions are provided using the completion hooks in Sema.11// - external completions are retrieved from the index (using hints from Sema)12// - the two sources overlap, and must be merged and overloads bundled13// - results must be scored and ranked (see Quality.h) before rendering14//15// Signature help works in a similar way as code completion, but it is simpler:16// it's purely AST-based, and there are few candidates.17//18//===----------------------------------------------------------------------===//19 20#include "CodeComplete.h"21#include "AST.h"22#include "CodeCompletionStrings.h"23#include "Compiler.h"24#include "Config.h"25#include "ExpectedTypes.h"26#include "Feature.h"27#include "FileDistance.h"28#include "FuzzyMatch.h"29#include "Headers.h"30#include "Hover.h"31#include "Preamble.h"32#include "Protocol.h"33#include "Quality.h"34#include "SourceCode.h"35#include "URI.h"36#include "index/Index.h"37#include "index/Symbol.h"38#include "index/SymbolOrigin.h"39#include "support/Logger.h"40#include "support/Markup.h"41#include "support/Threading.h"42#include "support/ThreadsafeFS.h"43#include "support/Trace.h"44#include "clang/AST/Decl.h"45#include "clang/AST/DeclBase.h"46#include "clang/AST/DeclTemplate.h"47#include "clang/Basic/CharInfo.h"48#include "clang/Basic/LangOptions.h"49#include "clang/Basic/SourceLocation.h"50#include "clang/Basic/TokenKinds.h"51#include "clang/Format/Format.h"52#include "clang/Frontend/CompilerInstance.h"53#include "clang/Frontend/FrontendActions.h"54#include "clang/Lex/ExternalPreprocessorSource.h"55#include "clang/Lex/Lexer.h"56#include "clang/Lex/Preprocessor.h"57#include "clang/Lex/PreprocessorOptions.h"58#include "clang/Sema/CodeCompleteConsumer.h"59#include "clang/Sema/DeclSpec.h"60#include "clang/Sema/Sema.h"61#include "llvm/ADT/ArrayRef.h"62#include "llvm/ADT/SmallVector.h"63#include "llvm/ADT/StringExtras.h"64#include "llvm/ADT/StringRef.h"65#include "llvm/Support/Casting.h"66#include "llvm/Support/Compiler.h"67#include "llvm/Support/Debug.h"68#include "llvm/Support/Error.h"69#include "llvm/Support/FormatVariadic.h"70#include "llvm/Support/ScopedPrinter.h"71#include <algorithm>72#include <iterator>73#include <limits>74#include <optional>75#include <utility>76 77// We log detailed candidate here if you run with -debug-only=codecomplete.78#define DEBUG_TYPE "CodeComplete"79 80namespace clang {81namespace clangd {82 83#if CLANGD_DECISION_FOREST84const CodeCompleteOptions::CodeCompletionRankingModel85 CodeCompleteOptions::DefaultRankingModel =86 CodeCompleteOptions::DecisionForest;87#else88const CodeCompleteOptions::CodeCompletionRankingModel89 CodeCompleteOptions::DefaultRankingModel = CodeCompleteOptions::Heuristics;90#endif91 92namespace {93 94// Note: changes to this function should also be reflected in the95// CodeCompletionResult overload where appropriate.96CompletionItemKind97toCompletionItemKind(index::SymbolKind Kind,98 const llvm::StringRef *Signature = nullptr) {99 using SK = index::SymbolKind;100 switch (Kind) {101 // FIXME: for backwards compatibility, the include directive kind is treated102 // the same as Unknown103 case SK::IncludeDirective:104 case SK::Unknown:105 return CompletionItemKind::Missing;106 case SK::Module:107 case SK::Namespace:108 case SK::NamespaceAlias:109 return CompletionItemKind::Module;110 case SK::Macro:111 // Use macro signature (if provided) to tell apart function-like and112 // object-like macros.113 return Signature && Signature->contains('(') ? CompletionItemKind::Function114 : CompletionItemKind::Constant;115 case SK::Enum:116 return CompletionItemKind::Enum;117 case SK::Struct:118 return CompletionItemKind::Struct;119 case SK::Class:120 case SK::Extension:121 case SK::Union:122 return CompletionItemKind::Class;123 case SK::Protocol:124 // Use interface instead of class for differentiation of classes and125 // protocols with the same name (e.g. @interface NSObject vs. @protocol126 // NSObject).127 return CompletionItemKind::Interface;128 case SK::TypeAlias:129 // We use the same kind as the VSCode C++ extension.130 // FIXME: pick a better option when we have one.131 return CompletionItemKind::Interface;132 case SK::Using:133 return CompletionItemKind::Reference;134 case SK::Function:135 case SK::ConversionFunction:136 return CompletionItemKind::Function;137 case SK::Variable:138 case SK::Parameter:139 case SK::NonTypeTemplateParm:140 return CompletionItemKind::Variable;141 case SK::Field:142 return CompletionItemKind::Field;143 case SK::EnumConstant:144 return CompletionItemKind::EnumMember;145 case SK::InstanceMethod:146 case SK::ClassMethod:147 case SK::StaticMethod:148 case SK::Destructor:149 return CompletionItemKind::Method;150 case SK::InstanceProperty:151 case SK::ClassProperty:152 case SK::StaticProperty:153 return CompletionItemKind::Property;154 case SK::Constructor:155 return CompletionItemKind::Constructor;156 case SK::TemplateTypeParm:157 case SK::TemplateTemplateParm:158 return CompletionItemKind::TypeParameter;159 case SK::Concept:160 return CompletionItemKind::Interface;161 }162 llvm_unreachable("Unhandled clang::index::SymbolKind.");163}164 165// Note: changes to this function should also be reflected in the166// index::SymbolKind overload where appropriate.167CompletionItemKind toCompletionItemKind(const CodeCompletionResult &Res,168 CodeCompletionContext::Kind CtxKind) {169 if (Res.Declaration)170 return toCompletionItemKind(index::getSymbolInfo(Res.Declaration).Kind);171 if (CtxKind == CodeCompletionContext::CCC_IncludedFile)172 return CompletionItemKind::File;173 switch (Res.Kind) {174 case CodeCompletionResult::RK_Declaration:175 llvm_unreachable("RK_Declaration without Decl");176 case CodeCompletionResult::RK_Keyword:177 return CompletionItemKind::Keyword;178 case CodeCompletionResult::RK_Macro:179 // There is no 'Macro' kind in LSP.180 // Avoid using 'Text' to avoid confusion with client-side word-based181 // completion proposals.182 return Res.MacroDefInfo && Res.MacroDefInfo->isFunctionLike()183 ? CompletionItemKind::Function184 : CompletionItemKind::Constant;185 case CodeCompletionResult::RK_Pattern:186 return CompletionItemKind::Snippet;187 }188 llvm_unreachable("Unhandled CodeCompletionResult::ResultKind.");189}190 191// FIXME: find a home for this (that can depend on both markup and Protocol).192MarkupContent renderDoc(const markup::Document &Doc, MarkupKind Kind) {193 MarkupContent Result;194 Result.kind = Kind;195 switch (Kind) {196 case MarkupKind::PlainText:197 Result.value.append(Doc.asPlainText());198 break;199 case MarkupKind::Markdown:200 if (Config::current().Documentation.CommentFormat ==201 Config::CommentFormatPolicy::PlainText)202 Result.value.append(Doc.asEscapedMarkdown());203 else204 Result.value.append(Doc.asMarkdown());205 break;206 }207 return Result;208}209 210Symbol::IncludeDirective insertionDirective(const CodeCompleteOptions &Opts) {211 if (!Opts.ImportInsertions || !Opts.MainFileSignals)212 return Symbol::IncludeDirective::Include;213 return Opts.MainFileSignals->InsertionDirective;214}215 216// Identifier code completion result.217struct RawIdentifier {218 llvm::StringRef Name;219 unsigned References; // # of usages in file.220};221 222/// A code completion result, in clang-native form.223/// It may be promoted to a CompletionItem if it's among the top-ranked results.224struct CompletionCandidate {225 llvm::StringRef Name; // Used for filtering and sorting.226 // We may have a result from Sema, from the index, or both.227 const CodeCompletionResult *SemaResult = nullptr;228 const Symbol *IndexResult = nullptr;229 const RawIdentifier *IdentifierResult = nullptr;230 llvm::SmallVector<SymbolInclude, 1> RankedIncludeHeaders;231 232 // Returns a token identifying the overload set this is part of.233 // 0 indicates it's not part of any overload set.234 size_t overloadSet(const CodeCompleteOptions &Opts, llvm::StringRef FileName,235 IncludeInserter *Inserter,236 CodeCompletionContext::Kind CCContextKind) const {237 if (!Opts.BundleOverloads.value_or(false))238 return 0;239 240 // Depending on the index implementation, we can see different header241 // strings (literal or URI) mapping to the same file. We still want to242 // bundle those, so we must resolve the header to be included here.243 std::string HeaderForHash;244 if (Inserter) {245 if (auto Header = headerToInsertIfAllowed(Opts, CCContextKind)) {246 if (auto HeaderFile = toHeaderFile(*Header, FileName)) {247 if (auto Spelled =248 Inserter->calculateIncludePath(*HeaderFile, FileName))249 HeaderForHash = *Spelled;250 } else {251 vlog("Code completion header path manipulation failed {0}",252 HeaderFile.takeError());253 }254 }255 }256 257 llvm::SmallString<256> Scratch;258 if (IndexResult) {259 switch (IndexResult->SymInfo.Kind) {260 case index::SymbolKind::ClassMethod:261 case index::SymbolKind::InstanceMethod:262 case index::SymbolKind::StaticMethod:263#ifndef NDEBUG264 llvm_unreachable("Don't expect members from index in code completion");265#else266 [[fallthrough]];267#endif268 case index::SymbolKind::Function:269 // We can't group overloads together that need different #includes.270 // This could break #include insertion.271 return llvm::hash_combine(272 (IndexResult->Scope + IndexResult->Name).toStringRef(Scratch),273 HeaderForHash);274 default:275 return 0;276 }277 }278 if (SemaResult) {279 // We need to make sure we're consistent with the IndexResult case!280 const NamedDecl *D = SemaResult->Declaration;281 if (!D || !D->isFunctionOrFunctionTemplate())282 return 0;283 {284 llvm::raw_svector_ostream OS(Scratch);285 D->printQualifiedName(OS);286 }287 return llvm::hash_combine(Scratch, HeaderForHash);288 }289 assert(IdentifierResult);290 return 0;291 }292 293 bool contextAllowsHeaderInsertion(CodeCompletionContext::Kind Kind) const {294 // Explicitly disable insertions for forward declarations since they don't295 // reference the declaration.296 if (Kind == CodeCompletionContext::CCC_ObjCClassForwardDecl)297 return false;298 return true;299 }300 301 // The best header to include if include insertion is allowed.302 std::optional<llvm::StringRef>303 headerToInsertIfAllowed(const CodeCompleteOptions &Opts,304 CodeCompletionContext::Kind ContextKind) const {305 if (Opts.InsertIncludes == Config::HeaderInsertionPolicy::NeverInsert ||306 RankedIncludeHeaders.empty() ||307 !contextAllowsHeaderInsertion(ContextKind))308 return std::nullopt;309 if (SemaResult && SemaResult->Declaration) {310 // Avoid inserting new #include if the declaration is found in the current311 // file e.g. the symbol is forward declared.312 auto &SM = SemaResult->Declaration->getASTContext().getSourceManager();313 for (const Decl *RD : SemaResult->Declaration->redecls())314 if (SM.isInMainFile(SM.getExpansionLoc(RD->getBeginLoc())))315 return std::nullopt;316 }317 Symbol::IncludeDirective Directive = insertionDirective(Opts);318 for (const auto &Inc : RankedIncludeHeaders)319 if ((Inc.Directive & Directive) != 0)320 return Inc.Header;321 return std::nullopt;322 }323 324 using Bundle = llvm::SmallVector<CompletionCandidate, 4>;325};326using ScoredBundle =327 std::pair<CompletionCandidate::Bundle, CodeCompletion::Scores>;328struct ScoredBundleGreater {329 bool operator()(const ScoredBundle &L, const ScoredBundle &R) {330 if (L.second.Total != R.second.Total)331 return L.second.Total > R.second.Total;332 return L.first.front().Name <333 R.first.front().Name; // Earlier name is better.334 }335};336 337// Remove the first template argument from Signature.338// If Signature only contains a single argument an empty string is returned.339std::string removeFirstTemplateArg(llvm::StringRef Signature) {340 auto Rest = Signature.split(",").second;341 if (Rest.empty())342 return "";343 return ("<" + Rest.ltrim()).str();344}345 346// Assembles a code completion out of a bundle of >=1 completion candidates.347// Many of the expensive strings are only computed at this point, once we know348// the candidate bundle is going to be returned.349//350// Many fields are the same for all candidates in a bundle (e.g. name), and are351// computed from the first candidate, in the constructor.352// Others vary per candidate, so add() must be called for remaining candidates.353struct CodeCompletionBuilder {354 CodeCompletionBuilder(ASTContext *ASTCtx, const CompletionCandidate &C,355 CodeCompletionString *SemaCCS,356 llvm::ArrayRef<std::string> AccessibleScopes,357 const IncludeInserter &Includes,358 llvm::StringRef FileName,359 CodeCompletionContext::Kind ContextKind,360 const CodeCompleteOptions &Opts,361 bool IsUsingDeclaration, tok::TokenKind NextTokenKind)362 : ASTCtx(ASTCtx), ArgumentLists(Opts.ArgumentLists),363 IsUsingDeclaration(IsUsingDeclaration), NextTokenKind(NextTokenKind) {364 Completion.Deprecated = true; // cleared by any non-deprecated overload.365 add(C, SemaCCS, ContextKind);366 if (C.SemaResult) {367 assert(ASTCtx);368 Completion.Origin |= SymbolOrigin::AST;369 Completion.Name = std::string(llvm::StringRef(SemaCCS->getTypedText()));370 Completion.FilterText = SemaCCS->getAllTypedText();371 if (Completion.Scope.empty()) {372 if ((C.SemaResult->Kind == CodeCompletionResult::RK_Declaration) ||373 (C.SemaResult->Kind == CodeCompletionResult::RK_Pattern))374 if (const auto *D = C.SemaResult->getDeclaration())375 if (const auto *ND = dyn_cast<NamedDecl>(D))376 Completion.Scope = std::string(377 splitQualifiedName(printQualifiedName(*ND)).first);378 }379 Completion.Kind = toCompletionItemKind(*C.SemaResult, ContextKind);380 // Sema could provide more info on whether the completion was a file or381 // folder.382 if (Completion.Kind == CompletionItemKind::File &&383 Completion.Name.back() == '/')384 Completion.Kind = CompletionItemKind::Folder;385 for (const auto &FixIt : C.SemaResult->FixIts) {386 Completion.FixIts.push_back(toTextEdit(387 FixIt, ASTCtx->getSourceManager(), ASTCtx->getLangOpts()));388 }389 llvm::sort(Completion.FixIts, [](const TextEdit &X, const TextEdit &Y) {390 return std::tie(X.range.start.line, X.range.start.character) <391 std::tie(Y.range.start.line, Y.range.start.character);392 });393 }394 if (C.IndexResult) {395 Completion.Origin |= C.IndexResult->Origin;396 if (Completion.Scope.empty())397 Completion.Scope = std::string(C.IndexResult->Scope);398 if (Completion.Kind == CompletionItemKind::Missing)399 Completion.Kind = toCompletionItemKind(C.IndexResult->SymInfo.Kind,400 &C.IndexResult->Signature);401 if (Completion.Name.empty())402 Completion.Name = std::string(C.IndexResult->Name);403 if (Completion.FilterText.empty())404 Completion.FilterText = Completion.Name;405 // If the completion was visible to Sema, no qualifier is needed. This406 // avoids unneeded qualifiers in cases like with `using ns::X`.407 if (Completion.RequiredQualifier.empty() && !C.SemaResult) {408 llvm::StringRef ShortestQualifier = C.IndexResult->Scope;409 for (llvm::StringRef Scope : AccessibleScopes) {410 llvm::StringRef Qualifier = C.IndexResult->Scope;411 if (Qualifier.consume_front(Scope) &&412 Qualifier.size() < ShortestQualifier.size())413 ShortestQualifier = Qualifier;414 }415 Completion.RequiredQualifier = std::string(ShortestQualifier);416 }417 }418 if (C.IdentifierResult) {419 Completion.Origin |= SymbolOrigin::Identifier;420 Completion.Kind = CompletionItemKind::Text;421 Completion.Name = std::string(C.IdentifierResult->Name);422 Completion.FilterText = Completion.Name;423 }424 425 // Turn absolute path into a literal string that can be #included.426 auto Inserted = [&](llvm::StringRef Header)427 -> llvm::Expected<std::pair<std::string, bool>> {428 auto ResolvedDeclaring =429 URI::resolve(C.IndexResult->CanonicalDeclaration.FileURI, FileName);430 if (!ResolvedDeclaring)431 return ResolvedDeclaring.takeError();432 auto ResolvedInserted = toHeaderFile(Header, FileName);433 if (!ResolvedInserted)434 return ResolvedInserted.takeError();435 auto Spelled = Includes.calculateIncludePath(*ResolvedInserted, FileName);436 if (!Spelled)437 return error("Header not on include path");438 return std::make_pair(439 std::move(*Spelled),440 Includes.shouldInsertInclude(*ResolvedDeclaring, *ResolvedInserted));441 };442 bool ShouldInsert =443 C.headerToInsertIfAllowed(Opts, ContextKind).has_value();444 Symbol::IncludeDirective Directive = insertionDirective(Opts);445 // Calculate include paths and edits for all possible headers.446 for (const auto &Inc : C.RankedIncludeHeaders) {447 if ((Inc.Directive & Directive) == 0)448 continue;449 450 if (auto ToInclude = Inserted(Inc.Header)) {451 CodeCompletion::IncludeCandidate Include;452 Include.Header = ToInclude->first;453 if (ToInclude->second && ShouldInsert)454 Include.Insertion = Includes.insert(455 ToInclude->first, Directive == Symbol::Import456 ? tooling::IncludeDirective::Import457 : tooling::IncludeDirective::Include);458 Completion.Includes.push_back(std::move(Include));459 } else460 log("Failed to generate include insertion edits for adding header "461 "(FileURI='{0}', IncludeHeader='{1}') into {2}: {3}",462 C.IndexResult->CanonicalDeclaration.FileURI, Inc.Header, FileName,463 ToInclude.takeError());464 }465 // Prefer includes that do not need edits (i.e. already exist).466 std::stable_partition(Completion.Includes.begin(),467 Completion.Includes.end(),468 [](const CodeCompletion::IncludeCandidate &I) {469 return !I.Insertion.has_value();470 });471 }472 473 void add(const CompletionCandidate &C, CodeCompletionString *SemaCCS,474 CodeCompletionContext::Kind ContextKind) {475 assert(bool(C.SemaResult) == bool(SemaCCS));476 Bundled.emplace_back();477 BundledEntry &S = Bundled.back();478 bool IsConcept = false;479 if (C.SemaResult) {480 getSignature(*SemaCCS, &S.Signature, &S.SnippetSuffix, C.SemaResult->Kind,481 C.SemaResult->CursorKind,482 /*IncludeFunctionArguments=*/C.SemaResult->FunctionCanBeCall,483 /*RequiredQualifiers=*/&Completion.RequiredQualifier);484 S.ReturnType = getReturnType(*SemaCCS);485 if (C.SemaResult->Kind == CodeCompletionResult::RK_Declaration)486 if (const auto *D = C.SemaResult->getDeclaration())487 if (isa<ConceptDecl>(D))488 IsConcept = true;489 } else if (C.IndexResult) {490 S.Signature = std::string(C.IndexResult->Signature);491 S.SnippetSuffix = std::string(C.IndexResult->CompletionSnippetSuffix);492 S.ReturnType = std::string(C.IndexResult->ReturnType);493 if (C.IndexResult->SymInfo.Kind == index::SymbolKind::Concept)494 IsConcept = true;495 }496 497 /// When a concept is used as a type-constraint (e.g. `Iterator auto x`),498 /// and in some other contexts, its first type argument is not written.499 /// Drop the parameter from the signature.500 if (IsConcept && ContextKind == CodeCompletionContext::CCC_TopLevel) {501 S.Signature = removeFirstTemplateArg(S.Signature);502 // Dropping the first placeholder from the suffix will leave a $2503 // with no $1.504 S.SnippetSuffix = removeFirstTemplateArg(S.SnippetSuffix);505 }506 507 if (!Completion.Documentation) {508 auto SetDoc = [&](llvm::StringRef Doc) {509 if (!Doc.empty()) {510 Completion.Documentation.emplace();511 parseDocumentation(Doc, *Completion.Documentation);512 }513 };514 if (C.IndexResult) {515 SetDoc(C.IndexResult->Documentation);516 } else if (C.SemaResult) {517 const auto DocComment = getDocComment(*ASTCtx, *C.SemaResult,518 /*CommentsFromHeaders=*/false);519 SetDoc(formatDocumentation(*SemaCCS, DocComment));520 }521 }522 if (Completion.Deprecated) {523 if (C.SemaResult)524 Completion.Deprecated &=525 C.SemaResult->Availability == CXAvailability_Deprecated;526 if (C.IndexResult)527 Completion.Deprecated &=528 bool(C.IndexResult->Flags & Symbol::Deprecated);529 }530 }531 532 CodeCompletion build() {533 Completion.ReturnType = summarizeReturnType();534 Completion.Signature = summarizeSignature();535 Completion.SnippetSuffix = summarizeSnippet();536 Completion.BundleSize = Bundled.size();537 return std::move(Completion);538 }539 540private:541 struct BundledEntry {542 std::string SnippetSuffix;543 std::string Signature;544 std::string ReturnType;545 };546 547 // If all BundledEntries have the same value for a property, return it.548 template <std::string BundledEntry::*Member>549 const std::string *onlyValue() const {550 auto B = Bundled.begin(), E = Bundled.end();551 for (auto *I = B + 1; I != E; ++I)552 if (I->*Member != B->*Member)553 return nullptr;554 return &(B->*Member);555 }556 557 template <bool BundledEntry::*Member> const bool *onlyValue() const {558 auto B = Bundled.begin(), E = Bundled.end();559 for (auto *I = B + 1; I != E; ++I)560 if (I->*Member != B->*Member)561 return nullptr;562 return &(B->*Member);563 }564 565 std::string summarizeReturnType() const {566 if (auto *RT = onlyValue<&BundledEntry::ReturnType>())567 return *RT;568 return "";569 }570 571 std::string summarizeSnippet() const {572 /// localize ArgumentLists tests for better readability573 const bool None = ArgumentLists == Config::ArgumentListsPolicy::None;574 const bool Open =575 ArgumentLists == Config::ArgumentListsPolicy::OpenDelimiter;576 const bool Delim = ArgumentLists == Config::ArgumentListsPolicy::Delimiters;577 const bool Full =578 ArgumentLists == Config::ArgumentListsPolicy::FullPlaceholders ||579 (!None && !Open && !Delim); // <-- failsafe: Full is default580 581 if (IsUsingDeclaration)582 return "";583 auto *Snippet = onlyValue<&BundledEntry::SnippetSuffix>();584 if (!Snippet)585 // All bundles are function calls.586 // FIXME(ibiryukov): sometimes add template arguments to a snippet, e.g.587 // we need to complete 'forward<$1>($0)'.588 return None ? "" : (Open ? "(" : "($0)");589 590 if (Snippet->empty())591 return "";592 593 bool MayHaveArgList = Completion.Kind == CompletionItemKind::Function ||594 Completion.Kind == CompletionItemKind::Method ||595 Completion.Kind == CompletionItemKind::Constructor ||596 Completion.Kind == CompletionItemKind::Text /*Macro*/;597 // If likely arg list already exists, don't add new parens & placeholders.598 // Snippet: function(int x, int y)599 // func^(1,2) -> function(1, 2)600 // NOT function(int x, int y)(1, 2)601 if (MayHaveArgList) {602 // Check for a template argument list in the code.603 // Snippet: function<class T>(int x)604 // fu^<int>(1) -> function<int>(1)605 if (NextTokenKind == tok::less && Snippet->front() == '<')606 return "";607 // Potentially followed by regular argument list.608 if (NextTokenKind == tok::l_paren) {609 // Snippet: function<class T>(int x)610 // fu^(1,2) -> function<class T>(1, 2)611 if (Snippet->front() == '<') {612 // Find matching '>', handling nested brackets.613 int Balance = 0;614 size_t I = 0;615 do {616 if (Snippet->at(I) == '>')617 --Balance;618 else if (Snippet->at(I) == '<')619 ++Balance;620 ++I;621 } while (Balance > 0);622 return Snippet->substr(0, I);623 }624 return "";625 }626 }627 if (Full)628 return *Snippet;629 630 // Replace argument snippets with a simplified pattern.631 if (MayHaveArgList) {632 // Functions snippets can be of 2 types:633 // - containing only function arguments, e.g.634 // foo(${1:int p1}, ${2:int p2});635 // We transform this pattern to '($0)' or '()'.636 // - template arguments and function arguments, e.g.637 // foo<${1:class}>(${2:int p1}).638 // We transform this pattern to '<$1>()$0' or '<$0>()'.639 640 bool EmptyArgs = llvm::StringRef(*Snippet).ends_with("()");641 if (Snippet->front() == '<')642 return None ? "" : (Open ? "<" : (EmptyArgs ? "<$1>()$0" : "<$1>($0)"));643 if (Snippet->front() == '(')644 return None ? "" : (Open ? "(" : (EmptyArgs ? "()" : "($0)"));645 return *Snippet; // Not an arg snippet?646 }647 // 'CompletionItemKind::Interface' matches template type aliases.648 if (Completion.Kind == CompletionItemKind::Interface ||649 Completion.Kind == CompletionItemKind::Class ||650 Completion.Kind == CompletionItemKind::Variable) {651 if (Snippet->front() != '<')652 return *Snippet; // Not an arg snippet?653 654 // Classes and template using aliases can only have template arguments,655 // e.g. Foo<${1:class}>.656 if (llvm::StringRef(*Snippet).ends_with("<>"))657 return "<>"; // can happen with defaulted template arguments.658 return None ? "" : (Open ? "<" : "<$0>");659 }660 return *Snippet;661 }662 663 std::string summarizeSignature() const {664 if (auto *Signature = onlyValue<&BundledEntry::Signature>())665 return *Signature;666 // All bundles are function calls.667 return "(…)";668 }669 670 // ASTCtx can be nullptr if not run with sema.671 ASTContext *ASTCtx;672 CodeCompletion Completion;673 llvm::SmallVector<BundledEntry, 1> Bundled;674 /// the way argument lists are handled.675 Config::ArgumentListsPolicy ArgumentLists;676 // No snippets will be generated for using declarations and when the function677 // arguments are already present.678 bool IsUsingDeclaration;679 tok::TokenKind NextTokenKind;680};681 682// Determine the symbol ID for a Sema code completion result, if possible.683SymbolID getSymbolID(const CodeCompletionResult &R, const SourceManager &SM) {684 switch (R.Kind) {685 case CodeCompletionResult::RK_Declaration:686 case CodeCompletionResult::RK_Pattern: {687 // Computing USR caches linkage, which may change after code completion.688 if (hasUnstableLinkage(R.Declaration))689 return {};690 return clang::clangd::getSymbolID(R.Declaration);691 }692 case CodeCompletionResult::RK_Macro:693 return clang::clangd::getSymbolID(R.Macro->getName(), R.MacroDefInfo, SM);694 case CodeCompletionResult::RK_Keyword:695 return {};696 }697 llvm_unreachable("unknown CodeCompletionResult kind");698}699 700// Scopes of the partial identifier we're trying to complete.701// It is used when we query the index for more completion results.702struct SpecifiedScope {703 // The scopes we should look in, determined by Sema.704 //705 // If the qualifier was fully resolved, we look for completions in these706 // scopes; if there is an unresolved part of the qualifier, it should be707 // resolved within these scopes.708 //709 // Examples of qualified completion:710 //711 // "::vec" => {""}712 // "using namespace std; ::vec^" => {"", "std::"}713 // "namespace ns {using namespace std;} ns::^" => {"ns::", "std::"}714 // "std::vec^" => {""} // "std" unresolved715 //716 // Examples of unqualified completion:717 //718 // "vec^" => {""}719 // "using namespace std; vec^" => {"", "std::"}720 // "namespace ns {inline namespace ni { struct Foo {}}}721 // using namespace ns::ni; Fo^ " => {"", "ns::ni::"}722 // "using namespace std; namespace ns { vec^ }" => {"ns::", "std::", ""}723 //724 // "" for global namespace, "ns::" for normal namespace.725 std::vector<std::string> AccessibleScopes;726 // This is an overestimate of AccessibleScopes, e.g. it ignores inline727 // namespaces, to fetch more relevant symbols from index.728 std::vector<std::string> QueryScopes;729 // The full scope qualifier as typed by the user (without the leading "::").730 // Set if the qualifier is not fully resolved by Sema.731 std::optional<std::string> UnresolvedQualifier;732 733 std::optional<std::string> EnclosingNamespace;734 735 bool AllowAllScopes = false;736 737 // Scopes that are accessible from current context. Used for dropping738 // unnecessary namespecifiers.739 std::vector<std::string> scopesForQualification() {740 std::set<std::string> Results;741 for (llvm::StringRef AS : AccessibleScopes)742 Results.insert(743 (AS + (UnresolvedQualifier ? *UnresolvedQualifier : "")).str());744 return {Results.begin(), Results.end()};745 }746 747 // Construct scopes being queried in indexes. The results are deduplicated.748 // This method formats the scopes to match the index request representation.749 std::vector<std::string> scopesForIndexQuery() {750 // The enclosing namespace must be first, it gets a quality boost.751 std::vector<std::string> EnclosingAtFront;752 if (EnclosingNamespace.has_value())753 EnclosingAtFront.push_back(*EnclosingNamespace);754 std::set<std::string> Deduplicated;755 for (llvm::StringRef S : QueryScopes)756 if (S != EnclosingNamespace)757 Deduplicated.insert((S + UnresolvedQualifier.value_or("")).str());758 759 EnclosingAtFront.reserve(EnclosingAtFront.size() + Deduplicated.size());760 llvm::copy(Deduplicated, std::back_inserter(EnclosingAtFront));761 762 return EnclosingAtFront;763 }764};765 766// Get all scopes that will be queried in indexes and whether symbols from767// any scope is allowed. The first scope in the list is the preferred scope768// (e.g. enclosing namespace).769SpecifiedScope getQueryScopes(CodeCompletionContext &CCContext,770 const Sema &CCSema,771 const CompletionPrefix &HeuristicPrefix,772 const CodeCompleteOptions &Opts) {773 SpecifiedScope Scopes;774 for (auto *Context : CCContext.getVisitedContexts()) {775 if (isa<TranslationUnitDecl>(Context)) {776 Scopes.QueryScopes.push_back("");777 Scopes.AccessibleScopes.push_back("");778 } else if (const auto *ND = dyn_cast<NamespaceDecl>(Context)) {779 Scopes.QueryScopes.push_back(printNamespaceScope(*Context));780 Scopes.AccessibleScopes.push_back(printQualifiedName(*ND) + "::");781 }782 }783 784 const CXXScopeSpec *SemaSpecifier =785 CCContext.getCXXScopeSpecifier().value_or(nullptr);786 // Case 1: unqualified completion.787 if (!SemaSpecifier) {788 // Case 2 (exception): sema saw no qualifier, but there appears to be one!789 // This can happen e.g. in incomplete macro expansions. Use heuristics.790 if (!HeuristicPrefix.Qualifier.empty()) {791 vlog("Sema said no scope specifier, but we saw {0} in the source code",792 HeuristicPrefix.Qualifier);793 StringRef SpelledSpecifier = HeuristicPrefix.Qualifier;794 if (SpelledSpecifier.consume_front("::")) {795 Scopes.AccessibleScopes = {""};796 Scopes.QueryScopes = {""};797 }798 Scopes.UnresolvedQualifier = std::string(SpelledSpecifier);799 return Scopes;800 }801 /// FIXME: When the enclosing namespace contains an inline namespace,802 /// it's dropped here. This leads to a behavior similar to803 /// https://github.com/clangd/clangd/issues/1451804 Scopes.EnclosingNamespace = printNamespaceScope(*CCSema.CurContext);805 // Allow AllScopes completion as there is no explicit scope qualifier.806 Scopes.AllowAllScopes = Opts.AllScopes;807 return Scopes;808 }809 // Case 3: sema saw and resolved a scope qualifier.810 if (SemaSpecifier && SemaSpecifier->isValid())811 return Scopes;812 813 // Case 4: There was a qualifier, and Sema didn't resolve it.814 Scopes.QueryScopes.push_back(""); // Make sure global scope is included.815 llvm::StringRef SpelledSpecifier = Lexer::getSourceText(816 CharSourceRange::getCharRange(SemaSpecifier->getRange()),817 CCSema.SourceMgr, clang::LangOptions());818 if (SpelledSpecifier.consume_front("::"))819 Scopes.QueryScopes = {""};820 Scopes.UnresolvedQualifier = std::string(SpelledSpecifier);821 // Sema excludes the trailing "::".822 if (!Scopes.UnresolvedQualifier->empty())823 *Scopes.UnresolvedQualifier += "::";824 825 Scopes.AccessibleScopes = Scopes.QueryScopes;826 827 return Scopes;828}829 830// Should we perform index-based completion in a context of the specified kind?831// FIXME: consider allowing completion, but restricting the result types.832bool contextAllowsIndex(enum CodeCompletionContext::Kind K) {833 switch (K) {834 case CodeCompletionContext::CCC_TopLevel:835 case CodeCompletionContext::CCC_ObjCInterface:836 case CodeCompletionContext::CCC_ObjCImplementation:837 case CodeCompletionContext::CCC_ObjCIvarList:838 case CodeCompletionContext::CCC_ClassStructUnion:839 case CodeCompletionContext::CCC_Statement:840 case CodeCompletionContext::CCC_Expression:841 case CodeCompletionContext::CCC_ObjCMessageReceiver:842 case CodeCompletionContext::CCC_EnumTag:843 case CodeCompletionContext::CCC_UnionTag:844 case CodeCompletionContext::CCC_ClassOrStructTag:845 case CodeCompletionContext::CCC_ObjCProtocolName:846 case CodeCompletionContext::CCC_Namespace:847 case CodeCompletionContext::CCC_Type:848 case CodeCompletionContext::CCC_ParenthesizedExpression:849 case CodeCompletionContext::CCC_ObjCInterfaceName:850 case CodeCompletionContext::CCC_Symbol:851 case CodeCompletionContext::CCC_SymbolOrNewName:852 case CodeCompletionContext::CCC_ObjCClassForwardDecl:853 case CodeCompletionContext::CCC_TopLevelOrExpression:854 return true;855 case CodeCompletionContext::CCC_OtherWithMacros:856 case CodeCompletionContext::CCC_DotMemberAccess:857 case CodeCompletionContext::CCC_ArrowMemberAccess:858 case CodeCompletionContext::CCC_ObjCCategoryName:859 case CodeCompletionContext::CCC_ObjCPropertyAccess:860 case CodeCompletionContext::CCC_MacroName:861 case CodeCompletionContext::CCC_MacroNameUse:862 case CodeCompletionContext::CCC_PreprocessorExpression:863 case CodeCompletionContext::CCC_PreprocessorDirective:864 case CodeCompletionContext::CCC_SelectorName:865 case CodeCompletionContext::CCC_TypeQualifiers:866 case CodeCompletionContext::CCC_ObjCInstanceMessage:867 case CodeCompletionContext::CCC_ObjCClassMessage:868 case CodeCompletionContext::CCC_IncludedFile:869 case CodeCompletionContext::CCC_Attribute:870 // FIXME: Provide identifier based completions for the following contexts:871 case CodeCompletionContext::CCC_Other: // Be conservative.872 case CodeCompletionContext::CCC_NaturalLanguage:873 case CodeCompletionContext::CCC_Recovery:874 case CodeCompletionContext::CCC_NewName:875 return false;876 }877 llvm_unreachable("unknown code completion context");878}879 880static bool isInjectedClass(const NamedDecl &D) {881 if (auto *R = dyn_cast_or_null<CXXRecordDecl>(&D))882 if (R->isInjectedClassName())883 return true;884 return false;885}886 887// Some member calls are excluded because they're so rarely useful.888static bool isExcludedMember(const NamedDecl &D) {889 // Destructor completion is rarely useful, and works inconsistently.890 // (s.^ completes ~string, but s.~st^ is an error).891 if (D.getKind() == Decl::CXXDestructor)892 return true;893 // Injected name may be useful for A::foo(), but who writes A::A::foo()?894 if (isInjectedClass(D))895 return true;896 // Explicit calls to operators are also rare.897 auto NameKind = D.getDeclName().getNameKind();898 if (NameKind == DeclarationName::CXXOperatorName ||899 NameKind == DeclarationName::CXXLiteralOperatorName ||900 NameKind == DeclarationName::CXXConversionFunctionName)901 return true;902 return false;903}904 905// The CompletionRecorder captures Sema code-complete output, including context.906// It filters out ignored results (but doesn't apply fuzzy-filtering yet).907// It doesn't do scoring or conversion to CompletionItem yet, as we want to908// merge with index results first.909// Generally the fields and methods of this object should only be used from910// within the callback.911struct CompletionRecorder : public CodeCompleteConsumer {912 CompletionRecorder(const CodeCompleteOptions &Opts,913 llvm::unique_function<void()> ResultsCallback)914 : CodeCompleteConsumer(Opts.getClangCompleteOpts()),915 CCContext(CodeCompletionContext::CCC_Other), Opts(Opts),916 CCAllocator(std::make_shared<GlobalCodeCompletionAllocator>()),917 CCTUInfo(CCAllocator), ResultsCallback(std::move(ResultsCallback)) {918 assert(this->ResultsCallback);919 }920 921 std::vector<CodeCompletionResult> Results;922 CodeCompletionContext CCContext;923 Sema *CCSema = nullptr; // Sema that created the results.924 // FIXME: Sema is scary. Can we store ASTContext and Preprocessor, instead?925 926 void ProcessCodeCompleteResults(class Sema &S, CodeCompletionContext Context,927 CodeCompletionResult *InResults,928 unsigned NumResults) final {929 // Results from recovery mode are generally useless, and the callback after930 // recovery (if any) is usually more interesting. To make sure we handle the931 // future callback from sema, we just ignore all callbacks in recovery mode,932 // as taking only results from recovery mode results in poor completion933 // results.934 // FIXME: in case there is no future sema completion callback after the935 // recovery mode, we might still want to provide some results (e.g. trivial936 // identifier-based completion).937 CodeCompletionContext::Kind ContextKind = Context.getKind();938 if (ContextKind == CodeCompletionContext::CCC_Recovery) {939 log("Code complete: Ignoring sema code complete callback with Recovery "940 "context.");941 return;942 }943 // If a callback is called without any sema result and the context does not944 // support index-based completion, we simply skip it to give way to945 // potential future callbacks with results.946 if (NumResults == 0 && !contextAllowsIndex(Context.getKind()))947 return;948 if (CCSema) {949 log("Multiple code complete callbacks (parser backtracked?). "950 "Dropping results from context {0}, keeping results from {1}.",951 getCompletionKindString(Context.getKind()),952 getCompletionKindString(this->CCContext.getKind()));953 return;954 }955 // Record the completion context.956 CCSema = &S;957 CCContext = Context;958 959 // Retain the results we might want.960 for (unsigned I = 0; I < NumResults; ++I) {961 auto &Result = InResults[I];962 if (Config::current().Completion.CodePatterns ==963 Config::CodePatternsPolicy::None &&964 Result.Kind == CodeCompletionResult::RK_Pattern &&965 // keep allowing the include files autocomplete suggestions966 ContextKind != CodeCompletionContext::CCC_IncludedFile)967 continue;968 // Class members that are shadowed by subclasses are usually noise.969 if (Result.Hidden && Result.Declaration &&970 Result.Declaration->isCXXClassMember())971 continue;972 if (!Opts.IncludeIneligibleResults &&973 (Result.Availability == CXAvailability_NotAvailable ||974 Result.Availability == CXAvailability_NotAccessible))975 continue;976 if (Result.Declaration &&977 !Context.getBaseType().isNull() // is this a member-access context?978 && isExcludedMember(*Result.Declaration))979 continue;980 // Skip injected class name when no class scope is not explicitly set.981 // E.g. show injected A::A in `using A::A^` but not in "A^".982 if (Result.Declaration && !Context.getCXXScopeSpecifier() &&983 isInjectedClass(*Result.Declaration))984 continue;985 // We choose to never append '::' to completion results in clangd.986 Result.StartsNestedNameSpecifier = false;987 Results.push_back(Result);988 }989 ResultsCallback();990 }991 992 CodeCompletionAllocator &getAllocator() override { return *CCAllocator; }993 CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }994 995 // Returns the filtering/sorting name for Result, which must be from Results.996 // Returned string is owned by this recorder (or the AST).997 llvm::StringRef getName(const CodeCompletionResult &Result) {998 switch (Result.Kind) {999 case CodeCompletionResult::RK_Declaration:1000 if (auto *ID = Result.Declaration->getIdentifier())1001 return ID->getName();1002 break;1003 case CodeCompletionResult::RK_Keyword:1004 return Result.Keyword;1005 case CodeCompletionResult::RK_Macro:1006 return Result.Macro->getName();1007 case CodeCompletionResult::RK_Pattern:1008 break;1009 }1010 auto *CCS = codeCompletionString(Result);1011 const CodeCompletionString::Chunk *OnlyText = nullptr;1012 for (auto &C : *CCS) {1013 if (C.Kind != CodeCompletionString::CK_TypedText)1014 continue;1015 if (OnlyText)1016 return CCAllocator->CopyString(CCS->getAllTypedText());1017 OnlyText = &C;1018 }1019 return OnlyText ? OnlyText->Text : llvm::StringRef();1020 }1021 1022 // Build a CodeCompletion string for R, which must be from Results.1023 // The CCS will be owned by this recorder.1024 CodeCompletionString *codeCompletionString(const CodeCompletionResult &R) {1025 // CodeCompletionResult doesn't seem to be const-correct. We own it, anyway.1026 return const_cast<CodeCompletionResult &>(R).CreateCodeCompletionString(1027 *CCSema, CCContext, *CCAllocator, CCTUInfo,1028 /*IncludeBriefComments=*/false);1029 }1030 1031private:1032 CodeCompleteOptions Opts;1033 std::shared_ptr<GlobalCodeCompletionAllocator> CCAllocator;1034 CodeCompletionTUInfo CCTUInfo;1035 llvm::unique_function<void()> ResultsCallback;1036};1037 1038struct ScoredSignature {1039 // When not null, requires documentation to be requested from the index with1040 // this ID.1041 SymbolID IDForDoc;1042 SignatureInformation Signature;1043 SignatureQualitySignals Quality;1044};1045 1046// Returns the index of the parameter matching argument number "Arg.1047// This is usually just "Arg", except for variadic functions/templates, where1048// "Arg" might be higher than the number of parameters. When that happens, we1049// assume the last parameter is variadic and assume all further args are1050// part of it.1051int paramIndexForArg(const CodeCompleteConsumer::OverloadCandidate &Candidate,1052 int Arg) {1053 int NumParams = Candidate.getNumParams();1054 if (auto *T = Candidate.getFunctionType()) {1055 if (auto *Proto = T->getAs<FunctionProtoType>()) {1056 if (Proto->isVariadic())1057 ++NumParams;1058 }1059 }1060 return std::min(Arg, std::max(NumParams - 1, 0));1061}1062 1063class SignatureHelpCollector final : public CodeCompleteConsumer {1064public:1065 SignatureHelpCollector(const clang::CodeCompleteOptions &CodeCompleteOpts,1066 MarkupKind DocumentationFormat,1067 const SymbolIndex *Index, SignatureHelp &SigHelp)1068 : CodeCompleteConsumer(CodeCompleteOpts), SigHelp(SigHelp),1069 Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),1070 CCTUInfo(Allocator), Index(Index),1071 DocumentationFormat(DocumentationFormat) {}1072 1073 void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,1074 OverloadCandidate *Candidates,1075 unsigned NumCandidates,1076 SourceLocation OpenParLoc,1077 bool Braced) override {1078 assert(!OpenParLoc.isInvalid());1079 SourceManager &SrcMgr = S.getSourceManager();1080 OpenParLoc = SrcMgr.getFileLoc(OpenParLoc);1081 if (SrcMgr.isInMainFile(OpenParLoc))1082 SigHelp.argListStart = sourceLocToPosition(SrcMgr, OpenParLoc);1083 else1084 elog("Location oustide main file in signature help: {0}",1085 OpenParLoc.printToString(SrcMgr));1086 1087 std::vector<ScoredSignature> ScoredSignatures;1088 SigHelp.signatures.reserve(NumCandidates);1089 ScoredSignatures.reserve(NumCandidates);1090 // FIXME(rwols): How can we determine the "active overload candidate"?1091 // Right now the overloaded candidates seem to be provided in a "best fit"1092 // order, so I'm not too worried about this.1093 SigHelp.activeSignature = 0;1094 assert(CurrentArg <= (unsigned)std::numeric_limits<int>::max() &&1095 "too many arguments");1096 1097 SigHelp.activeParameter = static_cast<int>(CurrentArg);1098 1099 for (unsigned I = 0; I < NumCandidates; ++I) {1100 OverloadCandidate Candidate = Candidates[I];1101 // We want to avoid showing instantiated signatures, because they may be1102 // long in some cases (e.g. when 'T' is substituted with 'std::string', we1103 // would get 'std::basic_string<char>').1104 if (auto *Func = Candidate.getFunction()) {1105 if (auto *Pattern = Func->getTemplateInstantiationPattern())1106 Candidate = OverloadCandidate(Pattern);1107 }1108 if (static_cast<int>(I) == SigHelp.activeSignature) {1109 // The activeParameter in LSP relates to the activeSignature. There is1110 // another, per-signature field, but we currently do not use it and not1111 // all clients might support it.1112 // FIXME: Add support for per-signature activeParameter field.1113 SigHelp.activeParameter =1114 paramIndexForArg(Candidate, SigHelp.activeParameter);1115 }1116 1117 const auto *CCS = Candidate.CreateSignatureString(1118 CurrentArg, S, *Allocator, CCTUInfo,1119 /*IncludeBriefComments=*/true, Braced);1120 assert(CCS && "Expected the CodeCompletionString to be non-null");1121 ScoredSignatures.push_back(processOverloadCandidate(1122 Candidate, *CCS,1123 Candidate.getFunction()1124 ? getDeclComment(S.getASTContext(), *Candidate.getFunction())1125 : ""));1126 }1127 1128 // Sema does not load the docs from the preamble, so we need to fetch extra1129 // docs from the index instead.1130 llvm::DenseMap<SymbolID, std::string> FetchedDocs;1131 if (Index) {1132 LookupRequest IndexRequest;1133 for (const auto &S : ScoredSignatures) {1134 if (!S.IDForDoc)1135 continue;1136 IndexRequest.IDs.insert(S.IDForDoc);1137 }1138 Index->lookup(IndexRequest, [&](const Symbol &S) {1139 if (!S.Documentation.empty())1140 FetchedDocs[S.ID] = std::string(S.Documentation);1141 });1142 vlog("SigHelp: requested docs for {0} symbols from the index, got {1} "1143 "symbols with non-empty docs in the response",1144 IndexRequest.IDs.size(), FetchedDocs.size());1145 }1146 1147 llvm::sort(ScoredSignatures, [](const ScoredSignature &L,1148 const ScoredSignature &R) {1149 // Ordering follows:1150 // - Less number of parameters is better.1151 // - Aggregate > Function > FunctionType > FunctionTemplate1152 // - High score is better.1153 // - Shorter signature is better.1154 // - Alphabetically smaller is better.1155 if (L.Quality.NumberOfParameters != R.Quality.NumberOfParameters)1156 return L.Quality.NumberOfParameters < R.Quality.NumberOfParameters;1157 if (L.Quality.NumberOfOptionalParameters !=1158 R.Quality.NumberOfOptionalParameters)1159 return L.Quality.NumberOfOptionalParameters <1160 R.Quality.NumberOfOptionalParameters;1161 if (L.Quality.Kind != R.Quality.Kind) {1162 using OC = CodeCompleteConsumer::OverloadCandidate;1163 auto KindPriority = [&](OC::CandidateKind K) {1164 switch (K) {1165 case OC::CK_Aggregate:1166 return 0;1167 case OC::CK_Function:1168 return 1;1169 case OC::CK_FunctionType:1170 return 2;1171 case OC::CK_FunctionProtoTypeLoc:1172 return 3;1173 case OC::CK_FunctionTemplate:1174 return 4;1175 case OC::CK_Template:1176 return 5;1177 }1178 llvm_unreachable("Unknown overload candidate type.");1179 };1180 return KindPriority(L.Quality.Kind) < KindPriority(R.Quality.Kind);1181 }1182 if (L.Signature.label.size() != R.Signature.label.size())1183 return L.Signature.label.size() < R.Signature.label.size();1184 return L.Signature.label < R.Signature.label;1185 });1186 1187 for (auto &SS : ScoredSignatures) {1188 auto IndexDocIt =1189 SS.IDForDoc ? FetchedDocs.find(SS.IDForDoc) : FetchedDocs.end();1190 if (IndexDocIt != FetchedDocs.end()) {1191 markup::Document SignatureComment;1192 parseDocumentation(IndexDocIt->second, SignatureComment);1193 SS.Signature.documentation =1194 renderDoc(SignatureComment, DocumentationFormat);1195 }1196 1197 SigHelp.signatures.push_back(std::move(SS.Signature));1198 }1199 }1200 1201 GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; }1202 1203 CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }1204 1205private:1206 void processParameterChunk(llvm::StringRef ChunkText,1207 SignatureInformation &Signature) const {1208 // (!) this is O(n), should still be fast compared to building ASTs.1209 unsigned ParamStartOffset = lspLength(Signature.label);1210 unsigned ParamEndOffset = ParamStartOffset + lspLength(ChunkText);1211 // A piece of text that describes the parameter that corresponds to1212 // the code-completion location within a function call, message send,1213 // macro invocation, etc.1214 Signature.label += ChunkText;1215 ParameterInformation Info;1216 Info.labelOffsets.emplace(ParamStartOffset, ParamEndOffset);1217 // FIXME: only set 'labelOffsets' when all clients migrate out of it.1218 Info.labelString = std::string(ChunkText);1219 1220 Signature.parameters.push_back(std::move(Info));1221 }1222 1223 void processOptionalChunk(const CodeCompletionString &CCS,1224 SignatureInformation &Signature,1225 SignatureQualitySignals &Signal) const {1226 for (const auto &Chunk : CCS) {1227 switch (Chunk.Kind) {1228 case CodeCompletionString::CK_Optional:1229 assert(Chunk.Optional &&1230 "Expected the optional code completion string to be non-null.");1231 processOptionalChunk(*Chunk.Optional, Signature, Signal);1232 break;1233 case CodeCompletionString::CK_VerticalSpace:1234 break;1235 case CodeCompletionString::CK_CurrentParameter:1236 case CodeCompletionString::CK_Placeholder:1237 processParameterChunk(Chunk.Text, Signature);1238 Signal.NumberOfOptionalParameters++;1239 break;1240 default:1241 Signature.label += Chunk.Text;1242 break;1243 }1244 }1245 }1246 1247 // FIXME(ioeric): consider moving CodeCompletionString logic here to1248 // CompletionString.h.1249 ScoredSignature processOverloadCandidate(const OverloadCandidate &Candidate,1250 const CodeCompletionString &CCS,1251 llvm::StringRef DocComment) const {1252 SignatureInformation Signature;1253 SignatureQualitySignals Signal;1254 const char *ReturnType = nullptr;1255 1256 markup::Document OverloadComment;1257 parseDocumentation(formatDocumentation(CCS, DocComment), OverloadComment);1258 Signature.documentation = renderDoc(OverloadComment, DocumentationFormat);1259 Signal.Kind = Candidate.getKind();1260 1261 for (const auto &Chunk : CCS) {1262 switch (Chunk.Kind) {1263 case CodeCompletionString::CK_ResultType:1264 // A piece of text that describes the type of an entity or,1265 // for functions and methods, the return type.1266 assert(!ReturnType && "Unexpected CK_ResultType");1267 ReturnType = Chunk.Text;1268 break;1269 case CodeCompletionString::CK_CurrentParameter:1270 case CodeCompletionString::CK_Placeholder:1271 processParameterChunk(Chunk.Text, Signature);1272 Signal.NumberOfParameters++;1273 break;1274 case CodeCompletionString::CK_Optional: {1275 // The rest of the parameters are defaulted/optional.1276 assert(Chunk.Optional &&1277 "Expected the optional code completion string to be non-null.");1278 processOptionalChunk(*Chunk.Optional, Signature, Signal);1279 break;1280 }1281 case CodeCompletionString::CK_VerticalSpace:1282 break;1283 default:1284 Signature.label += Chunk.Text;1285 break;1286 }1287 }1288 if (ReturnType) {1289 Signature.label += " -> ";1290 Signature.label += ReturnType;1291 }1292 dlog("Signal for {0}: {1}", Signature, Signal);1293 ScoredSignature Result;1294 Result.Signature = std::move(Signature);1295 Result.Quality = Signal;1296 const FunctionDecl *Func = Candidate.getFunction();1297 if (Func && Result.Signature.documentation.value.empty()) {1298 // Computing USR caches linkage, which may change after code completion.1299 if (!hasUnstableLinkage(Func))1300 Result.IDForDoc = clangd::getSymbolID(Func);1301 }1302 return Result;1303 }1304 1305 SignatureHelp &SigHelp;1306 std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;1307 CodeCompletionTUInfo CCTUInfo;1308 const SymbolIndex *Index;1309 MarkupKind DocumentationFormat;1310}; // SignatureHelpCollector1311 1312// Used only for completion of C-style comments in function call (i.e.1313// /*foo=*/7). Similar to SignatureHelpCollector, but needs to do less work.1314class ParamNameCollector final : public CodeCompleteConsumer {1315public:1316 ParamNameCollector(const clang::CodeCompleteOptions &CodeCompleteOpts,1317 std::set<std::string> &ParamNames)1318 : CodeCompleteConsumer(CodeCompleteOpts),1319 Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),1320 CCTUInfo(Allocator), ParamNames(ParamNames) {}1321 1322 void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,1323 OverloadCandidate *Candidates,1324 unsigned NumCandidates,1325 SourceLocation OpenParLoc,1326 bool Braced) override {1327 assert(CurrentArg <= (unsigned)std::numeric_limits<int>::max() &&1328 "too many arguments");1329 1330 for (unsigned I = 0; I < NumCandidates; ++I) {1331 if (const NamedDecl *ND = Candidates[I].getParamDecl(CurrentArg))1332 if (const auto *II = ND->getIdentifier())1333 ParamNames.emplace(II->getName());1334 }1335 }1336 1337private:1338 GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; }1339 1340 CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }1341 1342 std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;1343 CodeCompletionTUInfo CCTUInfo;1344 std::set<std::string> &ParamNames;1345};1346 1347struct SemaCompleteInput {1348 PathRef FileName;1349 size_t Offset;1350 const PreambleData &Preamble;1351 const std::optional<PreamblePatch> Patch;1352 const ParseInputs &ParseInput;1353};1354 1355void loadMainFilePreambleMacros(const Preprocessor &PP,1356 const PreambleData &Preamble) {1357 // The ExternalPreprocessorSource has our macros, if we know where to look.1358 // We can read all the macros using PreambleMacros->ReadDefinedMacros(),1359 // but this includes transitively included files, so may deserialize a lot.1360 ExternalPreprocessorSource *PreambleMacros = PP.getExternalSource();1361 // As we have the names of the macros, we can look up their IdentifierInfo1362 // and then use this to load just the macros we want.1363 const auto &ITable = PP.getIdentifierTable();1364 IdentifierInfoLookup *PreambleIdentifiers =1365 ITable.getExternalIdentifierLookup();1366 1367 if (!PreambleIdentifiers || !PreambleMacros)1368 return;1369 for (const auto &MacroName : Preamble.Macros.Names) {1370 if (ITable.find(MacroName.getKey()) != ITable.end())1371 continue;1372 if (auto *II = PreambleIdentifiers->get(MacroName.getKey()))1373 if (II->isOutOfDate())1374 PreambleMacros->updateOutOfDateIdentifier(*II);1375 }1376}1377 1378// Invokes Sema code completion on a file.1379// If \p Includes is set, it will be updated based on the compiler invocation.1380bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,1381 const clang::CodeCompleteOptions &Options,1382 const SemaCompleteInput &Input,1383 IncludeStructure *Includes = nullptr) {1384 trace::Span Tracer("Sema completion");1385 1386 IgnoreDiagnostics IgnoreDiags;1387 auto CI = buildCompilerInvocation(Input.ParseInput, IgnoreDiags);1388 if (!CI) {1389 elog("Couldn't create CompilerInvocation");1390 return false;1391 }1392 auto &FrontendOpts = CI->getFrontendOpts();1393 FrontendOpts.SkipFunctionBodies = true;1394 // Disable typo correction in Sema.1395 CI->getLangOpts().SpellChecking = false;1396 // Code completion won't trigger in delayed template bodies.1397 // This is on-by-default in windows to allow parsing SDK headers; we're only1398 // disabling it for the main-file (not preamble).1399 CI->getLangOpts().DelayedTemplateParsing = false;1400 // Setup code completion.1401 FrontendOpts.CodeCompleteOpts = Options;1402 FrontendOpts.CodeCompletionAt.FileName = std::string(Input.FileName);1403 std::tie(FrontendOpts.CodeCompletionAt.Line,1404 FrontendOpts.CodeCompletionAt.Column) =1405 offsetToClangLineColumn(Input.ParseInput.Contents, Input.Offset);1406 1407 std::unique_ptr<llvm::MemoryBuffer> ContentsBuffer =1408 llvm::MemoryBuffer::getMemBuffer(Input.ParseInput.Contents,1409 Input.FileName);1410 // The diagnostic options must be set before creating a CompilerInstance.1411 CI->getDiagnosticOpts().IgnoreWarnings = true;1412 // We reuse the preamble whether it's valid or not. This is a1413 // correctness/performance tradeoff: building without a preamble is slow, and1414 // completion is latency-sensitive.1415 // However, if we're completing *inside* the preamble section of the draft,1416 // overriding the preamble will break sema completion. Fortunately we can just1417 // skip all includes in this case; these completions are really simple.1418 PreambleBounds PreambleRegion =1419 ComputePreambleBounds(CI->getLangOpts(), *ContentsBuffer, 0);1420 bool CompletingInPreamble = Input.Offset < PreambleRegion.Size ||1421 (!PreambleRegion.PreambleEndsAtStartOfLine &&1422 Input.Offset == PreambleRegion.Size);1423 if (Input.Patch)1424 Input.Patch->apply(*CI);1425 // NOTE: we must call BeginSourceFile after prepareCompilerInstance. Otherwise1426 // the remapped buffers do not get freed.1427 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =1428 Input.ParseInput.TFS->view(Input.ParseInput.CompileCommand.Directory);1429 if (Input.Preamble.StatCache)1430 VFS = Input.Preamble.StatCache->getConsumingFS(std::move(VFS));1431 auto Clang = prepareCompilerInstance(1432 std::move(CI), !CompletingInPreamble ? &Input.Preamble.Preamble : nullptr,1433 std::move(ContentsBuffer), std::move(VFS), IgnoreDiags);1434 Clang->getPreprocessorOpts().SingleFileParseMode = CompletingInPreamble;1435 Clang->setCodeCompletionConsumer(Consumer.release());1436 1437 if (Input.Preamble.RequiredModules)1438 Input.Preamble.RequiredModules->adjustHeaderSearchOptions(Clang->getHeaderSearchOpts());1439 1440 SyntaxOnlyAction Action;1441 if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) {1442 log("BeginSourceFile() failed when running codeComplete for {0}",1443 Input.FileName);1444 return false;1445 }1446 // Macros can be defined within the preamble region of the main file.1447 // They don't fall nicely into our index/Sema dichotomy:1448 // - they're not indexed for completion (they're not available across files)1449 // - but Sema code complete won't see them: as part of the preamble, they're1450 // deserialized only when mentioned.1451 // Force them to be deserialized so SemaCodeComplete sees them.1452 loadMainFilePreambleMacros(Clang->getPreprocessor(), Input.Preamble);1453 if (Includes)1454 Includes->collect(*Clang);1455 if (llvm::Error Err = Action.Execute()) {1456 log("Execute() failed when running codeComplete for {0}: {1}",1457 Input.FileName, toString(std::move(Err)));1458 return false;1459 }1460 Action.EndSourceFile();1461 1462 return true;1463}1464 1465// Should we allow index completions in the specified context?1466bool allowIndex(CodeCompletionContext &CC) {1467 if (!contextAllowsIndex(CC.getKind()))1468 return false;1469 // We also avoid ClassName::bar (but allow namespace::bar).1470 auto Scope = CC.getCXXScopeSpecifier();1471 if (!Scope)1472 return true;1473 // We only query the index when qualifier is a namespace.1474 // If it's a class, we rely solely on sema completions.1475 switch ((*Scope)->getScopeRep().getKind()) {1476 case NestedNameSpecifier::Kind::Null:1477 case NestedNameSpecifier::Kind::Global:1478 case NestedNameSpecifier::Kind::Namespace:1479 return true;1480 case NestedNameSpecifier::Kind::MicrosoftSuper:1481 case NestedNameSpecifier::Kind::Type:1482 return false;1483 }1484 llvm_unreachable("invalid NestedNameSpecifier kind");1485}1486 1487// Should we include a symbol from the index given the completion kind?1488// FIXME: Ideally we can filter in the fuzzy find request itself.1489bool includeSymbolFromIndex(CodeCompletionContext::Kind Kind,1490 const Symbol &Sym) {1491 // Objective-C protocols are only useful in ObjC protocol completions,1492 // in other places they're confusing, especially when they share the same1493 // identifier with a class.1494 if (Sym.SymInfo.Kind == index::SymbolKind::Protocol &&1495 Sym.SymInfo.Lang == index::SymbolLanguage::ObjC)1496 return Kind == CodeCompletionContext::CCC_ObjCProtocolName;1497 else if (Kind == CodeCompletionContext::CCC_ObjCProtocolName)1498 // Don't show anything else in ObjC protocol completions.1499 return false;1500 1501 if (Kind == CodeCompletionContext::CCC_ObjCClassForwardDecl)1502 return Sym.SymInfo.Kind == index::SymbolKind::Class &&1503 Sym.SymInfo.Lang == index::SymbolLanguage::ObjC;1504 return true;1505}1506 1507std::future<std::pair<bool, SymbolSlab>>1508startAsyncFuzzyFind(const SymbolIndex &Index, const FuzzyFindRequest &Req) {1509 return runAsync<std::pair<bool, SymbolSlab>>([&Index, Req]() {1510 trace::Span Tracer("Async fuzzyFind");1511 SymbolSlab::Builder Syms;1512 bool Incomplete =1513 Index.fuzzyFind(Req, [&Syms](const Symbol &Sym) { Syms.insert(Sym); });1514 return std::make_pair(Incomplete, std::move(Syms).build());1515 });1516}1517 1518// Creates a `FuzzyFindRequest` based on the cached index request from the1519// last completion, if any, and the speculated completion filter text in the1520// source code.1521FuzzyFindRequest speculativeFuzzyFindRequestForCompletion(1522 FuzzyFindRequest CachedReq, const CompletionPrefix &HeuristicPrefix) {1523 CachedReq.Query = std::string(HeuristicPrefix.Name);1524 return CachedReq;1525}1526 1527// This function is similar to Lexer::findNextToken(), but assumes1528// that the input SourceLocation is the completion point (which is1529// a case findNextToken() does not handle).1530std::optional<Token>1531findTokenAfterCompletionPoint(SourceLocation CompletionPoint,1532 const SourceManager &SM,1533 const LangOptions &LangOpts) {1534 SourceLocation Loc = CompletionPoint;1535 if (Loc.isMacroID()) {1536 if (!Lexer::isAtEndOfMacroExpansion(Loc, SM, LangOpts, &Loc))1537 return std::nullopt;1538 }1539 1540 // Advance to the next SourceLocation after the completion point.1541 // Lexer::findNextToken() would call MeasureTokenLength() here,1542 // which does not handle the completion point (and can't, because1543 // the Lexer instance it constructs internally doesn't have a1544 // Preprocessor and so doesn't know about the completion point).1545 Loc = Loc.getLocWithOffset(1);1546 1547 // Break down the source location.1548 std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);1549 1550 // Try to load the file buffer.1551 bool InvalidTemp = false;1552 StringRef File = SM.getBufferData(LocInfo.first, &InvalidTemp);1553 if (InvalidTemp)1554 return std::nullopt;1555 1556 const char *TokenBegin = File.data() + LocInfo.second;1557 1558 // Lex from the start of the given location.1559 Lexer TheLexer(SM.getLocForStartOfFile(LocInfo.first), LangOpts, File.begin(),1560 TokenBegin, File.end());1561 // Find the token.1562 Token Tok;1563 TheLexer.LexFromRawLexer(Tok);1564 return Tok;1565}1566 1567// Runs Sema-based (AST) and Index-based completion, returns merged results.1568//1569// There are a few tricky considerations:1570// - the AST provides information needed for the index query (e.g. which1571// namespaces to search in). So Sema must start first.1572// - we only want to return the top results (Opts.Limit).1573// Building CompletionItems for everything else is wasteful, so we want to1574// preserve the "native" format until we're done with scoring.1575// - the data underlying Sema completion items is owned by the AST and various1576// other arenas, which must stay alive for us to build CompletionItems.1577// - we may get duplicate results from Sema and the Index, we need to merge.1578//1579// So we start Sema completion first, and do all our work in its callback.1580// We use the Sema context information to query the index.1581// Then we merge the two result sets, producing items that are Sema/Index/Both.1582// These items are scored, and the top N are synthesized into the LSP response.1583// Finally, we can clean up the data structures created by Sema completion.1584//1585// Main collaborators are:1586// - semaCodeComplete sets up the compiler machinery to run code completion.1587// - CompletionRecorder captures Sema completion results, including context.1588// - SymbolIndex (Opts.Index) provides index completion results as Symbols1589// - CompletionCandidates are the result of merging Sema and Index results.1590// Each candidate points to an underlying CodeCompletionResult (Sema), a1591// Symbol (Index), or both. It computes the result quality score.1592// CompletionCandidate also does conversion to CompletionItem (at the end).1593// - FuzzyMatcher scores how the candidate matches the partial identifier.1594// This score is combined with the result quality score for the final score.1595// - TopN determines the results with the best score.1596class CodeCompleteFlow {1597 PathRef FileName;1598 IncludeStructure Includes; // Complete once the compiler runs.1599 SpeculativeFuzzyFind *SpecFuzzyFind; // Can be nullptr.1600 const CodeCompleteOptions &Opts;1601 1602 // Sema takes ownership of Recorder. Recorder is valid until Sema cleanup.1603 CompletionRecorder *Recorder = nullptr;1604 CodeCompletionContext::Kind CCContextKind = CodeCompletionContext::CCC_Other;1605 bool IsUsingDeclaration = false;1606 // The snippets will not be generated if the token following completion1607 // location is an opening parenthesis (tok::l_paren) because this would add1608 // extra parenthesis.1609 tok::TokenKind NextTokenKind = tok::eof;1610 // Counters for logging.1611 int NSema = 0, NIndex = 0, NSemaAndIndex = 0, NIdent = 0;1612 bool Incomplete = false; // Would more be available with a higher limit?1613 CompletionPrefix HeuristicPrefix;1614 std::optional<FuzzyMatcher> Filter; // Initialized once Sema runs.1615 Range ReplacedRange;1616 std::vector<std::string> QueryScopes; // Initialized once Sema runs.1617 std::vector<std::string> AccessibleScopes; // Initialized once Sema runs.1618 // Initialized once QueryScopes is initialized, if there are scopes.1619 std::optional<ScopeDistance> ScopeProximity;1620 std::optional<OpaqueType> PreferredType; // Initialized once Sema runs.1621 // Whether to query symbols from any scope. Initialized once Sema runs.1622 bool AllScopes = false;1623 llvm::StringSet<> ContextWords;1624 // Include-insertion and proximity scoring rely on the include structure.1625 // This is available after Sema has run.1626 std::optional<IncludeInserter> Inserter; // Available during runWithSema.1627 std::optional<URIDistance> FileProximity; // Initialized once Sema runs.1628 /// Speculative request based on the cached request and the filter text before1629 /// the cursor.1630 /// Initialized right before sema run. This is only set if `SpecFuzzyFind` is1631 /// set and contains a cached request.1632 std::optional<FuzzyFindRequest> SpecReq;1633 1634public:1635 // A CodeCompleteFlow object is only useful for calling run() exactly once.1636 CodeCompleteFlow(PathRef FileName, const IncludeStructure &Includes,1637 SpeculativeFuzzyFind *SpecFuzzyFind,1638 const CodeCompleteOptions &Opts)1639 : FileName(FileName), Includes(Includes), SpecFuzzyFind(SpecFuzzyFind),1640 Opts(Opts) {}1641 1642 CodeCompleteResult run(const SemaCompleteInput &SemaCCInput) && {1643 trace::Span Tracer("CodeCompleteFlow");1644 HeuristicPrefix = guessCompletionPrefix(SemaCCInput.ParseInput.Contents,1645 SemaCCInput.Offset);1646 populateContextWords(SemaCCInput.ParseInput.Contents);1647 if (Opts.Index && SpecFuzzyFind && SpecFuzzyFind->CachedReq) {1648 assert(!SpecFuzzyFind->Result.valid());1649 SpecReq = speculativeFuzzyFindRequestForCompletion(1650 *SpecFuzzyFind->CachedReq, HeuristicPrefix);1651 SpecFuzzyFind->Result = startAsyncFuzzyFind(*Opts.Index, *SpecReq);1652 }1653 1654 // We run Sema code completion first. It builds an AST and calculates:1655 // - completion results based on the AST.1656 // - partial identifier and context. We need these for the index query.1657 CodeCompleteResult Output;1658 auto RecorderOwner = std::make_unique<CompletionRecorder>(Opts, [&]() {1659 assert(Recorder && "Recorder is not set");1660 CCContextKind = Recorder->CCContext.getKind();1661 IsUsingDeclaration = Recorder->CCContext.isUsingDeclaration();1662 auto Style = getFormatStyleForFile(SemaCCInput.FileName,1663 SemaCCInput.ParseInput.Contents,1664 *SemaCCInput.ParseInput.TFS, false);1665 const auto NextToken = findTokenAfterCompletionPoint(1666 Recorder->CCSema->getPreprocessor().getCodeCompletionLoc(),1667 Recorder->CCSema->getSourceManager(), Recorder->CCSema->LangOpts);1668 if (NextToken)1669 NextTokenKind = NextToken->getKind();1670 // If preprocessor was run, inclusions from preprocessor callback should1671 // already be added to Includes.1672 Inserter.emplace(1673 SemaCCInput.FileName, SemaCCInput.ParseInput.Contents, Style,1674 SemaCCInput.ParseInput.CompileCommand.Directory,1675 &Recorder->CCSema->getPreprocessor().getHeaderSearchInfo(),1676 Config::current().Style.QuotedHeaders,1677 Config::current().Style.AngledHeaders);1678 for (const auto &Inc : Includes.MainFileIncludes)1679 Inserter->addExisting(Inc);1680 1681 // Most of the cost of file proximity is in initializing the FileDistance1682 // structures based on the observed includes, once per query. Conceptually1683 // that happens here (though the per-URI-scheme initialization is lazy).1684 // The per-result proximity scoring is (amortized) very cheap.1685 FileDistanceOptions ProxOpts{}; // Use defaults.1686 const auto &SM = Recorder->CCSema->getSourceManager();1687 llvm::StringMap<SourceParams> ProxSources;1688 auto MainFileID =1689 Includes.getID(SM.getFileEntryForID(SM.getMainFileID()));1690 assert(MainFileID);1691 for (auto &HeaderIDAndDepth : Includes.includeDepth(*MainFileID)) {1692 auto &Source =1693 ProxSources[Includes.getRealPath(HeaderIDAndDepth.getFirst())];1694 Source.Cost = HeaderIDAndDepth.getSecond() * ProxOpts.IncludeCost;1695 // Symbols near our transitive includes are good, but only consider1696 // things in the same directory or below it. Otherwise there can be1697 // many false positives.1698 if (HeaderIDAndDepth.getSecond() > 0)1699 Source.MaxUpTraversals = 1;1700 }1701 FileProximity.emplace(ProxSources, ProxOpts);1702 1703 Output = runWithSema();1704 Inserter.reset(); // Make sure this doesn't out-live Clang.1705 SPAN_ATTACH(Tracer, "sema_completion_kind",1706 getCompletionKindString(CCContextKind));1707 log("Code complete: sema context {0}, query scopes [{1}] (AnyScope={2}), "1708 "expected type {3}{4}",1709 getCompletionKindString(CCContextKind),1710 llvm::join(QueryScopes.begin(), QueryScopes.end(), ","), AllScopes,1711 PreferredType ? Recorder->CCContext.getPreferredType().getAsString()1712 : "<none>",1713 IsUsingDeclaration ? ", inside using declaration" : "");1714 });1715 1716 Recorder = RecorderOwner.get();1717 1718 semaCodeComplete(std::move(RecorderOwner), Opts.getClangCompleteOpts(),1719 SemaCCInput, &Includes);1720 logResults(Output, Tracer);1721 return Output;1722 }1723 1724 void logResults(const CodeCompleteResult &Output, const trace::Span &Tracer) {1725 SPAN_ATTACH(Tracer, "sema_results", NSema);1726 SPAN_ATTACH(Tracer, "index_results", NIndex);1727 SPAN_ATTACH(Tracer, "merged_results", NSemaAndIndex);1728 SPAN_ATTACH(Tracer, "identifier_results", NIdent);1729 SPAN_ATTACH(Tracer, "returned_results", int64_t(Output.Completions.size()));1730 SPAN_ATTACH(Tracer, "incomplete", Output.HasMore);1731 log("Code complete: {0} results from Sema, {1} from Index, "1732 "{2} matched, {3} from identifiers, {4} returned{5}.",1733 NSema, NIndex, NSemaAndIndex, NIdent, Output.Completions.size(),1734 Output.HasMore ? " (incomplete)" : "");1735 assert(!Opts.Limit || Output.Completions.size() <= Opts.Limit);1736 // We don't assert that isIncomplete means we hit a limit.1737 // Indexes may choose to impose their own limits even if we don't have one.1738 }1739 1740 CodeCompleteResult runWithoutSema(llvm::StringRef Content, size_t Offset,1741 const ThreadsafeFS &TFS) && {1742 trace::Span Tracer("CodeCompleteWithoutSema");1743 // Fill in fields normally set by runWithSema()1744 HeuristicPrefix = guessCompletionPrefix(Content, Offset);1745 populateContextWords(Content);1746 CCContextKind = CodeCompletionContext::CCC_Recovery;1747 IsUsingDeclaration = false;1748 Filter = FuzzyMatcher(HeuristicPrefix.Name);1749 auto Pos = offsetToPosition(Content, Offset);1750 ReplacedRange.start = ReplacedRange.end = Pos;1751 ReplacedRange.start.character -= HeuristicPrefix.Name.size();1752 1753 llvm::StringMap<SourceParams> ProxSources;1754 ProxSources[FileName].Cost = 0;1755 FileProximity.emplace(ProxSources);1756 1757 auto Style = getFormatStyleForFile(FileName, Content, TFS, false);1758 // This will only insert verbatim headers.1759 Inserter.emplace(FileName, Content, Style,1760 /*BuildDir=*/"", /*HeaderSearchInfo=*/nullptr,1761 Config::current().Style.QuotedHeaders,1762 Config::current().Style.AngledHeaders);1763 1764 auto Identifiers = collectIdentifiers(Content, Style);1765 std::vector<RawIdentifier> IdentifierResults;1766 for (const auto &IDAndCount : Identifiers) {1767 RawIdentifier ID;1768 ID.Name = IDAndCount.first();1769 ID.References = IDAndCount.second;1770 // Avoid treating typed filter as an identifier.1771 if (ID.Name == HeuristicPrefix.Name)1772 --ID.References;1773 if (ID.References > 0)1774 IdentifierResults.push_back(std::move(ID));1775 }1776 1777 // Simplified version of getQueryScopes():1778 // - accessible scopes are determined heuristically.1779 // - all-scopes query if no qualifier was typed (and it's allowed).1780 SpecifiedScope Scopes;1781 Scopes.QueryScopes = visibleNamespaces(1782 Content.take_front(Offset), format::getFormattingLangOpts(Style));1783 for (std::string &S : Scopes.QueryScopes)1784 if (!S.empty())1785 S.append("::"); // visibleNamespaces doesn't include trailing ::.1786 if (HeuristicPrefix.Qualifier.empty())1787 AllScopes = Opts.AllScopes;1788 else if (HeuristicPrefix.Qualifier.starts_with("::")) {1789 Scopes.QueryScopes = {""};1790 Scopes.UnresolvedQualifier =1791 std::string(HeuristicPrefix.Qualifier.drop_front(2));1792 } else1793 Scopes.UnresolvedQualifier = std::string(HeuristicPrefix.Qualifier);1794 // First scope is the (modified) enclosing scope.1795 QueryScopes = Scopes.scopesForIndexQuery();1796 AccessibleScopes = QueryScopes;1797 ScopeProximity.emplace(QueryScopes);1798 1799 SymbolSlab IndexResults = Opts.Index ? queryIndex() : SymbolSlab();1800 1801 CodeCompleteResult Output = toCodeCompleteResult(mergeResults(1802 /*SemaResults=*/{}, IndexResults, IdentifierResults));1803 Output.RanParser = false;1804 logResults(Output, Tracer);1805 return Output;1806 }1807 1808private:1809 void populateContextWords(llvm::StringRef Content) {1810 // Take last 3 lines before the completion point.1811 unsigned RangeEnd = HeuristicPrefix.Qualifier.begin() - Content.data(),1812 RangeBegin = RangeEnd;1813 for (size_t I = 0; I < 3 && RangeBegin > 0; ++I) {1814 auto PrevNL = Content.rfind('\n', RangeBegin);1815 if (PrevNL == StringRef::npos) {1816 RangeBegin = 0;1817 break;1818 }1819 RangeBegin = PrevNL;1820 }1821 1822 ContextWords = collectWords(Content.slice(RangeBegin, RangeEnd));1823 dlog("Completion context words: {0}",1824 llvm::join(ContextWords.keys(), ", "));1825 }1826 1827 // This is called by run() once Sema code completion is done, but before the1828 // Sema data structures are torn down. It does all the real work.1829 CodeCompleteResult runWithSema() {1830 const auto &CodeCompletionRange = CharSourceRange::getCharRange(1831 Recorder->CCSema->getPreprocessor().getCodeCompletionTokenRange());1832 // When we are getting completions with an empty identifier, for example1833 // std::vector<int> asdf;1834 // asdf.^;1835 // Then the range will be invalid and we will be doing insertion, use1836 // current cursor position in such cases as range.1837 if (CodeCompletionRange.isValid()) {1838 ReplacedRange = halfOpenToRange(Recorder->CCSema->getSourceManager(),1839 CodeCompletionRange);1840 } else {1841 const auto &Pos = sourceLocToPosition(1842 Recorder->CCSema->getSourceManager(),1843 Recorder->CCSema->getPreprocessor().getCodeCompletionLoc());1844 ReplacedRange.start = ReplacedRange.end = Pos;1845 }1846 Filter = FuzzyMatcher(1847 Recorder->CCSema->getPreprocessor().getCodeCompletionFilter());1848 auto SpecifiedScopes = getQueryScopes(1849 Recorder->CCContext, *Recorder->CCSema, HeuristicPrefix, Opts);1850 1851 QueryScopes = SpecifiedScopes.scopesForIndexQuery();1852 AccessibleScopes = SpecifiedScopes.scopesForQualification();1853 AllScopes = SpecifiedScopes.AllowAllScopes;1854 if (!QueryScopes.empty())1855 ScopeProximity.emplace(QueryScopes);1856 PreferredType =1857 OpaqueType::fromType(Recorder->CCSema->getASTContext(),1858 Recorder->CCContext.getPreferredType());1859 // Sema provides the needed context to query the index.1860 // FIXME: in addition to querying for extra/overlapping symbols, we should1861 // explicitly request symbols corresponding to Sema results.1862 // We can use their signals even if the index can't suggest them.1863 // We must copy index results to preserve them, but there are at most Limit.1864 auto IndexResults = (Opts.Index && allowIndex(Recorder->CCContext))1865 ? queryIndex()1866 : SymbolSlab();1867 trace::Span Tracer("Populate CodeCompleteResult");1868 // Merge Sema and Index results, score them, and pick the winners.1869 auto Top =1870 mergeResults(Recorder->Results, IndexResults, /*Identifiers*/ {});1871 return toCodeCompleteResult(Top);1872 }1873 1874 CodeCompleteResult1875 toCodeCompleteResult(const std::vector<ScoredBundle> &Scored) {1876 CodeCompleteResult Output;1877 1878 // Convert the results to final form, assembling the expensive strings.1879 // If necessary, search the index for documentation comments.1880 LookupRequest Req;1881 llvm::DenseMap<SymbolID, uint32_t> SymbolToCompletion;1882 for (auto &C : Scored) {1883 Output.Completions.push_back(toCodeCompletion(C.first));1884 Output.Completions.back().Score = C.second;1885 Output.Completions.back().CompletionTokenRange = ReplacedRange;1886 if (Opts.Index && !Output.Completions.back().Documentation) {1887 for (auto &Cand : C.first) {1888 if (Cand.SemaResult &&1889 Cand.SemaResult->Kind == CodeCompletionResult::RK_Declaration) {1890 const NamedDecl *DeclToLookup = Cand.SemaResult->getDeclaration();1891 // For instantiations of members of class templates, the1892 // documentation will be stored at the member's original1893 // declaration.1894 if (const NamedDecl *Adjusted =1895 dyn_cast<NamedDecl>(&adjustDeclToTemplate(*DeclToLookup))) {1896 DeclToLookup = Adjusted;1897 }1898 auto ID = clangd::getSymbolID(DeclToLookup);1899 if (!ID)1900 continue;1901 Req.IDs.insert(ID);1902 SymbolToCompletion[ID] = Output.Completions.size() - 1;1903 }1904 }1905 }1906 }1907 Output.HasMore = Incomplete;1908 Output.Context = CCContextKind;1909 Output.CompletionRange = ReplacedRange;1910 1911 // Look up documentation from the index.1912 if (Opts.Index) {1913 Opts.Index->lookup(Req, [&](const Symbol &S) {1914 if (S.Documentation.empty())1915 return;1916 auto &C = Output.Completions[SymbolToCompletion.at(S.ID)];1917 C.Documentation.emplace();1918 parseDocumentation(S.Documentation, *C.Documentation);1919 });1920 }1921 1922 return Output;1923 }1924 1925 SymbolSlab queryIndex() {1926 trace::Span Tracer("Query index");1927 SPAN_ATTACH(Tracer, "limit", int64_t(Opts.Limit));1928 1929 // Build the query.1930 FuzzyFindRequest Req;1931 if (Opts.Limit)1932 Req.Limit = Opts.Limit;1933 Req.Query = std::string(Filter->pattern());1934 Req.RestrictForCodeCompletion = true;1935 Req.Scopes = QueryScopes;1936 Req.AnyScope = AllScopes;1937 // FIXME: we should send multiple weighted paths here.1938 Req.ProximityPaths.push_back(std::string(FileName));1939 if (PreferredType)1940 Req.PreferredTypes.push_back(std::string(PreferredType->raw()));1941 vlog("Code complete: fuzzyFind({0:2})", toJSON(Req));1942 1943 if (SpecFuzzyFind)1944 SpecFuzzyFind->NewReq = Req;1945 if (SpecFuzzyFind && SpecFuzzyFind->Result.valid() && (*SpecReq == Req)) {1946 vlog("Code complete: speculative fuzzy request matches the actual index "1947 "request. Waiting for the speculative index results.");1948 SPAN_ATTACH(Tracer, "Speculative results", true);1949 1950 trace::Span WaitSpec("Wait speculative results");1951 auto SpecRes = SpecFuzzyFind->Result.get();1952 Incomplete |= SpecRes.first;1953 return std::move(SpecRes.second);1954 }1955 1956 SPAN_ATTACH(Tracer, "Speculative results", false);1957 1958 // Run the query against the index.1959 SymbolSlab::Builder ResultsBuilder;1960 Incomplete |= Opts.Index->fuzzyFind(1961 Req, [&](const Symbol &Sym) { ResultsBuilder.insert(Sym); });1962 return std::move(ResultsBuilder).build();1963 }1964 1965 // Merges Sema and Index results where possible, to form CompletionCandidates.1966 // \p Identifiers is raw identifiers that can also be completion candidates.1967 // Identifiers are not merged with results from index or sema.1968 // Groups overloads if desired, to form CompletionCandidate::Bundles. The1969 // bundles are scored and top results are returned, best to worst.1970 std::vector<ScoredBundle>1971 mergeResults(const std::vector<CodeCompletionResult> &SemaResults,1972 const SymbolSlab &IndexResults,1973 const std::vector<RawIdentifier> &IdentifierResults) {1974 trace::Span Tracer("Merge and score results");1975 std::vector<CompletionCandidate::Bundle> Bundles;1976 llvm::DenseMap<size_t, size_t> BundleLookup;1977 auto AddToBundles = [&](const CodeCompletionResult *SemaResult,1978 const Symbol *IndexResult,1979 const RawIdentifier *IdentifierResult) {1980 CompletionCandidate C;1981 C.SemaResult = SemaResult;1982 C.IndexResult = IndexResult;1983 C.IdentifierResult = IdentifierResult;1984 if (C.IndexResult) {1985 C.Name = IndexResult->Name;1986 C.RankedIncludeHeaders = getRankedIncludes(*C.IndexResult);1987 } else if (C.SemaResult) {1988 C.Name = Recorder->getName(*SemaResult);1989 } else {1990 assert(IdentifierResult);1991 C.Name = IdentifierResult->Name;1992 }1993 if (auto OverloadSet = C.overloadSet(1994 Opts, FileName, Inserter ? &*Inserter : nullptr, CCContextKind)) {1995 auto Ret = BundleLookup.try_emplace(OverloadSet, Bundles.size());1996 if (Ret.second)1997 Bundles.emplace_back();1998 Bundles[Ret.first->second].push_back(std::move(C));1999 } else {2000 Bundles.emplace_back();2001 Bundles.back().push_back(std::move(C));2002 }2003 };2004 llvm::DenseSet<const Symbol *> UsedIndexResults;2005 auto CorrespondingIndexResult =2006 [&](const CodeCompletionResult &SemaResult) -> const Symbol * {2007 if (auto SymID =2008 getSymbolID(SemaResult, Recorder->CCSema->getSourceManager())) {2009 auto I = IndexResults.find(SymID);2010 if (I != IndexResults.end()) {2011 UsedIndexResults.insert(&*I);2012 return &*I;2013 }2014 }2015 return nullptr;2016 };2017 // Emit all Sema results, merging them with Index results if possible.2018 for (auto &SemaResult : SemaResults)2019 AddToBundles(&SemaResult, CorrespondingIndexResult(SemaResult), nullptr);2020 // Now emit any Index-only results.2021 for (const auto &IndexResult : IndexResults) {2022 if (UsedIndexResults.count(&IndexResult))2023 continue;2024 if (!includeSymbolFromIndex(CCContextKind, IndexResult))2025 continue;2026 AddToBundles(/*SemaResult=*/nullptr, &IndexResult, nullptr);2027 }2028 // Emit identifier results.2029 for (const auto &Ident : IdentifierResults)2030 AddToBundles(/*SemaResult=*/nullptr, /*IndexResult=*/nullptr, &Ident);2031 // We only keep the best N results at any time, in "native" format.2032 TopN<ScoredBundle, ScoredBundleGreater> Top(2033 Opts.Limit == 0 ? std::numeric_limits<size_t>::max() : Opts.Limit);2034 for (auto &Bundle : Bundles)2035 addCandidate(Top, std::move(Bundle));2036 return std::move(Top).items();2037 }2038 2039 std::optional<float> fuzzyScore(const CompletionCandidate &C) {2040 // Macros can be very spammy, so we only support prefix completion.2041 if (((C.SemaResult &&2042 C.SemaResult->Kind == CodeCompletionResult::RK_Macro) ||2043 (C.IndexResult &&2044 C.IndexResult->SymInfo.Kind == index::SymbolKind::Macro)) &&2045 !C.Name.starts_with_insensitive(Filter->pattern()))2046 return std::nullopt;2047 return Filter->match(C.Name);2048 }2049 2050 CodeCompletion::Scores2051 evaluateCompletion(const SymbolQualitySignals &Quality,2052 const SymbolRelevanceSignals &Relevance) {2053 using RM = CodeCompleteOptions::CodeCompletionRankingModel;2054 CodeCompletion::Scores Scores;2055 switch (Opts.RankingModel) {2056 case RM::Heuristics:2057 Scores.Quality = Quality.evaluateHeuristics();2058 Scores.Relevance = Relevance.evaluateHeuristics();2059 Scores.Total =2060 evaluateSymbolAndRelevance(Scores.Quality, Scores.Relevance);2061 // NameMatch is in fact a multiplier on total score, so rescoring is2062 // sound.2063 Scores.ExcludingName =2064 Relevance.NameMatch > std::numeric_limits<float>::epsilon()2065 ? Scores.Total / Relevance.NameMatch2066 : Scores.Quality;2067 return Scores;2068 2069 case RM::DecisionForest:2070 DecisionForestScores DFScores = Opts.DecisionForestScorer(2071 Quality, Relevance, Opts.DecisionForestBase);2072 Scores.ExcludingName = DFScores.ExcludingName;2073 Scores.Total = DFScores.Total;2074 return Scores;2075 }2076 llvm_unreachable("Unhandled CodeCompletion ranking model.");2077 }2078 2079 // Scores a candidate and adds it to the TopN structure.2080 void addCandidate(TopN<ScoredBundle, ScoredBundleGreater> &Candidates,2081 CompletionCandidate::Bundle Bundle) {2082 SymbolQualitySignals Quality;2083 SymbolRelevanceSignals Relevance;2084 Relevance.Context = CCContextKind;2085 Relevance.Name = Bundle.front().Name;2086 Relevance.FilterLength = HeuristicPrefix.Name.size();2087 Relevance.Query = SymbolRelevanceSignals::CodeComplete;2088 Relevance.FileProximityMatch = &*FileProximity;2089 if (ScopeProximity)2090 Relevance.ScopeProximityMatch = &*ScopeProximity;2091 if (PreferredType)2092 Relevance.HadContextType = true;2093 Relevance.ContextWords = &ContextWords;2094 Relevance.MainFileSignals = Opts.MainFileSignals;2095 2096 auto &First = Bundle.front();2097 if (auto FuzzyScore = fuzzyScore(First))2098 Relevance.NameMatch = *FuzzyScore;2099 else2100 return;2101 SymbolOrigin Origin = SymbolOrigin::Unknown;2102 bool FromIndex = false;2103 for (const auto &Candidate : Bundle) {2104 if (Candidate.IndexResult) {2105 Quality.merge(*Candidate.IndexResult);2106 Relevance.merge(*Candidate.IndexResult);2107 Origin |= Candidate.IndexResult->Origin;2108 FromIndex = true;2109 if (!Candidate.IndexResult->Type.empty())2110 Relevance.HadSymbolType |= true;2111 if (PreferredType &&2112 PreferredType->raw() == Candidate.IndexResult->Type) {2113 Relevance.TypeMatchesPreferred = true;2114 }2115 }2116 if (Candidate.SemaResult) {2117 Quality.merge(*Candidate.SemaResult);2118 Relevance.merge(*Candidate.SemaResult);2119 if (PreferredType) {2120 if (auto CompletionType = OpaqueType::fromCompletionResult(2121 Recorder->CCSema->getASTContext(), *Candidate.SemaResult)) {2122 Relevance.HadSymbolType |= true;2123 if (PreferredType == CompletionType)2124 Relevance.TypeMatchesPreferred = true;2125 }2126 }2127 Origin |= SymbolOrigin::AST;2128 }2129 if (Candidate.IdentifierResult) {2130 Quality.References = Candidate.IdentifierResult->References;2131 Relevance.Scope = SymbolRelevanceSignals::FileScope;2132 Origin |= SymbolOrigin::Identifier;2133 }2134 }2135 2136 CodeCompletion::Scores Scores = evaluateCompletion(Quality, Relevance);2137 if (Opts.RecordCCResult)2138 Opts.RecordCCResult(toCodeCompletion(Bundle), Quality, Relevance,2139 Scores.Total);2140 2141 dlog("CodeComplete: {0} ({1}) = {2}\n{3}{4}\n", First.Name,2142 llvm::to_string(Origin), Scores.Total, llvm::to_string(Quality),2143 llvm::to_string(Relevance));2144 2145 NSema += bool(Origin & SymbolOrigin::AST);2146 NIndex += FromIndex;2147 NSemaAndIndex += bool(Origin & SymbolOrigin::AST) && FromIndex;2148 NIdent += bool(Origin & SymbolOrigin::Identifier);2149 if (Candidates.push({std::move(Bundle), Scores}))2150 Incomplete = true;2151 }2152 2153 CodeCompletion toCodeCompletion(const CompletionCandidate::Bundle &Bundle) {2154 std::optional<CodeCompletionBuilder> Builder;2155 for (const auto &Item : Bundle) {2156 CodeCompletionString *SemaCCS =2157 Item.SemaResult ? Recorder->codeCompletionString(*Item.SemaResult)2158 : nullptr;2159 if (!Builder)2160 Builder.emplace(Recorder ? &Recorder->CCSema->getASTContext() : nullptr,2161 Item, SemaCCS, AccessibleScopes, *Inserter, FileName,2162 CCContextKind, Opts, IsUsingDeclaration, NextTokenKind);2163 else2164 Builder->add(Item, SemaCCS, CCContextKind);2165 }2166 return Builder->build();2167 }2168};2169 2170} // namespace2171 2172clang::CodeCompleteOptions CodeCompleteOptions::getClangCompleteOpts() const {2173 clang::CodeCompleteOptions Result;2174 Result.IncludeCodePatterns =2175 EnableSnippets && (CodePatterns != Config::CodePatternsPolicy::None);2176 Result.IncludeMacros = true;2177 Result.IncludeGlobals = true;2178 // We choose to include full comments and not do doxygen parsing in2179 // completion.2180 // FIXME: ideally, we should support doxygen in some form, e.g. do markdown2181 // formatting of the comments.2182 Result.IncludeBriefComments = false;2183 2184 // When an is used, Sema is responsible for completing the main file,2185 // the index can provide results from the preamble.2186 // Tell Sema not to deserialize the preamble to look for results.2187 Result.LoadExternal = ForceLoadPreamble || !Index;2188 Result.IncludeFixIts = IncludeFixIts;2189 2190 return Result;2191}2192 2193CompletionPrefix guessCompletionPrefix(llvm::StringRef Content,2194 unsigned Offset) {2195 assert(Offset <= Content.size());2196 StringRef Rest = Content.take_front(Offset);2197 CompletionPrefix Result;2198 2199 // Consume the unqualified name. We only handle ASCII characters.2200 // isAsciiIdentifierContinue will let us match "0invalid", but we don't mind.2201 while (!Rest.empty() && isAsciiIdentifierContinue(Rest.back()))2202 Rest = Rest.drop_back();2203 Result.Name = Content.slice(Rest.size(), Offset);2204 2205 // Consume qualifiers.2206 while (Rest.consume_back("::") && !Rest.ends_with(":")) // reject ::::2207 while (!Rest.empty() && isAsciiIdentifierContinue(Rest.back()))2208 Rest = Rest.drop_back();2209 Result.Qualifier =2210 Content.slice(Rest.size(), Result.Name.begin() - Content.begin());2211 2212 return Result;2213}2214 2215// Code complete the argument name on "/*" inside function call.2216// Offset should be pointing to the start of the comment, i.e.:2217// foo(^/*, rather than foo(/*^) where the cursor probably is.2218CodeCompleteResult codeCompleteComment(PathRef FileName, unsigned Offset,2219 llvm::StringRef Prefix,2220 const PreambleData *Preamble,2221 const ParseInputs &ParseInput) {2222 if (Preamble == nullptr) // Can't run without Sema.2223 return CodeCompleteResult();2224 2225 clang::CodeCompleteOptions Options;2226 Options.IncludeGlobals = false;2227 Options.IncludeMacros = false;2228 Options.IncludeCodePatterns = false;2229 Options.IncludeBriefComments = false;2230 std::set<std::string> ParamNames;2231 // We want to see signatures coming from newly introduced includes, hence a2232 // full patch.2233 semaCodeComplete(2234 std::make_unique<ParamNameCollector>(Options, ParamNames), Options,2235 {FileName, Offset, *Preamble,2236 PreamblePatch::createFullPatch(FileName, ParseInput, *Preamble),2237 ParseInput});2238 if (ParamNames.empty())2239 return CodeCompleteResult();2240 2241 CodeCompleteResult Result;2242 Range CompletionRange;2243 // Skip /*2244 Offset += 2;2245 CompletionRange.start = offsetToPosition(ParseInput.Contents, Offset);2246 CompletionRange.end =2247 offsetToPosition(ParseInput.Contents, Offset + Prefix.size());2248 Result.CompletionRange = CompletionRange;2249 Result.Context = CodeCompletionContext::CCC_NaturalLanguage;2250 for (llvm::StringRef Name : ParamNames) {2251 if (!Name.starts_with(Prefix))2252 continue;2253 CodeCompletion Item;2254 Item.Name = Name.str() + "=*/";2255 Item.FilterText = Item.Name;2256 Item.Kind = CompletionItemKind::Text;2257 Item.CompletionTokenRange = CompletionRange;2258 Item.Origin = SymbolOrigin::AST;2259 Result.Completions.push_back(Item);2260 }2261 2262 return Result;2263}2264 2265// If Offset is inside what looks like argument comment (e.g.2266// "/*^" or "/* foo^"), returns new offset pointing to the start of the /*2267// (place where semaCodeComplete should run).2268std::optional<unsigned>2269maybeFunctionArgumentCommentStart(llvm::StringRef Content) {2270 while (!Content.empty() && isAsciiIdentifierContinue(Content.back()))2271 Content = Content.drop_back();2272 Content = Content.rtrim();2273 if (Content.ends_with("/*"))2274 return Content.size() - 2;2275 return std::nullopt;2276}2277 2278CodeCompleteResult codeComplete(PathRef FileName, Position Pos,2279 const PreambleData *Preamble,2280 const ParseInputs &ParseInput,2281 CodeCompleteOptions Opts,2282 SpeculativeFuzzyFind *SpecFuzzyFind) {2283 auto Offset = positionToOffset(ParseInput.Contents, Pos);2284 if (!Offset) {2285 elog("Code completion position was invalid {0}", Offset.takeError());2286 return CodeCompleteResult();2287 }2288 2289 auto Content = llvm::StringRef(ParseInput.Contents).take_front(*Offset);2290 if (auto OffsetBeforeComment = maybeFunctionArgumentCommentStart(Content)) {2291 // We are doing code completion of a comment, where we currently only2292 // support completing param names in function calls. To do this, we2293 // require information from Sema, but Sema's comment completion stops at2294 // parsing, so we must move back the position before running it, extract2295 // information we need and construct completion items ourselves.2296 auto CommentPrefix = Content.substr(*OffsetBeforeComment + 2).trim();2297 return codeCompleteComment(FileName, *OffsetBeforeComment, CommentPrefix,2298 Preamble, ParseInput);2299 }2300 2301 auto Flow = CodeCompleteFlow(2302 FileName, Preamble ? Preamble->Includes : IncludeStructure(),2303 SpecFuzzyFind, Opts);2304 return (!Preamble || Opts.RunParser == CodeCompleteOptions::NeverParse)2305 ? std::move(Flow).runWithoutSema(ParseInput.Contents, *Offset,2306 *ParseInput.TFS)2307 : std::move(Flow).run({FileName, *Offset, *Preamble,2308 /*PreamblePatch=*/2309 PreamblePatch::createMacroPatch(2310 FileName, ParseInput, *Preamble),2311 ParseInput});2312}2313 2314SignatureHelp signatureHelp(PathRef FileName, Position Pos,2315 const PreambleData &Preamble,2316 const ParseInputs &ParseInput,2317 MarkupKind DocumentationFormat) {2318 auto Offset = positionToOffset(ParseInput.Contents, Pos);2319 if (!Offset) {2320 elog("Signature help position was invalid {0}", Offset.takeError());2321 return SignatureHelp();2322 }2323 SignatureHelp Result;2324 clang::CodeCompleteOptions Options;2325 Options.IncludeGlobals = false;2326 Options.IncludeMacros = false;2327 Options.IncludeCodePatterns = false;2328 Options.IncludeBriefComments = false;2329 semaCodeComplete(2330 std::make_unique<SignatureHelpCollector>(Options, DocumentationFormat,2331 ParseInput.Index, Result),2332 Options,2333 {FileName, *Offset, Preamble,2334 PreamblePatch::createFullPatch(FileName, ParseInput, Preamble),2335 ParseInput});2336 return Result;2337}2338 2339bool isIndexedForCodeCompletion(const NamedDecl &ND, ASTContext &ASTCtx) {2340 auto InTopLevelScope = [](const NamedDecl &ND) {2341 switch (ND.getDeclContext()->getDeclKind()) {2342 case Decl::TranslationUnit:2343 case Decl::Namespace:2344 case Decl::LinkageSpec:2345 return true;2346 default:2347 break;2348 };2349 return false;2350 };2351 auto InClassScope = [](const NamedDecl &ND) {2352 return ND.getDeclContext()->getDeclKind() == Decl::CXXRecord;2353 };2354 // We only complete symbol's name, which is the same as the name of the2355 // *primary* template in case of template specializations.2356 if (isExplicitTemplateSpecialization(&ND))2357 return false;2358 2359 // Category decls are not useful on their own outside the interface or2360 // implementation blocks. Moreover, sema already provides completion for2361 // these, even if it requires preamble deserialization. So by excluding them2362 // from the index, we reduce the noise in all the other completion scopes.2363 if (llvm::isa<ObjCCategoryDecl>(&ND) || llvm::isa<ObjCCategoryImplDecl>(&ND))2364 return false;2365 2366 if (InTopLevelScope(ND))2367 return true;2368 2369 // Always index enum constants, even if they're not in the top level scope:2370 // when2371 // --all-scopes-completion is set, we'll want to complete those as well.2372 if (const auto *EnumDecl = dyn_cast<clang::EnumDecl>(ND.getDeclContext()))2373 return (InTopLevelScope(*EnumDecl) || InClassScope(*EnumDecl));2374 2375 return false;2376}2377 2378CompletionItem CodeCompletion::render(const CodeCompleteOptions &Opts) const {2379 CompletionItem LSP;2380 const auto *InsertInclude = Includes.empty() ? nullptr : &Includes[0];2381 // We could move our indicators from label into labelDetails->description.2382 // In VSCode there are rendering issues that prevent these being aligned.2383 LSP.label = ((InsertInclude && InsertInclude->Insertion)2384 ? Opts.IncludeIndicator.Insert2385 : Opts.IncludeIndicator.NoInsert) +2386 (Opts.ShowOrigins ? "[" + llvm::to_string(Origin) + "]" : "") +2387 RequiredQualifier + Name;2388 LSP.labelDetails.emplace();2389 LSP.labelDetails->detail = Signature;2390 2391 LSP.kind = Kind;2392 LSP.detail = BundleSize > 12393 ? std::string(llvm::formatv("[{0} overloads]", BundleSize))2394 : ReturnType;2395 LSP.deprecated = Deprecated;2396 // Combine header information and documentation in LSP `documentation` field.2397 // This is not quite right semantically, but tends to display well in editors.2398 if (InsertInclude || Documentation) {2399 markup::Document Doc;2400 if (InsertInclude)2401 Doc.addParagraph().appendText("From ").appendCode(InsertInclude->Header);2402 if (Documentation)2403 Doc.append(*Documentation);2404 LSP.documentation = renderDoc(Doc, Opts.DocumentationFormat);2405 }2406 LSP.sortText = sortText(Score.Total, FilterText);2407 LSP.filterText = FilterText;2408 LSP.textEdit = {CompletionTokenRange, RequiredQualifier + Name, ""};2409 // Merge continuous additionalTextEdits into main edit. The main motivation2410 // behind this is to help LSP clients, it seems most of them are confused when2411 // they are provided with additionalTextEdits that are consecutive to main2412 // edit.2413 // Note that we store additional text edits from back to front in a line. That2414 // is mainly to help LSP clients again, so that changes do not effect each2415 // other.2416 for (const auto &FixIt : FixIts) {2417 if (FixIt.range.end == LSP.textEdit->range.start) {2418 LSP.textEdit->newText = FixIt.newText + LSP.textEdit->newText;2419 LSP.textEdit->range.start = FixIt.range.start;2420 } else {2421 LSP.additionalTextEdits.push_back(FixIt);2422 }2423 }2424 if (Opts.EnableSnippets)2425 LSP.textEdit->newText += SnippetSuffix;2426 2427 // FIXME(kadircet): Do not even fill insertText after making sure textEdit is2428 // compatible with most of the editors.2429 LSP.insertText = LSP.textEdit->newText;2430 // Some clients support snippets but work better with plaintext.2431 // So if the snippet is trivial, let the client know.2432 // https://github.com/clangd/clangd/issues/9222433 LSP.insertTextFormat = (Opts.EnableSnippets && !SnippetSuffix.empty())2434 ? InsertTextFormat::Snippet2435 : InsertTextFormat::PlainText;2436 if (InsertInclude && InsertInclude->Insertion)2437 LSP.additionalTextEdits.push_back(*InsertInclude->Insertion);2438 2439 LSP.score = Score.ExcludingName;2440 2441 return LSP;2442}2443 2444llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const CodeCompletion &C) {2445 OS << "Signature: " << "\"" << C.Signature << "\", "2446 << "SnippetSuffix: " << "\"" << C.SnippetSuffix << "\""2447 << ", Rendered:";2448 // For now just lean on CompletionItem.2449 return OS << C.render(CodeCompleteOptions());2450}2451 2452llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,2453 const CodeCompleteResult &R) {2454 OS << "CodeCompleteResult: " << R.Completions.size() << (R.HasMore ? "+" : "")2455 << " (" << getCompletionKindString(R.Context) << ")"2456 << " items:\n";2457 for (const auto &C : R.Completions)2458 OS << C << "\n";2459 return OS;2460}2461 2462// Heuristically detect whether the `Line` is an unterminated include filename.2463bool isIncludeFile(llvm::StringRef Line) {2464 Line = Line.ltrim();2465 if (!Line.consume_front("#"))2466 return false;2467 Line = Line.ltrim();2468 if (!(Line.consume_front("include_next") || Line.consume_front("include") ||2469 Line.consume_front("import")))2470 return false;2471 Line = Line.ltrim();2472 if (Line.consume_front("<"))2473 return Line.count('>') == 0;2474 if (Line.consume_front("\""))2475 return Line.count('"') == 0;2476 return false;2477}2478 2479bool allowImplicitCompletion(llvm::StringRef Content, unsigned Offset) {2480 // Look at last line before completion point only.2481 Content = Content.take_front(Offset);2482 auto Pos = Content.rfind('\n');2483 if (Pos != llvm::StringRef::npos)2484 Content = Content.substr(Pos + 1);2485 2486 // Complete after scope operators.2487 if (Content.ends_with(".") || Content.ends_with("->") ||2488 Content.ends_with("::") || Content.ends_with("/*"))2489 return true;2490 // Complete after `#include <` and #include `<foo/`.2491 if ((Content.ends_with("<") || Content.ends_with("\"") ||2492 Content.ends_with("/")) &&2493 isIncludeFile(Content))2494 return true;2495 2496 // Complete words. Give non-ascii characters the benefit of the doubt.2497 return !Content.empty() && (isAsciiIdentifierContinue(Content.back()) ||2498 !llvm::isASCII(Content.back()));2499}2500 2501} // namespace clangd2502} // namespace clang2503