//===--- CodeComplete.cpp ----------------------------------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Code completion has several moving parts:
//  - AST-based completions are provided using the completion hooks in Sema.
//  - external completions are retrieved from the index (using hints from Sema)
//  - the two sources overlap, and must be merged and overloads bundled
//  - results must be scored and ranked (see Quality.h) before rendering
//
// Signature help works in a similar way as code completion, but it is simpler:
// it's purely AST-based, and there are few candidates.
//
//===----------------------------------------------------------------------===//

#include "CodeComplete.h"
#include "AST.h"
#include "CodeCompletionStrings.h"
#include "Compiler.h"
#include "Config.h"
#include "ExpectedTypes.h"
#include "Feature.h"
#include "FileDistance.h"
#include "FuzzyMatch.h"
#include "Headers.h"
#include "Hover.h"
#include "Preamble.h"
#include "Protocol.h"
#include "Quality.h"
#include "SourceCode.h"
#include "URI.h"
#include "index/Index.h"
#include "index/Symbol.h"
#include "index/SymbolOrigin.h"
#include "support/Logger.h"
#include "support/Markup.h"
#include "support/Threading.h"
#include "support/ThreadsafeFS.h"
#include "support/Trace.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Format/Format.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Sema.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/ScopedPrinter.h"
#include <algorithm>
#include <iterator>
#include <limits>
#include <optional>
#include <utility>

// We log detailed candidate here if you run with -debug-only=codecomplete.
#define DEBUG_TYPE "CodeComplete"

namespace clang {
namespace clangd {

#if CLANGD_DECISION_FOREST
const CodeCompleteOptions::CodeCompletionRankingModel
    CodeCompleteOptions::DefaultRankingModel =
        CodeCompleteOptions::DecisionForest;
#else
const CodeCompleteOptions::CodeCompletionRankingModel
    CodeCompleteOptions::DefaultRankingModel = CodeCompleteOptions::Heuristics;
#endif

namespace {

// Note: changes to this function should also be reflected in the
// CodeCompletionResult overload where appropriate.
CompletionItemKind
toCompletionItemKind(index::SymbolKind Kind,
                     const llvm::StringRef *Signature = nullptr) {
  using SK = index::SymbolKind;
  switch (Kind) {
  // FIXME: for backwards compatibility, the include directive kind is treated
  // the same as Unknown
  case SK::IncludeDirective:
  case SK::Unknown:
    return CompletionItemKind::Missing;
  case SK::Module:
  case SK::Namespace:
  case SK::NamespaceAlias:
    return CompletionItemKind::Module;
  case SK::Macro:
    // Use macro signature (if provided) to tell apart function-like and
    // object-like macros.
    return Signature && Signature->contains('(') ? CompletionItemKind::Function
                                                 : CompletionItemKind::Constant;
  case SK::Enum:
    return CompletionItemKind::Enum;
  case SK::Struct:
    return CompletionItemKind::Struct;
  case SK::Class:
  case SK::Extension:
  case SK::Union:
    return CompletionItemKind::Class;
  case SK::Protocol:
    // Use interface instead of class for differentiation of classes and
    // protocols with the same name (e.g. @interface NSObject vs. @protocol
    // NSObject).
    return CompletionItemKind::Interface;
  case SK::TypeAlias:
    // We use the same kind as the VSCode C++ extension.
    // FIXME: pick a better option when we have one.
    return CompletionItemKind::Interface;
  case SK::Using:
    return CompletionItemKind::Reference;
  case SK::Function:
  case SK::ConversionFunction:
    return CompletionItemKind::Function;
  case SK::Variable:
  case SK::Parameter:
  case SK::NonTypeTemplateParm:
    return CompletionItemKind::Variable;
  case SK::Field:
    return CompletionItemKind::Field;
  case SK::EnumConstant:
    return CompletionItemKind::EnumMember;
  case SK::InstanceMethod:
  case SK::ClassMethod:
  case SK::StaticMethod:
  case SK::Destructor:
    return CompletionItemKind::Method;
  case SK::InstanceProperty:
  case SK::ClassProperty:
  case SK::StaticProperty:
    return CompletionItemKind::Property;
  case SK::Constructor:
    return CompletionItemKind::Constructor;
  case SK::TemplateTypeParm:
  case SK::TemplateTemplateParm:
    return CompletionItemKind::TypeParameter;
  case SK::Concept:
    return CompletionItemKind::Interface;
  }
  llvm_unreachable("Unhandled clang::index::SymbolKind.");
}

// Note: changes to this function should also be reflected in the
// index::SymbolKind overload where appropriate.
CompletionItemKind toCompletionItemKind(const CodeCompletionResult &Res,
                                        CodeCompletionContext::Kind CtxKind) {
  if (Res.Declaration)
    return toCompletionItemKind(index::getSymbolInfo(Res.Declaration).Kind);
  if (CtxKind == CodeCompletionContext::CCC_IncludedFile)
    return CompletionItemKind::File;
  switch (Res.Kind) {
  case CodeCompletionResult::RK_Declaration:
    llvm_unreachable("RK_Declaration without Decl");
  case CodeCompletionResult::RK_Keyword:
    return CompletionItemKind::Keyword;
  case CodeCompletionResult::RK_Macro:
    // There is no 'Macro' kind in LSP.
    // Avoid using 'Text' to avoid confusion with client-side word-based
    // completion proposals.
    return Res.MacroDefInfo && Res.MacroDefInfo->isFunctionLike()
               ? CompletionItemKind::Function
               : CompletionItemKind::Constant;
  case CodeCompletionResult::RK_Pattern:
    return CompletionItemKind::Snippet;
  }
  llvm_unreachable("Unhandled CodeCompletionResult::ResultKind.");
}

// FIXME: find a home for this (that can depend on both markup and Protocol).
MarkupContent renderDoc(const markup::Document &Doc, MarkupKind Kind) {
  MarkupContent Result;
  Result.kind = Kind;
  switch (Kind) {
  case MarkupKind::PlainText:
    Result.value.append(Doc.asPlainText());
    break;
  case MarkupKind::Markdown:
    if (Config::current().Documentation.CommentFormat ==
        Config::CommentFormatPolicy::PlainText)
      Result.value.append(Doc.asEscapedMarkdown());
    else
      Result.value.append(Doc.asMarkdown());
    break;
  }
  return Result;
}

Symbol::IncludeDirective insertionDirective(const CodeCompleteOptions &Opts) {
  if (!Opts.ImportInsertions || !Opts.MainFileSignals)
    return Symbol::IncludeDirective::Include;
  return Opts.MainFileSignals->InsertionDirective;
}

// Identifier code completion result.
struct RawIdentifier {
  llvm::StringRef Name;
  unsigned References; // # of usages in file.
};

/// A code completion result, in clang-native form.
/// It may be promoted to a CompletionItem if it's among the top-ranked results.
struct CompletionCandidate {
  llvm::StringRef Name; // Used for filtering and sorting.
  // We may have a result from Sema, from the index, or both.
  const CodeCompletionResult *SemaResult = nullptr;
  const Symbol *IndexResult = nullptr;
  const RawIdentifier *IdentifierResult = nullptr;
  llvm::SmallVector<SymbolInclude, 1> RankedIncludeHeaders;

  // Returns a token identifying the overload set this is part of.
  // 0 indicates it's not part of any overload set.
  size_t overloadSet(const CodeCompleteOptions &Opts, llvm::StringRef FileName,
                     IncludeInserter *Inserter,
                     CodeCompletionContext::Kind CCContextKind) const {
    if (!Opts.BundleOverloads.value_or(false))
      return 0;

    // Depending on the index implementation, we can see different header
    // strings (literal or URI) mapping to the same file. We still want to
    // bundle those, so we must resolve the header to be included here.
    std::string HeaderForHash;
    if (Inserter) {
      if (auto Header = headerToInsertIfAllowed(Opts, CCContextKind)) {
        if (auto HeaderFile = toHeaderFile(*Header, FileName)) {
          if (auto Spelled =
                  Inserter->calculateIncludePath(*HeaderFile, FileName))
            HeaderForHash = *Spelled;
        } else {
          vlog("Code completion header path manipulation failed {0}",
               HeaderFile.takeError());
        }
      }
    }

    llvm::SmallString<256> Scratch;
    if (IndexResult) {
      switch (IndexResult->SymInfo.Kind) {
      case index::SymbolKind::ClassMethod:
      case index::SymbolKind::InstanceMethod:
      case index::SymbolKind::StaticMethod:
#ifndef NDEBUG
        llvm_unreachable("Don't expect members from index in code completion");
#else
        [[fallthrough]];
#endif
      case index::SymbolKind::Function:
        // We can't group overloads together that need different #includes.
        // This could break #include insertion.
        return llvm::hash_combine(
            (IndexResult->Scope + IndexResult->Name).toStringRef(Scratch),
            HeaderForHash);
      default:
        return 0;
      }
    }
    if (SemaResult) {
      // We need to make sure we're consistent with the IndexResult case!
      const NamedDecl *D = SemaResult->Declaration;
      if (!D || !D->isFunctionOrFunctionTemplate())
        return 0;
      {
        llvm::raw_svector_ostream OS(Scratch);
        D->printQualifiedName(OS);
      }
      return llvm::hash_combine(Scratch, HeaderForHash);
    }
    assert(IdentifierResult);
    return 0;
  }

  bool contextAllowsHeaderInsertion(CodeCompletionContext::Kind Kind) const {
    // Explicitly disable insertions for forward declarations since they don't
    // reference the declaration.
    if (Kind == CodeCompletionContext::CCC_ObjCClassForwardDecl)
      return false;
    return true;
  }

  // The best header to include if include insertion is allowed.
  std::optional<llvm::StringRef>
  headerToInsertIfAllowed(const CodeCompleteOptions &Opts,
                          CodeCompletionContext::Kind ContextKind) const {
    if (Opts.InsertIncludes == Config::HeaderInsertionPolicy::NeverInsert ||
        RankedIncludeHeaders.empty() ||
        !contextAllowsHeaderInsertion(ContextKind))
      return std::nullopt;
    if (SemaResult && SemaResult->Declaration) {
      // Avoid inserting new #include if the declaration is found in the current
      // file e.g. the symbol is forward declared.
      auto &SM = SemaResult->Declaration->getASTContext().getSourceManager();
      for (const Decl *RD : SemaResult->Declaration->redecls())
        if (SM.isInMainFile(SM.getExpansionLoc(RD->getBeginLoc())))
          return std::nullopt;
    }
    Symbol::IncludeDirective Directive = insertionDirective(Opts);
    for (const auto &Inc : RankedIncludeHeaders)
      if ((Inc.Directive & Directive) != 0)
        return Inc.Header;
    return std::nullopt;
  }

  using Bundle = llvm::SmallVector<CompletionCandidate, 4>;
};
using ScoredBundle =
    std::pair<CompletionCandidate::Bundle, CodeCompletion::Scores>;
struct ScoredBundleGreater {
  bool operator()(const ScoredBundle &L, const ScoredBundle &R) {
    if (L.second.Total != R.second.Total)
      return L.second.Total > R.second.Total;
    return L.first.front().Name <
           R.first.front().Name; // Earlier name is better.
  }
};

// Remove the first template argument from Signature.
// If Signature only contains a single argument an empty string is returned.
std::string removeFirstTemplateArg(llvm::StringRef Signature) {
  auto Rest = Signature.split(",").second;
  if (Rest.empty())
    return "";
  return ("<" + Rest.ltrim()).str();
}

// Assembles a code completion out of a bundle of >=1 completion candidates.
// Many of the expensive strings are only computed at this point, once we know
// the candidate bundle is going to be returned.
//
// Many fields are the same for all candidates in a bundle (e.g. name), and are
// computed from the first candidate, in the constructor.
// Others vary per candidate, so add() must be called for remaining candidates.
struct CodeCompletionBuilder {
  CodeCompletionBuilder(ASTContext *ASTCtx, const CompletionCandidate &C,
                        CodeCompletionString *SemaCCS,
                        llvm::ArrayRef<std::string> AccessibleScopes,
                        const IncludeInserter &Includes,
                        llvm::StringRef FileName,
                        CodeCompletionContext::Kind ContextKind,
                        const CodeCompleteOptions &Opts,
                        bool IsUsingDeclaration, tok::TokenKind NextTokenKind)
      : ASTCtx(ASTCtx), ArgumentLists(Opts.ArgumentLists),
        IsUsingDeclaration(IsUsingDeclaration), NextTokenKind(NextTokenKind) {
    Completion.Deprecated = true; // cleared by any non-deprecated overload.
    add(C, SemaCCS, ContextKind);
    if (C.SemaResult) {
      assert(ASTCtx);
      Completion.Origin |= SymbolOrigin::AST;
      Completion.Name = std::string(llvm::StringRef(SemaCCS->getTypedText()));
      Completion.FilterText = SemaCCS->getAllTypedText();
      if (Completion.Scope.empty()) {
        if ((C.SemaResult->Kind == CodeCompletionResult::RK_Declaration) ||
            (C.SemaResult->Kind == CodeCompletionResult::RK_Pattern))
          if (const auto *D = C.SemaResult->getDeclaration())
            if (const auto *ND = dyn_cast<NamedDecl>(D))
              Completion.Scope = std::string(
                  splitQualifiedName(printQualifiedName(*ND)).first);
      }
      Completion.Kind = toCompletionItemKind(*C.SemaResult, ContextKind);
      // Sema could provide more info on whether the completion was a file or
      // folder.
      if (Completion.Kind == CompletionItemKind::File &&
          Completion.Name.back() == '/')
        Completion.Kind = CompletionItemKind::Folder;
      for (const auto &FixIt : C.SemaResult->FixIts) {
        Completion.FixIts.push_back(toTextEdit(
            FixIt, ASTCtx->getSourceManager(), ASTCtx->getLangOpts()));
      }
      llvm::sort(Completion.FixIts, [](const TextEdit &X, const TextEdit &Y) {
        return std::tie(X.range.start.line, X.range.start.character) <
               std::tie(Y.range.start.line, Y.range.start.character);
      });
    }
    if (C.IndexResult) {
      Completion.Origin |= C.IndexResult->Origin;
      if (Completion.Scope.empty())
        Completion.Scope = std::string(C.IndexResult->Scope);
      if (Completion.Kind == CompletionItemKind::Missing)
        Completion.Kind = toCompletionItemKind(C.IndexResult->SymInfo.Kind,
                                               &C.IndexResult->Signature);
      if (Completion.Name.empty())
        Completion.Name = std::string(C.IndexResult->Name);
      if (Completion.FilterText.empty())
        Completion.FilterText = Completion.Name;
      // If the completion was visible to Sema, no qualifier is needed. This
      // avoids unneeded qualifiers in cases like with `using ns::X`.
      if (Completion.RequiredQualifier.empty() && !C.SemaResult) {
        llvm::StringRef ShortestQualifier = C.IndexResult->Scope;
        for (llvm::StringRef Scope : AccessibleScopes) {
          llvm::StringRef Qualifier = C.IndexResult->Scope;
          if (Qualifier.consume_front(Scope) &&
              Qualifier.size() < ShortestQualifier.size())
            ShortestQualifier = Qualifier;
        }
        Completion.RequiredQualifier = std::string(ShortestQualifier);
      }
    }
    if (C.IdentifierResult) {
      Completion.Origin |= SymbolOrigin::Identifier;
      Completion.Kind = CompletionItemKind::Text;
      Completion.Name = std::string(C.IdentifierResult->Name);
      Completion.FilterText = Completion.Name;
    }

    // Turn absolute path into a literal string that can be #included.
    auto Inserted = [&](llvm::StringRef Header)
        -> llvm::Expected<std::pair<std::string, bool>> {
      auto ResolvedDeclaring =
          URI::resolve(C.IndexResult->CanonicalDeclaration.FileURI, FileName);
      if (!ResolvedDeclaring)
        return ResolvedDeclaring.takeError();
      auto ResolvedInserted = toHeaderFile(Header, FileName);
      if (!ResolvedInserted)
        return ResolvedInserted.takeError();
      auto Spelled = Includes.calculateIncludePath(*ResolvedInserted, FileName);
      if (!Spelled)
        return error("Header not on include path");
      return std::make_pair(
          std::move(*Spelled),
          Includes.shouldInsertInclude(*ResolvedDeclaring, *ResolvedInserted));
    };
    bool ShouldInsert =
        C.headerToInsertIfAllowed(Opts, ContextKind).has_value();
    Symbol::IncludeDirective Directive = insertionDirective(Opts);
    // Calculate include paths and edits for all possible headers.
    for (const auto &Inc : C.RankedIncludeHeaders) {
      if ((Inc.Directive & Directive) == 0)
        continue;

      if (auto ToInclude = Inserted(Inc.Header)) {
        CodeCompletion::IncludeCandidate Include;
        Include.Header = ToInclude->first;
        if (ToInclude->second && ShouldInsert)
          Include.Insertion = Includes.insert(
              ToInclude->first, Directive == Symbol::Import
                                    ? tooling::IncludeDirective::Import
                                    : tooling::IncludeDirective::Include);
        Completion.Includes.push_back(std::move(Include));
      } else
        log("Failed to generate include insertion edits for adding header "
            "(FileURI='{0}', IncludeHeader='{1}') into {2}: {3}",
            C.IndexResult->CanonicalDeclaration.FileURI, Inc.Header, FileName,
            ToInclude.takeError());
    }
    // Prefer includes that do not need edits (i.e. already exist).
    std::stable_partition(Completion.Includes.begin(),
                          Completion.Includes.end(),
                          [](const CodeCompletion::IncludeCandidate &I) {
                            return !I.Insertion.has_value();
                          });
  }

  void add(const CompletionCandidate &C, CodeCompletionString *SemaCCS,
           CodeCompletionContext::Kind ContextKind) {
    assert(bool(C.SemaResult) == bool(SemaCCS));
    Bundled.emplace_back();
    BundledEntry &S = Bundled.back();
    bool IsConcept = false;
    if (C.SemaResult) {
      getSignature(*SemaCCS, &S.Signature, &S.SnippetSuffix, C.SemaResult->Kind,
                   C.SemaResult->CursorKind,
                   /*IncludeFunctionArguments=*/C.SemaResult->FunctionCanBeCall,
                   /*RequiredQualifiers=*/&Completion.RequiredQualifier);
      S.ReturnType = getReturnType(*SemaCCS);
      if (C.SemaResult->Kind == CodeCompletionResult::RK_Declaration)
        if (const auto *D = C.SemaResult->getDeclaration())
          if (isa<ConceptDecl>(D))
            IsConcept = true;
    } else if (C.IndexResult) {
      S.Signature = std::string(C.IndexResult->Signature);
      S.SnippetSuffix = std::string(C.IndexResult->CompletionSnippetSuffix);
      S.ReturnType = std::string(C.IndexResult->ReturnType);
      if (C.IndexResult->SymInfo.Kind == index::SymbolKind::Concept)
        IsConcept = true;
    }

    /// When a concept is used as a type-constraint (e.g. `Iterator auto x`),
    /// and in some other contexts, its first type argument is not written.
    /// Drop the parameter from the signature.
    if (IsConcept && ContextKind == CodeCompletionContext::CCC_TopLevel) {
      S.Signature = removeFirstTemplateArg(S.Signature);
      // Dropping the first placeholder from the suffix will leave a $2
      // with no $1.
      S.SnippetSuffix = removeFirstTemplateArg(S.SnippetSuffix);
    }

    if (!Completion.Documentation) {
      auto SetDoc = [&](llvm::StringRef Doc) {
        if (!Doc.empty()) {
          Completion.Documentation.emplace();
          parseDocumentation(Doc, *Completion.Documentation);
        }
      };
      if (C.IndexResult) {
        SetDoc(C.IndexResult->Documentation);
      } else if (C.SemaResult) {
        const auto DocComment = getDocComment(*ASTCtx, *C.SemaResult,
                                              /*CommentsFromHeaders=*/false);
        SetDoc(formatDocumentation(*SemaCCS, DocComment));
      }
    }
    if (Completion.Deprecated) {
      if (C.SemaResult)
        Completion.Deprecated &=
            C.SemaResult->Availability == CXAvailability_Deprecated;
      if (C.IndexResult)
        Completion.Deprecated &=
            bool(C.IndexResult->Flags & Symbol::Deprecated);
    }
  }

  CodeCompletion build() {
    Completion.ReturnType = summarizeReturnType();
    Completion.Signature = summarizeSignature();
    Completion.SnippetSuffix = summarizeSnippet();
    Completion.BundleSize = Bundled.size();
    return std::move(Completion);
  }

private:
  struct BundledEntry {
    std::string SnippetSuffix;
    std::string Signature;
    std::string ReturnType;
  };

  // If all BundledEntries have the same value for a property, return it.
  template <std::string BundledEntry::*Member>
  const std::string *onlyValue() const {
    auto B = Bundled.begin(), E = Bundled.end();
    for (auto *I = B + 1; I != E; ++I)
      if (I->*Member != B->*Member)
        return nullptr;
    return &(B->*Member);
  }

  template <bool BundledEntry::*Member> const bool *onlyValue() const {
    auto B = Bundled.begin(), E = Bundled.end();
    for (auto *I = B + 1; I != E; ++I)
      if (I->*Member != B->*Member)
        return nullptr;
    return &(B->*Member);
  }

  std::string summarizeReturnType() const {
    if (auto *RT = onlyValue<&BundledEntry::ReturnType>())
      return *RT;
    return "";
  }

  std::string summarizeSnippet() const {
    /// localize ArgumentLists tests for better readability
    const bool None = ArgumentLists == Config::ArgumentListsPolicy::None;
    const bool Open =
        ArgumentLists == Config::ArgumentListsPolicy::OpenDelimiter;
    const bool Delim = ArgumentLists == Config::ArgumentListsPolicy::Delimiters;
    const bool Full =
        ArgumentLists == Config::ArgumentListsPolicy::FullPlaceholders ||
        (!None && !Open && !Delim); // <-- failsafe: Full is default

    if (IsUsingDeclaration)
      return "";
    auto *Snippet = onlyValue<&BundledEntry::SnippetSuffix>();
    if (!Snippet)
      // All bundles are function calls.
      // FIXME(ibiryukov): sometimes add template arguments to a snippet, e.g.
      // we need to complete 'forward<$1>($0)'.
      return None ? "" : (Open ? "(" : "($0)");

    if (Snippet->empty())
      return "";

    bool MayHaveArgList = Completion.Kind == CompletionItemKind::Function ||
                          Completion.Kind == CompletionItemKind::Method ||
                          Completion.Kind == CompletionItemKind::Constructor ||
                          Completion.Kind == CompletionItemKind::Text /*Macro*/;
    // If likely arg list already exists, don't add new parens & placeholders.
    //   Snippet: function(int x, int y)
    //   func^(1,2) -> function(1, 2)
    //             NOT function(int x, int y)(1, 2)
    if (MayHaveArgList) {
      // Check for a template argument list in the code.
      //   Snippet: function<class T>(int x)
      //   fu^<int>(1) -> function<int>(1)
      if (NextTokenKind == tok::less && Snippet->front() == '<')
        return "";
      // Potentially followed by regular argument list.
      if (NextTokenKind == tok::l_paren) {
        //   Snippet: function<class T>(int x)
        //   fu^(1,2) -> function<class T>(1, 2)
        if (Snippet->front() == '<') {
          // Find matching '>', handling nested brackets.
          int Balance = 0;
          size_t I = 0;
          do {
            if (Snippet->at(I) == '>')
              --Balance;
            else if (Snippet->at(I) == '<')
              ++Balance;
            ++I;
          } while (Balance > 0);
          return Snippet->substr(0, I);
        }
        return "";
      }
    }
    if (Full)
      return *Snippet;

    // Replace argument snippets with a simplified pattern.
    if (MayHaveArgList) {
      // Functions snippets can be of 2 types:
      // - containing only function arguments, e.g.
      //   foo(${1:int p1}, ${2:int p2});
      //   We transform this pattern to '($0)' or '()'.
      // - template arguments and function arguments, e.g.
      //   foo<${1:class}>(${2:int p1}).
      //   We transform this pattern to '<$1>()$0' or '<$0>()'.

      bool EmptyArgs = llvm::StringRef(*Snippet).ends_with("()");
      if (Snippet->front() == '<')
        return None ? "" : (Open ? "<" : (EmptyArgs ? "<$1>()$0" : "<$1>($0)"));
      if (Snippet->front() == '(')
        return None ? "" : (Open ? "(" : (EmptyArgs ? "()" : "($0)"));
      return *Snippet; // Not an arg snippet?
    }
    // 'CompletionItemKind::Interface' matches template type aliases.
    if (Completion.Kind == CompletionItemKind::Interface ||
        Completion.Kind == CompletionItemKind::Class ||
        Completion.Kind == CompletionItemKind::Variable) {
      if (Snippet->front() != '<')
        return *Snippet; // Not an arg snippet?

      // Classes and template using aliases can only have template arguments,
      // e.g. Foo<${1:class}>.
      if (llvm::StringRef(*Snippet).ends_with("<>"))
        return "<>"; // can happen with defaulted template arguments.
      return None ? "" : (Open ? "<" : "<$0>");
    }
    return *Snippet;
  }

  std::string summarizeSignature() const {
    if (auto *Signature = onlyValue<&BundledEntry::Signature>())
      return *Signature;
    // All bundles are function calls.
    return "(…)";
  }

  // ASTCtx can be nullptr if not run with sema.
  ASTContext *ASTCtx;
  CodeCompletion Completion;
  llvm::SmallVector<BundledEntry, 1> Bundled;
  /// the way argument lists are handled.
  Config::ArgumentListsPolicy ArgumentLists;
  // No snippets will be generated for using declarations and when the function
  // arguments are already present.
  bool IsUsingDeclaration;
  tok::TokenKind NextTokenKind;
};

// Determine the symbol ID for a Sema code completion result, if possible.
SymbolID getSymbolID(const CodeCompletionResult &R, const SourceManager &SM) {
  switch (R.Kind) {
  case CodeCompletionResult::RK_Declaration:
  case CodeCompletionResult::RK_Pattern: {
    // Computing USR caches linkage, which may change after code completion.
    if (hasUnstableLinkage(R.Declaration))
      return {};
    return clang::clangd::getSymbolID(R.Declaration);
  }
  case CodeCompletionResult::RK_Macro:
    return clang::clangd::getSymbolID(R.Macro->getName(), R.MacroDefInfo, SM);
  case CodeCompletionResult::RK_Keyword:
    return {};
  }
  llvm_unreachable("unknown CodeCompletionResult kind");
}

// Scopes of the partial identifier we're trying to complete.
// It is used when we query the index for more completion results.
struct SpecifiedScope {
  // The scopes we should look in, determined by Sema.
  //
  // If the qualifier was fully resolved, we look for completions in these
  // scopes; if there is an unresolved part of the qualifier, it should be
  // resolved within these scopes.
  //
  // Examples of qualified completion:
  //
  //   "::vec"                                      => {""}
  //   "using namespace std; ::vec^"                => {"", "std::"}
  //   "namespace ns {using namespace std;} ns::^"  => {"ns::", "std::"}
  //   "std::vec^"                                  => {""}  // "std" unresolved
  //
  // Examples of unqualified completion:
  //
  //   "vec^"                                        => {""}
  //   "using namespace std; vec^"                   => {"", "std::"}
  //   "namespace ns {inline namespace ni { struct Foo {}}}
  //    using namespace ns::ni; Fo^ "                => {"", "ns::ni::"}
  //   "using namespace std; namespace ns { vec^ }"  => {"ns::", "std::", ""}
  //
  // "" for global namespace, "ns::" for normal namespace.
  std::vector<std::string> AccessibleScopes;
  // This is an overestimate of AccessibleScopes, e.g. it ignores inline
  // namespaces, to fetch more relevant symbols from index.
  std::vector<std::string> QueryScopes;
  // The full scope qualifier as typed by the user (without the leading "::").
  // Set if the qualifier is not fully resolved by Sema.
  std::optional<std::string> UnresolvedQualifier;

  std::optional<std::string> EnclosingNamespace;

  bool AllowAllScopes = false;

  // Scopes that are accessible from current context. Used for dropping
  // unnecessary namespecifiers.
  std::vector<std::string> scopesForQualification() {
    std::set<std::string> Results;
    for (llvm::StringRef AS : AccessibleScopes)
      Results.insert(
          (AS + (UnresolvedQualifier ? *UnresolvedQualifier : "")).str());
    return {Results.begin(), Results.end()};
  }

  // Construct scopes being queried in indexes. The results are deduplicated.
  // This method formats the scopes to match the index request representation.
  std::vector<std::string> scopesForIndexQuery() {
    // The enclosing namespace must be first, it gets a quality boost.
    std::vector<std::string> EnclosingAtFront;
    if (EnclosingNamespace.has_value())
      EnclosingAtFront.push_back(*EnclosingNamespace);
    std::set<std::string> Deduplicated;
    for (llvm::StringRef S : QueryScopes)
      if (S != EnclosingNamespace)
        Deduplicated.insert((S + UnresolvedQualifier.value_or("")).str());

    EnclosingAtFront.reserve(EnclosingAtFront.size() + Deduplicated.size());
    llvm::copy(Deduplicated, std::back_inserter(EnclosingAtFront));

    return EnclosingAtFront;
  }
};

// Get all scopes that will be queried in indexes and whether symbols from
// any scope is allowed. The first scope in the list is the preferred scope
// (e.g. enclosing namespace).
SpecifiedScope getQueryScopes(CodeCompletionContext &CCContext,
                              const Sema &CCSema,
                              const CompletionPrefix &HeuristicPrefix,
                              const CodeCompleteOptions &Opts) {
  SpecifiedScope Scopes;
  for (auto *Context : CCContext.getVisitedContexts()) {
    if (isa<TranslationUnitDecl>(Context)) {
      Scopes.QueryScopes.push_back("");
      Scopes.AccessibleScopes.push_back("");
    } else if (const auto *ND = dyn_cast<NamespaceDecl>(Context)) {
      Scopes.QueryScopes.push_back(printNamespaceScope(*Context));
      Scopes.AccessibleScopes.push_back(printQualifiedName(*ND) + "::");
    }
  }

  const CXXScopeSpec *SemaSpecifier =
      CCContext.getCXXScopeSpecifier().value_or(nullptr);
  // Case 1: unqualified completion.
  if (!SemaSpecifier) {
    // Case 2 (exception): sema saw no qualifier, but there appears to be one!
    // This can happen e.g. in incomplete macro expansions. Use heuristics.
    if (!HeuristicPrefix.Qualifier.empty()) {
      vlog("Sema said no scope specifier, but we saw {0} in the source code",
           HeuristicPrefix.Qualifier);
      StringRef SpelledSpecifier = HeuristicPrefix.Qualifier;
      if (SpelledSpecifier.consume_front("::")) {
        Scopes.AccessibleScopes = {""};
        Scopes.QueryScopes = {""};
      }
      Scopes.UnresolvedQualifier = std::string(SpelledSpecifier);
      return Scopes;
    }
    /// FIXME: When the enclosing namespace contains an inline namespace,
    /// it's dropped here. This leads to a behavior similar to
    /// https://github.com/clangd/clangd/issues/1451
    Scopes.EnclosingNamespace = printNamespaceScope(*CCSema.CurContext);
    // Allow AllScopes completion as there is no explicit scope qualifier.
    Scopes.AllowAllScopes = Opts.AllScopes;
    return Scopes;
  }
  // Case 3: sema saw and resolved a scope qualifier.
  if (SemaSpecifier && SemaSpecifier->isValid())
    return Scopes;

  // Case 4: There was a qualifier, and Sema didn't resolve it.
  Scopes.QueryScopes.push_back(""); // Make sure global scope is included.
  llvm::StringRef SpelledSpecifier = Lexer::getSourceText(
      CharSourceRange::getCharRange(SemaSpecifier->getRange()),
      CCSema.SourceMgr, clang::LangOptions());
  if (SpelledSpecifier.consume_front("::"))
    Scopes.QueryScopes = {""};
  Scopes.UnresolvedQualifier = std::string(SpelledSpecifier);
  // Sema excludes the trailing "::".
  if (!Scopes.UnresolvedQualifier->empty())
    *Scopes.UnresolvedQualifier += "::";

  Scopes.AccessibleScopes = Scopes.QueryScopes;

  return Scopes;
}

// Should we perform index-based completion in a context of the specified kind?
// FIXME: consider allowing completion, but restricting the result types.
bool contextAllowsIndex(enum CodeCompletionContext::Kind K) {
  switch (K) {
  case CodeCompletionContext::CCC_TopLevel:
  case CodeCompletionContext::CCC_ObjCInterface:
  case CodeCompletionContext::CCC_ObjCImplementation:
  case CodeCompletionContext::CCC_ObjCIvarList:
  case CodeCompletionContext::CCC_ClassStructUnion:
  case CodeCompletionContext::CCC_Statement:
  case CodeCompletionContext::CCC_Expression:
  case CodeCompletionContext::CCC_ObjCMessageReceiver:
  case CodeCompletionContext::CCC_EnumTag:
  case CodeCompletionContext::CCC_UnionTag:
  case CodeCompletionContext::CCC_ClassOrStructTag:
  case CodeCompletionContext::CCC_ObjCProtocolName:
  case CodeCompletionContext::CCC_Namespace:
  case CodeCompletionContext::CCC_Type:
  case CodeCompletionContext::CCC_ParenthesizedExpression:
  case CodeCompletionContext::CCC_ObjCInterfaceName:
  case CodeCompletionContext::CCC_Symbol:
  case CodeCompletionContext::CCC_SymbolOrNewName:
  case CodeCompletionContext::CCC_ObjCClassForwardDecl:
  case CodeCompletionContext::CCC_TopLevelOrExpression:
    return true;
  case CodeCompletionContext::CCC_OtherWithMacros:
  case CodeCompletionContext::CCC_DotMemberAccess:
  case CodeCompletionContext::CCC_ArrowMemberAccess:
  case CodeCompletionContext::CCC_ObjCCategoryName:
  case CodeCompletionContext::CCC_ObjCPropertyAccess:
  case CodeCompletionContext::CCC_MacroName:
  case CodeCompletionContext::CCC_MacroNameUse:
  case CodeCompletionContext::CCC_PreprocessorExpression:
  case CodeCompletionContext::CCC_PreprocessorDirective:
  case CodeCompletionContext::CCC_SelectorName:
  case CodeCompletionContext::CCC_TypeQualifiers:
  case CodeCompletionContext::CCC_ObjCInstanceMessage:
  case CodeCompletionContext::CCC_ObjCClassMessage:
  case CodeCompletionContext::CCC_IncludedFile:
  case CodeCompletionContext::CCC_Attribute:
  // FIXME: Provide identifier based completions for the following contexts:
  case CodeCompletionContext::CCC_Other: // Be conservative.
  case CodeCompletionContext::CCC_NaturalLanguage:
  case CodeCompletionContext::CCC_Recovery:
  case CodeCompletionContext::CCC_NewName:
    return false;
  }
  llvm_unreachable("unknown code completion context");
}

static bool isInjectedClass(const NamedDecl &D) {
  if (auto *R = dyn_cast_or_null<CXXRecordDecl>(&D))
    if (R->isInjectedClassName())
      return true;
  return false;
}

// Some member calls are excluded because they're so rarely useful.
static bool isExcludedMember(const NamedDecl &D) {
  // Destructor completion is rarely useful, and works inconsistently.
  // (s.^ completes ~string, but s.~st^ is an error).
  if (D.getKind() == Decl::CXXDestructor)
    return true;
  // Injected name may be useful for A::foo(), but who writes A::A::foo()?
  if (isInjectedClass(D))
    return true;
  // Explicit calls to operators are also rare.
  auto NameKind = D.getDeclName().getNameKind();
  if (NameKind == DeclarationName::CXXOperatorName ||
      NameKind == DeclarationName::CXXLiteralOperatorName ||
      NameKind == DeclarationName::CXXConversionFunctionName)
    return true;
  return false;
}

// The CompletionRecorder captures Sema code-complete output, including context.
// It filters out ignored results (but doesn't apply fuzzy-filtering yet).
// It doesn't do scoring or conversion to CompletionItem yet, as we want to
// merge with index results first.
// Generally the fields and methods of this object should only be used from
// within the callback.
struct CompletionRecorder : public CodeCompleteConsumer {
  CompletionRecorder(const CodeCompleteOptions &Opts,
                     llvm::unique_function<void()> ResultsCallback)
      : CodeCompleteConsumer(Opts.getClangCompleteOpts()),
        CCContext(CodeCompletionContext::CCC_Other), Opts(Opts),
        CCAllocator(std::make_shared<GlobalCodeCompletionAllocator>()),
        CCTUInfo(CCAllocator), ResultsCallback(std::move(ResultsCallback)) {
    assert(this->ResultsCallback);
  }

  std::vector<CodeCompletionResult> Results;
  CodeCompletionContext CCContext;
  Sema *CCSema = nullptr; // Sema that created the results.
  // FIXME: Sema is scary. Can we store ASTContext and Preprocessor, instead?

  void ProcessCodeCompleteResults(class Sema &S, CodeCompletionContext Context,
                                  CodeCompletionResult *InResults,
                                  unsigned NumResults) final {
    // Results from recovery mode are generally useless, and the callback after
    // recovery (if any) is usually more interesting. To make sure we handle the
    // future callback from sema, we just ignore all callbacks in recovery mode,
    // as taking only results from recovery mode results in poor completion
    // results.
    // FIXME: in case there is no future sema completion callback after the
    // recovery mode, we might still want to provide some results (e.g. trivial
    // identifier-based completion).
    CodeCompletionContext::Kind ContextKind = Context.getKind();
    if (ContextKind == CodeCompletionContext::CCC_Recovery) {
      log("Code complete: Ignoring sema code complete callback with Recovery "
          "context.");
      return;
    }
    // If a callback is called without any sema result and the context does not
    // support index-based completion, we simply skip it to give way to
    // potential future callbacks with results.
    if (NumResults == 0 && !contextAllowsIndex(Context.getKind()))
      return;
    if (CCSema) {
      log("Multiple code complete callbacks (parser backtracked?). "
          "Dropping results from context {0}, keeping results from {1}.",
          getCompletionKindString(Context.getKind()),
          getCompletionKindString(this->CCContext.getKind()));
      return;
    }
    // Record the completion context.
    CCSema = &S;
    CCContext = Context;

    // Retain the results we might want.
    for (unsigned I = 0; I < NumResults; ++I) {
      auto &Result = InResults[I];
      if (Config::current().Completion.CodePatterns ==
              Config::CodePatternsPolicy::None &&
          Result.Kind == CodeCompletionResult::RK_Pattern &&
          // keep allowing the include files autocomplete suggestions
          ContextKind != CodeCompletionContext::CCC_IncludedFile)
        continue;
      // Class members that are shadowed by subclasses are usually noise.
      if (Result.Hidden && Result.Declaration &&
          Result.Declaration->isCXXClassMember())
        continue;
      if (!Opts.IncludeIneligibleResults &&
          (Result.Availability == CXAvailability_NotAvailable ||
           Result.Availability == CXAvailability_NotAccessible))
        continue;
      if (Result.Declaration &&
          !Context.getBaseType().isNull() // is this a member-access context?
          && isExcludedMember(*Result.Declaration))
        continue;
      // Skip injected class name when no class scope is not explicitly set.
      // E.g. show injected A::A in `using A::A^` but not in "A^".
      if (Result.Declaration && !Context.getCXXScopeSpecifier() &&
          isInjectedClass(*Result.Declaration))
        continue;
      // We choose to never append '::' to completion results in clangd.
      Result.StartsNestedNameSpecifier = false;
      Results.push_back(Result);
    }
    ResultsCallback();
  }

  CodeCompletionAllocator &getAllocator() override { return *CCAllocator; }
  CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }

  // Returns the filtering/sorting name for Result, which must be from Results.
  // Returned string is owned by this recorder (or the AST).
  llvm::StringRef getName(const CodeCompletionResult &Result) {
    switch (Result.Kind) {
    case CodeCompletionResult::RK_Declaration:
      if (auto *ID = Result.Declaration->getIdentifier())
        return ID->getName();
      break;
    case CodeCompletionResult::RK_Keyword:
      return Result.Keyword;
    case CodeCompletionResult::RK_Macro:
      return Result.Macro->getName();
    case CodeCompletionResult::RK_Pattern:
      break;
    }
    auto *CCS = codeCompletionString(Result);
    const CodeCompletionString::Chunk *OnlyText = nullptr;
    for (auto &C : *CCS) {
      if (C.Kind != CodeCompletionString::CK_TypedText)
        continue;
      if (OnlyText)
        return CCAllocator->CopyString(CCS->getAllTypedText());
      OnlyText = &C;
    }
    return OnlyText ? OnlyText->Text : llvm::StringRef();
  }

  // Build a CodeCompletion string for R, which must be from Results.
  // The CCS will be owned by this recorder.
  CodeCompletionString *codeCompletionString(const CodeCompletionResult &R) {
    // CodeCompletionResult doesn't seem to be const-correct. We own it, anyway.
    return const_cast<CodeCompletionResult &>(R).CreateCodeCompletionString(
        *CCSema, CCContext, *CCAllocator, CCTUInfo,
        /*IncludeBriefComments=*/false);
  }

private:
  CodeCompleteOptions Opts;
  std::shared_ptr<GlobalCodeCompletionAllocator> CCAllocator;
  CodeCompletionTUInfo CCTUInfo;
  llvm::unique_function<void()> ResultsCallback;
};

struct ScoredSignature {
  // When not null, requires documentation to be requested from the index with
  // this ID.
  SymbolID IDForDoc;
  SignatureInformation Signature;
  SignatureQualitySignals Quality;
};

// Returns the index of the parameter matching argument number "Arg.
// This is usually just "Arg", except for variadic functions/templates, where
// "Arg" might be higher than the number of parameters. When that happens, we
// assume the last parameter is variadic and assume all further args are
// part of it.
int paramIndexForArg(const CodeCompleteConsumer::OverloadCandidate &Candidate,
                     int Arg) {
  int NumParams = Candidate.getNumParams();
  if (auto *T = Candidate.getFunctionType()) {
    if (auto *Proto = T->getAs<FunctionProtoType>()) {
      if (Proto->isVariadic())
        ++NumParams;
    }
  }
  return std::min(Arg, std::max(NumParams - 1, 0));
}

class SignatureHelpCollector final : public CodeCompleteConsumer {
public:
  SignatureHelpCollector(const clang::CodeCompleteOptions &CodeCompleteOpts,
                         MarkupKind DocumentationFormat,
                         const SymbolIndex *Index, SignatureHelp &SigHelp)
      : CodeCompleteConsumer(CodeCompleteOpts), SigHelp(SigHelp),
        Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
        CCTUInfo(Allocator), Index(Index),
        DocumentationFormat(DocumentationFormat) {}

  void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
                                 OverloadCandidate *Candidates,
                                 unsigned NumCandidates,
                                 SourceLocation OpenParLoc,
                                 bool Braced) override {
    assert(!OpenParLoc.isInvalid());
    SourceManager &SrcMgr = S.getSourceManager();
    OpenParLoc = SrcMgr.getFileLoc(OpenParLoc);
    if (SrcMgr.isInMainFile(OpenParLoc))
      SigHelp.argListStart = sourceLocToPosition(SrcMgr, OpenParLoc);
    else
      elog("Location oustide main file in signature help: {0}",
           OpenParLoc.printToString(SrcMgr));

    std::vector<ScoredSignature> ScoredSignatures;
    SigHelp.signatures.reserve(NumCandidates);
    ScoredSignatures.reserve(NumCandidates);
    // FIXME(rwols): How can we determine the "active overload candidate"?
    // Right now the overloaded candidates seem to be provided in a "best fit"
    // order, so I'm not too worried about this.
    SigHelp.activeSignature = 0;
    assert(CurrentArg <= (unsigned)std::numeric_limits<int>::max() &&
           "too many arguments");

    SigHelp.activeParameter = static_cast<int>(CurrentArg);

    for (unsigned I = 0; I < NumCandidates; ++I) {
      OverloadCandidate Candidate = Candidates[I];
      // We want to avoid showing instantiated signatures, because they may be
      // long in some cases (e.g. when 'T' is substituted with 'std::string', we
      // would get 'std::basic_string<char>').
      if (auto *Func = Candidate.getFunction()) {
        if (auto *Pattern = Func->getTemplateInstantiationPattern())
          Candidate = OverloadCandidate(Pattern);
      }
      if (static_cast<int>(I) == SigHelp.activeSignature) {
        // The activeParameter in LSP relates to the activeSignature. There is
        // another, per-signature field, but we currently do not use it and not
        // all clients might support it.
        // FIXME: Add support for per-signature activeParameter field.
        SigHelp.activeParameter =
            paramIndexForArg(Candidate, SigHelp.activeParameter);
      }

      const auto *CCS = Candidate.CreateSignatureString(
          CurrentArg, S, *Allocator, CCTUInfo,
          /*IncludeBriefComments=*/true, Braced);
      assert(CCS && "Expected the CodeCompletionString to be non-null");
      ScoredSignatures.push_back(processOverloadCandidate(
          Candidate, *CCS,
          Candidate.getFunction()
              ? getDeclComment(S.getASTContext(), *Candidate.getFunction())
              : ""));
    }

    // Sema does not load the docs from the preamble, so we need to fetch extra
    // docs from the index instead.
    llvm::DenseMap<SymbolID, std::string> FetchedDocs;
    if (Index) {
      LookupRequest IndexRequest;
      for (const auto &S : ScoredSignatures) {
        if (!S.IDForDoc)
          continue;
        IndexRequest.IDs.insert(S.IDForDoc);
      }
      Index->lookup(IndexRequest, [&](const Symbol &S) {
        if (!S.Documentation.empty())
          FetchedDocs[S.ID] = std::string(S.Documentation);
      });
      vlog("SigHelp: requested docs for {0} symbols from the index, got {1} "
           "symbols with non-empty docs in the response",
           IndexRequest.IDs.size(), FetchedDocs.size());
    }

    llvm::sort(ScoredSignatures, [](const ScoredSignature &L,
                                    const ScoredSignature &R) {
      // Ordering follows:
      // - Less number of parameters is better.
      // - Aggregate > Function > FunctionType > FunctionTemplate
      // - High score is better.
      // - Shorter signature is better.
      // - Alphabetically smaller is better.
      if (L.Quality.NumberOfParameters != R.Quality.NumberOfParameters)
        return L.Quality.NumberOfParameters < R.Quality.NumberOfParameters;
      if (L.Quality.NumberOfOptionalParameters !=
          R.Quality.NumberOfOptionalParameters)
        return L.Quality.NumberOfOptionalParameters <
               R.Quality.NumberOfOptionalParameters;
      if (L.Quality.Kind != R.Quality.Kind) {
        using OC = CodeCompleteConsumer::OverloadCandidate;
        auto KindPriority = [&](OC::CandidateKind K) {
          switch (K) {
          case OC::CK_Aggregate:
            return 0;
          case OC::CK_Function:
            return 1;
          case OC::CK_FunctionType:
            return 2;
          case OC::CK_FunctionProtoTypeLoc:
            return 3;
          case OC::CK_FunctionTemplate:
            return 4;
          case OC::CK_Template:
            return 5;
          }
          llvm_unreachable("Unknown overload candidate type.");
        };
        return KindPriority(L.Quality.Kind) < KindPriority(R.Quality.Kind);
      }
      if (L.Signature.label.size() != R.Signature.label.size())
        return L.Signature.label.size() < R.Signature.label.size();
      return L.Signature.label < R.Signature.label;
    });

    for (auto &SS : ScoredSignatures) {
      auto IndexDocIt =
          SS.IDForDoc ? FetchedDocs.find(SS.IDForDoc) : FetchedDocs.end();
      if (IndexDocIt != FetchedDocs.end()) {
        markup::Document SignatureComment;
        parseDocumentation(IndexDocIt->second, SignatureComment);
        SS.Signature.documentation =
            renderDoc(SignatureComment, DocumentationFormat);
      }

      SigHelp.signatures.push_back(std::move(SS.Signature));
    }
  }

  GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; }

  CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }

private:
  void processParameterChunk(llvm::StringRef ChunkText,
                             SignatureInformation &Signature) const {
    // (!) this is O(n), should still be fast compared to building ASTs.
    unsigned ParamStartOffset = lspLength(Signature.label);
    unsigned ParamEndOffset = ParamStartOffset + lspLength(ChunkText);
    // A piece of text that describes the parameter that corresponds to
    // the code-completion location within a function call, message send,
    // macro invocation, etc.
    Signature.label += ChunkText;
    ParameterInformation Info;
    Info.labelOffsets.emplace(ParamStartOffset, ParamEndOffset);
    // FIXME: only set 'labelOffsets' when all clients migrate out of it.
    Info.labelString = std::string(ChunkText);

    Signature.parameters.push_back(std::move(Info));
  }

  void processOptionalChunk(const CodeCompletionString &CCS,
                            SignatureInformation &Signature,
                            SignatureQualitySignals &Signal) const {
    for (const auto &Chunk : CCS) {
      switch (Chunk.Kind) {
      case CodeCompletionString::CK_Optional:
        assert(Chunk.Optional &&
               "Expected the optional code completion string to be non-null.");
        processOptionalChunk(*Chunk.Optional, Signature, Signal);
        break;
      case CodeCompletionString::CK_VerticalSpace:
        break;
      case CodeCompletionString::CK_CurrentParameter:
      case CodeCompletionString::CK_Placeholder:
        processParameterChunk(Chunk.Text, Signature);
        Signal.NumberOfOptionalParameters++;
        break;
      default:
        Signature.label += Chunk.Text;
        break;
      }
    }
  }

  // FIXME(ioeric): consider moving CodeCompletionString logic here to
  // CompletionString.h.
  ScoredSignature processOverloadCandidate(const OverloadCandidate &Candidate,
                                           const CodeCompletionString &CCS,
                                           llvm::StringRef DocComment) const {
    SignatureInformation Signature;
    SignatureQualitySignals Signal;
    const char *ReturnType = nullptr;

    markup::Document OverloadComment;
    parseDocumentation(formatDocumentation(CCS, DocComment), OverloadComment);
    Signature.documentation = renderDoc(OverloadComment, DocumentationFormat);
    Signal.Kind = Candidate.getKind();

    for (const auto &Chunk : CCS) {
      switch (Chunk.Kind) {
      case CodeCompletionString::CK_ResultType:
        // A piece of text that describes the type of an entity or,
        // for functions and methods, the return type.
        assert(!ReturnType && "Unexpected CK_ResultType");
        ReturnType = Chunk.Text;
        break;
      case CodeCompletionString::CK_CurrentParameter:
      case CodeCompletionString::CK_Placeholder:
        processParameterChunk(Chunk.Text, Signature);
        Signal.NumberOfParameters++;
        break;
      case CodeCompletionString::CK_Optional: {
        // The rest of the parameters are defaulted/optional.
        assert(Chunk.Optional &&
               "Expected the optional code completion string to be non-null.");
        processOptionalChunk(*Chunk.Optional, Signature, Signal);
        break;
      }
      case CodeCompletionString::CK_VerticalSpace:
        break;
      default:
        Signature.label += Chunk.Text;
        break;
      }
    }
    if (ReturnType) {
      Signature.label += " -> ";
      Signature.label += ReturnType;
    }
    dlog("Signal for {0}: {1}", Signature, Signal);
    ScoredSignature Result;
    Result.Signature = std::move(Signature);
    Result.Quality = Signal;
    const FunctionDecl *Func = Candidate.getFunction();
    if (Func && Result.Signature.documentation.value.empty()) {
      // Computing USR caches linkage, which may change after code completion.
      if (!hasUnstableLinkage(Func))
        Result.IDForDoc = clangd::getSymbolID(Func);
    }
    return Result;
  }

  SignatureHelp &SigHelp;
  std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
  CodeCompletionTUInfo CCTUInfo;
  const SymbolIndex *Index;
  MarkupKind DocumentationFormat;
}; // SignatureHelpCollector

// Used only for completion of C-style comments in function call (i.e.
// /*foo=*/7). Similar to SignatureHelpCollector, but needs to do less work.
class ParamNameCollector final : public CodeCompleteConsumer {
public:
  ParamNameCollector(const clang::CodeCompleteOptions &CodeCompleteOpts,
                     std::set<std::string> &ParamNames)
      : CodeCompleteConsumer(CodeCompleteOpts),
        Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
        CCTUInfo(Allocator), ParamNames(ParamNames) {}

  void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
                                 OverloadCandidate *Candidates,
                                 unsigned NumCandidates,
                                 SourceLocation OpenParLoc,
                                 bool Braced) override {
    assert(CurrentArg <= (unsigned)std::numeric_limits<int>::max() &&
           "too many arguments");

    for (unsigned I = 0; I < NumCandidates; ++I) {
      if (const NamedDecl *ND = Candidates[I].getParamDecl(CurrentArg))
        if (const auto *II = ND->getIdentifier())
          ParamNames.emplace(II->getName());
    }
  }

private:
  GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; }

  CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }

  std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
  CodeCompletionTUInfo CCTUInfo;
  std::set<std::string> &ParamNames;
};

struct SemaCompleteInput {
  PathRef FileName;
  size_t Offset;
  const PreambleData &Preamble;
  const std::optional<PreamblePatch> Patch;
  const ParseInputs &ParseInput;
};

void loadMainFilePreambleMacros(const Preprocessor &PP,
                                const PreambleData &Preamble) {
  // The ExternalPreprocessorSource has our macros, if we know where to look.
  // We can read all the macros using PreambleMacros->ReadDefinedMacros(),
  // but this includes transitively included files, so may deserialize a lot.
  ExternalPreprocessorSource *PreambleMacros = PP.getExternalSource();
  // As we have the names of the macros, we can look up their IdentifierInfo
  // and then use this to load just the macros we want.
  const auto &ITable = PP.getIdentifierTable();
  IdentifierInfoLookup *PreambleIdentifiers =
      ITable.getExternalIdentifierLookup();

  if (!PreambleIdentifiers || !PreambleMacros)
    return;
  for (const auto &MacroName : Preamble.Macros.Names) {
    if (ITable.find(MacroName.getKey()) != ITable.end())
      continue;
    if (auto *II = PreambleIdentifiers->get(MacroName.getKey()))
      if (II->isOutOfDate())
        PreambleMacros->updateOutOfDateIdentifier(*II);
  }
}

// Invokes Sema code completion on a file.
// If \p Includes is set, it will be updated based on the compiler invocation.
bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
                      const clang::CodeCompleteOptions &Options,
                      const SemaCompleteInput &Input,
                      IncludeStructure *Includes = nullptr) {
  trace::Span Tracer("Sema completion");

  IgnoreDiagnostics IgnoreDiags;
  auto CI = buildCompilerInvocation(Input.ParseInput, IgnoreDiags);
  if (!CI) {
    elog("Couldn't create CompilerInvocation");
    return false;
  }
  auto &FrontendOpts = CI->getFrontendOpts();
  FrontendOpts.SkipFunctionBodies = true;
  // Disable typo correction in Sema.
  CI->getLangOpts().SpellChecking = false;
  // Code completion won't trigger in delayed template bodies.
  // This is on-by-default in windows to allow parsing SDK headers; we're only
  // disabling it for the main-file (not preamble).
  CI->getLangOpts().DelayedTemplateParsing = false;
  // Setup code completion.
  FrontendOpts.CodeCompleteOpts = Options;
  FrontendOpts.CodeCompletionAt.FileName = std::string(Input.FileName);
  std::tie(FrontendOpts.CodeCompletionAt.Line,
           FrontendOpts.CodeCompletionAt.Column) =
      offsetToClangLineColumn(Input.ParseInput.Contents, Input.Offset);

  std::unique_ptr<llvm::MemoryBuffer> ContentsBuffer =
      llvm::MemoryBuffer::getMemBuffer(Input.ParseInput.Contents,
                                       Input.FileName);
  // The diagnostic options must be set before creating a CompilerInstance.
  CI->getDiagnosticOpts().IgnoreWarnings = true;
  // We reuse the preamble whether it's valid or not. This is a
  // correctness/performance tradeoff: building without a preamble is slow, and
  // completion is latency-sensitive.
  // However, if we're completing *inside* the preamble section of the draft,
  // overriding the preamble will break sema completion. Fortunately we can just
  // skip all includes in this case; these completions are really simple.
  PreambleBounds PreambleRegion =
      ComputePreambleBounds(CI->getLangOpts(), *ContentsBuffer, 0);
  bool CompletingInPreamble = Input.Offset < PreambleRegion.Size ||
                              (!PreambleRegion.PreambleEndsAtStartOfLine &&
                               Input.Offset == PreambleRegion.Size);
  if (Input.Patch)
    Input.Patch->apply(*CI);
  // NOTE: we must call BeginSourceFile after prepareCompilerInstance. Otherwise
  // the remapped buffers do not get freed.
  llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
      Input.ParseInput.TFS->view(Input.ParseInput.CompileCommand.Directory);
  if (Input.Preamble.StatCache)
    VFS = Input.Preamble.StatCache->getConsumingFS(std::move(VFS));
  auto Clang = prepareCompilerInstance(
      std::move(CI), !CompletingInPreamble ? &Input.Preamble.Preamble : nullptr,
      std::move(ContentsBuffer), std::move(VFS), IgnoreDiags);
  Clang->getPreprocessorOpts().SingleFileParseMode = CompletingInPreamble;
  Clang->setCodeCompletionConsumer(Consumer.release());

  if (Input.Preamble.RequiredModules)
    Input.Preamble.RequiredModules->adjustHeaderSearchOptions(Clang->getHeaderSearchOpts());

  SyntaxOnlyAction Action;
  if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) {
    log("BeginSourceFile() failed when running codeComplete for {0}",
        Input.FileName);
    return false;
  }
  // Macros can be defined within the preamble region of the main file.
  // They don't fall nicely into our index/Sema dichotomy:
  //  - they're not indexed for completion (they're not available across files)
  //  - but Sema code complete won't see them: as part of the preamble, they're
  //    deserialized only when mentioned.
  // Force them to be deserialized so SemaCodeComplete sees them.
  loadMainFilePreambleMacros(Clang->getPreprocessor(), Input.Preamble);
  if (Includes)
    Includes->collect(*Clang);
  if (llvm::Error Err = Action.Execute()) {
    log("Execute() failed when running codeComplete for {0}: {1}",
        Input.FileName, toString(std::move(Err)));
    return false;
  }
  Action.EndSourceFile();

  return true;
}

// Should we allow index completions in the specified context?
bool allowIndex(CodeCompletionContext &CC) {
  if (!contextAllowsIndex(CC.getKind()))
    return false;
  // We also avoid ClassName::bar (but allow namespace::bar).
  auto Scope = CC.getCXXScopeSpecifier();
  if (!Scope)
    return true;
  // We only query the index when qualifier is a namespace.
  // If it's a class, we rely solely on sema completions.
  switch ((*Scope)->getScopeRep().getKind()) {
  case NestedNameSpecifier::Kind::Null:
  case NestedNameSpecifier::Kind::Global:
  case NestedNameSpecifier::Kind::Namespace:
    return true;
  case NestedNameSpecifier::Kind::MicrosoftSuper:
  case NestedNameSpecifier::Kind::Type:
    return false;
  }
  llvm_unreachable("invalid NestedNameSpecifier kind");
}

// Should we include a symbol from the index given the completion kind?
// FIXME: Ideally we can filter in the fuzzy find request itself.
bool includeSymbolFromIndex(CodeCompletionContext::Kind Kind,
                            const Symbol &Sym) {
  // Objective-C protocols are only useful in ObjC protocol completions,
  // in other places they're confusing, especially when they share the same
  // identifier with a class.
  if (Sym.SymInfo.Kind == index::SymbolKind::Protocol &&
      Sym.SymInfo.Lang == index::SymbolLanguage::ObjC)
    return Kind == CodeCompletionContext::CCC_ObjCProtocolName;
  else if (Kind == CodeCompletionContext::CCC_ObjCProtocolName)
    // Don't show anything else in ObjC protocol completions.
    return false;

  if (Kind == CodeCompletionContext::CCC_ObjCClassForwardDecl)
    return Sym.SymInfo.Kind == index::SymbolKind::Class &&
           Sym.SymInfo.Lang == index::SymbolLanguage::ObjC;
  return true;
}

std::future<std::pair<bool, SymbolSlab>>
startAsyncFuzzyFind(const SymbolIndex &Index, const FuzzyFindRequest &Req) {
  return runAsync<std::pair<bool, SymbolSlab>>([&Index, Req]() {
    trace::Span Tracer("Async fuzzyFind");
    SymbolSlab::Builder Syms;
    bool Incomplete =
        Index.fuzzyFind(Req, [&Syms](const Symbol &Sym) { Syms.insert(Sym); });
    return std::make_pair(Incomplete, std::move(Syms).build());
  });
}

// Creates a `FuzzyFindRequest` based on the cached index request from the
// last completion, if any, and the speculated completion filter text in the
// source code.
FuzzyFindRequest speculativeFuzzyFindRequestForCompletion(
    FuzzyFindRequest CachedReq, const CompletionPrefix &HeuristicPrefix) {
  CachedReq.Query = std::string(HeuristicPrefix.Name);
  return CachedReq;
}

// This function is similar to Lexer::findNextToken(), but assumes
// that the input SourceLocation is the completion point (which is
// a case findNextToken() does not handle).
std::optional<Token>
findTokenAfterCompletionPoint(SourceLocation CompletionPoint,
                              const SourceManager &SM,
                              const LangOptions &LangOpts) {
  SourceLocation Loc = CompletionPoint;
  if (Loc.isMacroID()) {
    if (!Lexer::isAtEndOfMacroExpansion(Loc, SM, LangOpts, &Loc))
      return std::nullopt;
  }

  // Advance to the next SourceLocation after the completion point.
  // Lexer::findNextToken() would call MeasureTokenLength() here,
  // which does not handle the completion point (and can't, because
  // the Lexer instance it constructs internally doesn't have a
  // Preprocessor and so doesn't know about the completion point).
  Loc = Loc.getLocWithOffset(1);

  // Break down the source location.
  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);

  // Try to load the file buffer.
  bool InvalidTemp = false;
  StringRef File = SM.getBufferData(LocInfo.first, &InvalidTemp);
  if (InvalidTemp)
    return std::nullopt;

  const char *TokenBegin = File.data() + LocInfo.second;

  // Lex from the start of the given location.
  Lexer TheLexer(SM.getLocForStartOfFile(LocInfo.first), LangOpts, File.begin(),
                 TokenBegin, File.end());
  // Find the token.
  Token Tok;
  TheLexer.LexFromRawLexer(Tok);
  return Tok;
}

// Runs Sema-based (AST) and Index-based completion, returns merged results.
//
// There are a few tricky considerations:
//   - the AST provides information needed for the index query (e.g. which
//     namespaces to search in). So Sema must start first.
//   - we only want to return the top results (Opts.Limit).
//     Building CompletionItems for everything else is wasteful, so we want to
//     preserve the "native" format until we're done with scoring.
//   - the data underlying Sema completion items is owned by the AST and various
//     other arenas, which must stay alive for us to build CompletionItems.
//   - we may get duplicate results from Sema and the Index, we need to merge.
//
// So we start Sema completion first, and do all our work in its callback.
// We use the Sema context information to query the index.
// Then we merge the two result sets, producing items that are Sema/Index/Both.
// These items are scored, and the top N are synthesized into the LSP response.
// Finally, we can clean up the data structures created by Sema completion.
//
// Main collaborators are:
//   - semaCodeComplete sets up the compiler machinery to run code completion.
//   - CompletionRecorder captures Sema completion results, including context.
//   - SymbolIndex (Opts.Index) provides index completion results as Symbols
//   - CompletionCandidates are the result of merging Sema and Index results.
//     Each candidate points to an underlying CodeCompletionResult (Sema), a
//     Symbol (Index), or both. It computes the result quality score.
//     CompletionCandidate also does conversion to CompletionItem (at the end).
//   - FuzzyMatcher scores how the candidate matches the partial identifier.
//     This score is combined with the result quality score for the final score.
//   - TopN determines the results with the best score.
class CodeCompleteFlow {
  PathRef FileName;
  IncludeStructure Includes;           // Complete once the compiler runs.
  SpeculativeFuzzyFind *SpecFuzzyFind; // Can be nullptr.
  const CodeCompleteOptions &Opts;

  // Sema takes ownership of Recorder. Recorder is valid until Sema cleanup.
  CompletionRecorder *Recorder = nullptr;
  CodeCompletionContext::Kind CCContextKind = CodeCompletionContext::CCC_Other;
  bool IsUsingDeclaration = false;
  // The snippets will not be generated if the token following completion
  // location is an opening parenthesis (tok::l_paren) because this would add
  // extra parenthesis.
  tok::TokenKind NextTokenKind = tok::eof;
  // Counters for logging.
  int NSema = 0, NIndex = 0, NSemaAndIndex = 0, NIdent = 0;
  bool Incomplete = false; // Would more be available with a higher limit?
  CompletionPrefix HeuristicPrefix;
  std::optional<FuzzyMatcher> Filter; // Initialized once Sema runs.
  Range ReplacedRange;
  std::vector<std::string> QueryScopes;      // Initialized once Sema runs.
  std::vector<std::string> AccessibleScopes; // Initialized once Sema runs.
  // Initialized once QueryScopes is initialized, if there are scopes.
  std::optional<ScopeDistance> ScopeProximity;
  std::optional<OpaqueType> PreferredType; // Initialized once Sema runs.
  // Whether to query symbols from any scope. Initialized once Sema runs.
  bool AllScopes = false;
  llvm::StringSet<> ContextWords;
  // Include-insertion and proximity scoring rely on the include structure.
  // This is available after Sema has run.
  std::optional<IncludeInserter> Inserter;  // Available during runWithSema.
  std::optional<URIDistance> FileProximity; // Initialized once Sema runs.
  /// Speculative request based on the cached request and the filter text before
  /// the cursor.
  /// Initialized right before sema run. This is only set if `SpecFuzzyFind` is
  /// set and contains a cached request.
  std::optional<FuzzyFindRequest> SpecReq;

public:
  // A CodeCompleteFlow object is only useful for calling run() exactly once.
  CodeCompleteFlow(PathRef FileName, const IncludeStructure &Includes,
                   SpeculativeFuzzyFind *SpecFuzzyFind,
                   const CodeCompleteOptions &Opts)
      : FileName(FileName), Includes(Includes), SpecFuzzyFind(SpecFuzzyFind),
        Opts(Opts) {}

  CodeCompleteResult run(const SemaCompleteInput &SemaCCInput) && {
    trace::Span Tracer("CodeCompleteFlow");
    HeuristicPrefix = guessCompletionPrefix(SemaCCInput.ParseInput.Contents,
                                            SemaCCInput.Offset);
    populateContextWords(SemaCCInput.ParseInput.Contents);
    if (Opts.Index && SpecFuzzyFind && SpecFuzzyFind->CachedReq) {
      assert(!SpecFuzzyFind->Result.valid());
      SpecReq = speculativeFuzzyFindRequestForCompletion(
          *SpecFuzzyFind->CachedReq, HeuristicPrefix);
      SpecFuzzyFind->Result = startAsyncFuzzyFind(*Opts.Index, *SpecReq);
    }

    // We run Sema code completion first. It builds an AST and calculates:
    //   - completion results based on the AST.
    //   - partial identifier and context. We need these for the index query.
    CodeCompleteResult Output;
    auto RecorderOwner = std::make_unique<CompletionRecorder>(Opts, [&]() {
      assert(Recorder && "Recorder is not set");
      CCContextKind = Recorder->CCContext.getKind();
      IsUsingDeclaration = Recorder->CCContext.isUsingDeclaration();
      auto Style = getFormatStyleForFile(SemaCCInput.FileName,
                                         SemaCCInput.ParseInput.Contents,
                                         *SemaCCInput.ParseInput.TFS, false);
      const auto NextToken = findTokenAfterCompletionPoint(
          Recorder->CCSema->getPreprocessor().getCodeCompletionLoc(),
          Recorder->CCSema->getSourceManager(), Recorder->CCSema->LangOpts);
      if (NextToken)
        NextTokenKind = NextToken->getKind();
      // If preprocessor was run, inclusions from preprocessor callback should
      // already be added to Includes.
      Inserter.emplace(
          SemaCCInput.FileName, SemaCCInput.ParseInput.Contents, Style,
          SemaCCInput.ParseInput.CompileCommand.Directory,
          &Recorder->CCSema->getPreprocessor().getHeaderSearchInfo(),
          Config::current().Style.QuotedHeaders,
          Config::current().Style.AngledHeaders);
      for (const auto &Inc : Includes.MainFileIncludes)
        Inserter->addExisting(Inc);

      // Most of the cost of file proximity is in initializing the FileDistance
      // structures based on the observed includes, once per query. Conceptually
      // that happens here (though the per-URI-scheme initialization is lazy).
      // The per-result proximity scoring is (amortized) very cheap.
      FileDistanceOptions ProxOpts{}; // Use defaults.
      const auto &SM = Recorder->CCSema->getSourceManager();
      llvm::StringMap<SourceParams> ProxSources;
      auto MainFileID =
          Includes.getID(SM.getFileEntryForID(SM.getMainFileID()));
      assert(MainFileID);
      for (auto &HeaderIDAndDepth : Includes.includeDepth(*MainFileID)) {
        auto &Source =
            ProxSources[Includes.getRealPath(HeaderIDAndDepth.getFirst())];
        Source.Cost = HeaderIDAndDepth.getSecond() * ProxOpts.IncludeCost;
        // Symbols near our transitive includes are good, but only consider
        // things in the same directory or below it. Otherwise there can be
        // many false positives.
        if (HeaderIDAndDepth.getSecond() > 0)
          Source.MaxUpTraversals = 1;
      }
      FileProximity.emplace(ProxSources, ProxOpts);

      Output = runWithSema();
      Inserter.reset(); // Make sure this doesn't out-live Clang.
      SPAN_ATTACH(Tracer, "sema_completion_kind",
                  getCompletionKindString(CCContextKind));
      log("Code complete: sema context {0}, query scopes [{1}] (AnyScope={2}), "
          "expected type {3}{4}",
          getCompletionKindString(CCContextKind),
          llvm::join(QueryScopes.begin(), QueryScopes.end(), ","), AllScopes,
          PreferredType ? Recorder->CCContext.getPreferredType().getAsString()
                        : "<none>",
          IsUsingDeclaration ? ", inside using declaration" : "");
    });

    Recorder = RecorderOwner.get();

    semaCodeComplete(std::move(RecorderOwner), Opts.getClangCompleteOpts(),
                     SemaCCInput, &Includes);
    logResults(Output, Tracer);
    return Output;
  }

  void logResults(const CodeCompleteResult &Output, const trace::Span &Tracer) {
    SPAN_ATTACH(Tracer, "sema_results", NSema);
    SPAN_ATTACH(Tracer, "index_results", NIndex);
    SPAN_ATTACH(Tracer, "merged_results", NSemaAndIndex);
    SPAN_ATTACH(Tracer, "identifier_results", NIdent);
    SPAN_ATTACH(Tracer, "returned_results", int64_t(Output.Completions.size()));
    SPAN_ATTACH(Tracer, "incomplete", Output.HasMore);
    log("Code complete: {0} results from Sema, {1} from Index, "
        "{2} matched, {3} from identifiers, {4} returned{5}.",
        NSema, NIndex, NSemaAndIndex, NIdent, Output.Completions.size(),
        Output.HasMore ? " (incomplete)" : "");
    assert(!Opts.Limit || Output.Completions.size() <= Opts.Limit);
    // We don't assert that isIncomplete means we hit a limit.
    // Indexes may choose to impose their own limits even if we don't have one.
  }

  CodeCompleteResult runWithoutSema(llvm::StringRef Content, size_t Offset,
                                    const ThreadsafeFS &TFS) && {
    trace::Span Tracer("CodeCompleteWithoutSema");
    // Fill in fields normally set by runWithSema()
    HeuristicPrefix = guessCompletionPrefix(Content, Offset);
    populateContextWords(Content);
    CCContextKind = CodeCompletionContext::CCC_Recovery;
    IsUsingDeclaration = false;
    Filter = FuzzyMatcher(HeuristicPrefix.Name);
    auto Pos = offsetToPosition(Content, Offset);
    ReplacedRange.start = ReplacedRange.end = Pos;
    ReplacedRange.start.character -= HeuristicPrefix.Name.size();

    llvm::StringMap<SourceParams> ProxSources;
    ProxSources[FileName].Cost = 0;
    FileProximity.emplace(ProxSources);

    auto Style = getFormatStyleForFile(FileName, Content, TFS, false);
    // This will only insert verbatim headers.
    Inserter.emplace(FileName, Content, Style,
                     /*BuildDir=*/"", /*HeaderSearchInfo=*/nullptr,
                     Config::current().Style.QuotedHeaders,
                     Config::current().Style.AngledHeaders);

    auto Identifiers = collectIdentifiers(Content, Style);
    std::vector<RawIdentifier> IdentifierResults;
    for (const auto &IDAndCount : Identifiers) {
      RawIdentifier ID;
      ID.Name = IDAndCount.first();
      ID.References = IDAndCount.second;
      // Avoid treating typed filter as an identifier.
      if (ID.Name == HeuristicPrefix.Name)
        --ID.References;
      if (ID.References > 0)
        IdentifierResults.push_back(std::move(ID));
    }

    // Simplified version of getQueryScopes():
    //  - accessible scopes are determined heuristically.
    //  - all-scopes query if no qualifier was typed (and it's allowed).
    SpecifiedScope Scopes;
    Scopes.QueryScopes = visibleNamespaces(
        Content.take_front(Offset), format::getFormattingLangOpts(Style));
    for (std::string &S : Scopes.QueryScopes)
      if (!S.empty())
        S.append("::"); // visibleNamespaces doesn't include trailing ::.
    if (HeuristicPrefix.Qualifier.empty())
      AllScopes = Opts.AllScopes;
    else if (HeuristicPrefix.Qualifier.starts_with("::")) {
      Scopes.QueryScopes = {""};
      Scopes.UnresolvedQualifier =
          std::string(HeuristicPrefix.Qualifier.drop_front(2));
    } else
      Scopes.UnresolvedQualifier = std::string(HeuristicPrefix.Qualifier);
    // First scope is the (modified) enclosing scope.
    QueryScopes = Scopes.scopesForIndexQuery();
    AccessibleScopes = QueryScopes;
    ScopeProximity.emplace(QueryScopes);

    SymbolSlab IndexResults = Opts.Index ? queryIndex() : SymbolSlab();

    CodeCompleteResult Output = toCodeCompleteResult(mergeResults(
        /*SemaResults=*/{}, IndexResults, IdentifierResults));
    Output.RanParser = false;
    logResults(Output, Tracer);
    return Output;
  }

private:
  void populateContextWords(llvm::StringRef Content) {
    // Take last 3 lines before the completion point.
    unsigned RangeEnd = HeuristicPrefix.Qualifier.begin() - Content.data(),
             RangeBegin = RangeEnd;
    for (size_t I = 0; I < 3 && RangeBegin > 0; ++I) {
      auto PrevNL = Content.rfind('\n', RangeBegin);
      if (PrevNL == StringRef::npos) {
        RangeBegin = 0;
        break;
      }
      RangeBegin = PrevNL;
    }

    ContextWords = collectWords(Content.slice(RangeBegin, RangeEnd));
    dlog("Completion context words: {0}",
         llvm::join(ContextWords.keys(), ", "));
  }

  // This is called by run() once Sema code completion is done, but before the
  // Sema data structures are torn down. It does all the real work.
  CodeCompleteResult runWithSema() {
    const auto &CodeCompletionRange = CharSourceRange::getCharRange(
        Recorder->CCSema->getPreprocessor().getCodeCompletionTokenRange());
    // When we are getting completions with an empty identifier, for example
    //    std::vector<int> asdf;
    //    asdf.^;
    // Then the range will be invalid and we will be doing insertion, use
    // current cursor position in such cases as range.
    if (CodeCompletionRange.isValid()) {
      ReplacedRange = halfOpenToRange(Recorder->CCSema->getSourceManager(),
                                      CodeCompletionRange);
    } else {
      const auto &Pos = sourceLocToPosition(
          Recorder->CCSema->getSourceManager(),
          Recorder->CCSema->getPreprocessor().getCodeCompletionLoc());
      ReplacedRange.start = ReplacedRange.end = Pos;
    }
    Filter = FuzzyMatcher(
        Recorder->CCSema->getPreprocessor().getCodeCompletionFilter());
    auto SpecifiedScopes = getQueryScopes(
        Recorder->CCContext, *Recorder->CCSema, HeuristicPrefix, Opts);

    QueryScopes = SpecifiedScopes.scopesForIndexQuery();
    AccessibleScopes = SpecifiedScopes.scopesForQualification();
    AllScopes = SpecifiedScopes.AllowAllScopes;
    if (!QueryScopes.empty())
      ScopeProximity.emplace(QueryScopes);
    PreferredType =
        OpaqueType::fromType(Recorder->CCSema->getASTContext(),
                             Recorder->CCContext.getPreferredType());
    // Sema provides the needed context to query the index.
    // FIXME: in addition to querying for extra/overlapping symbols, we should
    //        explicitly request symbols corresponding to Sema results.
    //        We can use their signals even if the index can't suggest them.
    // We must copy index results to preserve them, but there are at most Limit.
    auto IndexResults = (Opts.Index && allowIndex(Recorder->CCContext))
                            ? queryIndex()
                            : SymbolSlab();
    trace::Span Tracer("Populate CodeCompleteResult");
    // Merge Sema and Index results, score them, and pick the winners.
    auto Top =
        mergeResults(Recorder->Results, IndexResults, /*Identifiers*/ {});
    return toCodeCompleteResult(Top);
  }

  CodeCompleteResult
  toCodeCompleteResult(const std::vector<ScoredBundle> &Scored) {
    CodeCompleteResult Output;

    // Convert the results to final form, assembling the expensive strings.
    // If necessary, search the index for documentation comments.
    LookupRequest Req;
    llvm::DenseMap<SymbolID, uint32_t> SymbolToCompletion;
    for (auto &C : Scored) {
      Output.Completions.push_back(toCodeCompletion(C.first));
      Output.Completions.back().Score = C.second;
      Output.Completions.back().CompletionTokenRange = ReplacedRange;
      if (Opts.Index && !Output.Completions.back().Documentation) {
        for (auto &Cand : C.first) {
          if (Cand.SemaResult &&
              Cand.SemaResult->Kind == CodeCompletionResult::RK_Declaration) {
            auto ID = clangd::getSymbolID(Cand.SemaResult->getDeclaration());
            if (!ID)
              continue;
            Req.IDs.insert(ID);
            SymbolToCompletion[ID] = Output.Completions.size() - 1;
          }
        }
      }
    }
    Output.HasMore = Incomplete;
    Output.Context = CCContextKind;
    Output.CompletionRange = ReplacedRange;

    // Look up documentation from the index.
    if (Opts.Index) {
      Opts.Index->lookup(Req, [&](const Symbol &S) {
        if (S.Documentation.empty())
          return;
        auto &C = Output.Completions[SymbolToCompletion.at(S.ID)];
        C.Documentation.emplace();
        parseDocumentation(S.Documentation, *C.Documentation);
      });
    }

    return Output;
  }

  SymbolSlab queryIndex() {
    trace::Span Tracer("Query index");
    SPAN_ATTACH(Tracer, "limit", int64_t(Opts.Limit));

    // Build the query.
    FuzzyFindRequest Req;
    if (Opts.Limit)
      Req.Limit = Opts.Limit;
    Req.Query = std::string(Filter->pattern());
    Req.RestrictForCodeCompletion = true;
    Req.Scopes = QueryScopes;
    Req.AnyScope = AllScopes;
    // FIXME: we should send multiple weighted paths here.
    Req.ProximityPaths.push_back(std::string(FileName));
    if (PreferredType)
      Req.PreferredTypes.push_back(std::string(PreferredType->raw()));
    vlog("Code complete: fuzzyFind({0:2})", toJSON(Req));

    if (SpecFuzzyFind)
      SpecFuzzyFind->NewReq = Req;
    if (SpecFuzzyFind && SpecFuzzyFind->Result.valid() && (*SpecReq == Req)) {
      vlog("Code complete: speculative fuzzy request matches the actual index "
           "request. Waiting for the speculative index results.");
      SPAN_ATTACH(Tracer, "Speculative results", true);

      trace::Span WaitSpec("Wait speculative results");
      auto SpecRes = SpecFuzzyFind->Result.get();
      Incomplete |= SpecRes.first;
      return std::move(SpecRes.second);
    }

    SPAN_ATTACH(Tracer, "Speculative results", false);

    // Run the query against the index.
    SymbolSlab::Builder ResultsBuilder;
    Incomplete |= Opts.Index->fuzzyFind(
        Req, [&](const Symbol &Sym) { ResultsBuilder.insert(Sym); });
    return std::move(ResultsBuilder).build();
  }

  // Merges Sema and Index results where possible, to form CompletionCandidates.
  // \p Identifiers is raw identifiers that can also be completion candidates.
  // Identifiers are not merged with results from index or sema.
  // Groups overloads if desired, to form CompletionCandidate::Bundles. The
  // bundles are scored and top results are returned, best to worst.
  std::vector<ScoredBundle>
  mergeResults(const std::vector<CodeCompletionResult> &SemaResults,
               const SymbolSlab &IndexResults,
               const std::vector<RawIdentifier> &IdentifierResults) {
    trace::Span Tracer("Merge and score results");
    std::vector<CompletionCandidate::Bundle> Bundles;
    llvm::DenseMap<size_t, size_t> BundleLookup;
    auto AddToBundles = [&](const CodeCompletionResult *SemaResult,
                            const Symbol *IndexResult,
                            const RawIdentifier *IdentifierResult) {
      CompletionCandidate C;
      C.SemaResult = SemaResult;
      C.IndexResult = IndexResult;
      C.IdentifierResult = IdentifierResult;
      if (C.IndexResult) {
        C.Name = IndexResult->Name;
        C.RankedIncludeHeaders = getRankedIncludes(*C.IndexResult);
      } else if (C.SemaResult) {
        C.Name = Recorder->getName(*SemaResult);
      } else {
        assert(IdentifierResult);
        C.Name = IdentifierResult->Name;
      }
      if (auto OverloadSet = C.overloadSet(
              Opts, FileName, Inserter ? &*Inserter : nullptr, CCContextKind)) {
        auto Ret = BundleLookup.try_emplace(OverloadSet, Bundles.size());
        if (Ret.second)
          Bundles.emplace_back();
        Bundles[Ret.first->second].push_back(std::move(C));
      } else {
        Bundles.emplace_back();
        Bundles.back().push_back(std::move(C));
      }
    };
    llvm::DenseSet<const Symbol *> UsedIndexResults;
    auto CorrespondingIndexResult =
        [&](const CodeCompletionResult &SemaResult) -> const Symbol * {
      if (auto SymID =
              getSymbolID(SemaResult, Recorder->CCSema->getSourceManager())) {
        auto I = IndexResults.find(SymID);
        if (I != IndexResults.end()) {
          UsedIndexResults.insert(&*I);
          return &*I;
        }
      }
      return nullptr;
    };
    // Emit all Sema results, merging them with Index results if possible.
    for (auto &SemaResult : SemaResults)
      AddToBundles(&SemaResult, CorrespondingIndexResult(SemaResult), nullptr);
    // Now emit any Index-only results.
    for (const auto &IndexResult : IndexResults) {
      if (UsedIndexResults.count(&IndexResult))
        continue;
      if (!includeSymbolFromIndex(CCContextKind, IndexResult))
        continue;
      AddToBundles(/*SemaResult=*/nullptr, &IndexResult, nullptr);
    }
    // Emit identifier results.
    for (const auto &Ident : IdentifierResults)
      AddToBundles(/*SemaResult=*/nullptr, /*IndexResult=*/nullptr, &Ident);
    // We only keep the best N results at any time, in "native" format.
    TopN<ScoredBundle, ScoredBundleGreater> Top(
        Opts.Limit == 0 ? std::numeric_limits<size_t>::max() : Opts.Limit);
    for (auto &Bundle : Bundles)
      addCandidate(Top, std::move(Bundle));
    return std::move(Top).items();
  }

  std::optional<float> fuzzyScore(const CompletionCandidate &C) {
    // Macros can be very spammy, so we only support prefix completion.
    if (((C.SemaResult &&
          C.SemaResult->Kind == CodeCompletionResult::RK_Macro) ||
         (C.IndexResult &&
          C.IndexResult->SymInfo.Kind == index::SymbolKind::Macro)) &&
        !C.Name.starts_with_insensitive(Filter->pattern()))
      return std::nullopt;
    return Filter->match(C.Name);
  }

  CodeCompletion::Scores
  evaluateCompletion(const SymbolQualitySignals &Quality,
                     const SymbolRelevanceSignals &Relevance) {
    using RM = CodeCompleteOptions::CodeCompletionRankingModel;
    CodeCompletion::Scores Scores;
    switch (Opts.RankingModel) {
    case RM::Heuristics:
      Scores.Quality = Quality.evaluateHeuristics();
      Scores.Relevance = Relevance.evaluateHeuristics();
      Scores.Total =
          evaluateSymbolAndRelevance(Scores.Quality, Scores.Relevance);
      // NameMatch is in fact a multiplier on total score, so rescoring is
      // sound.
      Scores.ExcludingName =
          Relevance.NameMatch > std::numeric_limits<float>::epsilon()
              ? Scores.Total / Relevance.NameMatch
              : Scores.Quality;
      return Scores;

    case RM::DecisionForest:
      DecisionForestScores DFScores = Opts.DecisionForestScorer(
          Quality, Relevance, Opts.DecisionForestBase);
      Scores.ExcludingName = DFScores.ExcludingName;
      Scores.Total = DFScores.Total;
      return Scores;
    }
    llvm_unreachable("Unhandled CodeCompletion ranking model.");
  }

  // Scores a candidate and adds it to the TopN structure.
  void addCandidate(TopN<ScoredBundle, ScoredBundleGreater> &Candidates,
                    CompletionCandidate::Bundle Bundle) {
    SymbolQualitySignals Quality;
    SymbolRelevanceSignals Relevance;
    Relevance.Context = CCContextKind;
    Relevance.Name = Bundle.front().Name;
    Relevance.FilterLength = HeuristicPrefix.Name.size();
    Relevance.Query = SymbolRelevanceSignals::CodeComplete;
    Relevance.FileProximityMatch = &*FileProximity;
    if (ScopeProximity)
      Relevance.ScopeProximityMatch = &*ScopeProximity;
    if (PreferredType)
      Relevance.HadContextType = true;
    Relevance.ContextWords = &ContextWords;
    Relevance.MainFileSignals = Opts.MainFileSignals;

    auto &First = Bundle.front();
    if (auto FuzzyScore = fuzzyScore(First))
      Relevance.NameMatch = *FuzzyScore;
    else
      return;
    SymbolOrigin Origin = SymbolOrigin::Unknown;
    bool FromIndex = false;
    for (const auto &Candidate : Bundle) {
      if (Candidate.IndexResult) {
        Quality.merge(*Candidate.IndexResult);
        Relevance.merge(*Candidate.IndexResult);
        Origin |= Candidate.IndexResult->Origin;
        FromIndex = true;
        if (!Candidate.IndexResult->Type.empty())
          Relevance.HadSymbolType |= true;
        if (PreferredType &&
            PreferredType->raw() == Candidate.IndexResult->Type) {
          Relevance.TypeMatchesPreferred = true;
        }
      }
      if (Candidate.SemaResult) {
        Quality.merge(*Candidate.SemaResult);
        Relevance.merge(*Candidate.SemaResult);
        if (PreferredType) {
          if (auto CompletionType = OpaqueType::fromCompletionResult(
                  Recorder->CCSema->getASTContext(), *Candidate.SemaResult)) {
            Relevance.HadSymbolType |= true;
            if (PreferredType == CompletionType)
              Relevance.TypeMatchesPreferred = true;
          }
        }
        Origin |= SymbolOrigin::AST;
      }
      if (Candidate.IdentifierResult) {
        Quality.References = Candidate.IdentifierResult->References;
        Relevance.Scope = SymbolRelevanceSignals::FileScope;
        Origin |= SymbolOrigin::Identifier;
      }
    }

    CodeCompletion::Scores Scores = evaluateCompletion(Quality, Relevance);
    if (Opts.RecordCCResult)
      Opts.RecordCCResult(toCodeCompletion(Bundle), Quality, Relevance,
                          Scores.Total);

    dlog("CodeComplete: {0} ({1}) = {2}\n{3}{4}\n", First.Name,
         llvm::to_string(Origin), Scores.Total, llvm::to_string(Quality),
         llvm::to_string(Relevance));

    NSema += bool(Origin & SymbolOrigin::AST);
    NIndex += FromIndex;
    NSemaAndIndex += bool(Origin & SymbolOrigin::AST) && FromIndex;
    NIdent += bool(Origin & SymbolOrigin::Identifier);
    if (Candidates.push({std::move(Bundle), Scores}))
      Incomplete = true;
  }

  CodeCompletion toCodeCompletion(const CompletionCandidate::Bundle &Bundle) {
    std::optional<CodeCompletionBuilder> Builder;
    for (const auto &Item : Bundle) {
      CodeCompletionString *SemaCCS =
          Item.SemaResult ? Recorder->codeCompletionString(*Item.SemaResult)
                          : nullptr;
      if (!Builder)
        Builder.emplace(Recorder ? &Recorder->CCSema->getASTContext() : nullptr,
                        Item, SemaCCS, AccessibleScopes, *Inserter, FileName,
                        CCContextKind, Opts, IsUsingDeclaration, NextTokenKind);
      else
        Builder->add(Item, SemaCCS, CCContextKind);
    }
    return Builder->build();
  }
};

} // namespace

clang::CodeCompleteOptions CodeCompleteOptions::getClangCompleteOpts() const {
  clang::CodeCompleteOptions Result;
  Result.IncludeCodePatterns =
      EnableSnippets && (CodePatterns != Config::CodePatternsPolicy::None);
  Result.IncludeMacros = true;
  Result.IncludeGlobals = true;
  // We choose to include full comments and not do doxygen parsing in
  // completion.
  // FIXME: ideally, we should support doxygen in some form, e.g. do markdown
  // formatting of the comments.
  Result.IncludeBriefComments = false;

  // When an is used, Sema is responsible for completing the main file,
  // the index can provide results from the preamble.
  // Tell Sema not to deserialize the preamble to look for results.
  Result.LoadExternal = ForceLoadPreamble || !Index;
  Result.IncludeFixIts = IncludeFixIts;

  return Result;
}

CompletionPrefix guessCompletionPrefix(llvm::StringRef Content,
                                       unsigned Offset) {
  assert(Offset <= Content.size());
  StringRef Rest = Content.take_front(Offset);
  CompletionPrefix Result;

  // Consume the unqualified name. We only handle ASCII characters.
  // isAsciiIdentifierContinue will let us match "0invalid", but we don't mind.
  while (!Rest.empty() && isAsciiIdentifierContinue(Rest.back()))
    Rest = Rest.drop_back();
  Result.Name = Content.slice(Rest.size(), Offset);

  // Consume qualifiers.
  while (Rest.consume_back("::") && !Rest.ends_with(":")) // reject ::::
    while (!Rest.empty() && isAsciiIdentifierContinue(Rest.back()))
      Rest = Rest.drop_back();
  Result.Qualifier =
      Content.slice(Rest.size(), Result.Name.begin() - Content.begin());

  return Result;
}

// Code complete the argument name on "/*" inside function call.
// Offset should be pointing to the start of the comment, i.e.:
// foo(^/*, rather than foo(/*^) where the cursor probably is.
CodeCompleteResult codeCompleteComment(PathRef FileName, unsigned Offset,
                                       llvm::StringRef Prefix,
                                       const PreambleData *Preamble,
                                       const ParseInputs &ParseInput) {
  if (Preamble == nullptr) // Can't run without Sema.
    return CodeCompleteResult();

  clang::CodeCompleteOptions Options;
  Options.IncludeGlobals = false;
  Options.IncludeMacros = false;
  Options.IncludeCodePatterns = false;
  Options.IncludeBriefComments = false;
  std::set<std::string> ParamNames;
  // We want to see signatures coming from newly introduced includes, hence a
  // full patch.
  semaCodeComplete(
      std::make_unique<ParamNameCollector>(Options, ParamNames), Options,
      {FileName, Offset, *Preamble,
       PreamblePatch::createFullPatch(FileName, ParseInput, *Preamble),
       ParseInput});
  if (ParamNames.empty())
    return CodeCompleteResult();

  CodeCompleteResult Result;
  Range CompletionRange;
  // Skip /*
  Offset += 2;
  CompletionRange.start = offsetToPosition(ParseInput.Contents, Offset);
  CompletionRange.end =
      offsetToPosition(ParseInput.Contents, Offset + Prefix.size());
  Result.CompletionRange = CompletionRange;
  Result.Context = CodeCompletionContext::CCC_NaturalLanguage;
  for (llvm::StringRef Name : ParamNames) {
    if (!Name.starts_with(Prefix))
      continue;
    CodeCompletion Item;
    Item.Name = Name.str() + "=*/";
    Item.FilterText = Item.Name;
    Item.Kind = CompletionItemKind::Text;
    Item.CompletionTokenRange = CompletionRange;
    Item.Origin = SymbolOrigin::AST;
    Result.Completions.push_back(Item);
  }

  return Result;
}

// If Offset is inside what looks like argument comment (e.g.
// "/*^" or "/* foo^"), returns new offset pointing to the start of the /*
// (place where semaCodeComplete should run).
std::optional<unsigned>
maybeFunctionArgumentCommentStart(llvm::StringRef Content) {
  while (!Content.empty() && isAsciiIdentifierContinue(Content.back()))
    Content = Content.drop_back();
  Content = Content.rtrim();
  if (Content.ends_with("/*"))
    return Content.size() - 2;
  return std::nullopt;
}

CodeCompleteResult codeComplete(PathRef FileName, Position Pos,
                                const PreambleData *Preamble,
                                const ParseInputs &ParseInput,
                                CodeCompleteOptions Opts,
                                SpeculativeFuzzyFind *SpecFuzzyFind) {
  auto Offset = positionToOffset(ParseInput.Contents, Pos);
  if (!Offset) {
    elog("Code completion position was invalid {0}", Offset.takeError());
    return CodeCompleteResult();
  }

  auto Content = llvm::StringRef(ParseInput.Contents).take_front(*Offset);
  if (auto OffsetBeforeComment = maybeFunctionArgumentCommentStart(Content)) {
    // We are doing code completion of a comment, where we currently only
    // support completing param names in function calls. To do this, we
    // require information from Sema, but Sema's comment completion stops at
    // parsing, so we must move back the position before running it, extract
    // information we need and construct completion items ourselves.
    auto CommentPrefix = Content.substr(*OffsetBeforeComment + 2).trim();
    return codeCompleteComment(FileName, *OffsetBeforeComment, CommentPrefix,
                               Preamble, ParseInput);
  }

  auto Flow = CodeCompleteFlow(
      FileName, Preamble ? Preamble->Includes : IncludeStructure(),
      SpecFuzzyFind, Opts);
  return (!Preamble || Opts.RunParser == CodeCompleteOptions::NeverParse)
             ? std::move(Flow).runWithoutSema(ParseInput.Contents, *Offset,
                                              *ParseInput.TFS)
             : std::move(Flow).run({FileName, *Offset, *Preamble,
                                    /*PreamblePatch=*/
                                    PreamblePatch::createMacroPatch(
                                        FileName, ParseInput, *Preamble),
                                    ParseInput});
}

SignatureHelp signatureHelp(PathRef FileName, Position Pos,
                            const PreambleData &Preamble,
                            const ParseInputs &ParseInput,
                            MarkupKind DocumentationFormat) {
  auto Offset = positionToOffset(ParseInput.Contents, Pos);
  if (!Offset) {
    elog("Signature help position was invalid {0}", Offset.takeError());
    return SignatureHelp();
  }
  SignatureHelp Result;
  clang::CodeCompleteOptions Options;
  Options.IncludeGlobals = false;
  Options.IncludeMacros = false;
  Options.IncludeCodePatterns = false;
  Options.IncludeBriefComments = false;
  semaCodeComplete(
      std::make_unique<SignatureHelpCollector>(Options, DocumentationFormat,
                                               ParseInput.Index, Result),
      Options,
      {FileName, *Offset, Preamble,
       PreamblePatch::createFullPatch(FileName, ParseInput, Preamble),
       ParseInput});
  return Result;
}

bool isIndexedForCodeCompletion(const NamedDecl &ND, ASTContext &ASTCtx) {
  auto InTopLevelScope = [](const NamedDecl &ND) {
    switch (ND.getDeclContext()->getDeclKind()) {
    case Decl::TranslationUnit:
    case Decl::Namespace:
    case Decl::LinkageSpec:
      return true;
    default:
      break;
    };
    return false;
  };
  auto InClassScope = [](const NamedDecl &ND) {
    return ND.getDeclContext()->getDeclKind() == Decl::CXXRecord;
  };
  // We only complete symbol's name, which is the same as the name of the
  // *primary* template in case of template specializations.
  if (isExplicitTemplateSpecialization(&ND))
    return false;

  // Category decls are not useful on their own outside the interface or
  // implementation blocks. Moreover, sema already provides completion for
  // these, even if it requires preamble deserialization. So by excluding them
  // from the index, we reduce the noise in all the other completion scopes.
  if (llvm::isa<ObjCCategoryDecl>(&ND) || llvm::isa<ObjCCategoryImplDecl>(&ND))
    return false;

  if (InTopLevelScope(ND))
    return true;

  // Always index enum constants, even if they're not in the top level scope:
  // when
  // --all-scopes-completion is set, we'll want to complete those as well.
  if (const auto *EnumDecl = dyn_cast<clang::EnumDecl>(ND.getDeclContext()))
    return (InTopLevelScope(*EnumDecl) || InClassScope(*EnumDecl));

  return false;
}

CompletionItem CodeCompletion::render(const CodeCompleteOptions &Opts) const {
  CompletionItem LSP;
  const auto *InsertInclude = Includes.empty() ? nullptr : &Includes[0];
  // We could move our indicators from label into labelDetails->description.
  // In VSCode there are rendering issues that prevent these being aligned.
  LSP.label = ((InsertInclude && InsertInclude->Insertion)
                   ? Opts.IncludeIndicator.Insert
                   : Opts.IncludeIndicator.NoInsert) +
              (Opts.ShowOrigins ? "[" + llvm::to_string(Origin) + "]" : "") +
              RequiredQualifier + Name;
  LSP.labelDetails.emplace();
  LSP.labelDetails->detail = Signature;

  LSP.kind = Kind;
  LSP.detail = BundleSize > 1
                   ? std::string(llvm::formatv("[{0} overloads]", BundleSize))
                   : ReturnType;
  LSP.deprecated = Deprecated;
  // Combine header information and documentation in LSP `documentation` field.
  // This is not quite right semantically, but tends to display well in editors.
  if (InsertInclude || Documentation) {
    markup::Document Doc;
    if (InsertInclude)
      Doc.addParagraph().appendText("From ").appendCode(InsertInclude->Header);
    if (Documentation)
      Doc.append(*Documentation);
    LSP.documentation = renderDoc(Doc, Opts.DocumentationFormat);
  }
  LSP.sortText = sortText(Score.Total, FilterText);
  LSP.filterText = FilterText;
  LSP.textEdit = {CompletionTokenRange, RequiredQualifier + Name, ""};
  // Merge continuous additionalTextEdits into main edit. The main motivation
  // behind this is to help LSP clients, it seems most of them are confused when
  // they are provided with additionalTextEdits that are consecutive to main
  // edit.
  // Note that we store additional text edits from back to front in a line. That
  // is mainly to help LSP clients again, so that changes do not effect each
  // other.
  for (const auto &FixIt : FixIts) {
    if (FixIt.range.end == LSP.textEdit->range.start) {
      LSP.textEdit->newText = FixIt.newText + LSP.textEdit->newText;
      LSP.textEdit->range.start = FixIt.range.start;
    } else {
      LSP.additionalTextEdits.push_back(FixIt);
    }
  }
  if (Opts.EnableSnippets)
    LSP.textEdit->newText += SnippetSuffix;

  // FIXME(kadircet): Do not even fill insertText after making sure textEdit is
  // compatible with most of the editors.
  LSP.insertText = LSP.textEdit->newText;
  // Some clients support snippets but work better with plaintext.
  // So if the snippet is trivial, let the client know.
  // https://github.com/clangd/clangd/issues/922
  LSP.insertTextFormat = (Opts.EnableSnippets && !SnippetSuffix.empty())
                             ? InsertTextFormat::Snippet
                             : InsertTextFormat::PlainText;
  if (InsertInclude && InsertInclude->Insertion)
    LSP.additionalTextEdits.push_back(*InsertInclude->Insertion);

  LSP.score = Score.ExcludingName;

  return LSP;
}

llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const CodeCompletion &C) {
  OS << "Signature: " << "\"" << C.Signature << "\", "
     << "SnippetSuffix: " << "\"" << C.SnippetSuffix << "\""
     << ", Rendered:";
  // For now just lean on CompletionItem.
  return OS << C.render(CodeCompleteOptions());
}

llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
                              const CodeCompleteResult &R) {
  OS << "CodeCompleteResult: " << R.Completions.size() << (R.HasMore ? "+" : "")
     << " (" << getCompletionKindString(R.Context) << ")"
     << " items:\n";
  for (const auto &C : R.Completions)
    OS << C << "\n";
  return OS;
}

// Heuristically detect whether the `Line` is an unterminated include filename.
bool isIncludeFile(llvm::StringRef Line) {
  Line = Line.ltrim();
  if (!Line.consume_front("#"))
    return false;
  Line = Line.ltrim();
  if (!(Line.consume_front("include_next") || Line.consume_front("include") ||
        Line.consume_front("import")))
    return false;
  Line = Line.ltrim();
  if (Line.consume_front("<"))
    return Line.count('>') == 0;
  if (Line.consume_front("\""))
    return Line.count('"') == 0;
  return false;
}

bool allowImplicitCompletion(llvm::StringRef Content, unsigned Offset) {
  // Look at last line before completion point only.
  Content = Content.take_front(Offset);
  auto Pos = Content.rfind('\n');
  if (Pos != llvm::StringRef::npos)
    Content = Content.substr(Pos + 1);

  // Complete after scope operators.
  if (Content.ends_with(".") || Content.ends_with("->") ||
      Content.ends_with("::") || Content.ends_with("/*"))
    return true;
  // Complete after `#include <` and #include `<foo/`.
  if ((Content.ends_with("<") || Content.ends_with("\"") ||
       Content.ends_with("/")) &&
      isIncludeFile(Content))
    return true;

  // Complete words. Give non-ascii characters the benefit of the doubt.
  return !Content.empty() && (isAsciiIdentifierContinue(Content.back()) ||
                              !llvm::isASCII(Content.back()));
}

} // namespace clangd
} // namespace clang
