//===--- sourcekitd-test.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 "sourcekitd/sourcekitd.h"

// SWIFT_ENABLE_TENSORFLOW
#include "sourcekitd/FileSystemProvider.h"
// SWIFT_ENABLE_TENSORFLOW END
#include "SourceKit/Support/Concurrency.h"
#include "TestOptions.h"
#include "swift/Demangling/ManglingMacros.h"
// SWIFT_ENABLE_TENSORFLOW
#include "clang/Basic/InMemoryOutputFileSystem.h"
// SWIFT_ENABLE_TENSORFLOW END
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/raw_ostream.h"
#include <fstream>
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <sys/param.h>
#include <unistd.h>
#elif defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <Windows.h>
#endif

// FIXME: Platform compatibility.
#include <dispatch/dispatch.h>

using namespace llvm;

using namespace sourcekitd_test;

#if defined(_WIN32)
namespace {
int STDOUT_FILENO = _fileno(stdout);
}
#endif

static bool sendGlobalConfigRequest();
static int handleTestInvocation(ArrayRef<const char *> Args, TestOptions &InitOpts,
                                bool IsFirstInvocation);
static bool handleResponse(sourcekitd_response_t Resp, const TestOptions &Opts,
                           const std::string &SourceFile,
                           std::unique_ptr<llvm::MemoryBuffer> SourceBuf,
                           TestOptions *InitOpts);
static void printCursorInfo(sourcekitd_variant_t Info, StringRef Filename,
                            const llvm::StringMap<TestOptions::VFSFile> &VFSFiles,
                            llvm::raw_ostream &OS);
static void printNameTranslationInfo(sourcekitd_variant_t Info, llvm::raw_ostream &OS);
static void printRangeInfo(sourcekitd_variant_t Info, StringRef Filename,
                           llvm::raw_ostream &OS);
static void printExpressionType(sourcekitd_variant_t Info, llvm::raw_ostream &OS);
static void printDocInfo(sourcekitd_variant_t Info, StringRef Filename);
static void printInterfaceGen(sourcekitd_variant_t Info, bool CheckASCII);
static void printSemanticInfo();
static void printRelatedIdents(sourcekitd_variant_t Info, StringRef Filename,
                               const llvm::StringMap<TestOptions::VFSFile> &VFSFiles,
                               llvm::raw_ostream &OS);
static void printFoundInterface(sourcekitd_variant_t Info,
                                llvm::raw_ostream &OS);
static void printFoundUSR(sourcekitd_variant_t Info,
                          llvm::MemoryBuffer *SourceBuf,
                          llvm::raw_ostream &OS);
static void printNormalizedDocComment(sourcekitd_variant_t Info);
static void expandPlaceholders(llvm::MemoryBuffer *SourceBuf,
                               llvm::raw_ostream &OS);

static void printModuleGroupNames(sourcekitd_variant_t Info,
                                  llvm::raw_ostream &OS);
static void printSyntacticRenameEdits(sourcekitd_variant_t Info,
                                      llvm::raw_ostream &OS);
static void printRenameRanges(sourcekitd_variant_t Info, llvm::raw_ostream &OS);
static void prepareDemangleRequest(sourcekitd_object_t Req,
                                   const TestOptions &Opts);
static void printDemangleResults(sourcekitd_variant_t Info, raw_ostream &OS);
static void prepareMangleRequest(sourcekitd_object_t Req,
                                 const TestOptions &Opts);
static void printMangleResults(sourcekitd_variant_t Info, raw_ostream &OS);
static void printStatistics(sourcekitd_variant_t Info, raw_ostream &OS);

static unsigned
resolveFromLineCol(unsigned Line, unsigned Col, StringRef Filename,
                   const llvm::StringMap<TestOptions::VFSFile> &VFSFiles);
static unsigned resolveFromLineCol(unsigned Line, unsigned Col,
                                   llvm::MemoryBuffer *InputBuf);
static std::pair<unsigned, unsigned>
resolveToLineCol(unsigned Offset, StringRef Filename,
                 const llvm::StringMap<TestOptions::VFSFile> &VFSFiles);
static std::pair<unsigned, unsigned> resolveToLineCol(unsigned Offset,
                                                  llvm::MemoryBuffer *InputBuf);
static std::pair<unsigned, unsigned> resolveToLineColFromBuf(unsigned Offset,
                                                      const char *Buf);
static llvm::MemoryBuffer *
getBufferForFilename(StringRef Filename,
                     const llvm::StringMap<TestOptions::VFSFile> &VFSFiles);

static void notification_receiver(sourcekitd_response_t resp);

static SourceKitRequest ActiveRequest = SourceKitRequest::None;

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

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

static sourcekitd_uid_t SemaDiagnosticStage;

static sourcekitd_uid_t NoteDocUpdate;
static SourceKit::Semaphore semaSemaphore(0);
static sourcekitd_response_t semaResponse;
static const char *semaName;

static sourcekitd_uid_t NoteTest;
static SourceKit::Semaphore noteSyncSemaphore(0);

namespace {
struct AsyncResponseInfo {
  SourceKit::Semaphore semaphore{0};
  sourcekitd_response_t response = nullptr;
  TestOptions options;
  std::string sourceFilename;
  std::unique_ptr<llvm::MemoryBuffer> sourceBuffer;
};
} // end anonymous namespace

static std::vector<AsyncResponseInfo> asyncResponses;

struct NotificationBuffer {
  std::vector<sourcekitd_response_t> notes;
  /// Add a notification to the buffer, taking ownership of it. Must be called
  /// from the main queue.
  void add(sourcekitd_response_t note) {
    notes.push_back(note);
  }
  /// Call the given handler for all notifications currently buffered.
  void handleNotifications(llvm::function_ref<void(sourcekitd_response_t)> f) {
    // Notifications are handled on the main queue.
    dispatch_sync(dispatch_get_main_queue(), ^{
      for (auto note : notes) {
        f(note);
        sourcekitd_response_dispose(note);
      }
      notes.clear();
    });
  }
};
static NotificationBuffer notificationBuffer;

static void syncNotificationsWithService() {
  // Send TestNotification request, then wait for the notification. This ensures
  // that all notifications previously posted on the service side have been
  // passed to our notification handler.
  sourcekitd_object_t req = sourcekitd_request_dictionary_create(nullptr, nullptr, 0);
  sourcekitd_request_dictionary_set_uid(req, KeyRequest, RequestTestNotification);
  auto resp = sourcekitd_send_request_sync(req);
  if (sourcekitd_response_is_error(resp)) {
    sourcekitd_response_description_dump(resp);
    exit(1);
  }
  sourcekitd_response_dispose(resp);
  sourcekitd_request_release(req);
  if (noteSyncSemaphore.wait(60 * 1000)) {
    llvm::report_fatal_error("Test notification not received");
  }
}

static void printBufferedNotifications(bool syncWithService = true) {
  if (syncWithService) {
    syncNotificationsWithService();
  }
  notificationBuffer.handleNotifications([](sourcekitd_response_t note) {
    sourcekitd_response_description_dump_filedesc(note, STDOUT_FILENO);
  });
}

struct skt_args {
  int argc;
  const char **argv;
  int ret;
};
static void skt_main(skt_args *args);

int main(int argc, const char **argv) {
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    skt_args args = {argc, argv, 0};
    llvm::llvm_execute_on_thread((void (*)(void *))skt_main, &args);
    exit(args.ret);
  });

  dispatch_main();
}

static void skt_main(skt_args *args) {
  int argc = args->argc;
  const char **argv = args->argv;
  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);

  sourcekitd_initialize();

  sourcekitd_set_notification_handler(^(sourcekitd_response_t resp) {
    notification_receiver(resp);
  });

#define KEY(NAME, CONTENT) Key##NAME = sourcekitd_uid_get_from_cstr(CONTENT);
#include "SourceKit/Core/ProtocolUIDs.def"

  SemaDiagnosticStage = sourcekitd_uid_get_from_cstr("source.diagnostic.stage.swift.sema");

  NoteDocUpdate = sourcekitd_uid_get_from_cstr("source.notification.editor.documentupdate");
  NoteTest = sourcekitd_uid_get_from_cstr("source.notification.test");

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

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

  // A test invocation may initialize the options to be used for subsequent
  // invocations.
  TestOptions InitOpts;
  auto Args = llvm::makeArrayRef(argv+1, argc-1);
  bool firstInvocation = true;
  while (1) {
    unsigned i = 0;
    for (auto Arg: Args) {
      if (StringRef(Arg) == "==")
        break;
      ++i;
    }
    if (i == Args.size())
      break;
    if (int ret = handleTestInvocation(Args.slice(0, i), InitOpts,
                                       firstInvocation)) {
      sourcekitd_shutdown();
      args->ret = ret;
      return;
    }
    Args = Args.slice(i + 1);
    firstInvocation = false;
  }

  if (int ret = handleTestInvocation(Args, InitOpts, firstInvocation)) {
    sourcekitd_shutdown();
    args->ret = ret;
    return;
  }

  for (auto &info : asyncResponses) {
    if (info.semaphore.wait(60 * 1000)) {
      llvm::report_fatal_error("async request timed out");
    }

    if (handleResponse(info.response, info.options, info.sourceFilename,
                       std::move(info.sourceBuffer), nullptr)) {
      sourcekitd_shutdown();
      args->ret = 1;
      return;
    }
  }
  printBufferedNotifications();

  sourcekitd_shutdown();
  args->ret = 0;
  return;
}

static inline std::string getInterfaceGenDocumentName() {
  // "Absolute path" on all platforms since handleTestInvocation will attempt to make this absolute
  llvm::SmallString<64> path = llvm::StringRef("/<interface-gen>");
  llvm::sys::fs::make_absolute(path);
  llvm::sys::path::native(path);
  return std::string(path.str());
}

static int printAnnotations();
static int printDiags();

static void getSemanticInfo(sourcekitd_variant_t Info, StringRef Filename);

static Optional<int64_t> getReqOptValueAsInt(StringRef Value) {
  if (Value.equals_lower("true"))
    return 1;
  if (Value.equals_lower("false"))
    return 0;
  int64_t Ret;
  if (Value.find_first_not_of("-0123456789") != StringRef::npos ||
      Value.getAsInteger(0, Ret)) {
    return None;
  }
  return Ret;
}

static Optional<sourcekitd_uid_t> getReqOptValueAsUID(StringRef Value) {
  if (!Value.startswith("uid:"))
    return None;
  Value = Value.drop_front(4);
  return sourcekitd_uid_get_from_buf(Value.data(), Value.size());
}

static Optional<sourcekitd_object_t> getReqOptValueAsArray(StringRef Value) {
  if (!Value.startswith("[") || !Value.endswith("]"))
    return None;
  SmallVector<StringRef, 4> Elements;
  Value.drop_front().drop_back().split(Elements, ';');
  auto Array = sourcekitd_request_array_create(nullptr, 0);
  for (auto &Elem : Elements) {
    if (auto Val = getReqOptValueAsInt(Elem)) {
      sourcekitd_request_array_set_int64(Array, SOURCEKITD_ARRAY_APPEND, *Val);
    } else if (auto Val = getReqOptValueAsUID(Elem)) {
      sourcekitd_request_array_set_uid(Array, SOURCEKITD_ARRAY_APPEND, *Val);
    } else if (auto Val = getReqOptValueAsArray(Elem)) {
      sourcekitd_request_array_set_value(Array, SOURCEKITD_ARRAY_APPEND, *Val);
    } else {
      sourcekitd_request_array_set_stringbuf(Array, SOURCEKITD_ARRAY_APPEND,
                                             Elem.data(), Elem.size());
    }
  }
  return Array;
}

static void addRequestOptionsDirect(sourcekitd_object_t Req, TestOptions &Opts,
                                    StringRef prefix = "key.") {
  if (Opts.RequestOptions.empty())
    return;

  for (auto &Opt: Opts.RequestOptions) {
    auto KeyValue = StringRef(Opt).split('=');
    std::string KeyStr(prefix.str());
    KeyStr.append(KeyValue.first.str());
    sourcekitd_uid_t Key = sourcekitd_uid_get_from_cstr(KeyStr.c_str());

    StringRef RawValue = KeyValue.second;

    if (auto Val = getReqOptValueAsInt(RawValue)) {
      sourcekitd_request_dictionary_set_int64(Req, Key, *Val);
    } else if (auto Val = getReqOptValueAsUID(RawValue)) {
      sourcekitd_request_dictionary_set_uid(Req, Key, *Val);
    } else if (auto Val = getReqOptValueAsArray(RawValue)) {
      sourcekitd_request_dictionary_set_value(Req, Key, *Val);
      sourcekitd_request_release(*Val);
    } else {
      sourcekitd_request_dictionary_set_stringbuf(Req, Key, RawValue.data(), RawValue.size());
    }
  }
}

static void addRequestOptions(sourcekitd_object_t Req, TestOptions &Opts,
                              sourcekitd_uid_t Key, StringRef prefix = "key.") {
  if (Opts.RequestOptions.empty())
    return;

  sourcekitd_object_t CCOpts =
      sourcekitd_request_dictionary_create(nullptr, nullptr, 0);

  addRequestOptionsDirect(CCOpts, Opts, prefix);

  sourcekitd_request_dictionary_set_value(Req, Key, CCOpts);
  sourcekitd_request_release(CCOpts);
}

static bool readPopularAPIList(StringRef filename,
                               std::vector<std::string> &result) {
  std::ifstream in(filename.str());
  if (!in.is_open()) {
    llvm::errs() << "error opening '" << filename << "'\n";
    return true;
  }

  std::string line;
  while (std::getline(in, line)) {
    result.emplace_back();
    std::swap(result.back(), line);
  }
  return false;
}

namespace {
class PrintingTimer {
  std::string desc;
  llvm::sys::TimePoint<> start;
  llvm::raw_ostream &OS;
public:
  PrintingTimer(std::string desc, llvm::raw_ostream &OS = llvm::errs())
      : desc(std::move(desc)), start(std::chrono::system_clock::now()), OS(OS) {
  }
  ~PrintingTimer() {
    std::chrono::duration<float, std::milli> delta(
        std::chrono::system_clock::now() - start);
    OS << desc << ": " << llvm::formatv("{0:ms+f3}", delta) << "\n";
  }
};
}

/// Wrapper for sourcekitd_send_request_sync that handles printing options.
static sourcekitd_response_t sendRequestSync(sourcekitd_object_t req,
                                             const TestOptions &opts) {
  if (opts.PrintRequest)
    sourcekitd_request_description_dump(req);
  Optional<PrintingTimer> timer;
  if (opts.timeRequest)
    timer.emplace("request time");
  return sourcekitd_send_request_sync(req);
}

static int handleJsonRequestPath(StringRef QueryPath, const TestOptions &Opts) {
  auto Buffer = getBufferForFilename(QueryPath, Opts.VFSFiles)->getBuffer();
  char *Err = nullptr;
  auto Req = sourcekitd_request_create_from_yaml(Buffer.data(), &Err);
  if (!Req) {
    assert(Err);
    llvm::errs() << Err;
    free(Err);
    return 1;
  }

  sourcekitd_response_t Resp = sendRequestSync(Req, Opts);
  auto Error = sourcekitd_response_is_error(Resp);
  if (Opts.PrintResponse) {
    sourcekitd_response_description_dump_filedesc(Resp, STDOUT_FILENO);
  }
  return Error ? 1 : 0;
}

static int performShellExecution(ArrayRef<const char *> Args) {
  auto Program = llvm::sys::findProgramByName(Args[0]);
  if (std::error_code ec = Program.getError()) {
    llvm::errs() << "command not found: " << Args[0] << "\n";
    return ec.value();
  }
  SmallVector<StringRef, 8> execArgs(Args.begin(), Args.end());
  return llvm::sys::ExecuteAndWait(*Program, execArgs);
}

static int handleTestInvocation(TestOptions Opts, TestOptions &InitOpts);

static int handleTestInvocation(ArrayRef<const char *> Args,
                                TestOptions &InitOpts, bool firstInvocation) {

  unsigned Optargc = 0;
  for (auto Arg: Args) {
    if (StringRef(Arg) == "--")
      break;
    ++Optargc;
  }

  TestOptions Opts = InitOpts;
  if (Opts.parseArgs(Args.slice(0, Optargc)))
    return 1;

  if (!Opts.ModuleCachePath.empty())
    InitOpts.ModuleCachePath = Opts.ModuleCachePath;

  if (Optargc < Args.size())
    Opts.CompilerArgs = Args.slice(Optargc+1);

  if (firstInvocation && Opts.Request != SourceKitRequest::GlobalConfiguration &&
      !Opts.SuppressDefaultConfigRequest) {
    // We don't fail if this request fails for now so that sourcekitd-test is
    // still usable with older versions of sourcekitd that don't have the
    // global-configuration request.
    if (sendGlobalConfigRequest()) {
      llvm::outs() << "warning: global configuration request failed\n";
    }
  }

  if (Opts.ShellExecution)
    return performShellExecution(Opts.CompilerArgs);

  assert(Opts.repeatRequest >= 1);
  for (unsigned i = 0; i < Opts.repeatRequest; ++i) {
    if (int ret = handleTestInvocation(Opts, InitOpts)) {
      printBufferedNotifications(/*syncWithService=*/true);
      return ret;
    }
    // We will sync with the service before exiting; don't do so here.
    printBufferedNotifications(/*syncWithService=*/false);
  }
  return 0;
}

static bool sendGlobalConfigRequest() {
  TestOptions Opts;
  sourcekitd_object_t Req = sourcekitd_request_dictionary_create(nullptr,
                                                                 nullptr, 0);
  sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestGlobalConfiguration);

  // For test invocations we default to setting OptimizeForIDE to true. This
  // matches the use case of the most popular clients of sourcekitd (editors)
  // and also disables loading locations from .swiftsourceinfo files. This is
  // desirable for testing because the .swiftsourceinfo for the stdlib is
  // available when sourcekitd is tested, and can make some stdlib-dependent
  // sourcekitd tests unstable due to changing source locations from the stdlib
  // module.
  sourcekitd_request_dictionary_set_int64(Req, KeyOptimizeForIDE, static_cast<int64_t>(true));
  sourcekitd_response_t Resp = sendRequestSync(Req, Opts);
  bool IsError = sourcekitd_response_is_error(Resp);
  if (IsError)
    sourcekitd_response_description_dump(Resp);
  sourcekitd_request_release(Req);
  return IsError;
}

static int handleTestInvocation(TestOptions Opts, TestOptions &InitOpts) {
  // SWIFT_ENABLE_TENSORFLOW
#ifdef SWIFT_SOURCEKIT_USE_INPROC_LIBRARY
  if (Opts.InMemoryClangModuleCache) {
    SourceKit::setGlobalInMemoryOutputFileSystem(
        new clang::InMemoryOutputFileSystem());
  } else {
    SourceKit::setGlobalInMemoryOutputFileSystem(nullptr);
  }
#endif

  if (!Opts.JsonRequestPath.empty())
    return handleJsonRequestPath(Opts.JsonRequestPath, Opts);

  if (Opts.Request == SourceKitRequest::DemangleNames ||
      Opts.Request == SourceKitRequest::MangleSimpleClasses)
    Opts.SourceFile.clear();

  std::string SourceFile = Opts.SourceFile;
  if (!SourceFile.empty()) {
    llvm::SmallString<64> AbsSourceFile;
    AbsSourceFile += SourceFile;
    llvm::sys::fs::make_absolute(AbsSourceFile);
    llvm::sys::path::native(AbsSourceFile);
    SourceFile = std::string(AbsSourceFile.str());
  }
  std::string SemaName = !Opts.Name.empty() ? Opts.Name : SourceFile;

  if (!Opts.TextInputFile.empty()) {
    auto Buf = getBufferForFilename(Opts.TextInputFile, Opts.VFSFiles);
    Opts.SourceText = Buf->getBuffer().str();
  }

  std::unique_ptr<llvm::MemoryBuffer> SourceBuf;
  if (Opts.SourceText.hasValue()) {
    SourceBuf = llvm::MemoryBuffer::getMemBuffer(*Opts.SourceText, Opts.SourceFile);
  } else if (!SourceFile.empty()) {
    SourceBuf = llvm::MemoryBuffer::getMemBuffer(
        getBufferForFilename(SourceFile, Opts.VFSFiles)->getBuffer(),
        SourceFile);
  }

  // FIXME: we should detect if offset is required but not set.
  unsigned ByteOffset = Opts.Offset;
  if (Opts.Line != 0) {
    ByteOffset = resolveFromLineCol(Opts.Line, Opts.Col, SourceBuf.get());
  }

  if (Opts.EndLine != 0) {
    Opts.Length = resolveFromLineCol(Opts.EndLine, Opts.EndCol, SourceBuf.get()) -
      ByteOffset;
  }

  bool compilerArgsAreClang = false;

  sourcekitd_object_t Req = sourcekitd_request_dictionary_create(nullptr,
                                                                 nullptr, 0);
  ActiveRequest = Opts.Request;
  switch (Opts.Request) {
  case SourceKitRequest::None:
    llvm::errs() << "request is not set\n";
    // FIXME: This non-zero return value is not propagated as an exit code.
    //        In other words, despite returning 1 here, the program still exits
    //        with a zero (successful) exit code.
    return 1;

  case SourceKitRequest::GlobalConfiguration:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestGlobalConfiguration);

    for (auto &Opt : Opts.RequestOptions) {
      auto KeyValue = StringRef(Opt).split('=');
      std::string KeyStr("key.");
      KeyStr.append(KeyValue.first.str());
      sourcekitd_uid_t Key = sourcekitd_uid_get_from_cstr(KeyStr.c_str());

      int64_t Value = 0;
      KeyValue.second.getAsInteger(0, Value);
      sourcekitd_request_dictionary_set_int64(Req, Key, Value);
    }
    break;

  case SourceKitRequest::ProtocolVersion:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestProtocolVersion);
    break;
  
  case SourceKitRequest::CompilerVersion:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestCompilerVersion);
    break;

  case SourceKitRequest::DemangleNames:
    prepareDemangleRequest(Req, Opts);
    break;

  case SourceKitRequest::MangleSimpleClasses:
    prepareMangleRequest(Req, Opts);
    break;

  case SourceKitRequest::EnableCompileNotifications: {
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
                                          RequestEnableCompileNotifications);
    int64_t value = 1;
    for (auto &Opt : Opts.RequestOptions) {
      auto KeyValue = StringRef(Opt).split('=');
      if (KeyValue.first == "value") {
        KeyValue.second.getAsInteger(0, value);
      } else {
        llvm::errs() << "unknown parameter '" << KeyValue.first
                     << "' in -req-opts";
        return 1;
      }
    }
    sourcekitd_request_dictionary_set_int64(Req, KeyValue, value);
    break;
  }

  case SourceKitRequest::Index:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestIndex);
    break;

  case SourceKitRequest::CodeComplete:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestCodeComplete);
    sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
    sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
    // Default to sort by name.
    Opts.RequestOptions.insert(Opts.RequestOptions.begin(), "sort.byname=1");
    addRequestOptions(Req, Opts, KeyCodeCompleteOptions, "key.codecomplete.");
    break;

  case SourceKitRequest::CodeCompleteOpen:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
                                          RequestCodeCompleteOpen);
    sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
    sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
    addRequestOptions(Req, Opts, KeyCodeCompleteOptions, "key.codecomplete.");
    break;

  case SourceKitRequest::CodeCompleteClose:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
                                          RequestCodeCompleteClose);
    sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
    sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
    break;

  case SourceKitRequest::CodeCompleteUpdate:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
                                          RequestCodeCompleteUpdate);
    sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
    sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
    addRequestOptions(Req, Opts, KeyCodeCompleteOptions, "key.codecomplete.");
    break;

  case SourceKitRequest::CodeCompleteCacheOnDisk:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
                                          RequestCodeCompleteCacheOnDisk);
    sourcekitd_request_dictionary_set_string(Req, KeyName,
                                             Opts.CachePath.c_str());
    break;

  case SourceKitRequest::CodeCompleteSetPopularAPI: {
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
                                          RequestCodeCompleteSetPopularAPI);

    auto addPopularList = [&Req](StringRef filename, sourcekitd_uid_t key) {
      std::vector<std::string> names;
      if (readPopularAPIList(filename, names))
        return true;

      sourcekitd_object_t popular = sourcekitd_request_array_create(nullptr, 0);
      for (auto name : names)
        sourcekitd_request_array_set_string(popular, SOURCEKITD_ARRAY_APPEND,
                                            name.c_str());
      sourcekitd_request_dictionary_set_value(Req, key, popular);
      return false;
    };

    for (auto &Opt : Opts.RequestOptions) {
      auto KeyValue = StringRef(Opt).split('=');
      auto key = llvm::StringSwitch<sourcekitd_uid_t>(KeyValue.first)
        .Case("popular", KeyPopular)
        .Case("unpopular", KeyUnpopular)
        .Default(nullptr);
      if (!key) {
        llvm::errs() << "invalid key '" << KeyValue.first << "' in -req-opts\n";
        return 1;
      }

      if (addPopularList(KeyValue.second, key))
        return 1;
    }

    break;
  }

  case SourceKitRequest::TypeContextInfo:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
                                          RequestTypeContextInfo);
    sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
    addRequestOptions(Req, Opts, KeyTypeContextInfoOptions,
                      "key.typecontextinfo.");
    break;

  case SourceKitRequest::ConformingMethodList:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
                                          RequestConformingMethodList);
    sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
    addRequestOptionsDirect(Req, Opts);
    break;

  case SourceKitRequest::CursorInfo:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestCursorInfo);
    if (Opts.CollectActionables) {
      sourcekitd_request_dictionary_set_int64(Req, KeyRetrieveRefactorActions, 1);
    }
    if (Opts.Length) {
      sourcekitd_request_dictionary_set_int64(Req, KeyLength, Opts.Length);
    }
    if (!Opts.USR.empty()) {
      sourcekitd_request_dictionary_set_string(Req, KeyUSR, Opts.USR.c_str());
    } else {
      sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
    }
    addRequestOptionsDirect(Req, Opts);
    break;
  case SourceKitRequest::RangeInfo: {
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestRangeInfo);
    sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
    auto Length = Opts.Length;
    if (Opts.Length == 0 && Opts.EndLine > 0) {
      auto EndOff = resolveFromLineCol(Opts.EndLine, Opts.EndCol, SourceFile,
                                       Opts.VFSFiles);
      Length = EndOff - ByteOffset;
    }
    sourcekitd_request_dictionary_set_int64(Req, KeyLength, Length);
    break;
  }

  case SourceKitRequest::CollectExpresstionType: {
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestCollectExpressionType);
    addRequestOptionsDirect(Req, Opts);
    break;
  }

#define SEMANTIC_REFACTORING(KIND, NAME, ID) case SourceKitRequest::KIND:                 \
    {                                                                                     \
      sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestSemanticRefactoring); \
      sourcekitd_request_dictionary_set_uid(Req, KeyActionUID, KindRefactoring##KIND);    \
      sourcekitd_request_dictionary_set_string(Req, KeyName, Opts.Name.c_str());          \
      sourcekitd_request_dictionary_set_int64(Req, KeyLine, Opts.Line);                   \
      sourcekitd_request_dictionary_set_int64(Req, KeyColumn, Opts.Col);                  \
      sourcekitd_request_dictionary_set_int64(Req, KeyLength, Opts.Length);               \
      break;                                                                              \
    }
#include "swift/IDE/RefactoringKinds.def"

  case SourceKitRequest::MarkupToXML: {
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestMarkupToXML);
    break;
  }
  case SourceKitRequest::NameTranslation: {
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestNameTranslation);
    sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
    StringRef BaseName;
    llvm::SmallVector<StringRef, 4> ArgPieces;
    sourcekitd_uid_t ArgName;
    if (!Opts.SwiftName.empty()) {
      sourcekitd_request_dictionary_set_uid(Req, KeyNameKind, KindNameSwift);
      ArgName = KeyArgNames;
      StringRef Text(Opts.SwiftName);
      auto ArgStart = Text.find_first_of('(');
      if (ArgStart == StringRef::npos) {
        BaseName = Text;
      } else {
        BaseName = Text.substr(0, ArgStart);
        auto ArgEnd = Text.find_last_of(')');
        if (ArgEnd == StringRef::npos) {
          llvm::errs() << "Swift name is malformed.\n";
          return 1;
        }
        StringRef AllArgs = Text.substr(ArgStart + 1, ArgEnd - ArgStart - 1);
        AllArgs.split(ArgPieces, ':');
        if (!ArgPieces.empty()) {
          if (!ArgPieces.back().empty()) {
            llvm::errs() << "Swift name is malformed.\n";
            return 1;
          }
          ArgPieces.pop_back();
        }
      }
    } else if (!Opts.ObjCName.empty()) {
      sourcekitd_request_dictionary_set_uid(Req, KeyNameKind, KindNameObjc);
      BaseName = Opts.ObjCName;
      ArgName = KeySelectorPieces;
    } else if (!Opts.ObjCSelector.empty()) {
      sourcekitd_request_dictionary_set_uid(Req, KeyNameKind, KindNameObjc);
      StringRef Name(Opts.ObjCSelector);
      Name.split(ArgPieces, ':');
      if (ArgPieces.back().empty())
        ArgPieces.pop_back();
      ArgName = KeySelectorPieces;
    } else {
      llvm::errs() << "must specify either -swift-name or -objc-name or -objc-selector\n";
      return 1;
    }
    if (!BaseName.empty()) {
      std::string S = BaseName.str();
      sourcekitd_request_dictionary_set_string(Req, KeyBaseName, S.c_str());
    }
    if (!ArgPieces.empty()) {
      sourcekitd_object_t Arr = sourcekitd_request_array_create(nullptr, 0);
      for (StringRef A : ArgPieces) {
        std::string S = A.str();
        sourcekitd_request_array_set_string(Arr, SOURCEKITD_ARRAY_APPEND,
                                            S.c_str());
      }
      sourcekitd_request_dictionary_set_value(Req, ArgName, Arr);
    }
    break;
  }

  case SourceKitRequest::RelatedIdents:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestRelatedIdents);
    sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
    break;

  case SourceKitRequest::SyntaxMap:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorOpen);
    sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
    sourcekitd_request_dictionary_set_int64(Req, KeyEnableSyntaxMap, true);
    sourcekitd_request_dictionary_set_int64(Req, KeyEnableStructure, false);
    sourcekitd_request_dictionary_set_uid(Req, KeySyntaxTreeTransferMode,
                                          KindSyntaxTreeOff);
    sourcekitd_request_dictionary_set_int64(Req, KeySyntacticOnly, !Opts.UsedSema);
    break;

  case SourceKitRequest::Structure:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorOpen);
    sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
    sourcekitd_request_dictionary_set_int64(Req, KeyEnableSyntaxMap, false);
    sourcekitd_request_dictionary_set_int64(Req, KeyEnableStructure, true);
    sourcekitd_request_dictionary_set_uid(Req, KeySyntaxTreeTransferMode,
                                          KindSyntaxTreeOff);
    sourcekitd_request_dictionary_set_int64(Req, KeySyntacticOnly, !Opts.UsedSema);
    break;

  case SourceKitRequest::Format:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorOpen);
    sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
    sourcekitd_request_dictionary_set_int64(Req, KeyEnableSyntaxMap, false);
    sourcekitd_request_dictionary_set_int64(Req, KeyEnableStructure, false);
    sourcekitd_request_dictionary_set_uid(Req, KeySyntaxTreeTransferMode,
                                          KindSyntaxTreeOff);
    sourcekitd_request_dictionary_set_int64(Req, KeySyntacticOnly, !Opts.UsedSema);
    break;

  case SourceKitRequest::ExpandPlaceholder:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorOpen);
    sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
    sourcekitd_request_dictionary_set_int64(Req, KeyEnableSyntaxMap, false);
    sourcekitd_request_dictionary_set_int64(Req, KeyEnableStructure, false);
    sourcekitd_request_dictionary_set_int64(Req, KeySyntacticOnly, !Opts.UsedSema);
    break;

  case SourceKitRequest::SyntaxTree:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorOpen);
    sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
    sourcekitd_request_dictionary_set_int64(Req, KeyEnableSyntaxMap, false);
    sourcekitd_request_dictionary_set_int64(Req, KeyEnableStructure, false);
    sourcekitd_request_dictionary_set_uid(Req, KeySyntaxTreeTransferMode,
                                          KindSyntaxTreeFull);
    sourcekitd_request_dictionary_set_int64(Req, KeySyntacticOnly, true);
    break;

  case SourceKitRequest::DocInfo:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestDocInfo);
    break;

  case SourceKitRequest::SemanticInfo:
    InitOpts.UsedSema = true;
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorOpen);
    sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
    break;

  case SourceKitRequest::Open:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorOpen);
    sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
    break;

  case SourceKitRequest::Close:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorClose);
    sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
    break;

  case SourceKitRequest::Edit:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
                                          RequestEditorReplaceText);
    sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str());
    sourcekitd_request_dictionary_set_int64(Req, KeyOffset, ByteOffset);
    sourcekitd_request_dictionary_set_int64(Req, KeyLength, Opts.Length);
    sourcekitd_request_dictionary_set_string(Req, KeySourceText,
                                       Opts.ReplaceText.getValue().c_str());
    break;

  case SourceKitRequest::PrintAnnotations:
    return printAnnotations();
  case SourceKitRequest::PrintDiags:
    return printDiags();
  case SourceKitRequest::ExtractComment:
    if (Opts.SourceFile.empty()) {
      llvm::errs() << "Missing '<source-file>' \n";
      return 1;
    }
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
                                          RequestEditorExtractTextFromComment);
    break;

  case SourceKitRequest::InterfaceGen:
  case SourceKitRequest::InterfaceGenOpen:
    sourcekitd_request_dictionary_set_int64(Req, KeySynthesizedExtension,
                                            Opts.SynthesizedExtensions);
    if (Opts.ModuleName.empty() && Opts.HeaderPath.empty() &&
        Opts.SourceFile.empty() && Opts.USR.empty()) {
      llvm::errs() << "Missing '-module <module name>' or '-header <path>'" <<
        "or '<source-file>' or '-usr <USR>' \n";
      return 1;
    }
    if (!Opts.ModuleName.empty()) {
      sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
                                            RequestEditorOpenInterface);
    } else if (!Opts.USR.empty()) {
      sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
                                            RequestEditorOpenSwiftTypeInterface);
    } else if (!Opts.SourceFile.empty()) {
      sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
                                            RequestEditorOpenSwiftSourceInterface);
    } else {
      if (Opts.UsingSwiftArgs)
          sourcekitd_request_dictionary_set_int64(Req, KeyUsingSwiftArgs, true);
      else
        compilerArgsAreClang = true;
      sourcekitd_request_dictionary_set_uid(Req, KeyRequest,
                                            RequestEditorOpenHeaderInterface);
    }

    sourcekitd_request_dictionary_set_string(Req, KeyName, getInterfaceGenDocumentName().c_str());
    if (!Opts.ModuleGroupName.empty())
      sourcekitd_request_dictionary_set_string(Req, KeyGroupName,
                                               Opts.ModuleGroupName.c_str());
    if (!Opts.InterestedUSR.empty())
      sourcekitd_request_dictionary_set_string(Req, KeyInterestedUSR,
                                               Opts.InterestedUSR.c_str());
    if (!Opts.USR.empty())
      sourcekitd_request_dictionary_set_string(Req, KeyUSR, Opts.USR.c_str());
    break;

  case SourceKitRequest::FindInterfaceDoc:
    if (Opts.ModuleName.empty()) {
      llvm::errs() << "Missing '-module <module name>'\n";
      return 1;
    }
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorFindInterfaceDoc);
    break;

  case SourceKitRequest::FindUSR:
    if (Opts.USR.empty()) {
      llvm::errs() << "Missing '-usr <USR string>'\n";
      return 1;
    }
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestEditorFindUSR);
    sourcekitd_request_dictionary_set_string(Req, KeyUSR, Opts.USR.c_str());
    break;

  case SourceKitRequest::ModuleGroups:
    if (Opts.ModuleName.empty()) {
      llvm::errs() << "Missing '-module <module name>'\n";
      return 1;
    }
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestModuleGroups);
    break;

  case SourceKitRequest::FindLocalRenameRanges:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestFindLocalRenameRanges);
    sourcekitd_request_dictionary_set_int64(Req, KeyLine, Opts.Line);
    sourcekitd_request_dictionary_set_int64(Req, KeyColumn, Opts.Col);
    sourcekitd_request_dictionary_set_int64(Req, KeyLength, Opts.Length);
    break;

  case SourceKitRequest::SyntacticRename:
  case SourceKitRequest::FindRenameRanges: {
    if (Opts.Request == SourceKitRequest::SyntacticRename) {
      sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestSyntacticRename);
    } else {
      sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestFindRenameRanges);
    }
    if (Opts.RenameSpecPath.empty()) {
      llvm::errs() << "Missing '-rename-spec <file path>'\n";
      return 1;
    }
    auto Buffer =
        getBufferForFilename(Opts.RenameSpecPath, Opts.VFSFiles)->getBuffer();
    char *Err = nullptr;
    auto RenameSpec = sourcekitd_request_create_from_yaml(Buffer.data(), &Err);
    if (!RenameSpec) {
      assert(Err);
      llvm::errs() << Err;
      free(Err);
      return 1;
    }
    sourcekitd_request_dictionary_set_value(Req, KeyRenameLocations, RenameSpec);
    break;
  }
  case SourceKitRequest::Statistics:
    sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestStatistics);
    break;
  }

  if (!SourceFile.empty()) {
    if (Opts.PassAsSourceText) {
      auto Buf = getBufferForFilename(SourceFile, Opts.VFSFiles);
      sourcekitd_request_dictionary_set_string(Req, KeySourceText,
                                               Buf->getBufferStart());
    }
    sourcekitd_request_dictionary_set_string(Req, KeySourceFile,
                                             SourceFile.c_str());
  }

  if (Opts.SourceText) {
    sourcekitd_request_dictionary_set_string(Req, KeySourceText,
                                             Opts.SourceText->c_str());
    sourcekitd_request_dictionary_set_string(Req, KeySourceFile,
                                             SemaName.c_str());
  }

  if (!Opts.CompilerArgs.empty()) {
    sourcekitd_object_t Args = sourcekitd_request_array_create(nullptr, 0);
    if (!Opts.ModuleCachePath.empty()) {
      if (compilerArgsAreClang) {
        // We need -fmodules or else the clang argument parsing does not honour
        // -fmodules-cache-path. In reality, the swift ClangImporter will always
        // enable modules when importing, so this should only impact the
        // clang argument parsing. This is needed even if the header doesn't
        // use modules, since Swift itself will import its shims module, and
        // that needs to honour the -module-cache-path option when testing.
        sourcekitd_request_array_set_string(Args, SOURCEKITD_ARRAY_APPEND, "-fmodules");
        std::string opt = "-fmodules-cache-path=" + Opts.ModuleCachePath;
        sourcekitd_request_array_set_string(Args, SOURCEKITD_ARRAY_APPEND, opt.c_str());
      } else {
        sourcekitd_request_array_set_string(Args, SOURCEKITD_ARRAY_APPEND, "-module-cache-path");
        sourcekitd_request_array_set_string(Args, SOURCEKITD_ARRAY_APPEND, Opts.ModuleCachePath.c_str());
      }
    }
    for (auto Arg : Opts.CompilerArgs)
      sourcekitd_request_array_set_string(Args, SOURCEKITD_ARRAY_APPEND, Arg);
    sourcekitd_request_dictionary_set_value(Req, KeyCompilerArgs, Args);
    sourcekitd_request_release(Args);
  }

  if (!Opts.ModuleName.empty()) {
    sourcekitd_request_dictionary_set_string(Req, KeyModuleName,
                                             Opts.ModuleName.c_str());
  }
  if (!Opts.HeaderPath.empty()) {
    sourcekitd_request_dictionary_set_string(Req, KeyFilePath,
                                             Opts.HeaderPath.c_str());
  }
  if (Opts.CancelOnSubsequentRequest.hasValue()) {
    sourcekitd_request_dictionary_set_int64(Req, KeyCancelOnSubsequentRequest,
                                            *Opts.CancelOnSubsequentRequest);
  }

  if (!Opts.SwiftVersion.empty()) {
    if (Opts.PassVersionAsString) {
      sourcekitd_request_dictionary_set_string(Req, KeySwiftVersion,
                                               Opts.SwiftVersion.c_str());
    } else {
      unsigned ver;
      if (StringRef(Opts.SwiftVersion).getAsInteger(10, ver)) {
        llvm::errs() << "error: expected integer for 'swift-version'\n";
        return true;
      }
      sourcekitd_request_dictionary_set_int64(Req, KeySwiftVersion, ver);
    }
  }

  if (Opts.VFSName) {
    sourcekitd_request_dictionary_set_string(Req, KeyVFSName, Opts.VFSName->c_str());
  }
  if (!Opts.VFSFiles.empty()) {
    sourcekitd_object_t files = sourcekitd_request_array_create(nullptr, 0);
    for (auto &NameAndTarget : Opts.VFSFiles) {
      sourcekitd_object_t file = sourcekitd_request_dictionary_create(nullptr, nullptr, 0);
      sourcekitd_request_dictionary_set_string(file, KeyName, NameAndTarget.first().data());

      if (NameAndTarget.second.passAsSourceText) {
        auto content = getBufferForFilename(NameAndTarget.first(), Opts.VFSFiles);
        sourcekitd_request_dictionary_set_string(file, KeySourceText,  content->getBufferStart());
      } else {
        sourcekitd_request_dictionary_set_string(file, KeySourceFile,  NameAndTarget.second.path.c_str());
      }
      sourcekitd_request_array_set_value(files, SOURCEKITD_ARRAY_APPEND, file);
    }
    sourcekitd_object_t vfsOpts = sourcekitd_request_dictionary_create(nullptr, nullptr, 0);
    sourcekitd_request_dictionary_set_value(vfsOpts, KeyFiles, files);
    sourcekitd_request_dictionary_set_value(Req, KeyVFSOptions, vfsOpts);
    sourcekitd_request_release(vfsOpts);
    sourcekitd_request_release(files);
  }

  if (!Opts.isAsyncRequest) {
    sourcekitd_response_t Resp = sendRequestSync(Req, Opts);
    sourcekitd_request_release(Req);
    return handleResponse(Resp, Opts, SemaName, std::move(SourceBuf),
                          &InitOpts)
               ? 1
               : 0;
  } else {
#if SOURCEKITD_HAS_BLOCKS
    AsyncResponseInfo info;
    info.options = Opts;
    info.sourceFilename = std::move(SemaName);
    info.sourceBuffer = std::move(SourceBuf);
    unsigned respIndex = asyncResponses.size();
    asyncResponses.push_back(std::move(info));

    if (Opts.PrintRequest)
      sourcekitd_request_description_dump(Req);

    sourcekitd_send_request(Req, nullptr, ^(sourcekitd_response_t resp) {
      auto &info = asyncResponses[respIndex];
      info.response = resp;
      info.semaphore.signal(); // Ready to be handled!
    });

#else
    llvm::report_fatal_error(
        "-async not supported when sourcekitd is built without blocks support");
#endif

    sourcekitd_request_release(Req);
    return 0;
  }
}

static bool handleResponse(sourcekitd_response_t Resp, const TestOptions &Opts,
                           const std::string &SourceFile,
                           std::unique_ptr<llvm::MemoryBuffer> SourceBuf,
                           TestOptions *InitOpts) {
  bool KeepResponseAlive = false;
  bool IsError = sourcekitd_response_is_error(Resp);
  if (IsError) {
    sourcekitd_response_description_dump(Resp);

  } else if (!Opts.PrintResponse) {
    // Nothing.
  } else if (Opts.PrintResponseAsJSON) {
    sourcekitd_variant_t Info = sourcekitd_response_get_value(Resp);
    char *json = sourcekitd_variant_json_description_copy(Info);
    llvm::outs() << json << '\n';
    free(json);

  } else if (Opts.PrintRawResponse) {
    sourcekitd_response_description_dump_filedesc(Resp, STDOUT_FILENO);

  } else {
    sourcekitd_variant_t Info = sourcekitd_response_get_value(Resp);
    switch (Opts.Request) {
    case SourceKitRequest::None:
      llvm_unreachable("request should be set");
    case SourceKitRequest::PrintAnnotations:
    case SourceKitRequest::PrintDiags:
      llvm_unreachable("print-annotations/print-diags is handled elsewhere");

    case SourceKitRequest::EnableCompileNotifications:
      // Ignore the response.  If it was an error it is handled above.
      break;

    case SourceKitRequest::Open:
      getSemanticInfo(Info, SourceFile);
      KeepResponseAlive = true;
      break;

    case SourceKitRequest::Edit:
      if (Opts.Length == 0 && Opts.ReplaceText->empty()) {
        // Length=0, replace="" is a nop and will not trigger sema.
        sourcekitd_response_description_dump_filedesc(Resp, STDOUT_FILENO);
      } else {
        getSemanticInfo(Info, SourceFile);
        KeepResponseAlive = true;
      }
      break;

    case SourceKitRequest::DemangleNames:
      printDemangleResults(sourcekitd_response_get_value(Resp), outs());
      break;

    case SourceKitRequest::MangleSimpleClasses:
      printMangleResults(sourcekitd_response_get_value(Resp), outs());
      break;

    case SourceKitRequest::GlobalConfiguration:
    case SourceKitRequest::ProtocolVersion:
    case SourceKitRequest::CompilerVersion:
    case SourceKitRequest::Close:
    case SourceKitRequest::Index:
    case SourceKitRequest::CodeComplete:
    case SourceKitRequest::CodeCompleteOpen:
    case SourceKitRequest::CodeCompleteClose:
    case SourceKitRequest::CodeCompleteUpdate:
    case SourceKitRequest::CodeCompleteCacheOnDisk:
    case SourceKitRequest::CodeCompleteSetPopularAPI:
    case SourceKitRequest::TypeContextInfo:
    case SourceKitRequest::ConformingMethodList:
      sourcekitd_response_description_dump_filedesc(Resp, STDOUT_FILENO);
      break;

    case SourceKitRequest::RelatedIdents:
      printRelatedIdents(Info, SourceFile, Opts.VFSFiles, llvm::outs());
      break;

    case SourceKitRequest::CursorInfo:
      printCursorInfo(Info, SourceFile, Opts.VFSFiles, llvm::outs());
      break;

    case SourceKitRequest::NameTranslation:
      printNameTranslationInfo(Info, llvm::outs());
      break;

    case SourceKitRequest::RangeInfo:
      printRangeInfo(Info, SourceFile, llvm::outs());
      break;

    case SourceKitRequest::CollectExpresstionType:
      printExpressionType(Info, llvm::outs());
      break;

    case SourceKitRequest::DocInfo:
      printDocInfo(Info, SourceFile);
      break;

    case SourceKitRequest::SemanticInfo:
      getSemanticInfo(Info, SourceFile);
      printSemanticInfo();
      break;

    case SourceKitRequest::InterfaceGen:
      printInterfaceGen(Info, Opts.CheckInterfaceIsASCII);
      break;

    case SourceKitRequest::ExtractComment:
    case SourceKitRequest::MarkupToXML:
      printNormalizedDocComment(Info);
      break;

    case SourceKitRequest::InterfaceGenOpen:
      // Just initialize the options for the subsequent request.
      assert(!Opts.isAsyncRequest && InitOpts &&
             "async interface-gen-open is not supported");
      InitOpts->SourceFile = getInterfaceGenDocumentName();
      InitOpts->SourceText =
          sourcekitd_variant_dictionary_get_string(Info, KeySourceText);
      break;

    case SourceKitRequest::FindInterfaceDoc:
      printFoundInterface(Info, llvm::outs());
      break;

    case SourceKitRequest::FindUSR:
      printFoundUSR(Info, SourceBuf.get(), llvm::outs());
      break;

    case SourceKitRequest::SyntaxTree: {
      // Print only the serialized syntax tree.
      llvm::outs() << sourcekitd_variant_dictionary_get_string(
        sourcekitd_response_get_value(Resp), KeySerializedSyntaxTree);
      llvm::outs() << '\n';
      break;
    }
    case SourceKitRequest::SyntaxMap:
    case SourceKitRequest::Structure:
      sourcekitd_response_description_dump_filedesc(Resp, STDOUT_FILENO);
      if (Opts.ReplaceText.hasValue()) {
        unsigned Offset =
            resolveFromLineCol(Opts.Line, Opts.Col, SourceFile, Opts.VFSFiles);
        unsigned Length = Opts.Length;
        sourcekitd_object_t EdReq = sourcekitd_request_dictionary_create(nullptr,
                                                                    nullptr, 0);
        sourcekitd_request_dictionary_set_uid(EdReq, KeyRequest,
                                              RequestEditorReplaceText);
        sourcekitd_request_dictionary_set_string(EdReq, KeyName,
                                                 SourceFile.c_str());
        sourcekitd_request_dictionary_set_int64(EdReq, KeyOffset, Offset);
        sourcekitd_request_dictionary_set_int64(EdReq, KeyLength, Length);
        sourcekitd_request_dictionary_set_string(EdReq, KeySourceText,
                                           Opts.ReplaceText.getValue().c_str());
        bool EnableSyntaxMax = Opts.Request == SourceKitRequest::SyntaxMap;
        bool EnableSubStructure = Opts.Request == SourceKitRequest::Structure;
        sourcekitd_request_dictionary_set_int64(EdReq, KeyEnableSyntaxMap,
                                                EnableSyntaxMax);
        sourcekitd_request_dictionary_set_int64(EdReq, KeyEnableStructure,
                                                EnableSubStructure);
        sourcekitd_request_dictionary_set_int64(EdReq, KeySyntacticOnly,
                                                !Opts.UsedSema);

        sourcekitd_response_t EdResp = sendRequestSync(EdReq, Opts);
        sourcekitd_response_description_dump_filedesc(EdResp, STDOUT_FILENO);
        sourcekitd_response_dispose(EdResp);
        sourcekitd_request_release(EdReq);
      }
      break;

    case SourceKitRequest::Format:
      {
        sourcekitd_object_t Fmt = sourcekitd_request_dictionary_create(nullptr,
                                                                    nullptr, 0);
        sourcekitd_request_dictionary_set_uid(Fmt, KeyRequest,
                                              RequestEditorFormatText);
        sourcekitd_request_dictionary_set_string(Fmt, KeyName,
                                                 SourceFile.c_str());
        sourcekitd_request_dictionary_set_string(Fmt, KeySourceText, "");
        sourcekitd_request_dictionary_set_int64(Fmt, KeyLine, Opts.Line);
        sourcekitd_request_dictionary_set_int64(Fmt, KeyLength, Opts.Length);

        if (!Opts.RequestOptions.empty()) {
          sourcekitd_object_t FO = sourcekitd_request_dictionary_create(nullptr,
                                                                    nullptr, 0);
          for (auto &FmtOpt : Opts.RequestOptions) {
            auto KeyValue = StringRef(FmtOpt).split('=');
            std::string KeyStr("key.editor.format.");
            KeyStr.append(KeyValue.first.str());
            sourcekitd_uid_t Key = sourcekitd_uid_get_from_cstr(KeyStr.c_str());
            int64_t Value = 0;
            KeyValue.second.getAsInteger(0, Value);
            sourcekitd_request_dictionary_set_int64(FO, Key, Value);
          }
          sourcekitd_request_dictionary_set_value(Fmt, KeyFormatOptions, FO);
          sourcekitd_request_release(FO);
        }

        sourcekitd_response_t FmtResp = sendRequestSync(Fmt, Opts);
        sourcekitd_response_description_dump_filedesc(FmtResp, STDOUT_FILENO);
        sourcekitd_response_dispose(FmtResp);
        sourcekitd_request_release(Fmt);
      }
      break;

      case SourceKitRequest::ExpandPlaceholder:
        expandPlaceholders(SourceBuf.get(), llvm::outs());
        break;
      case SourceKitRequest::ModuleGroups:
        printModuleGroupNames(Info, llvm::outs());
        break;
#define SEMANTIC_REFACTORING(KIND, NAME, ID) case SourceKitRequest::KIND:
#include "swift/IDE/RefactoringKinds.def"
      case SourceKitRequest::SyntacticRename:
        printSyntacticRenameEdits(Info, llvm::outs());
        break;
      case SourceKitRequest::FindRenameRanges:
      case SourceKitRequest::FindLocalRenameRanges:
        printRenameRanges(Info, llvm::outs());
        break;
      case SourceKitRequest::Statistics:
        printStatistics(Info, llvm::outs());
    }
  }

  if (!KeepResponseAlive)
    sourcekitd_response_dispose(Resp);
  return IsError;
}

sourcekitd_variant_t LatestSemaAnnotations = {{0,0,0}};
sourcekitd_variant_t LatestSemaDiags = {{0,0,0}};

static void getSemanticInfoImpl(sourcekitd_variant_t Info) {
  LatestSemaAnnotations =
    sourcekitd_variant_dictionary_get_value(Info, KeyAnnotations);
  LatestSemaDiags =
    sourcekitd_variant_dictionary_get_value(Info, KeyDiagnostics);
}

static void getSemanticInfoImplAfterDocUpdate(sourcekitd_variant_t EditOrOpen,
                                              sourcekitd_variant_t DocUpdate) {
  if (sourcekitd_variant_dictionary_get_uid(EditOrOpen, KeyDiagnosticStage) ==
      SemaDiagnosticStage) {
    // FIXME: currently we only return annotations once, so if the original edit
    // or open request was slow enough, it may "take" the annotations. If that
    // is fixed, we can skip checking the diagnostic stage and always use the
    // DocUpdate variant.
    assert(sourcekitd_variant_get_type(sourcekitd_variant_dictionary_get_value(
               DocUpdate, KeyAnnotations)) == SOURCEKITD_VARIANT_TYPE_NULL);

    getSemanticInfoImpl(EditOrOpen);
  } else {
    getSemanticInfoImpl(DocUpdate);
  }
}

static void getSemanticInfo(sourcekitd_variant_t Info, StringRef Filename) {
  // Wait for the notification that semantic info is available.
  // But only for 1 min.
  bool expired = semaSemaphore.wait(60 * 1000);
  if (expired) {
    llvm::report_fatal_error("Never got notification for semantic info");
  }

  if (Filename != semaName){
    llvm::report_fatal_error(
      llvm::Twine("Got notification for different doc name: ") + semaName);
  }

  getSemanticInfoImplAfterDocUpdate(
      Info, sourcekitd_response_get_value(semaResponse));
}

static int printAnnotations() {
  sourcekitd_variant_description_dump_filedesc(LatestSemaAnnotations,
                                               STDOUT_FILENO);
  return 0;
}

static int printDiags() {
  sourcekitd_variant_description_dump_filedesc(LatestSemaDiags, STDOUT_FILENO);
  return 0;
}

static void printSemanticInfo() {
  printAnnotations();
  if (sourcekitd_variant_get_type(LatestSemaDiags) != SOURCEKITD_VARIANT_TYPE_NULL)
    printDiags();
}

static void notification_receiver(sourcekitd_response_t resp) {
  if (sourcekitd_response_is_error(resp)) {
    sourcekitd_response_description_dump(resp);
    exit(1);
  }

  sourcekitd_variant_t payload = sourcekitd_response_get_value(resp);
  sourcekitd_uid_t note =
      sourcekitd_variant_dictionary_get_uid(payload, KeyNotification);

  if (note == NoteDocUpdate) {
    semaName = sourcekitd_variant_dictionary_get_string(payload, KeyName);

    sourcekitd_object_t edReq = sourcekitd_request_dictionary_create(nullptr,
                                                                nullptr, 0);
    sourcekitd_request_dictionary_set_uid(edReq, KeyRequest,
                                          RequestEditorReplaceText);
    sourcekitd_request_dictionary_set_string(edReq, KeyName, semaName);
    sourcekitd_request_dictionary_set_string(edReq, KeySourceText, "");
    semaResponse = sourcekitd_send_request_sync(edReq);
    sourcekitd_request_release(edReq);
    semaSemaphore.signal();
  } else if (note == NoteTest) {
    noteSyncSemaphore.signal();
  } else {
    notificationBuffer.add(resp);
  }
}

static void printNameTranslationInfo(sourcekitd_variant_t Info,
                                     llvm::raw_ostream &OS) {
  const char *InternalDiagnostic =
      sourcekitd_variant_dictionary_get_string(Info, KeyInternalDiagnostic);
  if (InternalDiagnostic) {
    OS << "<empty name translation info; internal diagnostic: \""
       << InternalDiagnostic << "\">\n";
    return;
  }
  sourcekitd_uid_t KindUID = sourcekitd_variant_dictionary_get_uid(Info,
                                                                   KeyNameKind);
  if (KindUID == nullptr) {
    OS << "<empty name translation info>\n";
    return;
  }
  const char *Kind = sourcekitd_uid_get_string_ptr(KindUID);
  const char *BaseName = sourcekitd_variant_dictionary_get_string(Info,
                                                                  KeyBaseName);
  std::vector<const char *> Selectors;
  sourcekitd_variant_t SelectorsObj =
    sourcekitd_variant_dictionary_get_value(Info, KeySelectorPieces);
  for (unsigned i = 0, e = sourcekitd_variant_array_get_count(SelectorsObj);
         i != e; ++i) {
    sourcekitd_variant_t Entry =
      sourcekitd_variant_array_get_value(SelectorsObj, i);
    Selectors.push_back(sourcekitd_variant_dictionary_get_string(Entry, KeyName));
  }

  bool IsZeroArgSelector = false;
  auto IsZeroArgObj = sourcekitd_variant_dictionary_get_value(Info, KeyIsZeroArgSelector);
  if (sourcekitd_variant_get_type(IsZeroArgObj) != SOURCEKITD_VARIANT_TYPE_NULL) {
    IsZeroArgSelector = sourcekitd_variant_int64_get_value(IsZeroArgObj);
  }

  std::vector<const char *> Args;
  sourcekitd_variant_t ArgsObj =
    sourcekitd_variant_dictionary_get_value(Info, KeyArgNames);
  for (unsigned i = 0, e = sourcekitd_variant_array_get_count(ArgsObj);
       i != e; ++i) {
    sourcekitd_variant_t Entry =
      sourcekitd_variant_array_get_value(ArgsObj, i);
    Args.push_back(sourcekitd_variant_dictionary_get_string(Entry, KeyName));
  }

  OS << Kind << "\n";
  OS << StringRef(BaseName);
  if (!Args.empty()) {
    OS << "(";
    for (auto A : Args) {
      StringRef Text(A);
      if (Text.empty())
        OS << "_" << ":";
      else
        OS << Text << ":";
    }
    OS << ")";
  }
  for (auto S : Selectors) {
    OS << S;
    if (!IsZeroArgSelector) {
      OS << ":";
    }
  }
  OS << '\n';
}

static void printCursorInfo(sourcekitd_variant_t Info, StringRef FilenameIn,
                            const llvm::StringMap<TestOptions::VFSFile> &VFSFiles,
                            llvm::raw_ostream &OS) {
  const char *InternalDiagnostic =
      sourcekitd_variant_dictionary_get_string(Info, KeyInternalDiagnostic);
  if (InternalDiagnostic) {
    OS << "<empty cursor info; internal diagnostic: \""
       << InternalDiagnostic << "\">\n";
    return;
  }
  sourcekitd_uid_t KindUID = sourcekitd_variant_dictionary_get_uid(Info,
                                      sourcekitd_uid_get_from_cstr("key.kind"));
  if (KindUID == nullptr) {
    OS << "<empty cursor info>\n";
    return;
  }

  std::string Filename = FilenameIn.str();
  llvm::SmallString<256> output;
  if (!llvm::sys::fs::real_path(Filename, output))
    Filename = std::string(output.str());

  const char *Kind = sourcekitd_uid_get_string_ptr(KindUID);
  const char *USR = sourcekitd_variant_dictionary_get_string(Info, KeyUSR);
  const char *Name = sourcekitd_variant_dictionary_get_string(Info, KeyName);
  const char *Typename = sourcekitd_variant_dictionary_get_string(Info,
                                                                  KeyTypeName);
  const char *TypeUsr = sourcekitd_variant_dictionary_get_string(Info,
                                                                 KeyTypeUsr);
  const char *ContainerTypeUsr = sourcekitd_variant_dictionary_get_string(Info,
                                                          KeyContainerTypeUsr);
  const char *ModuleName = sourcekitd_variant_dictionary_get_string(Info,
                                                              KeyModuleName);
  const char *GroupName = sourcekitd_variant_dictionary_get_string(Info,
                                                                   KeyGroupName);

  const char *LocalizationKey =
    sourcekitd_variant_dictionary_get_string(Info, KeyLocalizationKey);
  const char *ModuleInterfaceName =
      sourcekitd_variant_dictionary_get_string(Info, KeyModuleInterfaceName);
  const char *TypeInterface =
      sourcekitd_variant_dictionary_get_string(Info, KeyTypeInterface);
  bool IsSystem = sourcekitd_variant_dictionary_get_bool(Info, KeyIsSystem);
  const char *AnnotDecl = sourcekitd_variant_dictionary_get_string(Info,
                                                              KeyAnnotatedDecl);
  const char *FullAnnotDecl =
      sourcekitd_variant_dictionary_get_string(Info, KeyFullyAnnotatedDecl);
  const char *SymbolGraph =
      sourcekitd_variant_dictionary_get_string(Info, KeySymbolGraph);
  const char *DocFullAsXML =
      sourcekitd_variant_dictionary_get_string(Info, KeyDocFullAsXML);
  sourcekitd_variant_t OffsetObj =
      sourcekitd_variant_dictionary_get_value(Info, KeyOffset);
  llvm::Optional<int64_t> Offset;
  unsigned Length = 0;
  if (sourcekitd_variant_get_type(OffsetObj) != SOURCEKITD_VARIANT_TYPE_NULL) {
    Offset = sourcekitd_variant_int64_get_value(OffsetObj);
    Length = sourcekitd_variant_dictionary_get_int64(Info, KeyLength);
  }
  const char *FilePath = sourcekitd_variant_dictionary_get_string(Info, KeyFilePath);

  std::vector<const char *> OverrideUSRs;
  sourcekitd_variant_t OverridesObj =
      sourcekitd_variant_dictionary_get_value(Info, KeyOverrides);
  for (unsigned i = 0, e = sourcekitd_variant_array_get_count(OverridesObj);
         i != e; ++i) {
    sourcekitd_variant_t Entry =
      sourcekitd_variant_array_get_value(OverridesObj, i);
    OverrideUSRs.push_back(sourcekitd_variant_dictionary_get_string(Entry, KeyUSR));
  }

  std::vector<const char *> GroupNames;
  sourcekitd_variant_t GroupObj =
    sourcekitd_variant_dictionary_get_value(Info, KeyModuleGroups);
  for (unsigned i = 0, e = sourcekitd_variant_array_get_count(GroupObj);
       i != e; ++i) {
    sourcekitd_variant_t Entry =
    sourcekitd_variant_array_get_value(GroupObj, i);
    GroupNames.push_back(sourcekitd_variant_dictionary_get_string(Entry, KeyGroupName));
  }

  std::vector<const char *> RelatedDecls;
  sourcekitd_variant_t RelatedDeclsObj =
  sourcekitd_variant_dictionary_get_value(Info, KeyRelatedDecls);
  for (unsigned i = 0, e = sourcekitd_variant_array_get_count(RelatedDeclsObj);
       i != e; ++i) {
    sourcekitd_variant_t Entry =
    sourcekitd_variant_array_get_value(RelatedDeclsObj, i);
    RelatedDecls.push_back(sourcekitd_variant_dictionary_get_string(Entry,
                                                             KeyAnnotatedDecl));
  }

  struct ActionInfo {
    const char* KindUID;
    const char* KindName;
    const char* UnavailReason;
  };
  std::vector<ActionInfo> AvailableActions;
  sourcekitd_variant_t ActionsObj =
  sourcekitd_variant_dictionary_get_value(Info, KeyRefactorActions);
  for (unsigned i = 0, e = sourcekitd_variant_array_get_count(ActionsObj);
       i != e; ++i) {
    sourcekitd_variant_t Entry =
    sourcekitd_variant_array_get_value(ActionsObj, i);
    AvailableActions.push_back({
      sourcekitd_uid_get_string_ptr(sourcekitd_variant_dictionary_get_uid(Entry,
                                                                KeyActionUID)),
      sourcekitd_variant_dictionary_get_string(Entry, KeyActionName),
      sourcekitd_variant_dictionary_get_string(Entry, KeyActionUnavailableReason)
    });
  }

  uint64_t ParentOffset =
    sourcekitd_variant_dictionary_get_int64(Info, KeyParentLoc);

  OS << Kind << " (";
  if (Offset.hasValue()) {
    if (Filename != FilePath)
      OS << FilePath << ":";
    auto LineCol = resolveToLineCol(Offset.getValue(), FilePath, VFSFiles);
    OS << LineCol.first << ':' << LineCol.second;
    auto EndLineCol =
        resolveToLineCol(Offset.getValue() + Length, FilePath, VFSFiles);
    OS << '-' << EndLineCol.first << ':' << EndLineCol.second;
  }
  OS << ")\n";
  OS << Name << '\n';
  if (USR)
    OS << USR << '\n';
  if (Typename)
    OS << Typename << '\n';
  if (TypeUsr)
    OS << TypeUsr << '\n';
  if (ContainerTypeUsr)
    OS << "<Container>" << ContainerTypeUsr << "</Container>" << '\n';
  if (ModuleName)
    OS << ModuleName << '\n';
  if (GroupName)
    OS << "<Group>" << GroupName << "</Group>" << '\n';
  if (ModuleInterfaceName)
    OS << ModuleInterfaceName << '\n';
  if (IsSystem)
    OS << "SYSTEM\n";
  if (AnnotDecl)
    OS << AnnotDecl << '\n';
  if (FullAnnotDecl)
    OS << FullAnnotDecl << '\n';
  if (DocFullAsXML)
    OS << DocFullAsXML << '\n';
  if (LocalizationKey) {
    OS << "<LocalizationKey>" << LocalizationKey;
    OS << "</LocalizationKey>" << '\n';
  }
  if (SymbolGraph) {
    OS << "SYMBOL GRAPH BEGIN\n";
    if (auto Val = json::parse(StringRef(SymbolGraph))) {
      OS << formatv("{0:2}", Val.get());
    } else {
      OS << SymbolGraph;
    }
    OS << "\nSYMBOL GRAPH END\n";
  }
  OS << "OVERRIDES BEGIN\n";
  for (auto OverUSR : OverrideUSRs)
    OS << OverUSR << '\n';
  OS << "OVERRIDES END\n";
  OS << "RELATED BEGIN\n";
  for (auto RelDecl : RelatedDecls)
    OS << RelDecl << '\n';
  OS << "RELATED END\n";
  OS << "TYPE INTERFACE BEGIN\n";
  if (TypeInterface)
    OS << TypeInterface << '\n';
  OS << "TYPE INTERFACE END\n";
  OS << "MODULE GROUPS BEGIN\n";
  for (auto Group : GroupNames)
    OS << Group << '\n';
  OS << "MODULE GROUPS END\n";
  OS << "ACTIONS BEGIN\n";
  for (auto Action : AvailableActions) {
    OS << Action.KindUID << '\n';
    OS << Action.KindName << '\n';
    if (Action.UnavailReason) {
      OS << Action.UnavailReason << '\n';
    }
  }
  OS << "ACTIONS END\n";
  if (ParentOffset) {
    OS << "PARENT OFFSET: " << ParentOffset << "\n";
  }
}

static void printRangeInfo(sourcekitd_variant_t Info, StringRef FilenameIn,
                            llvm::raw_ostream &OS) {
  sourcekitd_uid_t KindUID = sourcekitd_variant_dictionary_get_uid(Info,
                                      sourcekitd_uid_get_from_cstr("key.kind"));
  if (KindUID == nullptr) {
    OS << "<empty range info>\n";
    return;
  }

  std::string Filename = FilenameIn.str();
  llvm::SmallString<256> output;
  if (llvm::sys::fs::real_path(Filename, output))
    Filename = std::string(output.str());

  sourcekitd_variant_t OffsetObj =
    sourcekitd_variant_dictionary_get_value(Info, KeyOffset);
  llvm::Optional<int64_t> Offset;
  if (sourcekitd_variant_get_type(OffsetObj) != SOURCEKITD_VARIANT_TYPE_NULL) {
    Offset = sourcekitd_variant_int64_get_value(OffsetObj);
  }
  const char *Kind = sourcekitd_uid_get_string_ptr(KindUID);
  const char *Typename = sourcekitd_variant_dictionary_get_string(Info,
                                                                  KeyTypeName);

  const char *RangeContent = sourcekitd_variant_dictionary_get_string(Info,
                                                              KeyRangeContent);
  OS << "<kind>" << Kind << "</kind>\n";
  OS << "<content>" <<RangeContent << "</content>\n";
  if (Typename)
    OS << "<type>" <<Typename << "</type>\n";
}

static void printExpressionType(sourcekitd_variant_t Info, llvm::raw_ostream &OS) {
  auto TypeBuffer = sourcekitd_variant_dictionary_get_value(Info, KeyExpressionTypeList);
  unsigned Count = sourcekitd_variant_array_get_count(TypeBuffer);
  if (!Count) {
    OS << "cannot find expression types in the file\n";
    return;
  }
  OS << "<ExpressionTypes>\n";
  for (unsigned i = 0; i != Count; ++i) {
    sourcekitd_variant_t Item = sourcekitd_variant_array_get_value(TypeBuffer, i);
    unsigned Offset = sourcekitd_variant_dictionary_get_int64(Item, KeyExpressionOffset);
    unsigned Length = sourcekitd_variant_dictionary_get_int64(Item, KeyExpressionLength);
    OS << "(" << Offset << ", " << Offset + Length << "): " <<
      sourcekitd_variant_dictionary_get_string(Item, KeyExpressionType) << "\n";
    sourcekitd_variant_t protocols = sourcekitd_variant_dictionary_get_value(Item,
      KeyExpectedTypes);
    unsigned Count = sourcekitd_variant_array_get_count(protocols);
    for (unsigned i = 0; i != Count; i ++) {
      OS << "conforming to: " << sourcekitd_variant_array_get_string(protocols, i) << "\n";
    }
  }
  OS << "</ExpressionTypes>\n";
}

static void printFoundInterface(sourcekitd_variant_t Info,
                                llvm::raw_ostream &OS) {
  const char *Name = sourcekitd_variant_dictionary_get_string(Info,
                                                        KeyModuleInterfaceName);
  OS << "DOC: (";
  if (Name)
    OS << Name;
  OS << ")\n";

  sourcekitd_variant_t ArgObj =
      sourcekitd_variant_dictionary_get_value(Info, KeyCompilerArgs);

  OS << "ARGS: [";
  if (sourcekitd_variant_get_type(ArgObj) != SOURCEKITD_VARIANT_TYPE_NULL) {
    for (unsigned i = 0, e = sourcekitd_variant_array_get_count(ArgObj);
           i != e; ++i) {
      OS << sourcekitd_variant_array_get_string(ArgObj, i);
      OS << ' ';
    }
  }
  OS << "]\n";
}

static void printFoundUSR(sourcekitd_variant_t Info,
                          llvm::MemoryBuffer *SourceBuf,
                          llvm::raw_ostream &OS) {
  sourcekitd_variant_t OffsetObj =
      sourcekitd_variant_dictionary_get_value(Info, KeyOffset);
  llvm::Optional<int64_t> Offset;
  if (sourcekitd_variant_get_type(OffsetObj) != SOURCEKITD_VARIANT_TYPE_NULL)
    Offset = sourcekitd_variant_int64_get_value(OffsetObj);

  if (!Offset.hasValue()) {
    OS << "USR NOT FOUND\n";
    return;
  }

  int64_t Length = sourcekitd_variant_dictionary_get_int64(Info, KeyLength);

  auto LineCol1 = resolveToLineCol(Offset.getValue(), SourceBuf);
  auto LineCol2 = resolveToLineCol(Offset.getValue() + Length, SourceBuf);
  OS << '(' << LineCol1.first << ':' << LineCol1.second << '-'
            << LineCol2.first << ':' << LineCol2.second << ")\n";
}

static void printNormalizedDocComment(sourcekitd_variant_t Info) {
  sourcekitd_variant_t Source =
    sourcekitd_variant_dictionary_get_value(Info, KeySourceText);
  sourcekitd_variant_description_dump_filedesc(Source, STDOUT_FILENO);
}

static void printDocInfo(sourcekitd_variant_t Info, StringRef Filename) {
  const char *text =
      sourcekitd_variant_dictionary_get_string(Info, KeySourceText);
  llvm::raw_fd_ostream OS(STDOUT_FILENO, /*shouldClose=*/false);
  if (text) {
    OS << text << '\n';
    OS.flush();
  }

  sourcekitd_variant_t annotations =
      sourcekitd_variant_dictionary_get_value(Info, KeyAnnotations);
  sourcekitd_variant_t entities =
      sourcekitd_variant_dictionary_get_value(Info,
                                  sourcekitd_uid_get_from_cstr("key.entities"));
  sourcekitd_variant_t diags =
      sourcekitd_variant_dictionary_get_value(Info, KeyDiagnostics);

  sourcekitd_variant_description_dump_filedesc(annotations, STDOUT_FILENO);
  sourcekitd_variant_description_dump_filedesc(entities, STDOUT_FILENO);

  if (sourcekitd_variant_get_type(diags) != SOURCEKITD_VARIANT_TYPE_NULL)
    sourcekitd_variant_description_dump_filedesc(diags, STDOUT_FILENO);
}

static void checkTextIsASCII(const char *Text) {
  for (const char *p = Text; *p; ++p) {
    if (*p & 0x80) {
      auto LineCol = resolveToLineColFromBuf(p - Text, Text);

      llvm::errs() << "!!Interface text is non-ascii!!\n"
                   << "@ " << LineCol.first << ":" << LineCol.second << "\n";
      exit(1);
    }
  }
}

static void printModuleGroupNames(sourcekitd_variant_t Info,
                                  llvm::raw_ostream &OS) {
  sourcekitd_variant_t Groups =
    sourcekitd_variant_dictionary_get_value(Info, KeyModuleGroups);
  OS << "<GROUPS>\n";
  for (unsigned i = 0, e = sourcekitd_variant_array_get_count(Groups);
       i != e; ++i) {
    sourcekitd_variant_t Entry =
    sourcekitd_variant_array_get_value(Groups, i);
    OS << sourcekitd_variant_dictionary_get_string(Entry, KeyGroupName) << "\n";
  }
  OS << "<\\GROUPS>\n";
}

static StringRef getLineColRange(StringRef Text, int64_t StartLine,
                                 int64_t StartCol, int64_t EndLine,
                                 int64_t EndCol) {
  unsigned Line = 1;
  size_t Length = 0;

  while (Line < StartLine) {
    Text = Text.split('\n').second;
    ++Line;
  }
  Text = Text.drop_front(StartCol - 1);
  if (StartLine == EndLine)
    return Text.substr(0, EndCol - StartCol);

  while(Line < EndLine) {
    Length = Text.find('\n', Length) + 1;
    ++Line;
  }
  Length += EndCol - 1;

  return Text.substr(0, Length);
}

static void printSyntacticRenameEdits(sourcekitd_variant_t Info,
                                      llvm::raw_ostream &OS) {
  sourcekitd_variant_t CategorizedEdits =
    sourcekitd_variant_dictionary_get_value(Info, KeyCategorizedEdits);
  for (unsigned i = 0, e = sourcekitd_variant_array_get_count(CategorizedEdits);
       i != e; ++i) {
    sourcekitd_variant_t
    Categorized = sourcekitd_variant_array_get_value(CategorizedEdits, i);
    sourcekitd_uid_t
    Category = sourcekitd_variant_dictionary_get_uid(Categorized, KeyCategory);
    OS << sourcekitd_uid_get_string_ptr(Category) << ":\n";

    sourcekitd_variant_t Edits =
    sourcekitd_variant_dictionary_get_value(Categorized, KeyEdits);
    for(unsigned j = 0, je = sourcekitd_variant_array_get_count(Edits);
        j != je; ++j) {
      OS << "  "; // indent
      sourcekitd_variant_t Edit = sourcekitd_variant_array_get_value(Edits, j);
      int64_t Line = sourcekitd_variant_dictionary_get_int64(Edit, KeyLine);
      int64_t Column = sourcekitd_variant_dictionary_get_int64(Edit, KeyColumn);
      int64_t EndLine = sourcekitd_variant_dictionary_get_int64(Edit, KeyEndLine);
      int64_t EndColumn = sourcekitd_variant_dictionary_get_int64(Edit, KeyEndColumn);
      OS << Line << ':' << Column << '-' << EndLine << ':' << EndColumn << " \"";
      StringRef Text(sourcekitd_variant_dictionary_get_string(Edit, KeyText));
      OS << Text << "\"\n";
      sourcekitd_variant_t NoteRanges =
        sourcekitd_variant_dictionary_get_value(Edit, KeyRangesWorthNote);
      if (unsigned e = sourcekitd_variant_array_get_count(NoteRanges)) {
        for (unsigned i = 0; i != e; ++i) {
          OS << "  <note>";
          sourcekitd_variant_t Note =
            sourcekitd_variant_array_get_value(NoteRanges, i);
          int64_t Line = sourcekitd_variant_dictionary_get_int64(Note, KeyLine);
          int64_t Column = sourcekitd_variant_dictionary_get_int64(Note, KeyColumn);
          int64_t EndLine = sourcekitd_variant_dictionary_get_int64(Note, KeyEndLine);
          int64_t EndColumn = sourcekitd_variant_dictionary_get_int64(Note, KeyEndColumn);
          auto index = sourcekitd_variant_dictionary_get_value(Note, KeyArgIndex);
          sourcekitd_uid_t Kind = sourcekitd_variant_dictionary_get_uid(Note,
                                                              KeyKind);
          StringRef NoteText = getLineColRange(Text, Line, Column, EndLine, EndColumn);
          OS << sourcekitd_uid_get_string_ptr(Kind) << " ";
          OS << Line << ":" << Column << "-" << EndLine << ":" << EndColumn;
          if (sourcekitd_variant_get_type(index) != SOURCEKITD_VARIANT_TYPE_NULL) {
            OS << " arg-index=" << sourcekitd_variant_int64_get_value(index);
          }
          OS << " \"" << NoteText << "\"";
          OS << "</note>\n";
        }
      }
    }
  }
}

static void printRenameRanges(sourcekitd_variant_t Info,
                              llvm::raw_ostream &OS) {
  sourcekitd_variant_t CategorizedRanges =
      sourcekitd_variant_dictionary_get_value(Info, KeyCategorizedRanges);
  sourcekitd_variant_array_apply(CategorizedRanges, ^bool(
                                     size_t i,
                                     sourcekitd_variant_t Categorized) {
    sourcekitd_uid_t Category =
        sourcekitd_variant_dictionary_get_uid(Categorized, KeyCategory);
    OS << sourcekitd_uid_get_string_ptr(Category) << ":\n";

    sourcekitd_variant_t Ranges =
        sourcekitd_variant_dictionary_get_value(Categorized, KeyRanges);
    sourcekitd_variant_array_apply(Ranges, ^bool(size_t j,
                                                 sourcekitd_variant_t Range) {

      OS << "  "; // indent
      int64_t Line = sourcekitd_variant_dictionary_get_int64(Range, KeyLine);
      int64_t Column =
          sourcekitd_variant_dictionary_get_int64(Range, KeyColumn);
      int64_t EndLine =
          sourcekitd_variant_dictionary_get_int64(Range, KeyEndLine);
      int64_t EndColumn =
          sourcekitd_variant_dictionary_get_int64(Range, KeyEndColumn);
      OS << Line << ':' << Column << '-' << EndLine << ':' << EndColumn << " ";
      auto Kind = sourcekitd_variant_dictionary_get_uid(Range, KeyKind);
      OS << sourcekitd_uid_get_string_ptr(Kind);
      auto index = sourcekitd_variant_dictionary_get_value(Range, KeyArgIndex);
      if (sourcekitd_variant_get_type(index) != SOURCEKITD_VARIANT_TYPE_NULL) {
        OS << " arg-index=" << sourcekitd_variant_int64_get_value(index);
      }
      OS << "\n";
      return true;
    });
    return true;
  });
}

static void printInterfaceGen(sourcekitd_variant_t Info, bool CheckASCII) {
  const char *text =
      sourcekitd_variant_dictionary_get_string(Info, KeySourceText);

  if (text) {
    llvm::raw_fd_ostream OS(STDOUT_FILENO, /*shouldClose=*/false);
    OS << text << '\n';
  }

  if (CheckASCII) {
    checkTextIsASCII(text);
  }

  sourcekitd_variant_t syntaxmap =
      sourcekitd_variant_dictionary_get_value(Info, KeySyntaxMap);
  sourcekitd_variant_description_dump_filedesc(syntaxmap, STDOUT_FILENO);
  sourcekitd_variant_t annotations =
      sourcekitd_variant_dictionary_get_value(Info, KeyAnnotations);
  sourcekitd_variant_description_dump_filedesc(annotations, STDOUT_FILENO);
  sourcekitd_variant_t structure =
      sourcekitd_variant_dictionary_get_value(Info, KeySubStructure);
  sourcekitd_variant_description_dump_filedesc(structure, STDOUT_FILENO);
}

static void printRelatedIdents(sourcekitd_variant_t Info, StringRef Filename,
                               const llvm::StringMap<TestOptions::VFSFile> &VFSFiles,
                               llvm::raw_ostream &OS) {
  OS << "START RANGES\n";
  sourcekitd_variant_t Res =
      sourcekitd_variant_dictionary_get_value(Info, KeyResults);
  for (unsigned i=0, e = sourcekitd_variant_array_get_count(Res); i != e; ++i) {
    sourcekitd_variant_t Range = sourcekitd_variant_array_get_value(Res, i);
    int64_t Offset = sourcekitd_variant_dictionary_get_int64(Range, KeyOffset);
    int64_t Length = sourcekitd_variant_dictionary_get_int64(Range, KeyLength);
    auto LineCol = resolveToLineCol(Offset, Filename, VFSFiles);
    OS << LineCol.first << ':' << LineCol.second << " - " << Length << '\n';
  }
  OS << "END RANGES\n";
}

static void prepareDemangleRequest(sourcekitd_object_t Req,
                                   const TestOptions &Opts) {
  sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestDemangle);
  if (Opts.SimplifiedDemangling)
    sourcekitd_request_dictionary_set_int64(Req, KeySimplified, 1);
  sourcekitd_object_t arr = sourcekitd_request_array_create(nullptr, 0);
  sourcekitd_request_dictionary_set_value(Req, KeyNames, arr);

  auto addName = [&](StringRef MangledName) {
    sourcekitd_request_array_set_stringbuf(arr, SOURCEKITD_ARRAY_APPEND,
                                        MangledName.data(), MangledName.size());
  };

  if (Opts.Inputs.empty()) {
    auto input = llvm::MemoryBuffer::getSTDIN();
    if (!input) {
      llvm::errs() << input.getError().message() << '\n';
      ::exit(1);
    }
    llvm::StringRef inputContents = input.get()->getBuffer();

    // This doesn't handle Unicode symbols, but maybe that's okay.
    // Also accept the future mangling prefix.
    llvm::Regex maybeSymbol("(_T|_?\\$[Ss])[_a-zA-Z0-9$.]+");
    llvm::SmallVector<llvm::StringRef, 1> matches;
    while (maybeSymbol.match(inputContents, &matches)) {
      addName(matches.front());
      auto offset = matches.front().data() - inputContents.data();
      inputContents = inputContents.substr(offset + matches.front().size());
    }

  } else {
    for (llvm::StringRef name : Opts.Inputs) {
      addName(name);
    }
  }

  sourcekitd_request_release(arr);
}

static void prepareMangleRequest(sourcekitd_object_t Req,
                                 const TestOptions &Opts) {
  sourcekitd_request_dictionary_set_uid(Req, KeyRequest, RequestMangleSimpleClass);
  sourcekitd_object_t arr = sourcekitd_request_array_create(nullptr, 0);
  sourcekitd_request_dictionary_set_value(Req, KeyNames, arr);

  auto addPair = [&](StringRef ModuleName, StringRef ClassName) {
    sourcekitd_object_t pair =
      sourcekitd_request_dictionary_create(nullptr, nullptr, 0);
    sourcekitd_request_dictionary_set_stringbuf(pair, KeyModuleName,
                                          ModuleName.data(), ModuleName.size());
    sourcekitd_request_dictionary_set_stringbuf(pair, KeyName,
                                            ClassName.data(), ClassName.size());
    sourcekitd_request_array_set_value(arr, SOURCEKITD_ARRAY_APPEND, pair);
    sourcekitd_request_release(pair);
  };

  for (StringRef pair : Opts.Inputs) {
    auto Idx = pair.find('.');
    if (Idx == StringRef::npos) {
      errs() << "expected pairs with format '<module>.<class name>'\n";
      ::exit(1);
    }
    StringRef moduleName = pair.substr(0, Idx);
    StringRef className = pair.substr(Idx+1);
    addPair(moduleName, className);
  }

  sourcekitd_request_release(arr);
}

static void printDemangleResults(sourcekitd_variant_t Info, raw_ostream &OS) {
  OS << "START DEMANGLE\n";
  sourcekitd_variant_t results =
    sourcekitd_variant_dictionary_get_value(Info, KeyResults);
  sourcekitd_variant_array_apply(results, ^bool(size_t index, sourcekitd_variant_t value) {
    StringRef name = sourcekitd_variant_dictionary_get_string(value, KeyName);
    if (name.empty())
      OS << "<empty>";
    else
      OS << name;
    OS << '\n';
    return true;
  });
  OS << "END DEMANGLE\n";
}

static void printMangleResults(sourcekitd_variant_t Info, raw_ostream &OS) {
  OS << "START MANGLE\n";
  sourcekitd_variant_t results =
    sourcekitd_variant_dictionary_get_value(Info, KeyResults);
  sourcekitd_variant_array_apply(results, ^bool(size_t index, sourcekitd_variant_t value) {
    StringRef name = sourcekitd_variant_dictionary_get_string(value, KeyName);
    if (name.empty())
      OS << "<empty>";
    else
      OS << name;
    OS << '\n';
    return true;
  });
  OS << "END MANGLE\n";
}

static void printStatistics(sourcekitd_variant_t Info, raw_ostream &OS) {
  sourcekitd_variant_t results =
    sourcekitd_variant_dictionary_get_value(Info, KeyResults);
  sourcekitd_variant_array_apply(results, ^bool(size_t index, sourcekitd_variant_t value) {
    auto uid = sourcekitd_variant_dictionary_get_uid(value, KeyKind);
    auto desc = sourcekitd_variant_dictionary_get_string(value, KeyDescription);
    auto statValue = sourcekitd_variant_dictionary_get_int64(value, KeyValue);
    OS << statValue << "\t" << desc << "\t- " << sourcekitd_uid_get_string_ptr(uid) << "\n";
    return true;
  });
}

static std::string initializeSource(StringRef Input) {
  std::string result;
  {
    llvm::raw_string_ostream OS(result);
    StringRef CheckStr = "CHECK";
    size_t Pos = 0;
    while (true) {
      auto checkPos = Input.find(CheckStr, Pos);
      if (checkPos == StringRef::npos)
        break;
      checkPos = Input.substr(0, checkPos).rfind("//");
      assert(checkPos != StringRef::npos);
      size_t EndLine = Input.find('\n', checkPos);
      assert(EndLine != StringRef::npos);
      ++EndLine;
      OS << Input.slice(Pos, checkPos);
      Pos = EndLine;
    }

    OS << Input.slice(Pos, StringRef::npos);
  }
  return result;
}

static Optional<std::pair<unsigned, unsigned>>
firstPlaceholderRange(StringRef Source, unsigned from) {
  const char *StartPtr = Source.data();
  Source = Source.drop_front(from);

  while (true) {
    size_t Pos = Source.find("<#");
    if (Pos == StringRef::npos)
      break;
    unsigned OffsetStart = Source.data() + Pos - StartPtr;
    Source = Source.substr(Pos+2);
    if (Source.startswith("__skip__") || Source.startswith("T##__skip__"))
      continue;
    Pos = Source.find("#>");
    if (Pos == StringRef::npos)
      break;
    unsigned OffsetEnd = Source.data() + Pos + 2 - StartPtr;
    Source = Source.substr(Pos+2);
    return std::make_pair(OffsetStart, OffsetEnd-OffsetStart);
  }
  return llvm::None;
}

static void expandPlaceholders(llvm::MemoryBuffer *SourceBuf,
                               llvm::raw_ostream &OS) {
  auto syncEdit = [=](unsigned offset, unsigned length, const char *text) {
    auto SourceBufID = SourceBuf->getBufferIdentifier();
    auto req = sourcekitd_request_dictionary_create(nullptr, nullptr, 0);
    sourcekitd_request_dictionary_set_uid(req, KeyRequest,
                                          RequestEditorReplaceText);
    sourcekitd_request_dictionary_set_stringbuf(req, KeyName,
                                                SourceBufID.data(),
                                                SourceBufID.size());
    sourcekitd_request_dictionary_set_int64(req, KeyOffset, offset);
    sourcekitd_request_dictionary_set_int64(req, KeyLength, length);
    sourcekitd_request_dictionary_set_string(req, KeySourceText, text);

    sourcekitd_response_t resp = sourcekitd_send_request_sync(req);
    if (sourcekitd_response_is_error(resp)) {
      sourcekitd_response_description_dump(resp);
      exit(1);
    }
    sourcekitd_request_release(req);
    sourcekitd_response_dispose(resp);
  };

  std::string source = initializeSource(SourceBuf->getBuffer());
  // Sync contents with modified source.
  syncEdit(0, SourceBuf->getBuffer().size(), source.c_str());

  unsigned cursor = 0;

  while (auto Range = firstPlaceholderRange(source, cursor)) {
    unsigned Offset = Range->first;
    unsigned Length = Range->second;
    sourcekitd_object_t Exp = sourcekitd_request_dictionary_create(nullptr,
                                                                   nullptr, 0);
    sourcekitd_request_dictionary_set_uid(Exp, KeyRequest,
                                          RequestEditorExpandPlaceholder);
    auto SourceBufID = SourceBuf->getBufferIdentifier();
    sourcekitd_request_dictionary_set_stringbuf(Exp, KeyName,
                                                SourceBufID.data(),
                                                SourceBufID.size());
    sourcekitd_request_dictionary_set_string(Exp, KeySourceText, "");
    sourcekitd_request_dictionary_set_int64(Exp, KeyOffset, Offset);
    sourcekitd_request_dictionary_set_int64(Exp, KeyLength, Length);

    sourcekitd_response_t Resp = sourcekitd_send_request_sync(Exp);
    if (sourcekitd_response_is_error(Resp)) {
      sourcekitd_response_description_dump(Resp);
      exit(1);
    }
    sourcekitd_request_release(Exp);
    sourcekitd_variant_t Info = sourcekitd_response_get_value(Resp);
    const char *Text = sourcekitd_variant_dictionary_get_string(Info, KeySourceText);
    if (!Text) {
      cursor = Offset + Length;
      sourcekitd_response_dispose(Resp);
      continue;
    }
    unsigned EditOffset = sourcekitd_variant_dictionary_get_int64(Info, KeyOffset);
    unsigned EditLength = sourcekitd_variant_dictionary_get_int64(Info, KeyLength);

    // Apply edit locally.
    source.replace(EditOffset, EditLength, Text);

    // Apply edit on server.
    syncEdit(EditOffset, EditLength, Text);

    // Adjust cursor to after the edit (we do not expand recursively).
    cursor = EditOffset + strlen(Text);
    sourcekitd_response_dispose(Resp);
  }

  OS << source;
}

static std::pair<unsigned, unsigned>
resolveToLineCol(unsigned Offset, StringRef Filename,
                 const llvm::StringMap<TestOptions::VFSFile> &VFSFiles) {
  return resolveToLineCol(Offset, getBufferForFilename(Filename, VFSFiles));
}

static std::pair<unsigned, unsigned>
resolveToLineCol(unsigned Offset, llvm::MemoryBuffer *InputBuf) {
  if (Offset >= InputBuf->getBufferSize()) {
    llvm::errs() << "offset " << Offset << " for filename '"
        << InputBuf->getBufferIdentifier() << "' is too large\n";
    exit(1);
  }
  return resolveToLineColFromBuf(Offset, InputBuf->getBufferStart());
}

static std::pair<unsigned, unsigned>
resolveToLineColFromBuf(unsigned Offset, const char *Ptr) {
  const char *End = Ptr+Offset;

  unsigned Line = 1;
  const char *LineStart = Ptr;
  for (; Ptr < End; ++Ptr) {
    if (*Ptr == '\n') {
      ++Line;
      LineStart = Ptr+1;
    }
  }
  unsigned Col = Ptr-LineStart + 1;

  return { Line, Col };
}

static unsigned
resolveFromLineCol(unsigned Line, unsigned Col, StringRef Filename,
                   const llvm::StringMap<TestOptions::VFSFile> &VFSFiles) {
  return resolveFromLineCol(Line, Col,
                            getBufferForFilename(Filename, VFSFiles));
}

static unsigned resolveFromLineCol(unsigned Line, unsigned Col,
                                   llvm::MemoryBuffer *InputBuf) {
  if (Line == 0 || Col == 0) {
    llvm::errs() << "wrong pos format, line/col should start from 1\n";
    exit(1);
  }

  const char *Ptr = InputBuf->getBufferStart();
  const char *End = InputBuf->getBufferEnd();
  const char *LineStart = Ptr;
  --Line;
  for (; Line && (Ptr < End); ++Ptr) {
    if (*Ptr == '\n') {
      --Line;
      LineStart = Ptr+1;
    }
  }
  if (Line != 0) {
    llvm::errs() << "wrong pos format, line too large\n";
    exit(1);
  }
  Ptr = LineStart;
  for (; Ptr <= End; ++Ptr) {
    --Col;
    if (Col == 0)
      return Ptr - InputBuf->getBufferStart();
    if (*Ptr == '\n')
      break;
  }

  llvm::errs() << "wrong pos format, column too large\n";
  exit(1);
}

static llvm::StringMap<llvm::MemoryBuffer*> Buffers;

static llvm::MemoryBuffer *
getBufferForFilename(StringRef Filename,
                     const llvm::StringMap<TestOptions::VFSFile> &VFSFiles) {
  auto VFSFileIt = VFSFiles.find(Filename);
  auto MappedFilename =
      VFSFileIt == VFSFiles.end() ? Filename : StringRef(VFSFileIt->second.path);

  auto It = Buffers.find(MappedFilename);
  if (It != Buffers.end())
    return It->second;

  auto FileBufOrErr = llvm::MemoryBuffer::getFile(MappedFilename);
  if (!FileBufOrErr) {
    llvm::errs() << "error opening input file '" << MappedFilename << "' ("
                 << FileBufOrErr.getError().message() << ")\n";
    exit(1);
  }

  return Buffers[MappedFilename] = FileBufOrErr.get().release();
}
