summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam McCall <sam.mccall@gmail.com>2018-07-09 14:25:59 +0000
committerSam McCall <sam.mccall@gmail.com>2018-07-09 14:25:59 +0000
commitf89b65df5cc6150a4ea2ef9c74f47f3c5e500380 (patch)
treea3210cc7daaa92e83bf797f3b8df4ff4dd6c952e
parentbb30e881eedbcff9e1062a8f5a54787f51e9b51f (diff)
[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
-rw-r--r--clang-tools-extra/clangd/CMakeLists.txt1
-rw-r--r--clang-tools-extra/clangd/ClangdLSPServer.cpp41
-rw-r--r--clang-tools-extra/clangd/CodeComplete.cpp4
-rw-r--r--clang-tools-extra/clangd/JSONExpr.cpp554
-rw-r--r--clang-tools-extra/clangd/JSONExpr.h586
-rw-r--r--clang-tools-extra/clangd/JSONRPCDispatcher.cpp48
-rw-r--r--clang-tools-extra/clangd/JSONRPCDispatcher.h12
-rw-r--r--clang-tools-extra/clangd/Protocol.cpp182
-rw-r--r--clang-tools-extra/clangd/Protocol.h124
-rw-r--r--clang-tools-extra/clangd/ProtocolHandlers.cpp3
-rw-r--r--clang-tools-extra/clangd/Trace.cpp63
-rw-r--r--clang-tools-extra/clangd/Trace.h8
-rw-r--r--clang-tools-extra/unittests/clangd/CMakeLists.txt1
-rw-r--r--clang-tools-extra/unittests/clangd/JSONExprTests.cpp293
14 files changed, 245 insertions, 1675 deletions
diff --git a/clang-tools-extra/clangd/CMakeLists.txt b/clang-tools-extra/clangd/CMakeLists.txt
index 0f0536aff37..b55563bf249 100644
--- a/clang-tools-extra/clangd/CMakeLists.txt
+++ b/clang-tools-extra/clangd/CMakeLists.txt
@@ -23,7 +23,6 @@ add_clang_library(clangDaemon
FuzzyMatch.cpp
GlobalCompilationDatabase.cpp
Headers.cpp
- JSONExpr.cpp
JSONRPCDispatcher.cpp
Logger.cpp
Protocol.cpp
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp
index 385768a14b0..5ea1f793ba0 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -18,6 +18,7 @@
using namespace clang::clangd;
using namespace clang;
+using namespace llvm;
namespace {
@@ -87,25 +88,25 @@ void ClangdLSPServer::onInitialize(InitializeParams &Params) {
}
}
- 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(InitializeParams &Params) {
{"documentSymbolProvider", true},
{"workspaceSymbolProvider", true},
{"executeCommandProvider",
- json::obj{
+ json::Object{
{"commands", {ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND}},
}},
}}}});
@@ -212,7 +213,7 @@ void ClangdLSPServer::onWorkspaceSymbol(WorkspaceSymbolParams &Params) {
for (auto &Sym : *Items)
Sym.kind = adjustKindToCapability(Sym.kind, SupportedSymbolKinds);
- reply(json::ary(*Items));
+ reply(json::Array(*Items));
});
}
@@ -258,7 +259,7 @@ void ClangdLSPServer::onDocumentOnTypeFormatting(
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::onDocumentRangeFormatting(
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::onDocumentFormatting(DocumentFormattingParams &Params) {
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(DocumentSymbolParams &Params) {
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(CodeActionParams &Params) {
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(TextDocumentPositionParams &Params) {
if (!Items)
return replyError(ErrorCode::InvalidParams,
llvm::toString(Items.takeError()));
- reply(json::ary(*Items));
+ reply(json::Array(*Items));
});
}
@@ -380,7 +381,7 @@ void ClangdLSPServer::onDocumentHighlight(TextDocumentPositionParams &Params) {
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, JSONStreamStyle InputStyle) {
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::getFixes(StringRef File,
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(PathRef File,
}
// 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)},
}},
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp
index be252b52b64..ded1113d117 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -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.
diff --git a/clang-tools-extra/clangd/JSONExpr.cpp b/clang-tools-extra/clangd/JSONExpr.cpp
deleted file mode 100644
index 3f87c286f1d..00000000000
--- a/clang-tools-extra/clangd/JSONExpr.cpp
+++ /dev/null
@@ -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;
- };
- });
-}
diff --git a/clang-tools-extra/clangd/JSONExpr.h b/clang-tools-extra/clangd/JSONExpr.h
deleted file mode 100644
index 419932f09a5..00000000000
--- a/clang-tools-extra/clangd/JSONExpr.h
+++ /dev/null
@@ -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
diff --git a/clang-tools-extra/clangd/JSONRPCDispatcher.cpp b/clang-tools-extra/clangd/JSONRPCDispatcher.cpp
index f441edecda6..f81af3d1dda 100644
--- a/clang-tools-extra/clangd/JSONRPCDispatcher.cpp
+++ b/clang-tools-extra/clangd/JSONRPCDispatcher.cpp
@@ -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 &Message) {
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(StringRef Method, Handler H) {
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::Expr &Message, JSONOutput &Out) const {
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);
diff --git a/clang-tools-extra/clangd/JSONRPCDispatcher.h b/clang-tools-extra/clangd/JSONRPCDispatcher.h
index 502b5a3f746..3c0387ca2ef 100644
--- a/clang-tools-extra/clangd/JSONRPCDispatcher.h
+++ b/clang-tools-extra/clangd/JSONRPCDispatcher.h
@@ -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;
diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp
index 64f6bd60c02..a35e6ba8d27 100644
--- a/clang-tools-extra/clangd/Protocol.cpp
+++ b/clang-tools-extra/clangd/Protocol.cpp
@@ -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, URIForFile &R) {
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_ostream &OS, const Position &P) {
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_ostream &OS, const Range &R) {
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_ostream &OS, const Location &L) {
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, Metadata &R) {
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_ostream &OS, const TextEdit &TE) {
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, TraceLevel &Out) {
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, CompletionItemClientCapabilities &R) {
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, CompletionClientCapabilities &R) {
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, SymbolKind &Out) {
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::vector<SymbolKind> &Out) {
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(SymbolKind Kind,
}
}
-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, TextDocumentClientCapabilities &R) {
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, ClientCapabilities &R) {
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, InitializeParams &R) {
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, FileChangeType &Out) {
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, Diagnostic &R) {
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_ostream &OS, const Diagnostic &D) {
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, ExecuteCommandParams &R) {
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_ostream &O,
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 Kind) {
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 &CI) {
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, const CompletionItem &R) {
(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_ostream &O,
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_ostream &O,
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);
}
diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h
index 999b8432b76..e5c29669fbb 100644
--- a/clang-tools-extra/clangd/Protocol.h
+++ b/clang-tools-extra/clangd/Protocol.h
@@ -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_cast<size_t>(SymbolKind::File);
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
diff --git a/clang-tools-extra/clangd/ProtocolHandlers.cpp b/clang-tools-extra/clangd/ProtocolHandlers.cpp
index 479bf527039..400f3f5d0f3 100644
--- a/clang-tools-extra/clangd/ProtocolHandlers.cpp
+++ b/clang-tools-extra/clangd/ProtocolHandlers.cpp
@@ -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);
diff --git a/clang-tools-extra/clangd/Trace.cpp b/clang-tools-extra/clangd/Trace.cpp
index ccbf6dc2a4e..24c1fdd74e6 100644
--- a/clang-tools-extra/clangd/Trace.cpp
+++ b/clang-tools-extra/clangd/Trace.cpp
@@ -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> createJSONTracer(llvm::raw_ostream &OS,
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::Twine Name, json::obj *Args) {
// 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() {
diff --git a/clang-tools-extra/clangd/Trace.h b/clang-tools-extra/clangd/Trace.h
index 131ace55908..0c4c461855d 100644
--- a/clang-tools-extra/clangd/Trace.h
+++ b/clang-tools-extra/clangd/Trace.h
@@ -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;
diff --git a/clang-tools-extra/unittests/clangd/CMakeLists.txt b/clang-tools-extra/unittests/clangd/CMakeLists.txt
index 2d9853dd8dd..db694ad6cee 100644
--- a/clang-tools-extra/unittests/clangd/CMakeLists.txt
+++ b/clang-tools-extra/unittests/clangd/CMakeLists.txt
@@ -23,7 +23,6 @@ add_extra_unittest(ClangdTests
GlobalCompilationDatabaseTests.cpp
HeadersTests.cpp
IndexTests.cpp
- JSONExprTests.cpp
QualityTests.cpp
SourceCodeTests.cpp
SymbolCollectorTests.cpp
diff --git a/clang-tools-extra/unittests/clangd/JSONExprTests.cpp b/clang-tools-extra/unittests/clangd/JSONExprTests.cpp
deleted file mode 100644
index 3a41ac2eeea..00000000000
--- a/clang-tools-extra/unittests/clangd/JSONExprTests.cpp
+++ /dev/null
@@ -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