aboutsummaryrefslogtreecommitdiff
path: root/editors/code/src/test/utils/diagnotics/SuggestedFix.test.ts
diff options
context:
space:
mode:
authorRyan Cumming <[email protected]>2019-06-27 12:30:23 +0100
committerRyan Cumming <[email protected]>2019-06-29 08:39:36 +0100
commitabc0784e57610a0cceca63301489918015418df6 (patch)
tree05aec9fef88f31cee82e3507903a1dbcd6b4d30d /editors/code/src/test/utils/diagnotics/SuggestedFix.test.ts
parent0e1912de528b5092c10eedaf94c43c67d5f86f1a (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/test/utils/diagnotics/SuggestedFix.test.ts')
-rw-r--r--editors/code/src/test/utils/diagnotics/SuggestedFix.test.ts133
1 files changed, 133 insertions, 0 deletions
diff --git a/editors/code/src/test/utils/diagnotics/SuggestedFix.test.ts b/editors/code/src/test/utils/diagnotics/SuggestedFix.test.ts
new file mode 100644
index 000000000..6c7f436f3
--- /dev/null
+++ b/editors/code/src/test/utils/diagnotics/SuggestedFix.test.ts
@@ -0,0 +1,133 @@
1import * as assert from 'assert';
2import * as vscode from 'vscode';
3
4import { SuggestionApplicability } from '../../../utils/diagnostics/rust';
5import SuggestedFix from '../../../utils/diagnostics/SuggestedFix';
6
7const location1 = new vscode.Location(
8 vscode.Uri.file('/file/1'),
9 new vscode.Range(new vscode.Position(1, 2), new vscode.Position(3, 4))
10);
11
12const location2 = new vscode.Location(
13 vscode.Uri.file('/file/2'),
14 new vscode.Range(new vscode.Position(5, 6), new vscode.Position(7, 8))
15);
16
17describe('SuggestedFix', () => {
18 describe('isEqual', () => {
19 it('should treat identical instances as equal', () => {
20 const suggestion1 = new SuggestedFix(
21 'Replace me!',
22 location1,
23 'With this!'
24 );
25
26 const suggestion2 = new SuggestedFix(
27 'Replace me!',
28 location1,
29 'With this!'
30 );
31
32 assert(suggestion1.isEqual(suggestion2));
33 });
34
35 it('should treat instances with different titles as inequal', () => {
36 const suggestion1 = new SuggestedFix(
37 'Replace me!',
38 location1,
39 'With this!'
40 );
41
42 const suggestion2 = new SuggestedFix(
43 'Not the same title!',
44 location1,
45 'With this!'
46 );
47
48 assert(!suggestion1.isEqual(suggestion2));
49 });
50
51 it('should treat instances with different replacements as inequal', () => {
52 const suggestion1 = new SuggestedFix(
53 'Replace me!',
54 location1,
55 'With this!'
56 );
57
58 const suggestion2 = new SuggestedFix(
59 'Replace me!',
60 location1,
61 'With something else!'
62 );
63
64 assert(!suggestion1.isEqual(suggestion2));
65 });
66
67 it('should treat instances with different locations as inequal', () => {
68 const suggestion1 = new SuggestedFix(
69 'Replace me!',
70 location1,
71 'With this!'
72 );
73
74 const suggestion2 = new SuggestedFix(
75 'Replace me!',
76 location2,
77 'With this!'
78 );
79
80 assert(!suggestion1.isEqual(suggestion2));
81 });
82
83 it('should treat instances with different applicability as inequal', () => {
84 const suggestion1 = new SuggestedFix(
85 'Replace me!',
86 location1,
87 'With this!',
88 SuggestionApplicability.MachineApplicable
89 );
90
91 const suggestion2 = new SuggestedFix(
92 'Replace me!',
93 location2,
94 'With this!',
95 SuggestionApplicability.HasPlaceholders
96 );
97
98 assert(!suggestion1.isEqual(suggestion2));
99 });
100 });
101
102 describe('toCodeAction', () => {
103 it('should map a simple suggestion', () => {
104 const suggestion = new SuggestedFix(
105 'Replace me!',
106 location1,
107 'With this!'
108 );
109
110 const codeAction = suggestion.toCodeAction();
111 assert.strictEqual(codeAction.kind, vscode.CodeActionKind.QuickFix);
112 assert.strictEqual(codeAction.title, 'Replace me!');
113 assert.strictEqual(codeAction.isPreferred, false);
114
115 const edit = codeAction.edit;
116 if (!edit) {
117 return assert.fail('Code Action edit unexpectedly missing');
118 }
119
120 const editEntries = edit.entries();
121 assert.strictEqual(editEntries.length, 1);
122
123 const [[editUri, textEdits]] = editEntries;
124 assert.strictEqual(editUri.toString(), location1.uri.toString());
125
126 assert.strictEqual(textEdits.length, 1);
127 const [textEdit] = textEdits;
128
129 assert(textEdit.range.isEqual(location1.range));
130 assert.strictEqual(textEdit.newText, 'With this!');
131 });
132 });
133});