[clang-tools-extra] r336549 - [clangd] Remove JSON library in favor of llvm/Support/JSON

Sam McCall via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 9 07:25:59 PDT 2018


Author: sammccall
Date: Mon Jul  9 07:25:59 2018
New Revision: 336549

URL: http://llvm.org/viewvc/llvm-project?rev=336549&view=rev
Log:
[clangd] Remove JSON library in favor of llvm/Support/JSON

Summary:
The library has graduated from clangd to llvm/Support.
This is a mechanical change to move to the new API and remove the old one.

Main API changes:
 - namespace clang::clangd::json --> llvm::json
 - json::Expr --> json::Value
 - Expr::asString() etc --> Value::getAsString() etc
 - unsigned longs need a cast (due to r336541 adding lossless integer support)

Reviewers: ilya-biryukov

Subscribers: mgorny, ioeric, MaskRay, jkorous, omtcyfz, cfe-commits

Differential Revision: https://reviews.llvm.org/D49077

Removed:
    clang-tools-extra/trunk/clangd/JSONExpr.cpp
    clang-tools-extra/trunk/clangd/JSONExpr.h
    clang-tools-extra/trunk/unittests/clangd/JSONExprTests.cpp
Modified:
    clang-tools-extra/trunk/clangd/CMakeLists.txt
    clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
    clang-tools-extra/trunk/clangd/CodeComplete.cpp
    clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp
    clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h
    clang-tools-extra/trunk/clangd/Protocol.cpp
    clang-tools-extra/trunk/clangd/Protocol.h
    clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp
    clang-tools-extra/trunk/clangd/Trace.cpp
    clang-tools-extra/trunk/clangd/Trace.h
    clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt

Modified: clang-tools-extra/trunk/clangd/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CMakeLists.txt?rev=336549&r1=336548&r2=336549&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clangd/CMakeLists.txt Mon Jul  9 07:25:59 2018
@@ -23,7 +23,6 @@ add_clang_library(clangDaemon
   FuzzyMatch.cpp
   GlobalCompilationDatabase.cpp
   Headers.cpp
-  JSONExpr.cpp
   JSONRPCDispatcher.cpp
   Logger.cpp
   Protocol.cpp

Modified: clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp?rev=336549&r1=336548&r2=336549&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp Mon Jul  9 07:25:59 2018
@@ -18,6 +18,7 @@
 
 using namespace clang::clangd;
 using namespace clang;
+using namespace llvm;
 
 namespace {
 
@@ -87,25 +88,25 @@ void ClangdLSPServer::onInitialize(Initi
     }
   }
 
-  reply(json::obj{
+  reply(json::Object{
       {{"capabilities",
-        json::obj{
+        json::Object{
             {"textDocumentSync", (int)TextDocumentSyncKind::Incremental},
             {"documentFormattingProvider", true},
             {"documentRangeFormattingProvider", true},
             {"documentOnTypeFormattingProvider",
-             json::obj{
+             json::Object{
                  {"firstTriggerCharacter", "}"},
                  {"moreTriggerCharacter", {}},
              }},
             {"codeActionProvider", true},
             {"completionProvider",
-             json::obj{
+             json::Object{
                  {"resolveProvider", false},
                  {"triggerCharacters", {".", ">", ":"}},
              }},
             {"signatureHelpProvider",
-             json::obj{
+             json::Object{
                  {"triggerCharacters", {"(", ","}},
              }},
             {"definitionProvider", true},
@@ -115,7 +116,7 @@ void ClangdLSPServer::onInitialize(Initi
             {"documentSymbolProvider", true},
             {"workspaceSymbolProvider", true},
             {"executeCommandProvider",
-             json::obj{
+             json::Object{
                  {"commands", {ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND}},
              }},
         }}}});
@@ -212,7 +213,7 @@ void ClangdLSPServer::onWorkspaceSymbol(
         for (auto &Sym : *Items)
           Sym.kind = adjustKindToCapability(Sym.kind, SupportedSymbolKinds);
 
-        reply(json::ary(*Items));
+        reply(json::Array(*Items));
       });
 }
 
@@ -258,7 +259,7 @@ void ClangdLSPServer::onDocumentOnTypeFo
 
   auto ReplacementsOrError = Server.formatOnType(*Code, File, Params.position);
   if (ReplacementsOrError)
-    reply(json::ary(replacementsToEdits(*Code, ReplacementsOrError.get())));
+    reply(json::Array(replacementsToEdits(*Code, ReplacementsOrError.get())));
   else
     replyError(ErrorCode::UnknownErrorCode,
                llvm::toString(ReplacementsOrError.takeError()));
@@ -274,7 +275,7 @@ void ClangdLSPServer::onDocumentRangeFor
 
   auto ReplacementsOrError = Server.formatRange(*Code, File, Params.range);
   if (ReplacementsOrError)
-    reply(json::ary(replacementsToEdits(*Code, ReplacementsOrError.get())));
+    reply(json::Array(replacementsToEdits(*Code, ReplacementsOrError.get())));
   else
     replyError(ErrorCode::UnknownErrorCode,
                llvm::toString(ReplacementsOrError.takeError()));
@@ -289,7 +290,7 @@ void ClangdLSPServer::onDocumentFormatti
 
   auto ReplacementsOrError = Server.formatFile(*Code, File);
   if (ReplacementsOrError)
-    reply(json::ary(replacementsToEdits(*Code, ReplacementsOrError.get())));
+    reply(json::Array(replacementsToEdits(*Code, ReplacementsOrError.get())));
   else
     replyError(ErrorCode::UnknownErrorCode,
                llvm::toString(ReplacementsOrError.takeError()));
@@ -304,7 +305,7 @@ void ClangdLSPServer::onDocumentSymbol(D
                             llvm::toString(Items.takeError()));
         for (auto &Sym : *Items)
           Sym.kind = adjustKindToCapability(Sym.kind, SupportedSymbolKinds);
-        reply(json::ary(*Items));
+        reply(json::Array(*Items));
       });
 }
 
@@ -316,13 +317,13 @@ void ClangdLSPServer::onCodeAction(CodeA
     return replyError(ErrorCode::InvalidParams,
                       "onCodeAction called for non-added file");
 
-  json::ary Commands;
+  json::Array Commands;
   for (Diagnostic &D : Params.context.diagnostics) {
     for (auto &F : getFixes(Params.textDocument.uri.file(), D)) {
       WorkspaceEdit WE;
       std::vector<TextEdit> Edits(F.Edits.begin(), F.Edits.end());
       WE.changes = {{Params.textDocument.uri.uri(), std::move(Edits)}};
-      Commands.push_back(json::obj{
+      Commands.push_back(json::Object{
           {"title", llvm::formatv("Apply fix: {0}", F.Message)},
           {"command", ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND},
           {"arguments", {WE}},
@@ -364,7 +365,7 @@ void ClangdLSPServer::onGoToDefinition(T
         if (!Items)
           return replyError(ErrorCode::InvalidParams,
                             llvm::toString(Items.takeError()));
-        reply(json::ary(*Items));
+        reply(json::Array(*Items));
       });
 }
 
@@ -380,7 +381,7 @@ void ClangdLSPServer::onDocumentHighligh
         if (!Highlights)
           return replyError(ErrorCode::InternalError,
                             llvm::toString(Highlights.takeError()));
-        reply(json::ary(*Highlights));
+        reply(json::Array(*Highlights));
       });
 }
 
@@ -424,7 +425,7 @@ bool ClangdLSPServer::run(std::FILE *In,
   assert(!IsDone && "Run was called before");
 
   // Set up JSONRPCDispatcher.
-  JSONRPCDispatcher Dispatcher([](const json::Expr &Params) {
+  JSONRPCDispatcher Dispatcher([](const json::Value &Params) {
     replyError(ErrorCode::MethodNotFound, "method not found");
   });
   registerCallbackHandlers(Dispatcher, /*Callbacks=*/*this);
@@ -456,12 +457,12 @@ std::vector<Fix> ClangdLSPServer::getFix
 
 void ClangdLSPServer::onDiagnosticsReady(PathRef File,
                                          std::vector<Diag> Diagnostics) {
-  json::ary DiagnosticsJSON;
+  json::Array DiagnosticsJSON;
 
   DiagnosticToReplacementMap LocalFixIts; // Temporary storage
   for (auto &Diag : Diagnostics) {
     toLSPDiags(Diag, [&](clangd::Diagnostic Diag, llvm::ArrayRef<Fix> Fixes) {
-      DiagnosticsJSON.push_back(json::obj{
+      DiagnosticsJSON.push_back(json::Object{
           {"range", Diag.range},
           {"severity", Diag.severity},
           {"message", Diag.message},
@@ -481,11 +482,11 @@ void ClangdLSPServer::onDiagnosticsReady
   }
 
   // Publish diagnostics.
-  Out.writeMessage(json::obj{
+  Out.writeMessage(json::Object{
       {"jsonrpc", "2.0"},
       {"method", "textDocument/publishDiagnostics"},
       {"params",
-       json::obj{
+       json::Object{
            {"uri", URIForFile{File}},
            {"diagnostics", std::move(DiagnosticsJSON)},
        }},

Modified: clang-tools-extra/trunk/clangd/CodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CodeComplete.cpp?rev=336549&r1=336548&r2=336549&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/CodeComplete.cpp (original)
+++ clang-tools-extra/trunk/clangd/CodeComplete.cpp Mon Jul  9 07:25:59 2018
@@ -1014,7 +1014,7 @@ public:
     SPAN_ATTACH(Tracer, "sema_results", NSema);
     SPAN_ATTACH(Tracer, "index_results", NIndex);
     SPAN_ATTACH(Tracer, "merged_results", NBoth);
-    SPAN_ATTACH(Tracer, "returned_results", Output.Completions.size());
+    SPAN_ATTACH(Tracer, "returned_results", int64_t(Output.Completions.size()));
     SPAN_ATTACH(Tracer, "incomplete", Output.HasMore);
     log(llvm::formatv("Code complete: {0} results from Sema, {1} from Index, "
                       "{2} matched, {3} returned{4}.",
@@ -1056,7 +1056,7 @@ private:
 
   SymbolSlab queryIndex() {
     trace::Span Tracer("Query index");
-    SPAN_ATTACH(Tracer, "limit", Opts.Limit);
+    SPAN_ATTACH(Tracer, "limit", int64_t(Opts.Limit));
 
     SymbolSlab::Builder ResultsBuilder;
     // Build the query.

Removed: clang-tools-extra/trunk/clangd/JSONExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/JSONExpr.cpp?rev=336548&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/JSONExpr.cpp (original)
+++ clang-tools-extra/trunk/clangd/JSONExpr.cpp (removed)
@@ -1,554 +0,0 @@
-//=== JSONExpr.cpp - JSON expressions, parsing and serialization - C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===---------------------------------------------------------------------===//
-
-#include "JSONExpr.h"
-#include "llvm/Support/Format.h"
-#include <cctype>
-
-using namespace llvm;
-namespace clang {
-namespace clangd {
-namespace json {
-
-void Expr::copyFrom(const Expr &M) {
-  Type = M.Type;
-  switch (Type) {
-  case T_Null:
-  case T_Boolean:
-  case T_Number:
-    memcpy(Union.buffer, M.Union.buffer, sizeof(Union.buffer));
-    break;
-  case T_StringRef:
-    create<StringRef>(M.as<StringRef>());
-    break;
-  case T_String:
-    create<std::string>(M.as<std::string>());
-    break;
-  case T_Object:
-    create<ObjectExpr>(M.as<ObjectExpr>());
-    break;
-  case T_Array:
-    create<ArrayExpr>(M.as<ArrayExpr>());
-    break;
-  }
-}
-
-void Expr::moveFrom(const Expr &&M) {
-  Type = M.Type;
-  switch (Type) {
-  case T_Null:
-  case T_Boolean:
-  case T_Number:
-    memcpy(Union.buffer, M.Union.buffer, sizeof(Union.buffer));
-    break;
-  case T_StringRef:
-    create<StringRef>(M.as<StringRef>());
-    break;
-  case T_String:
-    create<std::string>(std::move(M.as<std::string>()));
-    M.Type = T_Null;
-    break;
-  case T_Object:
-    create<ObjectExpr>(std::move(M.as<ObjectExpr>()));
-    M.Type = T_Null;
-    break;
-  case T_Array:
-    create<ArrayExpr>(std::move(M.as<ArrayExpr>()));
-    M.Type = T_Null;
-    break;
-  }
-}
-
-void Expr::destroy() {
-  switch (Type) {
-  case T_Null:
-  case T_Boolean:
-  case T_Number:
-    break;
-  case T_StringRef:
-    as<StringRef>().~StringRef();
-    break;
-  case T_String:
-    as<std::string>().~basic_string();
-    break;
-  case T_Object:
-    as<ObjectExpr>().~ObjectExpr();
-    break;
-  case T_Array:
-    as<ArrayExpr>().~ArrayExpr();
-    break;
-  }
-}
-
-namespace {
-// Simple recursive-descent JSON parser.
-class Parser {
-public:
-  Parser(StringRef JSON)
-      : Start(JSON.begin()), P(JSON.begin()), End(JSON.end()) {}
-
-  bool parseExpr(Expr &Out);
-
-  bool assertEnd() {
-    eatWhitespace();
-    if (P == End)
-      return true;
-    return parseError("Text after end of document");
-  }
-
-  Error takeError() {
-    assert(Err);
-    return std::move(*Err);
-  }
-
-private:
-  void eatWhitespace() {
-    while (P != End && (*P == ' ' || *P == '\r' || *P == '\n' || *P == '\t'))
-      ++P;
-  }
-
-  // On invalid syntax, parseX() functions return false and set Err.
-  bool parseNumber(char First, double &Out);
-  bool parseString(std::string &Out);
-  bool parseUnicode(std::string &Out);
-  bool parseError(const char *Msg); // always returns false
-
-  char next() { return P == End ? 0 : *P++; }
-  char peek() { return P == End ? 0 : *P; }
-  static bool isNumber(char C) {
-    return C == '0' || C == '1' || C == '2' || C == '3' || C == '4' ||
-           C == '5' || C == '6' || C == '7' || C == '8' || C == '9' ||
-           C == 'e' || C == 'E' || C == '+' || C == '-' || C == '.';
-  }
-  static void encodeUtf8(uint32_t Rune, std::string &Out);
-
-  Optional<Error> Err;
-  const char *Start, *P, *End;
-};
-
-bool Parser::parseExpr(Expr &Out) {
-  eatWhitespace();
-  if (P == End)
-    return parseError("Unexpected EOF");
-  switch (char C = next()) {
-  // Bare null/true/false are easy - first char identifies them.
-  case 'n':
-    Out = nullptr;
-    return (next() == 'u' && next() == 'l' && next() == 'l') ||
-           parseError("Invalid bareword");
-  case 't':
-    Out = true;
-    return (next() == 'r' && next() == 'u' && next() == 'e') ||
-           parseError("Invalid bareword");
-  case 'f':
-    Out = false;
-    return (next() == 'a' && next() == 'l' && next() == 's' && next() == 'e') ||
-           parseError("Invalid bareword");
-  case '"': {
-    std::string S;
-    if (parseString(S)) {
-      Out = std::move(S);
-      return true;
-    }
-    return false;
-  }
-  case '[': {
-    Out = json::ary{};
-    json::ary &A = *Out.asArray();
-    eatWhitespace();
-    if (peek() == ']') {
-      ++P;
-      return true;
-    }
-    for (;;) {
-      A.emplace_back(nullptr);
-      if (!parseExpr(A.back()))
-        return false;
-      eatWhitespace();
-      switch (next()) {
-      case ',':
-        eatWhitespace();
-        continue;
-      case ']':
-        return true;
-      default:
-        return parseError("Expected , or ] after array element");
-      }
-    }
-  }
-  case '{': {
-    Out = json::obj{};
-    json::obj &O = *Out.asObject();
-    eatWhitespace();
-    if (peek() == '}') {
-      ++P;
-      return true;
-    }
-    for (;;) {
-      if (next() != '"')
-        return parseError("Expected object key");
-      std::string K;
-      if (!parseString(K))
-        return false;
-      eatWhitespace();
-      if (next() != ':')
-        return parseError("Expected : after object key");
-      eatWhitespace();
-      if (!parseExpr(O[std::move(K)]))
-        return false;
-      eatWhitespace();
-      switch (next()) {
-      case ',':
-        eatWhitespace();
-        continue;
-      case '}':
-        return true;
-      default:
-        return parseError("Expected , or } after object property");
-      }
-    }
-  }
-  default:
-    if (isNumber(C)) {
-      double Num;
-      if (parseNumber(C, Num)) {
-        Out = Num;
-        return true;
-      } else {
-        return false;
-      }
-    }
-    return parseError("Expected JSON value");
-  }
-}
-
-bool Parser::parseNumber(char First, double &Out) {
-  SmallString<24> S;
-  S.push_back(First);
-  while (isNumber(peek()))
-    S.push_back(next());
-  char *End;
-  Out = std::strtod(S.c_str(), &End);
-  return End == S.end() || parseError("Invalid number");
-}
-
-bool Parser::parseString(std::string &Out) {
-  // leading quote was already consumed.
-  for (char C = next(); C != '"'; C = next()) {
-    if (LLVM_UNLIKELY(P == End))
-      return parseError("Unterminated string");
-    if (LLVM_UNLIKELY((C & 0x1f) == C))
-      return parseError("Control character in string");
-    if (LLVM_LIKELY(C != '\\')) {
-      Out.push_back(C);
-      continue;
-    }
-    // Handle escape sequence.
-    switch (C = next()) {
-    case '"':
-    case '\\':
-    case '/':
-      Out.push_back(C);
-      break;
-    case 'b':
-      Out.push_back('\b');
-      break;
-    case 'f':
-      Out.push_back('\f');
-      break;
-    case 'n':
-      Out.push_back('\n');
-      break;
-    case 'r':
-      Out.push_back('\r');
-      break;
-    case 't':
-      Out.push_back('\t');
-      break;
-    case 'u':
-      if (!parseUnicode(Out))
-        return false;
-      break;
-    default:
-      return parseError("Invalid escape sequence");
-    }
-  }
-  return true;
-}
-
-void Parser::encodeUtf8(uint32_t Rune, std::string &Out) {
-  if (Rune <= 0x7F) {
-    Out.push_back(Rune & 0x7F);
-  } else if (Rune <= 0x7FF) {
-    uint8_t FirstByte = 0xC0 | ((Rune & 0x7C0) >> 6);
-    uint8_t SecondByte = 0x80 | (Rune & 0x3F);
-    Out.push_back(FirstByte);
-    Out.push_back(SecondByte);
-  } else if (Rune <= 0xFFFF) {
-    uint8_t FirstByte = 0xE0 | ((Rune & 0xF000) >> 12);
-    uint8_t SecondByte = 0x80 | ((Rune & 0xFC0) >> 6);
-    uint8_t ThirdByte = 0x80 | (Rune & 0x3F);
-    Out.push_back(FirstByte);
-    Out.push_back(SecondByte);
-    Out.push_back(ThirdByte);
-  } else if (Rune <= 0x10FFFF) {
-    uint8_t FirstByte = 0xF0 | ((Rune & 0x1F0000) >> 18);
-    uint8_t SecondByte = 0x80 | ((Rune & 0x3F000) >> 12);
-    uint8_t ThirdByte = 0x80 | ((Rune & 0xFC0) >> 6);
-    uint8_t FourthByte = 0x80 | (Rune & 0x3F);
-    Out.push_back(FirstByte);
-    Out.push_back(SecondByte);
-    Out.push_back(ThirdByte);
-    Out.push_back(FourthByte);
-  } else {
-    llvm_unreachable("Invalid codepoint");
-  }
-}
-
-// Parse a \uNNNN escape sequence, the \u have already been consumed.
-// May parse multiple escapes in the presence of surrogate pairs.
-bool Parser::parseUnicode(std::string &Out) {
-  // Note that invalid unicode is not a JSON error. It gets replaced by U+FFFD.
-  auto Invalid = [&] { Out.append(/* UTF-8 */ {'\xef', '\xbf', '\xbd'}); };
-  auto Parse4Hex = [this](uint16_t &Out) {
-    Out = 0;
-    char Bytes[] = {next(), next(), next(), next()};
-    for (unsigned char C : Bytes) {
-      if (!std::isxdigit(C))
-        return parseError("Invalid \\u escape sequence");
-      Out <<= 4;
-      Out |= (C > '9') ? (C & ~0x20) - 'A' + 10 : (C - '0');
-    }
-    return true;
-  };
-  uint16_t First;
-  if (!Parse4Hex(First))
-    return false;
-
-  // We loop to allow proper surrogate-pair error handling.
-  while (true) {
-    if (LLVM_LIKELY(First < 0xD800 || First >= 0xE000)) { // BMP.
-      encodeUtf8(First, Out);
-      return true;
-    }
-
-    if (First >= 0xDC00) {
-      Invalid(); // Lone trailing surrogate.
-      return true;
-    }
-
-    // We have a leading surrogate, and need a trailing one.
-    // Don't advance P: a lone surrogate is valid JSON (but invalid unicode)
-    if (P + 2 > End || *P != '\\' || *(P + 1) != 'u') {
-      Invalid(); // Lone leading not followed by \u...
-      return true;
-    }
-    P += 2;
-    uint16_t Second;
-    if (!Parse4Hex(Second))
-      return false;
-    if (Second < 0xDC00 || Second >= 0xE000) {
-      Invalid();      // Leading surrogate not followed by trailing.
-      First = Second; // Second escape still needs to be processed.
-      continue;
-    }
-
-    // Valid surrogate pair.
-    encodeUtf8(0x10000 | ((First - 0xD800) << 10) | (Second - 0xDC00), Out);
-    return true;
-  }
-}
-
-bool Parser::parseError(const char *Msg) {
-  int Line = 1;
-  const char *StartOfLine = Start;
-  for (const char *X = Start; X < P; ++X) {
-    if (*X == 0x0A) {
-      ++Line;
-      StartOfLine = X + 1;
-    }
-  }
-  Err.emplace(
-      llvm::make_unique<ParseError>(Msg, Line, P - StartOfLine, P - Start));
-  return false;
-}
-} // namespace
-
-Expected<Expr> parse(StringRef JSON) {
-  Parser P(JSON);
-  json::Expr E = nullptr;
-  if (P.parseExpr(E))
-    if (P.assertEnd())
-      return std::move(E);
-  return P.takeError();
-}
-char ParseError::ID = 0;
-
-} // namespace json
-} // namespace clangd
-} // namespace clang
-
-namespace {
-void quote(llvm::raw_ostream &OS, llvm::StringRef S) {
-  OS << '\"';
-  for (unsigned char C : S) {
-    if (C == 0x22 || C == 0x5C)
-      OS << '\\';
-    if (C >= 0x20) {
-      OS << C;
-      continue;
-    }
-    OS << '\\';
-    switch (C) {
-    // A few characters are common enough to make short escapes worthwhile.
-    case '\t':
-      OS << 't';
-      break;
-    case '\n':
-      OS << 'n';
-      break;
-    case '\r':
-      OS << 'r';
-      break;
-    default:
-      OS << 'u';
-      llvm::write_hex(OS, C, llvm::HexPrintStyle::Lower, 4);
-      break;
-    }
-  }
-  OS << '\"';
-}
-
-enum IndenterAction {
-  Indent,
-  Outdent,
-  Newline,
-  Space,
-};
-} // namespace
-
-// Prints JSON. The indenter can be used to control formatting.
-template <typename Indenter>
-void clang::clangd::json::Expr::print(raw_ostream &OS,
-                                      const Indenter &I) const {
-  switch (Type) {
-  case T_Null:
-    OS << "null";
-    break;
-  case T_Boolean:
-    OS << (as<bool>() ? "true" : "false");
-    break;
-  case T_Number:
-    OS << format("%g", as<double>());
-    break;
-  case T_StringRef:
-    quote(OS, as<StringRef>());
-    break;
-  case T_String:
-    quote(OS, as<std::string>());
-    break;
-  case T_Object: {
-    bool Comma = false;
-    OS << '{';
-    I(Indent);
-    for (const auto &P : as<Expr::ObjectExpr>()) {
-      if (Comma)
-        OS << ',';
-      Comma = true;
-      I(Newline);
-      quote(OS, P.first);
-      OS << ':';
-      I(Space);
-      P.second.print(OS, I);
-    }
-    I(Outdent);
-    if (Comma)
-      I(Newline);
-    OS << '}';
-    break;
-  }
-  case T_Array: {
-    bool Comma = false;
-    OS << '[';
-    I(Indent);
-    for (const auto &E : as<Expr::ArrayExpr>()) {
-      if (Comma)
-        OS << ',';
-      Comma = true;
-      I(Newline);
-      E.print(OS, I);
-    }
-    I(Outdent);
-    if (Comma)
-      I(Newline);
-    OS << ']';
-    break;
-  }
-  }
-}
-
-namespace clang {
-namespace clangd {
-namespace json {
-llvm::raw_ostream &operator<<(raw_ostream &OS, const Expr &E) {
-  E.print(OS, [](IndenterAction A) { /*ignore*/ });
-  return OS;
-}
-
-bool operator==(const Expr &L, const Expr &R) {
-  if (L.kind() != R.kind())
-    return false;
-  switch (L.kind()) {
-  case Expr::Null:
-    return *L.asNull() == *R.asNull();
-  case Expr::Boolean:
-    return *L.asBoolean() == *R.asBoolean();
-  case Expr::Number:
-    return *L.asNumber() == *R.asNumber();
-  case Expr::String:
-    return *L.asString() == *R.asString();
-  case Expr::Array:
-    return *L.asArray() == *R.asArray();
-  case Expr::Object:
-    return *L.asObject() == *R.asObject();
-  }
-  llvm_unreachable("Unknown expression kind");
-}
-} // namespace json
-} // namespace clangd
-} // namespace clang
-
-void llvm::format_provider<clang::clangd::json::Expr>::format(
-    const clang::clangd::json::Expr &E, raw_ostream &OS, StringRef Options) {
-  if (Options.empty()) {
-    OS << E;
-    return;
-  }
-  unsigned IndentAmount = 0;
-  if (Options.getAsInteger(/*Radix=*/10, IndentAmount))
-    assert(false && "json::Expr format options should be an integer");
-  unsigned IndentLevel = 0;
-  E.print(OS, [&](IndenterAction A) {
-    switch (A) {
-    case Newline:
-      OS << '\n';
-      OS.indent(IndentLevel);
-      break;
-    case Space:
-      OS << ' ';
-      break;
-    case Indent:
-      IndentLevel += IndentAmount;
-      break;
-    case Outdent:
-      IndentLevel -= IndentAmount;
-      break;
-    };
-  });
-}

Removed: clang-tools-extra/trunk/clangd/JSONExpr.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/JSONExpr.h?rev=336548&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/JSONExpr.h (original)
+++ clang-tools-extra/trunk/clangd/JSONExpr.h (removed)
@@ -1,586 +0,0 @@
-//===--- JSONExpr.h - JSON expressions, parsing and serialization - C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===---------------------------------------------------------------------===//
-
-// FIXME: rename to JSON.h now that the scope is wider?
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSON_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSON_H
-
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/raw_ostream.h"
-#include <map>
-
-namespace clang {
-namespace clangd {
-namespace json {
-class Expr;
-template <typename T> Expr toJSON(const llvm::Optional<T> &Opt);
-
-// An Expr is an JSON value of unknown type.
-// They can be copied, but should generally be moved.
-//
-// === Composing expressions ===
-//
-// You can implicitly construct Exprs from:
-//   - strings: std::string, SmallString, formatv, StringRef, char*
-//              (char*, and StringRef are references, not copies!)
-//   - numbers
-//   - booleans
-//   - null: nullptr
-//   - arrays: {"foo", 42.0, false}
-//   - serializable things: types with toJSON(const T&)->Expr, found by ADL
-//
-// They can also be constructed from object/array helpers:
-//   - json::obj is a type like map<StringExpr, Expr>
-//   - json::ary is a type like vector<Expr>
-// These can be list-initialized, or used to build up collections in a loop.
-// json::ary(Collection) converts all items in a collection to Exprs.
-//
-// === Inspecting expressions ===
-//
-// Each Expr is one of the JSON kinds:
-//   null    (nullptr_t)
-//   boolean (bool)
-//   number  (double)
-//   string  (StringRef)
-//   array   (json::ary)
-//   object  (json::obj)
-//
-// The kind can be queried directly, or implicitly via the typed accessors:
-//   if (Optional<StringRef> S = E.asString()
-//     assert(E.kind() == Expr::String);
-//
-// Array and Object also have typed indexing accessors for easy traversal:
-//   Expected<Expr> E = parse(R"( {"options": {"font": "sans-serif"}} )");
-//   if (json::obj* O = E->asObject())
-//     if (json::obj* Opts = O->getObject("options"))
-//       if (Optional<StringRef> Font = Opts->getString("font"))
-//         assert(Opts->at("font").kind() == Expr::String);
-//
-// === Converting expressions to objects ===
-//
-// The convention is to have a deserializer function findable via ADL:
-//     fromJSON(const json::Expr&, T&)->bool
-// Deserializers are provided for:
-//   - bool
-//   - int
-//   - double
-//   - std::string
-//   - vector<T>, where T is deserializable
-//   - map<string, T>, where T is deserializable
-//   - Optional<T>, where T is deserializable
-//
-// ObjectMapper can help writing fromJSON() functions for object types:
-//   bool fromJSON(const Expr &E, MyStruct &R) {
-//     ObjectMapper O(E);
-//     if (!O || !O.map("mandatory_field", R.MandatoryField))
-//       return false;
-//     O.map("optional_field", R.OptionalField);
-//     return true;
-//   }
-//
-// === Serialization ===
-//
-// Exprs can be serialized to JSON:
-//   1) raw_ostream << Expr                    // Basic formatting.
-//   2) raw_ostream << formatv("{0}", Expr)    // Basic formatting.
-//   3) raw_ostream << formatv("{0:2}", Expr)  // Pretty-print with indent 2.
-//
-// And parsed:
-//   Expected<Expr> E = json::parse("[1, 2, null]");
-//   assert(E && E->kind() == Expr::Array);
-class Expr {
-public:
-  enum Kind {
-    Null,
-    Boolean,
-    Number,
-    String,
-    Array,
-    Object,
-  };
-  class ObjectExpr;
-  class ObjectKey;
-  class ArrayExpr;
-
-  // It would be nice to have Expr() be null. But that would make {} null too...
-  Expr(const Expr &M) { copyFrom(M); }
-  Expr(Expr &&M) { moveFrom(std::move(M)); }
-  // "cheating" move-constructor for moving from initializer_list.
-  Expr(const Expr &&M) { moveFrom(std::move(M)); }
-  Expr(std::initializer_list<Expr> Elements) : Expr(ArrayExpr(Elements)) {}
-  Expr(ArrayExpr &&Elements) : Type(T_Array) {
-    create<ArrayExpr>(std::move(Elements));
-  }
-  Expr(ObjectExpr &&Properties) : Type(T_Object) {
-    create<ObjectExpr>(std::move(Properties));
-  }
-  // Strings: types with value semantics.
-  Expr(std::string &&V) : Type(T_String) { create<std::string>(std::move(V)); }
-  Expr(const std::string &V) : Type(T_String) { create<std::string>(V); }
-  Expr(const llvm::SmallVectorImpl<char> &V) : Type(T_String) {
-    create<std::string>(V.begin(), V.end());
-  }
-  Expr(const llvm::formatv_object_base &V) : Expr(V.str()){};
-  // Strings: types with reference semantics.
-  Expr(llvm::StringRef V) : Type(T_StringRef) { create<llvm::StringRef>(V); }
-  Expr(const char *V) : Type(T_StringRef) { create<llvm::StringRef>(V); }
-  Expr(std::nullptr_t) : Type(T_Null) {}
-  // Prevent implicit conversions to boolean.
-  template <typename T, typename = typename std::enable_if<
-                            std::is_same<T, bool>::value>::type>
-  Expr(T B) : Type(T_Boolean) {
-    create<bool>(B);
-  }
-  // Numbers: arithmetic types that are not boolean.
-  template <
-      typename T,
-      typename = typename std::enable_if<std::is_arithmetic<T>::value>::type,
-      typename = typename std::enable_if<std::integral_constant<
-          bool, !std::is_same<T, bool>::value>::value>::type>
-  Expr(T D) : Type(T_Number) {
-    create<double>(D);
-  }
-  // Types with a toJSON(const T&)->Expr function, found by ADL.
-  template <typename T,
-            typename = typename std::enable_if<std::is_same<
-                Expr, decltype(toJSON(*(const T *)nullptr))>::value>>
-  Expr(const T &V) : Expr(toJSON(V)) {}
-
-  Expr &operator=(const Expr &M) {
-    destroy();
-    copyFrom(M);
-    return *this;
-  }
-  Expr &operator=(Expr &&M) {
-    destroy();
-    moveFrom(std::move(M));
-    return *this;
-  }
-  ~Expr() { destroy(); }
-
-  Kind kind() const {
-    switch (Type) {
-    case T_Null:
-      return Null;
-    case T_Boolean:
-      return Boolean;
-    case T_Number:
-      return Number;
-    case T_String:
-    case T_StringRef:
-      return String;
-    case T_Object:
-      return Object;
-    case T_Array:
-      return Array;
-    }
-    llvm_unreachable("Unknown kind");
-  }
-
-  // Typed accessors return None/nullptr if the Expr is not of this type.
-  llvm::Optional<std::nullptr_t> asNull() const {
-    if (LLVM_LIKELY(Type == T_Null))
-      return nullptr;
-    return llvm::None;
-  }
-  llvm::Optional<bool> asBoolean() const {
-    if (LLVM_LIKELY(Type == T_Boolean))
-      return as<bool>();
-    return llvm::None;
-  }
-  llvm::Optional<double> asNumber() const {
-    if (LLVM_LIKELY(Type == T_Number))
-      return as<double>();
-    return llvm::None;
-  }
-  llvm::Optional<int64_t> asInteger() const {
-    if (LLVM_LIKELY(Type == T_Number)) {
-      double D = as<double>();
-      if (LLVM_LIKELY(std::modf(D, &D) == 0 &&
-                      D >= std::numeric_limits<int64_t>::min() &&
-                      D <= std::numeric_limits<int64_t>::max()))
-        return D;
-    }
-    return llvm::None;
-  }
-  llvm::Optional<llvm::StringRef> asString() const {
-    if (Type == T_String)
-      return llvm::StringRef(as<std::string>());
-    if (LLVM_LIKELY(Type == T_StringRef))
-      return as<llvm::StringRef>();
-    return llvm::None;
-  }
-  const ObjectExpr *asObject() const {
-    return LLVM_LIKELY(Type == T_Object) ? &as<ObjectExpr>() : nullptr;
-  }
-  ObjectExpr *asObject() {
-    return LLVM_LIKELY(Type == T_Object) ? &as<ObjectExpr>() : nullptr;
-  }
-  const ArrayExpr *asArray() const {
-    return LLVM_LIKELY(Type == T_Array) ? &as<ArrayExpr>() : nullptr;
-  }
-  ArrayExpr *asArray() {
-    return LLVM_LIKELY(Type == T_Array) ? &as<ArrayExpr>() : nullptr;
-  }
-
-  friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Expr &);
-
-private:
-  void destroy();
-  void copyFrom(const Expr &M);
-  // We allow moving from *const* Exprs, by marking all members as mutable!
-  // This hack is needed to support initializer-list syntax efficiently.
-  // (std::initializer_list<T> is a container of const T).
-  void moveFrom(const Expr &&M);
-
-  template <typename T, typename... U> void create(U &&... V) {
-    new (&as<T>()) T(std::forward<U>(V)...);
-  }
-  template <typename T> T &as() const {
-    return *reinterpret_cast<T *>(Union.buffer);
-  }
-
-  template <typename Indenter>
-  void print(llvm::raw_ostream &, const Indenter &) const;
-  friend struct llvm::format_provider<clang::clangd::json::Expr>;
-
-  enum ExprType : char {
-    T_Null,
-    T_Boolean,
-    T_Number,
-    T_StringRef,
-    T_String,
-    T_Object,
-    T_Array,
-  };
-  mutable ExprType Type;
-
-public:
-  // ObjectKey is a used to capture keys in Expr::ObjectExpr. Like Expr but:
-  //   - only strings are allowed
-  //   - it's optimized for the string literal case (Owned == nullptr)
-  class ObjectKey {
-  public:
-    ObjectKey(const char *S) : Data(S) {}
-    ObjectKey(llvm::StringRef S) : Data(S) {}
-    ObjectKey(std::string &&V)
-        : Owned(new std::string(std::move(V))), Data(*Owned) {}
-    ObjectKey(const std::string &V) : Owned(new std::string(V)), Data(*Owned) {}
-    ObjectKey(const llvm::SmallVectorImpl<char> &V)
-        : ObjectKey(std::string(V.begin(), V.end())) {}
-    ObjectKey(const llvm::formatv_object_base &V) : ObjectKey(V.str()) {}
-
-    ObjectKey(const ObjectKey &C) { *this = C; }
-    ObjectKey(ObjectKey &&C) : ObjectKey(static_cast<const ObjectKey &&>(C)) {}
-    ObjectKey &operator=(const ObjectKey &C) {
-      if (C.Owned) {
-        Owned.reset(new std::string(*C.Owned));
-        Data = *Owned;
-      } else {
-        Data = C.Data;
-      }
-      return *this;
-    }
-    ObjectKey &operator=(ObjectKey &&) = default;
-
-    operator llvm::StringRef() const { return Data; }
-
-    friend bool operator<(const ObjectKey &L, const ObjectKey &R) {
-      return L.Data < R.Data;
-    }
-
-    // "cheating" move-constructor for moving from initializer_list.
-    ObjectKey(const ObjectKey &&V) {
-      Owned = std::move(V.Owned);
-      Data = V.Data;
-    }
-
-  private:
-    mutable std::unique_ptr<std::string> Owned; // mutable for cheating.
-    llvm::StringRef Data;
-  };
-
-  class ObjectExpr : public std::map<ObjectKey, Expr> {
-  public:
-    explicit ObjectExpr() {}
-    // Use a custom struct for list-init, because pair forces extra copies.
-    struct KV;
-    explicit ObjectExpr(std::initializer_list<KV> Properties);
-
-    // Allow [] as if Expr was default-constructible as null.
-    Expr &operator[](const ObjectKey &K) {
-      return emplace(K, Expr(nullptr)).first->second;
-    }
-    Expr &operator[](ObjectKey &&K) {
-      return emplace(std::move(K), Expr(nullptr)).first->second;
-    }
-
-    // Look up a property, returning nullptr if it doesn't exist.
-    json::Expr *get(const ObjectKey &K) {
-      auto I = find(K);
-      if (I == end())
-        return nullptr;
-      return &I->second;
-    }
-    const json::Expr *get(const ObjectKey &K) const {
-      auto I = find(K);
-      if (I == end())
-        return nullptr;
-      return &I->second;
-    }
-    // Typed accessors return None/nullptr if
-    //   - the property doesn't exist
-    //   - or it has the wrong type
-    llvm::Optional<std::nullptr_t> getNull(const ObjectKey &K) const {
-      if (auto *V = get(K))
-        return V->asNull();
-      return llvm::None;
-    }
-    llvm::Optional<bool> getBoolean(const ObjectKey &K) const {
-      if (auto *V = get(K))
-        return V->asBoolean();
-      return llvm::None;
-    }
-    llvm::Optional<double> getNumber(const ObjectKey &K) const {
-      if (auto *V = get(K))
-        return V->asNumber();
-      return llvm::None;
-    }
-    llvm::Optional<int64_t> getInteger(const ObjectKey &K) const {
-      if (auto *V = get(K))
-        return V->asInteger();
-      return llvm::None;
-    }
-    llvm::Optional<llvm::StringRef> getString(const ObjectKey &K) const {
-      if (auto *V = get(K))
-        return V->asString();
-      return llvm::None;
-    }
-    const ObjectExpr *getObject(const ObjectKey &K) const {
-      if (auto *V = get(K))
-        return V->asObject();
-      return nullptr;
-    }
-    ObjectExpr *getObject(const ObjectKey &K) {
-      if (auto *V = get(K))
-        return V->asObject();
-      return nullptr;
-    }
-    const ArrayExpr *getArray(const ObjectKey &K) const {
-      if (auto *V = get(K))
-        return V->asArray();
-      return nullptr;
-    }
-    ArrayExpr *getArray(const ObjectKey &K) {
-      if (auto *V = get(K))
-        return V->asArray();
-      return nullptr;
-    }
-  };
-
-  class ArrayExpr : public std::vector<Expr> {
-  public:
-    explicit ArrayExpr() {}
-    explicit ArrayExpr(std::initializer_list<Expr> Elements) {
-      reserve(Elements.size());
-      for (const Expr &V : Elements)
-        emplace_back(std::move(V));
-    };
-    template <typename Collection> explicit ArrayExpr(const Collection &C) {
-      for (const auto &V : C)
-        emplace_back(V);
-    }
-
-    // Typed accessors return None/nullptr if the element has the wrong type.
-    llvm::Optional<std::nullptr_t> getNull(size_t I) const {
-      return (*this)[I].asNull();
-    }
-    llvm::Optional<bool> getBoolean(size_t I) const {
-      return (*this)[I].asBoolean();
-    }
-    llvm::Optional<double> getNumber(size_t I) const {
-      return (*this)[I].asNumber();
-    }
-    llvm::Optional<int64_t> getInteger(size_t I) const {
-      return (*this)[I].asInteger();
-    }
-    llvm::Optional<llvm::StringRef> getString(size_t I) const {
-      return (*this)[I].asString();
-    }
-    const ObjectExpr *getObject(size_t I) const {
-      return (*this)[I].asObject();
-    }
-    ObjectExpr *getObject(size_t I) { return (*this)[I].asObject(); }
-    const ArrayExpr *getArray(size_t I) const { return (*this)[I].asArray(); }
-    ArrayExpr *getArray(size_t I) { return (*this)[I].asArray(); }
-  };
-
-private:
-  mutable llvm::AlignedCharArrayUnion<bool, double, llvm::StringRef,
-                                      std::string, ArrayExpr, ObjectExpr>
-      Union;
-};
-
-bool operator==(const Expr &, const Expr &);
-inline bool operator!=(const Expr &L, const Expr &R) { return !(L == R); }
-inline bool operator==(const Expr::ObjectKey &L, const Expr::ObjectKey &R) {
-  return llvm::StringRef(L) == llvm::StringRef(R);
-}
-inline bool operator!=(const Expr::ObjectKey &L, const Expr::ObjectKey &R) {
-  return !(L == R);
-}
-
-struct Expr::ObjectExpr::KV {
-  ObjectKey K;
-  Expr V;
-};
-
-inline Expr::ObjectExpr::ObjectExpr(std::initializer_list<KV> Properties) {
-  for (const auto &P : Properties)
-    emplace(std::move(P.K), std::move(P.V));
-}
-
-// Give Expr::{Object,Array} more convenient names for literal use.
-using obj = Expr::ObjectExpr;
-using ary = Expr::ArrayExpr;
-
-// Standard deserializers.
-inline bool fromJSON(const json::Expr &E, std::string &Out) {
-  if (auto S = E.asString()) {
-    Out = *S;
-    return true;
-  }
-  return false;
-}
-inline bool fromJSON(const json::Expr &E, int &Out) {
-  if (auto S = E.asInteger()) {
-    Out = *S;
-    return true;
-  }
-  return false;
-}
-inline bool fromJSON(const json::Expr &E, double &Out) {
-  if (auto S = E.asNumber()) {
-    Out = *S;
-    return true;
-  }
-  return false;
-}
-inline bool fromJSON(const json::Expr &E, bool &Out) {
-  if (auto S = E.asBoolean()) {
-    Out = *S;
-    return true;
-  }
-  return false;
-}
-template <typename T>
-bool fromJSON(const json::Expr &E, llvm::Optional<T> &Out) {
-  if (E.asNull()) {
-    Out = llvm::None;
-    return true;
-  }
-  T Result;
-  if (!fromJSON(E, Result))
-    return false;
-  Out = std::move(Result);
-  return true;
-}
-template <typename T> bool fromJSON(const json::Expr &E, std::vector<T> &Out) {
-  if (auto *A = E.asArray()) {
-    Out.clear();
-    Out.resize(A->size());
-    for (size_t I = 0; I < A->size(); ++I)
-      if (!fromJSON((*A)[I], Out[I]))
-        return false;
-    return true;
-  }
-  return false;
-}
-template <typename T>
-bool fromJSON(const json::Expr &E, std::map<std::string, T> &Out) {
-  if (auto *O = E.asObject()) {
-    Out.clear();
-    for (const auto &KV : *O)
-      if (!fromJSON(KV.second, Out[llvm::StringRef(KV.first)]))
-        return false;
-    return true;
-  }
-  return false;
-}
-
-template <typename T>
-json::Expr toJSON(const llvm::Optional<T>& Opt) {
-  return Opt ? json::Expr(*Opt) : json::Expr(nullptr);
-}
-
-// Helper for mapping JSON objects onto protocol structs.
-// See file header for example.
-class ObjectMapper {
-public:
-  ObjectMapper(const json::Expr &E) : O(E.asObject()) {}
-
-  // True if the expression is an object.
-  // Must be checked before calling map().
-  operator bool() { return O; }
-
-  // Maps a property to a field, if it exists.
-  template <typename T> bool map(const char *Prop, T &Out) {
-    assert(*this && "Must check this is an object before calling map()");
-    if (const json::Expr *E = O->get(Prop))
-      return fromJSON(*E, Out);
-    return false;
-  }
-
-  // Optional requires special handling, because missing keys are OK.
-  template <typename T> bool map(const char *Prop, llvm::Optional<T> &Out) {
-    assert(*this && "Must check this is an object before calling map()");
-    if (const json::Expr *E = O->get(Prop))
-      return fromJSON(*E, Out);
-    Out = llvm::None;
-    return true;
-  }
-
-private:
-  const json::obj *O;
-};
-
-llvm::Expected<Expr> parse(llvm::StringRef JSON);
-
-class ParseError : public llvm::ErrorInfo<ParseError> {
-  const char *Msg;
-  unsigned Line, Column, Offset;
-
-public:
-  static char ID;
-  ParseError(const char *Msg, unsigned Line, unsigned Column, unsigned Offset)
-      : Msg(Msg), Line(Line), Column(Column), Offset(Offset) {}
-  void log(llvm::raw_ostream &OS) const override {
-    OS << llvm::formatv("[{0}:{1}, byte={2}]: {3}", Line, Column, Offset, Msg);
-  }
-  std::error_code convertToErrorCode() const override {
-    return llvm::inconvertibleErrorCode();
-  }
-};
-
-} // namespace json
-} // namespace clangd
-} // namespace clang
-
-namespace llvm {
-template <> struct format_provider<clang::clangd::json::Expr> {
-  static void format(const clang::clangd::json::Expr &, raw_ostream &,
-                     StringRef);
-};
-} // namespace llvm
-
-#endif

Modified: clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp?rev=336549&r1=336548&r2=336549&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp (original)
+++ clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp Mon Jul  9 07:25:59 2018
@@ -8,29 +8,30 @@
 //===----------------------------------------------------------------------===//
 
 #include "JSONRPCDispatcher.h"
-#include "JSONExpr.h"
 #include "ProtocolHandlers.h"
 #include "Trace.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Chrono.h"
 #include "llvm/Support/Errno.h"
+#include "llvm/Support/JSON.h"
 #include "llvm/Support/SourceMgr.h"
 #include <istream>
 
+using namespace llvm;
 using namespace clang;
 using namespace clangd;
 
 namespace {
-static Key<json::Expr> RequestID;
+static Key<json::Value> RequestID;
 static Key<JSONOutput *> RequestOut;
 
 // When tracing, we trace a request and attach the repsonse in reply().
 // Because the Span isn't available, we find the current request using Context.
 class RequestSpan {
-  RequestSpan(json::obj *Args) : Args(Args) {}
+  RequestSpan(llvm::json::Object *Args) : Args(Args) {}
   std::mutex Mu;
-  json::obj *Args;
+  llvm::json::Object *Args;
   static Key<std::unique_ptr<RequestSpan>> RSKey;
 
 public:
@@ -41,7 +42,7 @@ public:
   }
 
   // If there's an enclosing request and the tracer is interested, calls \p F
-  // with a json::obj where request info can be added.
+  // with a json::Object where request info can be added.
   template <typename Func> static void attach(Func &&F) {
     auto *RequestArgs = Context::current().get(RSKey);
     if (!RequestArgs || !*RequestArgs || !(*RequestArgs)->Args)
@@ -53,7 +54,7 @@ public:
 Key<std::unique_ptr<RequestSpan>> RequestSpan::RSKey;
 } // namespace
 
-void JSONOutput::writeMessage(const json::Expr &Message) {
+void JSONOutput::writeMessage(const json::Value &Message) {
   std::string S;
   llvm::raw_string_ostream OS(S);
   if (Pretty)
@@ -86,16 +87,16 @@ void JSONOutput::mirrorInput(const Twine
   InputMirror->flush();
 }
 
-void clangd::reply(json::Expr &&Result) {
+void clangd::reply(json::Value &&Result) {
   auto ID = Context::current().get(RequestID);
   if (!ID) {
     log("Attempted to reply to a notification!");
     return;
   }
-  RequestSpan::attach([&](json::obj &Args) { Args["Reply"] = Result; });
+  RequestSpan::attach([&](json::Object &Args) { Args["Reply"] = Result; });
   Context::current()
       .getExisting(RequestOut)
-      ->writeMessage(json::obj{
+      ->writeMessage(json::Object{
           {"jsonrpc", "2.0"},
           {"id", *ID},
           {"result", std::move(Result)},
@@ -104,32 +105,32 @@ void clangd::reply(json::Expr &&Result)
 
 void clangd::replyError(ErrorCode code, const llvm::StringRef &Message) {
   log("Error " + Twine(static_cast<int>(code)) + ": " + Message);
-  RequestSpan::attach([&](json::obj &Args) {
-    Args["Error"] =
-        json::obj{{"code", static_cast<int>(code)}, {"message", Message.str()}};
+  RequestSpan::attach([&](json::Object &Args) {
+    Args["Error"] = json::Object{{"code", static_cast<int>(code)},
+                                 {"message", Message.str()}};
   });
 
   if (auto ID = Context::current().get(RequestID)) {
     Context::current()
         .getExisting(RequestOut)
-        ->writeMessage(json::obj{
+        ->writeMessage(json::Object{
             {"jsonrpc", "2.0"},
             {"id", *ID},
-            {"error",
-             json::obj{{"code", static_cast<int>(code)}, {"message", Message}}},
+            {"error", json::Object{{"code", static_cast<int>(code)},
+                                   {"message", Message}}},
         });
   }
 }
 
-void clangd::call(StringRef Method, json::Expr &&Params) {
+void clangd::call(StringRef Method, json::Value &&Params) {
   // FIXME: Generate/Increment IDs for every request so that we can get proper
   // replies once we need to.
-  RequestSpan::attach([&](json::obj &Args) {
-    Args["Call"] = json::obj{{"method", Method.str()}, {"params", Params}};
+  RequestSpan::attach([&](json::Object &Args) {
+    Args["Call"] = json::Object{{"method", Method.str()}, {"params", Params}};
   });
   Context::current()
       .getExisting(RequestOut)
-      ->writeMessage(json::obj{
+      ->writeMessage(json::Object{
           {"jsonrpc", "2.0"},
           {"id", 1},
           {"method", Method},
@@ -142,13 +143,14 @@ void JSONRPCDispatcher::registerHandler(
   Handlers[Method] = std::move(H);
 }
 
-bool JSONRPCDispatcher::call(const json::Expr &Message, JSONOutput &Out) const {
+bool JSONRPCDispatcher::call(const json::Value &Message,
+                             JSONOutput &Out) const {
   // Message must be an object with "jsonrpc":"2.0".
-  auto *Object = Message.asObject();
+  auto *Object = Message.getAsObject();
   if (!Object || Object->getString("jsonrpc") != Optional<StringRef>("2.0"))
     return false;
   // ID may be any JSON value. If absent, this is a notification.
-  llvm::Optional<json::Expr> ID;
+  llvm::Optional<json::Value> ID;
   if (auto *I = Object->get("id"))
     ID = std::move(*I);
   // Method must be given.
@@ -156,7 +158,7 @@ bool JSONRPCDispatcher::call(const json:
   if (!Method)
     return false;
   // Params should be given, use null if not.
-  json::Expr Params = nullptr;
+  json::Value Params = nullptr;
   if (auto *P = Object->get("params"))
     Params = std::move(*P);
 

Modified: clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h?rev=336549&r1=336548&r2=336549&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h (original)
+++ clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h Mon Jul  9 07:25:59 2018
@@ -10,13 +10,13 @@
 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSONRPCDISPATCHER_H
 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSONRPCDISPATCHER_H
 
-#include "JSONExpr.h"
 #include "Logger.h"
 #include "Protocol.h"
 #include "Trace.h"
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringMap.h"
+#include "llvm/Support/JSON.h"
 #include <iosfwd>
 #include <mutex>
 
@@ -34,7 +34,7 @@ public:
       : Pretty(Pretty), Outs(Outs), Logs(Logs), InputMirror(InputMirror) {}
 
   /// Emit a JSONRPC message.
-  void writeMessage(const json::Expr &Result);
+  void writeMessage(const llvm::json::Value &Result);
 
   /// Write a line to the logging stream.
   void log(const Twine &Message) override;
@@ -57,20 +57,20 @@ private:
 
 /// Sends a successful reply.
 /// Current context must derive from JSONRPCDispatcher::Handler.
-void reply(json::Expr &&Result);
+void reply(llvm::json::Value &&Result);
 /// Sends an error response to the client, and logs it.
 /// Current context must derive from JSONRPCDispatcher::Handler.
 void replyError(ErrorCode code, const llvm::StringRef &Message);
 /// Sends a request to the client.
 /// Current context must derive from JSONRPCDispatcher::Handler.
-void call(llvm::StringRef Method, json::Expr &&Params);
+void call(llvm::StringRef Method, llvm::json::Value &&Params);
 
 /// Main JSONRPC entry point. This parses the JSONRPC "header" and calls the
 /// registered Handler for the method received.
 class JSONRPCDispatcher {
 public:
   // A handler responds to requests for a particular method name.
-  using Handler = std::function<void(const json::Expr &)>;
+  using Handler = std::function<void(const llvm::json::Value &)>;
 
   /// Create a new JSONRPCDispatcher. UnknownHandler is called when an unknown
   /// method is received.
@@ -81,7 +81,7 @@ public:
   void registerHandler(StringRef Method, Handler H);
 
   /// Parses a JSONRPC message and calls the Handler for it.
-  bool call(const json::Expr &Message, JSONOutput &Out) const;
+  bool call(const llvm::json::Value &Message, JSONOutput &Out) const;
 
 private:
   llvm::StringMap<Handler> Handlers;

Modified: clang-tools-extra/trunk/clangd/Protocol.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.cpp?rev=336549&r1=336548&r2=336549&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Protocol.cpp (original)
+++ clang-tools-extra/trunk/clangd/Protocol.cpp Mon Jul  9 07:25:59 2018
@@ -23,14 +23,15 @@
 
 namespace clang {
 namespace clangd {
+using namespace llvm;
 
 URIForFile::URIForFile(std::string AbsPath) {
   assert(llvm::sys::path::is_absolute(AbsPath) && "the path is relative");
   File = std::move(AbsPath);
 }
 
-bool fromJSON(const json::Expr &E, URIForFile &R) {
-  if (auto S = E.asString()) {
+bool fromJSON(const json::Value &E, URIForFile &R) {
+  if (auto S = E.getAsString()) {
     auto U = URI::parse(*S);
     if (!U) {
       log("Failed to parse URI " + *S + ": " + llvm::toString(U.takeError()));
@@ -51,28 +52,28 @@ bool fromJSON(const json::Expr &E, URIFo
   return false;
 }
 
-json::Expr toJSON(const URIForFile &U) { return U.uri(); }
+json::Value toJSON(const URIForFile &U) { return U.uri(); }
 
 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const URIForFile &U) {
   return OS << U.uri();
 }
 
-json::Expr toJSON(const TextDocumentIdentifier &R) {
-  return json::obj{{"uri", R.uri}};
+json::Value toJSON(const TextDocumentIdentifier &R) {
+  return json::Object{{"uri", R.uri}};
 }
 
-bool fromJSON(const json::Expr &Params, TextDocumentIdentifier &R) {
+bool fromJSON(const json::Value &Params, TextDocumentIdentifier &R) {
   json::ObjectMapper O(Params);
   return O && O.map("uri", R.uri);
 }
 
-bool fromJSON(const json::Expr &Params, Position &R) {
+bool fromJSON(const json::Value &Params, Position &R) {
   json::ObjectMapper O(Params);
   return O && O.map("line", R.line) && O.map("character", R.character);
 }
 
-json::Expr toJSON(const Position &P) {
-  return json::obj{
+json::Value toJSON(const Position &P) {
+  return json::Object{
       {"line", P.line},
       {"character", P.character},
   };
@@ -82,13 +83,13 @@ llvm::raw_ostream &operator<<(llvm::raw_
   return OS << P.line << ':' << P.character;
 }
 
-bool fromJSON(const json::Expr &Params, Range &R) {
+bool fromJSON(const json::Value &Params, Range &R) {
   json::ObjectMapper O(Params);
   return O && O.map("start", R.start) && O.map("end", R.end);
 }
 
-json::Expr toJSON(const Range &P) {
-  return json::obj{
+json::Value toJSON(const Range &P) {
+  return json::Object{
       {"start", P.start},
       {"end", P.end},
   };
@@ -98,8 +99,8 @@ llvm::raw_ostream &operator<<(llvm::raw_
   return OS << R.start << '-' << R.end;
 }
 
-json::Expr toJSON(const Location &P) {
-  return json::obj{
+json::Value toJSON(const Location &P) {
+  return json::Object{
       {"uri", P.uri},
       {"range", P.range},
   };
@@ -109,13 +110,13 @@ llvm::raw_ostream &operator<<(llvm::raw_
   return OS << L.range << '@' << L.uri;
 }
 
-bool fromJSON(const json::Expr &Params, TextDocumentItem &R) {
+bool fromJSON(const json::Value &Params, TextDocumentItem &R) {
   json::ObjectMapper O(Params);
   return O && O.map("uri", R.uri) && O.map("languageId", R.languageId) &&
          O.map("version", R.version) && O.map("text", R.text);
 }
 
-bool fromJSON(const json::Expr &Params, Metadata &R) {
+bool fromJSON(const json::Value &Params, Metadata &R) {
   json::ObjectMapper O(Params);
   if (!O)
     return false;
@@ -123,13 +124,13 @@ bool fromJSON(const json::Expr &Params,
   return true;
 }
 
-bool fromJSON(const json::Expr &Params, TextEdit &R) {
+bool fromJSON(const json::Value &Params, TextEdit &R) {
   json::ObjectMapper O(Params);
   return O && O.map("range", R.range) && O.map("newText", R.newText);
 }
 
-json::Expr toJSON(const TextEdit &P) {
-  return json::obj{
+json::Value toJSON(const TextEdit &P) {
+  return json::Object{
       {"range", P.range},
       {"newText", P.newText},
   };
@@ -141,8 +142,8 @@ llvm::raw_ostream &operator<<(llvm::raw_
   return OS << '"';
 }
 
-bool fromJSON(const json::Expr &E, TraceLevel &Out) {
-  if (auto S = E.asString()) {
+bool fromJSON(const json::Value &E, TraceLevel &Out) {
+  if (auto S = E.getAsString()) {
     if (*S == "off") {
       Out = TraceLevel::Off;
       return true;
@@ -157,7 +158,7 @@ bool fromJSON(const json::Expr &E, Trace
   return false;
 }
 
-bool fromJSON(const json::Expr &Params, CompletionItemClientCapabilities &R) {
+bool fromJSON(const json::Value &Params, CompletionItemClientCapabilities &R) {
   json::ObjectMapper O(Params);
   if (!O)
     return false;
@@ -166,7 +167,7 @@ bool fromJSON(const json::Expr &Params,
   return true;
 }
 
-bool fromJSON(const json::Expr &Params, CompletionClientCapabilities &R) {
+bool fromJSON(const json::Value &Params, CompletionClientCapabilities &R) {
   json::ObjectMapper O(Params);
   if (!O)
     return false;
@@ -176,8 +177,8 @@ bool fromJSON(const json::Expr &Params,
   return true;
 }
 
-bool fromJSON(const json::Expr &E, SymbolKind &Out) {
-  if (auto T = E.asInteger()) {
+bool fromJSON(const json::Value &E, SymbolKind &Out) {
+  if (auto T = E.getAsInteger()) {
     if (*T < static_cast<int>(SymbolKind::File) ||
         *T > static_cast<int>(SymbolKind::TypeParameter))
       return false;
@@ -187,8 +188,8 @@ bool fromJSON(const json::Expr &E, Symbo
   return false;
 }
 
-bool fromJSON(const json::Expr &E, std::vector<SymbolKind> &Out) {
-  if (auto *A = E.asArray()) {
+bool fromJSON(const json::Value &E, std::vector<SymbolKind> &Out) {
+  if (auto *A = E.getAsArray()) {
     Out.clear();
     for (size_t I = 0; I < A->size(); ++I) {
       SymbolKind KindOut;
@@ -200,7 +201,7 @@ bool fromJSON(const json::Expr &E, std::
   return false;
 }
 
-bool fromJSON(const json::Expr &Params, SymbolKindCapabilities &R) {
+bool fromJSON(const json::Value &Params, SymbolKindCapabilities &R) {
   json::ObjectMapper O(Params);
   return O && O.map("valueSet", R.valueSet);
 }
@@ -223,17 +224,17 @@ SymbolKind adjustKindToCapability(Symbol
   }
 }
 
-bool fromJSON(const json::Expr &Params, WorkspaceSymbolCapabilities &R) {
+bool fromJSON(const json::Value &Params, WorkspaceSymbolCapabilities &R) {
   json::ObjectMapper O(Params);
   return O && O.map("symbolKind", R.symbolKind);
 }
 
-bool fromJSON(const json::Expr &Params, WorkspaceClientCapabilities &R) {
+bool fromJSON(const json::Value &Params, WorkspaceClientCapabilities &R) {
   json::ObjectMapper O(Params);
   return O && O.map("symbol", R.symbol);
 }
 
-bool fromJSON(const json::Expr &Params, TextDocumentClientCapabilities &R) {
+bool fromJSON(const json::Value &Params, TextDocumentClientCapabilities &R) {
   json::ObjectMapper O(Params);
   if (!O)
     return false;
@@ -241,7 +242,7 @@ bool fromJSON(const json::Expr &Params,
   return true;
 }
 
-bool fromJSON(const json::Expr &Params, ClientCapabilities &R) {
+bool fromJSON(const json::Value &Params, ClientCapabilities &R) {
   json::ObjectMapper O(Params);
   if (!O)
     return false;
@@ -250,7 +251,7 @@ bool fromJSON(const json::Expr &Params,
   return true;
 }
 
-bool fromJSON(const json::Expr &Params, InitializeParams &R) {
+bool fromJSON(const json::Value &Params, InitializeParams &R) {
   json::ObjectMapper O(Params);
   if (!O)
     return false;
@@ -265,26 +266,26 @@ bool fromJSON(const json::Expr &Params,
   return true;
 }
 
-bool fromJSON(const json::Expr &Params, DidOpenTextDocumentParams &R) {
+bool fromJSON(const json::Value &Params, DidOpenTextDocumentParams &R) {
   json::ObjectMapper O(Params);
   return O && O.map("textDocument", R.textDocument) &&
          O.map("metadata", R.metadata);
 }
 
-bool fromJSON(const json::Expr &Params, DidCloseTextDocumentParams &R) {
+bool fromJSON(const json::Value &Params, DidCloseTextDocumentParams &R) {
   json::ObjectMapper O(Params);
   return O && O.map("textDocument", R.textDocument);
 }
 
-bool fromJSON(const json::Expr &Params, DidChangeTextDocumentParams &R) {
+bool fromJSON(const json::Value &Params, DidChangeTextDocumentParams &R) {
   json::ObjectMapper O(Params);
   return O && O.map("textDocument", R.textDocument) &&
          O.map("contentChanges", R.contentChanges) &&
          O.map("wantDiagnostics", R.wantDiagnostics);
 }
 
-bool fromJSON(const json::Expr &E, FileChangeType &Out) {
-  if (auto T = E.asInteger()) {
+bool fromJSON(const json::Value &E, FileChangeType &Out) {
+  if (auto T = E.getAsInteger()) {
     if (*T < static_cast<int>(FileChangeType::Created) ||
         *T > static_cast<int>(FileChangeType::Deleted))
       return false;
@@ -294,60 +295,60 @@ bool fromJSON(const json::Expr &E, FileC
   return false;
 }
 
-bool fromJSON(const json::Expr &Params, FileEvent &R) {
+bool fromJSON(const json::Value &Params, FileEvent &R) {
   json::ObjectMapper O(Params);
   return O && O.map("uri", R.uri) && O.map("type", R.type);
 }
 
-bool fromJSON(const json::Expr &Params, DidChangeWatchedFilesParams &R) {
+bool fromJSON(const json::Value &Params, DidChangeWatchedFilesParams &R) {
   json::ObjectMapper O(Params);
   return O && O.map("changes", R.changes);
 }
 
-bool fromJSON(const json::Expr &Params, TextDocumentContentChangeEvent &R) {
+bool fromJSON(const json::Value &Params, TextDocumentContentChangeEvent &R) {
   json::ObjectMapper O(Params);
   return O && O.map("range", R.range) && O.map("rangeLength", R.rangeLength) &&
          O.map("text", R.text);
 }
 
-bool fromJSON(const json::Expr &Params, FormattingOptions &R) {
+bool fromJSON(const json::Value &Params, FormattingOptions &R) {
   json::ObjectMapper O(Params);
   return O && O.map("tabSize", R.tabSize) &&
          O.map("insertSpaces", R.insertSpaces);
 }
 
-json::Expr toJSON(const FormattingOptions &P) {
-  return json::obj{
+json::Value toJSON(const FormattingOptions &P) {
+  return json::Object{
       {"tabSize", P.tabSize},
       {"insertSpaces", P.insertSpaces},
   };
 }
 
-bool fromJSON(const json::Expr &Params, DocumentRangeFormattingParams &R) {
+bool fromJSON(const json::Value &Params, DocumentRangeFormattingParams &R) {
   json::ObjectMapper O(Params);
   return O && O.map("textDocument", R.textDocument) &&
          O.map("range", R.range) && O.map("options", R.options);
 }
 
-bool fromJSON(const json::Expr &Params, DocumentOnTypeFormattingParams &R) {
+bool fromJSON(const json::Value &Params, DocumentOnTypeFormattingParams &R) {
   json::ObjectMapper O(Params);
   return O && O.map("textDocument", R.textDocument) &&
          O.map("position", R.position) && O.map("ch", R.ch) &&
          O.map("options", R.options);
 }
 
-bool fromJSON(const json::Expr &Params, DocumentFormattingParams &R) {
+bool fromJSON(const json::Value &Params, DocumentFormattingParams &R) {
   json::ObjectMapper O(Params);
   return O && O.map("textDocument", R.textDocument) &&
          O.map("options", R.options);
 }
 
-bool fromJSON(const json::Expr &Params, DocumentSymbolParams &R) {
+bool fromJSON(const json::Value &Params, DocumentSymbolParams &R) {
   json::ObjectMapper O(Params);
   return O && O.map("textDocument", R.textDocument);
 }
 
-bool fromJSON(const json::Expr &Params, Diagnostic &R) {
+bool fromJSON(const json::Value &Params, Diagnostic &R) {
   json::ObjectMapper O(Params);
   if (!O || !O.map("range", R.range) || !O.map("message", R.message))
     return false;
@@ -355,7 +356,7 @@ bool fromJSON(const json::Expr &Params,
   return true;
 }
 
-bool fromJSON(const json::Expr &Params, CodeActionContext &R) {
+bool fromJSON(const json::Value &Params, CodeActionContext &R) {
   json::ObjectMapper O(Params);
   return O && O.map("diagnostics", R.diagnostics);
 }
@@ -382,25 +383,25 @@ llvm::raw_ostream &operator<<(llvm::raw_
   return OS << '(' << D.severity << "): " << D.message << "]";
 }
 
-bool fromJSON(const json::Expr &Params, CodeActionParams &R) {
+bool fromJSON(const json::Value &Params, CodeActionParams &R) {
   json::ObjectMapper O(Params);
   return O && O.map("textDocument", R.textDocument) &&
          O.map("range", R.range) && O.map("context", R.context);
 }
 
-bool fromJSON(const json::Expr &Params, WorkspaceEdit &R) {
+bool fromJSON(const json::Value &Params, WorkspaceEdit &R) {
   json::ObjectMapper O(Params);
   return O && O.map("changes", R.changes);
 }
 
 const llvm::StringLiteral ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND =
     "clangd.applyFix";
-bool fromJSON(const json::Expr &Params, ExecuteCommandParams &R) {
+bool fromJSON(const json::Value &Params, ExecuteCommandParams &R) {
   json::ObjectMapper O(Params);
   if (!O || !O.map("command", R.command))
     return false;
 
-  auto Args = Params.asObject()->getArray("arguments");
+  auto Args = Params.getAsObject()->getArray("arguments");
   if (R.command == ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND) {
     return Args && Args->size() == 1 &&
            fromJSON(Args->front(), R.workspaceEdit);
@@ -408,8 +409,8 @@ bool fromJSON(const json::Expr &Params,
   return false; // Unrecognized command.
 }
 
-json::Expr toJSON(const SymbolInformation &P) {
-  return json::obj{
+json::Value toJSON(const SymbolInformation &P) {
+  return json::Object{
       {"name", P.name},
       {"kind", static_cast<int>(P.kind)},
       {"location", P.location},
@@ -423,32 +424,32 @@ llvm::raw_ostream &operator<<(llvm::raw_
   return O;
 }
 
-bool fromJSON(const json::Expr &Params, WorkspaceSymbolParams &R) {
+bool fromJSON(const json::Value &Params, WorkspaceSymbolParams &R) {
   json::ObjectMapper O(Params);
   return O && O.map("query", R.query);
 }
 
-json::Expr toJSON(const Command &C) {
-  auto Cmd = json::obj{{"title", C.title}, {"command", C.command}};
+json::Value toJSON(const Command &C) {
+  auto Cmd = json::Object{{"title", C.title}, {"command", C.command}};
   if (C.workspaceEdit)
     Cmd["arguments"] = {*C.workspaceEdit};
   return std::move(Cmd);
 }
 
-json::Expr toJSON(const WorkspaceEdit &WE) {
+json::Value toJSON(const WorkspaceEdit &WE) {
   if (!WE.changes)
-    return json::obj{};
-  json::obj FileChanges;
+    return json::Object{};
+  json::Object FileChanges;
   for (auto &Change : *WE.changes)
-    FileChanges[Change.first] = json::ary(Change.second);
-  return json::obj{{"changes", std::move(FileChanges)}};
+    FileChanges[Change.first] = json::Array(Change.second);
+  return json::Object{{"changes", std::move(FileChanges)}};
 }
 
-json::Expr toJSON(const ApplyWorkspaceEditParams &Params) {
-  return json::obj{{"edit", Params.edit}};
+json::Value toJSON(const ApplyWorkspaceEditParams &Params) {
+  return json::Object{{"edit", Params.edit}};
 }
 
-bool fromJSON(const json::Expr &Params, TextDocumentPositionParams &R) {
+bool fromJSON(const json::Value &Params, TextDocumentPositionParams &R) {
   json::ObjectMapper O(Params);
   return O && O.map("textDocument", R.textDocument) &&
          O.map("position", R.position);
@@ -464,18 +465,18 @@ static StringRef toTextKind(MarkupKind K
   llvm_unreachable("Invalid MarkupKind");
 }
 
-json::Expr toJSON(const MarkupContent &MC) {
+json::Value toJSON(const MarkupContent &MC) {
   if (MC.value.empty())
     return nullptr;
 
-  return json::obj{
+  return json::Object{
       {"kind", toTextKind(MC.kind)},
       {"value", MC.value},
   };
 }
 
-json::Expr toJSON(const Hover &H) {
-  json::obj Result{{"contents", toJSON(H.contents)}};
+json::Value toJSON(const Hover &H) {
+  json::Object Result{{"contents", toJSON(H.contents)}};
 
   if (H.range.hasValue())
     Result["range"] = toJSON(*H.range);
@@ -483,9 +484,9 @@ json::Expr toJSON(const Hover &H) {
   return std::move(Result);
 }
 
-json::Expr toJSON(const CompletionItem &CI) {
+json::Value toJSON(const CompletionItem &CI) {
   assert(!CI.label.empty() && "completion item label is required");
-  json::obj Result{{"label", CI.label}};
+  json::Object Result{{"label", CI.label}};
   if (CI.kind != CompletionItemKind::Missing)
     Result["kind"] = static_cast<int>(CI.kind);
   if (!CI.detail.empty())
@@ -503,7 +504,7 @@ json::Expr toJSON(const CompletionItem &
   if (CI.textEdit)
     Result["textEdit"] = *CI.textEdit;
   if (!CI.additionalTextEdits.empty())
-    Result["additionalTextEdits"] = json::ary(CI.additionalTextEdits);
+    Result["additionalTextEdits"] = json::Array(CI.additionalTextEdits);
   return std::move(Result);
 }
 
@@ -517,26 +518,26 @@ bool operator<(const CompletionItem &L,
          (R.sortText.empty() ? R.label : R.sortText);
 }
 
-json::Expr toJSON(const CompletionList &L) {
-  return json::obj{
+json::Value toJSON(const CompletionList &L) {
+  return json::Object{
       {"isIncomplete", L.isIncomplete},
-      {"items", json::ary(L.items)},
+      {"items", json::Array(L.items)},
   };
 }
 
-json::Expr toJSON(const ParameterInformation &PI) {
+json::Value toJSON(const ParameterInformation &PI) {
   assert(!PI.label.empty() && "parameter information label is required");
-  json::obj Result{{"label", PI.label}};
+  json::Object Result{{"label", PI.label}};
   if (!PI.documentation.empty())
     Result["documentation"] = PI.documentation;
   return std::move(Result);
 }
 
-json::Expr toJSON(const SignatureInformation &SI) {
+json::Value toJSON(const SignatureInformation &SI) {
   assert(!SI.label.empty() && "signature information label is required");
-  json::obj Result{
+  json::Object Result{
       {"label", SI.label},
-      {"parameters", json::ary(SI.parameters)},
+      {"parameters", json::Array(SI.parameters)},
   };
   if (!SI.documentation.empty())
     Result["documentation"] = SI.documentation;
@@ -549,26 +550,26 @@ llvm::raw_ostream &operator<<(llvm::raw_
   return O;
 }
 
-json::Expr toJSON(const SignatureHelp &SH) {
+json::Value toJSON(const SignatureHelp &SH) {
   assert(SH.activeSignature >= 0 &&
          "Unexpected negative value for number of active signatures.");
   assert(SH.activeParameter >= 0 &&
          "Unexpected negative value for active parameter index");
-  return json::obj{
+  return json::Object{
       {"activeSignature", SH.activeSignature},
       {"activeParameter", SH.activeParameter},
-      {"signatures", json::ary(SH.signatures)},
+      {"signatures", json::Array(SH.signatures)},
   };
 }
 
-bool fromJSON(const json::Expr &Params, RenameParams &R) {
+bool fromJSON(const json::Value &Params, RenameParams &R) {
   json::ObjectMapper O(Params);
   return O && O.map("textDocument", R.textDocument) &&
          O.map("position", R.position) && O.map("newName", R.newName);
 }
 
-json::Expr toJSON(const DocumentHighlight &DH) {
-  return json::obj{
+json::Value toJSON(const DocumentHighlight &DH) {
+  return json::Object{
       {"range", toJSON(DH.range)},
       {"kind", static_cast<int>(DH.kind)},
   };
@@ -584,12 +585,13 @@ llvm::raw_ostream &operator<<(llvm::raw_
   return O;
 }
 
-bool fromJSON(const json::Expr &Params, DidChangeConfigurationParams &CCP) {
+bool fromJSON(const json::Value &Params, DidChangeConfigurationParams &CCP) {
   json::ObjectMapper O(Params);
   return O && O.map("settings", CCP.settings);
 }
 
-bool fromJSON(const json::Expr &Params, ClangdConfigurationParamsChange &CCPC) {
+bool fromJSON(const json::Value &Params,
+              ClangdConfigurationParamsChange &CCPC) {
   json::ObjectMapper O(Params);
   return O && O.map("compilationDatabasePath", CCPC.compilationDatabasePath);
 }

Modified: clang-tools-extra/trunk/clangd/Protocol.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.h?rev=336549&r1=336548&r2=336549&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Protocol.h (original)
+++ clang-tools-extra/trunk/clangd/Protocol.h Mon Jul  9 07:25:59 2018
@@ -14,7 +14,7 @@
 // when they're needed.
 //
 // Each struct has a toJSON and fromJSON function, that converts between
-// the struct and a JSON representation. (See JSONExpr.h)
+// the struct and a JSON representation. (See JSON.h)
 //
 // Some structs also have operator<< serialization. This is for debugging and
 // tests, and is not generally machine-readable.
@@ -24,9 +24,9 @@
 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROTOCOL_H
 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROTOCOL_H
 
-#include "JSONExpr.h"
 #include "URI.h"
 #include "llvm/ADT/Optional.h"
+#include "llvm/Support/JSON.h"
 #include <bitset>
 #include <string>
 #include <vector>
@@ -76,15 +76,15 @@ private:
 };
 
 /// Serialize/deserialize \p URIForFile to/from a string URI.
-json::Expr toJSON(const URIForFile &U);
-bool fromJSON(const json::Expr &, URIForFile &);
+llvm::json::Value toJSON(const URIForFile &U);
+bool fromJSON(const llvm::json::Value &, URIForFile &);
 
 struct TextDocumentIdentifier {
   /// The text document's URI.
   URIForFile uri;
 };
-json::Expr toJSON(const TextDocumentIdentifier &);
-bool fromJSON(const json::Expr &, TextDocumentIdentifier &);
+llvm::json::Value toJSON(const TextDocumentIdentifier &);
+bool fromJSON(const llvm::json::Value &, TextDocumentIdentifier &);
 
 struct Position {
   /// Line position in a document (zero-based).
@@ -111,8 +111,8 @@ struct Position {
            std::tie(RHS.line, RHS.character);
   }
 };
-bool fromJSON(const json::Expr &, Position &);
-json::Expr toJSON(const Position &);
+bool fromJSON(const llvm::json::Value &, Position &);
+llvm::json::Value toJSON(const Position &);
 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Position &);
 
 struct Range {
@@ -134,8 +134,8 @@ struct Range {
 
   bool contains(Position Pos) const { return start <= Pos && Pos < end; }
 };
-bool fromJSON(const json::Expr &, Range &);
-json::Expr toJSON(const Range &);
+bool fromJSON(const llvm::json::Value &, Range &);
+llvm::json::Value toJSON(const Range &);
 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Range &);
 
 struct Location {
@@ -155,13 +155,13 @@ struct Location {
     return std::tie(LHS.uri, LHS.range) < std::tie(RHS.uri, RHS.range);
   }
 };
-json::Expr toJSON(const Location &);
+llvm::json::Value toJSON(const Location &);
 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Location &);
 
 struct Metadata {
   std::vector<std::string> extraFlags;
 };
-bool fromJSON(const json::Expr &, Metadata &);
+bool fromJSON(const llvm::json::Value &, Metadata &);
 
 struct TextEdit {
   /// The range of the text document to be manipulated. To insert
@@ -172,8 +172,8 @@ struct TextEdit {
   /// empty string.
   std::string newText;
 };
-bool fromJSON(const json::Expr &, TextEdit &);
-json::Expr toJSON(const TextEdit &);
+bool fromJSON(const llvm::json::Value &, TextEdit &);
+llvm::json::Value toJSON(const TextEdit &);
 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const TextEdit &);
 
 struct TextDocumentItem {
@@ -189,17 +189,17 @@ struct TextDocumentItem {
   /// The content of the opened text document.
   std::string text;
 };
-bool fromJSON(const json::Expr &, TextDocumentItem &);
+bool fromJSON(const llvm::json::Value &, TextDocumentItem &);
 
 enum class TraceLevel {
   Off = 0,
   Messages = 1,
   Verbose = 2,
 };
-bool fromJSON(const json::Expr &E, TraceLevel &Out);
+bool fromJSON(const llvm::json::Value &E, TraceLevel &Out);
 
 struct NoParams {};
-inline bool fromJSON(const json::Expr &, NoParams &) { return true; }
+inline bool fromJSON(const llvm::json::Value &, NoParams &) { return true; }
 using ShutdownParams = NoParams;
 using ExitParams = NoParams;
 
@@ -227,7 +227,7 @@ struct CompletionItemClientCapabilities
   // NOTE: not used by clangd at the moment.
   // std::vector<MarkupKind> documentationFormat;
 };
-bool fromJSON(const json::Expr &, CompletionItemClientCapabilities &);
+bool fromJSON(const llvm::json::Value &, CompletionItemClientCapabilities &);
 
 struct CompletionClientCapabilities {
   /// Whether completion supports dynamic registration.
@@ -241,7 +241,7 @@ struct CompletionClientCapabilities {
   /// `textDocument/completion` request.
   bool contextSupport = false;
 };
-bool fromJSON(const json::Expr &, CompletionClientCapabilities &);
+bool fromJSON(const llvm::json::Value &, CompletionClientCapabilities &);
 
 /// A symbol kind.
 enum class SymbolKind {
@@ -277,7 +277,7 @@ constexpr auto SymbolKindMin = static_ca
 constexpr auto SymbolKindMax = static_cast<size_t>(SymbolKind::TypeParameter);
 using SymbolKindBitset = std::bitset<SymbolKindMax + 1>;
 
-bool fromJSON(const json::Expr &, SymbolKind &);
+bool fromJSON(const llvm::json::Value &, SymbolKind &);
 
 struct SymbolKindCapabilities {
   /// The SymbolKinds that the client supports. If not set, the client only
@@ -285,8 +285,8 @@ struct SymbolKindCapabilities {
   /// value.
   llvm::Optional<std::vector<SymbolKind>> valueSet;
 };
-bool fromJSON(const json::Expr &, std::vector<SymbolKind> &);
-bool fromJSON(const json::Expr &, SymbolKindCapabilities &);
+bool fromJSON(const llvm::json::Value &, std::vector<SymbolKind> &);
+bool fromJSON(const llvm::json::Value &, SymbolKindCapabilities &);
 SymbolKind adjustKindToCapability(SymbolKind Kind,
                                   SymbolKindBitset &supportedSymbolKinds);
 
@@ -294,7 +294,7 @@ struct WorkspaceSymbolCapabilities {
   /// Capabilities SymbolKind.
   llvm::Optional<SymbolKindCapabilities> symbolKind;
 };
-bool fromJSON(const json::Expr &, WorkspaceSymbolCapabilities &);
+bool fromJSON(const llvm::json::Value &, WorkspaceSymbolCapabilities &);
 
 // FIXME: most of the capabilities are missing from this struct. Only the ones
 // used by clangd are currently there.
@@ -302,7 +302,7 @@ struct WorkspaceClientCapabilities {
   /// Capabilities specific to `workspace/symbol`.
   llvm::Optional<WorkspaceSymbolCapabilities> symbol;
 };
-bool fromJSON(const json::Expr &, WorkspaceClientCapabilities &);
+bool fromJSON(const llvm::json::Value &, WorkspaceClientCapabilities &);
 
 // FIXME: most of the capabilities are missing from this struct. Only the ones
 // used by clangd are currently there.
@@ -310,7 +310,7 @@ struct TextDocumentClientCapabilities {
   /// Capabilities specific to the `textDocument/completion`
   CompletionClientCapabilities completion;
 };
-bool fromJSON(const json::Expr &, TextDocumentClientCapabilities &);
+bool fromJSON(const llvm::json::Value &, TextDocumentClientCapabilities &);
 
 struct ClientCapabilities {
   // Workspace specific client capabilities.
@@ -320,7 +320,7 @@ struct ClientCapabilities {
   TextDocumentClientCapabilities textDocument;
 };
 
-bool fromJSON(const json::Expr &, ClientCapabilities &);
+bool fromJSON(const llvm::json::Value &, ClientCapabilities &);
 
 struct InitializeParams {
   /// The process Id of the parent process that started
@@ -349,7 +349,7 @@ struct InitializeParams {
   /// The initial trace setting. If omitted trace is disabled ('off').
   llvm::Optional<TraceLevel> trace;
 };
-bool fromJSON(const json::Expr &, InitializeParams &);
+bool fromJSON(const llvm::json::Value &, InitializeParams &);
 
 struct DidOpenTextDocumentParams {
   /// The document that was opened.
@@ -358,13 +358,13 @@ struct DidOpenTextDocumentParams {
   /// Extension storing per-file metadata, such as compilation flags.
   llvm::Optional<Metadata> metadata;
 };
-bool fromJSON(const json::Expr &, DidOpenTextDocumentParams &);
+bool fromJSON(const llvm::json::Value &, DidOpenTextDocumentParams &);
 
 struct DidCloseTextDocumentParams {
   /// The document that was closed.
   TextDocumentIdentifier textDocument;
 };
-bool fromJSON(const json::Expr &, DidCloseTextDocumentParams &);
+bool fromJSON(const llvm::json::Value &, DidCloseTextDocumentParams &);
 
 struct TextDocumentContentChangeEvent {
   /// The range of the document that changed.
@@ -376,7 +376,7 @@ struct TextDocumentContentChangeEvent {
   /// The new text of the range/document.
   std::string text;
 };
-bool fromJSON(const json::Expr &, TextDocumentContentChangeEvent &);
+bool fromJSON(const llvm::json::Value &, TextDocumentContentChangeEvent &);
 
 struct DidChangeTextDocumentParams {
   /// The document that did change. The version number points
@@ -393,7 +393,7 @@ struct DidChangeTextDocumentParams {
   /// This is a clangd extension.
   llvm::Optional<bool> wantDiagnostics;
 };
-bool fromJSON(const json::Expr &, DidChangeTextDocumentParams &);
+bool fromJSON(const llvm::json::Value &, DidChangeTextDocumentParams &);
 
 enum class FileChangeType {
   /// The file got created.
@@ -403,7 +403,7 @@ enum class FileChangeType {
   /// The file got deleted.
   Deleted = 3
 };
-bool fromJSON(const json::Expr &E, FileChangeType &Out);
+bool fromJSON(const llvm::json::Value &E, FileChangeType &Out);
 
 struct FileEvent {
   /// The file's URI.
@@ -411,27 +411,27 @@ struct FileEvent {
   /// The change type.
   FileChangeType type = FileChangeType::Created;
 };
-bool fromJSON(const json::Expr &, FileEvent &);
+bool fromJSON(const llvm::json::Value &, FileEvent &);
 
 struct DidChangeWatchedFilesParams {
   /// The actual file events.
   std::vector<FileEvent> changes;
 };
-bool fromJSON(const json::Expr &, DidChangeWatchedFilesParams &);
+bool fromJSON(const llvm::json::Value &, DidChangeWatchedFilesParams &);
 
 /// Clangd extension to manage a workspace/didChangeConfiguration notification
 /// since the data received is described as 'any' type in LSP.
 struct ClangdConfigurationParamsChange {
   llvm::Optional<std::string> compilationDatabasePath;
 };
-bool fromJSON(const json::Expr &, ClangdConfigurationParamsChange &);
+bool fromJSON(const llvm::json::Value &, ClangdConfigurationParamsChange &);
 
 struct DidChangeConfigurationParams {
   // We use this predefined struct because it is easier to use
   // than the protocol specified type of 'any'.
   ClangdConfigurationParamsChange settings;
 };
-bool fromJSON(const json::Expr &, DidChangeConfigurationParams &);
+bool fromJSON(const llvm::json::Value &, DidChangeConfigurationParams &);
 
 struct FormattingOptions {
   /// Size of a tab in spaces.
@@ -440,8 +440,8 @@ struct FormattingOptions {
   /// Prefer spaces over tabs.
   bool insertSpaces = false;
 };
-bool fromJSON(const json::Expr &, FormattingOptions &);
-json::Expr toJSON(const FormattingOptions &);
+bool fromJSON(const llvm::json::Value &, FormattingOptions &);
+llvm::json::Value toJSON(const FormattingOptions &);
 
 struct DocumentRangeFormattingParams {
   /// The document to format.
@@ -453,7 +453,7 @@ struct DocumentRangeFormattingParams {
   /// The format options
   FormattingOptions options;
 };
-bool fromJSON(const json::Expr &, DocumentRangeFormattingParams &);
+bool fromJSON(const llvm::json::Value &, DocumentRangeFormattingParams &);
 
 struct DocumentOnTypeFormattingParams {
   /// The document to format.
@@ -468,7 +468,7 @@ struct DocumentOnTypeFormattingParams {
   /// The format options.
   FormattingOptions options;
 };
-bool fromJSON(const json::Expr &, DocumentOnTypeFormattingParams &);
+bool fromJSON(const llvm::json::Value &, DocumentOnTypeFormattingParams &);
 
 struct DocumentFormattingParams {
   /// The document to format.
@@ -477,13 +477,13 @@ struct DocumentFormattingParams {
   /// The format options
   FormattingOptions options;
 };
-bool fromJSON(const json::Expr &, DocumentFormattingParams &);
+bool fromJSON(const llvm::json::Value &, DocumentFormattingParams &);
 
 struct DocumentSymbolParams {
   // The text document to find symbols in.
   TextDocumentIdentifier textDocument;
 };
-bool fromJSON(const json::Expr &, DocumentSymbolParams &);
+bool fromJSON(const llvm::json::Value &, DocumentSymbolParams &);
 
 struct Diagnostic {
   /// The range at which the message applies.
@@ -516,14 +516,14 @@ struct LSPDiagnosticCompare {
     return std::tie(LHS.range, LHS.message) < std::tie(RHS.range, RHS.message);
   }
 };
-bool fromJSON(const json::Expr &, Diagnostic &);
+bool fromJSON(const llvm::json::Value &, Diagnostic &);
 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Diagnostic &);
 
 struct CodeActionContext {
   /// An array of diagnostics.
   std::vector<Diagnostic> diagnostics;
 };
-bool fromJSON(const json::Expr &, CodeActionContext &);
+bool fromJSON(const llvm::json::Value &, CodeActionContext &);
 
 struct CodeActionParams {
   /// The document in which the command was invoked.
@@ -535,7 +535,7 @@ struct CodeActionParams {
   /// Context carrying additional information.
   CodeActionContext context;
 };
-bool fromJSON(const json::Expr &, CodeActionParams &);
+bool fromJSON(const llvm::json::Value &, CodeActionParams &);
 
 struct WorkspaceEdit {
   /// Holds changes to existing resources.
@@ -544,8 +544,8 @@ struct WorkspaceEdit {
   /// Note: "documentChanges" is not currently used because currently there is
   /// no support for versioned edits.
 };
-bool fromJSON(const json::Expr &, WorkspaceEdit &);
-json::Expr toJSON(const WorkspaceEdit &WE);
+bool fromJSON(const llvm::json::Value &, WorkspaceEdit &);
+llvm::json::Value toJSON(const WorkspaceEdit &WE);
 
 /// Exact commands are not specified in the protocol so we define the
 /// ones supported by Clangd here. The protocol specifies the command arguments
@@ -565,13 +565,13 @@ struct ExecuteCommandParams {
   // Arguments
   llvm::Optional<WorkspaceEdit> workspaceEdit;
 };
-bool fromJSON(const json::Expr &, ExecuteCommandParams &);
+bool fromJSON(const llvm::json::Value &, ExecuteCommandParams &);
 
 struct Command : public ExecuteCommandParams {
   std::string title;
 };
 
-json::Expr toJSON(const Command &C);
+llvm::json::Value toJSON(const Command &C);
 
 /// Represents information about programming constructs like variables, classes,
 /// interfaces etc.
@@ -588,7 +588,7 @@ struct SymbolInformation {
   /// The name of the symbol containing this symbol.
   std::string containerName;
 };
-json::Expr toJSON(const SymbolInformation &);
+llvm::json::Value toJSON(const SymbolInformation &);
 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const SymbolInformation &);
 
 /// The parameters of a Workspace Symbol Request.
@@ -596,12 +596,12 @@ struct WorkspaceSymbolParams {
   /// A non-empty query string
   std::string query;
 };
-bool fromJSON(const json::Expr &, WorkspaceSymbolParams &);
+bool fromJSON(const llvm::json::Value &, WorkspaceSymbolParams &);
 
 struct ApplyWorkspaceEditParams {
   WorkspaceEdit edit;
 };
-json::Expr toJSON(const ApplyWorkspaceEditParams &);
+llvm::json::Value toJSON(const ApplyWorkspaceEditParams &);
 
 struct TextDocumentPositionParams {
   /// The text document.
@@ -610,7 +610,7 @@ struct TextDocumentPositionParams {
   /// The position inside the text document.
   Position position;
 };
-bool fromJSON(const json::Expr &, TextDocumentPositionParams &);
+bool fromJSON(const llvm::json::Value &, TextDocumentPositionParams &);
 
 enum class MarkupKind {
   PlainText,
@@ -621,7 +621,7 @@ struct MarkupContent {
   MarkupKind kind = MarkupKind::PlainText;
   std::string value;
 };
-json::Expr toJSON(const MarkupContent &MC);
+llvm::json::Value toJSON(const MarkupContent &MC);
 
 struct Hover {
   /// The hover's content
@@ -631,7 +631,7 @@ struct Hover {
   /// that is used to visualize a hover, e.g. by changing the background color.
   llvm::Optional<Range> range;
 };
-json::Expr toJSON(const Hover &H);
+llvm::json::Value toJSON(const Hover &H);
 
 /// The kind of a completion entry.
 enum class CompletionItemKind {
@@ -724,7 +724,7 @@ struct CompletionItem {
   // data?: any - A data entry field that is preserved on a completion item
   //              between a completion and a completion resolve request.
 };
-json::Expr toJSON(const CompletionItem &);
+llvm::json::Value toJSON(const CompletionItem &);
 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const CompletionItem &);
 
 bool operator<(const CompletionItem &, const CompletionItem &);
@@ -738,7 +738,7 @@ struct CompletionList {
   /// The completion items.
   std::vector<CompletionItem> items;
 };
-json::Expr toJSON(const CompletionList &);
+llvm::json::Value toJSON(const CompletionList &);
 
 /// A single parameter of a particular signature.
 struct ParameterInformation {
@@ -749,7 +749,7 @@ struct ParameterInformation {
   /// The documentation of this parameter. Optional.
   std::string documentation;
 };
-json::Expr toJSON(const ParameterInformation &);
+llvm::json::Value toJSON(const ParameterInformation &);
 
 /// Represents the signature of something callable.
 struct SignatureInformation {
@@ -763,7 +763,7 @@ struct SignatureInformation {
   /// The parameters of this signature.
   std::vector<ParameterInformation> parameters;
 };
-json::Expr toJSON(const SignatureInformation &);
+llvm::json::Value toJSON(const SignatureInformation &);
 llvm::raw_ostream &operator<<(llvm::raw_ostream &,
                               const SignatureInformation &);
 
@@ -779,7 +779,7 @@ struct SignatureHelp {
   /// The active parameter of the active signature.
   int activeParameter = 0;
 };
-json::Expr toJSON(const SignatureHelp &);
+llvm::json::Value toJSON(const SignatureHelp &);
 
 struct RenameParams {
   /// The document that was opened.
@@ -791,7 +791,7 @@ struct RenameParams {
   /// The new name of the symbol.
   std::string newName;
 };
-bool fromJSON(const json::Expr &, RenameParams &);
+bool fromJSON(const llvm::json::Value &, RenameParams &);
 
 enum class DocumentHighlightKind { Text = 1, Read = 2, Write = 3 };
 
@@ -818,7 +818,7 @@ struct DocumentHighlight {
     return LHS.kind == RHS.kind && LHS.range == RHS.range;
   }
 };
-json::Expr toJSON(const DocumentHighlight &DH);
+llvm::json::Value toJSON(const DocumentHighlight &DH);
 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const DocumentHighlight &);
 
 } // namespace clangd

Modified: clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp?rev=336549&r1=336548&r2=336549&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp (original)
+++ clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp Mon Jul  9 07:25:59 2018
@@ -15,6 +15,7 @@
 
 using namespace clang;
 using namespace clang::clangd;
+using namespace llvm;
 
 namespace {
 
@@ -27,7 +28,7 @@ struct HandlerRegisterer {
   void operator()(StringRef Method, void (ProtocolCallbacks::*Handler)(Param)) {
     // Capture pointers by value, as the lambda will outlive this object.
     auto *Callbacks = this->Callbacks;
-    Dispatcher.registerHandler(Method, [=](const json::Expr &RawParams) {
+    Dispatcher.registerHandler(Method, [=](const json::Value &RawParams) {
       typename std::remove_reference<Param>::type P;
       if (fromJSON(RawParams, P)) {
         (Callbacks->*Handler)(P);

Modified: clang-tools-extra/trunk/clangd/Trace.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Trace.cpp?rev=336549&r1=336548&r2=336549&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Trace.cpp (original)
+++ clang-tools-extra/trunk/clangd/Trace.cpp Mon Jul  9 07:25:59 2018
@@ -36,9 +36,9 @@ public:
     // calculations!
     Out << R"({"displayTimeUnit":"ns","traceEvents":[)"
         << "\n";
-    rawEvent("M", json::obj{
+    rawEvent("M", json::Object{
                       {"name", "process_name"},
-                      {"args", json::obj{{"name", "clangd"}}},
+                      {"args", json::Object{{"name", "clangd"}}},
                   });
   }
 
@@ -49,7 +49,7 @@ public:
 
   // We stash a Span object in the context. It will record the start/end,
   // and this also allows us to look up the parent Span's information.
-  Context beginSpan(llvm::StringRef Name, json::obj *Args) override {
+  Context beginSpan(llvm::StringRef Name, json::Object *Args) override {
     return Context::current().derive(
         SpanKey, llvm::make_unique<JSONSpan>(this, Name, Args));
   }
@@ -62,18 +62,17 @@ public:
     Context::current().getExisting(SpanKey)->markEnded();
   }
 
-  void instant(llvm::StringRef Name, json::obj &&Args) override {
+  void instant(llvm::StringRef Name, json::Object &&Args) override {
     captureThreadMetadata();
-    jsonEvent("i", json::obj{{"name", Name}, {"args", std::move(Args)}});
+    jsonEvent("i", json::Object{{"name", Name}, {"args", std::move(Args)}});
   }
 
   // Record an event on the current thread. ph, pid, tid, ts are set.
   // Contents must be a list of the other JSON key/values.
-  void jsonEvent(StringRef Phase, json::obj &&Contents,
-                 uint64_t TID = get_threadid(),
-                 double Timestamp = 0) {
+  void jsonEvent(StringRef Phase, json::Object &&Contents,
+                 uint64_t TID = get_threadid(), double Timestamp = 0) {
     Contents["ts"] = Timestamp ? Timestamp : timestamp();
-    Contents["tid"] = TID;
+    Contents["tid"] = int64_t(TID);
     std::lock_guard<std::mutex> Lock(Mu);
     rawEvent(Phase, std::move(Contents));
   }
@@ -81,7 +80,7 @@ public:
 private:
   class JSONSpan {
   public:
-    JSONSpan(JSONTracer *Tracer, llvm::StringRef Name, json::obj *Args)
+    JSONSpan(JSONTracer *Tracer, llvm::StringRef Name, json::Object *Args)
         : StartTime(Tracer->timestamp()), EndTime(0), Name(Name),
           TID(get_threadid()), Tracer(Tracer), Args(Args) {
       // ~JSONSpan() may run in a different thread, so we need to capture now.
@@ -102,15 +101,15 @@ private:
 
         auto FlowID = nextID();
         Tracer->jsonEvent("s",
-                          json::obj{{"id", FlowID},
-                                    {"name", "Context crosses threads"},
-                                    {"cat", "dummy"}},
+                          json::Object{{"id", FlowID},
+                                       {"name", "Context crosses threads"},
+                                       {"cat", "dummy"}},
                           (*Parent)->TID, (*Parent)->StartTime);
         Tracer->jsonEvent("f",
-                          json::obj{{"id", FlowID},
-                                    {"bp", "e"},
-                                    {"name", "Context crosses threads"},
-                                    {"cat", "dummy"}},
+                          json::Object{{"id", FlowID},
+                                       {"bp", "e"},
+                                       {"name", "Context crosses threads"},
+                                       {"cat", "dummy"}},
                           TID);
       }
     }
@@ -118,9 +117,9 @@ private:
     ~JSONSpan() {
       // Finally, record the event (ending at EndTime, not timestamp())!
       Tracer->jsonEvent("X",
-                        json::obj{{"name", std::move(Name)},
-                                  {"args", std::move(*Args)},
-                                  {"dur", EndTime - StartTime}},
+                        json::Object{{"name", std::move(Name)},
+                                     {"args", std::move(*Args)},
+                                     {"dur", EndTime - StartTime}},
                         TID, StartTime);
     }
 
@@ -130,8 +129,8 @@ private:
     }
 
   private:
-    static uint64_t nextID() {
-      static std::atomic<uint64_t> Next = {0};
+    static int64_t nextID() {
+      static std::atomic<int64_t> Next = {0};
       return Next++;
     }
 
@@ -140,17 +139,17 @@ private:
     std::string Name;
     uint64_t TID;
     JSONTracer *Tracer;
-    json::obj *Args;
+    json::Object *Args;
   };
   static Key<std::unique_ptr<JSONSpan>> SpanKey;
 
   // Record an event. ph and pid are set.
   // Contents must be a list of the other JSON key/values.
-  void rawEvent(StringRef Phase, json::obj &&Event) /*REQUIRES(Mu)*/ {
+  void rawEvent(StringRef Phase, json::Object &&Event) /*REQUIRES(Mu)*/ {
     // PID 0 represents the clangd process.
     Event["pid"] = 0;
     Event["ph"] = Phase;
-    Out << Sep << formatv(JSONFormat, json::Expr(std::move(Event)));
+    Out << Sep << formatv(JSONFormat, json::Value(std::move(Event)));
     Sep = ",\n";
   }
 
@@ -162,10 +161,10 @@ private:
       SmallString<32> Name;
       get_thread_name(Name);
       if (!Name.empty()) {
-        rawEvent("M", json::obj{
-                          {"tid", TID},
+        rawEvent("M", json::Object{
+                          {"tid", int64_t(TID)},
                           {"name", "thread_name"},
-                          {"args", json::obj{{"name", Name}}},
+                          {"args", json::Object{{"name", Name}}},
                       });
       }
     }
@@ -204,14 +203,14 @@ std::unique_ptr<EventTracer> createJSONT
 void log(const Twine &Message) {
   if (!T)
     return;
-  T->instant("Log", json::obj{{"Message", Message.str()}});
+  T->instant("Log", json::Object{{"Message", Message.str()}});
 }
 
 // Returned context owns Args.
-static Context makeSpanContext(llvm::Twine Name, json::obj *Args) {
+static Context makeSpanContext(llvm::Twine Name, json::Object *Args) {
   if (!T)
     return Context::current().clone();
-  WithContextValue WithArgs{std::unique_ptr<json::obj>(Args)};
+  WithContextValue WithArgs{std::unique_ptr<json::Object>(Args)};
   return T->beginSpan(Name.isSingleStringRef() ? Name.getSingleStringRef()
                                                : llvm::StringRef(Name.str()),
                       Args);
@@ -221,7 +220,7 @@ static Context makeSpanContext(llvm::Twi
 // The args are owned by the context though. They stick around until the
 // beginSpan() context is destroyed, when the tracing engine will consume them.
 Span::Span(llvm::Twine Name)
-    : Args(T ? new json::obj() : nullptr),
+    : Args(T ? new json::Object() : nullptr),
       RestoreCtx(makeSpanContext(Name, Args)) {}
 
 Span::~Span() {

Modified: clang-tools-extra/trunk/clangd/Trace.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Trace.h?rev=336549&r1=336548&r2=336549&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Trace.h (original)
+++ clang-tools-extra/trunk/clangd/Trace.h Mon Jul  9 07:25:59 2018
@@ -20,8 +20,8 @@
 
 #include "Context.h"
 #include "Function.h"
-#include "JSONExpr.h"
 #include "llvm/ADT/Twine.h"
+#include "llvm/Support/JSON.h"
 #include "llvm/Support/raw_ostream.h"
 
 namespace clang {
@@ -39,7 +39,7 @@ public:
   /// Usually implementations will store an object in the returned context
   /// whose destructor records the end of the event.
   /// The args are *Args, only complete when the event ends.
-  virtual Context beginSpan(llvm::StringRef Name, json::obj *Args) = 0;
+  virtual Context beginSpan(llvm::StringRef Name, llvm::json::Object *Args) = 0;
   // Called when a Span is destroyed (it may still be active on other threads).
   // beginSpan() and endSpan() will always form a proper stack on each thread.
   // The Context returned by beginSpan is active, but Args is not ready.
@@ -48,7 +48,7 @@ public:
   virtual void endSpan(){};
 
   /// Called for instant events.
-  virtual void instant(llvm::StringRef Name, json::obj &&Args) = 0;
+  virtual void instant(llvm::StringRef Name, llvm::json::Object &&Args) = 0;
 };
 
 /// Sets up a global EventTracer that consumes events produced by Span and
@@ -87,7 +87,7 @@ public:
 
   /// Mutable metadata, if this span is interested.
   /// Prefer to use SPAN_ATTACH rather than accessing this directly.
-  json::obj *const Args;
+  llvm::json::Object *const Args;
 
 private:
   WithContext RestoreCtx;

Modified: clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt?rev=336549&r1=336548&r2=336549&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt Mon Jul  9 07:25:59 2018
@@ -23,7 +23,6 @@ add_extra_unittest(ClangdTests
   GlobalCompilationDatabaseTests.cpp
   HeadersTests.cpp
   IndexTests.cpp
-  JSONExprTests.cpp
   QualityTests.cpp
   SourceCodeTests.cpp
   SymbolCollectorTests.cpp

Removed: clang-tools-extra/trunk/unittests/clangd/JSONExprTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/JSONExprTests.cpp?rev=336548&view=auto
==============================================================================
--- clang-tools-extra/trunk/unittests/clangd/JSONExprTests.cpp (original)
+++ clang-tools-extra/trunk/unittests/clangd/JSONExprTests.cpp (removed)
@@ -1,293 +0,0 @@
-//===-- JSONExprTests.cpp - JSON expression unit tests ----------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "JSONExpr.h"
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
-namespace clang {
-namespace clangd {
-namespace json {
-
-namespace {
-
-std::string s(const Expr &E) { return llvm::formatv("{0}", E).str(); }
-std::string sp(const Expr &E) { return llvm::formatv("{0:2}", E).str(); }
-
-TEST(JSONExprTests, Types) {
-  EXPECT_EQ("true", s(true));
-  EXPECT_EQ("null", s(nullptr));
-  EXPECT_EQ("2.5", s(2.5));
-  EXPECT_EQ(R"("foo")", s("foo"));
-  EXPECT_EQ("[1,2,3]", s({1, 2, 3}));
-  EXPECT_EQ(R"({"x":10,"y":20})", s(obj{{"x", 10}, {"y", 20}}));
-}
-
-TEST(JSONExprTests, Constructors) {
-  // Lots of edge cases around empty and singleton init lists.
-  EXPECT_EQ("[[[3]]]", s({{{3}}}));
-  EXPECT_EQ("[[[]]]", s({{{}}}));
-  EXPECT_EQ("[[{}]]", s({{obj{}}}));
-  EXPECT_EQ(R"({"A":{"B":{}}})", s(obj{{"A", obj{{"B", obj{}}}}}));
-  EXPECT_EQ(R"({"A":{"B":{"X":"Y"}}})",
-            s(obj{{"A", obj{{"B", obj{{"X", "Y"}}}}}}));
-  EXPECT_EQ("null", s(llvm::Optional<double>()));
-  EXPECT_EQ("2.5", s(llvm::Optional<double>(2.5)));
-}
-
-TEST(JSONExprTests, StringOwnership) {
-  char X[] = "Hello";
-  Expr Alias = static_cast<const char *>(X);
-  X[1] = 'a';
-  EXPECT_EQ(R"("Hallo")", s(Alias));
-
-  std::string Y = "Hello";
-  Expr Copy = Y;
-  Y[1] = 'a';
-  EXPECT_EQ(R"("Hello")", s(Copy));
-}
-
-TEST(JSONExprTests, CanonicalOutput) {
-  // Objects are sorted (but arrays aren't)!
-  EXPECT_EQ(R"({"a":1,"b":2,"c":3})", s(obj{{"a", 1}, {"c", 3}, {"b", 2}}));
-  EXPECT_EQ(R"(["a","c","b"])", s({"a", "c", "b"}));
-  EXPECT_EQ("3", s(3.0));
-}
-
-TEST(JSONExprTests, Escaping) {
-  std::string test = {
-      0,                    // Strings may contain nulls.
-      '\b',   '\f',         // Have mnemonics, but we escape numerically.
-      '\r',   '\n',   '\t', // Escaped with mnemonics.
-      'S',    '\"',   '\\', // Printable ASCII characters.
-      '\x7f',               // Delete is not escaped.
-      '\xce', '\x94',       // Non-ASCII UTF-8 is not escaped.
-  };
-
-  std::string teststring = R"("\u0000\u0008\u000c\r\n\tS\"\\)"
-                           "\x7f\xCE\x94\"";
-
-  EXPECT_EQ(teststring, s(test));
-
-  EXPECT_EQ(R"({"object keys are\nescaped":true})",
-            s(obj{{"object keys are\nescaped", true}}));
-}
-
-TEST(JSONExprTests, PrettyPrinting) {
-  const char str[] = R"({
-  "empty_array": [],
-  "empty_object": {},
-  "full_array": [
-    1,
-    null
-  ],
-  "full_object": {
-    "nested_array": [
-      {
-        "property": "value"
-      }
-    ]
-  }
-})";
-
-  EXPECT_EQ(str, sp(obj{
-                     {"empty_object", obj{}},
-                     {"empty_array", {}},
-                     {"full_array", {1, nullptr}},
-                     {"full_object",
-                      obj{
-                          {"nested_array",
-                           {obj{
-                               {"property", "value"},
-                           }}},
-                      }},
-                 }));
-}
-
-TEST(JSONTest, Parse) {
-  auto Compare = [](llvm::StringRef S, Expr Expected) {
-    if (auto E = parse(S)) {
-      // Compare both string forms and with operator==, in case we have bugs.
-      EXPECT_EQ(*E, Expected);
-      EXPECT_EQ(sp(*E), sp(Expected));
-    } else {
-      handleAllErrors(E.takeError(), [S](const llvm::ErrorInfoBase &E) {
-        FAIL() << "Failed to parse JSON >>> " << S << " <<<: " << E.message();
-      });
-    }
-  };
-
-  Compare(R"(true)", true);
-  Compare(R"(false)", false);
-  Compare(R"(null)", nullptr);
-
-  Compare(R"(42)", 42);
-  Compare(R"(2.5)", 2.5);
-  Compare(R"(2e50)", 2e50);
-  Compare(R"(1.2e3456789)", std::numeric_limits<double>::infinity());
-
-  Compare(R"("foo")", "foo");
-  Compare(R"("\"\\\b\f\n\r\t")", "\"\\\b\f\n\r\t");
-  Compare(R"("\u0000")", llvm::StringRef("\0", 1));
-  Compare("\"\x7f\"", "\x7f");
-  Compare(R"("\ud801\udc37")", u8"\U00010437"); // UTF16 surrogate pair escape.
-  Compare("\"\xE2\x82\xAC\xF0\x9D\x84\x9E\"", u8"\u20ac\U0001d11e"); // UTF8
-  Compare(
-      R"("LoneLeading=\ud801, LoneTrailing=\udc01, LeadingLeadingTrailing=\ud801\ud801\udc37")",
-      u8"LoneLeading=\ufffd, LoneTrailing=\ufffd, "
-      u8"LeadingLeadingTrailing=\ufffd\U00010437"); // Invalid unicode.
-
-  Compare(R"({"":0,"":0})", obj{{"", 0}});
-  Compare(R"({"obj":{},"arr":[]})", obj{{"obj", obj{}}, {"arr", {}}});
-  Compare(R"({"\n":{"\u0000":[[[[]]]]}})",
-          obj{{"\n", obj{
-                         {llvm::StringRef("\0", 1), {{{{}}}}},
-                     }}});
-  Compare("\r[\n\t] ", {});
-}
-
-TEST(JSONTest, ParseErrors) {
-  auto ExpectErr = [](llvm::StringRef Msg, llvm::StringRef S) {
-    if (auto E = parse(S)) {
-      // Compare both string forms and with operator==, in case we have bugs.
-      FAIL() << "Parsed JSON >>> " << S << " <<< but wanted error: " << Msg;
-    } else {
-      handleAllErrors(E.takeError(), [S, Msg](const llvm::ErrorInfoBase &E) {
-        EXPECT_THAT(E.message(), testing::HasSubstr(Msg)) << S;
-      });
-    }
-  };
-  ExpectErr("Unexpected EOF", "");
-  ExpectErr("Unexpected EOF", "[");
-  ExpectErr("Text after end of document", "[][]");
-  ExpectErr("Invalid bareword", "fuzzy");
-  ExpectErr("Expected , or ]", "[2?]");
-  ExpectErr("Expected object key", "{a:2}");
-  ExpectErr("Expected : after object key", R"({"a",2})");
-  ExpectErr("Expected , or } after object property", R"({"a":2 "b":3})");
-  ExpectErr("Expected JSON value", R"([&%!])");
-  ExpectErr("Invalid number", "1e1.0");
-  ExpectErr("Unterminated string", R"("abc\"def)");
-  ExpectErr("Control character in string", "\"abc\ndef\"");
-  ExpectErr("Invalid escape sequence", R"("\030")");
-  ExpectErr("Invalid \\u escape sequence", R"("\usuck")");
-  ExpectErr("[3:3, byte=19]", R"({
-  "valid": 1,
-  invalid: 2
-})");
-}
-
-TEST(JSONTest, Inspection) {
-  llvm::Expected<Expr> Doc = parse(R"(
-    {
-      "null": null,
-      "boolean": false,
-      "number": 2.78,
-      "string": "json",
-      "array": [null, true, 3.14, "hello", [1,2,3], {"time": "arrow"}],
-      "object": {"fruit": "banana"}
-    }
-  )");
-  EXPECT_TRUE(!!Doc);
-
-  obj *O = Doc->asObject();
-  ASSERT_TRUE(O);
-
-  EXPECT_FALSE(O->getNull("missing"));
-  EXPECT_FALSE(O->getNull("boolean"));
-  EXPECT_TRUE(O->getNull("null"));
-
-  EXPECT_EQ(O->getNumber("number"), llvm::Optional<double>(2.78));
-  EXPECT_FALSE(O->getInteger("number"));
-  EXPECT_EQ(O->getString("string"), llvm::Optional<llvm::StringRef>("json"));
-  ASSERT_FALSE(O->getObject("missing"));
-  ASSERT_FALSE(O->getObject("array"));
-  ASSERT_TRUE(O->getObject("object"));
-  EXPECT_EQ(*O->getObject("object"), (obj{{"fruit", "banana"}}));
-
-  ary *A = O->getArray("array");
-  ASSERT_TRUE(A);
-  EXPECT_EQ(A->getBoolean(1), llvm::Optional<bool>(true));
-  ASSERT_TRUE(A->getArray(4));
-  EXPECT_EQ(*A->getArray(4), (ary{1, 2, 3}));
-  EXPECT_EQ(A->getArray(4)->getInteger(1), llvm::Optional<int64_t>(2));
-  int I = 0;
-  for (Expr &E : *A) {
-    if (I++ == 5) {
-      ASSERT_TRUE(E.asObject());
-      EXPECT_EQ(E.asObject()->getString("time"),
-                llvm::Optional<llvm::StringRef>("arrow"));
-    } else
-      EXPECT_FALSE(E.asObject());
-  }
-}
-
-// Sample struct with typical JSON-mapping rules.
-struct CustomStruct {
-  CustomStruct() : B(false) {}
-  CustomStruct(std::string S, llvm::Optional<int> I, bool B)
-      : S(S), I(I), B(B) {}
-  std::string S;
-  llvm::Optional<int> I;
-  bool B;
-};
-inline bool operator==(const CustomStruct &L, const CustomStruct &R) {
-  return L.S == R.S && L.I == R.I && L.B == R.B;
-}
-inline std::ostream &operator<<(std::ostream &OS, const CustomStruct &S) {
-  return OS << "(" << S.S << ", " << (S.I ? std::to_string(*S.I) : "None")
-            << ", " << S.B << ")";
-}
-bool fromJSON(const json::Expr &E, CustomStruct &R) {
-  ObjectMapper O(E);
-  if (!O || !O.map("str", R.S) || !O.map("int", R.I))
-    return false;
-  O.map("bool", R.B);
-  return true;
-}
-
-TEST(JSONTest, Deserialize) {
-  std::map<std::string, std::vector<CustomStruct>> R;
-  CustomStruct ExpectedStruct = {"foo", 42, true};
-  std::map<std::string, std::vector<CustomStruct>> Expected;
-  Expr J = obj{{"foo", ary{
-                           obj{
-                               {"str", "foo"},
-                               {"int", 42},
-                               {"bool", true},
-                               {"unknown", "ignored"},
-                           },
-                           obj{{"str", "bar"}},
-                           obj{
-                               {"str", "baz"},
-                               {"bool", "string"}, // OK, deserialize ignores.
-                           },
-                       }}};
-  Expected["foo"] = {
-      CustomStruct("foo", 42, true),
-      CustomStruct("bar", llvm::None, false),
-      CustomStruct("baz", llvm::None, false),
-  };
-  ASSERT_TRUE(fromJSON(J, R));
-  EXPECT_EQ(R, Expected);
-
-  CustomStruct V;
-  EXPECT_FALSE(fromJSON(nullptr, V)) << "Not an object " << V;
-  EXPECT_FALSE(fromJSON(obj{}, V)) << "Missing required field " << V;
-  EXPECT_FALSE(fromJSON(obj{{"str", 1}}, V)) << "Wrong type " << V;
-  // Optional<T> must parse as the correct type if present.
-  EXPECT_FALSE(fromJSON(obj{{"str", 1}, {"int", "string"}}, V))
-      << "Wrong type for Optional<T> " << V;
-}
-
-} // namespace
-} // namespace json
-} // namespace clangd
-} // namespace clang




More information about the cfe-commits mailing list