diff options
author | Ryan Cumming <[email protected]> | 2019-06-27 12:30:23 +0100 |
---|---|---|
committer | Ryan Cumming <[email protected]> | 2019-06-29 08:39:36 +0100 |
commit | abc0784e57610a0cceca63301489918015418df6 (patch) | |
tree | 05aec9fef88f31cee82e3507903a1dbcd6b4d30d /editors/code/src/utils/diagnostics/SuggestedFix.ts | |
parent | 0e1912de528b5092c10eedaf94c43c67d5f86f1a (diff) |
Fix `cargo watch` code action filtering
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.
Diffstat (limited to 'editors/code/src/utils/diagnostics/SuggestedFix.ts')
-rw-r--r-- | editors/code/src/utils/diagnostics/SuggestedFix.ts | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/editors/code/src/utils/diagnostics/SuggestedFix.ts b/editors/code/src/utils/diagnostics/SuggestedFix.ts new file mode 100644 index 000000000..b1be2a225 --- /dev/null +++ b/editors/code/src/utils/diagnostics/SuggestedFix.ts | |||
@@ -0,0 +1,67 @@ | |||
1 | import * as vscode from 'vscode'; | ||
2 | |||
3 | import { SuggestionApplicability } from './rust'; | ||
4 | |||
5 | /** | ||
6 | * Model object for text replacements suggested by the Rust compiler | ||
7 | * | ||
8 | * This is an intermediate form between the raw `rustc` JSON and a | ||
9 | * `vscode.CodeAction`. It's optimised for the use-cases of | ||
10 | * `SuggestedFixCollection`. | ||
11 | */ | ||
12 | export default class SuggestedFix { | ||
13 | public readonly title: string; | ||
14 | public readonly location: vscode.Location; | ||
15 | public readonly replacement: string; | ||
16 | public readonly applicability: SuggestionApplicability; | ||
17 | |||
18 | /** | ||
19 | * Diagnostics this suggested fix could resolve | ||
20 | */ | ||
21 | public diagnostics: vscode.Diagnostic[]; | ||
22 | |||
23 | constructor( | ||
24 | title: string, | ||
25 | location: vscode.Location, | ||
26 | replacement: string, | ||
27 | applicability: SuggestionApplicability = SuggestionApplicability.Unspecified | ||
28 | ) { | ||
29 | this.title = title; | ||
30 | this.location = location; | ||
31 | this.replacement = replacement; | ||
32 | this.applicability = applicability; | ||
33 | this.diagnostics = []; | ||
34 | } | ||
35 | |||
36 | /** | ||
37 | * Determines if this suggested fix is equivalent to another instance | ||
38 | */ | ||
39 | public isEqual(other: SuggestedFix): boolean { | ||
40 | return ( | ||
41 | this.title === other.title && | ||
42 | this.location.range.isEqual(other.location.range) && | ||
43 | this.replacement === other.replacement && | ||
44 | this.applicability === other.applicability | ||
45 | ); | ||
46 | } | ||
47 | |||
48 | /** | ||
49 | * Converts this suggested fix to a VS Code Quick Fix code action | ||
50 | */ | ||
51 | public toCodeAction(): vscode.CodeAction { | ||
52 | const codeAction = new vscode.CodeAction( | ||
53 | this.title, | ||
54 | vscode.CodeActionKind.QuickFix | ||
55 | ); | ||
56 | |||
57 | const edit = new vscode.WorkspaceEdit(); | ||
58 | edit.replace(this.location.uri, this.location.range, this.replacement); | ||
59 | codeAction.edit = edit; | ||
60 | |||
61 | codeAction.isPreferred = | ||
62 | this.applicability === SuggestionApplicability.MachineApplicable; | ||
63 | |||
64 | codeAction.diagnostics = [...this.diagnostics]; | ||
65 | return codeAction; | ||
66 | } | ||
67 | } | ||