typescript-language-server 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/README.md +128 -21
- package/lib/calls.d.ts +1 -1
- package/lib/calls.d.ts.map +1 -1
- package/lib/calls.js +140 -164
- package/lib/calls.js.map +1 -1
- package/lib/cli.js +1 -1
- package/lib/commands.d.ts +1 -0
- package/lib/commands.d.ts.map +1 -1
- package/lib/commands.js +3 -1
- package/lib/commands.js.map +1 -1
- package/lib/completion.d.ts +4 -7
- package/lib/completion.d.ts.map +1 -1
- package/lib/completion.js +64 -66
- package/lib/completion.js.map +1 -1
- package/lib/configuration-manager.d.ts +47 -0
- package/lib/configuration-manager.d.ts.map +1 -0
- package/lib/configuration-manager.js +105 -0
- package/lib/configuration-manager.js.map +1 -0
- package/lib/diagnostic-queue.d.ts +5 -4
- package/lib/diagnostic-queue.d.ts.map +1 -1
- package/lib/diagnostic-queue.js +7 -8
- package/lib/diagnostic-queue.js.map +1 -1
- package/lib/document-symbol.d.ts.map +1 -1
- package/lib/document-symbol.js +11 -10
- package/lib/document-symbol.js.map +1 -1
- package/lib/features/fix-all.d.ts.map +1 -1
- package/lib/features/fix-all.js +96 -112
- package/lib/features/fix-all.js.map +1 -1
- package/lib/features/inlay-hints.d.ts +11 -0
- package/lib/features/inlay-hints.d.ts.map +1 -0
- package/lib/features/inlay-hints.js +70 -0
- package/lib/features/inlay-hints.js.map +1 -0
- package/lib/features/source-definition.d.ts +11 -0
- package/lib/features/source-definition.d.ts.map +1 -0
- package/lib/features/source-definition.js +50 -0
- package/lib/features/source-definition.js.map +1 -0
- package/lib/file-lsp-server.spec.js +16 -25
- package/lib/file-lsp-server.spec.js.map +1 -1
- package/lib/hover.d.ts +2 -1
- package/lib/hover.d.ts.map +1 -1
- package/lib/hover.js +47 -7
- package/lib/hover.js.map +1 -1
- package/lib/logger.js +1 -1
- package/lib/logger.js.map +1 -1
- package/lib/lsp-client.d.ts +11 -15
- package/lib/lsp-client.d.ts.map +1 -1
- package/lib/lsp-client.js +29 -61
- package/lib/lsp-client.js.map +1 -1
- package/lib/lsp-connection.d.ts.map +1 -1
- package/lib/lsp-connection.js +3 -2
- package/lib/lsp-connection.js.map +1 -1
- package/lib/lsp-protocol.inlayHints.proposed.d.ts +0 -9
- package/lib/lsp-protocol.inlayHints.proposed.d.ts.map +1 -1
- package/lib/lsp-server.d.ts +15 -20
- package/lib/lsp-server.d.ts.map +1 -1
- package/lib/lsp-server.js +806 -901
- package/lib/lsp-server.js.map +1 -1
- package/lib/lsp-server.spec.js +772 -495
- package/lib/lsp-server.spec.js.map +1 -1
- package/lib/organize-imports.spec.js +8 -8
- package/lib/protocol-translation.d.ts +2 -7
- package/lib/protocol-translation.d.ts.map +1 -1
- package/lib/protocol-translation.js +19 -106
- package/lib/protocol-translation.js.map +1 -1
- package/lib/quickfix.js +1 -1
- package/lib/refactor.js +5 -1
- package/lib/refactor.js.map +1 -1
- package/lib/test-utils.d.ts +4 -3
- package/lib/test-utils.d.ts.map +1 -1
- package/lib/test-utils.js +103 -77
- package/lib/test-utils.js.map +1 -1
- package/lib/ts-protocol.d.ts +4 -19
- package/lib/ts-protocol.d.ts.map +1 -1
- package/lib/ts-protocol.js.map +1 -1
- package/lib/tsp-client.d.ts +36 -32
- package/lib/tsp-client.d.ts.map +1 -1
- package/lib/tsp-client.js +9 -7
- package/lib/tsp-client.js.map +1 -1
- package/lib/tsp-client.spec.js +26 -33
- package/lib/tsp-client.spec.js.map +1 -1
- package/lib/tsp-command-types.d.ts +1 -0
- package/lib/tsp-command-types.d.ts.map +1 -1
- package/lib/tsp-command-types.js +1 -1
- package/lib/tsp-command-types.js.map +1 -1
- package/lib/utils/typeConverters.d.ts +19 -1
- package/lib/utils/typeConverters.d.ts.map +1 -1
- package/lib/utils/typeConverters.js +103 -4
- package/lib/utils/typeConverters.js.map +1 -1
- package/lib/utils/versionProvider.js +17 -19
- package/lib/utils/versionProvider.js.map +1 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +2 -0
- package/lib/utils.js.map +1 -1
- package/package.json +10 -7
package/lib/lsp-server.spec.js
CHANGED
|
@@ -4,39 +4,30 @@
|
|
|
4
4
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
|
|
5
5
|
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
6
|
*/
|
|
7
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
8
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
9
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
10
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
11
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
12
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
13
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
14
|
-
});
|
|
15
|
-
};
|
|
16
7
|
import * as chai from 'chai';
|
|
17
8
|
import fs from 'fs-extra';
|
|
18
9
|
import * as lsp from 'vscode-languageserver';
|
|
19
10
|
import * as lspcalls from './lsp-protocol.calls.proposed.js';
|
|
20
|
-
import { uri, createServer, position, lastPosition, filePath,
|
|
11
|
+
import { uri, createServer, position, lastPosition, filePath, positionAfter, readContents, toPlatformEOL } from './test-utils.js';
|
|
21
12
|
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
22
13
|
import { Commands } from './commands.js';
|
|
23
14
|
import { CodeActionKind } from './utils/types.js';
|
|
24
15
|
const assert = chai.assert;
|
|
25
16
|
const diagnostics = new Map();
|
|
26
17
|
let server;
|
|
27
|
-
before(() =>
|
|
28
|
-
server =
|
|
29
|
-
rootUri:
|
|
30
|
-
publishDiagnostics: args => diagnostics.set(args.uri, args)
|
|
18
|
+
before(async () => {
|
|
19
|
+
server = await createServer({
|
|
20
|
+
rootUri: uri(),
|
|
21
|
+
publishDiagnostics: args => diagnostics.set(args.uri, args),
|
|
31
22
|
});
|
|
32
23
|
server.didChangeConfiguration({
|
|
33
24
|
settings: {
|
|
34
25
|
completions: {
|
|
35
|
-
completeFunctionCalls: true
|
|
36
|
-
}
|
|
37
|
-
}
|
|
26
|
+
completeFunctionCalls: true,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
38
29
|
});
|
|
39
|
-
})
|
|
30
|
+
});
|
|
40
31
|
beforeEach(() => {
|
|
41
32
|
server.closeAll();
|
|
42
33
|
// "closeAll" triggers final publishDiagnostics with an empty list so clear last.
|
|
@@ -48,7 +39,7 @@ after(() => {
|
|
|
48
39
|
server.shutdown();
|
|
49
40
|
});
|
|
50
41
|
describe('completion', () => {
|
|
51
|
-
it('simple test', () =>
|
|
42
|
+
it('simple test', async () => {
|
|
52
43
|
const doc = {
|
|
53
44
|
uri: uri('bar.ts'),
|
|
54
45
|
languageId: 'typescript',
|
|
@@ -57,23 +48,23 @@ describe('completion', () => {
|
|
|
57
48
|
export function foo(): void {
|
|
58
49
|
console.log('test')
|
|
59
50
|
}
|
|
60
|
-
|
|
51
|
+
`,
|
|
61
52
|
};
|
|
62
53
|
server.didOpenTextDocument({
|
|
63
|
-
textDocument: doc
|
|
54
|
+
textDocument: doc,
|
|
64
55
|
});
|
|
65
56
|
const pos = position(doc, 'console');
|
|
66
|
-
const proposals =
|
|
57
|
+
const proposals = await server.completion({ textDocument: doc, position: pos });
|
|
67
58
|
assert.isNotNull(proposals);
|
|
68
59
|
assert.isAtLeast(proposals.items.length, 800);
|
|
69
60
|
const item = proposals.items.find(i => i.label === 'addEventListener');
|
|
70
61
|
assert.isDefined(item);
|
|
71
|
-
const resolvedItem =
|
|
62
|
+
const resolvedItem = await server.completionResolve(item);
|
|
72
63
|
assert.isNotTrue(resolvedItem.deprecated, 'resolved item is not deprecated');
|
|
73
64
|
assert.isDefined(resolvedItem.detail);
|
|
74
65
|
server.didCloseTextDocument({ textDocument: doc });
|
|
75
|
-
})
|
|
76
|
-
it('simple JS test', () =>
|
|
66
|
+
});
|
|
67
|
+
it('simple JS test', async () => {
|
|
77
68
|
const doc = {
|
|
78
69
|
uri: uri('bar.js'),
|
|
79
70
|
languageId: 'javascript',
|
|
@@ -82,18 +73,18 @@ describe('completion', () => {
|
|
|
82
73
|
export function foo() {
|
|
83
74
|
console.log('test')
|
|
84
75
|
}
|
|
85
|
-
|
|
76
|
+
`,
|
|
86
77
|
};
|
|
87
78
|
server.didOpenTextDocument({
|
|
88
|
-
textDocument: doc
|
|
79
|
+
textDocument: doc,
|
|
89
80
|
});
|
|
90
81
|
const pos = position(doc, 'console');
|
|
91
|
-
const proposals =
|
|
82
|
+
const proposals = await server.completion({ textDocument: doc, position: pos });
|
|
92
83
|
assert.isNotNull(proposals);
|
|
93
84
|
assert.isAtLeast(proposals.items.length, 800);
|
|
94
85
|
const item = proposals.items.find(i => i.label === 'addEventListener');
|
|
95
86
|
assert.isDefined(item);
|
|
96
|
-
const resolvedItem =
|
|
87
|
+
const resolvedItem = await server.completionResolve(item);
|
|
97
88
|
assert.isDefined(resolvedItem.detail);
|
|
98
89
|
const containsInvalidCompletions = proposals.items.reduce((accumulator, current) => {
|
|
99
90
|
if (accumulator) {
|
|
@@ -105,8 +96,8 @@ describe('completion', () => {
|
|
|
105
96
|
}, false);
|
|
106
97
|
assert.isFalse(containsInvalidCompletions);
|
|
107
98
|
server.didCloseTextDocument({ textDocument: doc });
|
|
108
|
-
})
|
|
109
|
-
it('deprecated by JSDoc', () =>
|
|
99
|
+
});
|
|
100
|
+
it('deprecated by JSDoc', async () => {
|
|
110
101
|
const doc = {
|
|
111
102
|
uri: uri('bar.ts'),
|
|
112
103
|
languageId: 'typescript',
|
|
@@ -121,23 +112,23 @@ describe('completion', () => {
|
|
|
121
112
|
}
|
|
122
113
|
|
|
123
114
|
foo(); // call me
|
|
124
|
-
|
|
115
|
+
`,
|
|
125
116
|
};
|
|
126
117
|
server.didOpenTextDocument({
|
|
127
|
-
textDocument: doc
|
|
118
|
+
textDocument: doc,
|
|
128
119
|
});
|
|
129
120
|
const pos = position(doc, 'foo(); // call me');
|
|
130
|
-
const proposals =
|
|
121
|
+
const proposals = await server.completion({ textDocument: doc, position: pos });
|
|
131
122
|
assert.isNotNull(proposals);
|
|
132
123
|
const item = proposals.items.find(i => i.label === 'foo');
|
|
133
124
|
assert.isDefined(item);
|
|
134
|
-
const resolvedItem =
|
|
125
|
+
const resolvedItem = await server.completionResolve(item);
|
|
135
126
|
assert.isDefined(resolvedItem.detail);
|
|
136
127
|
assert.isArray(resolvedItem.tags);
|
|
137
128
|
assert.include(resolvedItem.tags, lsp.CompletionItemTag.Deprecated, 'resolved item is deprecated');
|
|
138
129
|
server.didCloseTextDocument({ textDocument: doc });
|
|
139
|
-
})
|
|
140
|
-
it('incorrect source location', () =>
|
|
130
|
+
});
|
|
131
|
+
it('incorrect source location', async () => {
|
|
141
132
|
const doc = {
|
|
142
133
|
uri: uri('bar.ts'),
|
|
143
134
|
languageId: 'typescript',
|
|
@@ -146,31 +137,31 @@ describe('completion', () => {
|
|
|
146
137
|
export function foo(): void {
|
|
147
138
|
console.log('test')
|
|
148
139
|
}
|
|
149
|
-
|
|
140
|
+
`,
|
|
150
141
|
};
|
|
151
142
|
server.didOpenTextDocument({
|
|
152
|
-
textDocument: doc
|
|
143
|
+
textDocument: doc,
|
|
153
144
|
});
|
|
154
145
|
const pos = position(doc, 'foo');
|
|
155
|
-
const proposals =
|
|
146
|
+
const proposals = await server.completion({ textDocument: doc, position: pos });
|
|
156
147
|
assert.isNull(proposals);
|
|
157
148
|
server.didCloseTextDocument({ textDocument: doc });
|
|
158
|
-
})
|
|
159
|
-
it('includes completions from global modules', () =>
|
|
149
|
+
});
|
|
150
|
+
it('includes completions from global modules', async () => {
|
|
160
151
|
const doc = {
|
|
161
152
|
uri: uri('bar.ts'),
|
|
162
153
|
languageId: 'typescript',
|
|
163
154
|
version: 1,
|
|
164
|
-
text: 'pathex'
|
|
155
|
+
text: 'pathex',
|
|
165
156
|
};
|
|
166
157
|
server.didOpenTextDocument({ textDocument: doc });
|
|
167
|
-
const proposals =
|
|
158
|
+
const proposals = await server.completion({ textDocument: doc, position: position(doc, 'ex') });
|
|
168
159
|
assert.isNotNull(proposals);
|
|
169
160
|
const pathExistsCompletion = proposals.items.find(completion => completion.label === 'pathExists');
|
|
170
161
|
assert.isDefined(pathExistsCompletion);
|
|
171
162
|
server.didCloseTextDocument({ textDocument: doc });
|
|
172
|
-
})
|
|
173
|
-
it('includes completions with invalid identifier names', () =>
|
|
163
|
+
});
|
|
164
|
+
it('includes completions with invalid identifier names', async () => {
|
|
174
165
|
const doc = {
|
|
175
166
|
uri: uri('bar.ts'),
|
|
176
167
|
languageId: 'typescript',
|
|
@@ -182,117 +173,117 @@ describe('completion', () => {
|
|
|
182
173
|
|
|
183
174
|
const foo: Foo
|
|
184
175
|
foo.i
|
|
185
|
-
|
|
176
|
+
`,
|
|
186
177
|
};
|
|
187
178
|
server.didOpenTextDocument({ textDocument: doc });
|
|
188
|
-
const proposals =
|
|
179
|
+
const proposals = await server.completion({ textDocument: doc, position: positionAfter(doc, '.i') });
|
|
189
180
|
assert.isNotNull(proposals);
|
|
190
181
|
const completion = proposals.items.find(completion => completion.label === 'invalid-identifier-name');
|
|
191
182
|
assert.isDefined(completion);
|
|
192
183
|
assert.isDefined(completion.textEdit);
|
|
193
184
|
assert.equal(completion.textEdit.newText, '["invalid-identifier-name"]');
|
|
194
185
|
server.didCloseTextDocument({ textDocument: doc });
|
|
195
|
-
})
|
|
196
|
-
it('includes detail field with package name for auto-imports', () =>
|
|
186
|
+
});
|
|
187
|
+
it('includes detail field with package name for auto-imports', async () => {
|
|
197
188
|
const doc = {
|
|
198
189
|
uri: uri('bar.ts'),
|
|
199
190
|
languageId: 'typescript',
|
|
200
191
|
version: 1,
|
|
201
|
-
text: 'readFile'
|
|
192
|
+
text: 'readFile',
|
|
202
193
|
};
|
|
203
194
|
server.didOpenTextDocument({ textDocument: doc });
|
|
204
|
-
const proposals =
|
|
195
|
+
const proposals = await server.completion({ textDocument: doc, position: positionAfter(doc, 'readFile') });
|
|
205
196
|
assert.isNotNull(proposals);
|
|
206
197
|
const completion = proposals.items.find(completion => completion.label === 'readFile');
|
|
207
198
|
assert.isDefined(completion);
|
|
208
199
|
assert.strictEqual(completion.detail, 'fs');
|
|
209
200
|
assert.strictEqual(completion.insertTextFormat, /* snippet */ 2);
|
|
210
201
|
server.didCloseTextDocument({ textDocument: doc });
|
|
211
|
-
})
|
|
212
|
-
it('resolves text edit for auto-import completion', () =>
|
|
202
|
+
});
|
|
203
|
+
it('resolves text edit for auto-import completion', async () => {
|
|
213
204
|
const doc = {
|
|
214
205
|
uri: uri('bar.ts'),
|
|
215
206
|
languageId: 'typescript',
|
|
216
207
|
version: 1,
|
|
217
|
-
text: 'readFile'
|
|
208
|
+
text: 'readFile',
|
|
218
209
|
};
|
|
219
210
|
server.didOpenTextDocument({ textDocument: doc });
|
|
220
|
-
const proposals =
|
|
211
|
+
const proposals = await server.completion({ textDocument: doc, position: positionAfter(doc, 'readFile') });
|
|
221
212
|
assert.isNotNull(proposals);
|
|
222
213
|
const completion = proposals.items.find(completion => completion.label === 'readFile');
|
|
223
214
|
assert.isDefined(completion);
|
|
224
|
-
const resolvedItem =
|
|
215
|
+
const resolvedItem = await server.completionResolve(completion);
|
|
225
216
|
assert.deepEqual(resolvedItem.additionalTextEdits, [
|
|
226
217
|
{
|
|
227
218
|
newText: 'import { readFile } from "fs";\n\n',
|
|
228
219
|
range: {
|
|
229
220
|
end: {
|
|
230
221
|
character: 0,
|
|
231
|
-
line: 0
|
|
222
|
+
line: 0,
|
|
232
223
|
},
|
|
233
224
|
start: {
|
|
234
225
|
character: 0,
|
|
235
|
-
line: 0
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
226
|
+
line: 0,
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
},
|
|
239
230
|
]);
|
|
240
231
|
server.didCloseTextDocument({ textDocument: doc });
|
|
241
|
-
})
|
|
242
|
-
it('resolves text edit for auto-import completion in right format', () =>
|
|
232
|
+
});
|
|
233
|
+
it('resolves text edit for auto-import completion in right format', async () => {
|
|
243
234
|
server.didChangeConfiguration({
|
|
244
235
|
settings: {
|
|
245
236
|
typescript: {
|
|
246
237
|
format: {
|
|
247
238
|
semicolons: 'remove',
|
|
248
|
-
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: false
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
239
|
+
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: false,
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
},
|
|
252
243
|
});
|
|
253
244
|
const doc = {
|
|
254
245
|
uri: uri('bar.ts'),
|
|
255
246
|
languageId: 'typescript',
|
|
256
247
|
version: 1,
|
|
257
|
-
text: 'readFile'
|
|
248
|
+
text: 'readFile',
|
|
258
249
|
};
|
|
259
250
|
server.didOpenTextDocument({ textDocument: doc });
|
|
260
|
-
const proposals =
|
|
251
|
+
const proposals = await server.completion({ textDocument: doc, position: positionAfter(doc, 'readFile') });
|
|
261
252
|
assert.isNotNull(proposals);
|
|
262
253
|
const completion = proposals.items.find(completion => completion.label === 'readFile');
|
|
263
254
|
assert.isDefined(completion);
|
|
264
|
-
const resolvedItem =
|
|
255
|
+
const resolvedItem = await server.completionResolve(completion);
|
|
265
256
|
assert.deepEqual(resolvedItem.additionalTextEdits, [
|
|
266
257
|
{
|
|
267
258
|
newText: 'import {readFile} from "fs"\n\n',
|
|
268
259
|
range: {
|
|
269
260
|
end: {
|
|
270
261
|
character: 0,
|
|
271
|
-
line: 0
|
|
262
|
+
line: 0,
|
|
272
263
|
},
|
|
273
264
|
start: {
|
|
274
265
|
character: 0,
|
|
275
|
-
line: 0
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}
|
|
266
|
+
line: 0,
|
|
267
|
+
},
|
|
268
|
+
},
|
|
269
|
+
},
|
|
279
270
|
]);
|
|
280
271
|
server.didCloseTextDocument({ textDocument: doc });
|
|
281
272
|
server.didChangeConfiguration({
|
|
282
273
|
settings: {
|
|
283
274
|
completions: {
|
|
284
|
-
completeFunctionCalls: true
|
|
275
|
+
completeFunctionCalls: true,
|
|
285
276
|
},
|
|
286
277
|
typescript: {
|
|
287
278
|
format: {
|
|
288
279
|
semicolons: 'ignore',
|
|
289
|
-
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
}
|
|
280
|
+
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
},
|
|
293
284
|
});
|
|
294
|
-
})
|
|
295
|
-
it('resolves a snippet for method completion', () =>
|
|
285
|
+
});
|
|
286
|
+
it('resolves a snippet for method completion', async () => {
|
|
296
287
|
const doc = {
|
|
297
288
|
uri: uri('bar.ts'),
|
|
298
289
|
languageId: 'typescript',
|
|
@@ -300,21 +291,21 @@ describe('completion', () => {
|
|
|
300
291
|
text: `
|
|
301
292
|
import fs from 'fs'
|
|
302
293
|
fs.readFile
|
|
303
|
-
|
|
294
|
+
`,
|
|
304
295
|
};
|
|
305
296
|
server.didOpenTextDocument({ textDocument: doc });
|
|
306
|
-
const proposals =
|
|
297
|
+
const proposals = await server.completion({ textDocument: doc, position: positionAfter(doc, 'readFile') });
|
|
307
298
|
assert.isNotNull(proposals);
|
|
308
299
|
const completion = proposals.items.find(completion => completion.label === 'readFile');
|
|
309
300
|
assert.strictEqual(completion.insertTextFormat, lsp.InsertTextFormat.Snippet);
|
|
310
301
|
assert.strictEqual(completion.label, 'readFile');
|
|
311
|
-
const resolvedItem =
|
|
302
|
+
const resolvedItem = await server.completionResolve(completion);
|
|
312
303
|
assert.strictEqual(resolvedItem.insertTextFormat, lsp.InsertTextFormat.Snippet);
|
|
313
304
|
// eslint-disable-next-line no-template-curly-in-string
|
|
314
305
|
assert.strictEqual(resolvedItem.insertText, 'readFile(${1:path}, ${2:options}, ${3:callback})$0');
|
|
315
306
|
server.didCloseTextDocument({ textDocument: doc });
|
|
316
|
-
})
|
|
317
|
-
it('includes textEdit for string completion', () =>
|
|
307
|
+
});
|
|
308
|
+
it('includes textEdit for string completion', async () => {
|
|
318
309
|
const doc = {
|
|
319
310
|
uri: uri('bar.ts'),
|
|
320
311
|
languageId: 'typescript',
|
|
@@ -325,16 +316,16 @@ describe('completion', () => {
|
|
|
325
316
|
}
|
|
326
317
|
|
|
327
318
|
test("fs/")
|
|
328
|
-
|
|
319
|
+
`,
|
|
329
320
|
};
|
|
330
321
|
server.didOpenTextDocument({ textDocument: doc });
|
|
331
|
-
const proposals =
|
|
322
|
+
const proposals = await server.completion({
|
|
332
323
|
textDocument: doc,
|
|
333
324
|
position: positionAfter(doc, 'test("fs/'),
|
|
334
325
|
context: {
|
|
335
326
|
triggerCharacter: '/',
|
|
336
|
-
triggerKind: 2
|
|
337
|
-
}
|
|
327
|
+
triggerKind: 2,
|
|
328
|
+
},
|
|
338
329
|
});
|
|
339
330
|
assert.isNotNull(proposals);
|
|
340
331
|
const completion = proposals.items.find(completion => completion.label === 'fs/read');
|
|
@@ -342,12 +333,12 @@ describe('completion', () => {
|
|
|
342
333
|
assert.deepStrictEqual(completion.textEdit, {
|
|
343
334
|
range: {
|
|
344
335
|
start: { line: 5, character: 20 },
|
|
345
|
-
end: { line: 5, character: 23 }
|
|
336
|
+
end: { line: 5, character: 23 },
|
|
346
337
|
},
|
|
347
|
-
newText: 'fs/read'
|
|
338
|
+
newText: 'fs/read',
|
|
348
339
|
});
|
|
349
|
-
})
|
|
350
|
-
it('includes labelDetails with useLabelDetailsInCompletionEntries enabled', () =>
|
|
340
|
+
});
|
|
341
|
+
it('includes labelDetails with useLabelDetailsInCompletionEntries enabled', async () => {
|
|
351
342
|
const doc = {
|
|
352
343
|
uri: uri('foo.ts'),
|
|
353
344
|
languageId: 'typescript',
|
|
@@ -359,33 +350,142 @@ describe('completion', () => {
|
|
|
359
350
|
const obj: IFoo = {
|
|
360
351
|
/*a*/
|
|
361
352
|
}
|
|
362
|
-
|
|
353
|
+
`,
|
|
363
354
|
};
|
|
364
355
|
server.didOpenTextDocument({ textDocument: doc });
|
|
365
|
-
const proposals =
|
|
356
|
+
const proposals = await server.completion({
|
|
366
357
|
textDocument: doc,
|
|
367
|
-
position: positionAfter(doc, '/*a*/')
|
|
358
|
+
position: positionAfter(doc, '/*a*/'),
|
|
368
359
|
});
|
|
369
360
|
assert.isNotNull(proposals);
|
|
370
361
|
assert.lengthOf(proposals.items, 2);
|
|
371
362
|
assert.deepInclude(proposals.items[0], {
|
|
372
363
|
label: 'bar',
|
|
373
364
|
kind: 2,
|
|
374
|
-
insertTextFormat: 2
|
|
365
|
+
insertTextFormat: 2,
|
|
375
366
|
});
|
|
376
367
|
assert.deepInclude(proposals.items[1], {
|
|
377
368
|
label: 'bar',
|
|
378
369
|
labelDetails: {
|
|
379
|
-
detail: '(x)'
|
|
370
|
+
detail: '(x)',
|
|
380
371
|
},
|
|
381
372
|
kind: 2,
|
|
382
373
|
insertTextFormat: 2,
|
|
383
|
-
insertText: toPlatformEOL('bar(x) {\n $0\n},')
|
|
374
|
+
insertText: toPlatformEOL('bar(x) {\n $0\n},'),
|
|
384
375
|
});
|
|
385
|
-
})
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
describe('definition', () => {
|
|
379
|
+
it('goes to definition', async () => {
|
|
380
|
+
// NOTE: This test needs to reference files that physically exist for the feature to work.
|
|
381
|
+
const indexUri = uri('source-definition', 'index.ts');
|
|
382
|
+
const indexDoc = {
|
|
383
|
+
uri: indexUri,
|
|
384
|
+
languageId: 'typescript',
|
|
385
|
+
version: 1,
|
|
386
|
+
text: readContents(filePath('source-definition', 'index.ts')),
|
|
387
|
+
};
|
|
388
|
+
server.didOpenTextDocument({ textDocument: indexDoc });
|
|
389
|
+
const definitions = await server.definition({
|
|
390
|
+
textDocument: indexDoc,
|
|
391
|
+
position: position(indexDoc, 'a/*identifier*/'),
|
|
392
|
+
});
|
|
393
|
+
assert.isArray(definitions);
|
|
394
|
+
assert.equal(definitions.length, 1);
|
|
395
|
+
assert.deepEqual(definitions[0], {
|
|
396
|
+
uri: uri('source-definition', 'a.d.ts'),
|
|
397
|
+
range: {
|
|
398
|
+
start: {
|
|
399
|
+
line: 0,
|
|
400
|
+
character: 21,
|
|
401
|
+
},
|
|
402
|
+
end: {
|
|
403
|
+
line: 0,
|
|
404
|
+
character: 22,
|
|
405
|
+
},
|
|
406
|
+
},
|
|
407
|
+
});
|
|
408
|
+
});
|
|
409
|
+
});
|
|
410
|
+
describe('definition (definition link supported)', () => {
|
|
411
|
+
let localServer;
|
|
412
|
+
before(async () => {
|
|
413
|
+
const clientCapabilitiesOverride = {
|
|
414
|
+
textDocument: {
|
|
415
|
+
definition: {
|
|
416
|
+
linkSupport: true,
|
|
417
|
+
},
|
|
418
|
+
},
|
|
419
|
+
};
|
|
420
|
+
localServer = await createServer({
|
|
421
|
+
rootUri: uri('source-definition'),
|
|
422
|
+
publishDiagnostics: args => diagnostics.set(args.uri, args),
|
|
423
|
+
clientCapabilitiesOverride,
|
|
424
|
+
});
|
|
425
|
+
});
|
|
426
|
+
beforeEach(() => {
|
|
427
|
+
localServer.closeAll();
|
|
428
|
+
// "closeAll" triggers final publishDiagnostics with an empty list so clear last.
|
|
429
|
+
diagnostics.clear();
|
|
430
|
+
localServer.workspaceEdits = [];
|
|
431
|
+
});
|
|
432
|
+
after(() => {
|
|
433
|
+
localServer.closeAll();
|
|
434
|
+
localServer.shutdown();
|
|
435
|
+
});
|
|
436
|
+
it('goes to definition', async () => {
|
|
437
|
+
// NOTE: This test needs to reference files that physically exist for the feature to work.
|
|
438
|
+
const indexUri = uri('source-definition', 'index.ts');
|
|
439
|
+
const indexDoc = {
|
|
440
|
+
uri: indexUri,
|
|
441
|
+
languageId: 'typescript',
|
|
442
|
+
version: 1,
|
|
443
|
+
text: readContents(filePath('source-definition', 'index.ts')),
|
|
444
|
+
};
|
|
445
|
+
localServer.didOpenTextDocument({ textDocument: indexDoc });
|
|
446
|
+
const definitions = await localServer.definition({
|
|
447
|
+
textDocument: indexDoc,
|
|
448
|
+
position: position(indexDoc, 'a/*identifier*/'),
|
|
449
|
+
});
|
|
450
|
+
assert.isArray(definitions);
|
|
451
|
+
assert.equal(definitions.length, 1);
|
|
452
|
+
assert.deepEqual(definitions[0], {
|
|
453
|
+
originSelectionRange: {
|
|
454
|
+
start: {
|
|
455
|
+
line: 1,
|
|
456
|
+
character: 0,
|
|
457
|
+
},
|
|
458
|
+
end: {
|
|
459
|
+
line: 1,
|
|
460
|
+
character: 1,
|
|
461
|
+
},
|
|
462
|
+
},
|
|
463
|
+
targetRange: {
|
|
464
|
+
start: {
|
|
465
|
+
line: 0,
|
|
466
|
+
character: 0,
|
|
467
|
+
},
|
|
468
|
+
end: {
|
|
469
|
+
line: 0,
|
|
470
|
+
character: 30,
|
|
471
|
+
},
|
|
472
|
+
},
|
|
473
|
+
targetUri: uri('source-definition', 'a.d.ts'),
|
|
474
|
+
targetSelectionRange: {
|
|
475
|
+
start: {
|
|
476
|
+
line: 0,
|
|
477
|
+
character: 21,
|
|
478
|
+
},
|
|
479
|
+
end: {
|
|
480
|
+
line: 0,
|
|
481
|
+
character: 22,
|
|
482
|
+
},
|
|
483
|
+
},
|
|
484
|
+
});
|
|
485
|
+
});
|
|
386
486
|
});
|
|
387
487
|
describe('diagnostics', () => {
|
|
388
|
-
it('simple test', () =>
|
|
488
|
+
it('simple test', async () => {
|
|
389
489
|
const doc = {
|
|
390
490
|
uri: uri('diagnosticsBar.ts'),
|
|
391
491
|
languageId: 'typescript',
|
|
@@ -394,20 +494,20 @@ describe('diagnostics', () => {
|
|
|
394
494
|
export function foo(): void {
|
|
395
495
|
missing('test')
|
|
396
496
|
}
|
|
397
|
-
|
|
497
|
+
`,
|
|
398
498
|
};
|
|
399
499
|
server.didOpenTextDocument({
|
|
400
|
-
textDocument: doc
|
|
500
|
+
textDocument: doc,
|
|
401
501
|
});
|
|
402
|
-
|
|
403
|
-
|
|
502
|
+
await server.requestDiagnostics();
|
|
503
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
404
504
|
const resultsForFile = diagnostics.get(doc.uri);
|
|
405
505
|
assert.isDefined(resultsForFile);
|
|
406
506
|
const fileDiagnostics = resultsForFile.diagnostics;
|
|
407
507
|
assert.equal(fileDiagnostics.length, 1);
|
|
408
508
|
assert.equal("Cannot find name 'missing'.", fileDiagnostics[0].message);
|
|
409
|
-
})
|
|
410
|
-
it('supports diagnostic tags', () =>
|
|
509
|
+
});
|
|
510
|
+
it('supports diagnostic tags', async () => {
|
|
411
511
|
const doc = {
|
|
412
512
|
uri: uri('diagnosticsBar.ts'),
|
|
413
513
|
languageId: 'typescript',
|
|
@@ -418,13 +518,13 @@ describe('diagnostics', () => {
|
|
|
418
518
|
/** @deprecated */
|
|
419
519
|
function foo(): void {}
|
|
420
520
|
foo();
|
|
421
|
-
|
|
521
|
+
`,
|
|
422
522
|
};
|
|
423
523
|
server.didOpenTextDocument({
|
|
424
|
-
textDocument: doc
|
|
524
|
+
textDocument: doc,
|
|
425
525
|
});
|
|
426
|
-
|
|
427
|
-
|
|
526
|
+
await server.requestDiagnostics();
|
|
527
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
428
528
|
const resultsForFile = diagnostics.get(doc.uri);
|
|
429
529
|
assert.isDefined(resultsForFile);
|
|
430
530
|
const fileDiagnostics = resultsForFile.diagnostics;
|
|
@@ -435,8 +535,8 @@ describe('diagnostics', () => {
|
|
|
435
535
|
const deprecatedDiagnostic = fileDiagnostics.find(d => d.code === 6387);
|
|
436
536
|
assert.isDefined(deprecatedDiagnostic);
|
|
437
537
|
assert.deepEqual(deprecatedDiagnostic.tags, [lsp.DiagnosticTag.Deprecated]);
|
|
438
|
-
})
|
|
439
|
-
it('multiple files test', () =>
|
|
538
|
+
});
|
|
539
|
+
it('multiple files test', async () => {
|
|
440
540
|
const doc = {
|
|
441
541
|
uri: uri('multipleFileDiagnosticsBar.ts'),
|
|
442
542
|
languageId: 'typescript',
|
|
@@ -445,7 +545,7 @@ describe('diagnostics', () => {
|
|
|
445
545
|
export function bar(): void {
|
|
446
546
|
missing('test')
|
|
447
547
|
}
|
|
448
|
-
|
|
548
|
+
`,
|
|
449
549
|
};
|
|
450
550
|
const doc2 = {
|
|
451
551
|
uri: uri('multipleFileDiagnosticsFoo.ts'),
|
|
@@ -455,16 +555,16 @@ describe('diagnostics', () => {
|
|
|
455
555
|
export function foo(): void {
|
|
456
556
|
missing('test')
|
|
457
557
|
}
|
|
458
|
-
|
|
558
|
+
`,
|
|
459
559
|
};
|
|
460
560
|
server.didOpenTextDocument({
|
|
461
|
-
textDocument: doc
|
|
561
|
+
textDocument: doc,
|
|
462
562
|
});
|
|
463
563
|
server.didOpenTextDocument({
|
|
464
|
-
textDocument: doc2
|
|
564
|
+
textDocument: doc2,
|
|
465
565
|
});
|
|
466
|
-
|
|
467
|
-
|
|
566
|
+
await server.requestDiagnostics();
|
|
567
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
468
568
|
assert.equal(diagnostics.size, 2);
|
|
469
569
|
const diagnosticsForDoc = diagnostics.get(doc.uri);
|
|
470
570
|
const diagnosticsForDoc2 = diagnostics.get(doc2.uri);
|
|
@@ -472,14 +572,14 @@ describe('diagnostics', () => {
|
|
|
472
572
|
assert.isDefined(diagnosticsForDoc2);
|
|
473
573
|
assert.equal(diagnosticsForDoc.diagnostics.length, 1, JSON.stringify(diagnostics));
|
|
474
574
|
assert.equal(diagnosticsForDoc2.diagnostics.length, 1, JSON.stringify(diagnostics));
|
|
475
|
-
})
|
|
476
|
-
it('code 6133 (ununsed variable) is ignored', () =>
|
|
575
|
+
});
|
|
576
|
+
it('code 6133 (ununsed variable) is ignored', async () => {
|
|
477
577
|
server.didChangeConfiguration({
|
|
478
578
|
settings: {
|
|
479
579
|
diagnostics: {
|
|
480
|
-
ignoredCodes: [6133]
|
|
481
|
-
}
|
|
482
|
-
}
|
|
580
|
+
ignoredCodes: [6133],
|
|
581
|
+
},
|
|
582
|
+
},
|
|
483
583
|
});
|
|
484
584
|
const doc = {
|
|
485
585
|
uri: uri('diagnosticsBar2.ts'),
|
|
@@ -490,21 +590,21 @@ describe('diagnostics', () => {
|
|
|
490
590
|
const x = 42;
|
|
491
591
|
return 1;
|
|
492
592
|
}
|
|
493
|
-
|
|
593
|
+
`,
|
|
494
594
|
};
|
|
495
595
|
server.didOpenTextDocument({
|
|
496
|
-
textDocument: doc
|
|
596
|
+
textDocument: doc,
|
|
497
597
|
});
|
|
498
|
-
|
|
499
|
-
|
|
598
|
+
await server.requestDiagnostics();
|
|
599
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
500
600
|
const diagnosticsForThisFile = diagnostics.get(doc.uri);
|
|
501
601
|
assert.isDefined(diagnosticsForThisFile);
|
|
502
602
|
const fileDiagnostics = diagnosticsForThisFile.diagnostics;
|
|
503
603
|
assert.equal(fileDiagnostics.length, 0, JSON.stringify(fileDiagnostics));
|
|
504
|
-
})
|
|
604
|
+
});
|
|
505
605
|
});
|
|
506
606
|
describe('document symbol', () => {
|
|
507
|
-
it('simple test', () =>
|
|
607
|
+
it('simple test', async () => {
|
|
508
608
|
const doc = {
|
|
509
609
|
uri: uri('bar.ts'),
|
|
510
610
|
languageId: 'typescript',
|
|
@@ -515,22 +615,19 @@ describe('document symbol', () => {
|
|
|
515
615
|
public myFunction(arg: string) {
|
|
516
616
|
}
|
|
517
617
|
}
|
|
518
|
-
|
|
618
|
+
`,
|
|
519
619
|
};
|
|
520
620
|
server.didOpenTextDocument({
|
|
521
|
-
textDocument: doc
|
|
522
|
-
});
|
|
523
|
-
const symbols = yield server.documentSymbol({
|
|
524
621
|
textDocument: doc,
|
|
525
|
-
position: lsp.Position.create(1, 1)
|
|
526
622
|
});
|
|
623
|
+
const symbols = await server.documentSymbol({ textDocument: doc });
|
|
527
624
|
assert.equal(`
|
|
528
625
|
Foo
|
|
529
626
|
foo
|
|
530
627
|
myFunction
|
|
531
628
|
`, symbolsAsString(symbols) + '\n');
|
|
532
|
-
})
|
|
533
|
-
it('merges interfaces correctly', () =>
|
|
629
|
+
});
|
|
630
|
+
it('merges interfaces correctly', async () => {
|
|
534
631
|
const doc = {
|
|
535
632
|
uri: uri('bar.ts'),
|
|
536
633
|
languageId: 'typescript',
|
|
@@ -543,15 +640,12 @@ interface Box {
|
|
|
543
640
|
|
|
544
641
|
interface Box {
|
|
545
642
|
scale: number;
|
|
546
|
-
}
|
|
643
|
+
}`,
|
|
547
644
|
};
|
|
548
645
|
server.didOpenTextDocument({
|
|
549
|
-
textDocument: doc
|
|
550
|
-
});
|
|
551
|
-
const symbols = yield server.documentSymbol({
|
|
552
646
|
textDocument: doc,
|
|
553
|
-
position: lsp.Position.create(1, 1)
|
|
554
647
|
});
|
|
648
|
+
const symbols = await server.documentSymbol({ textDocument: doc });
|
|
555
649
|
assert.equal(`
|
|
556
650
|
Box
|
|
557
651
|
height
|
|
@@ -559,8 +653,8 @@ Box
|
|
|
559
653
|
Box
|
|
560
654
|
scale
|
|
561
655
|
`, symbolsAsString(symbols) + '\n');
|
|
562
|
-
})
|
|
563
|
-
it('duplication test', () =>
|
|
656
|
+
});
|
|
657
|
+
it('duplication test', async () => {
|
|
564
658
|
const doc = {
|
|
565
659
|
uri: uri('bar.ts'),
|
|
566
660
|
languageId: 'typescript',
|
|
@@ -576,15 +670,12 @@ Box
|
|
|
576
670
|
public myFunction(arg: string) {
|
|
577
671
|
}
|
|
578
672
|
}
|
|
579
|
-
|
|
673
|
+
`,
|
|
580
674
|
};
|
|
581
675
|
server.didOpenTextDocument({
|
|
582
|
-
textDocument: doc
|
|
583
|
-
});
|
|
584
|
-
const symbols = yield server.documentSymbol({
|
|
585
676
|
textDocument: doc,
|
|
586
|
-
position: lsp.Position.create(1, 1)
|
|
587
677
|
});
|
|
678
|
+
const symbols = await server.documentSymbol({ textDocument: doc });
|
|
588
679
|
const expectation = `
|
|
589
680
|
Foo
|
|
590
681
|
foo
|
|
@@ -598,7 +689,7 @@ Foo
|
|
|
598
689
|
assert.deepEqual(symbols[0].range, { start: { line: 1, character: 8 }, end: { line: 5, character: 9 } });
|
|
599
690
|
assert.deepEqual(symbols[1].selectionRange, symbols[1].range);
|
|
600
691
|
assert.deepEqual(symbols[1].range, { start: { line: 6, character: 8 }, end: { line: 10, character: 9 } });
|
|
601
|
-
})
|
|
692
|
+
});
|
|
602
693
|
});
|
|
603
694
|
function symbolsAsString(symbols, indentation = '') {
|
|
604
695
|
return symbols.map(symbol => {
|
|
@@ -617,7 +708,7 @@ function symbolsAsString(symbols, indentation = '') {
|
|
|
617
708
|
}).join('');
|
|
618
709
|
}
|
|
619
710
|
describe('editing', () => {
|
|
620
|
-
it('open and change', () =>
|
|
711
|
+
it('open and change', async () => {
|
|
621
712
|
const doc = {
|
|
622
713
|
uri: uri('openAndChangeBar.ts'),
|
|
623
714
|
languageId: 'typescript',
|
|
@@ -625,10 +716,10 @@ describe('editing', () => {
|
|
|
625
716
|
text: `
|
|
626
717
|
export function foo(): void {
|
|
627
718
|
}
|
|
628
|
-
|
|
719
|
+
`,
|
|
629
720
|
};
|
|
630
721
|
server.didOpenTextDocument({
|
|
631
|
-
textDocument: doc
|
|
722
|
+
textDocument: doc,
|
|
632
723
|
});
|
|
633
724
|
server.didChangeTextDocument({
|
|
634
725
|
textDocument: doc,
|
|
@@ -638,21 +729,21 @@ describe('editing', () => {
|
|
|
638
729
|
export function foo(): void {
|
|
639
730
|
missing('test');
|
|
640
731
|
}
|
|
641
|
-
|
|
642
|
-
}
|
|
643
|
-
]
|
|
732
|
+
`,
|
|
733
|
+
},
|
|
734
|
+
],
|
|
644
735
|
});
|
|
645
|
-
|
|
646
|
-
|
|
736
|
+
await server.requestDiagnostics();
|
|
737
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
647
738
|
const resultsForFile = diagnostics.get(doc.uri);
|
|
648
739
|
assert.isDefined(resultsForFile);
|
|
649
740
|
const fileDiagnostics = resultsForFile.diagnostics;
|
|
650
741
|
assert.isTrue(fileDiagnostics.length >= 1, fileDiagnostics.map(d => d.message).join(','));
|
|
651
742
|
assert.equal("Cannot find name 'missing'.", fileDiagnostics[0].message);
|
|
652
|
-
})
|
|
743
|
+
});
|
|
653
744
|
});
|
|
654
745
|
describe('references', () => {
|
|
655
|
-
it('respects "includeDeclaration" in the request', () =>
|
|
746
|
+
it('respects "includeDeclaration" in the request', async () => {
|
|
656
747
|
const doc = {
|
|
657
748
|
uri: uri('foo.ts'),
|
|
658
749
|
languageId: 'typescript',
|
|
@@ -660,119 +751,119 @@ describe('references', () => {
|
|
|
660
751
|
text: `
|
|
661
752
|
function foo() {};
|
|
662
753
|
foo();
|
|
663
|
-
|
|
754
|
+
`,
|
|
664
755
|
};
|
|
665
756
|
server.didOpenTextDocument({
|
|
666
|
-
textDocument: doc
|
|
757
|
+
textDocument: doc,
|
|
667
758
|
});
|
|
668
759
|
// Without declaration/definition.
|
|
669
760
|
const position = lastPosition(doc, 'function foo()');
|
|
670
|
-
let references =
|
|
761
|
+
let references = await server.references({
|
|
671
762
|
context: { includeDeclaration: false },
|
|
672
763
|
textDocument: doc,
|
|
673
|
-
position
|
|
764
|
+
position,
|
|
674
765
|
});
|
|
675
766
|
assert.strictEqual(references.length, 1);
|
|
676
767
|
assert.strictEqual(references[0].range.start.line, 2);
|
|
677
768
|
// With declaration/definition.
|
|
678
|
-
references =
|
|
769
|
+
references = await server.references({
|
|
679
770
|
context: { includeDeclaration: true },
|
|
680
771
|
textDocument: doc,
|
|
681
|
-
position
|
|
772
|
+
position,
|
|
682
773
|
});
|
|
683
774
|
assert.strictEqual(references.length, 2);
|
|
684
|
-
})
|
|
685
|
-
});
|
|
686
|
-
describe('workspace configuration', () => {
|
|
687
|
-
it('receives workspace configuration notification', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
688
|
-
const doc = {
|
|
689
|
-
uri: uri('bar.ts'),
|
|
690
|
-
languageId: 'typescript',
|
|
691
|
-
version: 1,
|
|
692
|
-
text: `
|
|
693
|
-
export function foo(): void {
|
|
694
|
-
console.log('test')
|
|
695
|
-
}
|
|
696
|
-
`
|
|
697
|
-
};
|
|
698
|
-
server.didOpenTextDocument({
|
|
699
|
-
textDocument: doc
|
|
700
|
-
});
|
|
701
|
-
server.didChangeConfiguration({
|
|
702
|
-
settings: {
|
|
703
|
-
typescript: {
|
|
704
|
-
format: {
|
|
705
|
-
insertSpaceAfterCommaDelimiter: true
|
|
706
|
-
}
|
|
707
|
-
},
|
|
708
|
-
javascript: {
|
|
709
|
-
format: {
|
|
710
|
-
insertSpaceAfterCommaDelimiter: false
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
});
|
|
715
|
-
const file = filePath('bar.ts');
|
|
716
|
-
const settings = server.getWorkspacePreferencesForDocument(file);
|
|
717
|
-
assert.deepEqual(settings, { format: { insertSpaceAfterCommaDelimiter: true } });
|
|
718
|
-
}));
|
|
775
|
+
});
|
|
719
776
|
});
|
|
777
|
+
// describe('workspace configuration', () => {
|
|
778
|
+
// it('receives workspace configuration notification', async ()=>{
|
|
779
|
+
// const doc = {
|
|
780
|
+
// uri: uri('bar.ts'),
|
|
781
|
+
// languageId: 'typescript',
|
|
782
|
+
// version: 1,
|
|
783
|
+
// text: `
|
|
784
|
+
// export function foo(): void {
|
|
785
|
+
// console.log('test')
|
|
786
|
+
// }
|
|
787
|
+
// `
|
|
788
|
+
// };
|
|
789
|
+
// server.didOpenTextDocument({
|
|
790
|
+
// textDocument: doc
|
|
791
|
+
// });
|
|
792
|
+
// server.didChangeConfiguration({
|
|
793
|
+
// settings: {
|
|
794
|
+
// typescript: {
|
|
795
|
+
// format: {
|
|
796
|
+
// insertSpaceAfterCommaDelimiter: true
|
|
797
|
+
// }
|
|
798
|
+
// },
|
|
799
|
+
// javascript: {
|
|
800
|
+
// format: {
|
|
801
|
+
// insertSpaceAfterCommaDelimiter: false
|
|
802
|
+
// }
|
|
803
|
+
// }
|
|
804
|
+
// }
|
|
805
|
+
// });
|
|
806
|
+
// const file = filePath('bar.ts');
|
|
807
|
+
// const settings = server.getWorkspacePreferencesForDocument(file);
|
|
808
|
+
// assert.deepEqual(settings, { format: { insertSpaceAfterCommaDelimiter: true } });
|
|
809
|
+
// });
|
|
810
|
+
// });
|
|
720
811
|
describe('formatting', () => {
|
|
721
812
|
const uriString = uri('bar.ts');
|
|
722
813
|
const languageId = 'typescript';
|
|
723
814
|
const version = 1;
|
|
724
|
-
it('full document formatting', () =>
|
|
815
|
+
it('full document formatting', async () => {
|
|
725
816
|
const text = 'export function foo ( ) : void { }';
|
|
726
817
|
const textDocument = {
|
|
727
|
-
uri: uriString, languageId, version, text
|
|
818
|
+
uri: uriString, languageId, version, text,
|
|
728
819
|
};
|
|
729
820
|
server.didOpenTextDocument({ textDocument });
|
|
730
|
-
const edits =
|
|
821
|
+
const edits = await server.documentFormatting({
|
|
731
822
|
textDocument,
|
|
732
823
|
options: {
|
|
733
824
|
tabSize: 4,
|
|
734
|
-
insertSpaces: true
|
|
735
|
-
}
|
|
825
|
+
insertSpaces: true,
|
|
826
|
+
},
|
|
736
827
|
});
|
|
737
828
|
const result = TextDocument.applyEdits(TextDocument.create(uriString, languageId, version, text), edits);
|
|
738
829
|
assert.equal('export function foo(): void { }', result);
|
|
739
|
-
})
|
|
740
|
-
it('indent settings (3 spaces)', () =>
|
|
830
|
+
});
|
|
831
|
+
it('indent settings (3 spaces)', async () => {
|
|
741
832
|
const text = 'function foo() {\n// some code\n}';
|
|
742
833
|
const textDocument = {
|
|
743
|
-
uri: uriString, languageId, version, text
|
|
834
|
+
uri: uriString, languageId, version, text,
|
|
744
835
|
};
|
|
745
836
|
server.didOpenTextDocument({ textDocument });
|
|
746
|
-
const edits =
|
|
837
|
+
const edits = await server.documentFormatting({
|
|
747
838
|
textDocument,
|
|
748
839
|
options: {
|
|
749
840
|
tabSize: 3,
|
|
750
|
-
insertSpaces: true
|
|
751
|
-
}
|
|
841
|
+
insertSpaces: true,
|
|
842
|
+
},
|
|
752
843
|
});
|
|
753
844
|
const result = TextDocument.applyEdits(TextDocument.create(uriString, languageId, version, text), edits);
|
|
754
845
|
assert.equal('function foo() {\n // some code\n}', result);
|
|
755
|
-
})
|
|
756
|
-
it('indent settings (tabs)', () =>
|
|
846
|
+
});
|
|
847
|
+
it('indent settings (tabs)', async () => {
|
|
757
848
|
const text = 'function foo() {\n// some code\n}';
|
|
758
849
|
const textDocument = {
|
|
759
|
-
uri: uriString, languageId, version, text
|
|
850
|
+
uri: uriString, languageId, version, text,
|
|
760
851
|
};
|
|
761
852
|
server.didOpenTextDocument({ textDocument });
|
|
762
|
-
const edits =
|
|
853
|
+
const edits = await server.documentFormatting({
|
|
763
854
|
textDocument,
|
|
764
855
|
options: {
|
|
765
856
|
tabSize: 4,
|
|
766
|
-
insertSpaces: false
|
|
767
|
-
}
|
|
857
|
+
insertSpaces: false,
|
|
858
|
+
},
|
|
768
859
|
});
|
|
769
860
|
const result = TextDocument.applyEdits(TextDocument.create(uriString, languageId, version, text), edits);
|
|
770
861
|
assert.equal('function foo() {\n\t// some code\n}', result);
|
|
771
|
-
})
|
|
772
|
-
it('formatting setting set through workspace configuration', () =>
|
|
862
|
+
});
|
|
863
|
+
it('formatting setting set through workspace configuration', async () => {
|
|
773
864
|
const text = 'function foo() {\n// some code\n}';
|
|
774
865
|
const textDocument = {
|
|
775
|
-
uri: uriString, languageId, version, text
|
|
866
|
+
uri: uriString, languageId, version, text,
|
|
776
867
|
};
|
|
777
868
|
server.didOpenTextDocument({ textDocument });
|
|
778
869
|
server.didChangeConfiguration({
|
|
@@ -780,73 +871,110 @@ describe('formatting', () => {
|
|
|
780
871
|
typescript: {
|
|
781
872
|
format: {
|
|
782
873
|
newLineCharacter: '\n',
|
|
783
|
-
placeOpenBraceOnNewLineForFunctions: true
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
}
|
|
874
|
+
placeOpenBraceOnNewLineForFunctions: true,
|
|
875
|
+
},
|
|
876
|
+
},
|
|
877
|
+
},
|
|
787
878
|
});
|
|
788
|
-
const edits =
|
|
879
|
+
const edits = await server.documentFormatting({
|
|
789
880
|
textDocument,
|
|
790
881
|
options: {
|
|
791
882
|
tabSize: 4,
|
|
792
|
-
insertSpaces: false
|
|
793
|
-
}
|
|
883
|
+
insertSpaces: false,
|
|
884
|
+
},
|
|
794
885
|
});
|
|
795
886
|
const result = TextDocument.applyEdits(TextDocument.create(uriString, languageId, version, text), edits);
|
|
796
887
|
assert.equal('function foo()\n{\n\t// some code\n}', result);
|
|
797
|
-
})
|
|
798
|
-
it('selected range', () =>
|
|
888
|
+
});
|
|
889
|
+
it('selected range', async () => {
|
|
799
890
|
const text = 'function foo() {\nconst first = 1;\nconst second = 2;\nconst val = foo( "something" );\n//const fourth = 4;\n}';
|
|
800
891
|
const textDocument = {
|
|
801
|
-
uri: uriString, languageId, version, text
|
|
892
|
+
uri: uriString, languageId, version, text,
|
|
802
893
|
};
|
|
803
894
|
server.didOpenTextDocument({ textDocument });
|
|
804
|
-
const edits =
|
|
895
|
+
const edits = await server.documentRangeFormatting({
|
|
805
896
|
textDocument,
|
|
806
897
|
range: {
|
|
807
898
|
start: {
|
|
808
899
|
line: 2,
|
|
809
|
-
character: 0
|
|
900
|
+
character: 0,
|
|
810
901
|
},
|
|
811
902
|
end: {
|
|
812
903
|
line: 3,
|
|
813
|
-
character: 30
|
|
814
|
-
}
|
|
904
|
+
character: 30,
|
|
905
|
+
},
|
|
815
906
|
},
|
|
816
907
|
options: {
|
|
817
908
|
tabSize: 4,
|
|
818
|
-
insertSpaces: true
|
|
819
|
-
}
|
|
909
|
+
insertSpaces: true,
|
|
910
|
+
},
|
|
820
911
|
});
|
|
821
912
|
const result = TextDocument.applyEdits(TextDocument.create(uriString, languageId, version, text), edits);
|
|
822
913
|
assert.equal('function foo() {\nconst first = 1;\n const second = 2;\n const val = foo("something");\n//const fourth = 4;\n}', result);
|
|
823
|
-
})
|
|
914
|
+
});
|
|
824
915
|
});
|
|
825
916
|
describe('signatureHelp', () => {
|
|
826
|
-
it('simple test', () =>
|
|
917
|
+
it('simple test', async () => {
|
|
827
918
|
const doc = {
|
|
828
919
|
uri: uri('bar.ts'),
|
|
829
920
|
languageId: 'typescript',
|
|
830
921
|
version: 1,
|
|
831
922
|
text: `
|
|
832
923
|
export function foo(bar: string, baz?:boolean): void {}
|
|
924
|
+
export function foo(n: number, baz?: boolean): void
|
|
833
925
|
foo(param1, param2)
|
|
834
|
-
|
|
926
|
+
`,
|
|
835
927
|
};
|
|
836
928
|
server.didOpenTextDocument({
|
|
837
|
-
textDocument: doc
|
|
929
|
+
textDocument: doc,
|
|
838
930
|
});
|
|
839
|
-
let result = (
|
|
931
|
+
let result = (await server.signatureHelp({
|
|
840
932
|
textDocument: doc,
|
|
841
|
-
position: position(doc, 'param1')
|
|
933
|
+
position: position(doc, 'param1'),
|
|
842
934
|
}));
|
|
935
|
+
assert.equal(result.signatures.length, 2);
|
|
843
936
|
assert.equal('bar: string', result.signatures[result.activeSignature].parameters[result.activeParameter].label);
|
|
844
|
-
result = (
|
|
937
|
+
result = (await server.signatureHelp({
|
|
845
938
|
textDocument: doc,
|
|
846
|
-
position: position(doc, 'param2')
|
|
939
|
+
position: position(doc, 'param2'),
|
|
847
940
|
}));
|
|
848
941
|
assert.equal('baz?: boolean', result.signatures[result.activeSignature].parameters[result.activeParameter].label);
|
|
849
|
-
})
|
|
942
|
+
});
|
|
943
|
+
it('retrigger with specific signature active', async () => {
|
|
944
|
+
const doc = {
|
|
945
|
+
uri: uri('bar.ts'),
|
|
946
|
+
languageId: 'typescript',
|
|
947
|
+
version: 1,
|
|
948
|
+
text: `
|
|
949
|
+
export function foo(bar: string, baz?: boolean): void {}
|
|
950
|
+
export function foo(n: number, baz?: boolean): void
|
|
951
|
+
foo(param1, param2)
|
|
952
|
+
`,
|
|
953
|
+
};
|
|
954
|
+
server.didOpenTextDocument({ textDocument: doc });
|
|
955
|
+
let result = await server.signatureHelp({
|
|
956
|
+
textDocument: doc,
|
|
957
|
+
position: position(doc, 'param1'),
|
|
958
|
+
});
|
|
959
|
+
assert.equal(result.signatures.length, 2);
|
|
960
|
+
result = (await server.signatureHelp({
|
|
961
|
+
textDocument: doc,
|
|
962
|
+
position: position(doc, 'param1'),
|
|
963
|
+
context: {
|
|
964
|
+
isRetrigger: true,
|
|
965
|
+
triggerKind: lsp.SignatureHelpTriggerKind.Invoked,
|
|
966
|
+
activeSignatureHelp: {
|
|
967
|
+
signatures: result.signatures,
|
|
968
|
+
activeSignature: 1, // select second signature
|
|
969
|
+
},
|
|
970
|
+
},
|
|
971
|
+
}));
|
|
972
|
+
const { activeSignature, signatures } = result;
|
|
973
|
+
assert.equal(activeSignature, 1);
|
|
974
|
+
assert.deepInclude(signatures[activeSignature], {
|
|
975
|
+
label: 'foo(n: number, baz?: boolean): void',
|
|
976
|
+
});
|
|
977
|
+
});
|
|
850
978
|
});
|
|
851
979
|
describe('code actions', () => {
|
|
852
980
|
const doc = {
|
|
@@ -856,28 +984,28 @@ describe('code actions', () => {
|
|
|
856
984
|
text: `import { something } from "something";
|
|
857
985
|
export function foo(bar: string, baz?:boolean): void {}
|
|
858
986
|
foo(param1, param2)
|
|
859
|
-
|
|
987
|
+
`,
|
|
860
988
|
};
|
|
861
|
-
it('can provide quickfix code actions', () =>
|
|
989
|
+
it('can provide quickfix code actions', async () => {
|
|
862
990
|
server.didOpenTextDocument({
|
|
863
|
-
textDocument: doc
|
|
991
|
+
textDocument: doc,
|
|
864
992
|
});
|
|
865
|
-
const result = (
|
|
993
|
+
const result = (await server.codeAction({
|
|
866
994
|
textDocument: doc,
|
|
867
995
|
range: {
|
|
868
996
|
start: { line: 1, character: 25 },
|
|
869
|
-
end: { line: 1, character: 49 }
|
|
997
|
+
end: { line: 1, character: 49 },
|
|
870
998
|
},
|
|
871
999
|
context: {
|
|
872
1000
|
diagnostics: [{
|
|
873
1001
|
range: {
|
|
874
1002
|
start: { line: 1, character: 25 },
|
|
875
|
-
end: { line: 1, character: 49 }
|
|
1003
|
+
end: { line: 1, character: 49 },
|
|
876
1004
|
},
|
|
877
1005
|
code: 6133,
|
|
878
|
-
message: 'unused arg'
|
|
879
|
-
}]
|
|
880
|
-
}
|
|
1006
|
+
message: 'unused arg',
|
|
1007
|
+
}],
|
|
1008
|
+
},
|
|
881
1009
|
}));
|
|
882
1010
|
assert.strictEqual(result.length, 2);
|
|
883
1011
|
const quickFixDiagnostic = result.find(diagnostic => diagnostic.kind === 'quickfix');
|
|
@@ -893,29 +1021,29 @@ describe('code actions', () => {
|
|
|
893
1021
|
{
|
|
894
1022
|
textDocument: {
|
|
895
1023
|
uri: uri('bar.ts'),
|
|
896
|
-
version: 1
|
|
1024
|
+
version: 1,
|
|
897
1025
|
},
|
|
898
1026
|
edits: [
|
|
899
1027
|
{
|
|
900
1028
|
range: {
|
|
901
1029
|
start: {
|
|
902
1030
|
line: 1,
|
|
903
|
-
character: 24
|
|
1031
|
+
character: 24,
|
|
904
1032
|
},
|
|
905
1033
|
end: {
|
|
906
1034
|
line: 1,
|
|
907
|
-
character: 27
|
|
908
|
-
}
|
|
1035
|
+
character: 27,
|
|
1036
|
+
},
|
|
909
1037
|
},
|
|
910
|
-
newText: '_bar'
|
|
911
|
-
}
|
|
912
|
-
]
|
|
913
|
-
}
|
|
914
|
-
]
|
|
915
|
-
}
|
|
916
|
-
]
|
|
1038
|
+
newText: '_bar',
|
|
1039
|
+
},
|
|
1040
|
+
],
|
|
1041
|
+
},
|
|
1042
|
+
],
|
|
1043
|
+
},
|
|
1044
|
+
],
|
|
917
1045
|
},
|
|
918
|
-
kind: 'quickfix'
|
|
1046
|
+
kind: 'quickfix',
|
|
919
1047
|
});
|
|
920
1048
|
const refactorDiagnostic = result.find(diagnostic => diagnostic.kind === 'refactor');
|
|
921
1049
|
assert.isDefined(refactorDiagnostic);
|
|
@@ -932,34 +1060,34 @@ describe('code actions', () => {
|
|
|
932
1060
|
endLine: 2,
|
|
933
1061
|
endOffset: 50,
|
|
934
1062
|
refactor: 'Convert parameters to destructured object',
|
|
935
|
-
action: 'Convert parameters to destructured object'
|
|
936
|
-
}
|
|
937
|
-
]
|
|
1063
|
+
action: 'Convert parameters to destructured object',
|
|
1064
|
+
},
|
|
1065
|
+
],
|
|
938
1066
|
},
|
|
939
|
-
kind: 'refactor'
|
|
1067
|
+
kind: 'refactor',
|
|
940
1068
|
});
|
|
941
|
-
})
|
|
942
|
-
it('can filter quickfix code actions filtered by only', () =>
|
|
1069
|
+
});
|
|
1070
|
+
it('can filter quickfix code actions filtered by only', async () => {
|
|
943
1071
|
server.didOpenTextDocument({
|
|
944
|
-
textDocument: doc
|
|
1072
|
+
textDocument: doc,
|
|
945
1073
|
});
|
|
946
|
-
const result = (
|
|
1074
|
+
const result = (await server.codeAction({
|
|
947
1075
|
textDocument: doc,
|
|
948
1076
|
range: {
|
|
949
1077
|
start: { line: 1, character: 25 },
|
|
950
|
-
end: { line: 1, character: 49 }
|
|
1078
|
+
end: { line: 1, character: 49 },
|
|
951
1079
|
},
|
|
952
1080
|
context: {
|
|
953
1081
|
diagnostics: [{
|
|
954
1082
|
range: {
|
|
955
1083
|
start: { line: 1, character: 25 },
|
|
956
|
-
end: { line: 1, character: 49 }
|
|
1084
|
+
end: { line: 1, character: 49 },
|
|
957
1085
|
},
|
|
958
1086
|
code: 6133,
|
|
959
|
-
message: 'unused arg'
|
|
1087
|
+
message: 'unused arg',
|
|
960
1088
|
}],
|
|
961
|
-
only: ['refactor', 'invalid-action']
|
|
962
|
-
}
|
|
1089
|
+
only: ['refactor', 'invalid-action'],
|
|
1090
|
+
},
|
|
963
1091
|
}));
|
|
964
1092
|
assert.deepEqual(result, [
|
|
965
1093
|
{
|
|
@@ -972,65 +1100,65 @@ describe('code actions', () => {
|
|
|
972
1100
|
file: filePath('bar.ts'),
|
|
973
1101
|
refactor: 'Convert parameters to destructured object',
|
|
974
1102
|
startLine: 2,
|
|
975
|
-
startOffset: 26
|
|
976
|
-
}
|
|
1103
|
+
startOffset: 26,
|
|
1104
|
+
},
|
|
977
1105
|
],
|
|
978
1106
|
command: '_typescript.applyRefactoring',
|
|
979
|
-
title: 'Convert parameters to destructured object'
|
|
1107
|
+
title: 'Convert parameters to destructured object',
|
|
980
1108
|
},
|
|
981
1109
|
kind: 'refactor',
|
|
982
|
-
title: 'Convert parameters to destructured object'
|
|
983
|
-
}
|
|
1110
|
+
title: 'Convert parameters to destructured object',
|
|
1111
|
+
},
|
|
984
1112
|
]);
|
|
985
|
-
})
|
|
986
|
-
it('does not provide organize imports when there are errors', () =>
|
|
1113
|
+
});
|
|
1114
|
+
it('does not provide organize imports when there are errors', async () => {
|
|
987
1115
|
server.didOpenTextDocument({
|
|
988
|
-
textDocument: doc
|
|
1116
|
+
textDocument: doc,
|
|
989
1117
|
});
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
const result = (
|
|
1118
|
+
await server.requestDiagnostics();
|
|
1119
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
1120
|
+
const result = (await server.codeAction({
|
|
993
1121
|
textDocument: doc,
|
|
994
1122
|
range: {
|
|
995
1123
|
start: { line: 1, character: 29 },
|
|
996
|
-
end: { line: 1, character: 53 }
|
|
1124
|
+
end: { line: 1, character: 53 },
|
|
997
1125
|
},
|
|
998
1126
|
context: {
|
|
999
1127
|
diagnostics: [{
|
|
1000
1128
|
range: {
|
|
1001
1129
|
start: { line: 1, character: 25 },
|
|
1002
|
-
end: { line: 1, character: 49 }
|
|
1130
|
+
end: { line: 1, character: 49 },
|
|
1003
1131
|
},
|
|
1004
1132
|
code: 6133,
|
|
1005
|
-
message: 'unused arg'
|
|
1133
|
+
message: 'unused arg',
|
|
1006
1134
|
}],
|
|
1007
|
-
only: [CodeActionKind.SourceOrganizeImportsTs.value]
|
|
1008
|
-
}
|
|
1135
|
+
only: [CodeActionKind.SourceOrganizeImportsTs.value],
|
|
1136
|
+
},
|
|
1009
1137
|
}));
|
|
1010
1138
|
assert.deepEqual(result, []);
|
|
1011
|
-
})
|
|
1012
|
-
it('provides "add missing imports" when explicitly requested in only', () =>
|
|
1139
|
+
});
|
|
1140
|
+
it('provides "add missing imports" when explicitly requested in only', async () => {
|
|
1013
1141
|
const doc = {
|
|
1014
1142
|
uri: uri('bar.ts'),
|
|
1015
1143
|
languageId: 'typescript',
|
|
1016
1144
|
version: 1,
|
|
1017
|
-
text: 'existsSync(\'t\');'
|
|
1145
|
+
text: 'existsSync(\'t\');',
|
|
1018
1146
|
};
|
|
1019
1147
|
server.didOpenTextDocument({
|
|
1020
|
-
textDocument: doc
|
|
1148
|
+
textDocument: doc,
|
|
1021
1149
|
});
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
const result = (
|
|
1150
|
+
await server.requestDiagnostics();
|
|
1151
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
1152
|
+
const result = (await server.codeAction({
|
|
1025
1153
|
textDocument: doc,
|
|
1026
1154
|
range: {
|
|
1027
1155
|
start: { line: 1, character: 29 },
|
|
1028
|
-
end: { line: 1, character: 53 }
|
|
1156
|
+
end: { line: 1, character: 53 },
|
|
1029
1157
|
},
|
|
1030
1158
|
context: {
|
|
1031
1159
|
diagnostics: [],
|
|
1032
|
-
only: [CodeActionKind.SourceAddMissingImportsTs.value]
|
|
1033
|
-
}
|
|
1160
|
+
only: [CodeActionKind.SourceAddMissingImportsTs.value],
|
|
1161
|
+
},
|
|
1034
1162
|
}));
|
|
1035
1163
|
assert.deepEqual(result, [
|
|
1036
1164
|
{
|
|
@@ -1046,26 +1174,26 @@ describe('code actions', () => {
|
|
|
1046
1174
|
range: {
|
|
1047
1175
|
end: {
|
|
1048
1176
|
character: 0,
|
|
1049
|
-
line: 0
|
|
1177
|
+
line: 0,
|
|
1050
1178
|
},
|
|
1051
1179
|
start: {
|
|
1052
1180
|
character: 0,
|
|
1053
|
-
line: 0
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
}
|
|
1181
|
+
line: 0,
|
|
1182
|
+
},
|
|
1183
|
+
},
|
|
1184
|
+
},
|
|
1057
1185
|
],
|
|
1058
1186
|
textDocument: {
|
|
1059
1187
|
uri: uri('bar.ts'),
|
|
1060
|
-
version: 1
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1063
|
-
]
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1188
|
+
version: 1,
|
|
1189
|
+
},
|
|
1190
|
+
},
|
|
1191
|
+
],
|
|
1192
|
+
},
|
|
1193
|
+
},
|
|
1066
1194
|
]);
|
|
1067
|
-
})
|
|
1068
|
-
it('provides "fix all" when explicitly requested in only', () =>
|
|
1195
|
+
});
|
|
1196
|
+
it('provides "fix all" when explicitly requested in only', async () => {
|
|
1069
1197
|
const doc = {
|
|
1070
1198
|
uri: uri('bar.ts'),
|
|
1071
1199
|
languageId: 'typescript',
|
|
@@ -1073,23 +1201,23 @@ describe('code actions', () => {
|
|
|
1073
1201
|
text: `function foo() {
|
|
1074
1202
|
return
|
|
1075
1203
|
setTimeout(() => {})
|
|
1076
|
-
}
|
|
1204
|
+
}`,
|
|
1077
1205
|
};
|
|
1078
1206
|
server.didOpenTextDocument({
|
|
1079
|
-
textDocument: doc
|
|
1207
|
+
textDocument: doc,
|
|
1080
1208
|
});
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
const result = (
|
|
1209
|
+
await server.requestDiagnostics();
|
|
1210
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
1211
|
+
const result = (await server.codeAction({
|
|
1084
1212
|
textDocument: doc,
|
|
1085
1213
|
range: {
|
|
1086
1214
|
start: { line: 0, character: 0 },
|
|
1087
|
-
end: { line: 4, character: 0 }
|
|
1215
|
+
end: { line: 4, character: 0 },
|
|
1088
1216
|
},
|
|
1089
1217
|
context: {
|
|
1090
1218
|
diagnostics: [],
|
|
1091
|
-
only: [CodeActionKind.SourceFixAllTs.value]
|
|
1092
|
-
}
|
|
1219
|
+
only: [CodeActionKind.SourceFixAllTs.value],
|
|
1220
|
+
},
|
|
1093
1221
|
}));
|
|
1094
1222
|
assert.deepEqual(result, [
|
|
1095
1223
|
{
|
|
@@ -1104,54 +1232,54 @@ describe('code actions', () => {
|
|
|
1104
1232
|
range: {
|
|
1105
1233
|
end: {
|
|
1106
1234
|
character: 0,
|
|
1107
|
-
line: 3
|
|
1235
|
+
line: 3,
|
|
1108
1236
|
},
|
|
1109
1237
|
start: {
|
|
1110
1238
|
character: 0,
|
|
1111
|
-
line: 2
|
|
1112
|
-
}
|
|
1113
|
-
}
|
|
1114
|
-
}
|
|
1239
|
+
line: 2,
|
|
1240
|
+
},
|
|
1241
|
+
},
|
|
1242
|
+
},
|
|
1115
1243
|
],
|
|
1116
1244
|
textDocument: {
|
|
1117
1245
|
uri: uri('bar.ts'),
|
|
1118
|
-
version: 1
|
|
1119
|
-
}
|
|
1120
|
-
}
|
|
1121
|
-
]
|
|
1122
|
-
}
|
|
1123
|
-
}
|
|
1246
|
+
version: 1,
|
|
1247
|
+
},
|
|
1248
|
+
},
|
|
1249
|
+
],
|
|
1250
|
+
},
|
|
1251
|
+
},
|
|
1124
1252
|
]);
|
|
1125
|
-
})
|
|
1126
|
-
it('provides organize imports when explicitly requested in only', () =>
|
|
1253
|
+
});
|
|
1254
|
+
it('provides organize imports when explicitly requested in only', async () => {
|
|
1127
1255
|
const doc = {
|
|
1128
1256
|
uri: uri('bar.ts'),
|
|
1129
1257
|
languageId: 'typescript',
|
|
1130
1258
|
version: 1,
|
|
1131
1259
|
text: `import { existsSync } from 'fs';
|
|
1132
1260
|
import { accessSync } from 'fs';
|
|
1133
|
-
existsSync('t')
|
|
1261
|
+
existsSync('t');`,
|
|
1134
1262
|
};
|
|
1135
1263
|
server.didOpenTextDocument({
|
|
1136
|
-
textDocument: doc
|
|
1264
|
+
textDocument: doc,
|
|
1137
1265
|
});
|
|
1138
|
-
const result = (
|
|
1266
|
+
const result = (await server.codeAction({
|
|
1139
1267
|
textDocument: doc,
|
|
1140
1268
|
range: {
|
|
1141
1269
|
start: { line: 0, character: 0 },
|
|
1142
|
-
end: { line: 3, character: 0 }
|
|
1270
|
+
end: { line: 3, character: 0 },
|
|
1143
1271
|
},
|
|
1144
1272
|
context: {
|
|
1145
1273
|
diagnostics: [{
|
|
1146
1274
|
range: {
|
|
1147
1275
|
start: { line: 1, character: 25 },
|
|
1148
|
-
end: { line: 1, character: 49 }
|
|
1276
|
+
end: { line: 1, character: 49 },
|
|
1149
1277
|
},
|
|
1150
1278
|
code: 6133,
|
|
1151
|
-
message: 'unused arg'
|
|
1279
|
+
message: 'unused arg',
|
|
1152
1280
|
}],
|
|
1153
|
-
only: [CodeActionKind.SourceOrganizeImportsTs.value]
|
|
1154
|
-
}
|
|
1281
|
+
only: [CodeActionKind.SourceOrganizeImportsTs.value],
|
|
1282
|
+
},
|
|
1155
1283
|
}));
|
|
1156
1284
|
assert.deepEqual(result, [
|
|
1157
1285
|
{
|
|
@@ -1166,60 +1294,60 @@ existsSync('t');`
|
|
|
1166
1294
|
range: {
|
|
1167
1295
|
end: {
|
|
1168
1296
|
character: 0,
|
|
1169
|
-
line: 1
|
|
1297
|
+
line: 1,
|
|
1170
1298
|
},
|
|
1171
1299
|
start: {
|
|
1172
1300
|
character: 0,
|
|
1173
|
-
line: 0
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1301
|
+
line: 0,
|
|
1302
|
+
},
|
|
1303
|
+
},
|
|
1176
1304
|
},
|
|
1177
1305
|
{
|
|
1178
1306
|
newText: '',
|
|
1179
1307
|
range: {
|
|
1180
1308
|
end: {
|
|
1181
1309
|
character: 0,
|
|
1182
|
-
line: 2
|
|
1310
|
+
line: 2,
|
|
1183
1311
|
},
|
|
1184
1312
|
start: {
|
|
1185
1313
|
character: 0,
|
|
1186
|
-
line: 1
|
|
1187
|
-
}
|
|
1188
|
-
}
|
|
1189
|
-
}
|
|
1314
|
+
line: 1,
|
|
1315
|
+
},
|
|
1316
|
+
},
|
|
1317
|
+
},
|
|
1190
1318
|
],
|
|
1191
1319
|
textDocument: {
|
|
1192
1320
|
uri: uri('bar.ts'),
|
|
1193
|
-
version: 1
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
|
-
]
|
|
1197
|
-
}
|
|
1198
|
-
}
|
|
1321
|
+
version: 1,
|
|
1322
|
+
},
|
|
1323
|
+
},
|
|
1324
|
+
],
|
|
1325
|
+
},
|
|
1326
|
+
},
|
|
1199
1327
|
]);
|
|
1200
|
-
})
|
|
1201
|
-
it('provides "remove unused" when explicitly requested in only', () =>
|
|
1328
|
+
});
|
|
1329
|
+
it('provides "remove unused" when explicitly requested in only', async () => {
|
|
1202
1330
|
const doc = {
|
|
1203
1331
|
uri: uri('bar.ts'),
|
|
1204
1332
|
languageId: 'typescript',
|
|
1205
1333
|
version: 1,
|
|
1206
|
-
text: 'import { existsSync } from \'fs\';'
|
|
1334
|
+
text: 'import { existsSync } from \'fs\';',
|
|
1207
1335
|
};
|
|
1208
1336
|
server.didOpenTextDocument({
|
|
1209
|
-
textDocument: doc
|
|
1337
|
+
textDocument: doc,
|
|
1210
1338
|
});
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
const result = (
|
|
1339
|
+
await server.requestDiagnostics();
|
|
1340
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
1341
|
+
const result = (await server.codeAction({
|
|
1214
1342
|
textDocument: doc,
|
|
1215
1343
|
range: {
|
|
1216
1344
|
start: position(doc, 'existsSync'),
|
|
1217
|
-
end: positionAfter(doc, 'existsSync')
|
|
1345
|
+
end: positionAfter(doc, 'existsSync'),
|
|
1218
1346
|
},
|
|
1219
1347
|
context: {
|
|
1220
1348
|
diagnostics: [],
|
|
1221
|
-
only: [CodeActionKind.SourceRemoveUnusedTs.value]
|
|
1222
|
-
}
|
|
1349
|
+
only: [CodeActionKind.SourceRemoveUnusedTs.value],
|
|
1350
|
+
},
|
|
1223
1351
|
}));
|
|
1224
1352
|
assert.deepEqual(result, [
|
|
1225
1353
|
{
|
|
@@ -1234,26 +1362,26 @@ existsSync('t');`
|
|
|
1234
1362
|
range: {
|
|
1235
1363
|
end: {
|
|
1236
1364
|
character: 32,
|
|
1237
|
-
line: 0
|
|
1365
|
+
line: 0,
|
|
1238
1366
|
},
|
|
1239
1367
|
start: {
|
|
1240
1368
|
character: 0,
|
|
1241
|
-
line: 0
|
|
1242
|
-
}
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1369
|
+
line: 0,
|
|
1370
|
+
},
|
|
1371
|
+
},
|
|
1372
|
+
},
|
|
1245
1373
|
],
|
|
1246
1374
|
textDocument: {
|
|
1247
1375
|
uri: uri('bar.ts'),
|
|
1248
|
-
version: 1
|
|
1249
|
-
}
|
|
1250
|
-
}
|
|
1251
|
-
]
|
|
1252
|
-
}
|
|
1253
|
-
}
|
|
1376
|
+
version: 1,
|
|
1377
|
+
},
|
|
1378
|
+
},
|
|
1379
|
+
],
|
|
1380
|
+
},
|
|
1381
|
+
},
|
|
1254
1382
|
]);
|
|
1255
|
-
})
|
|
1256
|
-
it('only provides the "source.fixAll" kind if requested in only', () =>
|
|
1383
|
+
});
|
|
1384
|
+
it('only provides the "source.fixAll" kind if requested in only', async () => {
|
|
1257
1385
|
const doc = {
|
|
1258
1386
|
uri: uri('bar.ts'),
|
|
1259
1387
|
languageId: 'typescript',
|
|
@@ -1264,23 +1392,23 @@ existsSync('t');`
|
|
|
1264
1392
|
return
|
|
1265
1393
|
setTimeout(() => {})
|
|
1266
1394
|
}
|
|
1267
|
-
|
|
1395
|
+
`,
|
|
1268
1396
|
};
|
|
1269
1397
|
server.didOpenTextDocument({
|
|
1270
|
-
textDocument: doc
|
|
1398
|
+
textDocument: doc,
|
|
1271
1399
|
});
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
const result = (
|
|
1400
|
+
await server.requestDiagnostics();
|
|
1401
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
1402
|
+
const result = (await server.codeAction({
|
|
1275
1403
|
textDocument: doc,
|
|
1276
1404
|
range: {
|
|
1277
1405
|
start: { line: 0, character: 0 },
|
|
1278
|
-
end: lastPosition(doc, '}')
|
|
1406
|
+
end: lastPosition(doc, '}'),
|
|
1279
1407
|
},
|
|
1280
1408
|
context: {
|
|
1281
1409
|
diagnostics: [],
|
|
1282
|
-
only: [CodeActionKind.SourceFixAllTs.value]
|
|
1283
|
-
}
|
|
1410
|
+
only: [CodeActionKind.SourceFixAllTs.value],
|
|
1411
|
+
},
|
|
1284
1412
|
}));
|
|
1285
1413
|
assert.strictEqual(result.length, 1, JSON.stringify(result, null, 2));
|
|
1286
1414
|
assert.deepEqual(result, [
|
|
@@ -1296,55 +1424,55 @@ existsSync('t');`
|
|
|
1296
1424
|
range: {
|
|
1297
1425
|
start: {
|
|
1298
1426
|
line: 4,
|
|
1299
|
-
character: 0
|
|
1427
|
+
character: 0,
|
|
1300
1428
|
},
|
|
1301
1429
|
end: {
|
|
1302
1430
|
line: 5,
|
|
1303
|
-
character: 0
|
|
1304
|
-
}
|
|
1305
|
-
}
|
|
1306
|
-
}
|
|
1431
|
+
character: 0,
|
|
1432
|
+
},
|
|
1433
|
+
},
|
|
1434
|
+
},
|
|
1307
1435
|
],
|
|
1308
1436
|
textDocument: {
|
|
1309
1437
|
uri: uri('bar.ts'),
|
|
1310
|
-
version: 1
|
|
1311
|
-
}
|
|
1312
|
-
}
|
|
1313
|
-
]
|
|
1314
|
-
}
|
|
1315
|
-
}
|
|
1438
|
+
version: 1,
|
|
1439
|
+
},
|
|
1440
|
+
},
|
|
1441
|
+
],
|
|
1442
|
+
},
|
|
1443
|
+
},
|
|
1316
1444
|
]);
|
|
1317
|
-
})
|
|
1445
|
+
});
|
|
1318
1446
|
});
|
|
1319
1447
|
describe('executeCommand', () => {
|
|
1320
|
-
it('apply refactoring (move to new file)', () =>
|
|
1448
|
+
it('apply refactoring (move to new file)', async () => {
|
|
1321
1449
|
const fooUri = uri('foo.ts');
|
|
1322
1450
|
const doc = {
|
|
1323
1451
|
uri: fooUri,
|
|
1324
1452
|
languageId: 'typescript',
|
|
1325
1453
|
version: 1,
|
|
1326
|
-
text: 'export function fn(): void {}\nexport function newFn(): void {}'
|
|
1454
|
+
text: 'export function fn(): void {}\nexport function newFn(): void {}',
|
|
1327
1455
|
};
|
|
1328
1456
|
server.didOpenTextDocument({
|
|
1329
|
-
textDocument: doc
|
|
1457
|
+
textDocument: doc,
|
|
1330
1458
|
});
|
|
1331
|
-
const codeActions = (
|
|
1459
|
+
const codeActions = (await server.codeAction({
|
|
1332
1460
|
textDocument: doc,
|
|
1333
1461
|
range: {
|
|
1334
1462
|
start: position(doc, 'newFn'),
|
|
1335
|
-
end: position(doc, 'newFn')
|
|
1463
|
+
end: position(doc, 'newFn'),
|
|
1336
1464
|
},
|
|
1337
1465
|
context: {
|
|
1338
|
-
diagnostics: []
|
|
1339
|
-
}
|
|
1466
|
+
diagnostics: [],
|
|
1467
|
+
},
|
|
1340
1468
|
}));
|
|
1341
1469
|
// Find refactoring code action.
|
|
1342
|
-
const applyRefactoringAction = codeActions.find(action =>
|
|
1470
|
+
const applyRefactoringAction = codeActions.find(action => action.command?.command === Commands.APPLY_REFACTORING);
|
|
1343
1471
|
assert.isDefined(applyRefactoringAction);
|
|
1344
1472
|
// Execute refactoring action.
|
|
1345
|
-
|
|
1473
|
+
await server.executeCommand({
|
|
1346
1474
|
command: applyRefactoringAction.command.command,
|
|
1347
|
-
arguments: applyRefactoringAction.command.arguments
|
|
1475
|
+
arguments: applyRefactoringAction.command.arguments,
|
|
1348
1476
|
});
|
|
1349
1477
|
assert.equal(1, server.workspaceEdits.length);
|
|
1350
1478
|
const { changes } = server.workspaceEdits[0].edit;
|
|
@@ -1361,35 +1489,68 @@ describe('executeCommand', () => {
|
|
|
1361
1489
|
range: {
|
|
1362
1490
|
start: {
|
|
1363
1491
|
line: 1,
|
|
1364
|
-
character: 0
|
|
1492
|
+
character: 0,
|
|
1365
1493
|
},
|
|
1366
1494
|
end: {
|
|
1367
1495
|
line: 1,
|
|
1368
|
-
character: 32
|
|
1369
|
-
}
|
|
1496
|
+
character: 32,
|
|
1497
|
+
},
|
|
1370
1498
|
},
|
|
1371
|
-
newText: ''
|
|
1372
|
-
}
|
|
1499
|
+
newText: '',
|
|
1500
|
+
},
|
|
1373
1501
|
]);
|
|
1374
1502
|
assert.deepEqual(change2, [
|
|
1375
1503
|
{
|
|
1376
1504
|
range: {
|
|
1377
1505
|
start: {
|
|
1378
1506
|
line: 0,
|
|
1379
|
-
character: 0
|
|
1507
|
+
character: 0,
|
|
1380
1508
|
},
|
|
1381
1509
|
end: {
|
|
1382
1510
|
line: 0,
|
|
1383
|
-
character: 0
|
|
1384
|
-
}
|
|
1511
|
+
character: 0,
|
|
1512
|
+
},
|
|
1385
1513
|
},
|
|
1386
|
-
newText: 'export function newFn(): void { }\n'
|
|
1387
|
-
}
|
|
1514
|
+
newText: 'export function newFn(): void { }\n',
|
|
1515
|
+
},
|
|
1388
1516
|
]);
|
|
1389
|
-
})
|
|
1517
|
+
});
|
|
1518
|
+
it('go to source definition', async () => {
|
|
1519
|
+
// NOTE: This test needs to reference files that physically exist for the feature to work.
|
|
1520
|
+
const indexUri = uri('source-definition', 'index.ts');
|
|
1521
|
+
const indexDoc = {
|
|
1522
|
+
uri: indexUri,
|
|
1523
|
+
languageId: 'typescript',
|
|
1524
|
+
version: 1,
|
|
1525
|
+
text: readContents(filePath('source-definition', 'index.ts')),
|
|
1526
|
+
};
|
|
1527
|
+
server.didOpenTextDocument({ textDocument: indexDoc });
|
|
1528
|
+
const result = await server.executeCommand({
|
|
1529
|
+
command: Commands.SOURCE_DEFINITION,
|
|
1530
|
+
arguments: [
|
|
1531
|
+
indexUri,
|
|
1532
|
+
position(indexDoc, '/*identifier*/'),
|
|
1533
|
+
],
|
|
1534
|
+
});
|
|
1535
|
+
assert.isNotNull(result);
|
|
1536
|
+
assert.equal(result.length, 1);
|
|
1537
|
+
assert.deepEqual(result[0], {
|
|
1538
|
+
uri: uri('source-definition', 'a.js'),
|
|
1539
|
+
range: {
|
|
1540
|
+
start: {
|
|
1541
|
+
line: 0,
|
|
1542
|
+
character: 13,
|
|
1543
|
+
},
|
|
1544
|
+
end: {
|
|
1545
|
+
line: 0,
|
|
1546
|
+
character: 14,
|
|
1547
|
+
},
|
|
1548
|
+
},
|
|
1549
|
+
});
|
|
1550
|
+
});
|
|
1390
1551
|
});
|
|
1391
1552
|
describe('documentHighlight', () => {
|
|
1392
|
-
it('simple test', () =>
|
|
1553
|
+
it('simple test', async () => {
|
|
1393
1554
|
const barDoc = {
|
|
1394
1555
|
uri: uri('bar.d.ts'),
|
|
1395
1556
|
languageId: 'typescript',
|
|
@@ -1398,10 +1559,10 @@ describe('documentHighlight', () => {
|
|
|
1398
1559
|
export declare const Bar: unique symbol;
|
|
1399
1560
|
export interface Bar {
|
|
1400
1561
|
}
|
|
1401
|
-
|
|
1562
|
+
`,
|
|
1402
1563
|
};
|
|
1403
1564
|
server.didOpenTextDocument({
|
|
1404
|
-
textDocument: barDoc
|
|
1565
|
+
textDocument: barDoc,
|
|
1405
1566
|
});
|
|
1406
1567
|
const fooDoc = {
|
|
1407
1568
|
uri: uri('bar.ts'),
|
|
@@ -1411,17 +1572,17 @@ describe('documentHighlight', () => {
|
|
|
1411
1572
|
import { Bar } from './bar';
|
|
1412
1573
|
export class Foo implements Bar {
|
|
1413
1574
|
}
|
|
1414
|
-
|
|
1575
|
+
`,
|
|
1415
1576
|
};
|
|
1416
1577
|
server.didOpenTextDocument({
|
|
1417
|
-
textDocument: fooDoc
|
|
1578
|
+
textDocument: fooDoc,
|
|
1418
1579
|
});
|
|
1419
|
-
const result =
|
|
1580
|
+
const result = await server.documentHighlight({
|
|
1420
1581
|
textDocument: fooDoc,
|
|
1421
|
-
position: lastPosition(fooDoc, 'Bar')
|
|
1582
|
+
position: lastPosition(fooDoc, 'Bar'),
|
|
1422
1583
|
});
|
|
1423
1584
|
assert.equal(2, result.length, JSON.stringify(result, undefined, 2));
|
|
1424
|
-
})
|
|
1585
|
+
});
|
|
1425
1586
|
});
|
|
1426
1587
|
describe('calls', () => {
|
|
1427
1588
|
function resultToString(callsResult, direction) {
|
|
@@ -1456,7 +1617,7 @@ export function two() {
|
|
|
1456
1617
|
export function three() {
|
|
1457
1618
|
return "".toString();
|
|
1458
1619
|
}
|
|
1459
|
-
|
|
1620
|
+
`,
|
|
1460
1621
|
};
|
|
1461
1622
|
const fooDoc = {
|
|
1462
1623
|
uri: uri('foo.ts'),
|
|
@@ -1473,17 +1634,17 @@ class MyClass {
|
|
|
1473
1634
|
export function factory() {
|
|
1474
1635
|
new MyClass().doSomething();
|
|
1475
1636
|
}
|
|
1476
|
-
|
|
1637
|
+
`,
|
|
1477
1638
|
};
|
|
1478
1639
|
function openDocuments() {
|
|
1479
1640
|
server.didOpenTextDocument({ textDocument: doDoc });
|
|
1480
1641
|
server.didOpenTextDocument({ textDocument: fooDoc });
|
|
1481
1642
|
}
|
|
1482
|
-
it('callers: first step', () =>
|
|
1643
|
+
it('callers: first step', async () => {
|
|
1483
1644
|
openDocuments();
|
|
1484
|
-
const callsResult =
|
|
1645
|
+
const callsResult = await server.calls({
|
|
1485
1646
|
textDocument: fooDoc,
|
|
1486
|
-
position: position(fooDoc, 'doStuff();')
|
|
1647
|
+
position: position(fooDoc, 'doStuff();'),
|
|
1487
1648
|
});
|
|
1488
1649
|
assert.equal(resultToString(callsResult, lspcalls.CallDirection.Incoming), `
|
|
1489
1650
|
↘ doStuff (do.ts#1)
|
|
@@ -1491,59 +1652,60 @@ export function factory() {
|
|
|
1491
1652
|
↘ doSomething (foo.ts#2) - foo.ts#3
|
|
1492
1653
|
↘ x (foo.ts#4) - foo.ts#4
|
|
1493
1654
|
`.trim());
|
|
1494
|
-
})
|
|
1495
|
-
it('callers: second step', () =>
|
|
1655
|
+
});
|
|
1656
|
+
it('callers: second step', async () => {
|
|
1496
1657
|
openDocuments();
|
|
1497
|
-
const callsResult =
|
|
1658
|
+
const callsResult = await server.calls({
|
|
1498
1659
|
textDocument: fooDoc,
|
|
1499
|
-
position: position(fooDoc, 'doSomething() {')
|
|
1660
|
+
position: position(fooDoc, 'doSomething() {'),
|
|
1500
1661
|
});
|
|
1501
1662
|
assert.equal(resultToString(callsResult, lspcalls.CallDirection.Incoming), `
|
|
1502
1663
|
↘ doSomething (foo.ts#2)
|
|
1503
1664
|
↘ factory (foo.ts#8) - foo.ts#9
|
|
1504
1665
|
`.trim());
|
|
1505
|
-
})
|
|
1506
|
-
it.skip('callees: first step', () =>
|
|
1666
|
+
});
|
|
1667
|
+
it.skip('callees: first step', async () => {
|
|
1507
1668
|
openDocuments();
|
|
1508
1669
|
const direction = lspcalls.CallDirection.Outgoing;
|
|
1509
|
-
const callsResult =
|
|
1670
|
+
const callsResult = await server.calls({
|
|
1510
1671
|
direction,
|
|
1511
1672
|
textDocument: fooDoc,
|
|
1512
|
-
position: position(fooDoc, 'doStuff()')
|
|
1673
|
+
position: position(fooDoc, 'doStuff()'),
|
|
1513
1674
|
});
|
|
1514
1675
|
assert.equal(resultToString(callsResult, direction), `
|
|
1515
1676
|
↖ doStuff (do.ts#1)
|
|
1516
1677
|
↖ two (do.ts#4) - do.ts#2
|
|
1517
1678
|
`.trim());
|
|
1518
|
-
})
|
|
1519
|
-
it.skip('callees: second step', () =>
|
|
1679
|
+
});
|
|
1680
|
+
it.skip('callees: second step', async () => {
|
|
1520
1681
|
openDocuments();
|
|
1521
1682
|
const direction = lspcalls.CallDirection.Outgoing;
|
|
1522
|
-
const callsResult =
|
|
1683
|
+
const callsResult = await server.calls({
|
|
1523
1684
|
direction,
|
|
1524
1685
|
textDocument: doDoc,
|
|
1525
|
-
position: position(doDoc, 'function two()')
|
|
1686
|
+
position: position(doDoc, 'function two()'),
|
|
1526
1687
|
});
|
|
1527
1688
|
assert.equal(resultToString(callsResult, direction), `
|
|
1528
1689
|
↖ two (do.ts#4)
|
|
1529
1690
|
↖ three (do.ts#9) - do.ts#5
|
|
1530
1691
|
↖ ttt (do.ts#6) - do.ts#7
|
|
1531
1692
|
`.trim());
|
|
1532
|
-
})
|
|
1693
|
+
});
|
|
1533
1694
|
});
|
|
1534
1695
|
describe('diagnostics (no client support)', () => {
|
|
1535
1696
|
let localServer;
|
|
1536
|
-
before(() =>
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1697
|
+
before(async () => {
|
|
1698
|
+
const clientCapabilitiesOverride = {
|
|
1699
|
+
textDocument: {
|
|
1700
|
+
publishDiagnostics: undefined,
|
|
1701
|
+
},
|
|
1702
|
+
};
|
|
1703
|
+
localServer = await createServer({
|
|
1542
1704
|
rootUri: null,
|
|
1543
1705
|
publishDiagnostics: args => diagnostics.set(args.uri, args),
|
|
1544
|
-
clientCapabilitiesOverride
|
|
1706
|
+
clientCapabilitiesOverride,
|
|
1545
1707
|
});
|
|
1546
|
-
})
|
|
1708
|
+
});
|
|
1547
1709
|
beforeEach(() => {
|
|
1548
1710
|
localServer.closeAll();
|
|
1549
1711
|
// "closeAll" triggers final publishDiagnostics with an empty list so clear last.
|
|
@@ -1554,7 +1716,7 @@ describe('diagnostics (no client support)', () => {
|
|
|
1554
1716
|
localServer.closeAll();
|
|
1555
1717
|
localServer.shutdown();
|
|
1556
1718
|
});
|
|
1557
|
-
it('
|
|
1719
|
+
it('diagnostic tags are not returned', async () => {
|
|
1558
1720
|
const doc = {
|
|
1559
1721
|
uri: uri('diagnosticsBar.ts'),
|
|
1560
1722
|
languageId: 'typescript',
|
|
@@ -1563,26 +1725,27 @@ describe('diagnostics (no client support)', () => {
|
|
|
1563
1725
|
export function foo(): void {
|
|
1564
1726
|
missing('test')
|
|
1565
1727
|
}
|
|
1566
|
-
|
|
1728
|
+
`,
|
|
1567
1729
|
};
|
|
1568
1730
|
localServer.didOpenTextDocument({
|
|
1569
|
-
textDocument: doc
|
|
1731
|
+
textDocument: doc,
|
|
1570
1732
|
});
|
|
1571
|
-
|
|
1572
|
-
|
|
1733
|
+
await localServer.requestDiagnostics();
|
|
1734
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
1573
1735
|
const resultsForFile = diagnostics.get(doc.uri);
|
|
1574
1736
|
assert.isDefined(resultsForFile);
|
|
1575
|
-
assert.strictEqual(resultsForFile
|
|
1576
|
-
|
|
1737
|
+
assert.strictEqual(resultsForFile.diagnostics.length, 1);
|
|
1738
|
+
assert.notProperty(resultsForFile.diagnostics[0], 'tags');
|
|
1739
|
+
});
|
|
1577
1740
|
});
|
|
1578
1741
|
describe('jsx/tsx project', () => {
|
|
1579
1742
|
let localServer;
|
|
1580
|
-
before(() =>
|
|
1581
|
-
localServer =
|
|
1743
|
+
before(async () => {
|
|
1744
|
+
localServer = await createServer({
|
|
1582
1745
|
rootUri: uri('jsx'),
|
|
1583
|
-
publishDiagnostics: args => diagnostics.set(args.uri, args)
|
|
1746
|
+
publishDiagnostics: args => diagnostics.set(args.uri, args),
|
|
1584
1747
|
});
|
|
1585
|
-
})
|
|
1748
|
+
});
|
|
1586
1749
|
beforeEach(() => {
|
|
1587
1750
|
localServer.closeAll();
|
|
1588
1751
|
// "closeAll" triggers final publishDiagnostics with an empty list so clear last.
|
|
@@ -1593,47 +1756,47 @@ describe('jsx/tsx project', () => {
|
|
|
1593
1756
|
localServer.closeAll();
|
|
1594
1757
|
localServer.shutdown();
|
|
1595
1758
|
});
|
|
1596
|
-
it('includes snippet completion for element prop', () =>
|
|
1759
|
+
it('includes snippet completion for element prop', async () => {
|
|
1597
1760
|
const doc = {
|
|
1598
1761
|
uri: uri('jsx', 'app.tsx'),
|
|
1599
1762
|
languageId: 'typescriptreact',
|
|
1600
1763
|
version: 1,
|
|
1601
|
-
text: readContents(filePath('jsx', 'app.tsx'))
|
|
1764
|
+
text: readContents(filePath('jsx', 'app.tsx')),
|
|
1602
1765
|
};
|
|
1603
1766
|
localServer.didOpenTextDocument({
|
|
1604
|
-
textDocument: doc
|
|
1767
|
+
textDocument: doc,
|
|
1605
1768
|
});
|
|
1606
|
-
const completion =
|
|
1769
|
+
const completion = await localServer.completion({ textDocument: doc, position: position(doc, 'title') });
|
|
1607
1770
|
assert.isNotNull(completion);
|
|
1608
1771
|
const item = completion.items.find(i => i.label === 'title');
|
|
1609
1772
|
assert.isDefined(item);
|
|
1610
|
-
assert.strictEqual(item
|
|
1611
|
-
})
|
|
1773
|
+
assert.strictEqual(item?.insertTextFormat, 2);
|
|
1774
|
+
});
|
|
1612
1775
|
});
|
|
1613
1776
|
describe('inlayHints', () => {
|
|
1614
|
-
before(() =>
|
|
1777
|
+
before(async () => {
|
|
1615
1778
|
server.didChangeConfiguration({
|
|
1616
1779
|
settings: {
|
|
1617
1780
|
typescript: {
|
|
1618
1781
|
inlayHints: {
|
|
1619
|
-
includeInlayFunctionLikeReturnTypeHints: true
|
|
1620
|
-
}
|
|
1621
|
-
}
|
|
1622
|
-
}
|
|
1782
|
+
includeInlayFunctionLikeReturnTypeHints: true,
|
|
1783
|
+
},
|
|
1784
|
+
},
|
|
1785
|
+
},
|
|
1623
1786
|
});
|
|
1624
|
-
})
|
|
1787
|
+
});
|
|
1625
1788
|
after(() => {
|
|
1626
1789
|
server.didChangeConfiguration({
|
|
1627
1790
|
settings: {
|
|
1628
1791
|
typescript: {
|
|
1629
1792
|
inlayHints: {
|
|
1630
|
-
includeInlayFunctionLikeReturnTypeHints: false
|
|
1631
|
-
}
|
|
1632
|
-
}
|
|
1633
|
-
}
|
|
1793
|
+
includeInlayFunctionLikeReturnTypeHints: false,
|
|
1794
|
+
},
|
|
1795
|
+
},
|
|
1796
|
+
},
|
|
1634
1797
|
});
|
|
1635
1798
|
});
|
|
1636
|
-
it('inlayHints', () =>
|
|
1799
|
+
it('inlayHints', async () => {
|
|
1637
1800
|
const doc = {
|
|
1638
1801
|
uri: uri('module.ts'),
|
|
1639
1802
|
languageId: 'typescript',
|
|
@@ -1642,15 +1805,129 @@ describe('inlayHints', () => {
|
|
|
1642
1805
|
export function foo() {
|
|
1643
1806
|
return 3
|
|
1644
1807
|
}
|
|
1645
|
-
|
|
1808
|
+
`,
|
|
1646
1809
|
};
|
|
1647
1810
|
server.didOpenTextDocument({ textDocument: doc });
|
|
1648
|
-
const
|
|
1811
|
+
const inlayHints = await server.inlayHints({ textDocument: doc, range: lsp.Range.create(0, 0, 4, 0) });
|
|
1812
|
+
assert.isDefined(inlayHints);
|
|
1813
|
+
assert.strictEqual(inlayHints.length, 1);
|
|
1814
|
+
assert.deepEqual(inlayHints[0], {
|
|
1815
|
+
label: ': number',
|
|
1816
|
+
position: { line: 1, character: 29 },
|
|
1817
|
+
kind: lsp.InlayHintKind.Type,
|
|
1818
|
+
paddingLeft: true,
|
|
1819
|
+
});
|
|
1820
|
+
});
|
|
1821
|
+
it('inlayHints (legacy)', async () => {
|
|
1822
|
+
const doc = {
|
|
1823
|
+
uri: uri('module.ts'),
|
|
1824
|
+
languageId: 'typescript',
|
|
1825
|
+
version: 1,
|
|
1826
|
+
text: `
|
|
1827
|
+
export function foo() {
|
|
1828
|
+
return 3
|
|
1829
|
+
}
|
|
1830
|
+
`,
|
|
1831
|
+
};
|
|
1832
|
+
server.didOpenTextDocument({ textDocument: doc });
|
|
1833
|
+
const { inlayHints } = await server.inlayHintsLegacy({ textDocument: doc });
|
|
1649
1834
|
assert.isDefined(inlayHints);
|
|
1650
1835
|
assert.strictEqual(inlayHints.length, 1);
|
|
1651
1836
|
assert.strictEqual(inlayHints[0].text, ': number');
|
|
1652
1837
|
assert.strictEqual(inlayHints[0].kind, 'Type');
|
|
1653
1838
|
assert.deepStrictEqual(inlayHints[0].position, { line: 1, character: 29 });
|
|
1654
|
-
})
|
|
1839
|
+
});
|
|
1840
|
+
});
|
|
1841
|
+
describe('completions without client snippet support', () => {
|
|
1842
|
+
let localServer;
|
|
1843
|
+
before(async () => {
|
|
1844
|
+
const clientCapabilitiesOverride = {
|
|
1845
|
+
textDocument: {
|
|
1846
|
+
completion: {
|
|
1847
|
+
completionItem: {
|
|
1848
|
+
snippetSupport: false,
|
|
1849
|
+
},
|
|
1850
|
+
},
|
|
1851
|
+
},
|
|
1852
|
+
};
|
|
1853
|
+
localServer = await createServer({
|
|
1854
|
+
rootUri: null,
|
|
1855
|
+
publishDiagnostics: args => diagnostics.set(args.uri, args),
|
|
1856
|
+
clientCapabilitiesOverride,
|
|
1857
|
+
});
|
|
1858
|
+
});
|
|
1859
|
+
beforeEach(() => {
|
|
1860
|
+
localServer.closeAll();
|
|
1861
|
+
// "closeAll" triggers final publishDiagnostics with an empty list so clear last.
|
|
1862
|
+
diagnostics.clear();
|
|
1863
|
+
localServer.workspaceEdits = [];
|
|
1864
|
+
});
|
|
1865
|
+
after(() => {
|
|
1866
|
+
localServer.closeAll();
|
|
1867
|
+
localServer.shutdown();
|
|
1868
|
+
});
|
|
1869
|
+
it('resolves completion for method completion does not contain snippet', async () => {
|
|
1870
|
+
const doc = {
|
|
1871
|
+
uri: uri('bar.ts'),
|
|
1872
|
+
languageId: 'typescript',
|
|
1873
|
+
version: 1,
|
|
1874
|
+
text: `
|
|
1875
|
+
import fs from 'fs'
|
|
1876
|
+
fs.readFile
|
|
1877
|
+
`,
|
|
1878
|
+
};
|
|
1879
|
+
localServer.didOpenTextDocument({ textDocument: doc });
|
|
1880
|
+
const proposals = await localServer.completion({ textDocument: doc, position: positionAfter(doc, 'readFile') });
|
|
1881
|
+
assert.isNotNull(proposals);
|
|
1882
|
+
const completion = proposals.items.find(completion => completion.label === 'readFile');
|
|
1883
|
+
assert.notEqual(completion.insertTextFormat, lsp.InsertTextFormat.Snippet);
|
|
1884
|
+
assert.strictEqual(completion.label, 'readFile');
|
|
1885
|
+
const resolvedItem = await localServer.completionResolve(completion);
|
|
1886
|
+
assert.strictEqual(resolvedItem.label, 'readFile');
|
|
1887
|
+
assert.strictEqual(resolvedItem.insertText, undefined);
|
|
1888
|
+
assert.strictEqual(resolvedItem.insertTextFormat, undefined);
|
|
1889
|
+
localServer.didCloseTextDocument({ textDocument: doc });
|
|
1890
|
+
});
|
|
1891
|
+
it('does not include snippet completions for element prop', async () => {
|
|
1892
|
+
const doc = {
|
|
1893
|
+
uri: uri('jsx', 'app.tsx'),
|
|
1894
|
+
languageId: 'typescriptreact',
|
|
1895
|
+
version: 1,
|
|
1896
|
+
text: readContents(filePath('jsx', 'app.tsx')),
|
|
1897
|
+
};
|
|
1898
|
+
localServer.didOpenTextDocument({
|
|
1899
|
+
textDocument: doc,
|
|
1900
|
+
});
|
|
1901
|
+
const completion = await localServer.completion({ textDocument: doc, position: position(doc, 'title') });
|
|
1902
|
+
assert.isNotNull(completion);
|
|
1903
|
+
const item = completion.items.find(i => i.label === 'title');
|
|
1904
|
+
assert.isUndefined(item);
|
|
1905
|
+
});
|
|
1906
|
+
it('does not include snippet completions for object methods', async () => {
|
|
1907
|
+
const doc = {
|
|
1908
|
+
uri: uri('foo.ts'),
|
|
1909
|
+
languageId: 'typescript',
|
|
1910
|
+
version: 1,
|
|
1911
|
+
text: `
|
|
1912
|
+
interface IFoo {
|
|
1913
|
+
bar(x: number): void;
|
|
1914
|
+
}
|
|
1915
|
+
const obj: IFoo = {
|
|
1916
|
+
/*a*/
|
|
1917
|
+
}
|
|
1918
|
+
`,
|
|
1919
|
+
};
|
|
1920
|
+
localServer.didOpenTextDocument({ textDocument: doc });
|
|
1921
|
+
const proposals = await localServer.completion({
|
|
1922
|
+
textDocument: doc,
|
|
1923
|
+
position: positionAfter(doc, '/*a*/'),
|
|
1924
|
+
});
|
|
1925
|
+
assert.isNotNull(proposals);
|
|
1926
|
+
assert.lengthOf(proposals.items, 1);
|
|
1927
|
+
assert.deepInclude(proposals.items[0], {
|
|
1928
|
+
label: 'bar',
|
|
1929
|
+
kind: 2,
|
|
1930
|
+
});
|
|
1931
|
+
});
|
|
1655
1932
|
});
|
|
1656
1933
|
//# sourceMappingURL=lsp-server.spec.js.map
|