[clangd] Support CodeActionParams.only

Differential Revision: https://reviews.llvm.org/D89126
This commit is contained in:
Sam McCall 2020-10-09 15:17:26 +02:00
parent 20a3931f8f
commit 5627ae6c50
4 changed files with 76 additions and 13 deletions

View File

@ -993,12 +993,24 @@ void ClangdLSPServer::onCodeAction(const CodeActionParams &Params,
if (!Code)
return Reply(llvm::make_error<LSPError>(
"onCodeAction called for non-added file", ErrorCode::InvalidParams));
// Checks whether a particular CodeActionKind is included in the response.
auto KindAllowed = [Only(Params.context.only)](llvm::StringRef Kind) {
if (Only.empty())
return true;
return llvm::any_of(Only, [&](llvm::StringRef Base) {
return Kind.consume_front(Base) && (Kind.empty() || Kind.startswith("."));
});
};
// We provide a code action for Fixes on the specified diagnostics.
std::vector<CodeAction> FixIts;
for (const Diagnostic &D : Params.context.diagnostics) {
for (auto &F : getFixes(File.file(), D)) {
FixIts.push_back(toCodeAction(F, Params.textDocument.uri));
FixIts.back().diagnostics = {D};
if (KindAllowed(CodeAction::QUICKFIX_KIND)) {
for (const Diagnostic &D : Params.context.diagnostics) {
for (auto &F : getFixes(File.file(), D)) {
FixIts.push_back(toCodeAction(F, Params.textDocument.uri));
FixIts.back().diagnostics = {D};
}
}
}
@ -1038,14 +1050,10 @@ void ClangdLSPServer::onCodeAction(const CodeActionParams &Params,
}
return Reply(llvm::json::Array(Commands));
};
Server->enumerateTweaks(
File.file(), Params.range,
[&](const Tweak &T) {
if (!Opts.TweakFilter(T))
return false;
// FIXME: also consider CodeActionContext.only
return true;
[this, KindAllowed(std::move(KindAllowed))](const Tweak &T) {
return Opts.TweakFilter(T) && KindAllowed(T.kind());
},
std::move(ConsumeActions));
}

View File

@ -599,7 +599,10 @@ llvm::json::Value toJSON(const PublishDiagnosticsParams &PDP) {
bool fromJSON(const llvm::json::Value &Params, CodeActionContext &R,
llvm::json::Path P) {
llvm::json::ObjectMapper O(Params, P);
return O && O.map("diagnostics", R.diagnostics);
if (!O || !O.map("diagnostics", R.diagnostics))
return false;
O.map("only", R.only);
return true;
}
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Diagnostic &D) {

View File

@ -863,8 +863,19 @@ struct PublishDiagnosticsParams {
llvm::json::Value toJSON(const PublishDiagnosticsParams &);
struct CodeActionContext {
/// An array of diagnostics.
/// An array of diagnostics known on the client side overlapping the range
/// provided to the `textDocument/codeAction` request. They are provided so
/// that the server knows which errors are currently presented to the user for
/// the given range. There is no guarantee that these accurately reflect the
/// error state of the resource. The primary parameter to compute code actions
/// is the provided range.
std::vector<Diagnostic> diagnostics;
/// Requested kind of actions to return.
///
/// Actions not of this kind are filtered out by the client before being
/// shown. So servers can omit computing them.
std::vector<std::string> only;
};
bool fromJSON(const llvm::json::Value &, CodeActionContext &, llvm::json::Path);

View File

@ -51,6 +51,47 @@
# CHECK-NEXT: }
# CHECK-NEXT: ]
---
{
"jsonrpc": "2.0",
"id": 2,
"method": "textDocument/codeAction",
"params": {
"textDocument": { "uri": "test:///main.cpp" },
"range": {
"start": {"line": 0, "character": 0},
"end": {"line": 0, "character": 4}
},
"context": {
"diagnostics": [],
"only": ["quickfix"]
}
}
}
# CHECK: "id": 2,
# CHECK-NEXT: "jsonrpc": "2.0",
# CHECK-NEXT: "result": []
---
{
"jsonrpc": "2.0",
"id": 3,
"method": "textDocument/codeAction",
"params": {
"textDocument": { "uri": "test:///main.cpp" },
"range": {
"start": {"line": 0, "character": 0},
"end": {"line": 0, "character": 4}
},
"context": {
"diagnostics": [],
"only": ["refactor"]
}
}
}
# CHECK: "id": 3,
# CHECK-NEXT: "jsonrpc": "2.0",
# CHECK-NEXT: "result": [
# CHECK-NEXT: {
---
{"jsonrpc":"2.0","id":4,"method":"workspace/executeCommand","params":{"command":"clangd.applyTweak","arguments":[{"file":"test:///main.cpp","selection":{"end":{"character":4,"line":0},"start":{"character":0,"line":0}},"tweakID":"ExpandAutoType"}]}}
# CHECK: "newText": "int",
# CHECK-NEXT: "range": {
@ -64,7 +105,7 @@
# CHECK-NEXT: }
# CHECK-NEXT: }
---
{"jsonrpc":"2.0","id":4,"method":"shutdown"}
{"jsonrpc":"2.0","id":5,"method":"shutdown"}
---
{"jsonrpc":"2.0","method":"exit"}
---