mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 11:20:54 +00:00

There are two issues with the implementation of `provideCodeActions` introduced in #1439: 1. We're returning the code action based on the file its diagnostic is in; not the file the suggested fix is in. I'm not sure how often fixes are suggested cross-file but it's something we should handle. 2. We're not filtering code actions based on the passed range. The means if there is any suggestion in a file we'll show an action for every line of the file. I naively thought that VS Code would filter for us but that was wrong. Unfortunately the VS Code `CodeAction` object is very complex - it can handle edits across multiple files, run commands, etc. This makes it complex to check them for equality or see if any of their edits intersects with a specified range. To make it easier to work with suggestions this introduces a `SuggestedFix` model object and a `SuggestFixCollection` code action provider. This is a layer between the raw Rust JSON and VS Code's `CodeAction`s. I was reluctant to introduce another layer of abstraction here but my attempt to work directly with VS Code's model objects was worse.
99 lines
2.7 KiB
TypeScript
99 lines
2.7 KiB
TypeScript
import * as assert from 'assert';
|
|
import * as vscode from 'vscode';
|
|
|
|
import { areDiagnosticsEqual } from '../../../utils/diagnostics/vscode';
|
|
|
|
const range1 = new vscode.Range(
|
|
new vscode.Position(1, 2),
|
|
new vscode.Position(3, 4)
|
|
);
|
|
|
|
const range2 = new vscode.Range(
|
|
new vscode.Position(5, 6),
|
|
new vscode.Position(7, 8)
|
|
);
|
|
|
|
describe('areDiagnosticsEqual', () => {
|
|
it('should treat identical diagnostics as equal', () => {
|
|
const diagnostic1 = new vscode.Diagnostic(
|
|
range1,
|
|
'Hello, world!',
|
|
vscode.DiagnosticSeverity.Error
|
|
);
|
|
|
|
const diagnostic2 = new vscode.Diagnostic(
|
|
range1,
|
|
'Hello, world!',
|
|
vscode.DiagnosticSeverity.Error
|
|
);
|
|
|
|
assert(areDiagnosticsEqual(diagnostic1, diagnostic2));
|
|
});
|
|
|
|
it('should treat diagnostics with different sources as inequal', () => {
|
|
const diagnostic1 = new vscode.Diagnostic(
|
|
range1,
|
|
'Hello, world!',
|
|
vscode.DiagnosticSeverity.Error
|
|
);
|
|
diagnostic1.source = 'rustc';
|
|
|
|
const diagnostic2 = new vscode.Diagnostic(
|
|
range1,
|
|
'Hello, world!',
|
|
vscode.DiagnosticSeverity.Error
|
|
);
|
|
diagnostic2.source = 'clippy';
|
|
|
|
assert(!areDiagnosticsEqual(diagnostic1, diagnostic2));
|
|
});
|
|
|
|
it('should treat diagnostics with different ranges as inequal', () => {
|
|
const diagnostic1 = new vscode.Diagnostic(
|
|
range1,
|
|
'Hello, world!',
|
|
vscode.DiagnosticSeverity.Error
|
|
);
|
|
|
|
const diagnostic2 = new vscode.Diagnostic(
|
|
range2,
|
|
'Hello, world!',
|
|
vscode.DiagnosticSeverity.Error
|
|
);
|
|
|
|
assert(!areDiagnosticsEqual(diagnostic1, diagnostic2));
|
|
});
|
|
|
|
it('should treat diagnostics with different messages as inequal', () => {
|
|
const diagnostic1 = new vscode.Diagnostic(
|
|
range1,
|
|
'Hello, world!',
|
|
vscode.DiagnosticSeverity.Error
|
|
);
|
|
|
|
const diagnostic2 = new vscode.Diagnostic(
|
|
range1,
|
|
'Goodbye!, world!',
|
|
vscode.DiagnosticSeverity.Error
|
|
);
|
|
|
|
assert(!areDiagnosticsEqual(diagnostic1, diagnostic2));
|
|
});
|
|
|
|
it('should treat diagnostics with different severities as inequal', () => {
|
|
const diagnostic1 = new vscode.Diagnostic(
|
|
range1,
|
|
'Hello, world!',
|
|
vscode.DiagnosticSeverity.Warning
|
|
);
|
|
|
|
const diagnostic2 = new vscode.Diagnostic(
|
|
range1,
|
|
'Hello, world!',
|
|
vscode.DiagnosticSeverity.Error
|
|
);
|
|
|
|
assert(!areDiagnosticsEqual(diagnostic1, diagnostic2));
|
|
});
|
|
});
|