aboutsummaryrefslogtreecommitdiff
path: root/editors/code/src/test/utils/diagnotics/rust.test.ts
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-06-29 10:50:56 +0100
committerbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-06-29 10:50:56 +0100
commit8865db6768fd913b971df56fc0bcf7439fcb1e71 (patch)
tree3fff3954f7f5ca0c6045f9f7d96c1cd75bd896ee /editors/code/src/test/utils/diagnotics/rust.test.ts
parent64f71dd3fff7b902656a2c2465a1b5071b2b1903 (diff)
parent50c6ab709e38b63fb1e3ee5db40426ef131cbd71 (diff)
Merge #1454
1454: Fix `cargo watch` code action filtering r=etaoins a=etaoins 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. Co-authored-by: Ryan Cumming <[email protected]>
Diffstat (limited to 'editors/code/src/test/utils/diagnotics/rust.test.ts')
-rw-r--r--editors/code/src/test/utils/diagnotics/rust.test.ts173
1 files changed, 173 insertions, 0 deletions
diff --git a/editors/code/src/test/utils/diagnotics/rust.test.ts b/editors/code/src/test/utils/diagnotics/rust.test.ts
new file mode 100644
index 000000000..b555a4819
--- /dev/null
+++ b/editors/code/src/test/utils/diagnotics/rust.test.ts
@@ -0,0 +1,173 @@
1import * as assert from 'assert';
2import * as fs from 'fs';
3import * as vscode from 'vscode';
4
5import {
6 MappedRustDiagnostic,
7 mapRustDiagnosticToVsCode,
8 RustDiagnostic,
9 SuggestionApplicability
10} from '../../../utils/diagnostics/rust';
11
12function loadDiagnosticFixture(name: string): RustDiagnostic {
13 const jsonText = fs
14 .readFileSync(
15 // We're actually in our JavaScript output directory, climb out
16 `${__dirname}/../../../../src/test/fixtures/rust-diagnostics/${name}.json`
17 )
18 .toString();
19
20 return JSON.parse(jsonText);
21}
22
23function mapFixtureToVsCode(name: string): MappedRustDiagnostic {
24 const rd = loadDiagnosticFixture(name);
25 const mapResult = mapRustDiagnosticToVsCode(rd);
26
27 if (!mapResult) {
28 return assert.fail('Mapping unexpectedly failed');
29 }
30 return mapResult;
31}
32
33describe('mapRustDiagnosticToVsCode', () => {
34 it('should map an incompatible type for trait error', () => {
35 const { diagnostic, suggestedFixes } = mapFixtureToVsCode(
36 'error/E0053'
37 );
38
39 assert.strictEqual(
40 diagnostic.severity,
41 vscode.DiagnosticSeverity.Error
42 );
43 assert.strictEqual(diagnostic.source, 'rustc');
44 assert.strictEqual(
45 diagnostic.message,
46 [
47 `method \`next\` has an incompatible type for trait`,
48 `expected type \`fn(&mut ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&ty::Ref<M>>\``,
49 ` found type \`fn(&ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&'list ty::Ref<M>>\``
50 ].join('\n')
51 );
52 assert.strictEqual(diagnostic.code, 'E0053');
53 assert.strictEqual(diagnostic.tags, undefined);
54
55 // No related information
56 assert.deepStrictEqual(diagnostic.relatedInformation, []);
57
58 // There are no suggested fixes
59 assert.strictEqual(suggestedFixes.length, 0);
60 });
61
62 it('should map an unused variable warning', () => {
63 const { diagnostic, suggestedFixes } = mapFixtureToVsCode(
64 'warning/unused_variables'
65 );
66
67 assert.strictEqual(
68 diagnostic.severity,
69 vscode.DiagnosticSeverity.Warning
70 );
71 assert.strictEqual(
72 diagnostic.message,
73 [
74 'unused variable: `foo`',
75 '#[warn(unused_variables)] on by default'
76 ].join('\n')
77 );
78 assert.strictEqual(diagnostic.code, 'unused_variables');
79 assert.strictEqual(diagnostic.source, 'rustc');
80 assert.deepStrictEqual(diagnostic.tags, [
81 vscode.DiagnosticTag.Unnecessary
82 ]);
83
84 // No related information
85 assert.deepStrictEqual(diagnostic.relatedInformation, []);
86
87 // One suggested fix available to prefix the variable
88 assert.strictEqual(suggestedFixes.length, 1);
89 const [suggestedFix] = suggestedFixes;
90 assert.strictEqual(
91 suggestedFix.title,
92 'consider prefixing with an underscore: `_foo`'
93 );
94 assert.strictEqual(
95 suggestedFix.applicability,
96 SuggestionApplicability.MachineApplicable
97 );
98 });
99
100 it('should map a wrong number of parameters error', () => {
101 const { diagnostic, suggestedFixes } = mapFixtureToVsCode(
102 'error/E0061'
103 );
104
105 assert.strictEqual(
106 diagnostic.severity,
107 vscode.DiagnosticSeverity.Error
108 );
109 assert.strictEqual(
110 diagnostic.message,
111 'this function takes 2 parameters but 3 parameters were supplied'
112 );
113 assert.strictEqual(diagnostic.code, 'E0061');
114 assert.strictEqual(diagnostic.source, 'rustc');
115 assert.strictEqual(diagnostic.tags, undefined);
116
117 // One related information for the original definition
118 const relatedInformation = diagnostic.relatedInformation;
119 if (!relatedInformation) {
120 return assert.fail('Related information unexpectedly undefined');
121 }
122 assert.strictEqual(relatedInformation.length, 1);
123 const [related] = relatedInformation;
124 assert.strictEqual(related.message, 'defined here');
125
126 // There are no suggested fixes
127 assert.strictEqual(suggestedFixes.length, 0);
128 });
129
130 it('should map a Clippy copy pass by ref warning', () => {
131 const { diagnostic, suggestedFixes } = mapFixtureToVsCode(
132 'clippy/trivially_copy_pass_by_ref'
133 );
134
135 assert.strictEqual(
136 diagnostic.severity,
137 vscode.DiagnosticSeverity.Warning
138 );
139 assert.strictEqual(diagnostic.source, 'clippy');
140 assert.strictEqual(
141 diagnostic.message,
142 [
143 'this argument is passed by reference, but would be more efficient if passed by value',
144 '#[warn(clippy::trivially_copy_pass_by_ref)] implied by #[warn(clippy::all)]',
145 'for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref'
146 ].join('\n')
147 );
148 assert.strictEqual(diagnostic.code, 'trivially_copy_pass_by_ref');
149 assert.strictEqual(diagnostic.tags, undefined);
150
151 // One related information for the lint definition
152 const relatedInformation = diagnostic.relatedInformation;
153 if (!relatedInformation) {
154 return assert.fail('Related information unexpectedly undefined');
155 }
156 assert.strictEqual(relatedInformation.length, 1);
157 const [related] = relatedInformation;
158 assert.strictEqual(related.message, 'lint level defined here');
159
160 // One suggested fix to pass by value
161 assert.strictEqual(suggestedFixes.length, 1);
162 const [suggestedFix] = suggestedFixes;
163 assert.strictEqual(
164 suggestedFix.title,
165 'consider passing by value instead: `self`'
166 );
167 // Clippy does not mark this with any applicability
168 assert.strictEqual(
169 suggestedFix.applicability,
170 SuggestionApplicability.Unspecified
171 );
172 });
173});