[clang-tools-extra] r317486 - Adds a json::Expr type to represent intermediate JSON expressions.
Ilya Biryukov via cfe-commits
cfe-commits at lists.llvm.org
Wed Nov 8 03:55:32 PST 2017
What's the exact problem with "file://" URIs on Windows? How to properly
convert the Windows-style absolute paths into those? (i.e.
"C:\Users\Admin\MyProject\Main.cpp"?)
If so, there is an overview in Wikipedia (
https://en.wikipedia.org/wiki/File_URI_scheme#Windows_2). In short, they
should look this way: file:///c/Users/Admin/MyProject/Main.cpp.
On Wed, Nov 8, 2017 at 4:37 PM, Sam McCall <sam.mccall at gmail.com> wrote:
> I think all the JSON-related windows breakages are now fixed, and the
> remaining definitions.test breakage was caused by r317585.
> (Currently trying to get a windows machine to verify this)
>
> I have to confess I don't know much about how file:// URIs should work on
> windows. Marc-Andre - any thoughts, or maybe we should revert until we can
> work this one out?
>
> On Wed, Nov 8, 2017 at 3:39 AM, Yung, Douglas <douglas.yung at sony.com>
> wrote:
>
>> Hi Sam,
>>
>> The test definitions.test is currently failing on the PS4 Windows bot
>> because the URI returned is of the format "file:///C:/main.cpp" instead of
>> the expected "file:///main.cpp" when run on a Windows machine. Can you
>> please fix this ASAP so that we can get the bot green again?
>>
>> Here you can see the failure on the build bot:
>> http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-
>> scei-ps4-windows10pro-fast/builds/13343
>>
>> You can reproduce the failure by feeding the following file to clangd on
>> Windows:
>>
>> # Begin failure.test
>> Content-Length: 125
>>
>> {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"
>> processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
>>
>> 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"}]}}
>>
>> Content-Length: 148
>>
>> {"jsonrpc":"2.0","id":1,"method":"textDocument/definition","
>> params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":1,"
>> character":8}}}
>> # End failure.test
>>
>>
>> This is cut down from test\clangd\definitions.test. The failure is on
>> line 337 where it is looking for this:
>>
>> # CHECK-NEXT: "uri": "file:///main.cpp"
>>
>> However, clangd is generating:
>>
>> "uri": "file:///C:/main.cpp"
>>
>> If you could fix this as soon as possible it would be greatly appreciated
>> since it is causing the PS4 Windows bot to be red.
>>
>> Thanks!
>>
>> Douglas Yung
>>
>> > -----Original Message-----
>> > From: cfe-commits [mailto:cfe-commits-bounces at lists.llvm.org] On
>> Behalf Of Sam
>> > McCall via cfe-commits
>> > Sent: Monday, November 06, 2017 7:41
>> > To: cfe-commits at lists.llvm.org
>> > Subject: [clang-tools-extra] r317486 - Adds a json::Expr type to
>> represent
>> > intermediate JSON expressions.
>> >
>> > 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
>> S1uGHRyGTXaoy3DjqM
>> > 4/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=31
>> 7486&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=dif
>> > f
>> > ============================================================
>> ==================
>> > --- 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/publishDiagnostic
>> s","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=d
>> > iff
>> > ============================================================
>> ==================
>> > --- 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=dif
>> > f
>> > ============================================================
>> ==================
>> > --- 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=3174
>> 86&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_s
>> tr(),
>> > - 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.document
>> ation)
>> > - << 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.insertText
>> Format);
>> > 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=dif
>> > f
>> > ============================================================
>> ==================
>> > --- 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":{"textDocu
>> > ment":{"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","f
>> ilterText":"a","in
>> > sertText":"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":{"textDocu
>> > ment":{"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","f
>> ilterText":"a","in
>> > sertText":"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.t
>> est
>> > 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":{"textDocu
>> > ment":{"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,"sortText":"000050int","filterText"
>> :"int","insertText
>> > ":"int","insertTextFormat":1}
>> > +# CHECK-DAG:
>> > {"filterText":"int","insertText":"int","insertTextFormat":1,
>> "kind":14,"label":
>> > "int","sortText":"000050int"}
>> > #
>> > # Code pattern
>> > -# CHECK-DAG:
>> > {"label":"static_cast<type>(expression)","kind":15,"sortText
>> ":"000040static_ca
>> > st","filterText":"static_cast","insertText":"static_cast<${1
>> :type}>(${2:expres
>> > sion})","insertTextFormat":2}
>> > +# CHECK-DAG:
>> > {"filterText":"static_cast","insertText":"static_cast<${1:ty
>> pe}>(${2:expressio
>> > n})","insertTextFormat":2,"kind":15,"label":"static_cast<typ
>> e>(expression)","s
>> > ortText":"000040static_cast"}
>> > #
>> > # Struct
>> > -# CHECK-DAG:
>> > {"label":"Struct","kind":7,"sortText":"000050Struct","filter
>> Text":"Struct","in
>> > sertText":"Struct","insertTextFormat":1}
>> > +# CHECK-DAG:
>> > {"filterText":"Struct","insertText":"Struct","insertTextForm
>> at":1,"kind":7,"la
>> > bel":"Struct","sortText":"000050Struct"}
>> > #
>> > # Macro
>> > -# CHECK-DAG:
>> > {"label":"MACRO","kind":1,"sortText":"000070MACRO","filterTe
>> xt":"MACRO","inser
>> > tText":"MACRO","insertTextFormat":1}
>> > +# CHECK-DAG:
>> > {"filterText":"MACRO","insertText":"MACRO","insertTextFormat
>> ":1,"kind":1,"labe
>> > l":"MACRO","sortText":"000070MACRO"}
>> > #
>> > # Variable
>> > -# CHECK-DAG:
>> > {"label":"variable","kind":6,"detail":"int","sortText":"0000
>> 12variable","filte
>> > rText":"variable","insertText":"variable","insertTextFormat":1}
>> > +# CHECK-DAG:
>> > {"detail":"int","filterText":"variable","insertText":"variab
>> le","insertTextFor
>> > mat":1,"kind":6,"label":"variable","sortText":"000012variable"}
>> > #
>> > # Function
>> > -# CHECK-DAG:
>> > {"label":"function()","kind":3,"detail":"int","sortText":"00
>> 0012function","fil
>> > terText":"function","insertText":"function()","insertTextFormat":1}
>> > +# CHECK-DAG:
>> > {"detail":"int","filterText":"function","insertText":"functi
>> on()","insertTextF
>> > ormat":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.te
>> st
>> > 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,"detail":"void","sortText":"000034
>> pub","filterText":
>> > "pub","insertText":"pub","insertTextFormat":1}
>> > -# CHECK-DAG:
>> > {"label":"prot()","kind":2,"detail":"void","sortText":"00003
>> 4prot","filterText
>> > ":"prot","insertText":"prot","insertTextFormat":1}
>> > -# CHECK-DAG:
>> > {"label":"priv()","kind":2,"detail":"void","sortText":"00003
>> 4priv","filterText
>> > ":"priv","insertText":"priv","insertTextFormat":1}
>> > -# CHECK: ]}
>> > +# CHECK: {"id":2,"jsonrpc":"2.0","result":[
>> > +# CHECK-DAG:
>> > {"detail":"void","filterText":"pub","insertText":"pub","inse
>> rtTextFormat":1,"k
>> > ind":2,"label":"pub()","sortText":"000034pub"}
>> > +# CHECK-DAG:
>> > {"detail":"void","filterText":"prot","insertText":"prot","in
>> sertTextFormat":1,
>> > "kind":2,"label":"prot()","sortText":"000034prot"}
>> > +# CHECK-DAG:
>> > {"detail":"void","filterText":"priv","insertText":"priv","in
>> sertTextFormat":1,
>> > "kind":2,"label":"priv()","sortText":"000034priv"}
>> > +# CHECK-SAME: ]}
>> >
>> > Content-Length: 151
>> >
>> >
>> > {"jsonrpc":"2.0","id":3,"method":"textDocument/completion","
>> params":{"textDocu
>> > ment":{"uri":"file:///main.cpp"},"position":{"line":17,"character":4}}}
>> > -# CHECK: {"jsonrpc":"2.0","id":3,"result":[
>> > -# CHECK-DAG:
>> > {"label":"pub()","kind":2,"detail":"void","sortText":"000034
>> pub","filterText":
>> > "pub","insertText":"pub","insertTextFormat":1}
>> > -# CHECK-DAG:
>> > {"label":"prot()","kind":2,"detail":"void","sortText":"20003
>> 4prot","filterText
>> > ":"prot","insertText":"prot","insertTextFormat":1}
>> > -# CHECK-DAG:
>> > {"label":"priv()","kind":2,"detail":"void","sortText":"20003
>> 4priv","filterText
>> > ":"priv","insertText":"priv","insertTextFormat":1}
>> > -# CHECK: ]}
>> > +# CHECK: {"id":3,"jsonrpc":"2.0","result":[
>> > +# CHECK-DAG:
>> > {"detail":"void","filterText":"pub","insertText":"pub","inse
>> rtTextFormat":1,"k
>> > ind":2,"label":"pub()","sortText":"000034pub"}
>> > +# CHECK-DAG:
>> > {"detail":"void","filterText":"prot","insertText":"prot","in
>> sertTextFormat":1,
>> > "kind":2,"label":"prot()","sortText":"200034prot"}
>> > +# CHECK-DAG:
>> > {"detail":"void","filterText":"priv","insertText":"priv","in
>> sertTextFormat":1,
>> > "kind":2,"label":"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.te
>> st
>> > 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":{"textDocu
>> > ment":{"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","filte
>> rText":"foo","inse
>> > rtText":"foo","insertTextFormat":1}
>> > -# CHECK-DAG: {"label":"bar()
>> > const","kind":2,"detail":"int","sortText":"000037bar","filte
>> rText":"bar","inse
>> > rtText":"bar","insertTextFormat":1}
>> > -# CHECK-DAG: {"label":"Foo::foo()
>> > const","kind":2,"detail":"int","sortText":"000037foo","filte
>> rText":"foo","inse
>> > rtText":"foo","insertTextFormat":1}
>> > -# CHECK: ]}
>> > +# CHECK: {"id":2,"jsonrpc":"2.0","result":[
>> > +# CHECK-DAG:
>> > {"detail":"int","filterText":"foo","insertText":"foo","inser
>> tTextFormat":1,"ki
>> > nd":2,"label":"foo() const","sortText":"200035foo"}
>> > +# CHECK-DAG:
>> > {"detail":"int","filterText":"bar","insertText":"bar","inser
>> tTextFormat":1,"ki
>> > nd":2,"label":"bar() const","sortText":"000037bar"}
>> > +# CHECK-DAG:
>> > {"detail":"int","filterText":"foo","insertText":"foo","inser
>> tTextFormat":1,"ki
>> > nd":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","f
>> ilterText":"a","in
>> > sertText":"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,"detail":"int","sortText":"000035ccc
>> ","filterText":"cc
>> > c","insertText":"ccc","insertTextFormat":1}
>> > -# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake
>> > &","sortText":"000079operator=","filterText":"operator=","in
>> sertText":"operato
>> > r=(${1:const fake &})","insertTextFormat":2}
>> > -# CHECK-DAG:
>> > {"label":"~fake()","kind":4,"detail":"void","sortText":"0000
>> 79~fake","filterTe
>> > xt":"~fake","insertText":"~fake()","insertTextFormat":1}
>> > -# CHECK-DAG: {"label":"f(int i, const float f)
>> > const","kind":2,"detail":"int","sortText":"000035f","filterT
>> ext":"f","insertTe
>> > xt":"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","insertTex
>> tFormat":1,"kind":
>> > 5,"label":"a","sortText":"000035a"}
>> > +# CHECK-DAG:
>> > {"detail":"int","filterText":"bb","insertText":"bb","insertT
>> extFormat":1,"kind
>> > ":5,"label":"bb","sortText":"000035bb"}
>> > +# CHECK-DAG:
>> > {"detail":"int","filterText":"ccc","insertText":"ccc","inser
>> tTextFormat":1,"ki
>> > nd":5,"label":"ccc","sortText":"000035ccc"}
>> > +# CHECK-DAG: {"detail":"fake
>> > &","filterText":"operator=","insertText":"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":{"textDocu
>> > ment":{"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","f
>> ilterText":"a","in
>> > sertText":"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,"detail":"int","sortText":"000035ccc
>> ","filterText":"cc
>> > c","insertText":"ccc","insertTextFormat":1}
>> > -# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake
>> > &","sortText":"000079operator=","filterText":"operator=","in
>> sertText":"operato
>> > r=(${1:const fake &})","insertTextFormat":2}
>> > -# CHECK-DAG:
>> > {"label":"~fake()","kind":4,"detail":"void","sortText":"0000
>> 79~fake","filterTe
>> > xt":"~fake","insertText":"~fake()","insertTextFormat":1}
>> > -# CHECK-DAG: {"label":"f(int i, const float f)
>> > const","kind":2,"detail":"int","sortText":"000035f","filterT
>> ext":"f","insertTe
>> > xt":"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","insertTex
>> tFormat":1,"kind":
>> > 5,"label":"a","sortText":"000035a"}
>> > +# CHECK-DAG:
>> > {"detail":"int","filterText":"bb","insertText":"bb","insertT
>> extFormat":1,"kind
>> > ":5,"label":"bb","sortText":"000035bb"}
>> > +# CHECK-DAG:
>> > {"detail":"int","filterText":"ccc","insertText":"ccc","inser
>> tTextFormat":1,"ki
>> > nd":5,"label":"ccc","sortText":"000035ccc"}
>> > +# CHECK-DAG: {"detail":"fake
>> > &","filterText":"operator=","insertText":"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":{"textDocu
>> > ment":{"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()","inser
>> > tTextFormat":1}
>> > -# CHECK: ]}
>> > +# CHECK: {"id":3,"jsonrpc":"2.0","result":[
>> > +# CHECK-DAG: {"detail":"int (*)(int,
>> > int)","filterText":"func","insertText":"func()","insertTextF
>> ormat":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=di
>> > ff
>> > ============================================================
>> ==================
>> > --- 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","f
>> ilterText":"a","in
>> > sertText":"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,"detail":"int","sortText":"000035ccc
>> ","filterText":"cc
>> > c","insertText":"ccc","insertTextFormat":1}
>> > -# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake
>> > &","sortText":"000079operator=","filterText":"operator=","in
>> sertText":"operato
>> > r=","insertTextFormat":1}
>> > -# CHECK-DAG:
>> > {"label":"~fake()","kind":4,"detail":"void","sortText":"0000
>> 79~fake","filterTe
>> > xt":"~fake","insertText":"~fake","insertTextFormat":1}
>> > -# CHECK-DAG: {"label":"f(int i, const float f)
>> > const","kind":2,"detail":"int","sortText":"000035f","filterT
>> ext":"f","insertTe
>> > xt":"f","insertTextFormat":1}
>> > -# CHECK: ]}
>> > +# CHECK: {"id":1,"jsonrpc":"2.0","result":[
>> > +# CHECK-DAG:
>> > {"detail":"int","filterText":"a","insertText":"a","insertTex
>> tFormat":1,"kind":
>> > 5,"label":"a","sortText":"000035a"}
>> > +# CHECK-DAG:
>> > {"detail":"int","filterText":"bb","insertText":"bb","insertT
>> extFormat":1,"kind
>> > ":5,"label":"bb","sortText":"000035bb"}
>> > +# CHECK-DAG:
>> > {"detail":"int","filterText":"ccc","insertText":"ccc","inser
>> tTextFormat":1,"ki
>> > nd":5,"label":"ccc","sortText":"000035ccc"}
>> > +# CHECK-DAG: {"detail":"fake
>> > &","filterText":"operator=","insertText":"operator=","insert
>> TextFormat":1,"kin
>> > d":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","insertTex
>> tFormat":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":{"textDocu
>> > ment":{"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","f
>> ilterText":"a","in
>> > sertText":"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,"detail":"int","sortText":"000035ccc
>> ","filterText":"cc
>> > c","insertText":"ccc","insertTextFormat":1}
>> > -# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake
>> > &","sortText":"000079operator=","filterText":"operator=","in
>> sertText":"operato
>> > r=","insertTextFormat":1}
>> > -# CHECK-DAG:
>> > {"label":"~fake()","kind":4,"detail":"void","sortText":"0000
>> 79~fake","filterTe
>> > xt":"~fake","insertText":"~fake","insertTextFormat":1}
>> > -# CHECK-DAG: {"label":"f(int i, const float f)
>> > const","kind":2,"detail":"int","sortText":"000035f","filterT
>> ext":"f","insertTe
>> > xt":"f","insertTextFormat":1}
>> > -# CHECK: ]}
>> > +# CHECK: {"id":2,"jsonrpc":"2.0","result":[
>> > +# CHECK-DAG:
>> > {"detail":"int","filterText":"a","insertText":"a","insertTex
>> tFormat":1,"kind":
>> > 5,"label":"a","sortText":"000035a"}
>> > +# CHECK-DAG:
>> > {"detail":"int","filterText":"bb","insertText":"bb","insertT
>> extFormat":1,"kind
>> > ":5,"label":"bb","sortText":"000035bb"}
>> > +# CHECK-DAG:
>> > {"detail":"int","filterText":"ccc","insertText":"ccc","inser
>> tTextFormat":1,"ki
>> > nd":5,"label":"ccc","sortText":"000035ccc"}
>> > +# CHECK-DAG: {"detail":"fake
>> > &","filterText":"operator=","insertText":"operator=","insert
>> TextFormat":1,"kin
>> > d":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","insertTex
>> tFormat":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":{"textDocu
>> > ment":{"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","insertT
>> > extFormat":1}
>> > -# CHECK: ]}
>> > +# CHECK: {"id":3,"jsonrpc":"2.0","result":[
>> > +# CHECK-DAG: {"detail":"int (*)(int,
>> > int)","filterText":"func","insertText":"func","insertTextFor
>> mat":1,"kind":2,"l
>> > abel":"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=d
>> > iff
>> > ============================================================
>> ==================
>> > --- 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":{"textDocu
>> > ment":{"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":{"textDocu
>> > ment":{"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":{"textDocu
>> > ment":{"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":{"textDocu
>> > ment":{"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":{"textDocu
>> > ment":{"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":{"textDocu
>> > ment":{"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":{"textDocu
>> > ment":{"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":{"textDocu
>> > ment":{"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":{"textDocu
>> > ment":{"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":{"textDocu
>> > ment":{"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":{"textDocu
>> > ment":{"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":{"textDocu
>> > ment":{"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":{"textDocu
>> > ment":{"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":{"textDocu
>> > ment":{"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":{"textDocu
>> > ment":{"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":{"textDocu
>> > ment":{"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":{"textDocu
>> > ment":{"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":{"textDocu
>> > ment":{"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":{"ur
>> > i":"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":"f
>> > ile:///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=d
>> > iff
>> > ============================================================
>> ==================
>> > --- 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":{"ur
>> > i":"file:///foo.c","languageId":"c","version":1,"text":"void main()
>> {}"}}}
>> > -#
>> > -# CHECK:
>> > {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics",
>> "params":{"uri":"f
>> > ile:///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.t
>> est
>> > 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,"rootU
>> > ri":"file:///path/to/workspace","capabilities":{},"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","type":1},{"uri":"file:
>> ///path/to/file2.c
>> > pp","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":{"ur
>> > i":"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":"f
>> > ile:///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":{"ur
>> > i":"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":"f
>> > ile:///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":"i
>> nitialize
>> > 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":"f
>> > ile:///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":"i
>> nitialize
>> > 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":{"ur
>> > i":"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":"f
>> > ile:///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":{"textDocu
>> > ment":{"uri":"file:///foo.c"},"range":{"start":{"line":104,"
>> character":13},"en
>> > d":{"line":0,"character":35}},"context":{"diagnostics":[{"ra
>> nge":{"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":{"textDocu
>> > ment":{"uri":"file:///foo.c"},"range":{"start":{"line":104,"
>> character":13},"en
>> > d":{"line":0,"character":35}},"context":{"diagnostics":[{"ra
>> nge":{"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":{"textDoc
>> > ument":{"uri":"file:///foo.c"},"range":{"start":{"line":104,
>> "character":13},"e
>> > nd":{"line":0,"character":35}},"context":{"diagnostics":[{"r
>> ange":{"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}},"ne
>> > wText":")"}]}}]}}
>> > -# 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":{"comman
>> > d":"clangd.applyFix","arguments":[{"changes":{"file:///foo.
>> c":[{"range":{"star
>> > t":{"line":0,"character":32},"end":{"line":0,"character":32}
>> },"newText":"("},{
>> > "range":{"start":{"line":0,"character":37},"end":{"line":0,"
>> character":37}},"n
>> > ewText":")"}]}}]}}
>> > +# 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=di
>> > ff
>> > ============================================================
>> ==================
>> > --- 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,"rootP
>> > ath":"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":{"ur
>> > i":"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/rangeFormatti
>> ng","params":{"tex
>> > tDocument":{"uri":"file:///foo.c"},"range":{"start":{"line":
>> 1,"character":4},"
>> > end":{"line":1,"character":12}},"options":{"tabSize":4,"inse
>> rtSpaces":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/rangeFormatti
>> ng","params":{"tex
>> > tDocument":{"uri":"file:///foo.c"},"range":{"start":{"line":
>> 1,"character":2},"
>> > end":{"line":1,"character":12}},"options":{"tabSize":4,"inse
>> rtSpaces":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":{"textDocu
>> > ment":{"uri":"file:///foo.c"},"options":{"tabSize":4,"insert
>> Spaces":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":{"textDocu
>> > ment":{"uri":"file:///foo.c"},"options":{"tabSize":4,"insert
>> Spaces":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/onTypeFormatt
>> ing","params":{"te
>> > xtDocument":{"uri":"file:///foo.c"},"position":{"line":3,"ch
>> aracter":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":"","rootUr
>> > i":"file:///path/to/workspace","capabilities":{},"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,"rootU
>> > ri":"file:///path/to/workspace","capabilities":{},"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,"rootP
>> > ath":"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":{"ur
>> > i":"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":{"textDocu
>> > ment":{"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","f
>> ilterText":"a","in
>> > sertText":"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":{"textDocu
>> > ment":{"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","f
>> ilterText":"a","in
>> > sertText":"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":{"textDocu
>> > ment":{"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","f
>> ilterText":"a","in
>> > sertText":"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":{"textDocu
>> > ment":{"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/signatureHelp
>> ","params":{"textD
>> > ocument":{"uri":"file:///main.cpp"},"position":{"line":8,"ch
>> aracter":9}}}
>> > -# CHECK:
>> > {"jsonrpc":"2.0","id":1,"result":{"activeSignature":0,"activ
>> eParameter":0,"sig
>> > natures":[
>> > +# CHECK:
>> > {"id":1,"jsonrpc":"2.0","result":{"activeParameter":0,"activ
>> eSignature":0,"sig
>> > natures":[
>> > # 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/signatureHelp
>> ","params":{"textD
>> > ocument":{"uri":"file:///main.cpp"},"position":{"line":8,"ch
>> aracter":9}}}
>> > -# CHECK:
>> > {"jsonrpc":"2.0","id":2,"result":{"activeSignature":0,"activ
>> eParameter":0,"sig
>> > natures":[
>> > +# CHECK:
>> > {"id":2,"jsonrpc":"2.0","result":{"activeParameter":0,"activ
>> eSignature":0,"sig
>> > natures":[
>> > # 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/signatureHelp
>> ","params":{"textD
>> > ocument":{"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/jumpInTheAirL
>> ikeYouJustDontCare
>> > ","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=31
>> 7485&r2=317486&vie
>> > w=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
>>
>
>
--
Regards,
Ilya Biryukov
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20171108/e815ecfd/attachment-0001.html>
More information about the cfe-commits
mailing list