[clang-tools-extra] r344617 - [clangd] Send CodeAction responses to textDocument/codeAction (LSP 3.8)

Sam McCall via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 16 09:29:41 PDT 2018


Author: sammccall
Date: Tue Oct 16 09:29:41 2018
New Revision: 344617

URL: http://llvm.org/viewvc/llvm-project?rev=344617&view=rev
Log:
[clangd] Send CodeAction responses to textDocument/codeAction (LSP 3.8)

Summary:
I don't bother mirroring the full capabilities struct, just parse the
bits we care about. I'll send a new patch to use this approach elsewhere too.

Reviewers: kadircet

Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, arphaman, cfe-commits

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

Added:
    clang-tools-extra/trunk/test/clangd/fixits-codeaction.test
    clang-tools-extra/trunk/test/clangd/fixits-command.test
      - copied, changed from r344614, clang-tools-extra/trunk/test/clangd/fixits.test
Removed:
    clang-tools-extra/trunk/test/clangd/fixits.test
Modified:
    clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
    clang-tools-extra/trunk/clangd/ClangdLSPServer.h
    clang-tools-extra/trunk/clangd/Protocol.cpp
    clang-tools-extra/trunk/clangd/Protocol.h

Modified: clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp?rev=344617&r1=344616&r2=344617&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp Tue Oct 16 09:29:41 2018
@@ -103,6 +103,8 @@ void ClangdLSPServer::onInitialize(Initi
       Params.capabilities.textDocument.publishDiagnostics.clangdFixSupport;
   DiagOpts.SendDiagnosticCategory =
       Params.capabilities.textDocument.publishDiagnostics.categorySupport;
+  SupportsCodeAction =
+      Params.capabilities.textDocument.codeActionLiteralSupport;
 
   if (Params.capabilities.workspace && Params.capabilities.workspace->symbol &&
       Params.capabilities.workspace->symbol->symbolKind &&
@@ -339,29 +341,53 @@ void ClangdLSPServer::onDocumentSymbol(D
       });
 }
 
+static Optional<Command> asCommand(const CodeAction &Action) {
+  Command Cmd;
+  if (Action.command && Action.edit)
+    return llvm::None; // Not representable. (We never emit these anyway).
+  if (Action.command) {
+    Cmd = *Action.command;
+  } else if (Action.edit) {
+    Cmd.command = Command::CLANGD_APPLY_FIX_COMMAND;
+    Cmd.workspaceEdit = *Action.edit;
+  } else {
+    return llvm::None;
+  }
+  Cmd.title = Action.title;
+  if (Action.kind && *Action.kind == CodeAction::QUICKFIX_KIND)
+    Cmd.title = "Apply fix: " + Cmd.title;
+  return Cmd;
+}
+
 void ClangdLSPServer::onCodeAction(CodeActionParams &Params) {
-  // We provide a code action for each diagnostic at the requested location
-  // which has FixIts available.
-  auto Code = DraftMgr.getDraft(Params.textDocument.uri.file());
-  if (!Code)
+  // We provide a code action for Fixes on the specified diagnostics.
+  if (!DraftMgr.getDraft(Params.textDocument.uri.file()))
     return replyError(ErrorCode::InvalidParams,
                       "onCodeAction called for non-added file");
 
-  std::vector<Command> Commands;
+  std::vector<CodeAction> Actions;
   for (Diagnostic &D : Params.context.diagnostics) {
     for (auto &F : getFixes(Params.textDocument.uri.file(), D)) {
-      WorkspaceEdit WE;
-      std::vector<TextEdit> Edits(F.Edits.begin(), F.Edits.end());
-      Commands.emplace_back();
-      Commands.back().title = llvm::formatv("Apply fix: {0}", F.Message);
-      Commands.back().command = ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND;
-      Commands.back().workspaceEdit.emplace();
-      Commands.back().workspaceEdit->changes = {
-          {Params.textDocument.uri.uri(), std::move(Edits)},
-      };
+      Actions.emplace_back();
+      Actions.back().title = F.Message;
+      Actions.back().kind = CodeAction::QUICKFIX_KIND;
+      Actions.back().diagnostics = {D};
+      Actions.back().edit.emplace();
+      Actions.back().edit->changes.emplace();
+      (*Actions.back().edit->changes)[Params.textDocument.uri.uri()] = {
+          F.Edits.begin(), F.Edits.end()};
     }
   }
-  reply(json::Array(Commands));
+
+  if (SupportsCodeAction)
+    reply(json::Array(Actions));
+  else {
+    std::vector<Command> Commands;
+    for (const auto &Action : Actions)
+      if (auto Command = asCommand(Action))
+        Commands.push_back(std::move(*Command));
+    reply(json::Array(Commands));
+  }
 }
 
 void ClangdLSPServer::onCompletion(TextDocumentPositionParams &Params) {

Modified: clang-tools-extra/trunk/clangd/ClangdLSPServer.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.h?rev=344617&r1=344616&r2=344617&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdLSPServer.h (original)
+++ clang-tools-extra/trunk/clangd/ClangdLSPServer.h Tue Oct 16 09:29:41 2018
@@ -166,6 +166,8 @@ private:
   SymbolKindBitset SupportedSymbolKinds;
   /// The supported completion item kinds of the client.
   CompletionItemKindBitset SupportedCompletionItemKinds;
+  // Whether the client supports CodeAction response objects.
+  bool SupportsCodeAction = false;
 
   // Store of the current versions of the open documents.
   DraftStore DraftMgr;

Modified: clang-tools-extra/trunk/clangd/Protocol.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.cpp?rev=344617&r1=344616&r2=344617&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Protocol.cpp (original)
+++ clang-tools-extra/trunk/clangd/Protocol.cpp Tue Oct 16 09:29:41 2018
@@ -251,6 +251,9 @@ bool fromJSON(const json::Value &Params,
     return false;
   O.map("completion", R.completion);
   O.map("publishDiagnostics", R.publishDiagnostics);
+  if (auto *CodeAction = Params.getAsObject()->getObject("codeAction"))
+    if (CodeAction->getObject("codeActionLiteralSupport"))
+      R.codeActionLiteralSupport = true;
   return true;
 }
 
@@ -360,6 +363,17 @@ bool fromJSON(const json::Value &Params,
   return O && O.map("textDocument", R.textDocument);
 }
 
+llvm::json::Value toJSON(const Diagnostic &D) {
+  json::Object Diag{
+      {"range", D.range},
+      {"severity", D.severity},
+      {"message", D.message},
+  };
+  // FIXME: this should be used for publishDiagnostics.
+  // FIXME: send category and fixes when appropriate.
+  return std::move(Diag);
+}
+
 bool fromJSON(const json::Value &Params, Diagnostic &R) {
   json::ObjectMapper O(Params);
   if (!O || !O.map("range", R.range) || !O.map("message", R.message))
@@ -448,6 +462,21 @@ json::Value toJSON(const Command &C) {
   return std::move(Cmd);
 }
 
+const llvm::StringLiteral CodeAction::QUICKFIX_KIND = "quickfix";
+
+llvm::json::Value toJSON(const CodeAction &CA) {
+  auto CodeAction = json::Object{{"title", CA.title}};
+  if (CA.kind)
+    CodeAction["kind"] = *CA.kind;
+  if (CA.diagnostics)
+    CodeAction["diagnostics"] = json::Array(*CA.diagnostics);
+  if (CA.edit)
+    CodeAction["edit"] = *CA.edit;
+  if (CA.command)
+    CodeAction["command"] = *CA.command;
+  return std::move(CodeAction);
+}
+
 json::Value toJSON(const WorkspaceEdit &WE) {
   if (!WE.changes)
     return json::Object{};

Modified: clang-tools-extra/trunk/clangd/Protocol.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.h?rev=344617&r1=344616&r2=344617&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Protocol.h (original)
+++ clang-tools-extra/trunk/clangd/Protocol.h Tue Oct 16 09:29:41 2018
@@ -385,6 +385,10 @@ struct TextDocumentClientCapabilities {
 
   /// Capabilities specific to the 'textDocument/publishDiagnostics'
   PublishDiagnosticsClientCapabilities publishDiagnostics;
+
+  /// Flattened from codeAction.codeActionLiteralSupport.
+  // FIXME: flatten other properties in this way.
+  bool codeActionLiteralSupport = false;
 };
 bool fromJSON(const llvm::json::Value &, TextDocumentClientCapabilities &);
 
@@ -613,6 +617,7 @@ struct Diagnostic {
   /// which the issue was produced, e.g. "Semantic Issue" or "Parse Issue".
   std::string category;
 };
+llvm::json::Value toJSON(const Diagnostic &);
 
 /// A LSP-specific comparator used to find diagnostic in a container like
 /// std:map.
@@ -680,6 +685,32 @@ struct Command : public ExecuteCommandPa
 };
 llvm::json::Value toJSON(const Command &C);
 
+/// A code action represents a change that can be performed in code, e.g. to fix
+/// a problem or to refactor code.
+///
+/// A CodeAction must set either `edit` and/or a `command`. If both are
+/// supplied, the `edit` is applied first, then the `command` is executed.
+struct CodeAction {
+  /// A short, human-readable, title for this code action.
+  std::string title;
+
+  /// The kind of the code action.
+  /// Used to filter code actions.
+  llvm::Optional<std::string> kind;
+  const static llvm::StringLiteral QUICKFIX_KIND;
+
+  /// The diagnostics that this code action resolves.
+  llvm::Optional<std::vector<Diagnostic>> diagnostics;
+
+  /// The workspace edit this code action performs.
+  llvm::Optional<WorkspaceEdit> edit;
+
+  /// A command this code action executes. If a code action provides an edit
+  /// and a command, first the edit is executed and then the command.
+  llvm::Optional<Command> command;
+};
+llvm::json::Value toJSON(const CodeAction &);
+
 /// Represents information about programming constructs like variables, classes,
 /// interfaces etc.
 struct SymbolInformation {

Added: clang-tools-extra/trunk/test/clangd/fixits-codeaction.test
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/fixits-codeaction.test?rev=344617&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clangd/fixits-codeaction.test (added)
+++ clang-tools-extra/trunk/test/clangd/fixits-codeaction.test Tue Oct 16 09:29:41 2018
@@ -0,0 +1,126 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{"textDocument":{"codeAction":{"codeActionLiteralSupport":{}}}},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.c","languageId":"c","version":1,"text":"int main(int i, char **a) { if (i = 2) {}}"}}}
+#      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": 37,
+# CHECK-NEXT:            "line": 0
+# CHECK-NEXT:          },
+# CHECK-NEXT:          "start": {
+# CHECK-NEXT:            "character": 32,
+# CHECK-NEXT:            "line": 0
+# CHECK-NEXT:          }
+# CHECK-NEXT:        },
+# CHECK-NEXT:        "severity": 2
+# CHECK-NEXT:      }
+# CHECK-NEXT:    ],
+# CHECK-NEXT:    "uri": "file://{{.*}}/foo.c"
+# CHECK-NEXT:  }
+---
+{"jsonrpc":"2.0","id":2,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"test:///foo.c"},"range":{"start":{"line":104,"character":13},"end":{"line":0,"character":35}},"context":{"diagnostics":[{"range":{"start": {"line": 0, "character": 32}, "end": {"line": 0, "character": 37}},"severity":2,"message":"Using the result of an assignment as a condition without parentheses"}]}}}
+#      CHECK:  "id": 2,
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": [
+# CHECK-NEXT:    {
+# 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": 37,
+# CHECK-NEXT:              "line": 0
+# CHECK-NEXT:            },
+# CHECK-NEXT:            "start": {
+# CHECK-NEXT:              "character": 32,
+# CHECK-NEXT:              "line": 0
+# CHECK-NEXT:            }
+# CHECK-NEXT:          },
+# CHECK-NEXT:          "severity": 2
+# CHECK-NEXT:        }
+# CHECK-NEXT:      ],
+# 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:      "kind": "quickfix",
+# CHECK-NEXT:      "title": "place parentheses around the assignment to silence this warning"
+# CHECK-NEXT:    },
+# CHECK-NEXT:    {
+# 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": 37,
+# CHECK-NEXT:              "line": 0
+# CHECK-NEXT:            },
+# CHECK-NEXT:            "start": {
+# CHECK-NEXT:              "character": 32,
+# CHECK-NEXT:              "line": 0
+# CHECK-NEXT:            }
+# CHECK-NEXT:          },
+# CHECK-NEXT:          "severity": 2
+# CHECK-NEXT:        }
+# CHECK-NEXT:      ],
+# 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": 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:      "kind": "quickfix",
+# CHECK-NEXT:      "title": "use '==' to turn this assignment into an equality comparison"
+# CHECK-NEXT:    }
+# CHECK-NEXT:  ]
+---
+{"jsonrpc":"2.0","id":4,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
+

Copied: clang-tools-extra/trunk/test/clangd/fixits-command.test (from r344614, clang-tools-extra/trunk/test/clangd/fixits.test)
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/fixits-command.test?p2=clang-tools-extra/trunk/test/clangd/fixits-command.test&p1=clang-tools-extra/trunk/test/clangd/fixits.test&r1=344614&r2=344617&rev=344617&view=diff
==============================================================================
    (empty)

Removed: clang-tools-extra/trunk/test/clangd/fixits.test
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/fixits.test?rev=344616&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clangd/fixits.test (original)
+++ clang-tools-extra/trunk/test/clangd/fixits.test (removed)
@@ -1,210 +0,0 @@
-# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
-{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
----
-{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.c","languageId":"c","version":1,"text":"int main(int i, char **a) { if (i = 2) {}}"}}}
-#      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": 37,
-# CHECK-NEXT:            "line": 0
-# CHECK-NEXT:          },
-# CHECK-NEXT:          "start": {
-# CHECK-NEXT:            "character": 32,
-# CHECK-NEXT:            "line": 0
-# CHECK-NEXT:          }
-# CHECK-NEXT:        },
-# CHECK-NEXT:        "severity": 2
-# CHECK-NEXT:      }
-# CHECK-NEXT:    ],
-# CHECK-NEXT:    "uri": "file://{{.*}}/foo.c"
-# CHECK-NEXT:  }
----
-{"jsonrpc":"2.0","id":2,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"test:///foo.c"},"range":{"start":{"line":104,"character":13},"end":{"line":0,"character":35}},"context":{"diagnostics":[{"range":{"start": {"line": 0, "character": 32}, "end": {"line": 0, "character": 37}},"severity":2,"message":"Using the result of an assignment as a condition without parentheses"}]}}}
-#      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 fix: 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 fix: use '==' to turn this assignment into an equality comparison"
-# CHECK-NEXT:    }
-# CHECK-NEXT:  ]
----
-{"jsonrpc":"2.0","id":3,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"test:///foo.c"},"range":{"start":{"line":104,"character":13},"end":{"line":0,"character":35}},"context":{"diagnostics":[{"range":{"start": {"line": 0, "character": 32}, "end": {"line": 0, "character": 37}},"severity":2,"message":"Using the result of an assignment as a condition without parentheses"}]}}}
-# Make sure unused "code" and "source" fields ignored gracefully
-#      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 fix: 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 fix: use '==' to turn this assignment into an equality comparison"
-# CHECK-NEXT:    }
-# CHECK-NEXT:  ]
----
-{"jsonrpc":"2.0","id":4,"method":"workspace/executeCommand","params":{"command":"clangd.applyFix","arguments":[{"changes":{"test:///foo.c":[{"range":{"start":{"line":0,"character":32},"end":{"line":0,"character":32}},"newText":"("},{"range":{"start":{"line":0,"character":37},"end":{"line":0,"character":37}},"newText":")"}]}}]}}
-#      CHECK:  "id": 4,
-# CHECK-NEXT:  "jsonrpc": "2.0",
-# CHECK-NEXT:  "result": "Fix applied."
-#
-#      CHECK:  "id": 1,
-# CHECK-NEXT:  "jsonrpc": "2.0",
-# CHECK-NEXT:  "method": "workspace/applyEdit",
-# CHECK-NEXT:  "params": {
-# CHECK-NEXT:    "edit": {
-# CHECK-NEXT:      "changes": {
-# CHECK-NEXT:        "{{.*}}/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:  }
----
-{"jsonrpc":"2.0","id":4,"method":"shutdown"}
----
-{"jsonrpc":"2.0","method":"exit"}




More information about the cfe-commits mailing list