//===--- 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"

#include "SourceKit/Support/Concurrency.h"
#include "TestOptions.h"
#include "swift/Demangling/ManglingMacros.h"
#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) {
  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();
}
