1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
import * as assert from 'assert';
import * as vscode from 'vscode';
import SuggestedFix from '../../../utils/diagnostics/SuggestedFix';
import SuggestedFixCollection from '../../../utils/diagnostics/SuggestedFixCollection';
const uri1 = vscode.Uri.file('/file/1');
const uri2 = vscode.Uri.file('/file/2');
const mockDocument1 = ({
uri: uri1,
} as unknown) as vscode.TextDocument;
const mockDocument2 = ({
uri: uri2,
} as unknown) as vscode.TextDocument;
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),
);
const diagnostic1 = new vscode.Diagnostic(range1, 'First diagnostic');
const diagnostic2 = new vscode.Diagnostic(range2, 'Second diagnostic');
// This is a mutable object so return a fresh instance every time
function suggestion1(): SuggestedFix {
return new SuggestedFix(
'Replace me!',
new vscode.Location(uri1, range1),
'With this!',
);
}
describe('SuggestedFixCollection', () => {
it('should add a suggestion then return it as a code action', () => {
const suggestedFixes = new SuggestedFixCollection();
suggestedFixes.addSuggestedFixForDiagnostic(suggestion1(), diagnostic1);
// Specify the document and range that exactly matches
const codeActions = suggestedFixes.provideCodeActions(
mockDocument1,
range1,
);
assert.strictEqual(codeActions.length, 1);
const [codeAction] = codeActions;
assert.strictEqual(codeAction.title, suggestion1().title);
const { diagnostics } = codeAction;
if (!diagnostics) {
return assert.fail('Diagnostics unexpectedly missing');
}
assert.strictEqual(diagnostics.length, 1);
assert.strictEqual(diagnostics[0], diagnostic1);
});
it('should not return code actions for different ranges', () => {
const suggestedFixes = new SuggestedFixCollection();
suggestedFixes.addSuggestedFixForDiagnostic(suggestion1(), diagnostic1);
const codeActions = suggestedFixes.provideCodeActions(
mockDocument1,
range2,
);
assert(!codeActions || codeActions.length === 0);
});
it('should not return code actions for different documents', () => {
const suggestedFixes = new SuggestedFixCollection();
suggestedFixes.addSuggestedFixForDiagnostic(suggestion1(), diagnostic1);
const codeActions = suggestedFixes.provideCodeActions(
mockDocument2,
range1,
);
assert(!codeActions || codeActions.length === 0);
});
it('should not return code actions that have been cleared', () => {
const suggestedFixes = new SuggestedFixCollection();
suggestedFixes.addSuggestedFixForDiagnostic(suggestion1(), diagnostic1);
suggestedFixes.clear();
const codeActions = suggestedFixes.provideCodeActions(
mockDocument1,
range1,
);
assert(!codeActions || codeActions.length === 0);
});
it('should merge identical suggestions together', () => {
const suggestedFixes = new SuggestedFixCollection();
// Add the same suggestion for two diagnostics
suggestedFixes.addSuggestedFixForDiagnostic(suggestion1(), diagnostic1);
suggestedFixes.addSuggestedFixForDiagnostic(suggestion1(), diagnostic2);
const codeActions = suggestedFixes.provideCodeActions(
mockDocument1,
range1,
);
assert.strictEqual(codeActions.length, 1);
const [codeAction] = codeActions;
const { diagnostics } = codeAction;
if (!diagnostics) {
return assert.fail('Diagnostics unexpectedly missing');
}
// We should be associated with both diagnostics
assert.strictEqual(diagnostics.length, 2);
assert.strictEqual(diagnostics[0], diagnostic1);
assert.strictEqual(diagnostics[1], diagnostic2);
});
});
|