[clang-tools-extra] r317486 - Adds a json::Expr type to represent intermediate JSON expressions.
Galina Kistanova via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 6 16:27:56 PST 2017
One more broken builder:
http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast/builds/13294
On Mon, Nov 6, 2017 at 4:24 PM, Galina Kistanova <gkistanova at gmail.com>
wrote:
> Hello Sam,
>
> It looks like this commit broke one our builders:
> http://lab.llvm.org:8011/builders/clang-x86_64-linux-abi-test/builds/17766
>
> . . .
> FAILED: /usr/bin/c++ -DGTEST_HAS_RTTI=0 -D_DEBUG -D_GNU_SOURCE
> -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
> -Itools/clang/tools/extra/clangd -I/home/buildslave/slave_as-
> bldslv8/clang-x86_64-linux-abi-test/llvm/tools/clang/tools/extra/clangd
> -I/home/buildslave/slave_as-bldslv8/clang-x86_64-linux-
> abi-test/llvm/tools/clang/include -Itools/clang/include -Iinclude
> -I/home/buildslave/slave_as-bldslv8/clang-x86_64-linux-abi-test/llvm/include
> -fPIC -fvisibility-inlines-hidden -std=c++11 -Wall -W -Wno-unused-parameter
> -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic
> -Wno-long-long -Wno-maybe-uninitialized -Wdelete-non-virtual-dtor
> -Wno-comment -ffunction-sections -fdata-sections -fno-common
> -Woverloaded-virtual -fno-strict-aliasing -O3 -UNDEBUG -fno-exceptions
> -fno-rtti -MMD -MT tools/clang/tools/extra/clangd/CMakeFiles/clangDaemon.dir/JSONExpr.cpp.o
> -MF tools/clang/tools/extra/clangd/CMakeFiles/clangDaemon.dir/JSONExpr.cpp.o.d
> -o tools/clang/tools/extra/clangd/CMakeFiles/clangDaemon.dir/JSONExpr.cpp.o
> -c /home/buildslave/slave_as-bldslv8/clang-x86_64-linux-
> abi-test/llvm/tools/clang/tools/extra/clangd/JSONExpr.cpp
> /home/buildslave/slave_as-bldslv8/clang-x86_64-linux-
> abi-test/llvm/tools/clang/tools/extra/clangd/JSONExpr.cpp:184:65: error:
> ‘llvm::raw_ostream& clang::clangd::json::operator<<(llvm::raw_ostream&,
> const clang::clangd::json::Expr&)’ should have been declared inside
> ‘clang::clangd::json’
> const Expr &E) {
> ^
>
> Please have a look?
>
> Thanks
>
> Galina
>
>
> On Mon, Nov 6, 2017 at 7:40 AM, Sam McCall via cfe-commits <
> cfe-commits at lists.llvm.org> wrote:
>
>> Author: sammccall
>> Date: Mon Nov 6 07:40:30 2017
>> New Revision: 317486
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=317486&view=rev
>> Log:
>> Adds a json::Expr type to represent intermediate JSON expressions.
>>
>> Summary:
>> This form can be created with a nice clang-format-friendly literal syntax,
>> and gets escaping right. It knows how to call unparse() on our Protocol
>> types.
>> All the places where we pass around JSON internally now use this type.
>>
>> Object properties are sorted (stored as std::map) and so serialization is
>> canonicalized, with optional prettyprinting (triggered by a -pretty flag).
>> This makes the lit tests much nicer to read and somewhat nicer to debug.
>> (Unfortunately the completion tests use CHECK-DAG, which only has
>> line-granularity, so pretty-printing is disabled there. In future we
>> could make completion ordering deterministic, or switch to unittests).
>>
>> Compared to the current approach, it has some efficiencies like avoiding
>> copies
>> of string literals used as object keys, but is probably slower overall.
>> I think the code/test quality benefits are worth it.
>>
>> This patch doesn't attempt to do anything about JSON *parsing*.
>> It takes direction from the proposal in this doc[1], but is limited in
>> scope
>> and visibility, for now.
>> I am of half a mind just to use Expr as the target of a parser, and maybe
>> do a
>> little string deduplication, but not bother with clever memory allocation.
>> That would be simple, and fast enough for clangd...
>> [1] https://docs.google.com/document/d/1OEF9IauWwNuSigZzvvbjc1cV
>> S1uGHRyGTXaoy3DjqM4/edit
>>
>> +cc d0k so he can tell me not to use std::map.
>>
>> Reviewers: ioeric, malaperle
>>
>> Subscribers: bkramer, ilya-biryukov, mgorny, klimek
>>
>> Differential Revision: https://reviews.llvm.org/D39435
>>
>> Added:
>> clang-tools-extra/trunk/clangd/JSONExpr.cpp
>> clang-tools-extra/trunk/clangd/JSONExpr.h
>> clang-tools-extra/trunk/unittests/clangd/JSONExprTests.cpp
>> Modified:
>> clang-tools-extra/trunk/clangd/CMakeLists.txt
>> clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
>> clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp
>> clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h
>> clang-tools-extra/trunk/clangd/Protocol.cpp
>> clang-tools-extra/trunk/clangd/Protocol.h
>> clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp
>> clang-tools-extra/trunk/test/clangd/authority-less-uri.test
>> clang-tools-extra/trunk/test/clangd/completion-items-kinds.test
>> clang-tools-extra/trunk/test/clangd/completion-priorities.test
>> clang-tools-extra/trunk/test/clangd/completion-qualifiers.test
>> clang-tools-extra/trunk/test/clangd/completion-snippet.test
>> clang-tools-extra/trunk/test/clangd/completion.test
>> clang-tools-extra/trunk/test/clangd/definitions.test
>> clang-tools-extra/trunk/test/clangd/diagnostics-preamble.test
>> clang-tools-extra/trunk/test/clangd/diagnostics.test
>> clang-tools-extra/trunk/test/clangd/did-change-watch-files.test
>> clang-tools-extra/trunk/test/clangd/execute-command.test
>> clang-tools-extra/trunk/test/clangd/extra-flags.test
>> clang-tools-extra/trunk/test/clangd/fixits.test
>> clang-tools-extra/trunk/test/clangd/formatting.test
>> clang-tools-extra/trunk/test/clangd/initialize-params-invalid.test
>> clang-tools-extra/trunk/test/clangd/initialize-params.test
>> clang-tools-extra/trunk/test/clangd/input-mirror.test
>> clang-tools-extra/trunk/test/clangd/protocol.test
>> clang-tools-extra/trunk/test/clangd/signature-help.test
>> clang-tools-extra/trunk/test/clangd/unsupported-method.test
>> clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt
>>
>> Modified: clang-tools-extra/trunk/clangd/CMakeLists.txt
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> clangd/CMakeLists.txt?rev=317486&r1=317485&r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/clangd/CMakeLists.txt (original)
>> +++ clang-tools-extra/trunk/clangd/CMakeLists.txt Mon Nov 6 07:40:30
>> 2017
>> @@ -10,6 +10,7 @@ add_clang_library(clangDaemon
>> DraftStore.cpp
>> GlobalCompilationDatabase.cpp
>> JSONRPCDispatcher.cpp
>> + JSONExpr.cpp
>> Logger.cpp
>> Protocol.cpp
>> ProtocolHandlers.cpp
>>
>> Modified: clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> clangd/ClangdLSPServer.cpp?rev=317486&r1=317485&r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp (original)
>> +++ clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp Mon Nov 6
>> 07:40:30 2017
>> @@ -20,35 +20,46 @@ namespace {
>> std::vector<TextEdit>
>> replacementsToEdits(StringRef Code,
>> const std::vector<tooling::Replacement>
>> &Replacements) {
>> - std::vector<TextEdit> Edits;
>> // Turn the replacements into the format specified by the Language
>> Server
>> - // Protocol.
>> + // Protocol. Fuse them into one big JSON array.
>> + std::vector<TextEdit> Edits;
>> for (auto &R : Replacements) {
>> Range ReplacementRange = {
>> offsetToPosition(Code, R.getOffset()),
>> offsetToPosition(Code, R.getOffset() + R.getLength())};
>> Edits.push_back({ReplacementRange, R.getReplacementText()});
>> }
>> -
>> return Edits;
>> }
>>
>> } // namespace
>>
>> void ClangdLSPServer::onInitialize(Ctx C, InitializeParams &Params) {
>> - C.reply(
>> - R"({"capabilities":{
>> - "textDocumentSync": 1,
>> - "documentFormattingProvider": true,
>> - "documentRangeFormattingProvider": true,
>> - "documentOnTypeFormattingProvider":
>> {"firstTriggerCharacter":"}","moreTriggerCharacter":[]},
>> - "codeActionProvider": true,
>> - "completionProvider": {"resolveProvider": false,
>> "triggerCharacters": [".",">",":"]},
>> - "signatureHelpProvider": {"triggerCharacters": ["(",","]},
>> - "definitionProvider": true,
>> - "executeCommandProvider": {"commands": [")" +
>> - ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND + R"("]}
>> - }})");
>> + C.reply(json::obj{
>> + {"textDocumentSync", 1},
>> + {"documentFormattingProvider", true},
>> + {"documentRangeFormattingProvider", true},
>> + {"documentOnTypeFormattingProvider",
>> + json::obj{
>> + {"firstTriggerCharacter", "}"},
>> + {"moreTriggerCharacter", {}},
>> + }},
>> + {"codeActionProvider", true},
>> + {"completionProvider",
>> + json::obj{
>> + {"resolveProvider", false},
>> + {"triggerCharacters", {".", ">", ":"}},
>> + }},
>> + {"signatureHelpProvider",
>> + json::obj{
>> + {"triggerCharacters", {"(", ","}},
>> + }},
>> + {"definitionProvider", true},
>> + {"executeCommandProvider",
>> + json::obj{
>> + {"commands", {ExecuteCommandParams::CLANGD_
>> APPLY_FIX_COMMAND}},
>> + }},
>> + });
>> if (Params.rootUri && !Params.rootUri->file.empty())
>> Server.setRootPath(Params.rootUri->file);
>> else if (Params.rootPath && !Params.rootPath->empty())
>> @@ -58,7 +69,7 @@ void ClangdLSPServer::onInitialize(Ctx C
>> void ClangdLSPServer::onShutdown(Ctx C, ShutdownParams &Params) {
>> // Do essentially nothing, just say we're ready to exit.
>> ShutdownRequestReceived = true;
>> - C.reply("null");
>> + C.reply(nullptr);
>> }
>>
>> void ClangdLSPServer::onExit(Ctx C, ExitParams &Params) { IsDone = true;
>> }
>> @@ -98,7 +109,7 @@ void ClangdLSPServer::onCommand(Ctx C, E
>>
>> ApplyWorkspaceEditParams ApplyEdit;
>> ApplyEdit.edit = *Params.workspaceEdit;
>> - C.reply("\"Fix applied.\"");
>> + C.reply("Fix applied.");
>> // We don't need the response so id == 1 is OK.
>> // Ideally, we would wait for the response and if there is no error,
>> we
>> // would reply success/failure to the original RPC.
>> @@ -121,51 +132,45 @@ void ClangdLSPServer::onDocumentOnTypeFo
>> Ctx C, DocumentOnTypeFormattingParams &Params) {
>> auto File = Params.textDocument.uri.file;
>> std::string Code = Server.getDocument(File);
>> - std::string Edits = TextEdit::unparse(
>> - replacementsToEdits(Code, Server.formatOnType(File,
>> Params.position)));
>> - C.reply(Edits);
>> + C.reply(json::ary(
>> + replacementsToEdits(Code, Server.formatOnType(File,
>> Params.position))));
>> }
>>
>> void ClangdLSPServer::onDocumentRangeFormatting(
>> Ctx C, DocumentRangeFormattingParams &Params) {
>> auto File = Params.textDocument.uri.file;
>> std::string Code = Server.getDocument(File);
>> - std::string Edits = TextEdit::unparse(
>> - replacementsToEdits(Code, Server.formatRange(File, Params.range)));
>> - C.reply(Edits);
>> + C.reply(json::ary(
>> + replacementsToEdits(Code, Server.formatRange(File,
>> Params.range))));
>> }
>>
>> void ClangdLSPServer::onDocumentFormatting(Ctx C,
>> DocumentFormattingParams
>> &Params) {
>> auto File = Params.textDocument.uri.file;
>> std::string Code = Server.getDocument(File);
>> - std::string Edits =
>> - TextEdit::unparse(replacementsToEdits(Code,
>> Server.formatFile(File)));
>> - C.reply(Edits);
>> + C.reply(json::ary(replacementsToEdits(Code,
>> Server.formatFile(File))));
>> }
>>
>> void ClangdLSPServer::onCodeAction(Ctx C, CodeActionParams &Params) {
>> // We provide a code action for each diagnostic at the requested
>> location
>> // which has FixIts available.
>> std::string Code = Server.getDocument(Params.textDocument.uri.file);
>> - std::string Commands;
>> + json::ary Commands;
>> for (Diagnostic &D : Params.context.diagnostics) {
>> std::vector<clang::tooling::Replacement> Fixes =
>> getFixIts(Params.textDocument.uri.file, D);
>> auto Edits = replacementsToEdits(Code, Fixes);
>> - WorkspaceEdit WE;
>> - WE.changes = {{llvm::yaml::escape(Params.textDocument.uri.uri),
>> Edits}};
>> -
>> - if (!Edits.empty())
>> - Commands +=
>> - R"({"title":"Apply FixIt ')" + llvm::yaml::escape(D.message) +
>> - R"('", "command": ")" +
>> - ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND +
>> - R"(", "arguments": [)" + WorkspaceEdit::unparse(WE) + R"(]},)";
>> + if (!Edits.empty()) {
>> + WorkspaceEdit WE;
>> + WE.changes = {{Params.textDocument.uri.uri, std::move(Edits)}};
>> + Commands.push_back(json::obj{
>> + {"title", llvm::formatv("Apply FixIt {0}", D.message)},
>> + {"command", ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND},
>> + {"arguments", {WE}},
>> + });
>> + }
>> }
>> - if (!Commands.empty())
>> - Commands.pop_back();
>> - C.reply("[" + Commands + "]");
>> + C.reply(std::move(Commands));
>> }
>>
>> void ClangdLSPServer::onCompletion(Ctx C, TextDocumentPositionParams
>> &Params) {
>> @@ -177,15 +182,7 @@ void ClangdLSPServer::onCompletion(Ctx C
>> // had an API that would allow to attach
>> callbacks to
>> // futures returned by ClangdServer.
>> .Value;
>> -
>> - std::string Completions;
>> - for (const auto &Item : Items) {
>> - Completions += CompletionItem::unparse(Item);
>> - Completions += ",";
>> - }
>> - if (!Completions.empty())
>> - Completions.pop_back();
>> - C.reply("[" + Completions + "]");
>> + C.reply(json::ary(Items));
>> }
>>
>> void ClangdLSPServer::onSignatureHelp(Ctx C,
>> @@ -195,7 +192,7 @@ void ClangdLSPServer::onSignatureHelp(Ct
>> Position{Params.position.line, Params.position.character});
>> if (!SignatureHelp)
>> return C.replyError(-32602, llvm::toString(SignatureHelp.t
>> akeError()));
>> - C.reply(SignatureHelp::unparse(SignatureHelp->Value));
>> + C.reply(SignatureHelp->Value);
>> }
>>
>> void ClangdLSPServer::onGoToDefinition(Ctx C,
>> @@ -205,22 +202,14 @@ void ClangdLSPServer::onGoToDefinition(C
>> Position{Params.position.line, Params.position.character});
>> if (!Items)
>> return C.replyError(-32602, llvm::toString(Items.takeError()));
>> -
>> - std::string Locations;
>> - for (const auto &Item : Items->Value) {
>> - Locations += Location::unparse(Item);
>> - Locations += ",";
>> - }
>> - if (!Locations.empty())
>> - Locations.pop_back();
>> - C.reply("[" + Locations + "]");
>> + C.reply(json::ary(Items->Value));
>> }
>>
>> void ClangdLSPServer::onSwitchSourceHeader(Ctx C,
>> TextDocumentIdentifier
>> &Params) {
>> llvm::Optional<Path> Result = Server.switchSourceHeader(Para
>> ms.uri.file);
>> std::string ResultUri;
>> - C.reply(Result ? URI::unparse(URI::fromFile(*Result)) : R"("")");
>> + C.reply(Result ? URI::fromFile(*Result).uri : "");
>> }
>>
>> ClangdLSPServer::ClangdLSPServer(JSONOutput &Out, unsigned
>> AsyncThreadsCount,
>> @@ -270,17 +259,16 @@ ClangdLSPServer::getFixIts(StringRef Fil
>>
>> void ClangdLSPServer::onDiagnosticsReady(
>> PathRef File, Tagged<std::vector<DiagWithFixIts>> Diagnostics) {
>> - std::string DiagnosticsJSON;
>> + json::ary DiagnosticsJSON;
>>
>> DiagnosticToReplacementMap LocalFixIts; // Temporary storage
>> for (auto &DiagWithFixes : Diagnostics.Value) {
>> auto Diag = DiagWithFixes.Diag;
>> - DiagnosticsJSON +=
>> - R"({"range":)" + Range::unparse(Diag.range) +
>> - R"(,"severity":)" + std::to_string(Diag.severity) +
>> - R"(,"message":")" + llvm::yaml::escape(Diag.message) +
>> - R"("},)";
>> -
>> + DiagnosticsJSON.push_back(json::obj{
>> + {"range", Diag.range},
>> + {"severity", Diag.severity},
>> + {"message", Diag.message},
>> + });
>> // We convert to Replacements to become independent of the
>> SourceManager.
>> auto &FixItsForDiagnostic = LocalFixIts[Diag];
>> std::copy(DiagWithFixes.FixIts.begin(), DiagWithFixes.FixIts.end(),
>> @@ -295,10 +283,13 @@ void ClangdLSPServer::onDiagnosticsReady
>> }
>>
>> // Publish diagnostics.
>> - if (!DiagnosticsJSON.empty())
>> - DiagnosticsJSON.pop_back(); // Drop trailing comma.
>> - Out.writeMessage(
>> - R"({"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":")"
>> +
>> - URI::fromFile(File).uri + R"(","diagnostics":[)" + DiagnosticsJSON
>> +
>> - R"(]}})");
>> + Out.writeMessage(json::obj{
>> + {"jsonrpc", "2.0"},
>> + {"method", "textDocument/publishDiagnostics"},
>> + {"params",
>> + json::obj{
>> + {"uri", URI::fromFile(File)},
>> + {"diagnostics", std::move(DiagnosticsJSON)},
>> + }},
>> + });
>> }
>>
>> Added: clang-tools-extra/trunk/clangd/JSONExpr.cpp
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> clangd/JSONExpr.cpp?rev=317486&view=auto
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/clangd/JSONExpr.cpp (added)
>> +++ clang-tools-extra/trunk/clangd/JSONExpr.cpp Mon Nov 6 07:40:30 2017
>> @@ -0,0 +1,216 @@
>> +#include "JSONExpr.h"
>> +
>> +#include "llvm/Support/Format.h"
>> +
>> +namespace clang {
>> +namespace clangd {
>> +namespace json {
>> +using namespace llvm;
>> +
>> +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<Object>(M.as<Object>());
>> + break;
>> + case T_Array:
>> + create<Array>(M.as<Array>());
>> + 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<Object>(std::move(M.as<Object>()));
>> + M.Type = T_Null;
>> + break;
>> + case T_Array:
>> + create<Array>(std::move(M.as<Array>()));
>> + 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<Object>().~Object();
>> + break;
>> + case T_Array:
>> + as<Array>().~Array();
>> + break;
>> + }
>> +}
>> +
>> +} // 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::Object>()) {
>> + 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::Array>()) {
>> + if (Comma)
>> + OS << ',';
>> + Comma = true;
>> + I(Newline);
>> + E.print(OS, I);
>> + }
>> + I(Outdent);
>> + if (Comma)
>> + I(Newline);
>> + OS << ']';
>> + break;
>> + }
>> + }
>> +}
>> +
>> +llvm::raw_ostream &clang::clangd::json::operator<<(raw_ostream &OS,
>> + const Expr &E) {
>> + E.print(OS, [](IndenterAction A) { /*ignore*/ });
>> + return OS;
>> +}
>> +
>> +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;
>> + };
>> + });
>> +}
>>
>> Added: clang-tools-extra/trunk/clangd/JSONExpr.h
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> clangd/JSONExpr.h?rev=317486&view=auto
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/clangd/JSONExpr.h (added)
>> +++ clang-tools-extra/trunk/clangd/JSONExpr.h Mon Nov 6 07:40:30 2017
>> @@ -0,0 +1,247 @@
>> +//===--- JSONExpr.h - composable JSON expressions ---------------*- C++
>> -*-===//
>> +//
>> +// The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===------------------------------------------------------
>> ---------------===//
>> +
>> +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSON_H
>> +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSON_H
>> +
>> +#include <map>
>> +
>> +#include "llvm/ADT/SmallVector.h"
>> +#include "llvm/ADT/StringRef.h"
>> +#include "llvm/Support/FormatVariadic.h"
>> +#include "llvm/Support/raw_ostream.h"
>> +
>> +namespace clang {
>> +namespace clangd {
>> +namespace json {
>> +
>> +// An Expr is an opaque temporary JSON structure used to compose
>> documents.
>> +// They can be copied, but should generally be moved.
>> +//
>> +// You can implicitly construct literals 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: any T with a T::unparse(const T&) -> Expr
>> +//
>> +// 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.
>> +//
>> +// 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.
>> +class Expr {
>> +public:
>> + class Object;
>> + class ObjectKey;
>> + class Array;
>> +
>> + // 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(Array(Elements)) {}
>> + Expr(Array &&Elements) : Type(T_Array) { create<Array>(std::move(Elements));
>> }
>> + Expr(Object &&Properties) : Type(T_Object) {
>> + create<Object>(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_arithme
>> tic<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 static T::unparse function returning an Expr.
>> + // FIXME: should this be a free unparse() function found by ADL?
>> + template <typename T,
>> + typename = typename std::enable_if<std::is_same<
>> + Expr, decltype(T::unparse(*(const T *)nullptr))>::value>>
>> + Expr(const T &V) : Expr(T::unparse(V)) {}
>> +
>> + Expr &operator=(const Expr &M) {
>> + destroy();
>> + copyFrom(M);
>> + return *this;
>> + }
>> + Expr &operator=(Expr &&M) {
>> + destroy();
>> + moveFrom(std::move(M));
>> + return *this;
>> + }
>> + ~Expr() { destroy(); }
>> +
>> + 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::Objects. It's like
>> Expr but:
>> + // - only strings are allowed
>> + // - it's copyable (for std::map)
>> + // - we're slightly more eager to copy, to allow efficient key
>> compares
>> + // - 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) = default;
>> + 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 Object : public std::map<ObjectKey, Expr> {
>> + public:
>> + explicit Object() {}
>> + // Use a custom struct for list-init, because pair forces extra
>> copies.
>> + struct KV;
>> + explicit Object(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;
>> + }
>> + };
>> +
>> + class Array : public std::vector<Expr> {
>> + public:
>> + explicit Array() {}
>> + explicit Array(std::initializer_list<Expr> Elements) {
>> + reserve(Elements.size());
>> + for (const Expr &V : Elements)
>> + emplace_back(std::move(V));
>> + };
>> + template <typename Collection> explicit Array(const Collection &C) {
>> + for (const auto &V : C)
>> + emplace_back(V);
>> + }
>> + };
>> +
>> +private:
>> + mutable llvm::AlignedCharArrayUnion<bool, double, llvm::StringRef,
>> + std::string, Array, Object>
>> + Union;
>> +};
>> +
>> +struct Expr::Object::KV {
>> + ObjectKey K;
>> + Expr V;
>> +};
>> +
>> +inline Expr::Object::Object(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::Object;
>> +using ary = Expr::Array;
>> +
>> +} // namespace json
>> +} // namespace clangd
>> +} // namespace clang
>> +
>> +namespace llvm {
>> +template <> struct format_provider<clang::clangd::json::Expr> {
>> + static void format(const clang::clangd::json::Expr &, raw_ostream &,
>> + StringRef);
>> +};
>> +} // namespace llvm
>> +
>> +#endif
>>
>> Modified: clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> clangd/JSONRPCDispatcher.cpp?rev=317486&r1=317485&r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp (original)
>> +++ clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp Mon Nov 6
>> 07:40:30 2017
>> @@ -8,6 +8,7 @@
>> //===------------------------------------------------------
>> ----------------===//
>>
>> #include "JSONRPCDispatcher.h"
>> +#include "JSONExpr.h"
>> #include "ProtocolHandlers.h"
>> #include "Trace.h"
>> #include "llvm/ADT/SmallString.h"
>> @@ -18,17 +19,22 @@
>> using namespace clang;
>> using namespace clangd;
>>
>> -void JSONOutput::writeMessage(const Twine &Message) {
>> - llvm::SmallString<128> Storage;
>> - StringRef M = Message.toStringRef(Storage);
>> +void JSONOutput::writeMessage(const json::Expr &Message) {
>> + std::string S;
>> + llvm::raw_string_ostream OS(S);
>> + if (Pretty)
>> + OS << llvm::formatv("{0:2}", Message);
>> + else
>> + OS << Message;
>> + OS.flush();
>>
>> std::lock_guard<std::mutex> Guard(StreamMutex);
>> // Log without headers.
>> - Logs << "--> " << M << '\n';
>> + Logs << "--> " << S << '\n';
>> Logs.flush();
>>
>> // Emit message with header.
>> - Outs << "Content-Length: " << M.size() << "\r\n\r\n" << M;
>> + Outs << "Content-Length: " << S.size() << "\r\n\r\n" << S;
>> Outs.flush();
>> }
>>
>> @@ -47,30 +53,38 @@ void JSONOutput::mirrorInput(const Twine
>> InputMirror->flush();
>> }
>>
>> -void RequestContext::reply(const llvm::Twine &Result) {
>> - if (ID.empty()) {
>> +void RequestContext::reply(json::Expr &&Result) {
>> + if (!ID) {
>> Out.log("Attempted to reply to a notification!\n");
>> return;
>> }
>> - Out.writeMessage(llvm::Twine(R"({"jsonrpc":"2.0","id":)") + ID +
>> - R"(,"result":)" + Result + "}");
>> + Out.writeMessage(json::obj{
>> + {"jsonrpc", "2.0"},
>> + {"id", *ID},
>> + {"result", std::move(Result)},
>> + });
>> }
>>
>> void RequestContext::replyError(int code, const llvm::StringRef
>> &Message) {
>> Out.log("Error " + llvm::Twine(code) + ": " + Message + "\n");
>> - if (!ID.empty()) {
>> - Out.writeMessage(llvm::Twine(R"({"jsonrpc":"2.0","id":)") + ID +
>> - R"(,"error":{"code":)" + llvm::Twine(code) +
>> - R"(,"message":")" + llvm::yaml::escape(Message) +
>> - R"("}})");
>> + if (ID) {
>> + Out.writeMessage(json::obj{
>> + {"jsonrpc", "2.0"},
>> + {"id", *ID},
>> + {"error", json::obj{{"code", code}, {"message", Message}}},
>> + });
>> }
>> }
>>
>> -void RequestContext::call(StringRef Method, StringRef Params) {
>> +void RequestContext::call(StringRef Method, json::Expr &&Params) {
>> // FIXME: Generate/Increment IDs for every request so that we can get
>> proper
>> // replies once we need to.
>> - Out.writeMessage(llvm::Twine(R"({"jsonrpc":"2.0","id":1,"method":")" +
>> - Method + R"(","params":)" + Params +
>> R"(})"));
>> + Out.writeMessage(json::obj{
>> + {"jsonrpc", "2.0"},
>> + {"id", 1},
>> + {"method", Method},
>> + {"params", std::move(Params)},
>> + });
>> }
>>
>> void JSONRPCDispatcher::registerHandler(StringRef Method, Handler H) {
>> @@ -80,7 +94,7 @@ void JSONRPCDispatcher::registerHandler(
>>
>> static void
>> callHandler(const llvm::StringMap<JSONRPCDispatcher::Handler> &Handlers,
>> - llvm::yaml::ScalarNode *Method, llvm::yaml::ScalarNode *Id,
>> + llvm::yaml::ScalarNode *Method, llvm::Optional<json::Expr>
>> ID,
>> llvm::yaml::MappingNode *Params,
>> const JSONRPCDispatcher::Handler &UnknownHandler, JSONOutput
>> &Out) {
>> llvm::SmallString<64> MethodStorage;
>> @@ -88,7 +102,7 @@ callHandler(const llvm::StringMap<JSONRP
>> auto I = Handlers.find(MethodStr);
>> auto &Handler = I != Handlers.end() ? I->second : UnknownHandler;
>> trace::Span Tracer(MethodStr);
>> - Handler(RequestContext(Out, Id ? Id->getRawValue() : ""), Params);
>> + Handler(RequestContext(Out, std::move(ID)), Params);
>> }
>>
>> bool JSONRPCDispatcher::call(StringRef Content, JSONOutput &Out) const {
>> @@ -106,7 +120,7 @@ bool JSONRPCDispatcher::call(StringRef C
>> llvm::yaml::ScalarNode *Version = nullptr;
>> llvm::yaml::ScalarNode *Method = nullptr;
>> llvm::yaml::MappingNode *Params = nullptr;
>> - llvm::yaml::ScalarNode *Id = nullptr;
>> + llvm::Optional<json::Expr> ID;
>> for (auto &NextKeyValue : *Object) {
>> auto *KeyString =
>> dyn_cast_or_null<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
>> @@ -127,7 +141,18 @@ bool JSONRPCDispatcher::call(StringRef C
>> } else if (KeyValue == "method") {
>> Method = dyn_cast<llvm::yaml::ScalarNode>(Value);
>> } else if (KeyValue == "id") {
>> - Id = dyn_cast<llvm::yaml::ScalarNode>(Value);
>> + // ID may be either a string or a number.
>> + if (auto *IdNode = dyn_cast<llvm::yaml::ScalarNode>(Value)) {
>> + llvm::SmallString<32> S;
>> + llvm::StringRef V = IdNode->getValue(S);
>> + if (IdNode->getRawValue().startswith("\"")) {
>> + ID.emplace(V.str());
>> + } else {
>> + double D;
>> + if (!V.getAsDouble(D))
>> + ID.emplace(D);
>> + }
>> + }
>> } else if (KeyValue == "params") {
>> if (!Method)
>> return false;
>> @@ -136,7 +161,7 @@ bool JSONRPCDispatcher::call(StringRef C
>> // because it will break clients that put the id after params. A
>> possible
>> // fix would be to split the parsing and execution phases.
>> Params = dyn_cast<llvm::yaml::MappingNode>(Value);
>> - callHandler(Handlers, Method, Id, Params, UnknownHandler, Out);
>> + callHandler(Handlers, Method, std::move(ID), Params,
>> UnknownHandler, Out);
>> return true;
>> } else {
>> return false;
>> @@ -147,7 +172,7 @@ bool JSONRPCDispatcher::call(StringRef C
>> // leftovers.
>> if (!Method)
>> return false;
>> - callHandler(Handlers, Method, Id, nullptr, UnknownHandler, Out);
>> + callHandler(Handlers, Method, std::move(ID), nullptr, UnknownHandler,
>> Out);
>>
>> return true;
>> }
>>
>> Modified: clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> clangd/JSONRPCDispatcher.h?rev=317486&r1=317485&r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h (original)
>> +++ clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h Mon Nov 6
>> 07:40:30 2017
>> @@ -10,6 +10,7 @@
>> #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSONRPCDISPATCHER_H
>> #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSONRPCDISPATCHER_H
>>
>> +#include "JSONExpr.h"
>> #include "Logger.h"
>> #include "clang/Basic/LLVM.h"
>> #include "llvm/ADT/SmallString.h"
>> @@ -26,11 +27,11 @@ namespace clangd {
>> class JSONOutput : public Logger {
>> public:
>> JSONOutput(llvm::raw_ostream &Outs, llvm::raw_ostream &Logs,
>> - llvm::raw_ostream *InputMirror = nullptr)
>> - : Outs(Outs), Logs(Logs), InputMirror(InputMirror) {}
>> + llvm::raw_ostream *InputMirror = nullptr, bool Pretty =
>> false)
>> + : Outs(Outs), Logs(Logs), InputMirror(InputMirror), Pretty(Pretty)
>> {}
>>
>> /// Emit a JSONRPC message.
>> - void writeMessage(const Twine &Message);
>> + void writeMessage(const json::Expr &Result);
>>
>> /// Write to the logging stream.
>> /// No newline is implicitly added. (TODO: we should fix this!)
>> @@ -45,6 +46,7 @@ private:
>> llvm::raw_ostream &Outs;
>> llvm::raw_ostream &Logs;
>> llvm::raw_ostream *InputMirror;
>> + bool Pretty;
>>
>> std::mutex StreamMutex;
>> };
>> @@ -52,18 +54,19 @@ private:
>> /// Context object passed to handlers to allow replies.
>> class RequestContext {
>> public:
>> - RequestContext(JSONOutput &Out, StringRef ID) : Out(Out), ID(ID) {}
>> + RequestContext(JSONOutput &Out, llvm::Optional<json::Expr> ID)
>> + : Out(Out), ID(std::move(ID)) {}
>>
>> - /// Sends a successful reply. Result should be well-formed JSON.
>> - void reply(const Twine &Result);
>> + /// Sends a successful reply.
>> + void reply(json::Expr &&Result);
>> /// Sends an error response to the client, and logs it.
>> void replyError(int code, const llvm::StringRef &Message);
>> /// Sends a request to the client.
>> - void call(llvm::StringRef Method, StringRef Params);
>> + void call(llvm::StringRef Method, json::Expr &&Params);
>>
>> private:
>> JSONOutput &Out;
>> - llvm::SmallString<64> ID; // Valid JSON, or empty for a notification.
>> + llvm::Optional<json::Expr> ID;
>> };
>>
>> /// Main JSONRPC entry point. This parses the JSONRPC "header" and calls
>> the
>>
>> Modified: clang-tools-extra/trunk/clangd/Protocol.cpp
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> clangd/Protocol.cpp?rev=317486&r1=317485&r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/clangd/Protocol.cpp (original)
>> +++ clang-tools-extra/trunk/clangd/Protocol.cpp Mon Nov 6 07:40:30 2017
>> @@ -63,7 +63,7 @@ URI URI::parse(llvm::yaml::ScalarNode *P
>> return URI::fromUri(Param->getValue(Storage));
>> }
>>
>> -std::string URI::unparse(const URI &U) { return "\"" + U.uri + "\""; }
>> +json::Expr URI::unparse(const URI &U) { return U.uri; }
>>
>> llvm::Optional<TextDocumentIdentifier>
>> TextDocumentIdentifier::parse(llvm::yaml::MappingNode *Params,
>> @@ -125,11 +125,11 @@ llvm::Optional<Position> Position::parse
>> return Result;
>> }
>>
>> -std::string Position::unparse(const Position &P) {
>> - std::string Result;
>> - llvm::raw_string_ostream(Result)
>> - << llvm::format(R"({"line": %d, "character": %d})", P.line,
>> P.character);
>> - return Result;
>> +json::Expr Position::unparse(const Position &P) {
>> + return json::obj{
>> + {"line", P.line},
>> + {"character", P.character},
>> + };
>> }
>>
>> llvm::Optional<Range> Range::parse(llvm::yaml::MappingNode *Params,
>> @@ -165,20 +165,18 @@ llvm::Optional<Range> Range::parse(llvm:
>> return Result;
>> }
>>
>> -std::string Range::unparse(const Range &P) {
>> - std::string Result;
>> - llvm::raw_string_ostream(Result) << llvm::format(
>> - R"({"start": %s, "end": %s})", Position::unparse(P.start).c_str(),
>> - Position::unparse(P.end).c_str());
>> - return Result;
>> +json::Expr Range::unparse(const Range &P) {
>> + return json::obj{
>> + {"start", P.start},
>> + {"end", P.end},
>> + };
>> }
>>
>> -std::string Location::unparse(const Location &P) {
>> - std::string Result;
>> - llvm::raw_string_ostream(Result) << llvm::format(
>> - R"({"uri": %s, "range": %s})", URI::unparse(P.uri).c_str(),
>> - Range::unparse(P.range).c_str());
>> - return Result;
>> +json::Expr Location::unparse(const Location &P) {
>> + return json::obj{
>> + {"uri", P.uri},
>> + {"range", P.range},
>> + };
>> }
>>
>> llvm::Optional<TextDocumentItem>
>> @@ -279,25 +277,11 @@ llvm::Optional<TextEdit> TextEdit::parse
>> return Result;
>> }
>>
>> -std::string TextEdit::unparse(const TextEdit &P) {
>> - std::string Result;
>> - llvm::raw_string_ostream(Result) << llvm::format(
>> - R"({"range": %s, "newText": "%s"})", Range::unparse(P.range).c_str(
>> ),
>> - llvm::yaml::escape(P.newText).c_str());
>> - return Result;
>> -}
>> -
>> -std::string TextEdit::unparse(const std::vector<TextEdit> &TextEdits) {
>> - // Fuse all edits into one big JSON array.
>> - std::string Edits;
>> - for (auto &TE : TextEdits) {
>> - Edits += TextEdit::unparse(TE);
>> - Edits += ',';
>> - }
>> - if (!Edits.empty())
>> - Edits.pop_back();
>> -
>> - return "[" + Edits + "]";
>> +json::Expr TextEdit::unparse(const TextEdit &P) {
>> + return json::obj{
>> + {"range", P.range},
>> + {"newText", P.newText},
>> + };
>> }
>>
>> namespace {
>> @@ -611,11 +595,11 @@ FormattingOptions::parse(llvm::yaml::Map
>> return Result;
>> }
>>
>> -std::string FormattingOptions::unparse(const FormattingOptions &P) {
>> - std::string Result;
>> - llvm::raw_string_ostream(Result) << llvm::format(
>> - R"({"tabSize": %d, "insertSpaces": %d})", P.tabSize,
>> P.insertSpaces);
>> - return Result;
>> +json::Expr FormattingOptions::unparse(const FormattingOptions &P) {
>> + return json::obj{
>> + {"tabSize", P.tabSize},
>> + {"insertSpaces", P.insertSpaces},
>> + };
>> }
>>
>> llvm::Optional<DocumentRangeFormattingParams>
>> @@ -982,28 +966,18 @@ ExecuteCommandParams::parse(llvm::yaml::
>> return Result;
>> }
>>
>> -std::string WorkspaceEdit::unparse(const WorkspaceEdit &WE) {
>> - std::string Changes;
>> - for (auto &Change : *WE.changes) {
>> - Changes += llvm::formatv(R"("{0}": {1})", Change.first,
>> - TextEdit::unparse(Change.second));
>> - Changes += ',';
>> - }
>> - if (!Changes.empty())
>> - Changes.pop_back();
>> -
>> - std::string Result;
>> - llvm::raw_string_ostream(Result)
>> - << llvm::format(R"({"changes": {%s}})", Changes.c_str());
>> - return Result;
>> +json::Expr WorkspaceEdit::unparse(const WorkspaceEdit &WE) {
>> + if (!WE.changes)
>> + return json::obj{};
>> + json::obj FileChanges;
>> + for (auto &Change : *WE.changes)
>> + FileChanges[Change.first] = json::ary(Change.second);
>> + return json::obj{{"changes", std::move(FileChanges)}};
>> }
>>
>> -std::string
>> +json::Expr
>> ApplyWorkspaceEditParams::unparse(const ApplyWorkspaceEditParams
>> &Params) {
>> - std::string Result;
>> - llvm::raw_string_ostream(Result) << llvm::format(
>> - R"({"edit": %s})", WorkspaceEdit::unparse(Params.edit).c_str());
>> - return Result;
>> + return json::obj{{"edit", Params.edit}};
>> }
>>
>> llvm::Optional<TextDocumentPositionParams>
>> @@ -1040,96 +1014,57 @@ TextDocumentPositionParams::parse(llvm::
>> return Result;
>> }
>>
>> -std::string CompletionItem::unparse(const CompletionItem &CI) {
>> - std::string Result = "{";
>> - llvm::raw_string_ostream Os(Result);
>> +json::Expr CompletionItem::unparse(const CompletionItem &CI) {
>> assert(!CI.label.empty() && "completion item label is required");
>> - Os << R"("label":")" << llvm::yaml::escape(CI.label) << R"(",)";
>> + json::obj Result{{"label", CI.label}};
>> if (CI.kind != CompletionItemKind::Missing)
>> - Os << R"("kind":)" << static_cast<int>(CI.kind) << R"(,)";
>> + Result["kind"] = static_cast<int>(CI.kind);
>> if (!CI.detail.empty())
>> - Os << R"("detail":")" << llvm::yaml::escape(CI.detail) << R"(",)";
>> + Result["detail"] = CI.detail;
>> if (!CI.documentation.empty())
>> - Os << R"("documentation":")" << llvm::yaml::escape(CI.documentation)
>> - << R"(",)";
>> + Result["documentation"] = CI.documentation;
>> if (!CI.sortText.empty())
>> - Os << R"("sortText":")" << llvm::yaml::escape(CI.sortText) <<
>> R"(",)";
>> + Result["sortText"] = CI.sortText;
>> if (!CI.filterText.empty())
>> - Os << R"("filterText":")" << llvm::yaml::escape(CI.filterText) <<
>> R"(",)";
>> + Result["filterText"] = CI.filterText;
>> if (!CI.insertText.empty())
>> - Os << R"("insertText":")" << llvm::yaml::escape(CI.insertText) <<
>> R"(",)";
>> - if (CI.insertTextFormat != InsertTextFormat::Missing) {
>> - Os << R"("insertTextFormat":)" << static_cast<int>(CI.insertText
>> Format)
>> - << R"(,)";
>> - }
>> + Result["insertText"] = CI.insertText;
>> + if (CI.insertTextFormat != InsertTextFormat::Missing)
>> + Result["insertTextFormat"] = static_cast<int>(CI.insertTextFormat);
>> if (CI.textEdit)
>> - Os << R"("textEdit":)" << TextEdit::unparse(*CI.textEdit) << ',';
>> - if (!CI.additionalTextEdits.empty()) {
>> - Os << R"("additionalTextEdits":[)";
>> - for (const auto &Edit : CI.additionalTextEdits)
>> - Os << TextEdit::unparse(Edit) << ",";
>> - Os.flush();
>> - // The list additionalTextEdits is guaranteed nonempty at this point.
>> - // Replace the trailing comma with right brace.
>> - Result.back() = ']';
>> - }
>> - Os.flush();
>> - // Label is required, so Result is guaranteed to have a trailing comma.
>> - Result.back() = '}';
>> - return Result;
>> + Result["textEdit"] = *CI.textEdit;
>> + if (!CI.additionalTextEdits.empty())
>> + Result["additionalTextEdits"] = json::ary(CI.additionalTextEdits);
>> + return std::move(Result);
>> }
>>
>> -std::string ParameterInformation::unparse(const ParameterInformation
>> &PI) {
>> - std::string Result = "{";
>> - llvm::raw_string_ostream Os(Result);
>> +json::Expr ParameterInformation::unparse(const ParameterInformation
>> &PI) {
>> assert(!PI.label.empty() && "parameter information label is required");
>> - Os << R"("label":")" << llvm::yaml::escape(PI.label) << '\"';
>> + json::obj Result{{"label", PI.label}};
>> if (!PI.documentation.empty())
>> - Os << R"(,"documentation":")" << llvm::yaml::escape(PI.document
>> ation)
>> - << '\"';
>> - Os << '}';
>> - Os.flush();
>> - return Result;
>> + Result["documentation"] = PI.documentation;
>> + return std::move(Result);
>> }
>>
>> -std::string SignatureInformation::unparse(const SignatureInformation
>> &SI) {
>> - std::string Result = "{";
>> - llvm::raw_string_ostream Os(Result);
>> +json::Expr SignatureInformation::unparse(const SignatureInformation
>> &SI) {
>> assert(!SI.label.empty() && "signature information label is required");
>> - Os << R"("label":")" << llvm::yaml::escape(SI.label) << '\"';
>> + json::obj Result{
>> + {"label", SI.label},
>> + {"parameters", json::ary(SI.parameters)},
>> + };
>> if (!SI.documentation.empty())
>> - Os << R"(,"documentation":")" << llvm::yaml::escape(SI.document
>> ation)
>> - << '\"';
>> - Os << R"(,"parameters":[)";
>> - for (const auto &Parameter : SI.parameters) {
>> - Os << ParameterInformation::unparse(Parameter) << ',';
>> - }
>> - Os.flush();
>> - if (SI.parameters.empty())
>> - Result.push_back(']');
>> - else
>> - Result.back() = ']'; // Replace the last `,` with an `]`.
>> - Result.push_back('}');
>> - return Result;
>> + Result["documentation"] = SI.documentation;
>> + return std::move(Result);
>> }
>>
>> -std::string SignatureHelp::unparse(const SignatureHelp &SH) {
>> - std::string Result = "{";
>> - llvm::raw_string_ostream Os(Result);
>> +json::Expr SignatureHelp::unparse(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");
>> - Os << R"("activeSignature":)" << SH.activeSignature
>> - << R"(,"activeParameter":)" << SH.activeParameter <<
>> R"(,"signatures":[)";
>> - for (const auto &Signature : SH.signatures) {
>> - Os << SignatureInformation::unparse(Signature) << ',';
>> - }
>> - Os.flush();
>> - if (SH.signatures.empty())
>> - Result.push_back(']');
>> - else
>> - Result.back() = ']'; // Replace the last `,` with an `]`.
>> - Result.push_back('}');
>> - return Result;
>> + return json::obj{
>> + {"activeSignature", SH.activeSignature},
>> + {"activeParameter", SH.activeParameter},
>> + {"signatures", json::ary(SH.signatures)},
>> + };
>> }
>>
>> Modified: clang-tools-extra/trunk/clangd/Protocol.h
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> clangd/Protocol.h?rev=317486&r1=317485&r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/clangd/Protocol.h (original)
>> +++ clang-tools-extra/trunk/clangd/Protocol.h Mon Nov 6 07:40:30 2017
>> @@ -21,6 +21,7 @@
>> #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROTOCOL_H
>> #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROTOCOL_H
>>
>> +#include "JSONExpr.h"
>> #include "llvm/ADT/Optional.h"
>> #include "llvm/Support/YAMLParser.h"
>> #include <string>
>> @@ -39,7 +40,7 @@ struct URI {
>> static URI fromFile(llvm::StringRef file);
>>
>> static URI parse(llvm::yaml::ScalarNode *Param);
>> - static std::string unparse(const URI &U);
>> + static json::Expr unparse(const URI &U);
>>
>> friend bool operator==(const URI &LHS, const URI &RHS) {
>> return LHS.uri == RHS.uri;
>> @@ -80,7 +81,7 @@ struct Position {
>>
>> static llvm::Optional<Position> parse(llvm::yaml::MappingNode *Params,
>> clangd::Logger &Logger);
>> - static std::string unparse(const Position &P);
>> + static json::Expr unparse(const Position &P);
>> };
>>
>> struct Range {
>> @@ -99,7 +100,7 @@ struct Range {
>>
>> static llvm::Optional<Range> parse(llvm::yaml::MappingNode *Params,
>> clangd::Logger &Logger);
>> - static std::string unparse(const Range &P);
>> + static json::Expr unparse(const Range &P);
>> };
>>
>> struct Location {
>> @@ -119,7 +120,7 @@ struct Location {
>> return std::tie(LHS.uri, LHS.range) < std::tie(RHS.uri, RHS.range);
>> }
>>
>> - static std::string unparse(const Location &P);
>> + static json::Expr unparse(const Location &P);
>> };
>>
>> struct Metadata {
>> @@ -140,8 +141,7 @@ struct TextEdit {
>>
>> static llvm::Optional<TextEdit> parse(llvm::yaml::MappingNode *Params,
>> clangd::Logger &Logger);
>> - static std::string unparse(const TextEdit &P);
>> - static std::string unparse(const std::vector<TextEdit> &TextEdits);
>> + static json::Expr unparse(const TextEdit &P);
>> };
>>
>> struct TextDocumentItem {
>> @@ -283,7 +283,7 @@ struct FormattingOptions {
>>
>> static llvm::Optional<FormattingOptions>
>> parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
>> - static std::string unparse(const FormattingOptions &P);
>> + static json::Expr unparse(const FormattingOptions &P);
>> };
>>
>> struct DocumentRangeFormattingParams {
>> @@ -392,7 +392,7 @@ struct WorkspaceEdit {
>>
>> static llvm::Optional<WorkspaceEdit> parse(llvm::yaml::MappingNode
>> *Params,
>> clangd::Logger &Logger);
>> - static std::string unparse(const WorkspaceEdit &WE);
>> + static json::Expr unparse(const WorkspaceEdit &WE);
>> };
>>
>> /// Exact commands are not specified in the protocol so we define the
>> @@ -420,7 +420,7 @@ struct ExecuteCommandParams {
>>
>> struct ApplyWorkspaceEditParams {
>> WorkspaceEdit edit;
>> - static std::string unparse(const ApplyWorkspaceEditParams &Params);
>> + static json::Expr unparse(const ApplyWorkspaceEditParams &Params);
>> };
>>
>> struct TextDocumentPositionParams {
>> @@ -527,7 +527,7 @@ struct CompletionItem {
>> //
>> // data?: any - A data entry field that is preserved on a completion
>> item
>> // between a completion and a completion resolve request.
>> - static std::string unparse(const CompletionItem &P);
>> + static json::Expr unparse(const CompletionItem &P);
>> };
>>
>> /// A single parameter of a particular signature.
>> @@ -539,7 +539,7 @@ struct ParameterInformation {
>> /// The documentation of this parameter. Optional.
>> std::string documentation;
>>
>> - static std::string unparse(const ParameterInformation &);
>> + static json::Expr unparse(const ParameterInformation &);
>> };
>>
>> /// Represents the signature of something callable.
>> @@ -554,7 +554,7 @@ struct SignatureInformation {
>> /// The parameters of this signature.
>> std::vector<ParameterInformation> parameters;
>>
>> - static std::string unparse(const SignatureInformation &);
>> + static json::Expr unparse(const SignatureInformation &);
>> };
>>
>> /// Represents the signature of a callable.
>> @@ -569,7 +569,7 @@ struct SignatureHelp {
>> /// The active parameter of the active signature.
>> int activeParameter = 0;
>>
>> - static std::string unparse(const SignatureHelp &);
>> + static json::Expr unparse(const SignatureHelp &);
>> };
>>
>> } // namespace clangd
>>
>> Modified: clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> clangd/tool/ClangdMain.cpp?rev=317486&r1=317485&r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp (original)
>> +++ clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp Mon Nov 6
>> 07:40:30 2017
>> @@ -41,6 +41,10 @@ static llvm::cl::opt<bool> EnableSnippet
>> "Present snippet completions instead of plaintext completions"),
>> llvm::cl::init(false));
>>
>> +static llvm::cl::opt<bool>
>> + PrettyPrint("pretty", llvm::cl::desc("Pretty-print JSON output"),
>> + llvm::cl::init(false));
>> +
>> static llvm::cl::opt<bool> RunSynchronously(
>> "run-synchronously",
>> llvm::cl::desc("Parse on main thread. If set, -j is ignored"),
>> @@ -104,7 +108,8 @@ int main(int argc, char *argv[]) {
>> llvm::raw_ostream &Outs = llvm::outs();
>> llvm::raw_ostream &Logs = llvm::errs();
>> JSONOutput Out(Outs, Logs,
>> - InputMirrorStream ? InputMirrorStream.getPointer() :
>> nullptr);
>> + InputMirrorStream ? InputMirrorStream.getPointer() :
>> nullptr,
>> + PrettyPrint);
>>
>> // If --compile-commands-dir arg was invoked, check value and override
>> default
>> // path.
>>
>> Modified: clang-tools-extra/trunk/test/clangd/authority-less-uri.test
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> test/clangd/authority-less-uri.test?rev=317486&r1=317485&
>> r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/test/clangd/authority-less-uri.test
>> (original)
>> +++ clang-tools-extra/trunk/test/clangd/authority-less-uri.test Mon Nov
>> 6 07:40:30 2017
>> @@ -1,4 +1,4 @@
>> -# RUN: clangd -run-synchronously < %s | FileCheck %s
>> +# RUN: clangd -pretty -run-synchronously < %s | FileCheck
>> -strict-whitespace %s
>> # It is absolutely vital that this file has CRLF line endings.
>> #
>> # Test authority-less URI
>> @@ -15,22 +15,34 @@ Content-Length: 146
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/completion",
>> "params":{"textDocument":{"uri":"file:/main.cpp"},"position":{"line":3,"
>> character":5}}}
>> # Test authority-less URI
>> #
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[
>> -# CHECK-DAG: {"label":"a","kind":5,"detail"
>> :"int","sortText":"000035a","filterText":"a","insertText":"a
>> ","insertTextFormat":1}
>> -# CHECK: ]}
>> -
>> +# CHECK: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK: "filterText": "fake",
>> +# CHECK-NEXT: "insertText": "fake",
>> +# CHECK-NEXT: "insertTextFormat": 1,
>> +# CHECK-NEXT: "kind": 7,
>> +# CHECK-NEXT: "label": "fake::",
>> +# CHECK-NEXT: "sortText": "000075fake"
>> +# CHECK: ]
>> Content-Length: 172
>>
>> {"jsonrpc":"2.0","id":2,"method":"textDocument/completion",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"uri"
>> :"file:///main.cpp","position":{"line":3,"character":5}}}
>> # Test params parsing in the presence of a 1.x-compatible client
>> (inlined "uri")
>> #
>> -# CHECK: {"jsonrpc":"2.0","id":2,"result":[
>> -# CHECK-DAG: {"label":"a","kind":5,"detail"
>> :"int","sortText":"000035a","filterText":"a","insertText":"a
>> ","insertTextFormat":1}
>> -# CHECK: ]}
>> +# CHECK: "id": 2,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK: "filterText": "fake",
>> +# CHECK-NEXT: "insertText": "fake",
>> +# CHECK-NEXT: "insertTextFormat": 1,
>> +# CHECK-NEXT: "kind": 7,
>> +# CHECK-NEXT: "label": "fake::",
>> +# CHECK-NEXT: "sortText": "000075fake"
>> +# CHECK: ]
>> Content-Length: 44
>>
>> {"jsonrpc":"2.0","id":3,"method":"shutdown"}
>> -# CHECK: {"jsonrpc":"2.0","id":3,"result":null}
>> Content-Length: 33
>>
>> {"jsonrpc":"2.0":"method":"exit"}
>>
>> Modified: clang-tools-extra/trunk/test/clangd/completion-items-kinds.test
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> test/clangd/completion-items-kinds.test?rev=317486&r1=
>> 317485&r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/test/clangd/completion-items-kinds.test
>> (original)
>> +++ clang-tools-extra/trunk/test/clangd/completion-items-kinds.test Mon
>> Nov 6 07:40:30 2017
>> @@ -11,27 +11,26 @@ Content-Length: 148
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/completion",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":4,"character":7}}}
>> Content-Length: 58
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[
>> +# CHECK: {"id":1,"jsonrpc":"2.0","result":[
>> #
>> # Keyword
>> -# CHECK-DAG: {"label":"int","kind":14,"sort
>> Text":"000050int","filterText":"int","insertText":"int","
>> insertTextFormat":1}
>> +# CHECK-DAG: {"filterText":"int","insertTex
>> t":"int","insertTextFormat":1,"kind":14,"label":"int","
>> sortText":"000050int"}
>> #
>> # Code pattern
>> -# CHECK-DAG: {"label":"static_cast<type>(ex
>> pression)","kind":15,"sortText":"000040static_cast","
>> filterText":"static_cast","insertText":"static_cast<${1:type
>> }>(${2:expression})","insertTextFormat":2}
>> +# CHECK-DAG: {"filterText":"static_cast","i
>> nsertText":"static_cast<${1:type}>(${2:expression})","insert
>> TextFormat":2,"kind":15,"label":"static_cast<type>(expr
>> ession)","sortText":"000040static_cast"}
>> #
>> # Struct
>> -# CHECK-DAG: {"label":"Struct","kind":7,"so
>> rtText":"000050Struct","filterText":"Struct","insertText":"
>> Struct","insertTextFormat":1}
>> +# CHECK-DAG: {"filterText":"Struct","insert
>> Text":"Struct","insertTextFormat":1,"kind":7,"label":"
>> Struct","sortText":"000050Struct"}
>> #
>> # Macro
>> -# CHECK-DAG: {"label":"MACRO","kind":1,"sor
>> tText":"000070MACRO","filterText":"MACRO","insertText":"
>> MACRO","insertTextFormat":1}
>> +# CHECK-DAG: {"filterText":"MACRO","insertT
>> ext":"MACRO","insertTextFormat":1,"kind":1,"label":"MACRO","
>> sortText":"000070MACRO"}
>> #
>> # Variable
>> -# CHECK-DAG: {"label":"variable","kind":6,"
>> detail":"int","sortText":"000012variable","filterText":"vari
>> able","insertText":"variable","insertTextFormat":1}
>> +# CHECK-DAG: {"detail":"int","filterText":"
>> variable","insertText":"variable","insertTextFormat":1,"
>> kind":6,"label":"variable","sortText":"000012variable"}
>> #
>> # Function
>> -# CHECK-DAG: {"label":"function()","kind":3
>> ,"detail":"int","sortText":"000012function","filterText":"fu
>> nction","insertText":"function()","insertTextFormat":1}
>> +# CHECK-DAG: {"detail":"int","filterText":"
>> function","insertText":"function()","insertTextFormat":1,"
>> kind":3,"label":"function()","sortText":"000012function"}
>> #
>> -#
>> -# CHECK: ]}
>> +# CHECK-SAME: ]}
>>
>> {"jsonrpc":"2.0","id":3,"method":"shutdown","params":null}
>>
>> Modified: clang-tools-extra/trunk/test/clangd/completion-priorities.test
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> test/clangd/completion-priorities.test?rev=317486&r1=317485&
>> r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/test/clangd/completion-priorities.test
>> (original)
>> +++ clang-tools-extra/trunk/test/clangd/completion-priorities.test Mon
>> Nov 6 07:40:30 2017
>> @@ -16,25 +16,24 @@ Content-Length: 151
>> # The order of results returned by codeComplete seems to be
>> # nondeterministic, so we check regardless of order.
>> #
>> -# CHECK: {"jsonrpc":"2.0","id":2,"result":[
>> -# CHECK-DAG: {"label":"pub()","kind":2,"det
>> ail":"void","sortText":"000034pub","filterText":"pub","
>> insertText":"pub","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"prot()","kind":2,"de
>> tail":"void","sortText":"000034prot","filterText":"prot","
>> insertText":"prot","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"priv()","kind":2,"de
>> tail":"void","sortText":"000034priv","filterText":"priv","
>> insertText":"priv","insertTextFormat":1}
>> -# CHECK: ]}
>> +# CHECK: {"id":2,"jsonrpc":"2.0","result":[
>> +# CHECK-DAG: {"detail":"void","filterText":
>> "pub","insertText":"pub","insertTextFormat":1,"kind":2,"labe
>> l":"pub()","sortText":"000034pub"}
>> +# CHECK-DAG: {"detail":"void","filterText":
>> "prot","insertText":"prot","insertTextFormat":1,"kind":2,"la
>> bel":"prot()","sortText":"000034prot"}
>> +# CHECK-DAG: {"detail":"void","filterText":
>> "priv","insertText":"priv","insertTextFormat":1,"kind":2,"la
>> bel":"priv()","sortText":"000034priv"}
>> +# CHECK-SAME: ]}
>>
>> Content-Length: 151
>>
>> {"jsonrpc":"2.0","id":3,"method":"textDocument/completion",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":17,"character":4}}}
>> -# CHECK: {"jsonrpc":"2.0","id":3,"result":[
>> -# CHECK-DAG: {"label":"pub()","kind":2,"det
>> ail":"void","sortText":"000034pub","filterText":"pub","
>> insertText":"pub","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"prot()","kind":2,"de
>> tail":"void","sortText":"200034prot","filterText":"prot","
>> insertText":"prot","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"priv()","kind":2,"de
>> tail":"void","sortText":"200034priv","filterText":"priv","
>> insertText":"priv","insertTextFormat":1}
>> -# CHECK: ]}
>> +# CHECK: {"id":3,"jsonrpc":"2.0","result":[
>> +# CHECK-DAG: {"detail":"void","filterText":
>> "pub","insertText":"pub","insertTextFormat":1,"kind":2,"labe
>> l":"pub()","sortText":"000034pub"}
>> +# CHECK-DAG: {"detail":"void","filterText":
>> "prot","insertText":"prot","insertTextFormat":1,"kind":2,"la
>> bel":"prot()","sortText":"200034prot"}
>> +# CHECK-DAG: {"detail":"void","filterText":
>> "priv","insertText":"priv","insertTextFormat":1,"kind":2,"la
>> bel":"priv()","sortText":"200034priv"}
>> +# CHECK-SAME: ]}
>>
>> Content-Length: 58
>>
>> {"jsonrpc":"2.0","id":4,"method":"shutdown","params":null}
>> -# CHECK: {"jsonrpc":"2.0","id":4,"result":null}
>> Content-Length: 33
>>
>> {"jsonrpc":"2.0":"method":"exit"}
>>
>> Modified: clang-tools-extra/trunk/test/clangd/completion-qualifiers.test
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> test/clangd/completion-qualifiers.test?rev=317486&r1=317485&
>> r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/test/clangd/completion-qualifiers.test
>> (original)
>> +++ clang-tools-extra/trunk/test/clangd/completion-qualifiers.test Mon
>> Nov 6 07:40:30 2017
>> @@ -8,15 +8,14 @@ Content-Length: 297
>> Content-Length: 151
>>
>> {"jsonrpc":"2.0","id":2,"method":"textDocument/completion",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":11,"character":8}}}
>> -# CHECK: {"jsonrpc":"2.0","id":2,"result":[
>> -# CHECK-DAG: {"label":"foo() const","kind":2,"detail":"int"
>> ,"sortText":"200035foo","filterText":"foo","insertText":"
>> foo","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"bar() const","kind":2,"detail":"int"
>> ,"sortText":"000037bar","filterText":"bar","insertText":"
>> bar","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"Foo::foo() const","kind":2,"detail":"int"
>> ,"sortText":"000037foo","filterText":"foo","insertText":"
>> foo","insertTextFormat":1}
>> -# CHECK: ]}
>> +# CHECK: {"id":2,"jsonrpc":"2.0","result":[
>> +# CHECK-DAG: {"detail":"int","filterText":"
>> foo","insertText":"foo","insertTextFormat":1,"kind":2,"label":"foo()
>> const","sortText":"200035foo"}
>> +# CHECK-DAG: {"detail":"int","filterText":"
>> bar","insertText":"bar","insertTextFormat":1,"kind":2,"label":"bar()
>> const","sortText":"000037bar"}
>> +# CHECK-DAG: {"detail":"int","filterText":"
>> foo","insertText":"foo","insertTextFormat":1,"kind":2,"label":"Foo::foo()
>> const","sortText":"000037foo"}
>> +# CHECK-SAME: ]}
>> Content-Length: 44
>>
>> {"jsonrpc":"2.0","id":4,"method":"shutdown"}
>> -# CHECK: {"jsonrpc":"2.0","id":4,"result":null}
>> Content-Length: 33
>>
>> {"jsonrpc":"2.0":"method":"exit"}
>>
>> Modified: clang-tools-extra/trunk/test/clangd/completion-snippet.test
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> test/clangd/completion-snippet.test?rev=317486&r1=317485&r2=
>> 317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/test/clangd/completion-snippet.test
>> (original)
>> +++ clang-tools-extra/trunk/test/clangd/completion-snippet.test Mon Nov
>> 6 07:40:30 2017
>> @@ -15,27 +15,27 @@ Content-Length: 148
>> # The order of results returned by codeComplete seems to be
>> # nondeterministic, so we check regardless of order.
>> #
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[
>> -# CHECK-DAG: {"label":"a","kind":5,"detail"
>> :"int","sortText":"000035a","filterText":"a","insertText":"a
>> ","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"bb","kind":5,"detail
>> ":"int","sortText":"000035bb","filterText":"bb","insertText"
>> :"bb","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"ccc","kind":5,"detai
>> l":"int","sortText":"000035ccc","filterText":"ccc","
>> insertText":"ccc","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake
>> &","sortText":"000079operator=","filterText":"operator=","insertText":"operator=(${1:const
>> fake &})","insertTextFormat":2}
>> -# CHECK-DAG: {"label":"~fake()","kind":4,"d
>> etail":"void","sortText":"000079~fake","filterText":"~fake",
>> "insertText":"~fake()","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"f(int i, const float f)
>> const","kind":2,"detail":"int","sortText":"000035f","filterT
>> ext":"f","insertText":"f(${1:int i}, ${2:const float
>> f})","insertTextFormat":2}
>> -# CHECK: ]}
>> +# CHECK: {"id":1,"jsonrpc":"2.0","result":[
>> +# CHECK-DAG: {"detail":"int","filterText":"
>> a","insertText":"a","insertTextFormat":1,"kind":5,"label":"
>> a","sortText":"000035a"}
>> +# CHECK-DAG: {"detail":"int","filterText":"
>> bb","insertText":"bb","insertTextFormat":1,"kind":5,"label":
>> "bb","sortText":"000035bb"}
>> +# CHECK-DAG: {"detail":"int","filterText":"
>> ccc","insertText":"ccc","insertTextFormat":1,"kind":5,"label
>> ":"ccc","sortText":"000035ccc"}
>> +# CHECK-DAG: {"detail":"fake &","filterText":"operator=","i
>> nsertText":"operator=(${1:const fake &})","insertTextFormat":2,"kind":2,"label":"operator=(const
>> fake &)","sortText":"000079operator="}
>> +# CHECK-DAG: {"detail":"void","filterText":
>> "~fake","insertText":"~fake()","insertTextFormat":1,"kind":4
>> ,"label":"~fake()","sortText":"000079~fake"}
>> +# CHECK-DAG: {"detail":"int","filterText":"f","insertText":"f(${1:int
>> i}, ${2:const float f})","insertTextFormat":2,"kind":2,"label":"f(int i,
>> const float f) const","sortText":"000035f"}
>> +# CHECK-SAME: ]}
>> Content-Length: 148
>>
>> {"jsonrpc":"2.0","id":2,"method":"textDocument/completion",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":3,"character":5}}}
>> # Repeat the completion request, expect the same results.
>> #
>> -# CHECK: {"jsonrpc":"2.0","id":2,"result":[
>> -# CHECK-DAG: {"label":"a","kind":5,"detail"
>> :"int","sortText":"000035a","filterText":"a","insertText":"a
>> ","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"bb","kind":5,"detail
>> ":"int","sortText":"000035bb","filterText":"bb","insertText"
>> :"bb","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"ccc","kind":5,"detai
>> l":"int","sortText":"000035ccc","filterText":"ccc","
>> insertText":"ccc","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake
>> &","sortText":"000079operator=","filterText":"operator=","insertText":"operator=(${1:const
>> fake &})","insertTextFormat":2}
>> -# CHECK-DAG: {"label":"~fake()","kind":4,"d
>> etail":"void","sortText":"000079~fake","filterText":"~fake",
>> "insertText":"~fake()","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"f(int i, const float f)
>> const","kind":2,"detail":"int","sortText":"000035f","filterT
>> ext":"f","insertText":"f(${1:int i}, ${2:const float
>> f})","insertTextFormat":2}
>> -# CHECK: ]}
>> +# CHECK: {"id":2,"jsonrpc":"2.0","result":[
>> +# CHECK-DAG: {"detail":"int","filterText":"
>> a","insertText":"a","insertTextFormat":1,"kind":5,"label":"
>> a","sortText":"000035a"}
>> +# CHECK-DAG: {"detail":"int","filterText":"
>> bb","insertText":"bb","insertTextFormat":1,"kind":5,"label":
>> "bb","sortText":"000035bb"}
>> +# CHECK-DAG: {"detail":"int","filterText":"
>> ccc","insertText":"ccc","insertTextFormat":1,"kind":5,"label
>> ":"ccc","sortText":"000035ccc"}
>> +# CHECK-DAG: {"detail":"fake &","filterText":"operator=","i
>> nsertText":"operator=(${1:const fake &})","insertTextFormat":2,"kind":2,"label":"operator=(const
>> fake &)","sortText":"000079operator="}
>> +# CHECK-DAG: {"detail":"void","filterText":
>> "~fake","insertText":"~fake()","insertTextFormat":1,"kind":4
>> ,"label":"~fake()","sortText":"000079~fake"}
>> +# CHECK-DAG: {"detail":"int","filterText":"f","insertText":"f(${1:int
>> i}, ${2:const float f})","insertTextFormat":2,"kind":2,"label":"f(int i,
>> const float f) const","sortText":"000035f"}
>> +# CHECK-SAME: ]}
>> # Update the source file and check for completions again.
>> Content-Length: 226
>>
>> @@ -44,15 +44,12 @@ Content-Length: 226
>> Content-Length: 148
>>
>> {"jsonrpc":"2.0","id":3,"method":"textDocument/completion",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":3,"character":5}}}
>> -# Repeat the completion request, expect the same results.
>> -#
>> -# CHECK: {"jsonrpc":"2.0","id":3,"result":[
>> -# CHECK-DAG: {"label":"func()","kind":2,"detail":"int (*)(int,
>> int)","sortText":"000034func","filterText":"func","insertTex
>> t":"func()","insertTextFormat":1}
>> -# CHECK: ]}
>> +# CHECK: {"id":3,"jsonrpc":"2.0","result":[
>> +# CHECK-DAG: {"detail":"int (*)(int, int)","filterText":"func","ins
>> ertText":"func()","insertTextFormat":1,"kind":2,"label":"
>> func()","sortText":"000034func"}
>> +# CHECK-SAME: ]}
>> Content-Length: 44
>>
>> {"jsonrpc":"2.0","id":4,"method":"shutdown"}
>> -# CHECK: {"jsonrpc":"2.0","id":4,"result":null}
>> Content-Length: 33
>>
>> {"jsonrpc":"2.0":"method":"exit"}
>>
>> Modified: clang-tools-extra/trunk/test/clangd/completion.test
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> test/clangd/completion.test?rev=317486&r1=317485&r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/test/clangd/completion.test (original)
>> +++ clang-tools-extra/trunk/test/clangd/completion.test Mon Nov 6
>> 07:40:30 2017
>> @@ -15,27 +15,27 @@ Content-Length: 148
>> # The order of results returned by codeComplete seems to be
>> # nondeterministic, so we check regardless of order.
>> #
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[
>> -# CHECK-DAG: {"label":"a","kind":5,"detail"
>> :"int","sortText":"000035a","filterText":"a","insertText":"a
>> ","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"bb","kind":5,"detail
>> ":"int","sortText":"000035bb","filterText":"bb","insertText"
>> :"bb","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"ccc","kind":5,"detai
>> l":"int","sortText":"000035ccc","filterText":"ccc","
>> insertText":"ccc","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake
>> &","sortText":"000079operator=","filterText":"operator=","in
>> sertText":"operator=","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"~fake()","kind":4,"d
>> etail":"void","sortText":"000079~fake","filterText":"~fake",
>> "insertText":"~fake","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"f(int i, const float f)
>> const","kind":2,"detail":"int","sortText":"000035f","filterT
>> ext":"f","insertText":"f","insertTextFormat":1}
>> -# CHECK: ]}
>> +# CHECK: {"id":1,"jsonrpc":"2.0","result":[
>> +# CHECK-DAG: {"detail":"int","filterText":"
>> a","insertText":"a","insertTextFormat":1,"kind":5,"label":"
>> a","sortText":"000035a"}
>> +# CHECK-DAG: {"detail":"int","filterText":"
>> bb","insertText":"bb","insertTextFormat":1,"kind":5,"label":
>> "bb","sortText":"000035bb"}
>> +# CHECK-DAG: {"detail":"int","filterText":"
>> ccc","insertText":"ccc","insertTextFormat":1,"kind":5,"label
>> ":"ccc","sortText":"000035ccc"}
>> +# CHECK-DAG: {"detail":"fake &","filterText":"operator=","i
>> nsertText":"operator=","insertTextFormat":1,"kind":2,"label":"operator=(const
>> fake &)","sortText":"000079operator="}
>> +# CHECK-DAG: {"detail":"void","filterText":
>> "~fake","insertText":"~fake","insertTextFormat":1,"kind":4,"
>> label":"~fake()","sortText":"000079~fake"}
>> +# CHECK-DAG: {"detail":"int","filterText":"
>> f","insertText":"f","insertTextFormat":1,"kind":2,"label":"f(int i,
>> const float f) const","sortText":"000035f"}
>> +# CHECK-SAME: ]}
>> Content-Length: 148
>>
>> {"jsonrpc":"2.0","id":2,"method":"textDocument/completion",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":3,"character":5}}}
>> # Repeat the completion request, expect the same results.
>> #
>> -# CHECK: {"jsonrpc":"2.0","id":2,"result":[
>> -# CHECK-DAG: {"label":"a","kind":5,"detail"
>> :"int","sortText":"000035a","filterText":"a","insertText":"a
>> ","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"bb","kind":5,"detail
>> ":"int","sortText":"000035bb","filterText":"bb","insertText"
>> :"bb","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"ccc","kind":5,"detai
>> l":"int","sortText":"000035ccc","filterText":"ccc","
>> insertText":"ccc","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake
>> &","sortText":"000079operator=","filterText":"operator=","in
>> sertText":"operator=","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"~fake()","kind":4,"d
>> etail":"void","sortText":"000079~fake","filterText":"~fake",
>> "insertText":"~fake","insertTextFormat":1}
>> -# CHECK-DAG: {"label":"f(int i, const float f)
>> const","kind":2,"detail":"int","sortText":"000035f","filterT
>> ext":"f","insertText":"f","insertTextFormat":1}
>> -# CHECK: ]}
>> +# CHECK: {"id":2,"jsonrpc":"2.0","result":[
>> +# CHECK-DAG: {"detail":"int","filterText":"
>> a","insertText":"a","insertTextFormat":1,"kind":5,"label":"
>> a","sortText":"000035a"}
>> +# CHECK-DAG: {"detail":"int","filterText":"
>> bb","insertText":"bb","insertTextFormat":1,"kind":5,"label":
>> "bb","sortText":"000035bb"}
>> +# CHECK-DAG: {"detail":"int","filterText":"
>> ccc","insertText":"ccc","insertTextFormat":1,"kind":5,"label
>> ":"ccc","sortText":"000035ccc"}
>> +# CHECK-DAG: {"detail":"fake &","filterText":"operator=","i
>> nsertText":"operator=","insertTextFormat":1,"kind":2,"label":"operator=(const
>> fake &)","sortText":"000079operator="}
>> +# CHECK-DAG: {"detail":"void","filterText":
>> "~fake","insertText":"~fake","insertTextFormat":1,"kind":4,"
>> label":"~fake()","sortText":"000079~fake"}
>> +# CHECK-DAG: {"detail":"int","filterText":"
>> f","insertText":"f","insertTextFormat":1,"kind":2,"label":"f(int i,
>> const float f) const","sortText":"000035f"}
>> +# CHECK-SAME: ]}
>> # Update the source file and check for completions again.
>> Content-Length: 226
>>
>> @@ -46,13 +46,12 @@ Content-Length: 148
>> {"jsonrpc":"2.0","id":3,"method":"textDocument/completion",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":3,"character":5}}}
>> # Repeat the completion request, expect the same results.
>> #
>> -# CHECK: {"jsonrpc":"2.0","id":3,"result":[
>> -# CHECK-DAG: {"label":"func()","kind":2,"detail":"int (*)(int,
>> int)","sortText":"000034func","filterText":"func","insertTex
>> t":"func","insertTextFormat":1}
>> -# CHECK: ]}
>> +# CHECK: {"id":3,"jsonrpc":"2.0","result":[
>> +# CHECK-DAG: {"detail":"int (*)(int, int)","filterText":"func","ins
>> ertText":"func","insertTextFormat":1,"kind":2,"label":"func(
>> )","sortText":"000034func"}
>> +# CHECK-SAME: ]}
>> Content-Length: 44
>>
>> {"jsonrpc":"2.0","id":4,"method":"shutdown"}
>> -# CHECK: {"jsonrpc":"2.0","id":4,"result":null}
>> Content-Length: 33
>>
>> {"jsonrpc":"2.0":"method":"exit"}
>>
>> Modified: clang-tools-extra/trunk/test/clangd/definitions.test
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> test/clangd/definitions.test?rev=317486&r1=317485&r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/test/clangd/definitions.test (original)
>> +++ clang-tools-extra/trunk/test/clangd/definitions.test Mon Nov 6
>> 07:40:30 2017
>> @@ -1,4 +1,4 @@
>> -# RUN: clangd -run-synchronously < %s | FileCheck %s
>> +# RUN: clangd -pretty -run-synchronously < %s | FileCheck
>> -strict-whitespace %s
>> # It is absolutely vital that this file has CRLF line endings.
>> #
>> Content-Length: 125
>> @@ -13,14 +13,44 @@ Content-Length: 148
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/definition",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":2,"character":0}}}
>> # Go to local variable
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp",
>> "range": {"start": {"line": 1, "character": 0}, "end": {"line": 1,
>> "character": 5}}}]}
>> -
>> +# CHECK: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 5,
>> +# CHECK-NEXT: "line": 1
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 0,
>> +# CHECK-NEXT: "line": 1
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "uri": "file:///main.cpp"
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> Content-Length: 148
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/definition",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":2,"character":1}}}
>> # Go to local variable, end of token
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp",
>> "range": {"start": {"line": 1, "character": 0}, "end": {"line": 1,
>> "character": 5}}}]}
>> -
>> +# CHECK: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 5,
>> +# CHECK-NEXT: "line": 1
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 0,
>> +# CHECK-NEXT: "line": 1
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "uri": "file:///main.cpp"
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> Content-Length: 214
>>
>> {"jsonrpc":"2.0","method":"textDocument/didChange","params"
>> :{"textDocument":{"uri":"file:///main.cpp","version":2},"
>> contentChanges":[{"text":"struct Foo {\nint x;\n};\nint main() {\n Foo
>> bar = { x : 1 };\n}\n"}]}}
>> @@ -29,8 +59,23 @@ Content-Length: 149
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/definition",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":4,"character":14}}}
>> # Go to field, GNU old-style field designator
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp",
>> "range": {"start": {"line": 1, "character": 0}, "end": {"line": 1,
>> "character": 5}}}]}
>> -
>> +# CHECK: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 5,
>> +# CHECK-NEXT: "line": 1
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 0,
>> +# CHECK-NEXT: "line": 1
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "uri": "file:///main.cpp"
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> Content-Length: 215
>>
>> {"jsonrpc":"2.0","method":"textDocument/didChange","params"
>> :{"textDocument":{"uri":"file:///main.cpp","version":3},"
>> contentChanges":[{"text":"struct Foo {\nint x;\n};\nint main() {\n Foo
>> baz = { .x = 2 };\n}\n"}]}}
>> @@ -39,8 +84,23 @@ Content-Length: 149
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/definition",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":4,"character":15}}}
>> # Go to field, field designator
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp",
>> "range": {"start": {"line": 1, "character": 0}, "end": {"line": 1,
>> "character": 5}}}]}
>> -
>> +# CHECK: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 5,
>> +# CHECK-NEXT: "line": 1
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 0,
>> +# CHECK-NEXT: "line": 1
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "uri": "file:///main.cpp"
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> Content-Length: 187
>>
>> {"jsonrpc":"2.0","method":"textDocument/didChange","params"
>> :{"textDocument":{"uri":"file:///main.cpp","version":4},"contentChanges":[{"text":"int
>> main() {\n main();\n return 0;\n}"}]}}
>> @@ -49,8 +109,23 @@ Content-Length: 148
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/definition",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":1,"character":3}}}
>> # Go to function declaration, function call
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp",
>> "range": {"start": {"line": 0, "character": 0}, "end": {"line": 3,
>> "character": 1}}}]}
>> -
>> +# CHECK: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 1,
>> +# CHECK-NEXT: "line": 3
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 0,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "uri": "file:///main.cpp"
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> Content-Length: 208
>>
>> {"jsonrpc":"2.0","method":"textDocument/didChange","params"
>> :{"textDocument":{"uri":"file:///main.cpp","version":5},"
>> contentChanges":[{"text":"struct Foo {\n};\nint main() {\n Foo bar;\n
>> return 0;\n}\n"}]}}
>> @@ -59,8 +134,23 @@ Content-Length: 148
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/definition",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":3,"character":3}}}
>> # Go to struct declaration, new struct instance
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp",
>> "range": {"start": {"line": 0, "character": 0}, "end": {"line": 1,
>> "character": 1}}}]}
>> -
>> +# CHECK: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 1,
>> +# CHECK-NEXT: "line": 1
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 0,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "uri": "file:///main.cpp"
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> Content-Length: 231
>>
>> {"jsonrpc":"2.0","method":"textDocument/didChange","params"
>> :{"textDocument":{"uri":"file:///main.cpp","version":5},"
>> contentChanges":[{"text":"namespace n1 {\nstruct Foo {\n};\n}\nint
>> main() {\n n1::Foo bar;\n return 0;\n}\n"}]}}
>> @@ -69,8 +159,23 @@ Content-Length: 148
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/definition",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":5,"character":4}}}
>> # Go to struct declaration, new struct instance, qualified name
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp",
>> "range": {"start": {"line": 0, "character": 0}, "end": {"line": 3,
>> "character": 1}}}]}
>> -
>> +# CHECK: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 1,
>> +# CHECK-NEXT: "line": 3
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 0,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "uri": "file:///main.cpp"
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> Content-Length: 215
>>
>> {"jsonrpc":"2.0","method":"textDocument/didChange","params"
>> :{"textDocument":{"uri":"file:///main.cpp","version":6},"
>> contentChanges":[{"text":"struct Foo {\n int x;\n};\nint main() {\n
>> Foo bar;\n bar.x;\n}\n"}]}}
>> @@ -79,8 +184,23 @@ Content-Length: 148
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/definition",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":5,"character":7}}}
>> # Go to field declaration, field reference
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp",
>> "range": {"start": {"line": 1, "character": 2}, "end": {"line": 1,
>> "character": 7}}}]}
>> -
>> +# CHECK: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 7,
>> +# CHECK-NEXT: "line": 1
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 2,
>> +# CHECK-NEXT: "line": 1
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "uri": "file:///main.cpp"
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> Content-Length: 220
>>
>> {"jsonrpc":"2.0","method":"textDocument/didChange","params"
>> :{"textDocument":{"uri":"file:///main.cpp","version":7},"
>> contentChanges":[{"text":"struct Foo {\n void x();\n};\nint main() {\n
>> Foo bar;\n bar.x();\n}\n"}]}}
>> @@ -89,8 +209,23 @@ Content-Length: 148
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/definition",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":5,"character":7}}}
>> # Go to method declaration, method call
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp",
>> "range": {"start": {"line": 1, "character": 2}, "end": {"line": 1,
>> "character": 10}}}]}
>> -
>> +# CHECK: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 10,
>> +# CHECK-NEXT: "line": 1
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 2,
>> +# CHECK-NEXT: "line": 1
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "uri": "file:///main.cpp"
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> Content-Length: 240
>>
>> {"jsonrpc":"2.0","method":"textDocument/didChange","params"
>> :{"textDocument":{"uri":"file:///main.cpp","version":7},"
>> contentChanges":[{"text":"struct Foo {\n};\ntypedef Foo TypedefFoo;\nint
>> main() {\n TypedefFoo bar;\n return 0;\n}\n"}]}}
>> @@ -99,8 +234,23 @@ Content-Length: 149
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/definition",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":4,"character":10}}}
>> # Go to typedef
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp",
>> "range": {"start": {"line": 2, "character": 0}, "end": {"line": 2,
>> "character": 22}}}]}
>> -
>> +# CHECK: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 22,
>> +# CHECK-NEXT: "line": 2
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 0,
>> +# CHECK-NEXT: "line": 2
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "uri": "file:///main.cpp"
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> Content-Length: 254
>>
>> {"jsonrpc":"2.0","method":"textDocument/didChange","params"
>> :{"textDocument":{"uri":"file:///main.cpp","version":7},"
>> contentChanges":[{"text":"template <typename MyTemplateParam>\nvoid
>> foo() {\n MyTemplateParam a;\n}\nint main() {\n return 0;\n}\n"}]}}
>> @@ -109,8 +259,9 @@ Content-Length: 149
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/definition",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":2,"character":13}}}
>> # Go to template type parameter. Fails until clangIndex is modified to
>> handle those.
>> -# no-CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri":
>> "file:///main.cpp", "range": {"start": {"line": 0, "character": 10}, "end":
>> {"line": 0, "character": 34}}}]}
>> -
>> +# CHECK: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": []
>> Content-Length: 256
>>
>> {"jsonrpc":"2.0","method":"textDocument/didChange","params"
>> :{"textDocument":{"uri":"file:///main.cpp","version":7},"
>> contentChanges":[{"text":"namespace ns {\nstruct Foo {\nstatic void
>> bar() {}\n};\n}\nint main() {\n ns::Foo::bar();\n return 0;\n}\n"}]}}
>> @@ -119,8 +270,23 @@ Content-Length: 148
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/definition",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":6,"character":4}}}
>> # Go to namespace, static method call
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp",
>> "range": {"start": {"line": 0, "character": 0}, "end": {"line": 4,
>> "character": 1}}}]}
>> -
>> +# CHECK: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 1,
>> +# CHECK-NEXT: "line": 4
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 0,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "uri": "file:///main.cpp"
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> Content-Length: 265
>>
>> {"jsonrpc":"2.0","method":"textDocument/didChange","params"
>> :{"textDocument":{"uri":"file:///main.cpp","version":7},"
>> contentChanges":[{"text":"namespace ns {\nstruct Foo {\n int field;\n
>> Foo(int param) : field(param) {}\n};\n}\nint main() {\n return
>> 0;\n}\n"}]}}
>> @@ -128,9 +294,24 @@ Content-Length: 265
>> Content-Length: 149
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/definition",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":3,"character":21}}}
>> -# Go to field, member initializer
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp",
>> "range": {"start": {"line": 2, "character": 2}, "end": {"line": 2,
>> "character": 11}}}]}
>> -
>> +# Go to field, member initializer
>> +# CHECK: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 11,
>> +# CHECK-NEXT: "line": 2
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 2,
>> +# CHECK-NEXT: "line": 2
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "uri": "file:///main.cpp"
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> Content-Length: 204
>>
>> {"jsonrpc":"2.0","method":"textDocument/didChange","params"
>> :{"textDocument":{"uri":"file:///main.cpp","version":7},"
>> contentChanges":[{"text":"#define MY_MACRO 0\nint main() {\n return
>> MY_MACRO;\n}\n"}]}}
>> @@ -139,8 +320,23 @@ Content-Length: 148
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/definition",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":2,"character":9}}}
>> # Go to macro.
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri":
>> "file:///{{([A-Za-z]:/)?}}main.cpp", "range": {"start": {"line": 0,
>> "character": 8}, "end": {"line": 0, "character": 18}}}]}
>> -
>> +# CHECK: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 18,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 8,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "uri": "file:///main.cpp"
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> Content-Length: 217
>>
>> {"jsonrpc":"2.0","method":"textDocument/didChange","params"
>> :{"textDocument":{"uri":"file:///main.cpp","version":7},"
>> contentChanges":[{"text":"#define FOO 1\nint a = FOO;\n#define FOO
>> 2\nint b = FOO;\n#undef FOO\n"}]}}
>> @@ -149,29 +345,77 @@ Content-Length: 148
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/definition",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":1,"character":8}}}
>> # Go to macro, re-defined later
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri":
>> "file:///{{([A-Za-z]:/)?}}main.cpp", "range": {"start": {"line": 0,
>> "character": 8}, "end": {"line": 0, "character": 13}}}]}
>> -
>> +# CHECK: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 13,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 8,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "uri": "file:///main.cpp"
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> Content-Length: 148
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/definition",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":3,"character":8}}}
>> # Go to macro, undefined later
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp",
>> "range": {"start": {"line": 2, "character": 8}, "end": {"line": 2,
>> "character": 13}}}]}
>> -
>> +# CHECK: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 13,
>> +# CHECK-NEXT: "line": 2
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 8,
>> +# CHECK-NEXT: "line": 2
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "uri": "file:///main.cpp"
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> Content-Length: 148
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/definition",
>> "params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":4,"character":7}}}
>> # Go to macro, being undefined
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp",
>> "range": {"start": {"line": 2, "character": 8}, "end": {"line": 2,
>> "character": 13}}}]}
>> -
>> +# CHECK: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 13,
>> +# CHECK-NEXT: "line": 2
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 8,
>> +# CHECK-NEXT: "line": 2
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "uri": "file:///main.cpp"
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> Content-Length: 156
>>
>> {"jsonrpc":"2.0","id":2,"method":"textDocument/definition",
>> "params":{"textDocument":{"uri":"file:///doesnotexist.
>> cpp"},"position":{"line":4,"character":7}}}
>> -# CHECK: {"jsonrpc":"2.0","id":2,"error":{"code":-32602,"message":"findDefinitions
>> called on non-added file"}}
>> -
>> +# CHECK: "error": {
>> +# CHECK-NEXT: "code": -32602,
>> +# CHECK-NEXT: "message": "findDefinitions called on non-added file"
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "id": 2,
>> +# CHECK-NEXT: "jsonrpc": "2.0"
>> Content-Length: 48
>>
>> {"jsonrpc":"2.0","id":10000,"method":"shutdown"}
>> -# CHECK: {"jsonrpc":"2.0","id":10000,"result":null}
>> Content-Length: 33
>>
>> {"jsonrpc":"2.0":"method":"exit"}
>>
>> Modified: clang-tools-extra/trunk/test/clangd/diagnostics-preamble.test
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> test/clangd/diagnostics-preamble.test?rev=317486&r1=317485&
>> r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/test/clangd/diagnostics-preamble.test
>> (original)
>> +++ clang-tools-extra/trunk/test/clangd/diagnostics-preamble.test Mon
>> Nov 6 07:40:30 2017
>> @@ -1,4 +1,4 @@
>> -# RUN: clangd -run-synchronously < %s | FileCheck %s
>> +# RUN: clangd -pretty -run-synchronously < %s | FileCheck
>> -strict-whitespace %s
>> # It is absolutely vital that this file has CRLF line endings.
>> #
>> Content-Length: 125
>> @@ -8,12 +8,14 @@ Content-Length: 125
>> Content-Length: 206
>>
>> {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{
>> "textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#ifndef
>> FOO\n#define FOO\nint a;\n#else\nint a = b;#endif\n\n\n"}}}
>> -# CHECK: {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics",
>> "params":{"uri":"file:///main.cpp","diagnostics":[]}}
>> -
>> +# CHECK: "method": "textDocument/publishDiagnostics",
>> +# CHECK-NEXT: "params": {
>> +# CHECK-NEXT: "diagnostics": [],
>> +# CHECK-NEXT: "uri": "file:///main.cpp"
>> +# CHECK-NEXT: }
>> Content-Length: 58
>>
>> {"jsonrpc":"2.0","id":2,"method":"shutdown","params":null}
>> -# CHECK: {"jsonrpc":"2.0","id":2,"result":null}
>> Content-Length: 33
>>
>> {"jsonrpc":"2.0":"method":"exit"}
>>
>> Modified: clang-tools-extra/trunk/test/clangd/diagnostics.test
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> test/clangd/diagnostics.test?rev=317486&r1=317485&r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/test/clangd/diagnostics.test (original)
>> +++ clang-tools-extra/trunk/test/clangd/diagnostics.test Mon Nov 6
>> 07:40:30 2017
>> @@ -1,4 +1,4 @@
>> -# RUN: clangd -run-synchronously < %s | FileCheck %s
>> +# RUN: clangd -pretty -run-synchronously < %s | FileCheck
>> -strict-whitespace %s
>> # It is absolutely vital that this file has CRLF line endings.
>> #
>> Content-Length: 125
>> @@ -8,14 +8,43 @@ Content-Length: 125
>> Content-Length: 152
>>
>> {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{
>> "textDocument":{"uri":"file:///foo.c","languageId":"c","version":1,"text":"void
>> main() {}"}}}
>> -#
>> -# CHECK: {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics",
>> "params":{"uri":"file:///foo.c","diagnostics":[{"range":{"start":
>> {"line": 0, "character": 1}, "end": {"line": 0, "character":
>> 1}},"severity":2,"message":"return type of 'main' is not
>> 'int'"},{"range":{"start": {"line": 0, "character": 1}, "end": {"line": 0,
>> "character": 1}},"severity":3,"message":"change return type to 'int'"}]}}
>> -#
>> -#
>> +# CHECK: "method": "textDocument/publishDiagnostics",
>> +# CHECK-NEXT: "params": {
>> +# CHECK-NEXT: "diagnostics": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "message": "return type of 'main' is not 'int'",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 1,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 1,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "severity": 2
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "message": "change return type to 'int'",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 1,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 1,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "severity": 3
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ],
>> +# CHECK-NEXT: "uri": "file:///foo.c"
>> +# CHECK-NEXT: }
>> Content-Length: 44
>>
>> {"jsonrpc":"2.0","id":5,"method":"shutdown"}
>> -# CHECK: {"jsonrpc":"2.0","id":5,"result":null}
>> Content-Length: 33
>>
>> {"jsonrpc":"2.0":"method":"exit"}
>>
>> Modified: clang-tools-extra/trunk/test/clangd/did-change-watch-files.test
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> test/clangd/did-change-watch-files.test?rev=317486&r1=
>> 317485&r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/test/clangd/did-change-watch-files.test
>> (original)
>> +++ clang-tools-extra/trunk/test/clangd/did-change-watch-files.test Mon
>> Nov 6 07:40:30 2017
>> @@ -5,18 +5,7 @@
>> Content-Length: 143
>>
>> {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"
>> processId":123,"rootUri":"file:///path/to/workspace","capabi
>> lities":{},"trace":"off"}}
>> -# CHECK: Content-Length: 466
>> -# CHECK: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{
>> -# CHECK: "textDocumentSync": 1,
>> -# CHECK: "documentFormattingProvider": true,
>> -# CHECK: "documentRangeFormattingProvider": true,
>> -# CHECK: "documentOnTypeFormattingProvider":
>> {"firstTriggerCharacter":"}","moreTriggerCharacter":[]},
>> -# CHECK: "codeActionProvider": true,
>> -# CHECK: "completionProvider": {"resolveProvider": false,
>> "triggerCharacters": [".",">",":"]},
>> -# CHECK: "definitionProvider": true
>> -# CHECK: }}}
>> -#
>> -#Normal case
>> +# Normal case.
>> Content-Length: 217
>>
>> {"jsonrpc":"2.0","method":"workspace/didChangeWatchedFiles"
>> ,"params":{"changes":[{"uri":"file:///path/to/file.cpp","typ
>> e":1},{"uri":"file:///path/to/file2.cpp","type":2},{"uri":"
>> file:///path/to/file3.cpp","type":3}]}}
>>
>> Modified: clang-tools-extra/trunk/test/clangd/execute-command.test
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> test/clangd/execute-command.test?rev=317486&r1=317485&r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/test/clangd/execute-command.test (original)
>> +++ clang-tools-extra/trunk/test/clangd/execute-command.test Mon Nov 6
>> 07:40:30 2017
>> @@ -1,4 +1,4 @@
>> -# RUN: clangd -run-synchronously < %s | FileCheck %s
>> +# RUN: clangd -pretty -run-synchronously < %s | FileCheck
>> -strict-whitespace %s
>> # It is absolutely vital that this file has CRLF line endings.
>> #
>> Content-Length: 125
>> @@ -8,9 +8,54 @@ Content-Length: 125
>> Content-Length: 180
>>
>> {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{
>> "textDocument":{"uri":"file:///foo.c","languageId":"c","version":1,"text":"int
>> main(int i, char **a) { if (i = 2) {}}"}}}
>> -#
>> -# CHECK: {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics",
>> "params":{"uri":"file:///foo.c","diagnostics":[{"range":{"start":
>> {"line": 0, "character": 35}, "end": {"line": 0, "character":
>> 35}},"severity":2,"message":"using the result of an assignment as a
>> condition without parentheses"},{"range":{"start": {"line": 0,
>> "character": 35}, "end": {"line": 0, "character":
>> 35}},"severity":3,"message":"place parentheses around the assignment to
>> silence this warning"},{"range":{"start": {"line": 0, "character": 35},
>> "end": {"line": 0, "character": 35}},"severity":3,"message":"use '==' to
>> turn this assignment into an equality comparison"}]}}
>> -#
>> +# CHECK: "method": "textDocument/publishDiagnostics",
>> +# CHECK-NEXT: "params": {
>> +# CHECK-NEXT: "diagnostics": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "message": "using the result of an assignment as a
>> condition without parentheses",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 35,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 35,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "severity": 2
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "message": "place parentheses around the assignment
>> to silence this warning",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 35,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 35,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "severity": 3
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "message": "use '==' to turn this assignment into
>> an equality comparison",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 35,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 35,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "severity": 3
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ],
>> +# CHECK-NEXT: "uri": "file:///foo.c"
>> +# CHECK-NEXT: }
>> Content-Length: 72
>>
>> {"jsonrpc":"2.0","id":3,"method":"workspace/executeCommand","params":{}}
>>
>> Modified: clang-tools-extra/trunk/test/clangd/extra-flags.test
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> test/clangd/extra-flags.test?rev=317486&r1=317485&r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/test/clangd/extra-flags.test (original)
>> +++ clang-tools-extra/trunk/test/clangd/extra-flags.test Mon Nov 6
>> 07:40:30 2017
>> @@ -1,4 +1,4 @@
>> -# RUN: clangd -run-synchronously < %s | FileCheck %s
>> +# RUN: clangd -pretty -run-synchronously < %s | FileCheck
>> -strict-whitespace %s
>> # It is absolutely vital that this file has CRLF line endings.
>> #
>> Content-Length: 125
>> @@ -8,17 +8,80 @@ Content-Length: 125
>> Content-Length: 205
>>
>> {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{
>> "textDocument":{"uri":"file:///foo.c","languageId":"c","version":1,"text":"int
>> main() { int i; return i; }"},"metadata":{"extraFlags":["-Wall"]}}}
>> -# CHECK: {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics",
>> "params":{"uri":"file:///foo.c","diagnostics":[{"range":{"start":
>> {"line": 0, "character": 28}, "end": {"line": 0, "character":
>> 28}},"severity":2,"message":"variable 'i' is uninitialized when used
>> here"},{"range":{"start": {"line": 0, "character": 19}, "end": {"line": 0,
>> "character": 19}},"severity":3,"message":"initialize the variable 'i' to
>> silence this warning"}]}}
>> -#
>> +# CHECK: "method": "textDocument/publishDiagnostics",
>> +# CHECK-NEXT: "params": {
>> +# CHECK-NEXT: "diagnostics": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "message": "variable 'i' is uninitialized when used
>> here",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 28,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 28,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "severity": 2
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "message": "initialize the variable 'i' to silence
>> this warning",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 19,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 19,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "severity": 3
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ],
>> +# CHECK-NEXT: "uri": "file:///foo.c"
>> +# CHECK-NEXT: }
>> Content-Length: 175
>>
>> {"jsonrpc":"2.0","method":"textDocument/didChange","params"
>> :{"textDocument":{"uri":"file:///foo.c","version":2},"contentChanges":[{"text":"int
>> main() { int i; return i; }"}]}}
>> -# CHECK: {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics",
>> "params":{"uri":"file:///foo.c","diagnostics":[{"range":{"start":
>> {"line": 0, "character": 28}, "end": {"line": 0, "character":
>> 28}},"severity":2,"message":"variable 'i' is uninitialized when used
>> here"},{"range":{"start": {"line": 0, "character": 19}, "end": {"line": 0,
>> "character": 19}},"severity":3,"message":"initialize the variable 'i' to
>> silence this warning"}]}}
>> -#
>> +# CHECK: "method": "textDocument/publishDiagnostics",
>> +# CHECK-NEXT: "params": {
>> +# CHECK-NEXT: "diagnostics": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "message": "variable 'i' is uninitialized when used
>> here",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 28,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 28,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "severity": 2
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "message": "initialize the variable 'i' to silence
>> this warning",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 19,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 19,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "severity": 3
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ],
>> +# CHECK-NEXT: "uri": "file:///foo.c"
>> +# CHECK-NEXT: }
>> Content-Length: 44
>>
>> {"jsonrpc":"2.0","id":5,"method":"shutdown"}
>> -# CHECK: {"jsonrpc":"2.0","id":5,"result":null}
>> Content-Length: 33
>>
>> {"jsonrpc":"2.0":"method":"exit"}
>>
>> Modified: clang-tools-extra/trunk/test/clangd/fixits.test
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> test/clangd/fixits.test?rev=317486&r1=317485&r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/test/clangd/fixits.test (original)
>> +++ clang-tools-extra/trunk/test/clangd/fixits.test Mon Nov 6 07:40:30
>> 2017
>> @@ -1,4 +1,4 @@
>> -# RUN: clangd -run-synchronously < %s | FileCheck %s
>> +# RUN: clangd -pretty -run-synchronously < %s | FileCheck
>> -strict-whitespace %s
>> # It is absolutely vital that this file has CRLF line endings.
>> #
>> Content-Length: 125
>> @@ -8,30 +8,242 @@ Content-Length: 125
>> Content-Length: 180
>>
>> {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{
>> "textDocument":{"uri":"file:///foo.c","languageId":"c","version":1,"text":"int
>> main(int i, char **a) { if (i = 2) {}}"}}}
>> -#
>> -# CHECK: {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics",
>> "params":{"uri":"file:///foo.c","diagnostics":[{"range":{"start":
>> {"line": 0, "character": 35}, "end": {"line": 0, "character":
>> 35}},"severity":2,"message":"using the result of an assignment as a
>> condition without parentheses"},{"range":{"start": {"line": 0,
>> "character": 35}, "end": {"line": 0, "character":
>> 35}},"severity":3,"message":"place parentheses around the assignment to
>> silence this warning"},{"range":{"start": {"line": 0, "character": 35},
>> "end": {"line": 0, "character": 35}},"severity":3,"message":"use '==' to
>> turn this assignment into an equality comparison"}]}}
>> -#
>> +# CHECK: "method": "textDocument/publishDiagnostics",
>> +# CHECK-NEXT: "params": {
>> +# CHECK-NEXT: "diagnostics": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "message": "using the result of an assignment as a
>> condition without parentheses",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 35,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 35,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "severity": 2
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "message": "place parentheses around the assignment
>> to silence this warning",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 35,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 35,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "severity": 3
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "message": "use '==' to turn this assignment into
>> an equality comparison",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 35,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 35,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "severity": 3
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ],
>> +# CHECK-NEXT: "uri": "file:///foo.c"
>> +# CHECK-NEXT: }
>> Content-Length: 746
>>
>> {"jsonrpc":"2.0","id":2,"method":"textDocument/codeAction",
>> "params":{"textDocument":{"uri":"file:///foo.c"},"range":
>> {"start":{"line":104,"character":13},"end":{"line":
>> 0,"character":35}},"context":{"diagnostics":[{"range":{"start": {"line":
>> 0, "character": 35}, "end": {"line": 0, "character":
>> 35}},"severity":2,"message":"using the result of an assignment as a
>> condition without parentheses"},{"range":{"start": {"line": 0,
>> "character": 35}, "end": {"line": 0, "character":
>> 35}},"severity":3,"message":"place parentheses around the assignment to
>> silence this warning"},{"range":{"start": {"line": 0, "character": 35},
>> "end": {"line": 0, "character": 35}},"severity":3,"message":"use '==' to
>> turn this assignment into an equality comparison"}]}}}
>> -#
>> -# CHECK: {"jsonrpc":"2.0","id":2,"result":[{"title":"Apply FixIt 'place
>> parentheses around the assignment to silence this warning'", "command":
>> "clangd.applyFix", "arguments": [{"changes": {"file:///foo.c": [{"range":
>> {"start": {"line": 0, "character": 32}, "end": {"line": 0, "character":
>> 32}}, "newText": "("},{"range": {"start": {"line": 0, "character": 37},
>> "end": {"line": 0, "character": 37}}, "newText": ")"}]}}]},{"title":"Apply
>> FixIt 'use '==' to turn this assignment into an equality comparison'",
>> "command": "clangd.applyFix", "arguments": [{"changes": {"file:///foo.c":
>> [{"range": {"start": {"line": 0, "character": 34}, "end": {"line": 0,
>> "character": 35}}, "newText": "=="}]}}]}]}
>> -#
>> +# CHECK: "id": 2,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "arguments": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "changes": {
>> +# CHECK-NEXT: "file:///foo.c": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "newText": "(",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 32,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 32,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "newText": ")",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 37,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 37,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ],
>> +# CHECK-NEXT: "command": "clangd.applyFix",
>> +# CHECK-NEXT: "title": "Apply FixIt place parentheses around the
>> assignment to silence this warning"
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "arguments": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "changes": {
>> +# CHECK-NEXT: "file:///foo.c": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "newText": "==",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 35,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 34,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ],
>> +# CHECK-NEXT: "command": "clangd.applyFix",
>> +# CHECK-NEXT: "title": "Apply FixIt use '==' to turn this
>> assignment into an equality comparison"
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> Content-Length: 771
>>
>> -{"jsonrpc":"2.0","id":2,"method":"textDocument/codeAction",
>> "params":{"textDocument":{"uri":"file:///foo.c"},"range":
>> {"start":{"line":104,"character":13},"end":{"line":
>> 0,"character":35}},"context":{"diagnostics":[{"range":{"start": {"line":
>> 0, "character": 35}, "end": {"line": 0, "character":
>> 35}},"severity":2,"code":"1","source":"foo","message":"using the result
>> of an assignment as a condition without parentheses"},{"range":{"start":
>> {"line": 0, "character": 35}, "end": {"line": 0, "character":
>> 35}},"severity":3,"message":"place parentheses around the assignment to
>> silence this warning"},{"range":{"start": {"line": 0, "character": 35},
>> "end": {"line": 0, "character": 35}},"severity":3,"message":"use '==' to
>> turn this assignment into an equality comparison"}]}}}
>> +{"jsonrpc":"2.0","id":3,"method":"textDocument/codeAction",
>> "params":{"textDocument":{"uri":"file:///foo.c"},"range":
>> {"start":{"line":104,"character":13},"end":{"line":
>> 0,"character":35}},"context":{"diagnostics":[{"range":{"start": {"line":
>> 0, "character": 35}, "end": {"line": 0, "character":
>> 35}},"severity":2,"code":"1","source":"foo","message":"using the result
>> of an assignment as a condition without parentheses"},{"range":{"start":
>> {"line": 0, "character": 35}, "end": {"line": 0, "character":
>> 35}},"severity":3,"message":"place parentheses around the assignment to
>> silence this warning"},{"range":{"start": {"line": 0, "character": 35},
>> "end": {"line": 0, "character": 35}},"severity":3,"message":"use '==' to
>> turn this assignment into an equality comparison"}]}}}
>> # Make sure unused "code" and "source" fields ignored gracefully
>> -# CHECK: {"jsonrpc":"2.0","id":2,"result":[{"title":"Apply FixIt 'place
>> parentheses around the assignment to silence this warning'", "command":
>> "clangd.applyFix", "arguments": [{"changes": {"file:///foo.c": [{"range":
>> {"start": {"line": 0, "character": 32}, "end": {"line": 0, "character":
>> 32}}, "newText": "("},{"range": {"start": {"line": 0, "character": 37},
>> "end": {"line": 0, "character": 37}}, "newText": ")"}]}}]},{"title":"Apply
>> FixIt 'use '==' to turn this assignment into an equality comparison'",
>> "command": "clangd.applyFix", "arguments": [{"changes": {"file:///foo.c":
>> [{"range": {"start": {"line": 0, "character": 34}, "end": {"line": 0,
>> "character": 35}}, "newText": "=="}]}}]}]}
>> -#
>> +# CHECK: "id": 3,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "arguments": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "changes": {
>> +# CHECK-NEXT: "file:///foo.c": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "newText": "(",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 32,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 32,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "newText": ")",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 37,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 37,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ],
>> +# CHECK-NEXT: "command": "clangd.applyFix",
>> +# CHECK-NEXT: "title": "Apply FixIt place parentheses around the
>> assignment to silence this warning"
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "arguments": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "changes": {
>> +# CHECK-NEXT: "file:///foo.c": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "newText": "==",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 35,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 34,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ],
>> +# CHECK-NEXT: "command": "clangd.applyFix",
>> +# CHECK-NEXT: "title": "Apply FixIt use '==' to turn this
>> assignment into an equality comparison"
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> Content-Length: 329
>>
>> -{"jsonrpc":"2.0","id":3,"method":"workspace/executeCommand"
>> ,"params":{"command":"clangd.applyFix","arguments":[{"
>> changes":{"file:///foo.c":[{"range":{"start":{"line":0,"
>> character":32},"end":{"line":0,"character":32}},"newText":"
>> ("},{"range":{"start":{"line":0,"character":37},"end":{"
>> line":0,"character":37}},"newText":")"}]}}]}}
>> -# CHECK: {"jsonrpc":"2.0","id":3,"result":"Fix applied."}
>> -# CHECK: {"jsonrpc":"2.0","id":1,"method":"workspace/applyEdit","params":{"edit":
>> {"changes": {"file:///foo.c": [{"range": {"start": {"line": 0, "character":
>> 32}, "end": {"line": 0, "character": 32}}, "newText": "("},{"range":
>> {"start": {"line": 0, "character": 37}, "end": {"line": 0, "character":
>> 37}}, "newText": ")"}]}}}}
>> +{"jsonrpc":"2.0","id":4,"method":"workspace/executeCommand"
>> ,"params":{"command":"clangd.applyFix","arguments":[{"
>> changes":{"file:///foo.c":[{"range":{"start":{"line":0,"
>> character":32},"end":{"line":0,"character":32}},"newText":"
>> ("},{"range":{"start":{"line":0,"character":37},"end":{"
>> line":0,"character":37}},"newText":")"}]}}]}}
>> +# CHECK: "id": 4,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": "Fix applied."
>> +#
>> +# CHECK: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "method": "workspace/applyEdit",
>> +# CHECK-NEXT: "params": {
>> +# CHECK-NEXT: "edit": {
>> +# CHECK-NEXT: "changes": {
>> +# CHECK-NEXT: "file:///foo.c": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "newText": "(",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 32,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 32,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "newText": ")",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 37,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 37,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> Content-Length: 44
>>
>> -{"jsonrpc":"2.0","id":3,"method":"shutdown"}
>> -# CHECK: {"jsonrpc":"2.0","id":3,"result":null}
>> +{"jsonrpc":"2.0","id":4,"method":"shutdown"}
>> Content-Length: 33
>>
>> {"jsonrpc":"2.0":"method":"exit"}
>>
>> Modified: clang-tools-extra/trunk/test/clangd/formatting.test
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> test/clangd/formatting.test?rev=317486&r1=317485&r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/test/clangd/formatting.test (original)
>> +++ clang-tools-extra/trunk/test/clangd/formatting.test Mon Nov 6
>> 07:40:30 2017
>> @@ -1,30 +1,71 @@
>> -# RUN: clangd < %s | FileCheck %s
>> +# RUN: clangd -pretty -run-synchronously < %s | FileCheck
>> -strict-whitespace %s
>> # It is absolutely vital that this file has CRLF line endings.
>> #
>> Content-Length: 125
>>
>> {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"
>> processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
>> -# CHECK: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{
>> -# CHECK: "textDocumentSync": 1,
>> -# CHECK: "documentFormattingProvider": true,
>> -# CHECK: "documentRangeFormattingProvider": true,
>> -# CHECK: "documentOnTypeFormattingProvider":
>> {"firstTriggerCharacter":"}","moreTriggerCharacter":[]},
>> -# CHECK: "codeActionProvider": true,
>> -# CHECK: "completionProvider": {"resolveProvider": false,
>> "triggerCharacters": [".",">",":"]},
>> -# CHECK: "definitionProvider": true
>> -# CHECK: }}}
>> -#
>> Content-Length: 193
>>
>> {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{
>> "textDocument":{"uri":"file:///foo.c","languageId":"c","version":1,"text":"int
>> foo ( int x ) {\n x = x+1;\n return x;\n }"}}}
>> -#
>> -#
>> Content-Length: 233
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/rangeFormatt
>> ing","params":{"textDocument":{"uri":"file:///foo.c"},"
>> range":{"start":{"line":1,"character":4},"end":{"line":1,
>> "character":12}},"options":{"tabSize":4,"insertSpaces":true}}}
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"range": {"start": {"line":
>> 0, "character": 19}, "end": {"line": 1, "character": 4}}, "newText": "\n
>> "},{"range": {"start": {"line": 1, "character": 9}, "end": {"line": 1,
>> "character": 9}}, "newText": " "},{"range": {"start": {"line": 1,
>> "character": 10}, "end": {"line": 1, "character": 10}}, "newText": "
>> "},{"range": {"start": {"line": 1, "character": 12}, "end": {"line": 2,
>> "character": 4}}, "newText": "\n "}]}
>> -#
>> -#
>> +# CHECK: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "newText": "\n ",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 4,
>> +# CHECK-NEXT: "line": 1
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 19,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "newText": " ",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 9,
>> +# CHECK-NEXT: "line": 1
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 9,
>> +# CHECK-NEXT: "line": 1
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "newText": " ",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 10,
>> +# CHECK-NEXT: "line": 1
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 10,
>> +# CHECK-NEXT: "line": 1
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "newText": "\n ",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 4,
>> +# CHECK-NEXT: "line": 2
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 12,
>> +# CHECK-NEXT: "line": 1
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> Content-Length: 197
>>
>> {"jsonrpc":"2.0","method":"textDocument/didChange","params"
>> :{"textDocument":{"uri":"file:///foo.c","version":5},"contentChanges":[{"text":"int
>> foo ( int x ) {\n x = x + 1;\n return x;\n }"}]}}
>> @@ -33,14 +74,68 @@ Content-Length: 197
>> Content-Length: 233
>>
>> {"jsonrpc":"2.0","id":2,"method":"textDocument/rangeFormatt
>> ing","params":{"textDocument":{"uri":"file:///foo.c"},"
>> range":{"start":{"line":1,"character":2},"end":{"line":1,
>> "character":12}},"options":{"tabSize":4,"insertSpaces":true}}}
>> -# CHECK: {"jsonrpc":"2.0","id":2,"result":[]}
>> -#
>> +# CHECK: "id": 2,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": []
>> Content-Length: 153
>>
>> {"jsonrpc":"2.0","id":3,"method":"textDocument/formatting",
>> "params":{"textDocument":{"uri":"file:///foo.c"},"options":{"tabSize":4,"
>> insertSpaces":true}}}
>> -# CHECK: {"jsonrpc":"2.0","id":3,"result":[{"range": {"start": {"line":
>> 0, "character": 7}, "end": {"line": 0, "character": 8}}, "newText":
>> ""},{"range": {"start": {"line": 0, "character": 9}, "end": {"line": 0,
>> "character": 10}}, "newText": ""},{"range": {"start": {"line": 0,
>> "character": 15}, "end": {"line": 0, "character": 16}}, "newText":
>> ""},{"range": {"start": {"line": 2, "character": 11}, "end": {"line": 3,
>> "character": 4}}, "newText": "\n"}]}
>> -#
>> -#
>> +# CHECK: "id": 3,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "newText": "",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 8,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 7,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "newText": "",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 10,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 9,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "newText": "",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 16,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 15,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "newText": "\n",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 4,
>> +# CHECK-NEXT: "line": 3
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 11,
>> +# CHECK-NEXT: "line": 2
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>> Content-Length: 190
>>
>> {"jsonrpc":"2.0","method":"textDocument/didChange","params"
>> :{"textDocument":{"uri":"file:///foo.c","version":9},"contentChanges":[{"text":"int
>> foo(int x) {\n x = x + 1;\n return x;\n}"}]}}
>> @@ -49,8 +144,9 @@ Content-Length: 190
>> Content-Length: 153
>>
>> {"jsonrpc":"2.0","id":4,"method":"textDocument/formatting",
>> "params":{"textDocument":{"uri":"file:///foo.c"},"options":{"tabSize":4,"
>> insertSpaces":true}}}
>> -# CHECK: {"jsonrpc":"2.0","id":4,"result":[]}
>> -#
>> +# CHECK: "id": 4,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": []
>> Content-Length: 193
>>
>> {"jsonrpc":"2.0","method":"textDocument/didChange","params"
>> :{"textDocument":{"uri":"file:///foo.c","version":5},"contentChanges":[{"text":"int
>> foo ( int x ) {\n x = x + 1;\n return x;\n}"}]}}
>> @@ -59,13 +155,53 @@ Content-Length: 193
>> Content-Length: 204
>>
>> {"jsonrpc":"2.0","id":5,"method":"textDocument/onTypeFormat
>> ting","params":{"textDocument":{"uri":"file:///foo.c"},"
>> position":{"line":3,"character":1},"ch":"}","options":{"
>> tabSize":4,"insertSpaces":true}}}
>> -# CHECK: {"jsonrpc":"2.0","id":5,"result":[{"range": {"start": {"line":
>> 0, "character": 7}, "end": {"line": 0, "character": 8}}, "newText":
>> ""},{"range": {"start": {"line": 0, "character": 9}, "end": {"line": 0,
>> "character": 10}}, "newText": ""},{"range": {"start": {"line": 0,
>> "character": 15}, "end": {"line": 0, "character": 16}}, "newText": ""}]}
>> -#
>> +# CHECK: "id": 5,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "newText": "",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 8,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 7,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "newText": "",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 10,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 9,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: {
>> +# CHECK-NEXT: "newText": "",
>> +# CHECK-NEXT: "range": {
>> +# CHECK-NEXT: "end": {
>> +# CHECK-NEXT: "character": 16,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "start": {
>> +# CHECK-NEXT: "character": 15,
>> +# CHECK-NEXT: "line": 0
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: }
>> +# CHECK-NEXT: ]
>>
>> Content-Length: 44
>>
>> {"jsonrpc":"2.0","id":6,"method":"shutdown"}
>> -# CHECK: {"jsonrpc":"2.0","id":6,"result":null}
>> Content-Length: 33
>>
>> {"jsonrpc":"2.0":"method":"exit"}
>>
>> Modified: clang-tools-extra/trunk/test/clangd/initialize-params-invali
>> d.test
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> test/clangd/initialize-params-invalid.test?rev=317486&r1=
>> 317485&r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/test/clangd/initialize-params-invalid.test
>> (original)
>> +++ clang-tools-extra/trunk/test/clangd/initialize-params-invalid.test
>> Mon Nov 6 07:40:30 2017
>> @@ -1,27 +1,45 @@
>> -# RUN: clangd -run-synchronously < %s | FileCheck %s
>> +# RUN: clangd -pretty -run-synchronously < %s | FileCheck
>> -strict-whitespace %s
>> # It is absolutely vital that this file has CRLF line endings.
>> #
>> # Test with invalid initialize request parameters
>> Content-Length: 142
>>
>> {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"
>> processId":"","rootUri":"file:///path/to/workspace","capabil
>> ities":{},"trace":"off"}}
>> -# CHECK: Content-Length: 606
>> -# CHECK: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{
>> -# CHECK: "textDocumentSync": 1,
>> -# CHECK: "documentFormattingProvider": true,
>> -# CHECK: "documentRangeFormattingProvider": true,
>> -# CHECK: "documentOnTypeFormattingProvider":
>> {"firstTriggerCharacter":"}","moreTriggerCharacter":[]},
>> -# CHECK: "codeActionProvider": true,
>> -# CHECK: "completionProvider": {"resolveProvider": false,
>> "triggerCharacters": [".",">",":"]},
>> -# CHECK: "signatureHelpProvider": {"triggerCharacters": ["(",","]},
>> -# CHECK: "definitionProvider": true,
>> -# CHECK: "executeCommandProvider": {"commands": ["clangd.applyFix"]}
>> -# CHECK: }}}
>> -#
>> +# CHECK: "id": 0,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": {
>> +# CHECK-NEXT: "codeActionProvider": true,
>> +# CHECK-NEXT: "completionProvider": {
>> +# CHECK-NEXT: "resolveProvider": false,
>> +# CHECK-NEXT: "triggerCharacters": [
>> +# CHECK-NEXT: ".",
>> +# CHECK-NEXT: ">",
>> +# CHECK-NEXT: ":"
>> +# CHECK-NEXT: ]
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "definitionProvider": true,
>> +# CHECK-NEXT: "documentFormattingProvider": true,
>> +# CHECK-NEXT: "documentOnTypeFormattingProvider": {
>> +# CHECK-NEXT: "firstTriggerCharacter": "}",
>> +# CHECK-NEXT: "moreTriggerCharacter": []
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "documentRangeFormattingProvider": true,
>> +# CHECK-NEXT: "executeCommandProvider": {
>> +# CHECK-NEXT: "commands": [
>> +# CHECK-NEXT: "clangd.applyFix"
>> +# CHECK-NEXT: ]
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "signatureHelpProvider": {
>> +# CHECK-NEXT: "triggerCharacters": [
>> +# CHECK-NEXT: "(",
>> +# CHECK-NEXT: ","
>> +# CHECK-NEXT: ]
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "textDocumentSync": 1
>> +# CHECK-NEXT: }
>> Content-Length: 44
>>
>> {"jsonrpc":"2.0","id":3,"method":"shutdown"}
>> -# CHECK: {"jsonrpc":"2.0","id":3,"result":null}
>> Content-Length: 33
>>
>> {"jsonrpc":"2.0":"method":"exit"}
>>
>> Modified: clang-tools-extra/trunk/test/clangd/initialize-params.test
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> test/clangd/initialize-params.test?rev=317486&r1=317485&r2=
>> 317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/test/clangd/initialize-params.test (original)
>> +++ clang-tools-extra/trunk/test/clangd/initialize-params.test Mon Nov
>> 6 07:40:30 2017
>> @@ -1,27 +1,48 @@
>> -# RUN: clangd -run-synchronously < %s | FileCheck %s
>> +# RUN: clangd -pretty -run-synchronously < %s | FileCheck
>> -strict-whitespace %s
>> # It is absolutely vital that this file has CRLF line endings.
>> #
>> # Test initialize request parameters with rootUri
>> Content-Length: 143
>>
>> {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"
>> processId":123,"rootUri":"file:///path/to/workspace","capabi
>> lities":{},"trace":"off"}}
>> -# CHECK: Content-Length: 606
>> -# CHECK: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{
>> -# CHECK: "textDocumentSync": 1,
>> -# CHECK: "documentFormattingProvider": true,
>> -# CHECK: "documentRangeFormattingProvider": true,
>> -# CHECK: "documentOnTypeFormattingProvider":
>> {"firstTriggerCharacter":"}","moreTriggerCharacter":[]},
>> -# CHECK: "codeActionProvider": true,
>> -# CHECK: "completionProvider": {"resolveProvider": false,
>> "triggerCharacters": [".",">",":"]},
>> -# CHECK: "signatureHelpProvider": {"triggerCharacters": ["(",","]},
>> -# CHECK: "definitionProvider": true,
>> -# CHECK: "executeCommandProvider": {"commands": ["clangd.applyFix"]}
>> -# CHECK: }}}
>> -#
>> +# CHECK: "id": 0,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": {
>> +# CHECK-NEXT: "codeActionProvider": true,
>> +# CHECK-NEXT: "completionProvider": {
>> +# CHECK-NEXT: "resolveProvider": false,
>> +# CHECK-NEXT: "triggerCharacters": [
>> +# CHECK-NEXT: ".",
>> +# CHECK-NEXT: ">",
>> +# CHECK-NEXT: ":"
>> +# CHECK-NEXT: ]
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "definitionProvider": true,
>> +# CHECK-NEXT: "documentFormattingProvider": true,
>> +# CHECK-NEXT: "documentOnTypeFormattingProvider": {
>> +# CHECK-NEXT: "firstTriggerCharacter": "}",
>> +# CHECK-NEXT: "moreTriggerCharacter": []
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "documentRangeFormattingProvider": true,
>> +# CHECK-NEXT: "executeCommandProvider": {
>> +# CHECK-NEXT: "commands": [
>> +# CHECK-NEXT: "clangd.applyFix"
>> +# CHECK-NEXT: ]
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "signatureHelpProvider": {
>> +# CHECK-NEXT: "triggerCharacters": [
>> +# CHECK-NEXT: "(",
>> +# CHECK-NEXT: ","
>> +# CHECK-NEXT: ]
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "textDocumentSync": 1
>> +# CHECK-NEXT: }
>> Content-Length: 44
>>
>> {"jsonrpc":"2.0","id":3,"method":"shutdown"}
>> -# CHECK: {"jsonrpc":"2.0","id":3,"result":null}
>> +# CHECK: "id": 3,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": null
>> Content-Length: 33
>>
>> {"jsonrpc":"2.0":"method":"exit"}
>>
>> Modified: clang-tools-extra/trunk/test/clangd/input-mirror.test
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> test/clangd/input-mirror.test?rev=317486&r1=317485&r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/test/clangd/input-mirror.test (original)
>> +++ clang-tools-extra/trunk/test/clangd/input-mirror.test Mon Nov 6
>> 07:40:30 2017
>> @@ -1,4 +1,4 @@
>> -# RUN: clangd -run-synchronously -input-mirror-file %t < %s
>> +# RUN: clangd -pretty -run-synchronously -input-mirror-file %t < %s
>> # Note that we have to use '-b' as -input-mirror-file does not have a
>> newline at the end of file.
>> # RUN: diff -b %t %s
>> # It is absolutely vital that this file has CRLF line endings.
>> @@ -152,7 +152,6 @@ Content-Length: 148
>> Content-Length: 44
>>
>> {"jsonrpc":"2.0","id":3,"method":"shutdown"}
>> -# CHECK: {"jsonrpc":"2.0","id":3,"result":null}
>> Content-Length: 33
>>
>> {"jsonrpc":"2.0":"method":"exit"}
>>
>> Modified: clang-tools-extra/trunk/test/clangd/protocol.test
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> test/clangd/protocol.test?rev=317486&r1=317485&r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/test/clangd/protocol.test (original)
>> +++ clang-tools-extra/trunk/test/clangd/protocol.test Mon Nov 6
>> 07:40:30 2017
>> @@ -1,5 +1,5 @@
>> -# RUN: not clangd -run-synchronously < %s | FileCheck %s
>> -# RUN: not clangd -run-synchronously < %s 2>&1 | FileCheck
>> -check-prefix=STDERR %s
>> +# RUN: not clangd -pretty -run-synchronously < %s | FileCheck
>> -strict-whitespace %s
>> +# RUN: not clangd -pretty -run-synchronously < %s 2>&1 | FileCheck
>> -check-prefix=STDERR %s
>> # vim: fileformat=dos
>> # It is absolutely vital that this file has CRLF line endings.
>> #
>> @@ -12,16 +12,9 @@ Content-Type: application/vscode-jsonrpc
>> {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"
>> processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
>> # Test message with Content-Type after Content-Length
>> #
>> -# CHECK: "jsonrpc":"2.0","id":0,"result":{"capabilities":{
>> -# CHECK-DAG: "textDocumentSync": 1,
>> -# CHECK-DAG: "documentFormattingProvider": true,
>> -# CHECK-DAG: "documentRangeFormattingProvider": true,
>> -# CHECK-DAG: "documentOnTypeFormattingProvider":
>> {"firstTriggerCharacter":"}","moreTriggerCharacter":[]},
>> -# CHECK-DAG: "codeActionProvider": true,
>> -# CHECK-DAG: "completionProvider": {"resolveProvider": false,
>> "triggerCharacters": [".",">",":"]},
>> -# CHECK-DAG: "definitionProvider": true
>> -# CHECK: }}
>> -
>> +# CHECK: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": {
>> +# CHECK: }
>> Content-Length: 246
>>
>> {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{
>> "textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"struct
>> fake { int a, bb, ccc; int f(int i, const float f) const; };\nint main()
>> {\n fake f;\n f.\n}\n"}}}
>> @@ -36,9 +29,16 @@ Content-Length: 146
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/completion",
>> "params":{"textDocument":{"uri":"file:/main.cpp"},"position":{"line":3,"
>> character":5}}}
>> # Test message with Content-Type before Content-Length
>> #
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":[
>> -# CHECK-DAG: {"label":"a","kind":5,"detail"
>> :"int","sortText":"000035a","filterText":"a","insertText":"a
>> ","insertTextFormat":1}
>> -# CHECK: ]}
>> +# CHECK: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK: "filterText": "fake",
>> +# CHECK-NEXT: "insertText": "fake",
>> +# CHECK-NEXT: "insertTextFormat": 1,
>> +# CHECK-NEXT: "kind": 7,
>> +# CHECK-NEXT: "label": "fake::",
>> +# CHECK-NEXT: "sortText": "000075fake"
>> +# CHECK: ]
>>
>> X-Test: Testing
>> Content-Type: application/vscode-jsonrpc; charset-utf-8
>> @@ -55,9 +55,16 @@ Content-Length: 146
>> {"jsonrpc":"2.0","id":3,"method":"textDocument/completion",
>> "params":{"textDocument":{"uri":"file:/main.cpp"},"position":{"line":3,"
>> character":5}}}
>> # Test message with duplicate Content-Length headers
>> #
>> -# CHECK: {"jsonrpc":"2.0","id":3,"result":[
>> -# CHECK-DAG: {"label":"a","kind":5,"detail"
>> :"int","sortText":"000035a","filterText":"a","insertText":"a
>> ","insertTextFormat":1}
>> -# CHECK: ]}
>> +# CHECK: "id": 3,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK: "filterText": "fake",
>> +# CHECK-NEXT: "insertText": "fake",
>> +# CHECK-NEXT: "insertTextFormat": 1,
>> +# CHECK-NEXT: "kind": 7,
>> +# CHECK-NEXT: "label": "fake::",
>> +# CHECK-NEXT: "sortText": "000075fake"
>> +# CHECK: ]
>> # STDERR: Warning: Duplicate Content-Length header received. The
>> previous value for this message (10) was ignored.
>>
>> Content-Type: application/vscode-jsonrpc; charset-utf-8
>> @@ -74,10 +81,16 @@ Content-Length: 146
>> {"jsonrpc":"2.0","id":5,"method":"textDocument/completion",
>> "params":{"textDocument":{"uri":"file:/main.cpp"},"position":{"line":3,"
>> character":5}}}
>> # Test message with Content-Type before Content-Length
>> #
>> -# CHECK: {"jsonrpc":"2.0","id":5,"result":[
>> -# CHECK-DAG: {"label":"a","kind":5,"detail"
>> :"int","sortText":"000035a","filterText":"a","insertText":"a
>> ","insertTextFormat":1}
>> -# CHECK: ]}
>> -
>> +# CHECK: "id": 5,
>> +# CHECK-NEXT: "jsonrpc": "2.0",
>> +# CHECK-NEXT: "result": [
>> +# CHECK: "filterText": "fake",
>> +# CHECK-NEXT: "insertText": "fake",
>> +# CHECK-NEXT: "insertTextFormat": 1,
>> +# CHECK-NEXT: "kind": 7,
>> +# CHECK-NEXT: "label": "fake::",
>> +# CHECK-NEXT: "sortText": "000075fake"
>> +# CHECK: ]
>> Content-Length: 1024
>>
>> {"jsonrpc":"2.0","id":5,"method":"textDocument/completion",
>> "params":{"textDocument":{"uri":"file:/main.cpp"},"position":{"line":3,"
>> character":5}}}
>>
>> Modified: clang-tools-extra/trunk/test/clangd/signature-help.test
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> test/clangd/signature-help.test?rev=317486&r1=317485&r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/test/clangd/signature-help.test (original)
>> +++ clang-tools-extra/trunk/test/clangd/signature-help.test Mon Nov 6
>> 07:40:30 2017
>> @@ -15,12 +15,12 @@ Content-Length: 333
>> Content-Length: 151
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/signatureHel
>> p","params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":8,"character":9}}}
>> -# CHECK: {"jsonrpc":"2.0","id":1,"result":{"activeSignature":0,"activ
>> eParameter":0,"signatures":[
>> +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"activeParameter":0,"activ
>> eSignature":0,"signatures":[
>> # CHECK-DAG: {"label":"foo(float x, float y) ->
>> void","parameters":[{"label":"float x"},{"label":"float y"}]}
>> # CHECK-DAG: {"label":"foo(float x, int y) ->
>> void","parameters":[{"label":"float x"},{"label":"int y"}]}
>> # CHECK-DAG: {"label":"foo(int x, float y) ->
>> void","parameters":[{"label":"int x"},{"label":"float y"}]}
>> # CHECK-DAG: {"label":"foo(int x, int y) ->
>> void","parameters":[{"label":"int x"},{"label":"int y"}]}
>> -# CHECK: ]}
>> +# CHECK-SAME: ]}
>>
>> # Modify the document
>> Content-Length: 333
>> @@ -31,21 +31,20 @@ Content-Length: 333
>> Content-Length: 151
>>
>> {"jsonrpc":"2.0","id":2,"method":"textDocument/signatureHel
>> p","params":{"textDocument":{"uri":"file:///main.cpp"},"
>> position":{"line":8,"character":9}}}
>> -# CHECK: {"jsonrpc":"2.0","id":2,"result":{"activeSignature":0,"activ
>> eParameter":0,"signatures":[
>> +# CHECK: {"id":2,"jsonrpc":"2.0","result":{"activeParameter":0,"activ
>> eSignature":0,"signatures":[
>> # CHECK-DAG: {"label":"bar(int x, int y = 0) ->
>> void","parameters":[{"label":"int x"},{"label":"int y = 0"}]}
>> # CHECK-DAG: {"label":"bar(float x = 0, int y = 42) ->
>> void","parameters":[{"label":"float x = 0"},{"label":"int y = 42"}]}
>> -# CHECK: ]}
>> +# CHECK-SAME: ]}
>>
>> Content-Length: 159
>>
>> {"jsonrpc":"2.0","id":3,"method":"textDocument/signatureHel
>> p","params":{"textDocument":{"uri":"file:///doesnotexist.
>> cpp"},"position":{"line":8,"character":9}}}
>> -# CHECK: {"jsonrpc":"2.0","id":3,"error":{"code":-32602,"message":"signatureHelp
>> is called for non-added document"}}
>> +# CHECK: {"error":{"code":-32602,"message":"signatureHelp is called for
>> non-added document"},"id":3,"jsonrpc":"2.0"}
>>
>> # Shutdown.
>> Content-Length: 49
>>
>> {"jsonrpc":"2.0","id":100000,"method":"shutdown"}
>> -# CHECK: {"jsonrpc":"2.0","id":100000,"result":null}
>> Content-Length: 33
>>
>> {"jsonrpc":"2.0":"method":"exit"}
>>
>> Modified: clang-tools-extra/trunk/test/clangd/unsupported-method.test
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> test/clangd/unsupported-method.test?rev=317486&r1=317485&r2=
>> 317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/test/clangd/unsupported-method.test
>> (original)
>> +++ clang-tools-extra/trunk/test/clangd/unsupported-method.test Mon Nov
>> 6 07:40:30 2017
>> @@ -1,4 +1,4 @@
>> -# RUN: clangd -run-synchronously < %s | FileCheck %s
>> +# RUN: clangd -pretty -run-synchronously < %s | FileCheck
>> -strict-whitespace %s
>> # It is absolutely vital that this file has CRLF line endings.
>> #
>> Content-Length: 125
>> @@ -12,12 +12,16 @@ Content-Length: 143
>> Content-Length: 92
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/jumpInTheAir
>> LikeYouJustDontCare","params":{}}
>> -# CHECK: {"jsonrpc":"2.0","id":1,"error":{"code":-32601,"message":"method
>> not found"}}
>> +# CHECK: "error": {
>> +# CHECK-NEXT: "code": -32601,
>> +# CHECK-NEXT: "message": "method not found"
>> +# CHECK-NEXT: },
>> +# CHECK-NEXT: "id": 1,
>> +# CHECK-NEXT: "jsonrpc": "2.0"
>>
>> Content-Length: 44
>>
>> {"jsonrpc":"2.0","id":2,"method":"shutdown"}
>> -# CHECK: {"jsonrpc":"2.0","id":2,"result":null}
>> Content-Length: 33
>>
>> {"jsonrpc":"2.0":"method":"exit"}
>>
>> Modified: clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> unittests/clangd/CMakeLists.txt?rev=317486&r1=317485&r2=317486&view=diff
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt (original)
>> +++ clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt Mon Nov 6
>> 07:40:30 2017
>> @@ -10,6 +10,7 @@ include_directories(
>>
>> add_extra_unittest(ClangdTests
>> ClangdTests.cpp
>> + JSONExprTests.cpp
>> TraceTests.cpp
>> )
>>
>>
>> Added: clang-tools-extra/trunk/unittests/clangd/JSONExprTests.cpp
>> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/
>> unittests/clangd/JSONExprTests.cpp?rev=317486&view=auto
>> ============================================================
>> ==================
>> --- clang-tools-extra/trunk/unittests/clangd/JSONExprTests.cpp (added)
>> +++ clang-tools-extra/trunk/unittests/clangd/JSONExprTests.cpp Mon Nov
>> 6 07:40:30 2017
>> @@ -0,0 +1,112 @@
>> +//===-- 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"}}}}}}));
>> +}
>> +
>> +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.
>> + };
>> + EXPECT_EQ(R"("\u0000\u0008\u000c\r\n\tS\"\\)"
>> + u8"\x7fΔ\"",
>> + s(test));
>> +
>> + EXPECT_EQ(R"({"object keys are\nescaped":true})",
>> + s(obj{{"object keys are\nescaped", true}}));
>> +}
>> +
>> +TEST(JSONExprTests, PrettyPrinting) {
>> + EXPECT_EQ(
>> + R"({
>> + "empty_array": [],
>> + "empty_object": {},
>> + "full_array": [
>> + 1,
>> + null
>> + ],
>> + "full_object": {
>> + "nested_array": [
>> + {
>> + "property": "value"
>> + }
>> + ]
>> + }
>> +})",
>> + sp(obj{
>> + {"empty_object", obj{}},
>> + {"empty_array", {}},
>> + {"full_array", {1, nullptr}},
>> + {"full_object",
>> + obj{
>> + {"nested_array",
>> + {obj{
>> + {"property", "value"},
>> + }}},
>> + }},
>> + }));
>> +}
>> +
>> +} // namespace
>> +} // namespace json
>> +} // namespace clangd
>> +} // namespace clang
>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20171106/d688ab06/attachment-0001.html>
More information about the cfe-commits
mailing list