mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-07-07 21:25:37 +00:00
Merge pull request #20104 from Veykril/push-nqnmmlvksyty
Cleanup `provideCodeActions` vscode hook
This commit is contained in:
commit
332434aecd
1 changed files with 59 additions and 55 deletions
|
@ -3,7 +3,7 @@ import * as lc from "vscode-languageclient/node";
|
||||||
import * as vscode from "vscode";
|
import * as vscode from "vscode";
|
||||||
import * as ra from "../src/lsp_ext";
|
import * as ra from "../src/lsp_ext";
|
||||||
import * as Is from "vscode-languageclient/lib/common/utils/is";
|
import * as Is from "vscode-languageclient/lib/common/utils/is";
|
||||||
import { assert, unwrapUndefinable } from "./util";
|
import { assert } from "./util";
|
||||||
import * as diagnostics from "./diagnostics";
|
import * as diagnostics from "./diagnostics";
|
||||||
import { WorkspaceEdit } from "vscode";
|
import { WorkspaceEdit } from "vscode";
|
||||||
import { type Config, prepareVSCodeConfig } from "./config";
|
import { type Config, prepareVSCodeConfig } from "./config";
|
||||||
|
@ -188,11 +188,17 @@ export async function createClient(
|
||||||
context: await client.code2ProtocolConverter.asCodeActionContext(context, token),
|
context: await client.code2ProtocolConverter.asCodeActionContext(context, token),
|
||||||
};
|
};
|
||||||
const callback = async (
|
const callback = async (
|
||||||
values: (lc.Command | lc.CodeAction)[] | null,
|
values: (lc.Command | lc.CodeAction | object)[] | null,
|
||||||
): Promise<(vscode.Command | vscode.CodeAction)[] | undefined> => {
|
): Promise<(vscode.Command | vscode.CodeAction)[] | undefined> => {
|
||||||
if (values === null) return undefined;
|
if (values === null) return undefined;
|
||||||
const result: (vscode.CodeAction | vscode.Command)[] = [];
|
const result: (vscode.CodeAction | vscode.Command)[] = [];
|
||||||
const groups = new Map<string, { index: number; items: vscode.CodeAction[] }>();
|
const groups = new Map<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
primary: vscode.CodeAction;
|
||||||
|
items: { label: string; arguments: lc.CodeAction }[];
|
||||||
|
}
|
||||||
|
>();
|
||||||
for (const item of values) {
|
for (const item of values) {
|
||||||
// In our case we expect to get code edits only from diagnostics
|
// In our case we expect to get code edits only from diagnostics
|
||||||
if (lc.CodeAction.is(item)) {
|
if (lc.CodeAction.is(item)) {
|
||||||
|
@ -204,62 +210,55 @@ export async function createClient(
|
||||||
result.push(action);
|
result.push(action);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
assert(
|
assertIsCodeActionWithoutEditsAndCommands(item);
|
||||||
isCodeActionWithoutEditsAndCommands(item),
|
const kind = client.protocol2CodeConverter.asCodeActionKind(item.kind);
|
||||||
"We don't expect edits or commands here",
|
const group = item.group;
|
||||||
);
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
const kind = client.protocol2CodeConverter.asCodeActionKind((item as any).kind);
|
|
||||||
const action = new vscode.CodeAction(item.title, kind);
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
const group = (item as any).group;
|
|
||||||
action.command = {
|
|
||||||
command: "rust-analyzer.resolveCodeAction",
|
|
||||||
title: item.title,
|
|
||||||
arguments: [item],
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set a dummy edit, so that VS Code doesn't try to resolve this.
|
const mkAction = () => {
|
||||||
action.edit = new WorkspaceEdit();
|
const action = new vscode.CodeAction(item.title, kind);
|
||||||
|
action.command = {
|
||||||
|
command: "rust-analyzer.resolveCodeAction",
|
||||||
|
title: item.title,
|
||||||
|
arguments: [item],
|
||||||
|
};
|
||||||
|
// Set a dummy edit, so that VS Code doesn't try to resolve this.
|
||||||
|
action.edit = new WorkspaceEdit();
|
||||||
|
return action;
|
||||||
|
};
|
||||||
|
|
||||||
if (group) {
|
if (group) {
|
||||||
let entry = groups.get(group);
|
let entry = groups.get(group);
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
entry = { index: result.length, items: [] };
|
entry = { primary: mkAction(), items: [] };
|
||||||
groups.set(group, entry);
|
groups.set(group, entry);
|
||||||
result.push(action);
|
} else {
|
||||||
|
entry.items.push({
|
||||||
|
label: item.title,
|
||||||
|
arguments: item,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
entry.items.push(action);
|
|
||||||
} else {
|
} else {
|
||||||
result.push(action);
|
result.push(mkAction());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const [group, { index, items }] of groups) {
|
for (const [group, { items, primary }] of groups) {
|
||||||
if (items.length === 1) {
|
// This group contains more than one item, so rewrite it to be a group action
|
||||||
const item = unwrapUndefinable(items[0]);
|
if (items.length !== 0) {
|
||||||
result[index] = item;
|
const args = [
|
||||||
} else {
|
{
|
||||||
const action = new vscode.CodeAction(group);
|
label: primary.title,
|
||||||
const item = unwrapUndefinable(items[0]);
|
arguments: primary.command!.arguments![0],
|
||||||
action.kind = item.kind;
|
},
|
||||||
action.command = {
|
...items,
|
||||||
|
];
|
||||||
|
primary.title = group;
|
||||||
|
primary.command = {
|
||||||
command: "rust-analyzer.applyActionGroup",
|
command: "rust-analyzer.applyActionGroup",
|
||||||
title: "",
|
title: "",
|
||||||
arguments: [
|
arguments: [args],
|
||||||
items.map((item) => {
|
|
||||||
return {
|
|
||||||
label: item.title,
|
|
||||||
arguments: item.command!.arguments![0],
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set a dummy edit, so that VS Code doesn't try to resolve this.
|
|
||||||
action.edit = new WorkspaceEdit();
|
|
||||||
|
|
||||||
result[index] = action;
|
|
||||||
}
|
}
|
||||||
|
result.push(primary);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
@ -363,17 +362,22 @@ class OverrideFeatures implements lc.StaticFeature {
|
||||||
clear(): void {}
|
clear(): void {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
function assertIsCodeActionWithoutEditsAndCommands(
|
||||||
function isCodeActionWithoutEditsAndCommands(value: any): boolean {
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const candidate: lc.CodeAction = value;
|
candidate: any,
|
||||||
return (
|
): asserts candidate is lc.CodeAction & {
|
||||||
|
group?: string;
|
||||||
|
} {
|
||||||
|
assert(
|
||||||
candidate &&
|
candidate &&
|
||||||
Is.string(candidate.title) &&
|
Is.string(candidate.title) &&
|
||||||
(candidate.diagnostics === void 0 ||
|
(candidate.diagnostics === undefined ||
|
||||||
Is.typedArray(candidate.diagnostics, lc.Diagnostic.is)) &&
|
Is.typedArray(candidate.diagnostics, lc.Diagnostic.is)) &&
|
||||||
(candidate.kind === void 0 || Is.string(candidate.kind)) &&
|
(candidate.group === undefined || Is.string(candidate.group)) &&
|
||||||
candidate.edit === void 0 &&
|
(candidate.kind === undefined || Is.string(candidate.kind)) &&
|
||||||
candidate.command === void 0
|
candidate.edit === undefined &&
|
||||||
|
candidate.command === undefined,
|
||||||
|
`Expected a CodeAction without edits or commands, got: ${JSON.stringify(candidate)}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue