//===--- Requests.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 "DictionaryKeys.h"
#include "sourcekitd/CodeCompletionResultsArray.h"
#include "sourcekitd/DocStructureArray.h"
#include "sourcekitd/DocSupportAnnotationArray.h"
#include "sourcekitd/TokenAnnotationsArray.h"
#include "sourcekitd/ExpressionTypeArray.h"

#include "SourceKit/Core/Context.h"
#include "SourceKit/Core/LangSupport.h"
#include "SourceKit/Core/NotificationCenter.h"
#include "SourceKit/Support/Concurrency.h"
#include "SourceKit/Support/Logging.h"
#include "SourceKit/Support/Statistic.h"
#include "SourceKit/Support/Tracing.h"
#include "SourceKit/Support/UIdent.h"
#include "SourceKit/SwiftLang/Factory.h"

#include "swift/Basic/ExponentialGrowthAppendingBinaryByteStream.h"
#include "swift/Basic/Mangler.h"
#include "swift/Basic/Version.h"
#include "swift/Demangling/Demangler.h"
#include "swift/Demangling/ManglingMacros.h"
#include "swift/Syntax/Serialization/SyntaxSerialization.h"
#include "swift/Syntax/SyntaxNodes.h"

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/NativeFormatting.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <mutex>

// FIXME: Portability.
#include <dispatch/dispatch.h>

using namespace sourcekitd;
using namespace SourceKit;

namespace {
class LazySKDUID {
  const char *Name;
  mutable std::atomic<sourcekitd_uid_t> UID { nullptr };
public:
  LazySKDUID(const char *Name) : Name(Name) { }

  sourcekitd_uid_t get() const {
    sourcekitd_uid_t UIDValue = UID;
    if (!UIDValue)
      UID = SKDUIDFromUIdent(UIdent(Name));
    return UID;
  }

  operator sourcekitd_uid_t() const {
    return get();
  }

  StringRef str() const {
    return StringRef(Name);
  }
};

struct SKEditorConsumerOptions {
  bool EnableSyntaxMap = false;
  bool EnableStructure = false;
  bool EnableDiagnostics = false;
  SyntaxTreeTransferMode SyntaxTransferMode = SyntaxTreeTransferMode::Off;
  SyntaxTreeSerializationFormat SyntaxSerializationFormat =
      SyntaxTreeSerializationFormat::JSON;
  bool SyntacticOnly = false;
};

} // anonymous namespace

static Optional<UIdent> getUIDForOperationKind(trace::OperationKind OpKind);
static void fillDictionaryForDiagnosticInfo(ResponseBuilder::Dictionary Elem,
                                            const DiagnosticEntryInfo &Info);

#define REQUEST(NAME, CONTENT) static LazySKDUID Request##NAME(CONTENT);
#define KIND(NAME, CONTENT) static LazySKDUID Kind##NAME(CONTENT);
#include "SourceKit/Core/ProtocolUIDs.def"

#define REFACTORING(KIND, NAME, ID) static LazySKDUID Kind##Refactoring##KIND("source.refactoring.kind."#ID);
#include "swift/IDE/RefactoringKinds.def"

static SourceKit::Context *GlobalCtx = nullptr;

void sourcekitd::initializeService(
    StringRef runtimeLibPath, StringRef diagnosticDocumentationPath,
    std::function<void(sourcekitd_response_t)> postNotification) {
  llvm::EnablePrettyStackTrace();
  GlobalCtx =
      new SourceKit::Context(runtimeLibPath, diagnosticDocumentationPath,
                             SourceKit::createSwiftLangSupport);
  auto noteCenter = GlobalCtx->getNotificationCenter();

  noteCenter->addDocumentUpdateNotificationReceiver([postNotification](StringRef DocumentName) {
    static UIdent DocumentUpdateNotificationUID(
        "source.notification.editor.documentupdate");
    ResponseBuilder RespBuilder;
    auto Dict = RespBuilder.getDictionary();
    Dict.set(KeyNotification, DocumentUpdateNotificationUID);
    Dict.set(KeyName, DocumentName);
    postNotification(RespBuilder.createResponse());
  });

  noteCenter->addTestNotificationReceiver([postNotification] {
    static UIdent TestNotification("source.notification.test");
    ResponseBuilder RespBuilder;
    auto Dict = RespBuilder.getDictionary();
    Dict.set(KeyNotification, TestNotification);
    postNotification(RespBuilder.createResponse());
  });

  noteCenter->addSemaEnabledNotificationReceiver([postNotification] {
    static UIdent SemaEnabledNotificationUID(
        "source.notification.sema_enabled");
    ResponseBuilder RespBuilder;
    auto Dict = RespBuilder.getDictionary();
    Dict.set(KeyNotification, SemaEnabledNotificationUID);
    postNotification(RespBuilder.createResponse());
  });

  noteCenter->addCompileWillStartNotificationReceiver([postNotification](uint64_t OpId, trace::OperationKind OpKind, const trace::SwiftInvocation &Inv){
    static UIdent CompileWillStartUID("source.notification.compile-will-start");
    ResponseBuilder RespBuilder;
    auto Dict = RespBuilder.getDictionary();
    Dict.set(KeyNotification, CompileWillStartUID);
    Dict.set(KeyCompileID, std::to_string(OpId));
    Dict.set(KeyFilePath, Inv.Args.PrimaryFile);
    if (auto OperationUID = getUIDForOperationKind(OpKind))
      Dict.set(KeyCompileOperation, OperationUID.getValue());
    Dict.set(KeyCompilerArgsString, Inv.Args.Arguments);
    postNotification(RespBuilder.createResponse());
  });

  noteCenter->addCompileDidFinishNotificationReceiver([postNotification](uint64_t OpId, trace::OperationKind OpKind, ArrayRef<DiagnosticEntryInfo> Diagnostics){
    static UIdent CompileDidFinishUID("source.notification.compile-did-finish");
    ResponseBuilder RespBuilder;
    auto Dict = RespBuilder.getDictionary();
    Dict.set(KeyNotification, CompileDidFinishUID);
    Dict.set(KeyCompileID, std::to_string(OpId));
    if (auto OperationUID = getUIDForOperationKind(OpKind))
      Dict.set(KeyCompileOperation, OperationUID.getValue());
    auto DiagArray = Dict.setArray(KeyDiagnostics);
    for (const auto &DiagInfo : Diagnostics)
      fillDictionaryForDiagnosticInfo(DiagArray.appendDictionary(), DiagInfo);
    postNotification(RespBuilder.createResponse());
  });
}

void sourcekitd::shutdownService() {
  delete GlobalCtx;
  GlobalCtx = nullptr;
}

static SourceKit::Context &getGlobalContext() {
  assert(GlobalCtx);
  return *GlobalCtx;
}

namespace SourceKit {
void SOURCEKITD_PUBLIC setGlobalInMemoryOutputFileSystem(IntrusiveRefCntPtr<clang::InMemoryOutputFileSystem> FS) {
  getGlobalContext().getSwiftLangSupport().setInMemoryOutputFileSystem(std::move(FS));
}
} // namespace SourceKit

static sourcekitd_response_t demangleNames(ArrayRef<const char *> MangledNames,
                                           bool Simplified);

static sourcekitd_response_t
mangleSimpleClassNames(ArrayRef<std::pair<StringRef, StringRef>> ModuleClassPairs);

static sourcekitd_response_t indexSource(StringRef Filename,
                                         ArrayRef<const char *> Args);

static sourcekitd_response_t reportDocInfo(llvm::MemoryBuffer *InputBuf,
                                           StringRef ModuleName,
                                           ArrayRef<const char *> Args);

static void reportCursorInfo(const RequestResult<CursorInfoData> &Result, ResponseReceiver Rec);

static void reportExpressionTypeInfo(const RequestResult<ExpressionTypesInFile> &Result,
                                     ResponseReceiver Rec);

static void reportRangeInfo(const RequestResult<RangeInfo> &Result, ResponseReceiver Rec);

static void reportNameInfo(const RequestResult<NameTranslatingInfo> &Result, ResponseReceiver Rec);

static void findRelatedIdents(StringRef Filename,
                              int64_t Offset,
                              bool CancelOnSubsequentRequest,
                              ArrayRef<const char *> Args,
                              ResponseReceiver Rec);

static sourcekitd_response_t
codeComplete(llvm::MemoryBuffer *InputBuf, int64_t Offset,
             Optional<RequestDict> optionsDict,
             ArrayRef<const char *> Args, Optional<VFSOptions> vfsOptions);

static sourcekitd_response_t codeCompleteOpen(StringRef name,
                                              llvm::MemoryBuffer *InputBuf,
                                              int64_t Offset,
                                              Optional<RequestDict> optionsDict,
                                              ArrayRef<const char *> Args,
                                              Optional<VFSOptions> vfsOptions);

static sourcekitd_response_t
codeCompleteUpdate(StringRef name, int64_t Offset,
                   Optional<RequestDict> optionsDict);

static sourcekitd_response_t codeCompleteClose(StringRef name, int64_t Offset);

static sourcekitd_response_t typeContextInfo(llvm::MemoryBuffer *InputBuf,
                                             int64_t Offset,
                                             Optional<RequestDict> optionsDict,
                                             ArrayRef<const char *> Args,
                                             Optional<VFSOptions> vfsOptions);

static sourcekitd_response_t
conformingMethodList(llvm::MemoryBuffer *InputBuf, int64_t Offset,
                     Optional<RequestDict> optionsDict,
                     ArrayRef<const char *> Args,
                     ArrayRef<const char *> ExpectedTypes,
                     Optional<VFSOptions> vfsOptions);

static sourcekitd_response_t
editorOpen(StringRef Name, llvm::MemoryBuffer *Buf,
           SKEditorConsumerOptions Opts, ArrayRef<const char *> Args,
           Optional<VFSOptions> vfsOptions);

static sourcekitd_response_t
editorOpenInterface(StringRef Name, StringRef ModuleName,
                    Optional<StringRef> Group, ArrayRef<const char *> Args,
                    bool SynthesizedExtensions,
                    Optional<StringRef> InterestedUSR);

static sourcekitd_response_t
editorOpenHeaderInterface(StringRef Name, StringRef HeaderName,
                          ArrayRef<const char *> Args,
                          bool UsingSwiftArgs,
                          bool SynthesizedExtensions,
                          StringRef swiftVersion);

static void
editorOpenSwiftSourceInterface(StringRef Name, StringRef SourceName,
                               ArrayRef<const char *> Args,
                               ResponseReceiver Rec);

static void
editorOpenSwiftTypeInterface(StringRef TypeUsr, ArrayRef<const char *> Args,
                             ResponseReceiver Rec);

static sourcekitd_response_t editorExtractTextFromComment(StringRef Source);

static sourcekitd_response_t editorConvertMarkupToXML(StringRef Source);

static sourcekitd_response_t
editorClose(StringRef Name, bool RemoveCache);

static sourcekitd_response_t
editorReplaceText(StringRef Name, llvm::MemoryBuffer *Buf, unsigned Offset,
                  unsigned Length, SKEditorConsumerOptions Opts);

static void
editorApplyFormatOptions(StringRef Name, RequestDict &FmtOptions);

static sourcekitd_response_t
editorFormatText(StringRef Name, unsigned Line, unsigned Length);

static sourcekitd_response_t
editorExpandPlaceholder(StringRef Name, unsigned Offset, unsigned Length);

static sourcekitd_response_t
editorFindUSR(StringRef DocumentName, StringRef USR);

static sourcekitd_response_t
editorFindInterfaceDoc(StringRef ModuleName, ArrayRef<const char *> Args);

static sourcekitd_response_t
editorFindModuleGroups(StringRef ModuleName, ArrayRef<const char *> Args);

static bool
buildRenameLocationsFromDict(RequestDict &Req, bool UseNewName,
                             std::vector<RenameLocations> &RenameLocations,
                             llvm::SmallString<64> &Error);

static sourcekitd_response_t
createCategorizedEditsResponse(
    const RequestResult<ArrayRef<CategorizedEdits>> &Result);

static sourcekitd_response_t
syntacticRename(llvm::MemoryBuffer *InputBuf,
                ArrayRef<RenameLocations> RenameLocations,
                ArrayRef<const char*> Args);

static sourcekitd_response_t
createCategorizedRenameRangesResponse(
    const RequestResult<ArrayRef<CategorizedRenameRanges>> &Result);

static sourcekitd_response_t
findRenameRanges(llvm::MemoryBuffer *InputBuf,
                 ArrayRef<RenameLocations> RenameLocations,
                 ArrayRef<const char *> Args);

static bool isSemanticEditorDisabled();
static void enableCompileNotifications(bool value);

static SyntaxTreeTransferMode syntaxTransferModeFromUID(sourcekitd_uid_t UID) {
  if (UID == nullptr) {
    // Default is no syntax tree
    return SyntaxTreeTransferMode::Off;
  } else if (UID == KindSyntaxTreeOff) {
    return SyntaxTreeTransferMode::Off;
  } else if (UID == KindSyntaxTreeIncremental) {
    return SyntaxTreeTransferMode::Incremental;
  } else if (UID == KindSyntaxTreeFull) {
    return SyntaxTreeTransferMode::Full;
  } else {
    llvm_unreachable("Unexpected syntax tree transfer mode");
  }
}

static llvm::Optional<SyntaxTreeSerializationFormat>
syntaxSerializationFormatFromUID(sourcekitd_uid_t UID) {
  if (UID == nullptr) {
    // Default is JSON
    return SyntaxTreeSerializationFormat::JSON;
  } else if (UID == KindSyntaxTreeSerializationJSON) {
    return SyntaxTreeSerializationFormat::JSON;
  } else if (UID == KindSyntaxTreeSerializationByteTree) {
    return SyntaxTreeSerializationFormat::ByteTree;
  } else {
    return llvm::None;
  }
}

namespace {
class SKOptionsDictionary : public OptionsDictionary {
  RequestDict Options;

public:
  explicit SKOptionsDictionary(RequestDict Options) : Options(Options) {}

  bool valueForOption(UIdent Key, unsigned &Val) override {
    int64_t result;
    if (Options.getInt64(Key, result, false))
      return false;
    Val = static_cast<unsigned>(result);
    return true;
  }

  bool valueForOption(UIdent Key, bool &Val) override {
    int64_t result;
    if (Options.getInt64(Key, result, false))
      return false;
    Val = result ? true : false;
    return true;
  }

  bool valueForOption(UIdent Key, StringRef &Val) override {
    Optional<StringRef> value = Options.getString(Key);
    if (!value)
      return false;
    Val = *value;
    return true;
  }

  bool forEach(UIdent key, llvm::function_ref<bool(OptionsDictionary &)> applier) override {
    return Options.dictionaryArrayApply(key, [=](RequestDict dict) {
      SKOptionsDictionary skDict(dict);
      return applier(skDict);
    });
  }
};
} // anonymous namespace

static void handleRequestImpl(sourcekitd_object_t Req,
                              ResponseReceiver Receiver);

void sourcekitd::handleRequest(sourcekitd_object_t Req,
                               ResponseReceiver Receiver) {
  LOG_SECTION("handleRequest-before", InfoHighPrio) {
    sourcekitd::printRequestObject(Req, Log->getOS());
  }

  handleRequestImpl(Req, [Receiver](sourcekitd_response_t Resp) {
    LOG_SECTION("handleRequest-after", InfoHighPrio) {
      // Responses are big, print them out with info medium priority.
      if (Logger::isLoggingEnabledForLevel(Logger::Level::InfoMediumPrio))
        sourcekitd::printResponse(Resp, Log->getOS());
    }

    Receiver(Resp);
  });
}

static std::unique_ptr<llvm::MemoryBuffer> getInputBufForRequest(
    Optional<StringRef> SourceFile, Optional<StringRef> SourceText,
    const Optional<VFSOptions> &vfsOptions, llvm::SmallString<64> &ErrBuf) {
  std::unique_ptr<llvm::MemoryBuffer> InputBuf;

  if (SourceText.hasValue()) {
    StringRef BufName;
    if (SourceFile.hasValue())
      BufName = *SourceFile;
    else
      BufName = "<input>";
    InputBuf = llvm::MemoryBuffer::getMemBuffer(*SourceText, BufName);

  } else if (vfsOptions.hasValue() && SourceFile.hasValue()) {
    ErrBuf = "using 'key.sourcefile' to read source text from the filesystem "
             "is not supported when using 'key.vfs.name'";
    return nullptr;

  } else if (SourceFile.hasValue()) {
    llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
        llvm::MemoryBuffer::getFile(*SourceFile);
    if (FileBufOrErr) {
      InputBuf = std::move(FileBufOrErr.get());
    } else {
      llvm::raw_svector_ostream OSErr(ErrBuf);
      OSErr << "error opening input file '" << *SourceFile << "' ("
            << FileBufOrErr.getError().message() << ')';
      return nullptr;
    }
  } else {
    InputBuf = llvm::WritableMemoryBuffer::getNewMemBuffer(0, "<input>");
  }

  return InputBuf;
}

/// Read optional VFSOptions from a request dictionary. The request dictionary
/// *must* outlive the resulting VFSOptions.
/// \returns true on failure and sets \p error.
static Optional<VFSOptions> getVFSOptions(RequestDict &Req) {
  auto name = Req.getString(KeyVFSName);
  if (!name)
    return None;

  std::unique_ptr<OptionsDictionary> options;
  if (auto dict = Req.getDictionary(KeyVFSOptions)) {
    options = std::make_unique<SKOptionsDictionary>(*dict);
  }

  return VFSOptions{name->str(), std::move(options)};
}

static void handleSemanticRequest(
    RequestDict Req, ResponseReceiver Receiver, sourcekitd_uid_t ReqUID,
    Optional<StringRef> SourceFile, Optional<StringRef> SourceText,
    ArrayRef<const char *> Args, Optional<VFSOptions> vfsOptions);

void handleRequestImpl(sourcekitd_object_t ReqObj, ResponseReceiver Rec) {
  // NOTE: if we had a connection context, these stats should move into it.
  static Statistic numRequests(UIdentFromSKDUID(KindStatNumRequests), "# of requests (total)");
  static Statistic numSemaRequests(UIdentFromSKDUID(KindStatNumSemaRequests), "# of semantic requests");
  ++numRequests;

  RequestDict Req(ReqObj);
  sourcekitd_uid_t ReqUID = Req.getUID(KeyRequest);
  if (!ReqUID)
    return Rec(createErrorRequestInvalid("missing 'key.request' with UID value"));

  if (ReqUID == RequestGlobalConfiguration) {
    auto Config = getGlobalContext().getGlobalConfiguration();
    ResponseBuilder RB;
    auto dict = RB.getDictionary();

    Optional<bool> OptimizeForIDE =
        Req.getOptionalInt64(KeyOptimizeForIDE)
            .map([](int64_t v) -> bool { return v; });
    Optional<unsigned> CompletionMaxASTContextReuseCount =
        Req.getOptionalInt64(KeyCompletionMaxASTContextReuseCount)
            .map([](int64_t v) -> unsigned { return v; });
    Optional<unsigned> CompletionCheckDependencyInterval =
        Req.getOptionalInt64(KeyCompletionCheckDependencyInterval)
            .map([](int64_t v) -> unsigned { return v; });

    GlobalConfig::Settings UpdatedConfig =
        Config->update(OptimizeForIDE, CompletionMaxASTContextReuseCount,
                       CompletionCheckDependencyInterval);

    getGlobalContext().getSwiftLangSupport().globalConfigurationUpdated(Config);

    dict.set(KeyOptimizeForIDE, UpdatedConfig.OptimizeForIDE);
    dict.set(KeyCompletionMaxASTContextReuseCount,
             UpdatedConfig.CompletionOpts.MaxASTContextReuseCount);
    dict.set(KeyCompletionCheckDependencyInterval,
             UpdatedConfig.CompletionOpts.CheckDependencyInterval);

    return Rec(RB.createResponse());
  }
  if (ReqUID == RequestProtocolVersion) {
    ResponseBuilder RB;
    auto dict = RB.getDictionary();
    dict.set(KeyVersionMajor, ProtocolMajorVersion);
    dict.set(KeyVersionMinor, static_cast<int64_t>(ProtocolMinorVersion));
    return Rec(RB.createResponse());
  }

  if (ReqUID == RequestCompilerVersion) {
    ResponseBuilder RB;
    auto dict = RB.getDictionary();
    auto thisVersion = swift::version::Version::getCurrentLanguageVersion();
    dict.set(KeyVersionMajor, static_cast<int64_t>(thisVersion[0]));
    dict.set(KeyVersionMinor, static_cast<int64_t>(thisVersion[1]));
    if (thisVersion.size() > 2)
      dict.set(KeyVersionPatch, static_cast<int64_t>(thisVersion[2]));
    else
      dict.set(KeyVersionPatch, static_cast<int64_t>(0));
    return Rec(RB.createResponse());
  }

  if (ReqUID == RequestCrashWithExit) {
    // 'exit' has the same effect as crashing but without the crash log.
    ::exit(1);
  }

  if (ReqUID == RequestTestNotification) {
    getGlobalContext().getNotificationCenter()->postTestNotification();
    return Rec(ResponseBuilder().createResponse());
  }

  if (ReqUID == RequestDemangle) {
    SmallVector<const char *, 8> MangledNames;
    bool Failed = Req.getStringArray(KeyNames, MangledNames, /*isOptional=*/true);
    if (Failed) {
      return Rec(createErrorRequestInvalid(
                                        "'key.names' not an array of strings"));
    }
    int64_t Simplified = false;
    Req.getInt64(KeySimplified, Simplified, /*isOptional=*/true);
    return Rec(demangleNames(MangledNames, Simplified));
  }

  if (ReqUID == RequestMangleSimpleClass) {
    SmallVector<std::pair<StringRef, StringRef>, 16> ModuleClassPairs;
    sourcekitd_response_t err = nullptr;
    bool failed = Req.dictionaryArrayApply(KeyNames, [&](RequestDict dict) {
      Optional<StringRef> ModuleName = dict.getString(KeyModuleName);
      if (!ModuleName.hasValue()) {
        err = createErrorRequestInvalid("missing 'key.modulename'");
        return true;
      }
      Optional<StringRef> ClassName = dict.getString(KeyName);
      if (!ClassName.hasValue()) {
        err = createErrorRequestInvalid("missing 'key.name'");
        return true;
      }
      ModuleClassPairs.push_back(std::make_pair(*ModuleName, *ClassName));
      return false;
    });

    if (failed) {
      if (!err)
        err = createErrorRequestInvalid("missing 'key.names'");
      return Rec(err);
    }

    return Rec(mangleSimpleClassNames(ModuleClassPairs));
  }

  if (ReqUID == RequestEnableCompileNotifications) {
    int64_t value = true;
    if (Req.getInt64(KeyValue, value, /*isOptional=*/false)) {
      return Rec(createErrorRequestInvalid("missing 'key.value'"));
    }
    enableCompileNotifications(value);
    return Rec(ResponseBuilder().createResponse());
  }

  // Just accept 'source.request.buildsettings.register' for now, don't do
  // anything else.
  // FIXME: Heavy WIP here.
  if (ReqUID == RequestBuildSettingsRegister) {
    return Rec(ResponseBuilder().createResponse());
  }

  Optional<StringRef> SourceFile = Req.getString(KeySourceFile);
  Optional<StringRef> SourceText = Req.getString(KeySourceText);

  llvm::SmallString<64> ErrBuf;

  Optional<VFSOptions> vfsOptions;

  if (Optional<StringRef> VFSName = Req.getString(KeyVFSName)) {
    if (ReqUID != RequestEditorOpen && ReqUID != RequestCodeComplete &&
        ReqUID != RequestCodeCompleteOpen && ReqUID != RequestCursorInfo) {
      return Rec(createErrorRequestInvalid(
          "This request does not support custom filesystems"));
    }

    vfsOptions = getVFSOptions(Req);
  }

  SmallVector<const char *, 8> Args;
  bool Failed = Req.getStringArray(KeyCompilerArgs, Args, /*isOptional=*/true);
  if (Failed) {
    return Rec(createErrorRequestInvalid(
        "'key.compilerargs' not an array of strings"));
  }

  if (ReqUID == RequestDocInfo) {
    std::unique_ptr<llvm::MemoryBuffer> InputBuf = getInputBufForRequest(
        SourceFile, SourceText, vfsOptions, ErrBuf);
    if (!InputBuf)
      return Rec(createErrorRequestFailed(ErrBuf.c_str()));
    StringRef ModuleName;
    Optional<StringRef> ModuleNameOpt = Req.getString(KeyModuleName);
    if (ModuleNameOpt.hasValue()) ModuleName = *ModuleNameOpt;
    return Rec(reportDocInfo(InputBuf.get(), ModuleName, Args));
  }

  if (ReqUID == RequestEditorOpen) {
    Optional<StringRef> Name = Req.getString(KeyName);
    if (!Name.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.name'"));
    std::unique_ptr<llvm::MemoryBuffer> InputBuf =
        getInputBufForRequest(SourceFile, SourceText, vfsOptions, ErrBuf);
    if (!InputBuf)
      return Rec(createErrorRequestFailed(ErrBuf.c_str()));
    int64_t EnableSyntaxMap = true;
    Req.getInt64(KeyEnableSyntaxMap, EnableSyntaxMap, /*isOptional=*/true);
    int64_t EnableStructure = true;
    Req.getInt64(KeyEnableStructure, EnableStructure, /*isOptional=*/true);
    int64_t EnableDiagnostics = true;
    Req.getInt64(KeyEnableDiagnostics, EnableDiagnostics, /*isOptional=*/true);
    auto TransferModeUID = Req.getUID(KeySyntaxTreeTransferMode);
    auto SerializationFormatUID = Req.getUID(KeySyntaxTreeSerializationFormat);
    int64_t SyntacticOnly = false;
    Req.getInt64(KeySyntacticOnly, SyntacticOnly, /*isOptional=*/true);

    SKEditorConsumerOptions Opts;
    Opts.EnableSyntaxMap = EnableSyntaxMap;
    Opts.EnableStructure = EnableStructure;
    Opts.EnableDiagnostics = EnableDiagnostics;
    Opts.SyntaxTransferMode = syntaxTransferModeFromUID(TransferModeUID);
    auto SyntaxSerializationFormat =
        syntaxSerializationFormatFromUID(SerializationFormatUID);
    if (!SyntaxSerializationFormat)
      return Rec(createErrorRequestFailed("Invalid serialization format"));
    Opts.SyntaxSerializationFormat = SyntaxSerializationFormat.getValue();
    Opts.SyntacticOnly = SyntacticOnly;
    return Rec(editorOpen(*Name, InputBuf.get(), Opts, Args, std::move(vfsOptions)));
  }
  if (ReqUID == RequestEditorClose) {
    Optional<StringRef> Name = Req.getString(KeyName);
    if (!Name.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.name'"));

    // Whether we remove the cached AST from libcache, by default, false.
    int64_t RemoveCache = false;
    Req.getInt64(KeyRemoveCache, RemoveCache, /*isOptional=*/true);
    return Rec(editorClose(*Name, RemoveCache));
  }
  if (ReqUID == RequestEditorReplaceText) {
    Optional<StringRef> Name = Req.getString(KeyName);
    if (!Name.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.name'"));
    std::unique_ptr<llvm::MemoryBuffer> InputBuf = getInputBufForRequest(
        SourceFile, SourceText, vfsOptions, ErrBuf);
    if (!InputBuf)
      return Rec(createErrorRequestFailed(ErrBuf.c_str()));
    int64_t Offset = 0;
    Req.getInt64(KeyOffset, Offset, /*isOptional=*/true);
    int64_t Length = 0;
    Req.getInt64(KeyLength, Length, /*isOptional=*/true);
    int64_t EnableSyntaxMap = true;
    Req.getInt64(KeyEnableSyntaxMap, EnableSyntaxMap, /*isOptional=*/true);
    int64_t EnableStructure = true;
    Req.getInt64(KeyEnableStructure, EnableStructure, /*isOptional=*/true);
    int64_t EnableDiagnostics = true;
    Req.getInt64(KeyEnableDiagnostics, EnableDiagnostics, /*isOptional=*/true);
    int64_t SyntacticOnly = false;
    Req.getInt64(KeySyntacticOnly, SyntacticOnly, /*isOptional=*/true);
    auto TransferModeUID = Req.getUID(KeySyntaxTreeTransferMode);
    auto SerializationFormatUID = Req.getUID(KeySyntaxTreeSerializationFormat);

    SKEditorConsumerOptions Opts;
    Opts.EnableSyntaxMap = EnableSyntaxMap;
    Opts.EnableStructure = EnableStructure;
    Opts.EnableDiagnostics = EnableDiagnostics;
    Opts.SyntaxTransferMode = syntaxTransferModeFromUID(TransferModeUID);
    auto SyntaxSerializationFormat =
        syntaxSerializationFormatFromUID(SerializationFormatUID);
    if (!SyntaxSerializationFormat)
      return Rec(createErrorRequestFailed("Invalid serialization format"));
    Opts.SyntaxSerializationFormat = SyntaxSerializationFormat.getValue();
    Opts.SyntacticOnly = SyntacticOnly;

    return Rec(editorReplaceText(*Name, InputBuf.get(), Offset, Length, Opts));
  }
  if (ReqUID == RequestEditorFormatText) {
    Optional<StringRef> Name = Req.getString(KeyName);
    if (!Name.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.name'"));
    Optional<RequestDict> FmtOptions = Req.getDictionary(KeyFormatOptions);
    if (FmtOptions.hasValue())
      editorApplyFormatOptions(*Name, *FmtOptions);
    int64_t Line = 0;
    Req.getInt64(KeyLine, Line, /*isOptional=*/false);
    int64_t Length = 0;
    Req.getInt64(KeyLength, Length, /*isOptional=*/true);
    return Rec(editorFormatText(*Name, Line, Length));
  }
  if (ReqUID == RequestEditorExpandPlaceholder) {
    Optional<StringRef> Name = Req.getString(KeyName);
    if (!Name.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.name'"));
    int64_t Offset = 0;
    Req.getInt64(KeyOffset, Offset, /*isOptional=*/false);
    int64_t Length = 0;
    Req.getInt64(KeyLength, Length, /*isOptional=*/false);
    return Rec(editorExpandPlaceholder(*Name, Offset, Length));
  }

  if (ReqUID == RequestEditorOpenInterface) {
    Optional<StringRef> Name = Req.getString(KeyName);
    if (!Name.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.name'"));
    Optional<StringRef> ModuleName = Req.getString(KeyModuleName);
    if (!ModuleName.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.modulename'"));
    Optional<StringRef> GroupName = Req.getString(KeyGroupName);
    int64_t SynthesizedExtension = false;
    Req.getInt64(KeySynthesizedExtension, SynthesizedExtension,
                 /*isOptional=*/true);
    Optional<StringRef> InterestedUSR = Req.getString(KeyInterestedUSR);
    return Rec(editorOpenInterface(*Name, *ModuleName, GroupName, Args,
                                   SynthesizedExtension, InterestedUSR));
  }

  if (ReqUID == RequestEditorOpenHeaderInterface) {
    Optional<StringRef> Name = Req.getString(KeyName);
    if (!Name.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.name'"));
    Optional<StringRef> HeaderName = Req.getString(KeyFilePath);
    if (!HeaderName.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.filepath'"));
    int64_t SynthesizedExtension = false;
    Req.getInt64(KeySynthesizedExtension, SynthesizedExtension,
                 /*isOptional=*/true);
    Optional<int64_t> UsingSwiftArgs = Req.getOptionalInt64(KeyUsingSwiftArgs);
    std::string swiftVer;
    Optional<StringRef> swiftVerValStr = Req.getString(KeySwiftVersion);
    if (swiftVerValStr.hasValue()) {
      swiftVer = swiftVerValStr.getValue().str();
    } else {
      Optional<int64_t> swiftVerVal = Req.getOptionalInt64(KeySwiftVersion);
      if (swiftVerVal.hasValue())
        swiftVer = std::to_string(*swiftVerVal);
    }
    return Rec(editorOpenHeaderInterface(*Name, *HeaderName, Args,
                                         UsingSwiftArgs.getValueOr(false),
                                         SynthesizedExtension, swiftVer));
  }

  if (ReqUID == RequestEditorOpenSwiftSourceInterface) {
    Optional<StringRef> Name = Req.getString(KeyName);
    if (!Name.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.name'"));
    Optional<StringRef> FileName = Req.getString(KeySourceFile);
    if (!FileName.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.sourcefile'"));
    return editorOpenSwiftSourceInterface(*Name, *FileName, Args, Rec);
  }

  if (ReqUID == RequestEditorOpenSwiftTypeInterface) {
    Optional<StringRef> Usr = Req.getString(KeyUSR);
    if (!Usr.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.usr'"));
    return editorOpenSwiftTypeInterface(*Usr, Args, Rec);
  }

  if (ReqUID == RequestEditorExtractTextFromComment) {
    Optional<StringRef> Source = Req.getString(KeySourceText);
    if (!Source.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.sourcetext'"));
    return Rec(editorExtractTextFromComment(Source.getValue()));
  }

  if (ReqUID == RequestMarkupToXML) {
    Optional<StringRef> Source = Req.getString(KeySourceText);
    if (!Source.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.sourcetext'"));
    return Rec(editorConvertMarkupToXML(Source.getValue()));
  }

  if (ReqUID == RequestEditorFindUSR) {
    Optional<StringRef> Name = Req.getString(KeySourceFile);
    if (!Name.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.sourcefile'"));
    Optional<StringRef> USR = Req.getString(KeyUSR);
    if (!USR.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.usr'"));
    return Rec(editorFindUSR(*Name, *USR));
  }

  if (ReqUID == RequestEditorFindInterfaceDoc) {
    Optional<StringRef> ModuleName = Req.getString(KeyModuleName);
    if (!ModuleName.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.modulename'"));
    return Rec(editorFindInterfaceDoc(*ModuleName, Args));
  }

  if (ReqUID == RequestModuleGroups) {
    Optional<StringRef> ModuleName = Req.getString(KeyModuleName);
    if (!ModuleName.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.modulename'"));
    return Rec(editorFindModuleGroups(*ModuleName, Args));
  }

  if (ReqUID == RequestSyntacticRename) {
    std::unique_ptr<llvm::MemoryBuffer> InputBuf = getInputBufForRequest(
        SourceFile, SourceText, vfsOptions, ErrBuf);
    if (!InputBuf)
      return Rec(createErrorRequestFailed(ErrBuf.c_str()));

    std::vector<RenameLocations> RenameLocations;
    if (buildRenameLocationsFromDict(Req, true, RenameLocations, ErrBuf))
      return Rec(createErrorRequestFailed(ErrBuf.c_str()));
    return Rec(syntacticRename(InputBuf.get(), RenameLocations, Args));
  }

  if (ReqUID == RequestFindRenameRanges) {
    std::unique_ptr<llvm::MemoryBuffer> InputBuf = getInputBufForRequest(
        SourceFile, SourceText, vfsOptions, ErrBuf);
    if (!InputBuf)
      return Rec(createErrorRequestFailed(ErrBuf.c_str()));

    std::vector<RenameLocations> RenameLocations;
    if (buildRenameLocationsFromDict(Req, false, RenameLocations, ErrBuf))
      return Rec(createErrorRequestFailed(ErrBuf.c_str()));
    return Rec(findRenameRanges(InputBuf.get(), RenameLocations, Args));
  }

  if (ReqUID == RequestCodeCompleteClose) {
    // Unlike opening code completion, this is not a semantic request.
    Optional<StringRef> Name = Req.getString(KeyName);
    if (!Name.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.name'"));
    int64_t Offset;
    if (Req.getInt64(KeyOffset, Offset, /*isOptional=*/false))
      return Rec(createErrorRequestInvalid("missing 'key.offset'"));
    return Rec(codeCompleteClose(*Name, Offset));
  }

  if (ReqUID == RequestCodeCompleteCacheOnDisk) {
    Optional<StringRef> Name = Req.getString(KeyName);
    if (!Name.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.name'"));
    LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
    Lang.codeCompleteCacheOnDisk(*Name);
    ResponseBuilder b;
    return Rec(b.createResponse());
  }

  if (ReqUID == RequestCodeCompleteSetPopularAPI) {
    llvm::SmallVector<const char *, 0> popular;
    llvm::SmallVector<const char *, 0> unpopular;
    Req.getStringArray(KeyPopular, popular, /*isOptional=*/false);
    Req.getStringArray(KeyUnpopular, unpopular, /*isOptional=*/false);
    LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
    Lang.codeCompleteSetPopularAPI(popular, unpopular);
    ResponseBuilder b;
    return Rec(b.createResponse());
  }

  if (ReqUID == RequestCodeCompleteSetCustom) {
    SmallVector<CustomCompletionInfo, 16> customCompletions;
    sourcekitd_response_t err = nullptr;
    bool failed = Req.dictionaryArrayApply(KeyResults, [&](RequestDict dict) {
      CustomCompletionInfo CCInfo;
      Optional<StringRef> Name = dict.getString(KeyName);
      if (!Name.hasValue()) {
        err = createErrorRequestInvalid("missing 'key.name'");
        return true;
      }
      CCInfo.Name = (*Name).str();

      sourcekitd_uid_t Kind = dict.getUID(KeyKind);
      if (!Kind) {
        err = createErrorRequestInvalid("missing 'key.kind'");
        return true;
      }
      CCInfo.Kind = Kind;

      SmallVector<sourcekitd_uid_t, 3> contexts;
      if (dict.getUIDArray(KeyContext, contexts, false)) {
        err = createErrorRequestInvalid("missing 'key.context'");
        return true;
      }

      for (auto context : contexts) {
        if (context == KindExpr) {
          CCInfo.Contexts |= CustomCompletionInfo::Expr;
        } else if (context == KindStmt) {
          CCInfo.Contexts |= CustomCompletionInfo::Stmt;
        } else if (context == KindType) {
          CCInfo.Contexts |= CustomCompletionInfo::Type;
        } else if (context == KindForEachSequence) {
          CCInfo.Contexts |= CustomCompletionInfo::ForEachSequence;
        } else {
          err = createErrorRequestInvalid("invalid value for 'key.context'");
          return true;
        }
      }

      customCompletions.push_back(std::move(CCInfo));
      return false;
    });

    if (failed) {
      if (!err)
        err = createErrorRequestInvalid("missing 'key.results'");
      return Rec(err);
    }

    LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
    Lang.codeCompleteSetCustom(customCompletions);
    return Rec(ResponseBuilder().createResponse());
  }

  if (ReqUID == RequestStatistics) {
    LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
    Lang.getStatistics([Rec](ArrayRef<Statistic *> stats) {
      ResponseBuilder builder;
      auto results = builder.getDictionary().setArray(KeyResults);
      auto addStat = [&results](Statistic *stat) {
        auto dict = results.appendDictionary();
        dict.set(KeyKind, stat->name);
        dict.set(KeyDescription, stat->description);
        dict.set(KeyValue, stat->value);
      };

      addStat(&numRequests);
      addStat(&numSemaRequests);
      std::for_each(stats.begin(), stats.end(), addStat);

      Rec(builder.createResponse());
    });
    return;
  }

  if (!SourceFile.hasValue() && !SourceText.hasValue() &&
      ReqUID != RequestCodeCompleteUpdate)
    return Rec(createErrorRequestInvalid(
        "missing 'key.sourcefile' or 'key.sourcetext'"));

  // Requests that need semantic typechecking.

  // Typechecking arrays can blow up the stack currently.
  // Run them under a malloc'ed stack.

  static WorkQueue SemaQueue{ WorkQueue::Dequeuing::Concurrent,
                              "sourcekit.request.semantic" };
  sourcekitd_request_retain(ReqObj);
  ++numSemaRequests;
  SemaQueue.dispatch(
      [ReqObj, Rec, ReqUID, SourceFile, SourceText, Args] {
        RequestDict Req(ReqObj);
        auto vfsOptions = getVFSOptions(Req);
        handleSemanticRequest(Req, Rec, ReqUID, SourceFile, SourceText, Args,
                              std::move(vfsOptions));
        sourcekitd_request_release(ReqObj);
      },
      /*isStackDeep=*/true);
}

static void handleSemanticRequest(
    RequestDict Req, ResponseReceiver Rec, sourcekitd_uid_t ReqUID,
    Optional<StringRef> SourceFile, Optional<StringRef> SourceText,
    ArrayRef<const char *> Args, Optional<VFSOptions> vfsOptions) {
  llvm::SmallString<64> ErrBuf;

  if (isSemanticEditorDisabled())
      return Rec(createErrorRequestFailed("semantic editor is disabled"));

  if (ReqUID == RequestCodeComplete) {
    std::unique_ptr<llvm::MemoryBuffer> InputBuf =
        getInputBufForRequest(SourceFile, SourceText, vfsOptions, ErrBuf);
    if (!InputBuf)
      return Rec(createErrorRequestFailed(ErrBuf.c_str()));
    int64_t Offset;
    if (Req.getInt64(KeyOffset, Offset, /*isOptional=*/false))
      return Rec(createErrorRequestInvalid("missing 'key.offset'"));
    Optional<RequestDict> options = Req.getDictionary(KeyCodeCompleteOptions);
    return Rec(codeComplete(InputBuf.get(), Offset, options, Args,
                            std::move(vfsOptions)));
  }

  if (ReqUID == RequestCodeCompleteOpen) {
    std::unique_ptr<llvm::MemoryBuffer> InputBuf = getInputBufForRequest(
        SourceFile, SourceText, vfsOptions, ErrBuf);
    if (!InputBuf)
      return Rec(createErrorRequestFailed(ErrBuf.c_str()));
    Optional<StringRef> Name = Req.getString(KeyName);
    if (!Name.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.name'"));
    int64_t Offset;
    if (Req.getInt64(KeyOffset, Offset, /*isOptional=*/false))
      return Rec(createErrorRequestInvalid("missing 'key.offset'"));
    Optional<RequestDict> options = Req.getDictionary(KeyCodeCompleteOptions);
    return Rec(codeCompleteOpen(*Name, InputBuf.get(), Offset, options, Args,
                                std::move(vfsOptions)));
  }

  if (ReqUID == RequestCodeCompleteUpdate) {
    Optional<StringRef> Name = Req.getString(KeyName);
    if (!Name.hasValue())
      return Rec(createErrorRequestInvalid("missing 'key.name'"));
    int64_t Offset;
    if (Req.getInt64(KeyOffset, Offset, /*isOptional=*/false))
      return Rec(createErrorRequestInvalid("missing 'key.offset'"));
    Optional<RequestDict> options = Req.getDictionary(KeyCodeCompleteOptions);
    return Rec(codeCompleteUpdate(*Name, Offset, options));
  }

  if (ReqUID == RequestTypeContextInfo) {
    std::unique_ptr<llvm::MemoryBuffer> InputBuf = getInputBufForRequest(
        SourceFile, SourceText, vfsOptions, ErrBuf);
    if (!InputBuf)
      return Rec(createErrorRequestFailed(ErrBuf.c_str()));
    int64_t Offset;
    if (Req.getInt64(KeyOffset, Offset, /*isOptional=*/false))
      return Rec(createErrorRequestInvalid("missing 'key.offset'"));
    Optional<RequestDict> options =
        Req.getDictionary(KeyTypeContextInfoOptions);
    return Rec(typeContextInfo(InputBuf.get(), Offset, options, Args,
                               std::move(vfsOptions)));
  }

  if (ReqUID == RequestConformingMethodList) {
    std::unique_ptr<llvm::MemoryBuffer> InputBuf = getInputBufForRequest(
        SourceFile, SourceText, vfsOptions, ErrBuf);
    if (!InputBuf)
      return Rec(createErrorRequestFailed(ErrBuf.c_str()));
    int64_t Offset;
    if (Req.getInt64(KeyOffset, Offset, /*isOptional=*/false))
      return Rec(createErrorRequestInvalid("missing 'key.offset'"));
    SmallVector<const char *, 8> ExpectedTypeNames;
    if (Req.getStringArray(KeyExpectedTypes, ExpectedTypeNames, true))
      return Rec(createErrorRequestInvalid("invalid 'key.expectedtypes'"));
    Optional<RequestDict> options =
        Req.getDictionary(KeyConformingMethodListOptions);
    return Rec(
        conformingMethodList(InputBuf.get(), Offset, options, Args,
                             ExpectedTypeNames, std::move(vfsOptions)));
  }

  if (!SourceFile.hasValue())
    return Rec(createErrorRequestInvalid("missing 'key.sourcefile'"));

  if (ReqUID == RequestIndex) {
    return Rec(indexSource(*SourceFile, Args));
  }

  if (ReqUID == RequestCursorInfo) {
    LangSupport &Lang = getGlobalContext().getSwiftLangSupport();

    // For backwards compatibility, the default is 1.
    int64_t CancelOnSubsequentRequest = 1;
    Req.getInt64(KeyCancelOnSubsequentRequest, CancelOnSubsequentRequest,
                 /*isOptional=*/true);

    int64_t Offset;
    if (!Req.getInt64(KeyOffset, Offset, /*isOptional=*/false)) {
      int64_t Length = 0;
      Req.getInt64(KeyLength, Length, /*isOptional=*/true);
      int64_t Actionables = false;
      Req.getInt64(KeyRetrieveRefactorActions, Actionables, /*isOptional=*/true);
      int64_t SymbolGraph = false;
      Req.getInt64(KeyRetrieveSymbolGraph, SymbolGraph, /*isOptional=*/true);
      return Lang.getCursorInfo(
          *SourceFile, Offset, Length, Actionables, SymbolGraph,
          CancelOnSubsequentRequest, Args, std::move(vfsOptions),
          [Rec](const RequestResult<CursorInfoData> &Result) {
            reportCursorInfo(Result, Rec);
          });
    }
    if (auto USR = Req.getString(KeyUSR)) {
      return Lang.getCursorInfoFromUSR(
          *SourceFile, *USR, CancelOnSubsequentRequest, Args, std::move(vfsOptions),
          [Rec](const RequestResult<CursorInfoData> &Result) {
            reportCursorInfo(Result, Rec);
          });
    }

    return Rec(createErrorRequestInvalid(
        "either 'key.offset' or 'key.usr' is required"));
  }

  if (ReqUID == RequestRangeInfo) {
    LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
    int64_t Offset;
    int64_t Length;
    // For backwards compatibility, the default is 1.
    int64_t CancelOnSubsequentRequest = 1;
    Req.getInt64(KeyCancelOnSubsequentRequest, CancelOnSubsequentRequest,
                 /*isOptional=*/true);
    if (!Req.getInt64(KeyOffset, Offset, /*isOptional=*/false)) {
      if (!Req.getInt64(KeyLength, Length, /*isOptional=*/false)) {
        return Lang.getRangeInfo(*SourceFile, Offset, Length,
                                 CancelOnSubsequentRequest, Args,
          [Rec](const RequestResult<RangeInfo> &Result) {
            reportRangeInfo(Result, Rec);
          });
      }
    }

    return Rec(createErrorRequestInvalid(
      "'key.offset' or 'key.length' is required"));
  }

  if (ReqUID == RequestSemanticRefactoring) {
    int64_t Line = 0;
    int64_t Column = 0;
    int64_t Length = 0;
    auto KA = Req.getUID(KeyActionUID);
    if (!KA) {
      return Rec(createErrorRequestInvalid("'key.actionuid' is required"));
    }
    SemanticRefactoringInfo Info;
    Info.Kind = SemanticRefactoringKind::None;

#define SEMANTIC_REFACTORING(KIND, NAME, ID)                                   \
  if (KA == KindRefactoring##KIND) Info.Kind = SemanticRefactoringKind::KIND;
#include "swift/IDE/RefactoringKinds.def"

    if (Info.Kind == SemanticRefactoringKind::None)
      return Rec(createErrorRequestInvalid("'key.actionuid' isn't recognized"));

    if (!Req.getInt64(KeyLine, Line, /*isOptional=*/false)) {
      if (!Req.getInt64(KeyColumn, Column, /*isOptional=*/false)) {
        Req.getInt64(KeyLength, Length, /*isOptional=*/true);
        if (auto N = Req.getString(KeyName))
          Info.PreferredName = *N;
        LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
        Info.Line = Line;
        Info.Column = Column;
        Info.Length = Length;
        return Lang.semanticRefactoring(*SourceFile, Info, Args,
          [Rec](const RequestResult<ArrayRef<CategorizedEdits>> &Result) {
            Rec(createCategorizedEditsResponse(Result));
        });
      }
    }
    return Rec(createErrorRequestInvalid("'key.line' or 'key.column' are required"));
  }

  if (ReqUID == RequestCollectExpressionType) {
    LangSupport &Lang = getGlobalContext().getSwiftLangSupport();

    SmallVector<const char *, 8> ExpectedProtocols;
    if (Req.getStringArray(KeyExpectedTypes, ExpectedProtocols, true))
      return Rec(createErrorRequestInvalid("invalid 'key.expectedtypes'"));
    int64_t CanonicalTy = false;
    Req.getInt64(KeyCanonicalizeType, CanonicalTy, /*isOptional=*/true);
    return Lang.collectExpressionTypes(*SourceFile, Args, ExpectedProtocols,
                                       CanonicalTy,
      [Rec](const RequestResult<ExpressionTypesInFile> &Result) {
        reportExpressionTypeInfo(Result, Rec);
      });
  }

  if (ReqUID == RequestFindLocalRenameRanges) {
    int64_t Line = 0, Column = 0, Length = 0;
    if (Req.getInt64(KeyLine, Line, /*isOptional=*/false))
      return Rec(createErrorRequestInvalid("'key.line' is required"));
    if (Req.getInt64(KeyColumn, Column, /*isOptional=*/false))
      return Rec(createErrorRequestInvalid("'key.column' is required"));
    Req.getInt64(KeyLength, Length, /*isOptional=*/true);

    LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
    return Lang.findLocalRenameRanges(
        *SourceFile, Line, Column, Length, Args,
        [Rec](const RequestResult<ArrayRef<CategorizedRenameRanges>> &Result) {
          Rec(createCategorizedRenameRangesResponse(Result));
        });
  }

  if (ReqUID == RequestNameTranslation) {
    LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
    int64_t Offset;
    if (Req.getInt64(KeyOffset, Offset, /*isOptional=*/false)) {
      return Rec(createErrorRequestInvalid("'key.offset' is required"));
    }
    NameTranslatingInfo Input;
    auto NK = Req.getUID(KeyNameKind);
    if (!NK) {
      return Rec(createErrorRequestInvalid("'key.namekind' is required"));
    }

    static UIdent UIDKindNameSwift(KindNameSwift.str());
    static UIdent UIDKindNameObjc(KindNameObjc.str());

    if (NK == KindNameSwift.get())
      Input.NameKind = UIDKindNameSwift;
    else if (NK == KindNameObjc.get())
      Input.NameKind = UIDKindNameObjc;
    else
      return Rec(createErrorRequestInvalid("'key.namekind' is unrecognizable"));
    if (auto Base = Req.getString(KeyBaseName)) {
      if (Input.NameKind == UIDKindNameSwift) {
        Input.BaseName = Base.getValue().trim('`');
      } else {
        Input.BaseName = Base.getValue();
      }
    }
    llvm::SmallVector<const char*, 4> ArgParts;
    llvm::SmallVector<const char*, 4> Selectors;
    Req.getStringArray(KeyArgNames, ArgParts, true);
    Req.getStringArray(KeySelectorPieces, Selectors, true);
    if (!ArgParts.empty() && !Selectors.empty()) {
      return Rec(createErrorRequestInvalid("cannot specify 'key.selectorpieces' "
                                           "and 'key.argnames' at the same time"));
    }
    std::transform(ArgParts.begin(), ArgParts.end(),
                   std::back_inserter(Input.ArgNames),
                   [](const char *C) { return StringRef(C).trim('`'); });
    std::transform(Selectors.begin(), Selectors.end(),
                   std::back_inserter(Input.ArgNames),
                   [](const char *C) { return StringRef(C); });
    return Lang.getNameInfo(*SourceFile, Offset, Input, Args,
      [Rec](const RequestResult<NameTranslatingInfo> &Result) {
        reportNameInfo(Result, Rec);
      });
  }

  if (ReqUID == RequestRelatedIdents) {
    int64_t Offset;
    if (Req.getInt64(KeyOffset, Offset, /*isOptional=*/false))
      return Rec(createErrorRequestInvalid("missing 'key.offset'"));

    // For backwards compatibility, the default is 1.
    int64_t CancelOnSubsequentRequest = 1;
    Req.getInt64(KeyCancelOnSubsequentRequest, CancelOnSubsequentRequest,
                 /*isOptional=*/true);

    return findRelatedIdents(*SourceFile, Offset, CancelOnSubsequentRequest,
                             Args, Rec);
  }

  {
    llvm::raw_svector_ostream OSErr(ErrBuf);
    OSErr << "unknown request: " << UIdentFromSKDUID(ReqUID).getName();
  }
  return Rec(createErrorRequestInvalid(ErrBuf.c_str()));
}

//===----------------------------------------------------------------------===//
// Index
//===----------------------------------------------------------------------===//

namespace {
class SKIndexingConsumer : public IndexingConsumer {
  struct Entity {
    UIdent Kind;
    ResponseBuilder::Dictionary Data;
    ResponseBuilder::Array Entities;
    ResponseBuilder::Array Related;
  };
  SmallVector<Entity, 6> EntitiesStack;

  struct Dependency {
    UIdent Kind;
    ResponseBuilder::Dictionary Data;
    ResponseBuilder::Array Dependencies;
  };
  SmallVector<Dependency, 6> DependenciesStack;

  ResponseBuilder::Dictionary TopDict;
  bool Cancelled = false;

public:
  std::string ErrorDescription;

  explicit SKIndexingConsumer(ResponseBuilder &RespBuilder) {
    TopDict = RespBuilder.getDictionary();

    // First in stack is the top-level "key.entities" container.
    EntitiesStack.push_back(
        { UIdent(),
          TopDict,
          ResponseBuilder::Array(),
          ResponseBuilder::Array() });

    DependenciesStack.push_back({UIdent(), TopDict, ResponseBuilder::Array() });
  }
  ~SKIndexingConsumer() override {
    assert(Cancelled ||
           (EntitiesStack.size() == 1 && DependenciesStack.size() == 1));
    (void) Cancelled;
  }

  void failed(StringRef ErrDescription) override;

  bool startDependency(UIdent Kind,
                       StringRef Name,
                       StringRef Path,
                       bool IsSystem) override;

  bool finishDependency(UIdent Kind) override;

  bool startSourceEntity(const EntityInfo &Info) override;

  bool recordRelatedEntity(const EntityInfo &Info) override;

  bool finishSourceEntity(UIdent Kind) override;
};
} // end anonymous namespace

static sourcekitd_response_t indexSource(StringRef Filename,
                                         ArrayRef<const char *> Args) {
  ResponseBuilder RespBuilder;
  SKIndexingConsumer IdxConsumer(RespBuilder);
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.indexSource(Filename, IdxConsumer, Args);

  if (!IdxConsumer.ErrorDescription.empty())
    return createErrorRequestFailed(IdxConsumer.ErrorDescription.c_str());

  return RespBuilder.createResponse();
}

void SKIndexingConsumer::failed(StringRef ErrDescription) {
  ErrorDescription = ErrDescription.str();
}

bool SKIndexingConsumer::startDependency(UIdent Kind,
                                         StringRef Name,
                                         StringRef Path,
                                         bool IsSystem) {
  Dependency &Parent = DependenciesStack.back();
  ResponseBuilder::Array &Arr = Parent.Dependencies;
  if (Arr.isNull())
    Arr = Parent.Data.setArray(KeyDependencies);

  auto Elem = Arr.appendDictionary();
  Elem.set(KeyKind, Kind);
  Elem.set(KeyName, Name);
  Elem.set(KeyFilePath, Path);
  if (IsSystem)
    Elem.setBool(KeyIsSystem, IsSystem);

  DependenciesStack.push_back({ Kind, Elem, ResponseBuilder::Array() });
  return true;
}

bool SKIndexingConsumer::finishDependency(UIdent Kind) {
  assert(DependenciesStack.back().Kind == Kind);
  DependenciesStack.pop_back();
  return true;
}

bool SKIndexingConsumer::startSourceEntity(const EntityInfo &Info) {
  Entity &Parent = EntitiesStack.back();
  ResponseBuilder::Array &Arr = Parent.Entities;
  if (Arr.isNull())
    Arr = Parent.Data.setArray(KeyEntities);

  auto Elem = Arr.appendDictionary();
  Elem.set(KeyKind, Info.Kind);
  if (!Info.Name.empty())
    Elem.set(KeyName, Info.Name);
  if (!Info.USR.empty())
    Elem.set(KeyUSR, Info.USR);
  if (Info.Line != 0) {
    assert(Info.Column != 0);
    Elem.set(KeyLine, Info.Line);
    Elem.set(KeyColumn, Info.Column);
  }
  if (!Info.Group.empty())
    Elem.set(KeyGroupName, Info.Group);

  if (!Info.ReceiverUSR.empty())
    Elem.set(KeyReceiverUSR, Info.ReceiverUSR);
  if (Info.IsDynamic)
    Elem.setBool(KeyIsDynamic, true);
  if (Info.IsImplicit)
    Elem.setBool(KeyIsImplicit, true);
  if (Info.IsTestCandidate)
    Elem.setBool(KeyIsTestCandidate, true);

  if (!Info.Attrs.empty()) {
    auto AttrArray = Elem.setArray(KeyAttributes);
    for (auto Attr : Info.Attrs) {
      auto AttrDict = AttrArray.appendDictionary();
      AttrDict.set(KeyAttribute, Attr);
    }
  }

  if (Info.EffectiveAccess)
    Elem.set(KeyEffectiveAccess, Info.EffectiveAccess.getValue());

  EntitiesStack.push_back({ Info.Kind, Elem, ResponseBuilder::Array(),
                            ResponseBuilder::Array()});
  return true;
}

bool SKIndexingConsumer::recordRelatedEntity(const EntityInfo &Info) {
  assert(EntitiesStack.size() > 1 && "Related entity at top-level ?");
  Entity &Parent = EntitiesStack.back();
  ResponseBuilder::Array &Arr = Parent.Related;
  if (Arr.isNull())
    Arr = Parent.Data.setArray(KeyRelated);

  auto Elem = Arr.appendDictionary();
  Elem.set(KeyKind, Info.Kind);
  if (!Info.Name.empty())
    Elem.set(KeyName, Info.Name);
  if (!Info.USR.empty())
    Elem.set(KeyUSR, Info.USR);
  if (Info.Line != 0) {
    assert(Info.Column != 0);
    Elem.set(KeyLine, Info.Line);
    Elem.set(KeyColumn, Info.Column);
  }

  return true;
}

bool SKIndexingConsumer::finishSourceEntity(UIdent Kind) {
  Entity &CurrEnt = EntitiesStack.back();
  assert(CurrEnt.Kind == Kind);
  (void) CurrEnt;
  EntitiesStack.pop_back();
  return true;
}

//===----------------------------------------------------------------------===//
// ReportDocInfo
//===----------------------------------------------------------------------===//

namespace {

class SKDocConsumer : public DocInfoConsumer {
  ResponseBuilder &RespBuilder;

  struct Entity {
    UIdent Kind;
    ResponseBuilder::Dictionary Data;
    ResponseBuilder::Array Entities;
    ResponseBuilder::Array Inherits;
    ResponseBuilder::Array Conforms;
    ResponseBuilder::Array Attrs;
  };
  SmallVector<Entity, 6> EntitiesStack;

  ResponseBuilder::Dictionary TopDict;
  ResponseBuilder::Array Diags;

  DocSupportAnnotationArrayBuilder AnnotationsBuilder;

  bool Cancelled = false;

  void addDocEntityInfoToDict(const DocEntityInfo &Info,
                              ResponseBuilder::Dictionary Dict);
public:
  std::string ErrorDescription;

  explicit SKDocConsumer(ResponseBuilder &RespBuilder)
      : RespBuilder(RespBuilder) {
    TopDict = RespBuilder.getDictionary();

    // First in stack is the top-level "key.entities" container.
    EntitiesStack.push_back(
        { UIdent(),
          TopDict,
          ResponseBuilder::Array(),
          ResponseBuilder::Array(),
          ResponseBuilder::Array(),
          ResponseBuilder::Array() });
  }
  ~SKDocConsumer() override {
    assert(Cancelled || EntitiesStack.size() == 1);
    (void) Cancelled;
  }

  sourcekitd_response_t createResponse() {
    TopDict.setCustomBuffer(KeyAnnotations, AnnotationsBuilder.createBuffer());
    return RespBuilder.createResponse();
  }

  void failed(StringRef ErrDescription) override;

  bool handleSourceText(StringRef Text) override;

  bool handleAnnotation(const DocEntityInfo &Info) override;

  bool startSourceEntity(const DocEntityInfo &Info) override;

  bool handleInheritsEntity(const DocEntityInfo &Info) override;
  bool handleConformsToEntity(const DocEntityInfo &Info) override;
  bool handleExtendsEntity(const DocEntityInfo &Info) override;

  bool handleAvailableAttribute(const AvailableAttrInfo &Info) override;

  bool finishSourceEntity(UIdent Kind) override;

  bool handleDiagnostic(const DiagnosticEntryInfo &Info) override;
};
} // end anonymous namespace

static sourcekitd_response_t demangleNames(ArrayRef<const char *> MangledNames,
                                           bool Simplified) {
  swift::Demangle::DemangleOptions DemangleOptions;
  if (Simplified) {
    DemangleOptions =
      swift::Demangle::DemangleOptions::SimplifiedUIDemangleOptions();
  }

  auto getDemangledName = [&](StringRef MangledName) -> std::string {
    if (!swift::Demangle::isSwiftSymbol(MangledName))
      return std::string(); // Not a mangled name

    std::string Result = swift::Demangle::demangleSymbolAsString(
        MangledName, DemangleOptions);

    if (Result == MangledName)
      return std::string(); // Not a mangled name

    return Result;
  };

  ResponseBuilder RespBuilder;
  auto Arr = RespBuilder.getDictionary().setArray(KeyResults);
  for (auto MangledName : MangledNames) {
    std::string Result = getDemangledName(MangledName);
    auto Entry = Arr.appendDictionary();
    Entry.set(KeyName, Result.c_str());
  }

  return RespBuilder.createResponse();
}

static std::string mangleSimpleClass(StringRef moduleName,
                                     StringRef className) {
  using namespace swift::Demangle;
  Demangler Dem;
  auto moduleNode = Dem.createNode(Node::Kind::Module, moduleName);
  auto IdNode = Dem.createNode(Node::Kind::Identifier, className);
  auto classNode = Dem.createNode(Node::Kind::Class);
  auto typeNode = Dem.createNode(Node::Kind::Type);
  auto typeManglingNode = Dem.createNode(Node::Kind::TypeMangling);
  auto globalNode = Dem.createNode(Node::Kind::Global);

  classNode->addChild(moduleNode, Dem);
  classNode->addChild(IdNode, Dem);
  typeNode->addChild(classNode, Dem);
  typeManglingNode->addChild(typeNode, Dem);
  globalNode->addChild(typeManglingNode, Dem);
  return mangleNode(globalNode);
}

static sourcekitd_response_t
mangleSimpleClassNames(ArrayRef<std::pair<StringRef, StringRef>> ModuleClassPairs) {
  ResponseBuilder RespBuilder;
  auto Arr = RespBuilder.getDictionary().setArray(KeyResults);
  for (auto &pair : ModuleClassPairs) {
    std::string Result = mangleSimpleClass(pair.first, pair.second);
    auto Entry = Arr.appendDictionary();
    Entry.set(KeyName, Result.c_str());
  }

  return RespBuilder.createResponse();
}

static sourcekitd_response_t reportDocInfo(llvm::MemoryBuffer *InputBuf,
                                           StringRef ModuleName,
                                           ArrayRef<const char *> Args) {
  ResponseBuilder RespBuilder;
  SKDocConsumer DocConsumer(RespBuilder);
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.getDocInfo(InputBuf, ModuleName, Args, DocConsumer);

  if (!DocConsumer.ErrorDescription.empty())
    return createErrorRequestFailed(DocConsumer.ErrorDescription.c_str());

  return DocConsumer.createResponse();
}

void SKDocConsumer::addDocEntityInfoToDict(const DocEntityInfo &Info,
                                           ResponseBuilder::Dictionary Elem) {
  Elem.set(KeyKind, Info.Kind);
  if (!Info.Name.empty())
    Elem.set(KeyName, Info.Name);
  if (!Info.Argument.empty())
    Elem.set(KeyKeyword, Info.Argument);
  if (!Info.SubModuleName.empty())
    Elem.set(KeyModuleName, Info.SubModuleName);
  if (!Info.USR.empty())
    Elem.set(KeyUSR, Info.USR);
  if (!Info.OriginalUSR.empty())
    Elem.set(KeyOriginalUSR, Info.OriginalUSR);
  if (!Info.ProvideImplementationOfUSR.empty())
    Elem.set(KeyDefaultImplementationOf, Info.ProvideImplementationOfUSR);
  if (Info.Length > 0) {
    Elem.set(KeyOffset, Info.Offset);
    Elem.set(KeyLength, Info.Length);
  }
  if (Info.IsUnavailable)
    Elem.set(KeyIsUnavailable, Info.IsUnavailable);
  if (Info.IsDeprecated)
    Elem.set(KeyIsDeprecated, Info.IsDeprecated);
  if (Info.IsOptional)
    Elem.set(KeyIsOptional, Info.IsOptional);
  if (!Info.DocComment.empty())
    Elem.set(KeyDocFullAsXML, Info.DocComment);
  if (!Info.FullyAnnotatedDecl.empty())
    Elem.set(KeyFullyAnnotatedDecl, Info.FullyAnnotatedDecl);
  if (!Info.FullyAnnotatedGenericSig.empty())
    Elem.set(KeyFullyAnnotatedGenericSignature, Info.FullyAnnotatedGenericSig);
  if (!Info.LocalizationKey.empty())
    Elem.set(KeyLocalizationKey, Info.LocalizationKey);

  if (!Info.GenericParams.empty()) {
    auto GPArray = Elem.setArray(KeyGenericParams);
    for (auto &GP : Info.GenericParams) {
      auto GPElem = GPArray.appendDictionary();
      GPElem.set(KeyName, GP.Name);
      if (!GP.Inherits.empty())
        GPElem.set(KeyInherits, GP.Inherits);
    }
  }
  // Note that due to protocol extensions, GenericRequirements may be non-empty
  // while GenericParams is empty.
  if (!Info.GenericRequirements.empty()) {
    auto ReqArray = Elem.setArray(KeyGenericRequirements);

    for (auto &Req : Info.GenericRequirements) {
      auto ReqElem = ReqArray.appendDictionary();
      ReqElem.set(KeyDescription, Req);
    }
  }

  if (!Info.RequiredBystanders.empty())
    Elem.set(KeyRequiredBystanders, Info.RequiredBystanders);
}

void SKDocConsumer::failed(StringRef ErrDescription) {
  ErrorDescription = ErrDescription.str();
}

bool SKDocConsumer::handleSourceText(StringRef Text) {
  TopDict.set(KeySourceText, Text);
  return true;
}

bool SKDocConsumer::handleAnnotation(const DocEntityInfo &Info) {
  AnnotationsBuilder.add(Info);
  return true;
}

bool SKDocConsumer::startSourceEntity(const DocEntityInfo &Info) {
  Entity &Parent = EntitiesStack.back();
  ResponseBuilder::Array &Arr = Parent.Entities;
  if (Arr.isNull())
    Arr = Parent.Data.setArray(KeyEntities);

  auto Elem = Arr.appendDictionary();
  addDocEntityInfoToDict(Info, Elem);

  EntitiesStack.push_back({ Info.Kind, Elem, ResponseBuilder::Array(),
                            ResponseBuilder::Array(),
                            ResponseBuilder::Array(),
                            ResponseBuilder::Array()});
  return true;
}

bool SKDocConsumer::handleInheritsEntity(const DocEntityInfo &Info) {
  assert(EntitiesStack.size() > 1 && "Related entity at top-level ?");
  Entity &Parent = EntitiesStack.back();
  ResponseBuilder::Array &Arr = Parent.Inherits;
  if (Arr.isNull())
    Arr = Parent.Data.setArray(KeyInherits);

  addDocEntityInfoToDict(Info, Arr.appendDictionary());
  return true;
}

bool SKDocConsumer::handleConformsToEntity(const DocEntityInfo &Info) {
  assert(EntitiesStack.size() > 1 && "Related entity at top-level ?");
  Entity &Parent = EntitiesStack.back();
  ResponseBuilder::Array &Arr = Parent.Conforms;
  if (Arr.isNull())
    Arr = Parent.Data.setArray(KeyConforms);

  addDocEntityInfoToDict(Info, Arr.appendDictionary());
  return true;
}

bool SKDocConsumer::handleExtendsEntity(const DocEntityInfo &Info) {
  assert(EntitiesStack.size() > 1 && "Related entity at top-level ?");
  Entity &Parent = EntitiesStack.back();
  addDocEntityInfoToDict(Info, Parent.Data.setDictionary(KeyExtends));
  return true;
}

bool SKDocConsumer::handleAvailableAttribute(const AvailableAttrInfo &Info) {
  Entity &Parent = EntitiesStack.back();
  ResponseBuilder::Array &Arr = Parent.Attrs;
  if (Arr.isNull())
    Arr = Parent.Data.setArray(KeyAttributes);

  auto Elem = Arr.appendDictionary();
  Elem.set(KeyKind, Info.AttrKind);
  if (Info.IsUnavailable)
    Elem.set(KeyIsUnavailable, Info.IsUnavailable);
  if (Info.IsDeprecated)
    Elem.set(KeyIsDeprecated, Info.IsDeprecated);
  if (Info.Platform.isValid())
    Elem.set(KeyPlatform, Info.Platform);
  if (!Info.Message.empty())
    Elem.set(KeyMessage, Info.Message);
  if (Info.Introduced.hasValue())
    Elem.set(KeyIntroduced, Info.Introduced.getValue().getAsString());
  if (Info.Deprecated.hasValue())
    Elem.set(KeyDeprecated, Info.Deprecated.getValue().getAsString());
  if (Info.Obsoleted.hasValue())
    Elem.set(KeyObsoleted, Info.Obsoleted.getValue().getAsString());

  return true;
}

bool SKDocConsumer::finishSourceEntity(UIdent Kind) {
  Entity &CurrEnt = EntitiesStack.back();
  assert(CurrEnt.Kind == Kind);
  (void) CurrEnt;
  EntitiesStack.pop_back();
  return true;
}

bool SKDocConsumer::handleDiagnostic(const DiagnosticEntryInfo &Info) {
  ResponseBuilder::Array &Arr = Diags;
  if (Arr.isNull())
    Arr = TopDict.setArray(KeyDiagnostics);

  auto Elem = Arr.appendDictionary();
  fillDictionaryForDiagnosticInfo(Elem, Info);
  return true;
}

//===----------------------------------------------------------------------===//
// ReportCursorInfo
//===----------------------------------------------------------------------===//

static void reportCursorInfo(const RequestResult<CursorInfoData> &Result,
                             ResponseReceiver Rec) {
  if (Result.isCancelled())
    return Rec(createErrorRequestCancelled());
  if (Result.isError())
    return Rec(createErrorRequestFailed(Result.getError()));

  const CursorInfoData &Info = Result.value();

  ResponseBuilder RespBuilder;
  if (!Info.InternalDiagnostic.empty()) {
    auto Elem = RespBuilder.getDictionary();
    Elem.set(KeyInternalDiagnostic, Info.InternalDiagnostic);
    return Rec(RespBuilder.createResponse());
  }
  if (Info.Kind.isInvalid())
    return Rec(RespBuilder.createResponse());

  auto Elem = RespBuilder.getDictionary();
  Elem.set(KeyKind, Info.Kind);
  Elem.set(KeyName, Info.Name);
  if (!Info.USR.empty())
    Elem.set(KeyUSR, Info.USR);
  if (!Info.TypeName.empty())
    Elem.set(KeyTypeName, Info.TypeName);
  if (!Info.DocComment.empty())
    Elem.set(KeyDocFullAsXML, Info.DocComment);
  if (!Info.AnnotatedDeclaration.empty())
    Elem.set(KeyAnnotatedDecl, Info.AnnotatedDeclaration);
  if (!Info.FullyAnnotatedDeclaration.empty())
    Elem.set(KeyFullyAnnotatedDecl, Info.FullyAnnotatedDeclaration);
  if (!Info.ModuleName.empty())
    Elem.set(KeyModuleName, Info.ModuleName);
  if (!Info.GroupName.empty())
    Elem.set(KeyGroupName, Info.GroupName);
  if (!Info.LocalizationKey.empty())
    Elem.set(KeyLocalizationKey, Info.LocalizationKey);
  if (!Info.ModuleInterfaceName.empty())
    Elem.set(KeyModuleInterfaceName, Info.ModuleInterfaceName);
  if (Info.DeclarationLoc.hasValue()) {
    Elem.set(KeyOffset, Info.DeclarationLoc.getValue().first);
    Elem.set(KeyLength, Info.DeclarationLoc.getValue().second);
    if (!Info.Filename.empty())
      Elem.set(KeyFilePath, Info.Filename);
  }
  if (!Info.OverrideUSRs.empty()) {
    auto Overrides = Elem.setArray(KeyOverrides);
    for (auto USR : Info.OverrideUSRs) {
      auto Override = Overrides.appendDictionary();
      Override.set(KeyUSR, USR);
    }
  }
  if (!Info.ModuleGroupArray.empty()) {
    auto Groups = Elem.setArray(KeyModuleGroups);
    for (auto Name : Info.ModuleGroupArray) {
      auto Entry = Groups.appendDictionary();
      Entry.set(KeyGroupName, Name);
    }
  }
  if (!Info.AvailableActions.empty()) {
    auto Actions = Elem.setArray(KeyRefactorActions);
    for (auto Info : Info.AvailableActions) {
      auto Entry = Actions.appendDictionary();
      Entry.set(KeyActionUID, Info.Kind);
      Entry.set(KeyActionName, Info.KindName);
      if (!Info.UnavailableReason.empty())
        Entry.set(KeyActionUnavailableReason, Info.UnavailableReason);
    }
  }
  if (Info.ParentNameOffset) {
    Elem.set(KeyParentLoc, Info.ParentNameOffset.getValue());
  }
  if (!Info.AnnotatedRelatedDeclarations.empty()) {
    auto RelDecls = Elem.setArray(KeyRelatedDecls);
    for (auto AnnotDecl : Info.AnnotatedRelatedDeclarations) {
      auto RelDecl = RelDecls.appendDictionary();
      RelDecl.set(KeyAnnotatedDecl, AnnotDecl);
    }
  }
  if (Info.IsSystem)
    Elem.setBool(KeyIsSystem, true);
  if (!Info.TypeInterface.empty())
    Elem.set(KeyTypeInterface, Info.TypeInterface);
  if (!Info.TypeUSR.empty())
    Elem.set(KeyTypeUsr, Info.TypeUSR);
  if (!Info.ContainerTypeUSR.empty())
    Elem.set(KeyContainerTypeUsr, Info.ContainerTypeUSR);
  if (!Info.SymbolGraph.empty())
    Elem.set(KeySymbolGraph, Info.SymbolGraph);

  return Rec(RespBuilder.createResponse());
}

//===----------------------------------------------------------------------===//
// ReportRangeInfo
//===----------------------------------------------------------------------===//

static void reportRangeInfo(const RequestResult<RangeInfo> &Result,
                            ResponseReceiver Rec) {
  if (Result.isCancelled())
    return Rec(createErrorRequestCancelled());
  if (Result.isError())
    return Rec(createErrorRequestFailed(Result.getError()));

  const RangeInfo &Info = Result.value();

  ResponseBuilder RespBuilder;
  auto Elem = RespBuilder.getDictionary();
  Elem.set(KeyKind, Info.RangeKind);
  Elem.set(KeyTypeName, Info.ExprType);
  Elem.set(KeyRangeContent, Info.RangeContent);
  Rec(RespBuilder.createResponse());
}

//===----------------------------------------------------------------------===//
// ReportNameInfo
//===----------------------------------------------------------------------===//

static void reportNameInfo(const RequestResult<NameTranslatingInfo> &Result,
                           ResponseReceiver Rec) {
  if (Result.isCancelled())
    return Rec(createErrorRequestCancelled());
  if (Result.isError())
    return Rec(createErrorRequestFailed(Result.getError()));

  const NameTranslatingInfo &Info = Result.value();

  ResponseBuilder RespBuilder;
  if (!Info.InternalDiagnostic.empty()) {
    auto Elem = RespBuilder.getDictionary();
    Elem.set(KeyInternalDiagnostic, Info.InternalDiagnostic);
    return Rec(RespBuilder.createResponse());
  }
  if (Info.NameKind.isInvalid())
    return Rec(RespBuilder.createResponse());
  if (Info.BaseName.empty() && Info.ArgNames.empty())
    return Rec(RespBuilder.createResponse());

  auto Elem = RespBuilder.getDictionary();
  Elem.set(KeyNameKind, Info.NameKind);

  if (!Info.BaseName.empty()) {
    Elem.set(KeyBaseName, Info.BaseName);
  }
  if (!Info.ArgNames.empty()) {
    static UIdent UIDKindNameSwift(KindNameSwift.str());
    auto Arr = Elem.setArray(Info.NameKind == UIDKindNameSwift ?
                             KeyArgNames : KeySelectorPieces);
    for (auto N : Info.ArgNames) {
      auto NameEle = Arr.appendDictionary();
      NameEle.set(KeyName, N);
    }
  }
  if (Info.IsZeroArgSelector) {
    Elem.set(KeyIsZeroArgSelector, Info.IsZeroArgSelector);
  }
  Rec(RespBuilder.createResponse());
}

//===----------------------------------------------------------------------===//
// ReportExpressionTypeInfo
//===----------------------------------------------------------------------===//
static void reportExpressionTypeInfo(const RequestResult<ExpressionTypesInFile> &Result,
                                     ResponseReceiver Rec) {
  if (Result.isCancelled())
    return Rec(createErrorRequestCancelled());
  if (Result.isError())
    return Rec(createErrorRequestFailed(Result.getError()));

  const ExpressionTypesInFile &Info = Result.value();

  ResponseBuilder Builder;
  auto Dict = Builder.getDictionary();
  ExpressionTypeArrayBuilder ArrBuilder(Info.TypeBuffer);
  for (auto &R: Info.Results) {
    ArrBuilder.add(R);
  }
  Dict.setCustomBuffer(KeyExpressionTypeList, ArrBuilder.createBuffer());
  Rec(Builder.createResponse());
}

//===----------------------------------------------------------------------===//
// FindRelatedIdents
//===----------------------------------------------------------------------===//

static void findRelatedIdents(StringRef Filename,
                              int64_t Offset,
                              bool CancelOnSubsequentRequest,
                              ArrayRef<const char *> Args,
                              ResponseReceiver Rec) {
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.findRelatedIdentifiersInFile(Filename, Offset, CancelOnSubsequentRequest,
                                    Args,
                                    [Rec](const RequestResult<RelatedIdentsInfo> &Result) {
  if (Result.isCancelled())
    return Rec(createErrorRequestCancelled());
  if (Result.isError())
    return Rec(createErrorRequestFailed(Result.getError()));

  const RelatedIdentsInfo &Info = Result.value();

    ResponseBuilder RespBuilder;
    auto Arr = RespBuilder.getDictionary().setArray(KeyResults);
    for (auto R : Info.Ranges) {
      auto Elem = Arr.appendDictionary();
      Elem.set(KeyOffset, R.first);
      Elem.set(KeyLength, R.second);
    }

    Rec(RespBuilder.createResponse());
  });
}

//===----------------------------------------------------------------------===//
// CodeComplete
//===----------------------------------------------------------------------===//

namespace {
class SKCodeCompletionConsumer : public CodeCompletionConsumer {
  ResponseBuilder &RespBuilder;
  CodeCompletionResultsArrayBuilder ResultsBuilder;

  std::string ErrorDescription;

public:
  explicit SKCodeCompletionConsumer(ResponseBuilder &RespBuilder)
    : RespBuilder(RespBuilder) {
  }

  sourcekitd_response_t createResponse() {
    if (!ErrorDescription.empty())
      return createErrorRequestFailed(ErrorDescription.c_str());

    RespBuilder.getDictionary().setCustomBuffer(KeyResults,
                                                ResultsBuilder.createBuffer());
    return RespBuilder.createResponse();
  }


  void failed(StringRef ErrDescription) override;

  void setCompletionKind(UIdent kind) override;
  void setReusingASTContext(bool flag) override;
  void setAnnotatedTypename(bool flag) override;
  bool handleResult(const CodeCompletionInfo &Info) override;
};
} // end anonymous namespace

static sourcekitd_response_t
codeComplete(llvm::MemoryBuffer *InputBuf, int64_t Offset,
             Optional<RequestDict> optionsDict,
             ArrayRef<const char *> Args,
             Optional<VFSOptions> vfsOptions) {
  ResponseBuilder RespBuilder;
  SKCodeCompletionConsumer CCC(RespBuilder);

  std::unique_ptr<SKOptionsDictionary> options;
  if (optionsDict)
    options = std::make_unique<SKOptionsDictionary>(*optionsDict);

  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.codeComplete(InputBuf, Offset, options.get(), CCC, Args,
                    std::move(vfsOptions));
  return CCC.createResponse();
}

void SKCodeCompletionConsumer::failed(StringRef ErrDescription) {
  ErrorDescription = ErrDescription.str();
}

void SKCodeCompletionConsumer::setCompletionKind(UIdent kind) {
  assert(kind.isValid());
  RespBuilder.getDictionary().set(KeyKind, kind);
}

void SKCodeCompletionConsumer::setReusingASTContext(bool flag) {
  if (flag)
    RespBuilder.getDictionary().setBool(KeyReusingASTContext, flag);
}

void SKCodeCompletionConsumer::setAnnotatedTypename(bool flag) {
  if (flag)
    RespBuilder.getDictionary().setBool(KeyAnnotatedTypename, flag);
}

bool SKCodeCompletionConsumer::handleResult(const CodeCompletionInfo &R) {
  Optional<StringRef> ModuleNameOpt;
  if (!R.ModuleName.empty())
    ModuleNameOpt = R.ModuleName;
  Optional<StringRef> DocBriefOpt;
  if (!R.DocBrief.empty())
    DocBriefOpt = R.DocBrief;
  Optional<StringRef> AssocUSRsOpt;
  if (!R.AssocUSRs.empty())
    AssocUSRsOpt = R.AssocUSRs;

  assert(!R.ModuleImportDepth && "not implemented on CompactArray path");

  ResultsBuilder.add(R.Kind,
                     R.Name,
                     R.Description,
                     R.SourceText,
                     R.TypeName,
                     ModuleNameOpt,
                     DocBriefOpt,
                     AssocUSRsOpt,
                     R.SemanticContext,
                     R.TypeRelation,
                     R.NotRecommended,
                     R.IsSystem,
                     R.NumBytesToErase);
  return true;
}


//===----------------------------------------------------------------------===//
// (New) CodeComplete
//===----------------------------------------------------------------------===//

namespace {
class SKGroupedCodeCompletionConsumer : public GroupedCodeCompletionConsumer {
  ResponseBuilder &RespBuilder;
  ResponseBuilder::Dictionary Response;
  SmallVector<ResponseBuilder::Array, 3> GroupContentsStack;
  std::string ErrorDescription;

public:
  explicit SKGroupedCodeCompletionConsumer(ResponseBuilder &RespBuilder)
      : RespBuilder(RespBuilder) {}

  sourcekitd_response_t createResponse() {
    if (!ErrorDescription.empty())
      return createErrorRequestFailed(ErrorDescription.c_str());
    assert(GroupContentsStack.empty() && "mismatched start/endGroup");
    return RespBuilder.createResponse();
  }

  void failed(StringRef ErrDescription) override;
  bool handleResult(const CodeCompletionInfo &Info) override;
  void startGroup(UIdent kind, StringRef name) override;
  void endGroup() override;
  void setNextRequestStart(unsigned offset) override;
  void setReusingASTContext(bool flag) override;
  void setAnnotatedTypename(bool flag) override;
};
} // end anonymous namespace

static sourcekitd_response_t codeCompleteOpen(StringRef Name,
                                              llvm::MemoryBuffer *InputBuf,
                                              int64_t Offset,
                                              Optional<RequestDict> optionsDict,
                                              ArrayRef<const char *> Args,
                                              Optional<VFSOptions> vfsOptions) {
  ResponseBuilder RespBuilder;
  SKGroupedCodeCompletionConsumer CCC(RespBuilder);
  std::unique_ptr<SKOptionsDictionary> options;
  std::vector<FilterRule> filterRules;
  if (optionsDict) {
    options = std::make_unique<SKOptionsDictionary>(*optionsDict);
    bool failed = false;
    optionsDict->dictionaryArrayApply(KeyFilterRules, [&](RequestDict dict) {
      FilterRule rule;
      auto kind = dict.getUID(KeyKind);
      if (kind == KindCodeCompletionEverything) {
        rule.kind = FilterRule::Everything;
      } else if (kind == KindCodeCompletionModule) {
        rule.kind = FilterRule::Module;
      } else if (kind == KindCodeCompletionKeyword) {
        rule.kind = FilterRule::Keyword;
      } else if (kind == KindCodeCompletionLiteral) {
        rule.kind = FilterRule::Literal;
      } else if (kind == KindCodeCompletionCustom) {
        rule.kind = FilterRule::CustomCompletion;
      } else if (kind == KindCodeCompletionIdentifier) {
        rule.kind = FilterRule::Identifier;
      } else if (kind == KindCodeCompletionDescription) {
        rule.kind = FilterRule::Description;
      } else {
        // Warning: unknown
      }

      int64_t hide;
      if (dict.getInt64(KeyHide, hide, false)) {
        failed = true;
        CCC.failed("filter rule missing required key 'key.hide'");
        return true;
      }

      rule.hide = hide;

      switch (rule.kind) {
      case FilterRule::Everything:
        break;
      case FilterRule::Module:
      case FilterRule::Identifier: {
        SmallVector<const char *, 8> names;
        if (dict.getStringArray(KeyNames, names, false)) {
          failed = true;
          CCC.failed("filter rule missing required key 'key.names'");
          return true;
        }
        rule.names.assign(names.begin(), names.end());
        break;
      }
      case FilterRule::Description: {
        SmallVector<const char *, 8> names;
        if (dict.getStringArray(KeyNames, names, false)) {
          failed = true;
          CCC.failed("filter rule missing required key 'key.names'");
          return true;
        }
        rule.names.assign(names.begin(), names.end());
        break;
      }
      case FilterRule::Keyword:
      case FilterRule::Literal:
      case FilterRule::CustomCompletion: {
        SmallVector<sourcekitd_uid_t, 8> uids;
        dict.getUIDArray(KeyUIDs, uids, true);
        for (auto uid : uids)
          rule.uids.push_back(UIdentFromSKDUID(uid));
        break;
      }
      }

      filterRules.push_back(std::move(rule));
      return false; // continue
    });

    if (failed)
      return CCC.createResponse();
  }
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.codeCompleteOpen(Name, InputBuf, Offset, options.get(), filterRules, CCC,
                        Args, std::move(vfsOptions));
  return CCC.createResponse();
}

static sourcekitd_response_t codeCompleteClose(StringRef Name, int64_t Offset) {
  ResponseBuilder RespBuilder;
  SKGroupedCodeCompletionConsumer CCC(RespBuilder);
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.codeCompleteClose(Name, Offset, CCC);
  return CCC.createResponse();
}

static sourcekitd_response_t
codeCompleteUpdate(StringRef name, int64_t offset,
                   Optional<RequestDict> optionsDict) {
  ResponseBuilder RespBuilder;
  SKGroupedCodeCompletionConsumer CCC(RespBuilder);
  std::unique_ptr<SKOptionsDictionary> options;
  if (optionsDict)
    options = std::make_unique<SKOptionsDictionary>(*optionsDict);
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.codeCompleteUpdate(name, offset, options.get(), CCC);
  return CCC.createResponse();
}

void SKGroupedCodeCompletionConsumer::failed(StringRef ErrDescription) {
  ErrorDescription = ErrDescription.str();
}

bool SKGroupedCodeCompletionConsumer::handleResult(const CodeCompletionInfo &R) {
  assert(!GroupContentsStack.empty() && "missing root group");

  auto result = GroupContentsStack.back().appendDictionary();
  if (R.CustomKind)
    result.set(KeyKind, sourcekitd_uid_t(R.CustomKind));
  else
    result.set(KeyKind, R.Kind);
  result.set(KeyName, R.Name);
  result.set(KeyDescription, R.Description);
  result.set(KeySourceText, R.SourceText);
  result.set(KeyTypeName, R.TypeName);
  result.set(KeyContext, R.SemanticContext);
  if (!R.ModuleName.empty())
    result.set(KeyModuleName, R.ModuleName);
  if (!R.DocBrief.empty())
    result.set(KeyDocBrief, R.DocBrief);
  if (!R.AssocUSRs.empty())
    result.set(KeyAssociatedUSRs, R.AssocUSRs);
  if (R.ModuleImportDepth)
    result.set(KeyModuleImportDepth, *R.ModuleImportDepth);
  if (R.NotRecommended)
    result.set(KeyNotRecommended, R.NotRecommended);
  if (R.IsSystem)
    result.set(KeyIsSystem, R.IsSystem);
  result.set(KeyNumBytesToErase, R.NumBytesToErase);

  if (R.descriptionStructure) {
    auto addRange = [](ResponseBuilder::Dictionary dict, UIdent offset,
                       UIdent length, CodeCompletionInfo::IndexRange range) {
      if (!range.empty()) {
        dict.set(offset, range.begin);
        dict.set(length, range.length());
      }
    };

    auto structure = result.setDictionary(KeySubStructure);
    addRange(structure, KeyNameOffset, KeyNameLength,
             R.descriptionStructure->baseName);
    addRange(structure, KeyBodyOffset, KeyBodyLength,
             R.descriptionStructure->parameterRange);
    addRange(structure, KeyThrowOffset, KeyThrowLength,
             R.descriptionStructure->throwsRange);

    if (R.parametersStructure) {
      auto params = structure.setArray(KeySubStructure);
      for (auto &P : *R.parametersStructure) {
        auto param = params.appendDictionary();
        addRange(param, KeyNameOffset, KeyNameLength, P.name);
        addRange(param, KeyBodyOffset, KeyBodyLength, P.afterColon);
        if (P.isLocalName)
          param.set(KeyIsLocal, true);
      }
    }
  }

  return true;
}

void SKGroupedCodeCompletionConsumer::startGroup(UIdent kind, StringRef name) {
  ResponseBuilder::Dictionary group;
  if (GroupContentsStack.empty()) {
    group = RespBuilder.getDictionary();
    Response = group;
  } else {
    group = GroupContentsStack.back().appendDictionary();
  }
  group.set(KeyKind, kind);
  group.set(KeyName, name);
  auto contents = group.setArray(KeyResults);
  GroupContentsStack.push_back(contents);
}
void SKGroupedCodeCompletionConsumer::endGroup() {
  assert(!GroupContentsStack.empty());
  GroupContentsStack.pop_back();
}
void SKGroupedCodeCompletionConsumer::setNextRequestStart(unsigned offset) {
  assert(!Response.isNull());
  Response.set(KeyNextRequestStart, offset);
}
void SKGroupedCodeCompletionConsumer::setReusingASTContext(bool flag) {
  if (flag)
    RespBuilder.getDictionary().setBool(KeyReusingASTContext, flag);
}
void SKGroupedCodeCompletionConsumer::setAnnotatedTypename(bool flag) {
  if (flag)
    RespBuilder.getDictionary().setBool(KeyAnnotatedTypename, flag);
}

//===----------------------------------------------------------------------===//
// Type Context Info
//===----------------------------------------------------------------------===//

static sourcekitd_response_t typeContextInfo(llvm::MemoryBuffer *InputBuf,
                                             int64_t Offset,
                                             Optional<RequestDict> optionsDict,
                                             ArrayRef<const char *> Args,
                                             Optional<VFSOptions> vfsOptions) {
  ResponseBuilder RespBuilder;

  class Consumer : public TypeContextInfoConsumer {
    ResponseBuilder RespBuilder;
    ResponseBuilder::Array SKResults;
    Optional<std::string> ErrorDescription;

  public:
    Consumer(ResponseBuilder Builder)
        : RespBuilder(Builder),
          SKResults(Builder.getDictionary().setArray(KeyResults)) {}

    void handleResult(const TypeContextInfoItem &Item) override {
      auto SKElem = SKResults.appendDictionary();
      SKElem.set(KeyTypeName, Item.TypeName);
      SKElem.set(KeyTypeUsr, Item.TypeUSR);
      auto members = SKElem.setArray(KeyImplicitMembers);
      for (auto member : Item.ImplicitMembers) {
        auto memberElem = members.appendDictionary();
        memberElem.set(KeyName, member.Name);
        memberElem.set(KeyDescription, member.Description);
        memberElem.set(KeySourceText, member.SourceText);
        if (!member.DocBrief.empty())
          memberElem.set(KeyDocBrief, member.DocBrief);
      }
    }

    void setReusingASTContext(bool flag) override {
      if (flag)
        RespBuilder.getDictionary().setBool(KeyReusingASTContext, flag);
    }

    void failed(StringRef ErrDescription) override {
      ErrorDescription = ErrDescription.str();
    }

    bool isError() const { return ErrorDescription.hasValue(); }
    const char *getErrorDescription() const {
      return ErrorDescription->c_str();
    }
  } Consumer(RespBuilder);

  std::unique_ptr<SKOptionsDictionary> options;
  if (optionsDict)
    options = std::make_unique<SKOptionsDictionary>(*optionsDict);

  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.getExpressionContextInfo(InputBuf, Offset, options.get(), Args, Consumer,
                                std::move(vfsOptions));

  if (Consumer.isError())
    return createErrorRequestFailed(Consumer.getErrorDescription());
  return RespBuilder.createResponse();
}

//===----------------------------------------------------------------------===//
// Conforming Method List
//===----------------------------------------------------------------------===//

static sourcekitd_response_t
conformingMethodList(llvm::MemoryBuffer *InputBuf, int64_t Offset,
                     Optional<RequestDict> optionsDict,
                     ArrayRef<const char *> Args,
                     ArrayRef<const char *> ExpectedTypes,
                     Optional<VFSOptions> vfsOptions) {
  ResponseBuilder RespBuilder;

  class Consumer : public ConformingMethodListConsumer {
    ResponseBuilder::Dictionary SKResult;
    Optional<std::string> ErrorDescription;

  public:
    Consumer(ResponseBuilder Builder) : SKResult(Builder.getDictionary()) {}

    void handleResult(const ConformingMethodListResult &Result) override {
      SKResult.set(KeyTypeName, Result.TypeName);
      SKResult.set(KeyTypeUsr, Result.TypeUSR);
      auto members = SKResult.setArray(KeyMembers);
      for (auto member : Result.Members) {
        auto memberElem = members.appendDictionary();
        memberElem.set(KeyName, member.Name);
        memberElem.set(KeyTypeName, member.TypeName);
        memberElem.set(KeyTypeUsr, member.TypeUSR);
        memberElem.set(KeyDescription, member.Description);
        memberElem.set(KeySourceText, member.SourceText);
        if (!member.DocBrief.empty())
          memberElem.set(KeyDocBrief, member.DocBrief);
      }
    }

    void setReusingASTContext(bool flag) override {
      if (flag)
        SKResult.setBool(KeyReusingASTContext, flag);
    }

    void failed(StringRef ErrDescription) override {
      ErrorDescription = ErrDescription.str();
    }

    bool isError() const { return ErrorDescription.hasValue(); }
    const char *getErrorDescription() const {
      return ErrorDescription->c_str();
    }
  } Consumer(RespBuilder);

  std::unique_ptr<SKOptionsDictionary> options;
  if (optionsDict)
    options = std::make_unique<SKOptionsDictionary>(*optionsDict);

  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.getConformingMethodList(InputBuf, Offset, options.get(), Args,
                               ExpectedTypes, Consumer, std::move(vfsOptions));

  if (Consumer.isError())
    return createErrorRequestFailed(Consumer.getErrorDescription());
  return RespBuilder.createResponse();
}

//===----------------------------------------------------------------------===//
// Editor
//===----------------------------------------------------------------------===//

namespace {
class SKEditorConsumer : public EditorConsumer {
  ResponseReceiver RespReceiver;
  ResponseBuilder RespBuilder;

public:
  ResponseBuilder::Dictionary Dict;
  DocStructureArrayBuilder DocStructure;
  TokenAnnotationsArrayBuilder SyntaxMap;
  TokenAnnotationsArrayBuilder SemanticAnnotations;

  ResponseBuilder::Array Diags;
  sourcekitd_response_t Error = nullptr;

  SKEditorConsumerOptions Opts;

public:
  SKEditorConsumer(SKEditorConsumerOptions Opts) : Opts(Opts) {
    Dict = RespBuilder.getDictionary();
  }

  SKEditorConsumer(ResponseReceiver RespReceiver, SKEditorConsumerOptions Opts)
      : SKEditorConsumer(Opts) {
    this->RespReceiver = RespReceiver;
  }

  sourcekitd_response_t createResponse();

  bool needsSemanticInfo() override {
    return !Opts.SyntacticOnly && !isSemanticEditorDisabled();
  }

  void handleRequestError(const char *Description) override;

  bool syntaxMapEnabled() override { return Opts.EnableSyntaxMap; }

  void handleSyntaxMap(unsigned Offset, unsigned Length, UIdent Kind) override;

  void handleSemanticAnnotation(unsigned Offset, unsigned Length, UIdent Kind,
                                bool isSystem) override;

  bool documentStructureEnabled() override { return Opts.EnableStructure; }

  void beginDocumentSubStructure(unsigned Offset, unsigned Length, UIdent Kind,
                                 UIdent AccessLevel,
                                 UIdent SetterAccessLevel,
                                 unsigned NameOffset,
                                 unsigned NameLength,
                                 unsigned BodyOffset,
                                 unsigned BodyLength,
                                 unsigned DocOffset,
                                 unsigned DocLength,
                                 StringRef DisplayName,
                                 StringRef TypeName,
                                 StringRef RuntimeName,
                                 StringRef SelectorName,
                                 ArrayRef<StringRef> InheritedTypes,
                                 ArrayRef<std::tuple<UIdent, unsigned, unsigned>> Attrs) override;

  void endDocumentSubStructure() override;

  void handleDocumentSubStructureElement(UIdent Kind, unsigned Offset,
                                         unsigned Length) override;

  void recordAffectedRange(unsigned Offset, unsigned Length) override;

  void recordAffectedLineRange(unsigned Line, unsigned Length) override;

  void recordFormattedText(StringRef Text) override;

  void setDiagnosticStage(UIdent DiagStage) override;
  void handleDiagnostic(const DiagnosticEntryInfo &Info,
                        UIdent DiagStage) override;

  void handleSourceText(StringRef Text) override;

  void handleSyntaxTree(const swift::syntax::SourceFileSyntax &SyntaxTree,
                        std::unordered_set<unsigned> &ReusedNodeIds) override;

  SyntaxTreeTransferMode syntaxTreeTransferMode() override {
    return Opts.SyntaxTransferMode;
  }

  void finished() override {
    if (RespReceiver)
      RespReceiver(createResponse());
  }
};

} // end anonymous namespace

static sourcekitd_response_t
editorOpen(StringRef Name, llvm::MemoryBuffer *Buf,
           SKEditorConsumerOptions Opts, ArrayRef<const char *> Args,
           Optional<VFSOptions> vfsOptions) {
  SKEditorConsumer EditC(Opts);
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.editorOpen(Name, Buf, EditC, Args, std::move(vfsOptions));
  return EditC.createResponse();
}

static sourcekitd_response_t
editorOpenInterface(StringRef Name, StringRef ModuleName,
                    Optional<StringRef> Group, ArrayRef<const char *> Args,
                    bool SynthesizedExtensions,
                    Optional<StringRef> InterestedUSR) {
  SKEditorConsumerOptions Opts;
  Opts.EnableSyntaxMap = true;
  Opts.EnableStructure = true;
  SKEditorConsumer EditC(Opts);
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.editorOpenInterface(EditC, Name, ModuleName, Group, Args,
                           SynthesizedExtensions, InterestedUSR);
  return EditC.createResponse();
}


/// Getting the interface from a swift source file differs from getting interfaces
/// from headers or modules for its performing asynchronously.
static void
editorOpenSwiftSourceInterface(StringRef Name, StringRef HeaderName,
                               ArrayRef<const char *> Args,
                               ResponseReceiver Rec) {
  SKEditorConsumerOptions Opts;
  Opts.EnableSyntaxMap = true;
  Opts.EnableStructure = true;
  auto EditC = std::make_shared<SKEditorConsumer>(Rec, Opts);
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.editorOpenSwiftSourceInterface(Name, HeaderName, Args, EditC);
}

static void
editorOpenSwiftTypeInterface(StringRef TypeUsr, ArrayRef<const char *> Args,
                             ResponseReceiver Rec) {
  SKEditorConsumerOptions Opts;
  Opts.EnableSyntaxMap = true;
  Opts.EnableStructure = true;
  auto EditC = std::make_shared<SKEditorConsumer>(Rec, Opts);
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.editorOpenTypeInterface(*EditC, Args, TypeUsr);
}

static sourcekitd_response_t editorExtractTextFromComment(StringRef Source) {
  SKEditorConsumerOptions Opts;
  Opts.SyntacticOnly = true;
  SKEditorConsumer EditC(Opts);
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.editorExtractTextFromComment(Source, EditC);
  return EditC.createResponse();
}

static sourcekitd_response_t editorConvertMarkupToXML(StringRef Source) {
  SKEditorConsumerOptions Opts;
  Opts.SyntacticOnly = true;
  SKEditorConsumer EditC(Opts);
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.editorConvertMarkupToXML(Source, EditC);
  return EditC.createResponse();
}

static sourcekitd_response_t
editorOpenHeaderInterface(StringRef Name, StringRef HeaderName,
                          ArrayRef<const char *> Args,
                          bool UsingSwiftArgs,
                          bool SynthesizedExtensions,
                          StringRef swiftVersion) {
  SKEditorConsumerOptions Opts;
  Opts.EnableSyntaxMap = true;
  Opts.EnableStructure = true;
  SKEditorConsumer EditC(Opts);
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.editorOpenHeaderInterface(EditC, Name, HeaderName, Args, UsingSwiftArgs,
                                 SynthesizedExtensions, swiftVersion);
  return EditC.createResponse();
}

static sourcekitd_response_t
editorClose(StringRef Name, bool RemoveCache) {
  ResponseBuilder RespBuilder;
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.editorClose(Name, RemoveCache);
  return RespBuilder.createResponse();
}

static sourcekitd_response_t
editorReplaceText(StringRef Name, llvm::MemoryBuffer *Buf, unsigned Offset,
                  unsigned Length, SKEditorConsumerOptions Opts) {
  SKEditorConsumer EditC(Opts);
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.editorReplaceText(Name, Buf, Offset, Length, EditC);
  return EditC.createResponse();
}

static void
editorApplyFormatOptions(StringRef Name, RequestDict &FmtOptions) {
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  SKOptionsDictionary SKFmtOptions(FmtOptions);
  Lang.editorApplyFormatOptions(Name, SKFmtOptions);
}

static sourcekitd_response_t
editorFormatText(StringRef Name, unsigned Line, unsigned Length) {
  SKEditorConsumerOptions Opts;
  Opts.SyntacticOnly = true;
  SKEditorConsumer EditC(Opts);
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.editorFormatText(Name, Line, Length, EditC);
  return EditC.createResponse();
}

static sourcekitd_response_t
editorExpandPlaceholder(StringRef Name, unsigned Offset, unsigned Length) {
  SKEditorConsumerOptions Opts;
  Opts.SyntacticOnly = true;
  SKEditorConsumer EditC(Opts);
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.editorExpandPlaceholder(Name, Offset, Length, EditC);
  return EditC.createResponse();
}

sourcekitd_response_t SKEditorConsumer::createResponse() {
  if (Error)
    return Error;

  if (Opts.EnableSyntaxMap) {
    Dict.setCustomBuffer(KeySyntaxMap, SyntaxMap.createBuffer());
  }
  if (!SemanticAnnotations.empty()) {
    Dict.setCustomBuffer(KeyAnnotations, SemanticAnnotations.createBuffer());
  }
  if (Opts.EnableStructure) {
    Dict.setCustomBuffer(KeySubStructure, DocStructure.createBuffer());
  }


  return RespBuilder.createResponse();
}

void SKEditorConsumer::handleRequestError(const char *Description) {
  if (!Error) {
    Error = createErrorRequestFailed(Description);
  }
  if (RespReceiver) {
    RespReceiver(Error);
    RespReceiver = ResponseReceiver();
  }
}

void SKEditorConsumer::handleSyntaxMap(unsigned Offset, unsigned Length,
                                       UIdent Kind) {
  if (!Opts.EnableSyntaxMap)
    return;

  SyntaxMap.add(Kind, Offset, Length, /*IsSystem=*/false);
}

void SKEditorConsumer::handleSemanticAnnotation(unsigned Offset,
                                                unsigned Length, UIdent Kind,
                                                bool isSystem) {
  assert(Kind.isValid());
  SemanticAnnotations.add(Kind, Offset, Length, isSystem);
}

void
SKEditorConsumer::beginDocumentSubStructure(unsigned Offset,
                                            unsigned Length, UIdent Kind,
                                            UIdent AccessLevel,
                                            UIdent SetterAccessLevel,
                                            unsigned NameOffset,
                                            unsigned NameLength,
                                            unsigned BodyOffset,
                                            unsigned BodyLength,
                                            unsigned DocOffset,
                                            unsigned DocLength,
                                            StringRef DisplayName,
                                            StringRef TypeName,
                                            StringRef RuntimeName,
                                            StringRef SelectorName,
                                            ArrayRef<StringRef> InheritedTypes,
                                            ArrayRef<std::tuple<UIdent, unsigned, unsigned>> Attrs) {
  if (Opts.EnableStructure) {
    DocStructure.beginSubStructure(
        Offset, Length, Kind, AccessLevel, SetterAccessLevel, NameOffset,
        NameLength, BodyOffset, BodyLength, DocOffset, DocLength, DisplayName,
        TypeName, RuntimeName, SelectorName, InheritedTypes, Attrs);
  }
}

void SKEditorConsumer::endDocumentSubStructure() {
  if (Opts.EnableStructure)
    DocStructure.endSubStructure();
}

void SKEditorConsumer::handleDocumentSubStructureElement(UIdent Kind,
                                                         unsigned Offset,
                                                         unsigned Length) {
  if (Opts.EnableStructure)
    DocStructure.addElement(Kind, Offset, Length);
}

void SKEditorConsumer::recordAffectedRange(unsigned Offset, unsigned Length) {
  Dict.set(KeyOffset, Offset);
  Dict.set(KeyLength, Length);
}

void SKEditorConsumer::recordAffectedLineRange(unsigned Line, unsigned Length) {
  Dict.set(KeyLine, Line);
  Dict.set(KeyLength, Length);
}

void SKEditorConsumer::recordFormattedText(StringRef Text) {
  Dict.set(KeySourceText, Text);
}

static void fillDictionaryForDiagnosticInfoBase(
    ResponseBuilder::Dictionary Elem, const DiagnosticEntryInfoBase &Info);

static void fillDictionaryForDiagnosticInfo(
    ResponseBuilder::Dictionary Elem, const DiagnosticEntryInfo &Info) {

  UIdent SeverityUID;
  static UIdent UIDKindDiagWarning(KindDiagWarning.str());
  static UIdent UIDKindDiagError(KindDiagError.str());
  switch (Info.Severity) {
  case DiagnosticSeverityKind::Warning:
    SeverityUID = UIDKindDiagWarning;
    break;
  case DiagnosticSeverityKind::Error:
    SeverityUID = UIDKindDiagError;
    break;
  }

  Elem.set(KeySeverity, SeverityUID);
  fillDictionaryForDiagnosticInfoBase(Elem, Info);

  if (!Info.Notes.empty()) {
    auto NotesArr = Elem.setArray(KeyDiagnostics);
    for (auto &NoteDiag : Info.Notes) {
      auto NoteElem = NotesArr.appendDictionary();
      NoteElem.set(KeySeverity, KindDiagNote);
      fillDictionaryForDiagnosticInfoBase(NoteElem, NoteDiag);
    }
  }
}

static void fillDictionaryForDiagnosticInfoBase(
    ResponseBuilder::Dictionary Elem, const DiagnosticEntryInfoBase &Info) {

  Elem.set(KeyDescription, Info.Description);
  if (Info.Line != 0) {
    Elem.set(KeyLine, Info.Line);
    Elem.set(KeyColumn, Info.Column);
  } else {
    Elem.set(KeyOffset, Info.Offset);
  }
  if (!Info.Filename.empty())
    Elem.set(KeyFilePath, Info.Filename);

  if (!Info.EducationalNotePaths.empty())
    Elem.set(KeyEducationalNotePaths, Info.EducationalNotePaths);

  if (!Info.Ranges.empty()) {
    auto RangesArr = Elem.setArray(KeyRanges);
    for (auto R : Info.Ranges) {
      auto RangeElem = RangesArr.appendDictionary();
      RangeElem.set(KeyOffset, R.first);
      RangeElem.set(KeyLength, R.second);
    }
  }

  if (!Info.Fixits.empty()) {
    auto FixitsArr = Elem.setArray(KeyFixits);
    for (auto F : Info.Fixits) {
      auto FixitElem = FixitsArr.appendDictionary();
      FixitElem.set(KeyOffset, F.Offset);
      FixitElem.set(KeyLength, F.Length);
      FixitElem.set(KeySourceText, F.Text);
    }
  }
}

void SKEditorConsumer::setDiagnosticStage(UIdent DiagStage) {
  Dict.set(KeyDiagnosticStage, DiagStage);
}

void SKEditorConsumer::handleDiagnostic(const DiagnosticEntryInfo &Info,
                                        UIdent DiagStage) {
  if (!Opts.EnableDiagnostics)
    return;

  ResponseBuilder::Array &Arr = Diags;
  if (Arr.isNull())
    Arr = Dict.setArray(KeyDiagnostics);

  auto Elem = Arr.appendDictionary();
  Elem.set(KeyDiagnosticStage, DiagStage);
  fillDictionaryForDiagnosticInfo(Elem, Info);
}

void SKEditorConsumer::handleSourceText(StringRef Text) {
  Dict.set(KeySourceText, Text);
}

void serializeSyntaxTreeAsByteTree(
    const swift::syntax::SourceFileSyntax &SyntaxTree,
    std::unordered_set<unsigned> &ReusedNodeIds,
    ResponseBuilder::Dictionary &Dict) {
  auto StartClock = clock();
  // Serialize the syntax tree as a ByteTree
  auto Stream = swift::ExponentialGrowthAppendingBinaryByteStream();
  Stream.reserve(32 * 1024);
  std::map<void *, void *> UserInfo;
  UserInfo[swift::byteTree::UserInfoKeyReusedNodeIds] = &ReusedNodeIds;
  swift::byteTree::ByteTreeWriter::write(Stream,
                                         swift::byteTree::SYNTAX_TREE_VERSION,
                                         *SyntaxTree.getRaw(), UserInfo);

  std::unique_ptr<llvm::WritableMemoryBuffer> Buf =
      llvm::WritableMemoryBuffer::getNewUninitMemBuffer(sizeof(uint64_t) + Stream.data().size());
  *reinterpret_cast<uint64_t*>(Buf->getBufferStart()) =
      (uint64_t)CustomBufferKind::RawData;
  memcpy(Buf->getBufferStart() + sizeof(uint64_t),
         Stream.data().data(), Stream.data().size());

  Dict.setCustomBuffer(KeySerializedSyntaxTree, std::move(Buf));

  auto EndClock = clock();
  LOG_SECTION("incrParse Performance", InfoLowPrio) {
    Log->getOS() << "Serialized " << Stream.data().size()
                 << " bytes as ByteTree in ";
    auto Seconds = (double)(EndClock - StartClock) * 1000 / CLOCKS_PER_SEC;
    llvm::write_double(Log->getOS(), Seconds, llvm::FloatStyle::Fixed, 2);
    Log->getOS() << "ms";
  }
}

void serializeSyntaxTreeAsJson(
    const swift::syntax::SourceFileSyntax &SyntaxTree,
    std::unordered_set<unsigned> ReusedNodeIds,
    ResponseBuilder::Dictionary &Dict) {
  auto StartClock = clock();
  // 4096 is a heuristic buffer size that appears to usually be able to fit an
  // incremental syntax tree
  size_t ReserveBufferSize = 4096;
  std::string SyntaxTreeString;
  SyntaxTreeString.reserve(ReserveBufferSize);
  {
    llvm::raw_string_ostream SyntaxTreeStream(SyntaxTreeString);
    SyntaxTreeStream.SetBufferSize(ReserveBufferSize);
    swift::json::Output::UserInfoMap JsonUserInfo;
    JsonUserInfo[swift::json::OmitNodesUserInfoKey] = &ReusedNodeIds;
    swift::json::Output SyntaxTreeOutput(SyntaxTreeStream, JsonUserInfo,
                                         /*PrettyPrint=*/false);
    SyntaxTreeOutput << *SyntaxTree.getRaw();
  }
  Dict.set(KeySerializedSyntaxTree, SyntaxTreeString);

  auto EndClock = clock();
  LOG_SECTION("incrParse Performance", InfoLowPrio) {
    Log->getOS() << "Serialized " << SyntaxTreeString.size()
                 << " bytes as JSON in ";
    auto Seconds = (double)(EndClock - StartClock) * 1000 / CLOCKS_PER_SEC;
    llvm::write_double(Log->getOS(), Seconds, llvm::FloatStyle::Fixed, 2);
    Log->getOS() << "ms";
  }
}

void SKEditorConsumer::handleSyntaxTree(
    const swift::syntax::SourceFileSyntax &SyntaxTree,
    std::unordered_set<unsigned> &ReusedNodeIds) {

  std::unordered_set<unsigned> OmitNodes;
  switch (Opts.SyntaxTransferMode) {
  case SourceKit::SyntaxTreeTransferMode::Off:
    // Don't serialize the tree at all
    return;
  case SourceKit::SyntaxTreeTransferMode::Full:
    // Serialize the tree without omitting any nodes
    OmitNodes = {};
    break;
  case SourceKit::SyntaxTreeTransferMode::Incremental:
    // Serialize the tree and omit all nodes that have been reused
    OmitNodes = ReusedNodeIds;
    break;
  }

  switch (Opts.SyntaxSerializationFormat) {
  case SourceKit::SyntaxTreeSerializationFormat::JSON:
    serializeSyntaxTreeAsJson(SyntaxTree, OmitNodes, Dict);
    break;
  case SourceKit::SyntaxTreeSerializationFormat::ByteTree:
    serializeSyntaxTreeAsByteTree(SyntaxTree, OmitNodes, Dict);
    break;
  }
}

static sourcekitd_response_t
editorFindUSR(StringRef DocumentName, StringRef USR) {
  ResponseBuilder RespBuilder;
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  llvm::Optional<std::pair<unsigned, unsigned>>
      Range = Lang.findUSRRange(DocumentName, USR);
  if (!Range) {
    // If cannot find the synthesized USR, find the actual USR instead.
    Range = Lang.findUSRRange(DocumentName,
                              USR.split(LangSupport::SynthesizedUSRSeparator).
                                first);
  }
  if (Range.hasValue()) {
    RespBuilder.getDictionary().set(KeyOffset, Range->first);
    RespBuilder.getDictionary().set(KeyLength, Range->second);
  }
  return RespBuilder.createResponse();
}

static sourcekitd_response_t
editorFindInterfaceDoc(StringRef ModuleName, ArrayRef<const char *> Args) {
  ResponseBuilder RespBuilder;
  sourcekitd_response_t Resp;
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.findInterfaceDocument(ModuleName, Args,
    [&](const RequestResult<InterfaceDocInfo> &Result) {
      if (Result.isCancelled()) {
        Resp = createErrorRequestCancelled();
        return;
      }
      if (Result.isError()) {
        Resp = createErrorRequestFailed(Result.getError());
        return;
      }

      const InterfaceDocInfo &Info = Result.value();

      auto Elem = RespBuilder.getDictionary();
      if (!Info.ModuleInterfaceName.empty())
        Elem.set(KeyModuleInterfaceName, Info.ModuleInterfaceName);
      if (!Info.CompilerArgs.empty())
        Elem.set(KeyCompilerArgs, Info.CompilerArgs);
      Resp = RespBuilder.createResponse();
    });

  return Resp;
}

static sourcekitd_response_t
editorFindModuleGroups(StringRef ModuleName, ArrayRef<const char *> Args) {
  ResponseBuilder RespBuilder;
  sourcekitd_response_t Resp;
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  Lang.findModuleGroups(ModuleName, Args,
                        [&](const RequestResult<ArrayRef<StringRef>> &Result) {
    if (Result.isCancelled()) {
      Resp = createErrorRequestCancelled();
      return;
    }
    if (Result.isError()) {
      Resp = createErrorRequestFailed(Result.getError());
      return;
    }

    ArrayRef<StringRef> Groups = Result.value();

    auto Dict = RespBuilder.getDictionary();
    auto Arr = Dict.setArray(KeyModuleGroups);
    for (auto G : Groups) {
      auto Entry = Arr.appendDictionary();
      Entry.set(KeyGroupName, G);
    }
    Resp = RespBuilder.createResponse();
  });
  return Resp;
}

static bool
buildRenameLocationsFromDict(RequestDict &Req, bool UseNewName,
                             std::vector<RenameLocations> &RenameLocations,
                             llvm::SmallString<64> &Error) {
  bool Failed = Req.dictionaryArrayApply(KeyRenameLocations,
                                         [&](RequestDict RenameLocation) {
    int64_t IsFunctionLike = false;
    if (RenameLocation.getInt64(KeyIsFunctionLike, IsFunctionLike, false)) {
      Error = "missing key.is_function_like";
      return true;
    }

    int64_t IsNonProtocolType = false;
    if (RenameLocation.getInt64(KeyIsNonProtocolType, IsNonProtocolType, false)) {
      Error = "missing key.is_non_protocol_type";
      return true;
    }

    Optional<StringRef> OldName = RenameLocation.getString(KeyName);
    if (!OldName.hasValue()) {
      Error = "missing key.name";
      return true;
    }

    Optional<StringRef> NewName;
    if (UseNewName) {
      NewName = RenameLocation.getString(KeyNewName);
      if (!NewName.hasValue()) {
        Error = "missing key.newname";
        return true;
      }
    }

    RenameLocations.push_back({*OldName,
                               UseNewName ? *NewName : "",
                               static_cast<bool>(IsFunctionLike),
                               static_cast<bool>(IsNonProtocolType),
                               {}});
    auto &LineCols = RenameLocations.back().LineColumnLocs;
    bool Failed = RenameLocation.dictionaryArrayApply(KeyLocations,
                                                      [&](RequestDict LineAndCol) {
      int64_t Line = 0;
      int64_t Column = 0;

      if (LineAndCol.getInt64(KeyLine, Line, false)) {
        Error = "missing key.line";
        return true;
      }
      if (LineAndCol.getInt64(KeyColumn, Column, false)) {
        Error = "missing key.column";
        return true;
      }

      sourcekitd_uid_t NameType = LineAndCol.getUID(KeyNameType);
      if (!NameType) {
        Error = "missing key.nametype";
        return true;
      }
      RenameType RenameType = RenameType::Unknown;
      if (NameType == KindDefinition) {
        RenameType = RenameType::Definition;
      } else if (NameType == KindReference) {
        RenameType = RenameType::Reference;
      } else if (NameType == KindCall) {
        RenameType = RenameType::Call;
      } else if (NameType != KindUnknown) {
        Error = "invalid value for 'key.nametype'";
        return true;
      }
      LineCols.push_back({static_cast<unsigned>(Line),
        static_cast<unsigned>(Column), RenameType});
      return false;
    });
    if (Failed && Error.empty()) {
      Error = "invalid key.locations";
    }
    return Failed;
  });
  if (Failed && Error.empty()) {
    Error = "invalid key.renamelocations";
  }
  return Failed;
}

static sourcekitd_response_t
createCategorizedEditsResponse(const RequestResult<ArrayRef<CategorizedEdits>> &Result) {
  if (Result.isCancelled())
    return createErrorRequestCancelled();
  if (Result.isError())
    return createErrorRequestFailed(Result.getError());

  const ArrayRef<CategorizedEdits> &AllEdits = Result.value();

  ResponseBuilder RespBuilder;
  auto Dict = RespBuilder.getDictionary();
  auto Arr = Dict.setArray(KeyCategorizedEdits);
  for (auto &TheEdit : AllEdits) {
    auto Entry = Arr.appendDictionary();
    Entry.set(KeyCategory, TheEdit.Category);
    auto Edits = Entry.setArray(KeyEdits);
    for(auto E: TheEdit.Edits) {
      auto Edit = Edits.appendDictionary();
      Edit.set(KeyLine, E.StartLine);
      Edit.set(KeyColumn, E.StartColumn);
      Edit.set(KeyEndLine, E.EndLine);
      Edit.set(KeyEndColumn, E.EndColumn);
      Edit.set(KeyText, E.NewText);
      if (!E.RegionsWithNote.empty()) {
        auto Notes = Edit.setArray(KeyRangesWorthNote);
        for (auto R : E.RegionsWithNote) {
          auto N = Notes.appendDictionary();
          N.set(KeyKind, R.Kind);
          N.set(KeyLine, R.StartLine);
          N.set(KeyColumn, R.StartColumn);
          N.set(KeyEndLine, R.EndLine);
          N.set(KeyEndColumn, R.EndColumn);
          if (R.ArgIndex)
            N.set(KeyArgIndex, *R.ArgIndex);
        }
      }
    }
  }
  return RespBuilder.createResponse();
}

static sourcekitd_response_t
syntacticRename(llvm::MemoryBuffer *InputBuf,
                ArrayRef<RenameLocations> RenameLocations,
                ArrayRef<const char*> Args) {
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  sourcekitd_response_t Result;
  Lang.syntacticRename(InputBuf, RenameLocations, Args,
    [&](const RequestResult<ArrayRef<CategorizedEdits>> &ReqResult) {
      Result = createCategorizedEditsResponse(ReqResult);
  });
  return Result;
}

static sourcekitd_response_t
createCategorizedRenameRangesResponse(const RequestResult<ArrayRef<CategorizedRenameRanges>> &Result) {
  if (Result.isCancelled())
    return createErrorRequestCancelled();
  if (Result.isError())
    return createErrorRequestFailed(Result.getError());

  const ArrayRef<CategorizedRenameRanges> &Ranges = Result.value();

  ResponseBuilder RespBuilder;
  auto Dict = RespBuilder.getDictionary();
  auto Arr = Dict.setArray(KeyCategorizedRanges);
  for (const auto &CategorizedRange : Ranges) {
    auto Entry = Arr.appendDictionary();
    Entry.set(KeyCategory, CategorizedRange.Category);
    auto Ranges = Entry.setArray(KeyRanges);
    for (const auto &R : CategorizedRange.Ranges) {
      auto Range = Ranges.appendDictionary();
      Range.set(KeyLine, R.StartLine);
      Range.set(KeyColumn, R.StartColumn);
      Range.set(KeyEndLine, R.EndLine);
      Range.set(KeyEndColumn, R.EndColumn);
      Range.set(KeyKind, R.Kind);
      if (R.ArgIndex) {
        Range.set(KeyArgIndex, *R.ArgIndex);
      }
    }
  }
  return RespBuilder.createResponse();
}

static sourcekitd_response_t
findRenameRanges(llvm::MemoryBuffer *InputBuf,
                 ArrayRef<RenameLocations> RenameLocations,
                 ArrayRef<const char *> Args) {
  LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
  sourcekitd_response_t Result;
  Lang.findRenameRanges(
      InputBuf, RenameLocations, Args,
      [&](const RequestResult<ArrayRef<CategorizedRenameRanges>> &ReqResult) {
        Result = createCategorizedRenameRangesResponse(ReqResult);
      });
  return Result;
}

static bool isSemanticEditorDisabled() {
  enum class SemaInfoToggle : char {
    None, Disable, Enable
  };
  static SemaInfoToggle Toggle = SemaInfoToggle::None;

  if (Toggle == SemaInfoToggle::None) {
    static std::once_flag flag;
    std::call_once(flag, []() {
      Toggle = SemaInfoToggle::Enable;

      const char *EnvOpt = ::getenv("SOURCEKIT_DELAY_SEMA_EDITOR");
      if (!EnvOpt) {
        return;
      }

      unsigned Seconds;
      if (StringRef(EnvOpt).getAsInteger(10, Seconds))
        return;

      // A crash occurred previously. Disable semantic info in the editor for
      // the given amount, to avoid repeated crashers.
      LOG_WARN_FUNC("delaying semantic editor for " << Seconds << " seconds");
      Toggle = SemaInfoToggle::Disable;
      dispatch_time_t When = dispatch_time(DISPATCH_TIME_NOW,
                                           NSEC_PER_SEC * Seconds);
      dispatch_after(When, dispatch_get_main_queue(), ^{
        Toggle = SemaInfoToggle::Enable;
        getGlobalContext()
            .getNotificationCenter()
            ->postSemaEnabledNotification();
      });
    });
  }

  assert(Toggle != SemaInfoToggle::None);
  return Toggle == SemaInfoToggle::Disable;
}

namespace {
class CompileTrackingConsumer final : public trace::TraceConsumer {
public:
  void operationStarted(uint64_t OpId, trace::OperationKind OpKind,
                        const trace::SwiftInvocation &Inv,
                        const trace::StringPairs &OpArgs) override;
  void operationFinished(uint64_t OpId, trace::OperationKind OpKind,
                         ArrayRef<DiagnosticEntryInfo> Diagnostics) override;
  swift::OptionSet<trace::OperationKind> desiredOperations() override {
    return swift::OptionSet<trace::OperationKind>() |
           trace::OperationKind::PerformSema |
           trace::OperationKind::CodeCompletion;
  }
};
} // end anonymous namespace

static Optional<UIdent> getUIDForOperationKind(trace::OperationKind OpKind) {
  static UIdent CompileOperationIndexSource("source.compile.operation.index-source");
  static UIdent CompileOperationCodeCompletion("source.compile.operation.code-completion");
  switch (OpKind) {
    case trace::OperationKind::PerformSema:
      return None;
    case trace::OperationKind::IndexSource:
      return CompileOperationIndexSource;
    case trace::OperationKind::CodeCompletion:
      return CompileOperationCodeCompletion;
    default:
      llvm_unreachable("Unknown operation kind");
  }
}

void CompileTrackingConsumer::operationStarted(
    uint64_t OpId, trace::OperationKind OpKind,
    const trace::SwiftInvocation &Inv, const trace::StringPairs &OpArgs) {
  if (desiredOperations().contains(OpKind))
    getGlobalContext()
        .getNotificationCenter()
        ->postCompileWillStartNotification(OpId, OpKind, Inv);
}

void CompileTrackingConsumer::operationFinished(
    uint64_t OpId, trace::OperationKind OpKind,
    ArrayRef<DiagnosticEntryInfo> Diagnostics) {
  if (desiredOperations().contains(OpKind))
    getGlobalContext()
        .getNotificationCenter()
        ->postCompileDidFinishNotification(OpId, OpKind, Diagnostics);
}

static void enableCompileNotifications(bool value) {
  static std::atomic<bool> status{false};
  if (status.exchange(value) == value) {
    return; // Unchanged.
  }

  static CompileTrackingConsumer compileConsumer;
  if (value) {
    trace::registerConsumer(&compileConsumer);
  } else {
    trace::unregisterConsumer(&compileConsumer);
  }
}
