//===--- SwiftSourceDocInfo.cpp -------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "SourceKit/Support/FileSystemProvider.h"
#include "SourceKit/Support/ImmutableTextBuffer.h"
#include "SourceKit/Support/Logging.h"
#include "SourceKit/Support/UIdent.h"
#include "SwiftASTManager.h"
#include "SwiftEditorDiagConsumer.h"
#include "SwiftLangSupport.h"

#include "swift/AST/ASTDemangler.h"
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/Decl.h"
#include "swift/AST/LookupKinds.h"
#include "swift/AST/ModuleNameLookup.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/SwiftNameTranslation.h"
#include "swift/AST/GenericSignature.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/IDE/CommentConversion.h"
#include "swift/IDE/ModuleInterfacePrinting.h"
#include "swift/IDE/SourceEntityWalker.h"
#include "swift/IDE/Utils.h"
#include "swift/IDE/Refactoring.h"
#include "swift/IDE/IDERequests.h"
#include "swift/Markup/XMLUtils.h"
#include "swift/Sema/IDETypeChecking.h"
#include "swift/SymbolGraphGen/SymbolGraphGen.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Index/USRGeneration.h"
#include "clang/Lex/Lexer.h"

#include "llvm/Support/MemoryBuffer.h"

#include <numeric>

using namespace SourceKit;
using namespace swift;
using namespace swift::ide;

namespace {
class AnnotatedDeclarationPrinter : public XMLEscapingPrinter {
public:
  AnnotatedDeclarationPrinter(raw_ostream &OS)
    :XMLEscapingPrinter(OS) { }

private:
  void printTypeRef(
      Type T, const TypeDecl *TD, Identifier Name,
      PrintNameContext NameContext = PrintNameContext::Normal) override {
    printXML("<Type usr=\"");
    SwiftLangSupport::printUSR(TD, OS);
    printXML("\">");
    StreamPrinter::printTypeRef(T, TD, Name, NameContext);
    printXML("</Type>");
  }
};
} // end anonymous namespace

static StringRef getTagForDecl(const Decl *D, bool isRef) {
  auto UID = SwiftLangSupport::getUIDForDecl(D, isRef);
  static const char *prefix = "source.lang.swift.";
  assert(UID.getName().startswith(prefix));
  return UID.getName().drop_front(strlen(prefix));
}

static StringRef ExternalParamNameTag = "decl.var.parameter.argument_label";
static StringRef LocalParamNameTag = "decl.var.parameter.name";
static StringRef GenericParamNameTag = "decl.generic_type_param.name";
static StringRef SyntaxKeywordTag = "syntaxtype.keyword";

static StringRef getTagForParameter(PrintStructureKind context) {
  switch (context) {
  case PrintStructureKind::FunctionParameter:
    return "decl.var.parameter";
  case PrintStructureKind::FunctionReturnType:
    return "decl.function.returntype";
  case PrintStructureKind::FunctionType:
    return "";
  case PrintStructureKind::TupleType:
    return "tuple";
  case PrintStructureKind::TupleElement:
    return "tuple.element";
  case PrintStructureKind::GenericParameter:
    return "decl.generic_type_param";
  case PrintStructureKind::GenericRequirement:
    return "decl.generic_type_requirement";
  case PrintStructureKind::BuiltinAttribute:
    return "syntaxtype.attribute.builtin";
  case PrintStructureKind::NumberLiteral:
    return "syntaxtype.number";
  case PrintStructureKind::StringLiteral:
    return "syntaxtype.string";
  case PrintStructureKind::DefaultArgumentClause:
  case PrintStructureKind::DeclGenericParameterClause:
  case PrintStructureKind::DeclGenericRequirementClause:
  case PrintStructureKind::EffectsSpecifiers:
  case PrintStructureKind::DeclResultTypeClause:
  case PrintStructureKind::FunctionParameterList:
  case PrintStructureKind::FunctionParameterType:
    // These kinds are ignored by 'isIgnoredPrintStructureKind()'
    llvm_unreachable("ignored structure kind");
  }
  llvm_unreachable("unexpected structure kind");
}

static StringRef getDeclNameTagForDecl(const Decl *D) {
  switch (D->getKind()) {
  case DeclKind::Param:
    // When we're examining the parameter itself, it is the local name that is
    // the name of the variable.
    return LocalParamNameTag;
  case DeclKind::GenericTypeParam:
    return ""; // Handled by printName.
  case DeclKind::Constructor:
  case DeclKind::Destructor:
  case DeclKind::Subscript:
    // The names 'init'/'deinit'/'subscript' are actually keywords.
    return SyntaxKeywordTag;
  default:
    return "decl.name";
  }
}

namespace {
/// A typesafe union of contexts that the printer can be inside.
/// Currently: Decl, PrintStructureKind
class PrintContext {
  // Use the low bit to determine the type; store the enum value shifted left
  // to leave the low bit free.
  const uintptr_t value;
  static constexpr unsigned declTag = 0;
  static constexpr unsigned PrintStructureKindTag = 1;
  static constexpr unsigned typeTag = 2;
  static constexpr unsigned tagMask = 3;
  static constexpr unsigned tagShift = 2;
  bool hasTag(unsigned tag) const { return (value & tagMask) == tag; }

public:
  PrintContext(const Decl *D) : value(uintptr_t(D)) {
    static_assert(llvm::PointerLikeTypeTraits<Decl *>::NumLowBitsAvailable >=
                      tagShift,
                  "missing spare bit in Decl *");
  }
  PrintContext(PrintStructureKind K)
      : value((uintptr_t(K) << tagShift) | PrintStructureKindTag) {}
  PrintContext(TypeLoc unused) : value(typeTag) {}

  /// Get the context as a Decl, or nullptr.
  const Decl *getDecl() const {
    return hasTag(declTag) ? (const Decl *)value : nullptr;
  }
  /// Get the context as a PrintStructureKind, or None.
  Optional<PrintStructureKind> getPrintStructureKind() const {
    if (!hasTag(PrintStructureKindTag))
      return None;
    return PrintStructureKind(value >> tagShift);
  }
  /// Whether this is a PrintStructureKind context of the given \p kind.
  bool is(PrintStructureKind kind) const {
    auto storedKind = getPrintStructureKind();
    return storedKind && *storedKind == kind;
  }
  bool isType() const { return hasTag(typeTag); }
};

/// An ASTPrinter for annotating declarations with XML tags that describe the
/// key substructure of the declaration for CursorInfo/DocInfo.
///
/// Prints declarations with decl- and type-specific tags derived from the
/// UIDs used for decl/refs. For example (including newlines purely for ease of
/// reading):
///
/// \verbatim
///   <decl.function.free>
///     func <decl.name>foo</decl.name>
///     (
///     <decl.var.parameter>
///       <decl.var.parameter.name>x</decl.var.parameter.name>:
///       <ref.struct usr="Si">Int</ref.struct>
///     </decl.var.parameter>
///     ) -> <decl.function.returntype>
///            <ref.struct usr="Si">Int</ref.struct></decl.function.returntype>
///  </decl.function.free>
/// \endverbatim
class FullyAnnotatedDeclarationPrinter final : public XMLEscapingPrinter {
public:
  FullyAnnotatedDeclarationPrinter(raw_ostream &OS) : XMLEscapingPrinter(OS) {}

private:

  // MARK: The ASTPrinter callback interface.

  void printDeclPre(const Decl *D, Optional<BracketOptions> Bracket) override {
    contextStack.emplace_back(PrintContext(D));
    openTag(getTagForDecl(D, /*isRef=*/false));
  }
  void printDeclPost(const Decl *D, Optional<BracketOptions> Bracket) override {
    assert(contextStack.back().getDecl() == D && "unmatched printDeclPre");
    contextStack.pop_back();
    closeTag(getTagForDecl(D, /*isRef=*/false));
  }

  void printDeclLoc(const Decl *D) override {
    auto tag = getDeclNameTagForDecl(D);
    if (!tag.empty())
      openTag(tag);
  }
  void printDeclNameEndLoc(const Decl *D) override {
    auto tag = getDeclNameTagForDecl(D);
    if (!tag.empty())
      closeTag(tag);
  }

  void printTypePre(const TypeLoc &TL) override {
    auto tag = getTypeTagForCurrentContext();
    contextStack.emplace_back(PrintContext(TL));
    if (!tag.empty())
      openTag(tag);
  }
  void printTypePost(const TypeLoc &TL) override {
    assert(contextStack.back().isType());
    contextStack.pop_back();
    auto tag = getTypeTagForCurrentContext();
    if (!tag.empty())
      closeTag(tag);
  }

  bool isIgnoredPrintStructureKind(PrintStructureKind kind) {
    switch (kind) {
    case PrintStructureKind::DefaultArgumentClause:
    case PrintStructureKind::DeclGenericParameterClause:
    case PrintStructureKind::DeclGenericRequirementClause:
    case PrintStructureKind::EffectsSpecifiers:
    case PrintStructureKind::DeclResultTypeClause:
    case PrintStructureKind::FunctionParameterList:
    case PrintStructureKind::FunctionParameterType:
      return true;
    default:
      return false;
    }
  }

  void printStructurePre(PrintStructureKind kind, const Decl *D) override {
    if (isIgnoredPrintStructureKind(kind))
      return;
    if (kind == PrintStructureKind::TupleElement ||
        kind == PrintStructureKind::TupleType)
      fixupTuple(kind);

    contextStack.emplace_back(PrintContext(kind));
    auto tag = getTagForParameter(kind);
    if (tag.empty())
      return;

    if (D && kind == PrintStructureKind::GenericParameter) {
      assert(isa<ValueDecl>(D) && "unexpected non-value decl for param");
      openTagWithUSRForDecl(tag, cast<ValueDecl>(D));
    } else {
      openTag(tag);
    }
  }
  void printStructurePost(PrintStructureKind kind, const Decl *D) override {
    if (isIgnoredPrintStructureKind(kind))
      return;
    if (kind == PrintStructureKind::TupleElement ||
        kind == PrintStructureKind::TupleType) {
      auto prev = contextStack.pop_back_val();
      (void)prev;
      fixupTuple(kind);
      assert(prev.is(kind) && "unmatched printStructurePre");
    } else {
      assert(contextStack.back().is(kind) && "unmatched printStructurePre");
      contextStack.pop_back();
    }

    auto tag = getTagForParameter(kind);
    if (!tag.empty())
      closeTag(tag);
  }

  void printNamePre(PrintNameContext context) override {
    auto tag = getTagForPrintNameContext(context);
    if (!tag.empty())
      openTag(tag);
  }
  void printNamePost(PrintNameContext context) override {
    auto tag = getTagForPrintNameContext(context);
    if (!tag.empty())
      closeTag(tag);
  }

  void printTypeRef(
      Type T, const TypeDecl *TD, Identifier name,
      PrintNameContext NameContext = PrintNameContext::Normal) override {
    auto tag = getTagForDecl(TD, /*isRef=*/true);
    openTagWithUSRForDecl(tag, TD);
    insideRef = true;
    XMLEscapingPrinter::printTypeRef(T, TD, name, NameContext);
    insideRef = false;
    closeTag(tag);
  }

  // MARK: Convenience functions for printing.

  void openTag(StringRef tag) { OS << "<" << tag << ">"; }
  void closeTag(StringRef tag) { OS << "</" << tag << ">"; }

  void openTagWithUSRForDecl(StringRef tag, const ValueDecl *VD) {
    OS << "<" << tag << " usr=\"";
    SwiftLangSupport::printUSR(VD, OS);
    OS << "\">";
  }

  // MARK: Misc.

  StringRef getTypeTagForCurrentContext() const {
    if (contextStack.empty())
      return "";

    static StringRef parameterTypeTag = "decl.var.parameter.type";
    static StringRef genericParamTypeTag = "decl.generic_type_param.constraint";

    auto context = contextStack.back();
    if (context.is(PrintStructureKind::FunctionParameter))
      return parameterTypeTag;
    if (context.is(PrintStructureKind::GenericParameter))
      return genericParamTypeTag;
    if (context.is(PrintStructureKind::TupleElement))
      return "tuple.element.type";
    if (context.getPrintStructureKind().hasValue() || context.isType())
      return "";

    assert(context.getDecl() && "unexpected context kind");
    switch (context.getDecl()->getKind()) {
    case DeclKind::Param:
      return parameterTypeTag;
    case DeclKind::GenericTypeParam:
      return genericParamTypeTag;
    case DeclKind::Var:
      return "decl.var.type";
    case DeclKind::Subscript:
    case DeclKind::Func:
    default:
      return "";
    }
  }

  StringRef getTagForPrintNameContext(PrintNameContext context) {
    if (insideRef)
      return "";

    bool insideParam =
        !contextStack.empty() &&
        contextStack.back().is(PrintStructureKind::FunctionParameter);

    switch (context) {
    case PrintNameContext::FunctionParameterExternal:
      return ExternalParamNameTag;
    case PrintNameContext::FunctionParameterLocal:
      return LocalParamNameTag;
    case PrintNameContext::TupleElement:
      if (insideParam)
        return ExternalParamNameTag;
      return "tuple.element.argument_label";
    case PrintNameContext::Keyword:
    case PrintNameContext::IntroducerKeyword:
      return SyntaxKeywordTag;
    case PrintNameContext::GenericParameter:
      return GenericParamNameTag;
    case PrintNameContext::Attribute:
      return "syntaxtype.attribute.name";
    default:
      return "";
    }
  }

  /// 'Fix' a tuple or tuple element structure kind to be a function parameter
  /// or function type if we are currently inside a function type. This
  /// simplifies functions that need to differentiate a tuple from the input
  /// part of a function type.
  void fixupTuple(PrintStructureKind &kind) {
    assert(kind == PrintStructureKind::TupleElement ||
           kind == PrintStructureKind::TupleType);
    // Skip over 'type's in the context stack.
    for (auto I = contextStack.rbegin(), E = contextStack.rend(); I != E; ++I) {
      if (I->is(PrintStructureKind::FunctionType)) {
        if (kind == PrintStructureKind::TupleElement)
          kind = PrintStructureKind::FunctionParameter;
        else
          kind = PrintStructureKind::FunctionType;
        break;
      } else if (!I->isType()) {
        break;
      }
    }
  }

private:
  /// A stack of contexts being printed, used to determine the context for
  /// subsequent ASTPrinter callbacks.
  llvm::SmallVector<PrintContext, 3> contextStack;
  bool insideRef = false;
};
} // end anonymous namespace

static Type findBaseTypeForReplacingArchetype(const ValueDecl *VD, const Type Ty) {
  if (Ty.isNull())
    return Type();

  // Find the nominal type decl related to VD.
  if (!VD->getDeclContext()->isTypeContext())
    return Type();

  return Ty->getRValueType()->getInOutObjectType()->getMetatypeInstanceType();
}

static void printAnnotatedDeclaration(const ValueDecl *VD,
                                      const Type BaseTy,
                                      raw_ostream &OS) {
  AnnotatedDeclarationPrinter Printer(OS);
  PrintOptions PO = PrintOptions::printQuickHelpDeclaration();
  if (BaseTy) {
    PO.setBaseType(BaseTy);
    PO.PrintAsMember = true;
  }

  // If it's implicit, try to find an overridden ValueDecl that's not implicit.
  // This will ensure we can properly annotate TypeRepr with a usr
  // in AnnotatedDeclarationPrinter.
  while (VD->isImplicit() && VD->getOverriddenDecl())
    VD = VD->getOverriddenDecl();

  // VD may be a compiler synthesized member, constructor, or shorthand argument
  // so always print it even if it's implicit.
  //
  // FIXME: Update PrintOptions::printQuickHelpDeclaration to print implicit
  // decls by default. That causes issues due to newlines being printed before
  // implicit OpaqueTypeDecls at time of writing.
  PO.TreatAsExplicitDeclList.push_back(VD);

  // Wrap this up in XML, as that's what we'll use for documentation comments.
  OS<<"<Declaration>";
  VD->print(Printer, PO);
  OS<<"</Declaration>";
}

void SwiftLangSupport::printFullyAnnotatedDeclaration(const ValueDecl *VD,
                                                      Type BaseTy,
                                                      raw_ostream &OS) {
  FullyAnnotatedDeclarationPrinter Printer(OS);
  PrintOptions PO = PrintOptions::printQuickHelpDeclaration();
  if (BaseTy) {
    PO.setBaseType(BaseTy);
    PO.PrintAsMember = true;
  }

  // If it's implicit, try to find an overridden ValueDecl that's not implicit.
  // This will ensure we can properly annotate TypeRepr with a usr
  // in AnnotatedDeclarationPrinter.
  while (VD->isImplicit() && VD->getOverriddenDecl())
    VD = VD->getOverriddenDecl();

  // VD may be a compiler synthesized member, constructor, or shorthand argument
  // so always print it even if it's implicit.
  //
  // FIXME: Update PrintOptions::printQuickHelpDeclaration to print implicit
  // decls by default. That causes issues due to newlines being printed before
  // implicit OpaqueTypeDecls at time of writing.
  PO.TreatAsExplicitDeclList.push_back(VD);

  VD->print(Printer, PO);
}

void SwiftLangSupport::printFullyAnnotatedDeclaration(const ExtensionDecl *ED,
                                                      raw_ostream &OS) {
  FullyAnnotatedDeclarationPrinter Printer(OS);
  PrintOptions PO = PrintOptions::printQuickHelpDeclaration();
  ED->print(Printer, PO);
}

void SwiftLangSupport::printFullyAnnotatedSynthesizedDeclaration(
    const swift::ValueDecl *VD, TypeOrExtensionDecl Target,
    llvm::raw_ostream &OS) {
  FullyAnnotatedDeclarationPrinter Printer(OS);
  PrintOptions PO = PrintOptions::printQuickHelpDeclaration();
  PO.initForSynthesizedExtension(Target);
  PO.PrintAsMember = true;
  VD->print(Printer, PO);
}

void SwiftLangSupport::printFullyAnnotatedSynthesizedDeclaration(
    const swift::ExtensionDecl *ED, TypeOrExtensionDecl Target,
    llvm::raw_ostream &OS) {
  FullyAnnotatedDeclarationPrinter Printer(OS);
  PrintOptions PO = PrintOptions::printQuickHelpDeclaration();
  PO.initForSynthesizedExtension(Target);
  ED->print(Printer, PO);
}

template <typename FnTy>
static void walkRelatedDecls(const ValueDecl *VD, const FnTy &Fn) {
  if (isa<ParamDecl>(VD))
    return; // Parameters don't have interesting related declarations.

  auto &ctx = VD->getASTContext();

  llvm::SmallDenseMap<DeclName, unsigned, 16> NamesSeen;
  ++NamesSeen[VD->getName()];


  auto *DC = VD->getDeclContext();
  bool typeLookup = DC->isTypeContext();

  SmallVector<ValueDecl *, 4> results;

  if (typeLookup) {
    auto type = DC->getDeclaredInterfaceType();
    if (!type->is<ErrorType>()) {
      DC->lookupQualified(type, DeclNameRef(VD->getBaseName()),
                          NL_QualifiedDefault, results);
    }
  } else {
    namelookup::lookupInModule(DC->getModuleScopeContext(),
                               VD->getBaseName(), results,
                               NLKind::UnqualifiedLookup,
                               namelookup::ResolutionKind::Overloadable,
                               DC->getModuleScopeContext(),
                               NL_UnqualifiedDefault);
  }

  SmallVector<ValueDecl *, 8> RelatedDecls;
  for (auto result : results) {
    if (result->getAttrs().isUnavailable(ctx))
      continue;

    if (result != VD) {
      ++NamesSeen[result->getName()];
      RelatedDecls.push_back(result);
    }
  }

  // Now provide the results along with whether the name is duplicate or not.
  for (auto result : RelatedDecls)
    Fn(result, typeLookup, NamesSeen[result->getName()] > 1);
}

//===----------------------------------------------------------------------===//
// SwiftLangSupport::getCursorInfo
//===----------------------------------------------------------------------===//

static StringRef getSourceToken(unsigned Offset,
                                ImmutableTextSnapshotRef Snap) {
  auto MemBuf = Snap->getBuffer()->getInternalBuffer();

  // FIXME: Invalid offset shouldn't reach here.
  if (Offset >= MemBuf->getBufferSize())
    return StringRef();

  SourceManager SM;
  auto MemBufRef = llvm::MemoryBuffer::getMemBuffer(MemBuf->getBuffer(),
                                                 MemBuf->getBufferIdentifier());
  auto BufId = SM.addNewSourceBuffer(std::move(MemBufRef));
  SourceLoc Loc = SM.getLocForOffset(BufId, Offset);
  return Lexer::getTokenAtLocation(SM, Loc).getText();
}

static llvm::Optional<unsigned>
mapOffsetToOlderSnapshot(unsigned Offset,
                         ImmutableTextSnapshotRef NewSnap,
                         ImmutableTextSnapshotRef OldSnap) {
  SmallVector<ReplaceImmutableTextUpdateRef, 16> Updates;
  OldSnap->foreachReplaceUntil(NewSnap,
    [&](ReplaceImmutableTextUpdateRef Upd)->bool {
      Updates.push_back(Upd);
      return true;
    });

  // Walk the updates backwards and "undo" them.
  for (auto I = Updates.rbegin(), E = Updates.rend(); I != E; ++I) {
    auto Upd = *I;
    if (Upd->getByteOffset() <= Offset &&
        Offset < Upd->getByteOffset() + Upd->getText().size())
      return None; // Offset is part of newly inserted text.

    if (Upd->getByteOffset() <= Offset) {
      Offset += Upd->getLength(); // "bring back" what was removed.
      Offset -= Upd->getText().size(); // "remove" what was added.
    }
  }
  return Offset;
}

static llvm::Optional<unsigned>
mapOffsetToNewerSnapshot(unsigned Offset,
                         ImmutableTextSnapshotRef OldSnap,
                         ImmutableTextSnapshotRef NewSnap) {
  bool Completed = OldSnap->foreachReplaceUntil(NewSnap,
    [&](ReplaceImmutableTextUpdateRef Upd)->bool {
      if (Upd->getByteOffset() <= Offset &&
          Offset < Upd->getByteOffset() + Upd->getLength())
        return false; // Offset is part of removed text.

      if (Upd->getByteOffset() <= Offset) {
        Offset += Upd->getText().size();
        Offset -= Upd->getLength();
      }
      return true;
    });

  if (Completed)
    return Offset;
  return None;
}

/// Tries to remap the location from a previous snapshot to the latest one and
/// then sets the location's line and column.
static void mapLocToLatestSnapshot(
    SwiftLangSupport &Lang, LocationInfo &Location,
    ArrayRef<ImmutableTextSnapshotRef> PreviousASTSnaps) {
  auto EditorDoc = Lang.getEditorDocuments()->findByPath(Location.Filename);
  if (!EditorDoc)
    return;

  ImmutableTextSnapshotRef LatestSnap = EditorDoc->getLatestSnapshot();
  if (!LatestSnap)
    return;

  for (auto &PrevSnap : PreviousASTSnaps) {
    if (PrevSnap->isFromSameBuffer(LatestSnap)) {
      if (PrevSnap->getStamp() == LatestSnap->getStamp())
        break;

      auto OptBegin = mapOffsetToNewerSnapshot(Location.Offset,
                                               PrevSnap, LatestSnap);
      if (!OptBegin.hasValue()) {
        Location.Filename = StringRef();
        return;
      }

      auto OptEnd = mapOffsetToNewerSnapshot(Location.Offset +
                                             Location.Length,
                                             PrevSnap, LatestSnap);
      if (!OptEnd.hasValue()) {
        Location.Filename = StringRef();
        return;
      }

      Location.Offset = *OptBegin;
      Location.Length = *OptEnd - *OptBegin;
    }
  }

  std::tie(Location.Line, Location.Column) =
      LatestSnap->getBuffer()->getLineAndColumn(Location.Offset);
}


/// Returns true for error.
static bool passCursorInfoForModule(ModuleEntity Mod,
                                    SwiftInterfaceGenMap &IFaceGenContexts,
                                    const CompilerInvocation &Invok,
                       std::function<void(const RequestResult<CursorInfoData> &)> Receiver) {
  std::string FullName = Mod.getFullName();
  SmallVector<CursorSymbolInfo, 1> Symbols;
  SmallVector<StringRef, 4> ModuleGroups;

  CursorSymbolInfo &Symbol = Symbols.emplace_back();
  Symbol.Kind = SwiftLangSupport::getUIDForModuleRef();
  Symbol.Name = Mod.getName();
  Symbol.ModuleName = FullName;
  if (auto IFaceGenRef = IFaceGenContexts.find(Symbol.ModuleName, Invok))
    Symbol.ModuleInterfaceName = IFaceGenRef->getDocumentName();
  Symbol.IsSystem = Mod.isSystemModule();
  if (auto MD = Mod.getAsSwiftModule()) {
    ide::collectModuleGroups(const_cast<ModuleDecl *>(MD), ModuleGroups);
    Symbol.ModuleGroupArray = llvm::makeArrayRef(ModuleGroups);
  }

  CursorInfoData Data;
  Data.Symbols = llvm::makeArrayRef(Symbols);
  Receiver(RequestResult<CursorInfoData>::fromResult(Data));
  return false;
}

static void
collectAvailableRenameInfo(const ValueDecl *VD, Optional<RenameRefInfo> RefInfo,
                           SmallVectorImpl<RefactoringInfo> &Refactorings) {
  SmallVector<RenameAvailabilityInfo, 2> Renames;
  collectRenameAvailabilityInfo(VD, RefInfo, Renames);
  for (auto Info : Renames) {
    Refactorings.emplace_back(
        SwiftLangSupport::getUIDForRefactoringKind(Info.Kind),
        ide::getDescriptiveRefactoringKindName(Info.Kind),
        ide::getDescriptiveRenameUnavailableReason(Info.AvailableKind));
  }
}

static void collectAvailableRefactoringsOtherThanRename(
    ResolvedCursorInfo CursorInfo,
    SmallVectorImpl<RefactoringInfo> &Refactorings) {
  SmallVector<RefactoringKind, 8> Kinds;
  collectAvailableRefactorings(CursorInfo, Kinds, /*ExcludeRename*/ true);
  for (auto Kind : Kinds) {
    Refactorings.emplace_back(SwiftLangSupport::getUIDForRefactoringKind(Kind),
                              ide::getDescriptiveRefactoringKindName(Kind),
                              StringRef());
  }
}

static Optional<unsigned>
getParamParentNameOffset(const ValueDecl *VD, SourceLoc Cursor) {
  if (Cursor.isInvalid())
    return None;
  SourceLoc Loc;
  if (auto PD = dyn_cast<ParamDecl>(VD)) {

    // Avoid returning parent loc for internal-only names.
    if (PD->getArgumentNameLoc().isValid() && PD->getArgumentNameLoc() != Cursor)
      return None;
    auto *DC = PD->getDeclContext();
    switch (DC->getContextKind()) {
      case DeclContextKind::SubscriptDecl:
        Loc = cast<SubscriptDecl>(DC)->getNameLoc();
        break;
      case DeclContextKind::AbstractFunctionDecl:
        Loc = cast<AbstractFunctionDecl>(DC)->getNameLoc();
        break;
      default:
        break;
    }
  }
  if (Loc.isInvalid())
    return None;
  auto &SM = VD->getASTContext().SourceMgr;
  return SM.getLocOffsetInBuffer(Loc, SM.findBufferContainingLoc(Loc));
}

static StringRef getModuleName(const ValueDecl *VD,
                               llvm::BumpPtrAllocator &Allocator) {
  ASTContext &Ctx = VD->getASTContext();
  ClangImporter *Importer =
      static_cast<ClangImporter *>(Ctx.getClangModuleLoader());
  if (auto ClangNode = VD->getClangNode()) {
    if (const auto *ClangMod = Importer->getClangOwningModule(ClangNode))
      return copyString(Allocator, ClangMod->getFullModuleName());
    return "";
  }

  ModuleDecl *MD = VD->getModuleContext();
  // If the decl is from a cross-import overlay module, report the
  // overlay's declaring module as the owning module.
  if (ModuleDecl *Declaring = MD->getDeclaringModuleIfCrossImportOverlay())
    MD = Declaring;
  return MD->getNameStr();
}

struct DeclInfo {
  const ValueDecl *VD;
  Type ContainerType;
  bool IsRef;
  bool IsDynamic;
  ArrayRef<NominalTypeDecl *> ReceiverTypes;

  /// If VD is a synthesized property wrapper backing storage (_foo) or
  /// projected value ($foo) of a property (foo), the property instead.
  /// Otherwise, VD.
  const ValueDecl *OriginalProperty = nullptr;
  bool Unavailable = true;
  Type BaseType;
  bool InSynthesizedExtension = false;

  DeclInfo(const ValueDecl *VD, Type ContainerType, bool IsRef, bool IsDynamic,
           ArrayRef<NominalTypeDecl *> ReceiverTypes,
           const CompilerInvocation &Invoc)
      : VD(VD), ContainerType(ContainerType), IsRef(IsRef),
        IsDynamic(IsDynamic), ReceiverTypes(ReceiverTypes) {
    if (VD == nullptr)
      return;

    // The synthesized properties $foo and _foo aren't unavailable even if
    // the original property foo is, so check them rather than the original
    // property.
    Unavailable = AvailableAttr::isUnavailable(VD);
    // No point computing the rest since they won't be used anyway.
    if (Unavailable)
      return;

    OriginalProperty = VD;
    if (auto *VarD = dyn_cast<VarDecl>(VD)) {
      if (auto *Wrapped = VarD->getOriginalWrappedProperty())
        OriginalProperty = Wrapped;
    }

    BaseType = findBaseTypeForReplacingArchetype(VD, ContainerType);
    InSynthesizedExtension = false;
    if (BaseType) {
      if (auto Target = BaseType->getAnyNominal()) {
        SynthesizedExtensionAnalyzer Analyzer(
            Target, PrintOptions::printModuleInterface(
                        Invoc.getFrontendOptions().PrintFullConvention));
        InSynthesizedExtension = Analyzer.isInSynthesizedExtension(VD);
      }
    }
  }
};

static StringRef copyAndClearString(llvm::BumpPtrAllocator &Allocator,
                                    SmallVectorImpl<char> &Str) {
  auto Ref = copyString(Allocator, StringRef(Str.data(), Str.size()));
  Str.clear();
  return Ref;
}

template <typename T>
static ArrayRef<T> copyAndClearArray(llvm::BumpPtrAllocator &Allocator,
                                     SmallVectorImpl<T> &Array) {
  auto Ref = copyArray(Allocator, llvm::makeArrayRef(Array));
  Array.clear();
  return Ref;
}

static void setLocationInfoForClangNode(ClangNode ClangNode,
                                        ClangImporter *Importer,
                                        LocationInfo &Location) {
  clang::ASTContext &ClangCtx = Importer->getClangASTContext();
  clang::SourceManager &ClangSM = ClangCtx.getSourceManager();

  clang::SourceRange SR = ClangNode.getLocation();
  if (auto MD =
          dyn_cast_or_null<clang::ObjCMethodDecl>(ClangNode.getAsDecl())) {
    SR = clang::SourceRange(MD->getSelectorStartLoc(),
                            MD->getDeclaratorEndLoc());
  }

  clang::CharSourceRange CharRange =
      clang::Lexer::makeFileCharRange(clang::CharSourceRange::getTokenRange(SR),
                                      ClangSM, ClangCtx.getLangOpts());
  if (CharRange.isInvalid())
    return;

  std::pair<clang::FileID, unsigned> Decomp =
      ClangSM.getDecomposedLoc(CharRange.getBegin());
  if (!Decomp.first.isInvalid()) {
    if (auto FE = ClangSM.getFileEntryForID(Decomp.first)) {
      Location.Filename = FE->getName();

      std::pair<clang::FileID, unsigned> EndDecomp =
          ClangSM.getDecomposedLoc(CharRange.getEnd());

      Location.Offset = Decomp.second;
      Location.Length = EndDecomp.second - Decomp.second;
      Location.Line = ClangSM.getLineNumber(Decomp.first, Decomp.second);
      Location.Column = ClangSM.getColumnNumber(Decomp.first, Decomp.second);
    }
  }
}

static unsigned getCharLength(SourceManager &SM, SourceRange TokenRange) {
  SourceLoc CharEndLoc = Lexer::getLocForEndOfToken(SM, TokenRange.End);
  return SM.getByteDistance(TokenRange.Start, CharEndLoc);
}

static void setLocationInfo(const ValueDecl *VD,
                            LocationInfo &Location) {
  ASTContext &Ctx = VD->getASTContext();
  SourceManager &SM = Ctx.SourceMgr;

  auto ClangNode = VD->getClangNode();

  auto Loc = VD->getLoc(/*SerializedOK=*/true);
  if (Loc.isValid()) {
    auto getSignatureRange = [&](const ValueDecl *VD) -> Optional<unsigned> {
      if (auto FD = dyn_cast<AbstractFunctionDecl>(VD)) {
        SourceRange R = FD->getSignatureSourceRange();
        if (R.isValid())
          return getCharLength(SM, R);
      }
      return None;
    };
    unsigned NameLen;
    if (auto SigLen = getSignatureRange(VD)) {
      NameLen = SigLen.getValue();
    } else if (VD->hasName()) {
      NameLen = VD->getBaseName().userFacingName().size();
    } else {
      NameLen = getCharLength(SM, Loc);
    }

    unsigned DeclBufID = SM.findBufferContainingLoc(Loc);
    Location.Filename = SM.getIdentifierForBuffer(DeclBufID);
    Location.Offset = SM.getLocOffsetInBuffer(Loc, DeclBufID);
    Location.Length = NameLen;
    std::tie(Location.Line, Location.Column) = SM.getLineAndColumnInBuffer(
        Loc, DeclBufID);
  } else if (ClangNode) {
    ClangImporter *Importer =
        static_cast<ClangImporter*>(Ctx.getClangModuleLoader());
    setLocationInfoForClangNode(ClangNode, Importer, Location);
  }
}

static llvm::Error
fillSymbolInfo(CursorSymbolInfo &Symbol, const DeclInfo &DInfo,
               ModuleDecl *MainModule, SourceLoc CursorLoc, bool AddSymbolGraph,
               SwiftLangSupport &Lang, const CompilerInvocation &Invoc,
               ArrayRef<ImmutableTextSnapshotRef> PreviousSnaps,
               llvm::BumpPtrAllocator &Allocator) {
  SmallString<256> Buffer;
  SmallVector<StringRef, 4> Strings;
  llvm::raw_svector_ostream OS(Buffer);

  Symbol.DeclarationLang = SwiftLangSupport::getUIDForDeclLanguage(DInfo.VD);
  Symbol.Kind = SwiftLangSupport::getUIDForDecl(DInfo.VD, DInfo.IsRef);

  SwiftLangSupport::printDisplayName(DInfo.VD, OS);
  Symbol.Name = copyAndClearString(Allocator, Buffer);

  SwiftLangSupport::printUSR(DInfo.OriginalProperty, OS);
  if (DInfo.InSynthesizedExtension) {
    OS << LangSupport::SynthesizedUSRSeparator;
    SwiftLangSupport::printUSR(DInfo.BaseType->getAnyNominal(), OS);
  }
  Symbol.USR = copyAndClearString(Allocator, Buffer);

  {
    PrintOptions Options;
    Options.PrintTypeAliasUnderlyingType = true;
    DInfo.VD->getInterfaceType().print(OS, Options);
  }
  Symbol.TypeName = copyAndClearString(Allocator, Buffer);

  SwiftLangSupport::printDeclTypeUSR(DInfo.VD, OS);
  Symbol.TypeUSR = copyAndClearString(Allocator, Buffer);

  if (DInfo.ContainerType && !DInfo.ContainerType->hasArchetype()) {
    SwiftLangSupport::printTypeUSR(DInfo.ContainerType, OS);
  }
  Symbol.ContainerTypeUSR = copyAndClearString(Allocator, Buffer);

  ide::getDocumentationCommentAsXML(DInfo.OriginalProperty, OS);
  Symbol.DocComment = copyAndClearString(Allocator, Buffer);

  {
    auto *Group = DInfo.InSynthesizedExtension ? DInfo.BaseType->getAnyNominal()
                                               : DInfo.VD;
    if (auto Name = Group->getGroupName())
      Symbol.GroupName = Name.getValue();
  }

  ide::getLocalizationKey(DInfo.VD, OS);
  Symbol.LocalizationKey = copyAndClearString(Allocator, Buffer);

  printAnnotatedDeclaration(DInfo.VD, DInfo.BaseType, OS);
  Symbol.AnnotatedDeclaration = copyAndClearString(Allocator, Buffer);

  SwiftLangSupport::printFullyAnnotatedDeclaration(DInfo.VD, DInfo.BaseType,
                                                   OS);
  Symbol.FullyAnnotatedDeclaration = copyAndClearString(Allocator, Buffer);

  if (AddSymbolGraph) {
    SmallVector<symbolgraphgen::PathComponent, 4> PathComponents;
    SmallVector<symbolgraphgen::FragmentInfo, 8> FragmentInfos;
    symbolgraphgen::SymbolGraphOptions Options{
        "",
        Invoc.getLangOptions().Target,
        /*PrettyPrint=*/false,
        AccessLevel::Private,
        /*EmitSynthesizedMembers*/ false,
        /*PrintMessages*/ false,
        /*SkipInheritedDocs*/ false,
        /*IncludeSPISymbols*/ true,
    };

    symbolgraphgen::printSymbolGraphForDecl(DInfo.VD, DInfo.BaseType,
                                            DInfo.InSynthesizedExtension,
                                            Options, OS, PathComponents,
                                            FragmentInfos);
    Symbol.SymbolGraph = copyAndClearString(Allocator, Buffer);

    SmallVector<ParentInfo, 4> Parents;
    for (auto &Component : PathComponents) {
      SwiftLangSupport::printUSR(Component.VD, OS);
      Parents.emplace_back(copyString(Allocator, Component.Title),
                           Component.Kind,
                           copyAndClearString(Allocator, Buffer));
    };
    Symbol.ParentContexts = copyArray(Allocator, llvm::makeArrayRef(Parents));

    SmallVector<ReferencedDeclInfo, 8> ReferencedDecls;
    for (auto &FI: FragmentInfos) {
      SmallVector<ParentInfo, 4> FIParents;
      for (auto &Component: FI.ParentContexts) {
        SwiftLangSupport::printUSR(Component.VD, OS);
        FIParents.emplace_back(copyString(Allocator, Component.Title),
                               Component.Kind,
                               copyAndClearString(Allocator, Buffer));
      }

      ASTContext &Ctx = FI.VD->getASTContext();
      StringRef Filename = "";
      if (auto Loc = FI.VD->getLoc(/*SerializedOK=*/true)) {
        Filename = Ctx.SourceMgr.getDisplayNameForLoc(Loc);
      } else if (auto ClangNode = FI.VD->getClangNode()) {
        auto Loc = ClangNode.getLocation();
        if (Loc.isValid()) {
          Filename = Ctx.getClangModuleLoader()->getClangASTContext()
              .getSourceManager()
              .getFilename(Loc);
        }
      }

      SwiftLangSupport::printUSR(FI.VD, OS);
      ReferencedDecls.emplace_back(
          copyAndClearString(Allocator, Buffer),
          SwiftLangSupport::getUIDForDeclLanguage(FI.VD),
          swift::getAccessLevelSpelling(FI.VD->getFormalAccess()), Filename,
          getModuleName(FI.VD, Allocator),
          FI.VD->getModuleContext()->isSystemModule(),
          FI.VD->isSPI(),
          copyArray(Allocator, llvm::makeArrayRef(FIParents)));
    }
    Symbol.ReferencedSymbols = copyArray(Allocator,
                                         llvm::makeArrayRef(ReferencedDecls));
  }

  Symbol.ModuleName = getModuleName(DInfo.VD, Allocator);
  if (auto IFaceGenRef =
          Lang.getIFaceGenContexts().find(Symbol.ModuleName, Invoc))
    Symbol.ModuleInterfaceName = IFaceGenRef->getDocumentName();

  setLocationInfo(DInfo.OriginalProperty, Symbol.Location);
  if (!Symbol.Location.Filename.empty()) {
    mapLocToLatestSnapshot(Lang, Symbol.Location, PreviousSnaps);
    if (Symbol.Location.Filename.empty()) {
      return llvm::createStringError(
          llvm::inconvertibleErrorCode(),
          "Failed to remap declaration to latest snapshot.");
    }
  }

  ide::walkOverriddenDecls(
      DInfo.VD,
      [&](llvm::PointerUnion<const ValueDecl *, const clang::NamedDecl *> D) {
        // Could have junk in from previous failing USR print
        Buffer.clear();
        if (auto VD = D.dyn_cast<const ValueDecl *>()) {
          if (SwiftLangSupport::printUSR(VD, OS))
            return;
        } else {
          if (clang::index::generateUSRForDecl(
                  D.get<const clang::NamedDecl *>(), Buffer))
            return;
        }
        Strings.push_back(copyAndClearString(Allocator, Buffer));
      });
  Symbol.OverrideUSRs = copyAndClearArray(Allocator, Strings);

  walkRelatedDecls(DInfo.VD, [&](const ValueDecl *RelatedDecl,
                                 bool UseOriginalBase, bool DuplicateName) {
    OS << "<RelatedName usr=\"";
    SwiftLangSupport::printUSR(RelatedDecl, OS);
    OS << "\">";
    if (isa<AbstractFunctionDecl>(RelatedDecl) && DuplicateName) {
      // Related decls are generally overloads, so print parameter types to
      // differentiate them.
      PrintOptions PO;
      PO.SkipAttributes = true;
      PO.PrintStaticKeyword = false;
      PO.PrintSelfAccessKindKeyword = false;
      PO.SkipIntroducerKeywords = true;
      PO.ArgAndParamPrinting =
          PrintOptions::ArgAndParamPrintingMode::ArgumentOnly;
      XMLEscapingPrinter Printer(OS);
      if (UseOriginalBase && DInfo.BaseType) {
        PO.setBaseType(DInfo.BaseType);
        PO.PrintAsMember = true;
      }
      RelatedDecl->print(Printer, PO);
    } else {
      SmallString<128> RelatedBuffer;
      llvm::raw_svector_ostream RelatedOS(RelatedBuffer);
      SwiftLangSupport::printDisplayName(RelatedDecl, RelatedOS);
      swift::markup::appendWithXMLEscaping(OS, RelatedBuffer);
    }
    OS << "</RelatedName>";

    Strings.push_back(copyAndClearString(Allocator, Buffer));
  });
  Symbol.AnnotatedRelatedDeclarations = copyAndClearArray(Allocator, Strings);

  for (auto *ReceiverTy : DInfo.ReceiverTypes) {
    if (!SwiftLangSupport::printUSR(ReceiverTy, OS))
      Strings.push_back(copyAndClearString(Allocator, Buffer));
  }
  Symbol.ReceiverUSRs = copyAndClearArray(Allocator, Strings);

  Symbol.IsSystem = DInfo.VD->getModuleContext()->isSystemModule();
  Symbol.IsDynamic = DInfo.IsDynamic;
  Symbol.IsSynthesized = DInfo.VD->isImplicit();

  Symbol.ParentNameOffset = getParamParentNameOffset(DInfo.VD, CursorLoc);

  return llvm::Error::success();
}

/// Returns true on success, false on error (and sets `Diagnostic` accordingly).
static bool passCursorInfoForDecl(
    const ResolvedCursorInfo &Info, ModuleDecl *MainModule,
    bool AddRefactorings, bool AddSymbolGraph,
    ArrayRef<RefactoringInfo> KnownRefactoringInfo, SwiftLangSupport &Lang,
    const CompilerInvocation &Invoc, std::string &Diagnostic,
    ArrayRef<ImmutableTextSnapshotRef> PreviousSnaps,
    std::function<void(const RequestResult<CursorInfoData> &)> Receiver) {
  DeclInfo OrigInfo(Info.ValueD, Info.ContainerType, Info.IsRef, Info.IsDynamic,
                    Info.ReceiverTypes, Invoc);
  DeclInfo CtorTypeInfo(Info.CtorTyRef, Type(), true, false,
                        ArrayRef<NominalTypeDecl *>(), Invoc);
  DeclInfo &MainInfo = CtorTypeInfo.VD ? CtorTypeInfo : OrigInfo;
  if (MainInfo.Unavailable) {
    Diagnostic = "Unavailable in the current compilation context.";
    return false;
  }

  llvm::BumpPtrAllocator Allocator;

  SmallVector<CursorSymbolInfo, 2> Symbols;
  CursorSymbolInfo &MainSymbol = Symbols.emplace_back();
  // The primary result for constructor calls, eg. `MyType()` should be
  // the type itself, rather than the constructor. The constructor will be
  // added as a secondary result.
  if (auto Err = fillSymbolInfo(MainSymbol, MainInfo, MainModule, Info.Loc,
                                AddSymbolGraph, Lang, Invoc, PreviousSnaps,
                                Allocator)) {
    llvm::handleAllErrors(std::move(Err), [&](const llvm::StringError &E) {
      Diagnostic = E.message();
    });
    return false;
  }
  if (MainInfo.VD != OrigInfo.VD && !OrigInfo.Unavailable) {
    CursorSymbolInfo &CtorSymbol = Symbols.emplace_back();
    if (auto Err = fillSymbolInfo(CtorSymbol, OrigInfo, MainModule, Info.Loc,
                                  AddSymbolGraph, Lang, Invoc, PreviousSnaps,
                                  Allocator)) {
      // Ignore but make sure to remove the partially-filled symbol
      llvm::handleAllErrors(std::move(Err), [&](const llvm::StringError &E) {});
      Symbols.pop_back();
    }
  }

  SmallVector<RefactoringInfo, 8> Refactorings;
  if (AddRefactorings) {
    Optional<RenameRefInfo> RefInfo;
    if (Info.IsRef)
      RefInfo = {Info.SF, Info.Loc, Info.IsKeywordArgument};
    collectAvailableRenameInfo(MainInfo.VD, RefInfo, Refactorings);
    collectAvailableRefactoringsOtherThanRename(Info, Refactorings);
  }
  Refactorings.insert(Refactorings.end(), KnownRefactoringInfo.begin(),
                      KnownRefactoringInfo.end());

  CursorInfoData Data;
  Data.Symbols = llvm::makeArrayRef(Symbols);
  Data.AvailableActions = llvm::makeArrayRef(Refactorings);
  Receiver(RequestResult<CursorInfoData>::fromResult(Data));
  return true;
}

static clang::DeclarationName
getClangDeclarationName(const clang::NamedDecl *ND, NameTranslatingInfo &Info) {
  auto &Ctx = ND->getASTContext();
  auto OrigName = ND->getDeclName();
  assert(SwiftLangSupport::getNameKindForUID(Info.NameKind) == NameKind::ObjC);
  if (Info.BaseName.empty() == Info.ArgNames.empty()) {
    // cannot have both.
    return clang::DeclarationName();
  }
  if (!Info.BaseName.empty()) {
    return clang::DeclarationName(&Ctx.Idents.get(Info.BaseName));
  } else {
    switch (OrigName.getNameKind()) {
    case clang::DeclarationName::ObjCZeroArgSelector:
    case clang::DeclarationName::ObjCOneArgSelector:
    case clang::DeclarationName::ObjCMultiArgSelector:
      break;
    default:
      return clang::DeclarationName();
    }

    auto OrigSel = OrigName.getObjCSelector();
    unsigned NumPieces = OrigSel.isUnarySelector() ? 1 : OrigSel.getNumArgs();
    if (Info.ArgNames.size() > NumPieces)
      return clang::DeclarationName();

    ArrayRef<StringRef> Args = llvm::makeArrayRef(Info.ArgNames);
    std::vector<clang::IdentifierInfo *> Pieces;
    for (unsigned i = 0; i < NumPieces; ++i) {
      if (i >= Info.ArgNames.size() || Info.ArgNames[i].empty()) {
        Pieces.push_back(OrigSel.getIdentifierInfoForSlot(i));
      } else {
        StringRef T = Args[i];
        Pieces.push_back(&Ctx.Idents.get(T.endswith(":") ? T.drop_back() : T));
      }
    }
    return clang::DeclarationName(
        Ctx.Selectors.getSelector(OrigSel.getNumArgs(), Pieces.data()));
  }
}

static DeclName getSwiftDeclName(const ValueDecl *VD,
                                 NameTranslatingInfo &Info) {
  auto &Ctx = VD->getDeclContext()->getASTContext();
  assert(SwiftLangSupport::getNameKindForUID(Info.NameKind) == NameKind::Swift);
  const DeclName OrigName = VD->getName();
  DeclBaseName BaseName = Info.BaseName.empty()
                              ? OrigName.getBaseName()
                              : DeclBaseName(
                                Info.BaseName == "init"
                                  ? DeclBaseName::createConstructor()
                                  : Ctx.getIdentifier(Info.BaseName));
  auto OrigArgs = OrigName.getArgumentNames();
  SmallVector<Identifier, 8> Args(OrigArgs.begin(), OrigArgs.end());
  if (Info.ArgNames.size() > OrigArgs.size())
    return DeclName();
  for (unsigned i = 0; i < OrigArgs.size(); ++i) {
    if (i < Info.ArgNames.size() && !Info.ArgNames[i].empty()) {
      StringRef Arg = Info.ArgNames[i];
      Args[i] = Ctx.getIdentifier(Arg == "_" ? StringRef() : Arg);
    }
  }
  return DeclName(Ctx, BaseName, llvm::makeArrayRef(Args));
}

/// Returns true on success, false on error (and sets `Diagnostic` accordingly).
static bool passNameInfoForDecl(ResolvedCursorInfo CursorInfo,
                                NameTranslatingInfo &Info,
                                std::string &Diagnostic,
                    std::function<void(const RequestResult<NameTranslatingInfo> &)> Receiver) {
  auto *VD = CursorInfo.ValueD;

  // If the given name is not a function name, and the cursor points to
  // a contructor call, we use the type declaration instead of the init
  // declaration to translate the name.
  if (Info.ArgNames.empty() && !Info.IsZeroArgSelector) {
    if (auto *TD = CursorInfo.CtorTyRef) {
      VD = TD;
    }
  }
  switch (SwiftLangSupport::getNameKindForUID(Info.NameKind)) {
  case NameKind::Swift: {
    NameTranslatingInfo Result;
    auto DeclName = getSwiftDeclName(VD, Info);
    if (!DeclName) {
      Diagnostic = "Unable to resolve Swift declaration name.";
      return false;
    }
    auto ResultPair =
        swift::objc_translation::getObjCNameForSwiftDecl(VD, DeclName);
    Identifier Name = ResultPair.first;
    if (!Name.empty()) {
      Result.NameKind = SwiftLangSupport::getUIDForNameKind(NameKind::ObjC);
      Result.BaseName = Name.str();
      Receiver(RequestResult<NameTranslatingInfo>::fromResult(Result));
    } else if (ObjCSelector Selector = ResultPair.second) {
      Result.NameKind = SwiftLangSupport::getUIDForNameKind(NameKind::ObjC);
      SmallString<64> Buffer;
      StringRef Total = Selector.getString(Buffer);
      SmallVector<StringRef, 4> Pieces;
      Total.split(Pieces, ":");
      if (Selector.getNumArgs()) {
        assert(Pieces.back().empty());
        Pieces.pop_back();
      } else {
        Result.IsZeroArgSelector = true;
      }
      Result.ArgNames.insert(Result.ArgNames.begin(), Pieces.begin(), Pieces.end());
      Receiver(RequestResult<NameTranslatingInfo>::fromResult(Result));
    } else {
      Diagnostic = "Unable to resolve name info.";
      return false;
    }
    return true;
  }
  case NameKind::ObjC: {
    ClangImporter *Importer = static_cast<ClangImporter *>(VD->getDeclContext()->
      getASTContext().getClangModuleLoader());

    const clang::NamedDecl *Named = nullptr;
    auto *BaseDecl = VD;

    while (!Named && BaseDecl) {
      Named = dyn_cast_or_null<clang::NamedDecl>(BaseDecl->getClangDecl());
      BaseDecl = BaseDecl->getOverriddenDecl();
    }
    if (!Named) {
      Diagnostic = "Unable to resolve a named declaration.";
      return false;
    }

    auto ObjCName = getClangDeclarationName(Named, Info);
    if (!ObjCName) {
      Diagnostic = "Unable to resolve ObjC declaration name.";
      return false;
    }

    DeclName Name = Importer->importName(Named, ObjCName);
    NameTranslatingInfo Result;
    Result.NameKind = SwiftLangSupport::getUIDForNameKind(NameKind::Swift);
    Result.BaseName = Name.getBaseName().userFacingName();
    llvm::transform(Name.getArgumentNames(),
                    std::back_inserter(Result.ArgNames),
                    [](Identifier Id) { return Id.str(); });
    Receiver(RequestResult<NameTranslatingInfo>::fromResult(Result));
    return true;
  }
  }
}

class CursorRangeInfoConsumer : public SwiftASTConsumer {
protected:
  SwiftLangSupport &Lang;
  SwiftInvocationRef ASTInvok;
  std::string InputFile;
  unsigned Offset;
  unsigned Length;

private:
  const bool TryExistingAST;
  SmallVector<ImmutableTextSnapshotRef, 4> PreviousASTSnaps;

protected:
  bool CancelOnSubsequentRequest;
protected:
  ArrayRef<ImmutableTextSnapshotRef> getPreviousASTSnaps() {
    return llvm::makeArrayRef(PreviousASTSnaps);
  }

public:
  CursorRangeInfoConsumer(StringRef InputFile, unsigned Offset, unsigned Length,
                          SwiftLangSupport &Lang, SwiftInvocationRef ASTInvok,
                          bool TryExistingAST, bool CancelOnSubsequentRequest)
    : Lang(Lang), ASTInvok(ASTInvok),InputFile(InputFile.str()), Offset(Offset),
      Length(Length), TryExistingAST(TryExistingAST),
      CancelOnSubsequentRequest(CancelOnSubsequentRequest) {}

  bool canUseASTWithSnapshots(ArrayRef<ImmutableTextSnapshotRef> Snapshots) override {
    if (!TryExistingAST) {
      LOG_INFO_FUNC(High, "will resolve using up-to-date AST");
      return false;
    }

    // If there is an existing AST and the offset can be mapped back to the
    // document snapshot that was used to create it, then use that AST.
    // The downside is that we may return stale information, but we get the
    // benefit of increased responsiveness, since the request will not be
    // blocked waiting on the AST to be fully typechecked.

    ImmutableTextSnapshotRef InputSnap;
    if (auto EditorDoc = Lang.getEditorDocuments()->findByPath(InputFile))
      InputSnap = EditorDoc->getLatestSnapshot();
    if (!InputSnap)
      return false;

    auto mappedBackOffset = [&]()->llvm::Optional<unsigned> {
      for (auto &Snap : Snapshots) {
        if (Snap->isFromSameBuffer(InputSnap)) {
          if (Snap->getStamp() == InputSnap->getStamp())
            return Offset;

          auto OptOffset = mapOffsetToOlderSnapshot(Offset, InputSnap, Snap);
          if (!OptOffset.hasValue())
            return None;

          // Check that the new and old offset still point to the same token.
          StringRef NewTok = getSourceToken(Offset, InputSnap);
          if (NewTok.empty())
            return None;
          if (NewTok == getSourceToken(OptOffset.getValue(), Snap))
            return OptOffset;

          return None;
        }
      }
      return None;
    };

    auto OldOffsetOpt = mappedBackOffset();
    if (OldOffsetOpt.hasValue()) {
      Offset = *OldOffsetOpt;
      PreviousASTSnaps.append(Snapshots.begin(), Snapshots.end());
      LOG_INFO_FUNC(High, "will try existing AST");
      return true;
    }

    LOG_INFO_FUNC(High, "will resolve using up-to-date AST");
    return false;
  }
};

static void resolveCursor(
    SwiftLangSupport &Lang, StringRef InputFile, unsigned Offset,
    unsigned Length, bool Actionables, bool SymbolGraph,
    SwiftInvocationRef Invok, bool TryExistingAST,
    bool CancelOnSubsequentRequest,
    llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fileSystem,
    SourceKitCancellationToken CancellationToken,
    std::function<void(const RequestResult<CursorInfoData> &)> Receiver) {
  assert(Invok);
  assert(fileSystem);

  class CursorInfoConsumer : public CursorRangeInfoConsumer {
    bool Actionables;
    bool SymbolGraph;
    SourceKitCancellationToken CancellationToken;
    std::function<void(const RequestResult<CursorInfoData> &)> Receiver;

  public:
    CursorInfoConsumer(
        StringRef InputFile, unsigned Offset, unsigned Length, bool Actionables,
        bool SymbolGraph, SwiftLangSupport &Lang, SwiftInvocationRef ASTInvok,
        bool TryExistingAST, bool CancelOnSubsequentRequest,
        SourceKitCancellationToken CancellationToken,
        std::function<void(const RequestResult<CursorInfoData> &)> Receiver)
        : CursorRangeInfoConsumer(InputFile, Offset, Length, Lang, ASTInvok,
                                  TryExistingAST, CancelOnSubsequentRequest),
          Actionables(Actionables), SymbolGraph(SymbolGraph),
          CancellationToken(CancellationToken), Receiver(std::move(Receiver)) {}

    void handlePrimaryAST(ASTUnitRef AstUnit) override {
      auto &CompIns = AstUnit->getCompilerInstance();
      ModuleDecl *MainModule = CompIns.getMainModule();
      SourceManager &SM = CompIns.getSourceMgr();
      unsigned BufferID = AstUnit->getPrimarySourceFile().getBufferID().getValue();
      SourceLoc Loc =
        Lexer::getLocForStartOfToken(SM, BufferID, Offset);
      if (Loc.isInvalid()) {
        Receiver(RequestResult<CursorInfoData>::fromError(
          "Unable to resolve the start of the token."));
        return;
      }

      // Sanitize length.
      if (Length) {
        SourceLoc TokEnd = Lexer::getLocForEndOfToken(SM, Loc);
        SourceLoc EndLoc = SM.getLocForOffset(BufferID, Offset + Length);

        // If TokEnd is not before the given EndLoc, the EndLoc contains no
        // more stuff than this token, so set the length to 0.
        if (SM.isBeforeInBuffer(EndLoc, TokEnd) || TokEnd == EndLoc)
          Length = 0;
      }

      // Retrieve relevant actions on the code under selection.
      llvm::SmallVector<RefactoringInfo, 8> Actions;
      if (Actionables && Length) {
        SmallVector<RefactoringKind, 8> Kinds;
        RangeConfig Range;
        Range.BufferId = BufferID;
        auto Pair = SM.getLineAndColumnInBuffer(Loc);
        Range.Line = Pair.first;
        Range.Column = Pair.second;
        Range.Length = Length;
        bool CollectRangeStartRefactorings = false;
        collectAvailableRefactorings(&AstUnit->getPrimarySourceFile(), Range,
                                     CollectRangeStartRefactorings, Kinds, {});
        for (RefactoringKind Kind : Kinds) {
          Actions.emplace_back(SwiftLangSupport::getUIDForRefactoringKind(Kind),
                               getDescriptiveRefactoringKindName(Kind),
                               /*UnavailableReason*/ StringRef());
        }
        if (!CollectRangeStartRefactorings) {
          // If Length is given then this request is only for refactorings,
          // return straight away unless we need cursor based refactorings as
          // well.
          CursorInfoData Data;
          Data.AvailableActions = llvm::makeArrayRef(Actions);
          Receiver(RequestResult<CursorInfoData>::fromResult(Data));
          return;
        }
        // Fall through to collect cursor based refactorings
      }

      auto *File = &AstUnit->getPrimarySourceFile();
      ResolvedCursorInfo CursorInfo =
        evaluateOrDefault(File->getASTContext().evaluator,
                          CursorInfoRequest{CursorInfoOwner(File, Loc)},
                          ResolvedCursorInfo());

      CompilerInvocation CompInvok;
      ASTInvok->applyTo(CompInvok);

      switch (CursorInfo.Kind) {
      case CursorInfoKind::ModuleRef:
        passCursorInfoForModule(CursorInfo.Mod, Lang.getIFaceGenContexts(),
                                CompInvok, Receiver);
        return;
      case CursorInfoKind::ValueRef: {
        std::string Diagnostic;
        bool Success = passCursorInfoForDecl(
            CursorInfo, MainModule, Actionables, SymbolGraph, Actions, Lang,
            CompInvok, Diagnostic, getPreviousASTSnaps(), Receiver);
        if (!Success) {
          if (!getPreviousASTSnaps().empty()) {
            // Attempt again using the up-to-date AST.
            resolveCursor(Lang, InputFile, Offset, Length, Actionables,
                          SymbolGraph, ASTInvok, /*TryExistingAST=*/false,
                          CancelOnSubsequentRequest, SM.getFileSystem(),
                          CancellationToken, Receiver);
          } else {
            CursorInfoData Info;
            Info.InternalDiagnostic = Diagnostic;
            Receiver(RequestResult<CursorInfoData>::fromResult(Info));
          }
        }
        return;
      }
      case CursorInfoKind::ExprStart:
      case CursorInfoKind::StmtStart: {
        if (Actionables) {
          collectAvailableRefactoringsOtherThanRename(CursorInfo, Actions);
          if (!Actions.empty()) {
            CursorInfoData Data;
            Data.AvailableActions = llvm::makeArrayRef(Actions);
            Receiver(RequestResult<CursorInfoData>::fromResult(Data));
            return;
          }
        }

        CursorInfoData Info;
        Info.InternalDiagnostic =
            "Resolved to incomplete expression or statement.";
        Receiver(RequestResult<CursorInfoData>::fromResult(Info));
        return;
      }
      case CursorInfoKind::Invalid:
        CursorInfoData Data;
        if (Actionables) {
          Data.AvailableActions = llvm::makeArrayRef(Actions);
        } else {
          Data.InternalDiagnostic = "Unable to resolve cursor info.";
        }
        Receiver(RequestResult<CursorInfoData>::fromResult(Data));
        return;
      }
    }

    void cancelled() override {
      Receiver(RequestResult<CursorInfoData>::cancelled());
    }

    void failed(StringRef Error) override {
      LOG_WARN_FUNC("cursor info failed: " << Error);
      Receiver(RequestResult<CursorInfoData>::fromError(Error));
    }
  };

  auto Consumer = std::make_shared<CursorInfoConsumer>(
      InputFile, Offset, Length, Actionables, SymbolGraph, Lang, Invok,
      TryExistingAST, CancelOnSubsequentRequest, CancellationToken, Receiver);

  /// FIXME: When request cancellation is implemented and Xcode adopts it,
  /// don't use 'OncePerASTToken'.
  static const char OncePerASTToken = 0;
  static const char OncePerASTTokenWithActionables = 0;
  const void *Once = nullptr;
  if (CancelOnSubsequentRequest)
    Once = Actionables ? &OncePerASTTokenWithActionables : &OncePerASTToken;
  Lang.getASTManager()->processASTAsync(Invok, std::move(Consumer), Once,
                                        CancellationToken, fileSystem);
}

static void computeDiagnostics(
    SwiftLangSupport &Lang, StringRef InputFile, SwiftInvocationRef Invok,
    llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
    SourceKitCancellationToken CancellationToken,
    std::function<void(const RequestResult<DiagnosticsResult> &)> Receiver) {

  class DiagnosticsConsumer : public SwiftASTConsumer {
    std::function<void(const RequestResult<DiagnosticsResult> &)> Receiver;

  public:
    DiagnosticsConsumer(
        std::function<void(const RequestResult<DiagnosticsResult> &)> Receiver)
        : Receiver(Receiver) {}

    void handlePrimaryAST(ASTUnitRef AstUnit) override {
      unsigned BufferID =
          AstUnit->getPrimarySourceFile().getBufferID().getValue();
      auto &DiagConsumer = AstUnit->getEditorDiagConsumer();
      auto Diagnostics = DiagConsumer.getDiagnosticsForBuffer(BufferID);
      Receiver(RequestResult<DiagnosticsResult>::fromResult(Diagnostics));
    }
  };

  auto Consumer = std::make_shared<DiagnosticsConsumer>(std::move(Receiver));

  Lang.getASTManager()->processASTAsync(Invok, std::move(Consumer),
                                        /*OncePerASTToken=*/nullptr,
                                        CancellationToken, FileSystem);
}

static void resolveName(
    SwiftLangSupport &Lang, StringRef InputFile, unsigned Offset,
    SwiftInvocationRef Invok, bool TryExistingAST, NameTranslatingInfo &Input,
    SourceKitCancellationToken CancellationToken,
    std::function<void(const RequestResult<NameTranslatingInfo> &)> Receiver) {
  assert(Invok);

  class NameInfoConsumer : public CursorRangeInfoConsumer {
    NameTranslatingInfo Input;
    SourceKitCancellationToken CancellationToken;
    std::function<void(const RequestResult<NameTranslatingInfo> &)> Receiver;

  public:
    NameInfoConsumer(
        StringRef InputFile, unsigned Offset, SwiftLangSupport &Lang,
        SwiftInvocationRef ASTInvok, bool TryExistingAST,
        NameTranslatingInfo Input, SourceKitCancellationToken CancellationToken,
        std::function<void(const RequestResult<NameTranslatingInfo> &)>
            Receiver)
        : CursorRangeInfoConsumer(InputFile, Offset, 0, Lang, ASTInvok,
                                  TryExistingAST,
                                  /*CancelOnSubsequentRequest=*/false),
          Input(std::move(Input)), CancellationToken(CancellationToken),
          Receiver(std::move(Receiver)) {}

    void handlePrimaryAST(ASTUnitRef AstUnit) override {
      auto &CompIns = AstUnit->getCompilerInstance();

      unsigned BufferID = AstUnit->getPrimarySourceFile().getBufferID().getValue();
      SourceLoc Loc =
        Lexer::getLocForStartOfToken(CompIns.getSourceMgr(), BufferID, Offset);
      if (Loc.isInvalid()) {
        Receiver(RequestResult<NameTranslatingInfo>::fromError(
          "Unable to resolve the start of the token."));
        return;
      }

      auto *File = &AstUnit->getPrimarySourceFile();
      ResolvedCursorInfo CursorInfo =
        evaluateOrDefault(File->getASTContext().evaluator,
                          CursorInfoRequest{CursorInfoOwner(File, Loc)},
                          ResolvedCursorInfo());
      if (CursorInfo.isInvalid()) {
        NameTranslatingInfo Info;
        Info.InternalDiagnostic = "Unable to resolve cursor info.";
        Receiver(RequestResult<NameTranslatingInfo>::fromResult(Info));
        return;
      }

      CompilerInvocation CompInvok;
      ASTInvok->applyTo(CompInvok);

      switch(CursorInfo.Kind) {
      case CursorInfoKind::ModuleRef:
        return;

      case CursorInfoKind::ValueRef: {
        std::string Diagnostic;
        bool Success = passNameInfoForDecl(CursorInfo, Input, Diagnostic,
                                           Receiver);
        if (!Success) {
          if (!getPreviousASTSnaps().empty()) {
            // Attempt again using the up-to-date AST.
            resolveName(Lang, InputFile, Offset, ASTInvok,
                        /*TryExistingAST=*/false, Input, CancellationToken,
                        Receiver);
          } else {
            NameTranslatingInfo Info;
            Info.InternalDiagnostic = Diagnostic;
            Receiver(RequestResult<NameTranslatingInfo>::fromResult(Info));
          }
        }
        return;
      }
      case CursorInfoKind::ExprStart:
      case CursorInfoKind::StmtStart: {
        NameTranslatingInfo Info;
        Info.InternalDiagnostic =
            "Resolved to incomplete expression or statement.";
        Receiver(RequestResult<NameTranslatingInfo>::fromResult(Info));
        return;
      }
      case CursorInfoKind::Invalid:
        llvm_unreachable("bad sema token kind.");
      }
    }

    void cancelled() override {
      Receiver(RequestResult<NameTranslatingInfo>::cancelled());
    }

    void failed(StringRef Error) override {
      LOG_WARN_FUNC("name info failed: " << Error);
      Receiver(RequestResult<NameTranslatingInfo>::fromError(Error));
    }
  };

  auto Consumer = std::make_shared<NameInfoConsumer>(
      InputFile, Offset, Lang, Invok, TryExistingAST, Input, CancellationToken,
      Receiver);

  Lang.getASTManager()->processASTAsync(
      Invok, std::move(Consumer), /*OncePerASTToken=*/nullptr,
      CancellationToken, llvm::vfs::getRealFileSystem());
}

static void
resolveRange(SwiftLangSupport &Lang, StringRef InputFile, unsigned Offset,
             unsigned Length, SwiftInvocationRef Invok, bool TryExistingAST,
             bool CancelOnSubsequentRequest,
             SourceKitCancellationToken CancellationToken,
             std::function<void(const RequestResult<RangeInfo> &)> Receiver) {
  assert(Invok);

  class RangeInfoConsumer : public CursorRangeInfoConsumer {
    SourceKitCancellationToken CancellationToken;
    std::function<void(const RequestResult<RangeInfo> &)> Receiver;

  public:
    RangeInfoConsumer(
        StringRef InputFile, unsigned Offset, unsigned Length,
        SwiftLangSupport &Lang, SwiftInvocationRef ASTInvok,
        bool TryExistingAST, bool CancelOnSubsequentRequest,
        SourceKitCancellationToken CancellationToken,
        std::function<void(const RequestResult<RangeInfo> &)> Receiver)
        : CursorRangeInfoConsumer(InputFile, Offset, Length, Lang, ASTInvok,
                                  TryExistingAST, CancelOnSubsequentRequest),
          CancellationToken(CancellationToken), Receiver(std::move(Receiver)) {}

    void handlePrimaryAST(ASTUnitRef AstUnit) override {
      // FIXME: Implement tracing
      auto *File = &AstUnit->getPrimarySourceFile();
      ResolvedRangeInfo Info = evaluateOrDefault(File->getASTContext().evaluator,
        RangeInfoRequest(RangeInfoOwner({File, Offset, Length})),
                                                 ResolvedRangeInfo());

      CompilerInvocation CompInvok;
      ASTInvok->applyTo(CompInvok);

      RangeInfo Result;
      Result.RangeKind = Lang.getUIDForRangeKind(Info.Kind);
      if (Info.Kind == RangeKind::Invalid) {
        Result.RangeContent = "";
      } else {
        assert(Info.ContentRange.isValid());
        Result.RangeContent = Info.ContentRange.str();
      }

      switch (Info.Kind) {
      case RangeKind::SingleExpression: {
        SmallString<64> SS;
        llvm::raw_svector_ostream OS(SS);
        Info.ExitInfo.ReturnType->print(OS);
        Result.ExprType = OS.str();
        Receiver(RequestResult<RangeInfo>::fromResult(Result));
        return;
      }
      case RangeKind::SingleDecl:
      case RangeKind::MultiTypeMemberDecl:
      case RangeKind::MultiStatement:
      case RangeKind::SingleStatement: {
        Receiver(RequestResult<RangeInfo>::fromResult(Result));
        return;
      }
      case RangeKind::PartOfExpression:
      case RangeKind::Invalid:
        if (!getPreviousASTSnaps().empty()) {
          // Attempt again using the up-to-date AST.
          resolveRange(Lang, InputFile, Offset, Length, ASTInvok,
                       /*TryExistingAST=*/false, CancelOnSubsequentRequest,
                       CancellationToken, Receiver);
        } else {
          Receiver(RequestResult<RangeInfo>::fromResult(Result));
        }
        return;
      }
    }

    void cancelled() override {
      Receiver(RequestResult<RangeInfo>::cancelled());
    }

    void failed(StringRef Error) override {
      LOG_WARN_FUNC("range info failed: " << Error);
      Receiver(RequestResult<RangeInfo>::fromError(Error));
    }
  };

  auto Consumer = std::make_shared<RangeInfoConsumer>(
      InputFile, Offset, Length, Lang, Invok, TryExistingAST,
      CancelOnSubsequentRequest, CancellationToken, Receiver);
  /// FIXME: When request cancellation is implemented and Xcode adopts it,
  /// don't use 'OncePerASTToken'.
  static const char OncePerASTToken = 0;
  const void *Once = CancelOnSubsequentRequest ? &OncePerASTToken : nullptr;
  Lang.getASTManager()->processASTAsync(Invok, std::move(Consumer), Once,
                                        CancellationToken,
                                        llvm::vfs::getRealFileSystem());
}

void SwiftLangSupport::getCursorInfo(
    StringRef InputFile, unsigned Offset, unsigned Length, bool Actionables,
    bool SymbolGraph, bool CancelOnSubsequentRequest,
    ArrayRef<const char *> Args, Optional<VFSOptions> vfsOptions,
    SourceKitCancellationToken CancellationToken,
    std::function<void(const RequestResult<CursorInfoData> &)> Receiver) {

  std::string error;
  auto fileSystem = getFileSystem(vfsOptions, InputFile, error);
  if (!fileSystem)
    return Receiver(RequestResult<CursorInfoData>::fromError(error));

  if (auto IFaceGenRef = IFaceGenContexts.get(InputFile)) {
    IFaceGenRef->accessASTAsync([this, IFaceGenRef, Offset, Actionables,
                                 SymbolGraph, Receiver] {
      SwiftInterfaceGenContext::ResolvedEntity Entity;
      Entity = IFaceGenRef->resolveEntityForOffset(Offset);
      if (Entity.isResolved()) {
        CompilerInvocation Invok;
        IFaceGenRef->applyTo(Invok);
        if (Entity.Mod) {
          passCursorInfoForModule(Entity.Mod, IFaceGenContexts, Invok,
                                  Receiver);
        } else {
          std::string Diagnostic;  // Unused.
          ModuleDecl *MainModule = IFaceGenRef->getModuleDecl();
          ResolvedCursorInfo Info;
          Info.ValueD = const_cast<ValueDecl *>(Entity.Dcl);
          Info.IsRef = Entity.IsRef;
          passCursorInfoForDecl(Info, MainModule, Actionables, SymbolGraph, {},
                                *this, Invok, Diagnostic, {}, Receiver);
        }
      } else {
        CursorInfoData Info;
        Info.InternalDiagnostic =
            "Unable to resolve entity from generated interface.";
        Receiver(RequestResult<CursorInfoData>::fromResult(Info));
      }
    });
    return;
  }

  std::string Error;
  SwiftInvocationRef Invok =
      ASTMgr->getInvocation(Args, InputFile, fileSystem, Error);
  if (!Error.empty()) {
    LOG_WARN_FUNC("error creating ASTInvocation: " << Error);
  }
  if (!Invok) {
    Receiver(RequestResult<CursorInfoData>::fromError(Error));
    return;
  }

  resolveCursor(*this, InputFile, Offset, Length, Actionables, SymbolGraph,
                Invok, /*TryExistingAST=*/true, CancelOnSubsequentRequest,
                fileSystem, CancellationToken, Receiver);
}

void SwiftLangSupport::getDiagnostics(
    StringRef InputFile, ArrayRef<const char *> Args,
    Optional<VFSOptions> VfsOptions,
    SourceKitCancellationToken CancellationToken,
    std::function<void(const RequestResult<DiagnosticsResult> &)> Receiver) {
  std::string FileSystemError;
  auto FileSystem = getFileSystem(VfsOptions, InputFile, FileSystemError);
  if (!FileSystem) {
    Receiver(RequestResult<DiagnosticsResult>::fromError(FileSystemError));
    return;
  }

  std::string InvocationError;
  SwiftInvocationRef Invok =
      ASTMgr->getInvocation(Args, InputFile, FileSystem, InvocationError);
  if (!InvocationError.empty()) {
    LOG_WARN_FUNC("error creating ASTInvocation: " << InvocationError);
  }
  if (!Invok) {
    Receiver(RequestResult<DiagnosticsResult>::fromError(InvocationError));
    return;
  }

  computeDiagnostics(*this, InputFile, Invok, FileSystem, CancellationToken,
                     Receiver);
}

void SwiftLangSupport::getRangeInfo(
    StringRef InputFile, unsigned Offset, unsigned Length,
    bool CancelOnSubsequentRequest, ArrayRef<const char *> Args,
    SourceKitCancellationToken CancellationToken,
    std::function<void(const RequestResult<RangeInfo> &)> Receiver) {
  if (IFaceGenContexts.get(InputFile)) {
    // FIXME: return range info for generated interfaces.
    Receiver(RequestResult<RangeInfo>::fromError(
        "Range info for generated interfaces is not implemented."));
    return;
  }
  std::string Error;
  SwiftInvocationRef Invok = ASTMgr->getInvocation(Args, InputFile, Error);
  if (!Invok) {
    LOG_WARN_FUNC("failed to create an ASTInvocation: " << Error);
    Receiver(RequestResult<RangeInfo>::fromError(Error));
    return;
  }
  if (Length == 0) {
    Receiver(RequestResult<RangeInfo>::fromError("Invalid range length."));
    return;
  }
  resolveRange(*this, InputFile, Offset, Length, Invok, /*TryExistingAST=*/true,
               CancelOnSubsequentRequest, CancellationToken, Receiver);
}

void SwiftLangSupport::getNameInfo(
    StringRef InputFile, unsigned Offset, NameTranslatingInfo &Input,
    ArrayRef<const char *> Args, SourceKitCancellationToken CancellationToken,
    std::function<void(const RequestResult<NameTranslatingInfo> &)> Receiver) {

  if (auto IFaceGenRef = IFaceGenContexts.get(InputFile)) {
    IFaceGenRef->accessASTAsync([IFaceGenRef, Offset, Input, Receiver] {
      SwiftInterfaceGenContext::ResolvedEntity Entity;
      Entity = IFaceGenRef->resolveEntityForOffset(Offset);
      if (Entity.isResolved()) {
        CompilerInvocation Invok;
        IFaceGenRef->applyTo(Invok);
        if (Entity.Mod) {
          // Module is ignored
        } else {
          // FIXME: Should pass the main module for the interface but currently
          // it's not necessary.
        }
      } else {
        NameTranslatingInfo Info;
        Info.InternalDiagnostic =
            "Unable to resolve entity from generated interface.";
        Receiver(RequestResult<NameTranslatingInfo>::fromResult(Info));
      }
    });
    return;
  }

  std::string Error;
  SwiftInvocationRef Invok = ASTMgr->getInvocation(Args, InputFile, Error);
  if (!Invok) {
    LOG_WARN_FUNC("failed to create an ASTInvocation: " << Error);
    Receiver(RequestResult<NameTranslatingInfo>::fromError(Error));
    return;
  }

  resolveName(*this, InputFile, Offset, Invok, /*TryExistingAST=*/true, Input,
              CancellationToken, Receiver);
}

static void resolveCursorFromUSR(
    SwiftLangSupport &Lang, StringRef InputFile, StringRef USR,
    SwiftInvocationRef Invok, bool TryExistingAST,
    bool CancelOnSubsequentRequest,
    llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fileSystem,
    SourceKitCancellationToken CancellationToken,
    std::function<void(const RequestResult<CursorInfoData> &)> Receiver) {
  assert(Invok);

  class CursorInfoConsumer : public SwiftASTConsumer {
    std::string InputFile;
    StringRef USR;
    SwiftLangSupport &Lang;
    SwiftInvocationRef ASTInvok;
    const bool TryExistingAST;
    bool CancelOnSubsequentRequest;
    SourceKitCancellationToken CancellationToken;
    std::function<void(const RequestResult<CursorInfoData> &)> Receiver;
    SmallVector<ImmutableTextSnapshotRef, 4> PreviousASTSnaps;

  public:
    CursorInfoConsumer(
        StringRef InputFile, StringRef USR, SwiftLangSupport &Lang,
        SwiftInvocationRef ASTInvok, bool TryExistingAST,
        bool CancelOnSubsequentRequest,
        SourceKitCancellationToken CancellationToken,
        std::function<void(const RequestResult<CursorInfoData> &)> Receiver)
        : InputFile(InputFile), USR(USR), Lang(Lang),
          ASTInvok(std::move(ASTInvok)), TryExistingAST(TryExistingAST),
          CancelOnSubsequentRequest(CancelOnSubsequentRequest),
          CancellationToken(CancellationToken), Receiver(std::move(Receiver)) {}

    bool canUseASTWithSnapshots(
        ArrayRef<ImmutableTextSnapshotRef> Snapshots) override {
      if (!TryExistingAST) {
        LOG_INFO_FUNC(High, "will resolve using up-to-date AST");
        return false;
      }

      if (!Snapshots.empty()) {
        PreviousASTSnaps.append(Snapshots.begin(), Snapshots.end());
        LOG_INFO_FUNC(High, "will try existing AST");
        return true;
      }

      LOG_INFO_FUNC(High, "will resolve using up-to-date AST");
      return false;
    }

    void handlePrimaryAST(ASTUnitRef AstUnit) override {
      auto &CompIns = AstUnit->getCompilerInstance();
      ModuleDecl *MainModule = CompIns.getMainModule();

      if (USR.startswith("c:")) {
        LOG_WARN_FUNC("lookup for C/C++/ObjC USRs not implemented");
        CursorInfoData Info;
        Info.InternalDiagnostic = "Lookup for C/C++/ObjC USRs not implemented.";
        Receiver(RequestResult<CursorInfoData>::fromResult(Info));
        return;
      }

      auto &context = CompIns.getASTContext();
      TypeDecl *D = Demangle::getTypeDeclForUSR(context, USR);

      if (!D) {
        CursorInfoData Info;
        Info.InternalDiagnostic = "Unable to resolve type from USR.";
        Receiver(RequestResult<CursorInfoData>::fromResult(Info));
        return;
      }

      CompilerInvocation CompInvok;
      ASTInvok->applyTo(CompInvok);

      if (auto *M = dyn_cast<ModuleDecl>(D)) {
        passCursorInfoForModule(M, Lang.getIFaceGenContexts(), CompInvok,
                                Receiver);
      } else {
        ResolvedCursorInfo Info;
        Info.ValueD = D;
        Info.IsRef = false;

        auto *DC = D->getDeclContext();
        Type selfTy;
        if (DC->isTypeContext()) {
          Info.ContainerType = DC->getSelfInterfaceType();
          Info.ContainerType = D->getInnermostDeclContext()->mapTypeIntoContext(
              Info.ContainerType);
        }

        std::string Diagnostic;
        bool Success =
            passCursorInfoForDecl(Info, MainModule, /*AddRefactorings*/ false,
                                  /*AddSymbolGraph*/ false, {}, Lang, CompInvok,
                                  Diagnostic, PreviousASTSnaps, Receiver);
        if (!Success) {
          if (!PreviousASTSnaps.empty()) {
            // Attempt again using the up-to-date AST.
            resolveCursorFromUSR(Lang, InputFile, USR, ASTInvok,
                                 /*TryExistingAST=*/false,
                                 CancelOnSubsequentRequest,
                                 CompIns.getSourceMgr().getFileSystem(),
                                 CancellationToken, Receiver);
          } else {
            CursorInfoData Info;
            Info.InternalDiagnostic = Diagnostic;
            Receiver(RequestResult<CursorInfoData>::fromResult(Info));
          }
        }
      }
    }

    void cancelled() override {
      Receiver(RequestResult<CursorInfoData>::cancelled());
    }

    void failed(StringRef Error) override {
      LOG_WARN_FUNC("cursor info failed: " << Error);
      Receiver(RequestResult<CursorInfoData>::fromError(Error));
    }
  };

  auto Consumer = std::make_shared<CursorInfoConsumer>(
      InputFile, USR, Lang, Invok, TryExistingAST, CancelOnSubsequentRequest,
      CancellationToken, Receiver);
  /// FIXME: When request cancellation is implemented and Xcode adopts it,
  /// don't use 'OncePerASTToken'.
  static const char OncePerASTToken = 0;
  const void *Once = CancelOnSubsequentRequest ? &OncePerASTToken : nullptr;
  Lang.getASTManager()->processASTAsync(Invok, std::move(Consumer), Once,
                                        CancellationToken, fileSystem);
}

void SwiftLangSupport::getCursorInfoFromUSR(
    StringRef filename, StringRef USR, bool CancelOnSubsequentRequest,
    ArrayRef<const char *> Args, Optional<VFSOptions> vfsOptions,
    SourceKitCancellationToken CancellationToken,
    std::function<void(const RequestResult<CursorInfoData> &)> Receiver) {
  std::string error;

  auto fileSystem = getFileSystem(vfsOptions, filename, error);
  if (!fileSystem)
    return Receiver(RequestResult<CursorInfoData>::fromError(error));

  if (auto IFaceGenRef = IFaceGenContexts.get(filename)) {
    LOG_WARN_FUNC("Info from usr for generated interface not implemented yet.");
    CursorInfoData Info;
    Info.InternalDiagnostic = "Info for generated interfaces not implemented.";
    Receiver(RequestResult<CursorInfoData>::fromResult(Info));
    return;
  }

  std::string Error;
  SwiftInvocationRef Invok =
      ASTMgr->getInvocation(Args, filename, fileSystem, Error);
  if (!Invok) {
    LOG_WARN_FUNC("failed to create an ASTInvocation: " << Error);
    Receiver(RequestResult<CursorInfoData>::fromError(Error));
    return;
  }

  resolveCursorFromUSR(*this, filename, USR, Invok, /*TryExistingAST=*/true,
                       CancelOnSubsequentRequest, fileSystem, CancellationToken,
                       Receiver);
}

//===----------------------------------------------------------------------===//
// SwiftLangSupport::findUSRRange
//===----------------------------------------------------------------------===//

llvm::Optional<std::pair<unsigned, unsigned>>
SwiftLangSupport::findUSRRange(StringRef DocumentName, StringRef USR) {
  if (auto IFaceGenRef = IFaceGenContexts.get(DocumentName))
    return IFaceGenRef->findUSRRange(USR);

  // Only works for a module interface document currently.
  // FIXME: Report it as failed request.
  return None;
}

//===----------------------------------------------------------------------===//
// SwiftLangSupport::findRelatedIdentifiersInFile
//===----------------------------------------------------------------------===//

namespace {
class RelatedIdScanner : public SourceEntityWalker {
  ValueDecl *Dcl;
  llvm::SmallVectorImpl<std::pair<unsigned, unsigned>> &Ranges;
  SourceManager &SourceMgr;
  unsigned BufferID = -1;
  bool Cancelled = false;

public:
  explicit RelatedIdScanner(SourceFile &SrcFile, unsigned BufferID,
                            ValueDecl *D,
      llvm::SmallVectorImpl<std::pair<unsigned, unsigned>> &Ranges)
    : Ranges(Ranges), SourceMgr(SrcFile.getASTContext().SourceMgr),
      BufferID(BufferID) {
    if (auto *V = dyn_cast<VarDecl>(D)) {
      // Always use the canonical var decl for comparison. This is so we
      // pick up all occurrences of x in case statements like the below:
      //   case .first(let x), .second(let x)
      //     fallthrough
      //   case .third(let x)
      //     print(x)
      Dcl = V->getCanonicalVarDecl();

      // If we have a prioperty wrapper backing property or projected value, use
      // the wrapped property instead (i.e. if this is _foo or $foo, pretend
      // it's foo).
      if (auto *Wrapped = V->getOriginalWrappedProperty()) {
        Dcl = Wrapped;
      }
    } else {
      Dcl = D;
    }
  }

private:
  bool walkToDeclPre(Decl *D, CharSourceRange Range) override {
    if (Cancelled)
      return false;
    if (auto *V = dyn_cast<VarDecl>(D)) {
      // Handle references to the implicitly generated vars in case statements
      // matching multiple patterns
      D = V->getCanonicalVarDecl();
    }
    if (D == Dcl)
      return passId(Range);
    return true;
  }

  bool visitDeclReference(ValueDecl *D, CharSourceRange Range,
                          TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef, Type T,
                          ReferenceMetaData Data) override {
    if (Cancelled)
      return false;

    if (auto *V = dyn_cast<VarDecl>(D)) {
      D = V->getCanonicalVarDecl();

      // If we have a prioperty wrapper backing property or projected value, use
      // the wrapped property for comparison instead (i.e. if this is _foo or
      // $foo, pretend it's foo).
      if (auto *Wrapped = V->getOriginalWrappedProperty()) {
        assert(Range.getByteLength() > 1 &&
               (Range.str().front() == '_' || Range.str().front() == '$'));
        D = Wrapped;
        Range = CharSourceRange(Range.getStart().getAdvancedLoc(1), Range.getByteLength() - 1);
      }
    } else if (CtorTyRef) {
      D = CtorTyRef;
    }

    if (D == Dcl)
      return passId(Range);
    return true;
  }

  bool passId(CharSourceRange Range) {
    unsigned Offset = SourceMgr.getLocOffsetInBuffer(Range.getStart(),BufferID);
    Ranges.push_back({ Offset, Range.getByteLength() });
    return !Cancelled;
  }
};

} // end anonymous namespace

void SwiftLangSupport::findRelatedIdentifiersInFile(
    StringRef InputFile, unsigned Offset, bool CancelOnSubsequentRequest,
    ArrayRef<const char *> Args, SourceKitCancellationToken CancellationToken,
    std::function<void(const RequestResult<RelatedIdentsInfo> &)> Receiver) {

  std::string Error;
  SwiftInvocationRef Invok = ASTMgr->getInvocation(Args, InputFile, Error);
  if (!Invok) {
    LOG_WARN_FUNC("failed to create an ASTInvocation: " << Error);
    Receiver(RequestResult<RelatedIdentsInfo>::fromError(Error));
    return;
  }

  class RelatedIdConsumer : public SwiftASTConsumer {
    unsigned Offset;
    std::function<void(const RequestResult<RelatedIdentsInfo> &)> Receiver;
    SwiftInvocationRef Invok;

  public:
    RelatedIdConsumer(unsigned Offset,
                      std::function<void(const RequestResult<RelatedIdentsInfo> &)> Receiver,
                      SwiftInvocationRef Invok)
      : Offset(Offset), Receiver(std::move(Receiver)), Invok(Invok) { }

    // FIXME: Don't silently eat errors here.
    void handlePrimaryAST(ASTUnitRef AstUnit) override {
      auto &CompInst = AstUnit->getCompilerInstance();
      auto &SrcFile = AstUnit->getPrimarySourceFile();


      SmallVector<std::pair<unsigned, unsigned>, 8> Ranges;

      auto Action = [&]() {
        unsigned BufferID = SrcFile.getBufferID().getValue();
        SourceLoc Loc =
          Lexer::getLocForStartOfToken(CompInst.getSourceMgr(), BufferID, Offset);
        if (Loc.isInvalid())
          return;

        ResolvedCursorInfo CursorInfo =
          evaluateOrDefault(SrcFile.getASTContext().evaluator,
                            CursorInfoRequest{CursorInfoOwner(&SrcFile, Loc)},
                            ResolvedCursorInfo());
        if (CursorInfo.isInvalid())
          return;
        if (CursorInfo.IsKeywordArgument)
          return;

        ValueDecl *VD = CursorInfo.typeOrValue();
        if (!VD)
          return; // This was a module reference.

        // Only accept pointing to an identifier.
        if (!CursorInfo.IsRef &&
            (isa<ConstructorDecl>(VD) ||
             isa<DestructorDecl>(VD) ||
             isa<SubscriptDecl>(VD)))
          return;
        if (VD->isOperator())
          return;

        RelatedIdScanner Scanner(SrcFile, BufferID, VD, Ranges);

        if (auto *Case = getCaseStmtOfCanonicalVar(VD)) {
          Scanner.walk(Case);
          while ((Case = Case->getFallthroughDest().getPtrOrNull())) {
            Scanner.walk(Case);
          }
        } else if (DeclContext *LocalDC = VD->getDeclContext()->getLocalContext()) {
          Scanner.walk(LocalDC);
        } else {
          Scanner.walk(SrcFile);
        }
      };
      Action();

      RelatedIdentsInfo Info;
      Info.Ranges = Ranges;
      Receiver(RequestResult<RelatedIdentsInfo>::fromResult(Info));
    }

    void cancelled() override {
      Receiver(RequestResult<RelatedIdentsInfo>::cancelled());
    }

    void failed(StringRef Error) override {
      LOG_WARN_FUNC("related idents failed: " << Error);
      Receiver(RequestResult<RelatedIdentsInfo>::fromError(Error));
    }

    static CaseStmt *getCaseStmtOfCanonicalVar(Decl *D) {
      assert(D);
      if (auto *VD = dyn_cast<VarDecl>(D)) {
        if (auto *Canonical = VD->getCanonicalVarDecl()) {
          return dyn_cast_or_null<CaseStmt>(Canonical->getRecursiveParentPatternStmt());
        }
      }
      return nullptr;
    }
  };

  auto Consumer = std::make_shared<RelatedIdConsumer>(Offset, Receiver, Invok);
  /// FIXME: When request cancellation is implemented and Xcode adopts it,
  /// don't use 'OncePerASTToken'.
  static const char OncePerASTToken = 0;
  const void *Once = CancelOnSubsequentRequest ? &OncePerASTToken : nullptr;
  ASTMgr->processASTAsync(Invok, std::move(Consumer), Once, CancellationToken,
                          llvm::vfs::getRealFileSystem());
}

//===----------------------------------------------------------------------===//
// SwiftLangSupport::semanticRefactoring
//===----------------------------------------------------------------------===//

static RefactoringKind getIDERefactoringKind(SemanticRefactoringInfo Info) {
  switch(Info.Kind) {
    case SemanticRefactoringKind::None: return RefactoringKind::None;
#define SEMANTIC_REFACTORING(KIND, NAME, ID)                                   \
    case SemanticRefactoringKind::KIND: return RefactoringKind::KIND;
#include "swift/IDE/RefactoringKinds.def"
  }
}

void SwiftLangSupport::semanticRefactoring(
    StringRef Filename, SemanticRefactoringInfo Info,
    ArrayRef<const char *> Args, SourceKitCancellationToken CancellationToken,
    CategorizedEditsReceiver Receiver) {
  std::string Error;
  SwiftInvocationRef Invok = ASTMgr->getInvocation(Args, Filename, Error);
  if (!Invok) {
    LOG_WARN_FUNC("failed to create an ASTInvocation: " << Error);
    Receiver(RequestResult<ArrayRef<CategorizedEdits>>::fromError(Error));
    return;
  }
  assert(Invok);

  class SemaRefactoringConsumer : public SwiftASTConsumer {
    SemanticRefactoringInfo Info;
    CategorizedEditsReceiver Receiver;

  public:
    SemaRefactoringConsumer(SemanticRefactoringInfo Info,
                            CategorizedEditsReceiver Receiver) : Info(Info),
                                                Receiver(std::move(Receiver)) {}

    void handlePrimaryAST(ASTUnitRef AstUnit) override {
      auto &CompIns = AstUnit->getCompilerInstance();
      ModuleDecl *MainModule = CompIns.getMainModule();
      RefactoringOptions Opts(getIDERefactoringKind(Info));
      Opts.Range.BufferId =  AstUnit->getPrimarySourceFile().getBufferID().
        getValue();
      Opts.Range.Line = Info.Line;
      Opts.Range.Column = Info.Column;
      Opts.Range.Length = Info.Length;
      Opts.PreferredName = Info.PreferredName.str();

      RequestRefactoringEditConsumer EditConsumer(Receiver);
      refactorSwiftModule(MainModule, Opts, EditConsumer, EditConsumer);
    }

    void cancelled() override {
      Receiver(RequestResult<ArrayRef<CategorizedEdits>>::cancelled());
    }

    void failed(StringRef Error) override {
      Receiver(RequestResult<ArrayRef<CategorizedEdits>>::fromError(Error));
    }
  };

  auto Consumer = std::make_shared<SemaRefactoringConsumer>(Info, Receiver);
  /// FIXME: When request cancellation is implemented and Xcode adopts it,
  /// don't use 'OncePerASTToken'.
  static const char OncePerASTToken = 0;
  getASTManager()->processASTAsync(Invok, std::move(Consumer), &OncePerASTToken,
                                   CancellationToken,
                                   llvm::vfs::getRealFileSystem());
}

void SwiftLangSupport::collectExpressionTypes(
    StringRef FileName, ArrayRef<const char *> Args,
    ArrayRef<const char *> ExpectedProtocols, bool CanonicalType,
    SourceKitCancellationToken CancellationToken,
    std::function<void(const RequestResult<ExpressionTypesInFile> &)>
        Receiver) {
  std::string Error;
  SwiftInvocationRef Invok = ASTMgr->getInvocation(Args, FileName, Error);
  if (!Invok) {
    LOG_WARN_FUNC("failed to create an ASTInvocation: " << Error);
    Receiver(RequestResult<ExpressionTypesInFile>::fromError(Error));
    return;
  }
  assert(Invok);
  class ExpressionTypeCollector: public SwiftASTConsumer {
    std::function<void(const RequestResult<ExpressionTypesInFile> &)> Receiver;
    std::vector<const char *> ExpectedProtocols;
    bool CanonicalType;
  public:
    ExpressionTypeCollector(
        std::function<void(const RequestResult<ExpressionTypesInFile> &)> Receiver,
        ArrayRef<const char *> ExpectedProtocols,
        bool CanonicalType):
          Receiver(std::move(Receiver)),
          ExpectedProtocols(ExpectedProtocols.vec()),
          CanonicalType(CanonicalType) {}
    void handlePrimaryAST(ASTUnitRef AstUnit) override {
      auto *SF = AstUnit->getCompilerInstance().getPrimarySourceFile();
      std::vector<ExpressionTypeInfo> Scratch;
      llvm::SmallString<256> TypeBuffer;
      llvm::raw_svector_ostream OS(TypeBuffer);
      ExpressionTypesInFile Result;
      for (auto Item: collectExpressionType(*SF, ExpectedProtocols, Scratch,
                                            CanonicalType, OS)) {
        Result.Results.push_back({Item.offset, Item.length, Item.typeOffset, {}});
        for (auto P: Item.protocols) {
          Result.Results.back().ProtocolOffsets.push_back(P.first);
        }
      }
      Result.TypeBuffer = OS.str();
      Receiver(RequestResult<ExpressionTypesInFile>::fromResult(Result));
    }

    void cancelled() override {
      Receiver(RequestResult<ExpressionTypesInFile>::cancelled());
    }

    void failed(StringRef Error) override {
      Receiver(RequestResult<ExpressionTypesInFile>::fromError(Error));
    }
  };
  auto Collector = std::make_shared<ExpressionTypeCollector>(Receiver,
                                                             ExpectedProtocols,
                                                             CanonicalType);
  /// FIXME: When request cancellation is implemented and Xcode adopts it,
  /// don't use 'OncePerASTToken'.
  static const char OncePerASTToken = 0;
  getASTManager()->processASTAsync(Invok, std::move(Collector),
                                   &OncePerASTToken, CancellationToken,
                                   llvm::vfs::getRealFileSystem());
}

void SwiftLangSupport::collectVariableTypes(
    StringRef FileName, ArrayRef<const char *> Args, Optional<unsigned> Offset,
    Optional<unsigned> Length, SourceKitCancellationToken CancellationToken,
    std::function<void(const RequestResult<VariableTypesInFile> &)> Receiver) {
  std::string Error;
  SwiftInvocationRef Invok = ASTMgr->getInvocation(Args, FileName, Error);
  if (!Invok) {
    LOG_WARN_FUNC("failed to create an ASTInvocation: " << Error);
    Receiver(RequestResult<VariableTypesInFile>::fromError(Error));
    return;
  }
  assert(Invok);

  class VariableTypeCollectorASTConsumer : public SwiftASTConsumer {
  private:
    std::function<void(const RequestResult<VariableTypesInFile> &)> Receiver;
    Optional<unsigned> Offset;
    Optional<unsigned> Length;

  public:
    VariableTypeCollectorASTConsumer(
        std::function<void(const RequestResult<VariableTypesInFile> &)>
            Receiver,
        Optional<unsigned> Offset, Optional<unsigned> Length)
        : Receiver(std::move(Receiver)), Offset(Offset), Length(Length) {}

    void handlePrimaryAST(ASTUnitRef AstUnit) override {
      auto &CompInst = AstUnit->getCompilerInstance();
      auto *SF = CompInst.getPrimarySourceFile();

      // Construct the range for which variable types are to be queried. If
      // offset/length are unset, the (default) range will be used, which
      // corresponds to the entire document.
      SourceRange Range;
      if (Offset.hasValue() && Length.hasValue()) {
        auto &SM = CompInst.getSourceMgr();
        unsigned BufferID = SF->getBufferID().getValue();
        SourceLoc Start = Lexer::getLocForStartOfToken(SM, BufferID, *Offset);
        SourceLoc End =
            Lexer::getLocForStartOfToken(SM, BufferID, *Offset + *Length);
        Range = SourceRange(Start, End);
      }

      std::vector<VariableTypeInfo> Infos;
      std::string TypeBuffer;
      llvm::raw_string_ostream OS(TypeBuffer);
      VariableTypesInFile Result;

      collectVariableType(*SF, Range, Infos, OS);

      for (auto Info : Infos) {
        Result.Results.push_back({Info.Offset, Info.Length, Info.TypeOffset, Info.HasExplicitType});
      }
      Result.TypeBuffer = OS.str();
      Receiver(RequestResult<VariableTypesInFile>::fromResult(Result));
    }

    void cancelled() override {
      Receiver(RequestResult<VariableTypesInFile>::cancelled());
    }

    void failed(StringRef Error) override {
      Receiver(RequestResult<VariableTypesInFile>::fromError(Error));
    }
  };

  auto Collector = std::make_shared<VariableTypeCollectorASTConsumer>(
      Receiver, Offset, Length);
  /// FIXME: When request cancellation is implemented and Xcode adopts it,
  /// don't use 'OncePerASTToken'.
  static const char OncePerASTToken = 0;
  getASTManager()->processASTAsync(Invok, std::move(Collector),
                                   &OncePerASTToken, CancellationToken,
                                   llvm::vfs::getRealFileSystem());
}
