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