typescript-language-server 1.0.0 → 1.1.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 +31 -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 +807 -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.js
CHANGED
|
@@ -4,15 +4,6 @@
|
|
|
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 path from 'node:path';
|
|
17
8
|
import fs from 'fs-extra';
|
|
18
9
|
import debounce from 'p-debounce';
|
|
@@ -24,10 +15,10 @@ import API from './utils/api.js';
|
|
|
24
15
|
import { PrefixingLogger } from './logger.js';
|
|
25
16
|
import { TspClient } from './tsp-client.js';
|
|
26
17
|
import { DiagnosticEventQueue } from './diagnostic-queue.js';
|
|
27
|
-
import { toDocumentHighlight,
|
|
18
|
+
import { toDocumentHighlight, asTagsDocumentation, uriToPath, toSymbolKind, toLocation, pathToUri, toTextEdit, asPlainText, normalizePath } from './protocol-translation.js';
|
|
28
19
|
import { LspDocuments } from './document.js';
|
|
29
20
|
import { asCompletionItem, asResolvedCompletionItem, getCompletionTriggerCharacter } from './completion.js';
|
|
30
|
-
import { asSignatureHelp } from './hover.js';
|
|
21
|
+
import { asSignatureHelp, toTsTriggerReason } from './hover.js';
|
|
31
22
|
import { Commands } from './commands.js';
|
|
32
23
|
import { provideQuickFix } from './quickfix.js';
|
|
33
24
|
import { provideRefactors } from './refactor.js';
|
|
@@ -36,38 +27,11 @@ import { collectDocumentSymbols, collectSymbolInformation } from './document-sym
|
|
|
36
27
|
import { computeCallers, computeCallees } from './calls.js';
|
|
37
28
|
import { TypeScriptVersionProvider } from './utils/versionProvider.js';
|
|
38
29
|
import { TypeScriptAutoFixProvider } from './features/fix-all.js';
|
|
30
|
+
import { TypeScriptInlayHintsProvider } from './features/inlay-hints.js';
|
|
31
|
+
import { SourceDefinitionCommand } from './features/source-definition.js';
|
|
32
|
+
import { Position, Range } from './utils/typeConverters.js';
|
|
39
33
|
import { CodeActionKind } from './utils/types.js';
|
|
40
|
-
|
|
41
|
-
allowIncompleteCompletions: true,
|
|
42
|
-
allowRenameOfImportPath: true,
|
|
43
|
-
allowTextChangesInNewFiles: true,
|
|
44
|
-
disableSuggestions: false,
|
|
45
|
-
displayPartsForJSDoc: true,
|
|
46
|
-
generateReturnInDocTemplate: true,
|
|
47
|
-
importModuleSpecifierEnding: 'auto',
|
|
48
|
-
importModuleSpecifierPreference: 'shortest',
|
|
49
|
-
includeAutomaticOptionalChainCompletions: true,
|
|
50
|
-
includeCompletionsForImportStatements: true,
|
|
51
|
-
includeCompletionsForModuleExports: true,
|
|
52
|
-
includeCompletionsWithClassMemberSnippets: true,
|
|
53
|
-
includeCompletionsWithInsertText: true,
|
|
54
|
-
includeCompletionsWithObjectLiteralMethodSnippets: true,
|
|
55
|
-
includeCompletionsWithSnippetText: true,
|
|
56
|
-
includeInlayEnumMemberValueHints: false,
|
|
57
|
-
includeInlayFunctionLikeReturnTypeHints: false,
|
|
58
|
-
includeInlayFunctionParameterTypeHints: false,
|
|
59
|
-
includeInlayParameterNameHints: 'none',
|
|
60
|
-
includeInlayParameterNameHintsWhenArgumentMatchesName: false,
|
|
61
|
-
includeInlayPropertyDeclarationTypeHints: false,
|
|
62
|
-
includeInlayVariableTypeHints: false,
|
|
63
|
-
includePackageJsonAutoImports: 'auto',
|
|
64
|
-
jsxAttributeCompletionStyle: 'auto',
|
|
65
|
-
lazyConfiguredProjectsFromExternalProject: false,
|
|
66
|
-
providePrefixAndSuffixTextForRename: true,
|
|
67
|
-
provideRefactorNotApplicableReason: false,
|
|
68
|
-
quotePreference: 'auto',
|
|
69
|
-
useLabelDetailsInCompletionEntries: true
|
|
70
|
-
};
|
|
34
|
+
import { ConfigurationManager } from './configuration-manager.js';
|
|
71
35
|
class ServerInitializingIndicator {
|
|
72
36
|
constructor(lspClient) {
|
|
73
37
|
this.lspClient = lspClient;
|
|
@@ -76,24 +40,24 @@ class ServerInitializingIndicator {
|
|
|
76
40
|
if (this._loadingProjectName) {
|
|
77
41
|
this._loadingProjectName = undefined;
|
|
78
42
|
if (this._progressReporter) {
|
|
79
|
-
this._progressReporter.
|
|
43
|
+
this._progressReporter.done();
|
|
80
44
|
this._progressReporter = undefined;
|
|
81
45
|
}
|
|
82
46
|
}
|
|
83
47
|
}
|
|
84
|
-
startedLoadingProject(projectName) {
|
|
48
|
+
async startedLoadingProject(projectName) {
|
|
85
49
|
// TS projects are loaded sequentially. Cancel existing task because it should always be resolved before
|
|
86
50
|
// the incoming project loading task is.
|
|
87
51
|
this.reset();
|
|
88
52
|
this._loadingProjectName = projectName;
|
|
89
|
-
this._progressReporter = this.lspClient.createProgressReporter();
|
|
53
|
+
this._progressReporter = await this.lspClient.createProgressReporter();
|
|
90
54
|
this._progressReporter.begin('Initializing JS/TS language features…');
|
|
91
55
|
}
|
|
92
56
|
finishedLoadingProject(projectName) {
|
|
93
57
|
if (this._loadingProjectName === projectName) {
|
|
94
58
|
this._loadingProjectName = undefined;
|
|
95
59
|
if (this._progressReporter) {
|
|
96
|
-
this._progressReporter.
|
|
60
|
+
this._progressReporter.done();
|
|
97
61
|
this._progressReporter = undefined;
|
|
98
62
|
}
|
|
99
63
|
}
|
|
@@ -102,14 +66,18 @@ class ServerInitializingIndicator {
|
|
|
102
66
|
export class LspServer {
|
|
103
67
|
constructor(options) {
|
|
104
68
|
this.options = options;
|
|
69
|
+
this._tspClient = null;
|
|
70
|
+
this._loadingIndicator = null;
|
|
71
|
+
this.initializeParams = null;
|
|
72
|
+
this.typeScriptAutoFixProvider = null;
|
|
105
73
|
this.features = {};
|
|
106
74
|
this.documents = new LspDocuments();
|
|
107
75
|
// True if diagnostic request is currently debouncing or the request is in progress. False only if there are
|
|
108
76
|
// no pending requests.
|
|
109
77
|
this.pendingDebouncedRequest = false;
|
|
110
78
|
this.doRequestDiagnosticsDebounced = debounce(() => this.doRequestDiagnostics(), 200);
|
|
79
|
+
this.configurationManager = new ConfigurationManager(this.documents);
|
|
111
80
|
this.logger = new PrefixingLogger(options.logger, '[lspserver]');
|
|
112
|
-
this.workspaceConfiguration = {};
|
|
113
81
|
}
|
|
114
82
|
closeAll() {
|
|
115
83
|
for (const file of [...this.documents.files]) {
|
|
@@ -162,169 +130,180 @@ export class LspServer {
|
|
|
162
130
|
}
|
|
163
131
|
return null;
|
|
164
132
|
}
|
|
165
|
-
initialize(params) {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
&&
|
|
202
|
-
|
|
133
|
+
async initialize(params) {
|
|
134
|
+
this.logger.log('initialize', params);
|
|
135
|
+
if (this._tspClient) {
|
|
136
|
+
throw new Error('The "initialize" request has already called before.');
|
|
137
|
+
}
|
|
138
|
+
this.initializeParams = params;
|
|
139
|
+
const clientCapabilities = this.initializeParams.capabilities;
|
|
140
|
+
this._loadingIndicator = new ServerInitializingIndicator(this.options.lspClient);
|
|
141
|
+
this.workspaceRoot = this.initializeParams.rootUri ? uriToPath(this.initializeParams.rootUri) : this.initializeParams.rootPath || undefined;
|
|
142
|
+
const userInitializationOptions = this.initializeParams.initializationOptions || {};
|
|
143
|
+
const { disableAutomaticTypingAcquisition, hostInfo, maxTsServerMemory, npmLocation, locale } = userInitializationOptions;
|
|
144
|
+
const { logVerbosity, plugins } = {
|
|
145
|
+
logVerbosity: userInitializationOptions.logVerbosity || this.options.tsserverLogVerbosity,
|
|
146
|
+
plugins: userInitializationOptions.plugins || [],
|
|
147
|
+
};
|
|
148
|
+
const logFile = this.getLogFile(logVerbosity);
|
|
149
|
+
const globalPlugins = [];
|
|
150
|
+
const pluginProbeLocations = [];
|
|
151
|
+
for (const plugin of plugins) {
|
|
152
|
+
globalPlugins.push(plugin.name);
|
|
153
|
+
pluginProbeLocations.push(plugin.location);
|
|
154
|
+
}
|
|
155
|
+
const typescriptVersion = this.findTypescriptVersion();
|
|
156
|
+
if (typescriptVersion) {
|
|
157
|
+
this.logger.info(`Using Typescript version (${typescriptVersion.source}) ${typescriptVersion.versionString} from path "${typescriptVersion.tsServerPath}"`);
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
throw Error('Could not find a valid TypeScript installation. Please ensure that the "typescript" dependency is installed in the workspace or that a valid --tsserver-path is specified. Exiting.');
|
|
161
|
+
}
|
|
162
|
+
this.configurationManager.mergeTsPreferences(userInitializationOptions.preferences || {});
|
|
163
|
+
// Setup supported features.
|
|
164
|
+
const { textDocument } = clientCapabilities;
|
|
165
|
+
this.features.definitionLinkSupport = textDocument?.definition?.linkSupport && typescriptVersion.version?.gte(API.v270);
|
|
166
|
+
const completionCapabilities = textDocument?.completion;
|
|
167
|
+
if (completionCapabilities?.completionItem) {
|
|
168
|
+
if (this.configurationManager.tsPreferences.useLabelDetailsInCompletionEntries
|
|
169
|
+
&& completionCapabilities.completionItem.labelDetailsSupport
|
|
170
|
+
&& typescriptVersion.version?.gte(API.v470)) {
|
|
171
|
+
this.features.completionLabelDetails = true;
|
|
172
|
+
}
|
|
173
|
+
if (completionCapabilities.completionItem.snippetSupport) {
|
|
174
|
+
this.features.completionSnippets = true;
|
|
175
|
+
}
|
|
176
|
+
if (textDocument?.publishDiagnostics?.tagSupport) {
|
|
177
|
+
this.features.diagnosticsTagSupport = true;
|
|
203
178
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
179
|
+
}
|
|
180
|
+
this.configurationManager.mergeTsPreferences({
|
|
181
|
+
useLabelDetailsInCompletionEntries: this.features.completionLabelDetails,
|
|
182
|
+
});
|
|
183
|
+
this.diagnosticQueue = new DiagnosticEventQueue(diagnostics => this.options.lspClient.publishDiagnostics(diagnostics), this.documents, this.features, this.logger);
|
|
184
|
+
this._tspClient = new TspClient({
|
|
185
|
+
apiVersion: typescriptVersion.version || API.defaultVersion,
|
|
186
|
+
tsserverPath: typescriptVersion.tsServerPath,
|
|
187
|
+
logFile,
|
|
188
|
+
logVerbosity,
|
|
189
|
+
disableAutomaticTypingAcquisition,
|
|
190
|
+
maxTsServerMemory,
|
|
191
|
+
npmLocation,
|
|
192
|
+
locale,
|
|
193
|
+
globalPlugins,
|
|
194
|
+
pluginProbeLocations,
|
|
195
|
+
logger: this.options.logger,
|
|
196
|
+
onEvent: this.onTsEvent.bind(this),
|
|
197
|
+
onExit: (exitCode, signal) => {
|
|
198
|
+
if (exitCode) {
|
|
199
|
+
this.logger.error(`tsserver process has exited (exit code: ${exitCode}, signal: ${signal}). Stopping the server.`);
|
|
222
200
|
}
|
|
223
|
-
});
|
|
224
|
-
const started = this.tspClient.start();
|
|
225
|
-
if (!started) {
|
|
226
|
-
throw new Error('tsserver process has failed to start.');
|
|
227
|
-
}
|
|
228
|
-
process.on('exit', () => {
|
|
229
201
|
this.shutdown();
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
const started = this.tspClient.start();
|
|
205
|
+
if (!started) {
|
|
206
|
+
throw new Error('tsserver process has failed to start.');
|
|
207
|
+
}
|
|
208
|
+
process.on('exit', () => {
|
|
209
|
+
this.shutdown();
|
|
210
|
+
});
|
|
211
|
+
process.on('SIGINT', () => {
|
|
212
|
+
process.exit();
|
|
213
|
+
});
|
|
214
|
+
this.typeScriptAutoFixProvider = new TypeScriptAutoFixProvider(this.tspClient);
|
|
215
|
+
await Promise.all([
|
|
216
|
+
this.configurationManager.setAndConfigureTspClient(this._tspClient, hostInfo),
|
|
217
|
+
this.tspClient.request("compilerOptionsForInferredProjects" /* CommandTypes.CompilerOptionsForInferredProjects */, {
|
|
218
|
+
options: {
|
|
219
|
+
module: "CommonJS" /* tsp.ModuleKind.CommonJS */,
|
|
220
|
+
target: "ES2016" /* tsp.ScriptTarget.ES2016 */,
|
|
221
|
+
jsx: "Preserve" /* tsp.JsxEmit.Preserve */,
|
|
222
|
+
allowJs: true,
|
|
223
|
+
allowSyntheticDefaultImports: true,
|
|
224
|
+
allowNonTsExtensions: true,
|
|
225
|
+
},
|
|
226
|
+
}),
|
|
227
|
+
]);
|
|
228
|
+
const logFileUri = logFile && pathToUri(logFile, undefined);
|
|
229
|
+
const initializeResult = {
|
|
230
|
+
capabilities: {
|
|
231
|
+
textDocumentSync: lsp.TextDocumentSyncKind.Incremental,
|
|
232
|
+
completionProvider: {
|
|
233
|
+
triggerCharacters: ['.', '"', '\'', '/', '@', '<'],
|
|
234
|
+
resolveProvider: true,
|
|
235
|
+
},
|
|
236
|
+
codeActionProvider: clientCapabilities.textDocument?.codeAction?.codeActionLiteralSupport
|
|
237
|
+
? { codeActionKinds: [
|
|
238
|
+
...TypeScriptAutoFixProvider.kinds.map(kind => kind.value),
|
|
239
|
+
CodeActionKind.SourceOrganizeImportsTs.value,
|
|
240
|
+
CodeActionKind.QuickFix.value,
|
|
241
|
+
CodeActionKind.Refactor.value,
|
|
242
|
+
] } : true,
|
|
243
|
+
definitionProvider: true,
|
|
244
|
+
documentFormattingProvider: true,
|
|
245
|
+
documentRangeFormattingProvider: true,
|
|
246
|
+
documentHighlightProvider: true,
|
|
247
|
+
documentSymbolProvider: true,
|
|
248
|
+
executeCommandProvider: {
|
|
249
|
+
commands: [
|
|
250
|
+
Commands.APPLY_WORKSPACE_EDIT,
|
|
251
|
+
Commands.APPLY_CODE_ACTION,
|
|
252
|
+
Commands.APPLY_REFACTORING,
|
|
253
|
+
Commands.ORGANIZE_IMPORTS,
|
|
254
|
+
Commands.APPLY_RENAME_FILE,
|
|
255
|
+
Commands.SOURCE_DEFINITION,
|
|
256
|
+
],
|
|
257
|
+
},
|
|
258
|
+
hoverProvider: true,
|
|
259
|
+
inlayHintProvider: true,
|
|
260
|
+
renameProvider: true,
|
|
261
|
+
referencesProvider: true,
|
|
262
|
+
signatureHelpProvider: {
|
|
263
|
+
triggerCharacters: ['(', ',', '<'],
|
|
264
|
+
retriggerCharacters: [')'],
|
|
265
|
+
},
|
|
266
|
+
workspaceSymbolProvider: true,
|
|
267
|
+
implementationProvider: true,
|
|
268
|
+
typeDefinitionProvider: true,
|
|
269
|
+
foldingRangeProvider: true,
|
|
270
|
+
semanticTokensProvider: {
|
|
271
|
+
documentSelector: null,
|
|
272
|
+
legend: {
|
|
273
|
+
// list taken from: https://github.com/microsoft/TypeScript/blob/main/src/services/classifier2020.ts#L10
|
|
274
|
+
tokenTypes: [
|
|
275
|
+
'class',
|
|
276
|
+
'enum',
|
|
277
|
+
'interface',
|
|
278
|
+
'namespace',
|
|
279
|
+
'typeParameter',
|
|
280
|
+
'type',
|
|
281
|
+
'parameter',
|
|
282
|
+
'variable',
|
|
283
|
+
'enumMember',
|
|
284
|
+
'property',
|
|
285
|
+
'function',
|
|
286
|
+
'member',
|
|
287
|
+
],
|
|
288
|
+
// token from: https://github.com/microsoft/TypeScript/blob/main/src/services/classifier2020.ts#L14
|
|
289
|
+
tokenModifiers: [
|
|
290
|
+
'declaration',
|
|
291
|
+
'static',
|
|
292
|
+
'async',
|
|
293
|
+
'readonly',
|
|
294
|
+
'defaultLibrary',
|
|
295
|
+
'local',
|
|
296
|
+
],
|
|
285
297
|
},
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
typeDefinitionProvider: true,
|
|
289
|
-
foldingRangeProvider: true,
|
|
290
|
-
semanticTokensProvider: {
|
|
291
|
-
documentSelector: null,
|
|
292
|
-
legend: {
|
|
293
|
-
// list taken from: https://github.com/microsoft/TypeScript/blob/main/src/services/classifier2020.ts#L10
|
|
294
|
-
tokenTypes: [
|
|
295
|
-
'class',
|
|
296
|
-
'enum',
|
|
297
|
-
'interface',
|
|
298
|
-
'namespace',
|
|
299
|
-
'typeParameter',
|
|
300
|
-
'type',
|
|
301
|
-
'parameter',
|
|
302
|
-
'variable',
|
|
303
|
-
'enumMember',
|
|
304
|
-
'property',
|
|
305
|
-
'function',
|
|
306
|
-
'member'
|
|
307
|
-
],
|
|
308
|
-
// token from: https://github.com/microsoft/TypeScript/blob/main/src/services/classifier2020.ts#L14
|
|
309
|
-
tokenModifiers: [
|
|
310
|
-
'declaration',
|
|
311
|
-
'static',
|
|
312
|
-
'async',
|
|
313
|
-
'readonly',
|
|
314
|
-
'defaultLibrary',
|
|
315
|
-
'local'
|
|
316
|
-
]
|
|
317
|
-
},
|
|
318
|
-
full: true,
|
|
319
|
-
range: true
|
|
320
|
-
}
|
|
298
|
+
full: true,
|
|
299
|
+
range: true,
|
|
321
300
|
},
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
301
|
+
},
|
|
302
|
+
logFileUri,
|
|
303
|
+
};
|
|
304
|
+
initializeResult.capabilities.callsProvider = true;
|
|
305
|
+
this.logger.log('onInitialize result', initializeResult);
|
|
306
|
+
return initializeResult;
|
|
328
307
|
}
|
|
329
308
|
getLogFile(logVerbosity) {
|
|
330
309
|
if (logVerbosity === undefined || logVerbosity === 'off') {
|
|
@@ -350,19 +329,9 @@ export class LspServer {
|
|
|
350
329
|
return undefined;
|
|
351
330
|
}
|
|
352
331
|
didChangeConfiguration(params) {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
(_b = this.diagnosticQueue) === null || _b === void 0 ? void 0 : _b.updateIgnoredDiagnosticCodes(ignoredDiagnosticCodes);
|
|
357
|
-
}
|
|
358
|
-
getWorkspacePreferencesForDocument(file) {
|
|
359
|
-
var _a;
|
|
360
|
-
const doc = this.documents.get(file);
|
|
361
|
-
if (!doc) {
|
|
362
|
-
return {};
|
|
363
|
-
}
|
|
364
|
-
const preferencesKey = doc.languageId.startsWith('typescript') ? 'typescript' : 'javascript';
|
|
365
|
-
return (_a = this.workspaceConfiguration[preferencesKey]) !== null && _a !== void 0 ? _a : {};
|
|
332
|
+
this.configurationManager.setWorkspaceConfiguration(params.settings || {});
|
|
333
|
+
const ignoredDiagnosticCodes = this.configurationManager.workspaceConfiguration.diagnostics?.ignoredCodes || [];
|
|
334
|
+
this.diagnosticQueue?.updateIgnoredDiagnosticCodes(ignoredDiagnosticCodes);
|
|
366
335
|
}
|
|
367
336
|
interuptDiagnostics(f) {
|
|
368
337
|
if (!this.diagnosticsTokenSource) {
|
|
@@ -373,28 +342,24 @@ export class LspServer {
|
|
|
373
342
|
this.requestDiagnostics();
|
|
374
343
|
return result;
|
|
375
344
|
}
|
|
376
|
-
requestDiagnostics() {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
yield this.doRequestDiagnosticsDebounced();
|
|
380
|
-
});
|
|
345
|
+
async requestDiagnostics() {
|
|
346
|
+
this.pendingDebouncedRequest = true;
|
|
347
|
+
await this.doRequestDiagnosticsDebounced();
|
|
381
348
|
}
|
|
382
|
-
doRequestDiagnostics() {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
this.pendingDebouncedRequest = false;
|
|
395
|
-
}
|
|
349
|
+
async doRequestDiagnostics() {
|
|
350
|
+
this.cancelDiagnostics();
|
|
351
|
+
const geterrTokenSource = new lsp.CancellationTokenSource();
|
|
352
|
+
this.diagnosticsTokenSource = geterrTokenSource;
|
|
353
|
+
const { files } = this.documents;
|
|
354
|
+
try {
|
|
355
|
+
return await this.tspClient.request("geterr" /* CommandTypes.Geterr */, { delay: 0, files }, this.diagnosticsTokenSource.token);
|
|
356
|
+
}
|
|
357
|
+
finally {
|
|
358
|
+
if (this.diagnosticsTokenSource === geterrTokenSource) {
|
|
359
|
+
this.diagnosticsTokenSource = undefined;
|
|
360
|
+
this.pendingDebouncedRequest = false;
|
|
396
361
|
}
|
|
397
|
-
}
|
|
362
|
+
}
|
|
398
363
|
}
|
|
399
364
|
cancelDiagnostics() {
|
|
400
365
|
if (this.diagnosticsTokenSource) {
|
|
@@ -412,7 +377,7 @@ export class LspServer {
|
|
|
412
377
|
file,
|
|
413
378
|
fileContent: params.textDocument.text,
|
|
414
379
|
scriptKindName: this.getScriptKindName(params.textDocument.languageId),
|
|
415
|
-
projectRootPath: this.workspaceRoot
|
|
380
|
+
projectRootPath: this.workspaceRoot,
|
|
416
381
|
});
|
|
417
382
|
this.requestDiagnostics();
|
|
418
383
|
}
|
|
@@ -422,9 +387,9 @@ export class LspServer {
|
|
|
422
387
|
textDocument: params.textDocument,
|
|
423
388
|
contentChanges: [
|
|
424
389
|
{
|
|
425
|
-
text: params.textDocument.text
|
|
426
|
-
}
|
|
427
|
-
]
|
|
390
|
+
text: params.textDocument.text,
|
|
391
|
+
},
|
|
392
|
+
],
|
|
428
393
|
});
|
|
429
394
|
}
|
|
430
395
|
}
|
|
@@ -455,7 +420,7 @@ export class LspServer {
|
|
|
455
420
|
// so we don't leave stale ones.
|
|
456
421
|
this.options.lspClient.publishDiagnostics({
|
|
457
422
|
uri: document.uri,
|
|
458
|
-
diagnostics: []
|
|
423
|
+
diagnostics: [],
|
|
459
424
|
});
|
|
460
425
|
}
|
|
461
426
|
didChangeTextDocument(params) {
|
|
@@ -497,7 +462,7 @@ export class LspServer {
|
|
|
497
462
|
offset,
|
|
498
463
|
endLine,
|
|
499
464
|
endOffset,
|
|
500
|
-
insertString: change.text
|
|
465
|
+
insertString: change.text,
|
|
501
466
|
});
|
|
502
467
|
document.applyEdit(textDocument.version, change);
|
|
503
468
|
}
|
|
@@ -506,76 +471,95 @@ export class LspServer {
|
|
|
506
471
|
didSaveTextDocument(_params) {
|
|
507
472
|
// do nothing
|
|
508
473
|
}
|
|
509
|
-
definition(params) {
|
|
510
|
-
return
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
type: 'definition',
|
|
514
|
-
params
|
|
515
|
-
});
|
|
474
|
+
async definition(params) {
|
|
475
|
+
return this.getDefinition({
|
|
476
|
+
type: this.features.definitionLinkSupport ? "definitionAndBoundSpan" /* CommandTypes.DefinitionAndBoundSpan */ : "definition" /* CommandTypes.Definition */,
|
|
477
|
+
params,
|
|
516
478
|
});
|
|
517
479
|
}
|
|
518
|
-
implementation(params) {
|
|
519
|
-
return
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
params
|
|
523
|
-
});
|
|
480
|
+
async implementation(params) {
|
|
481
|
+
return this.getSymbolLocations({
|
|
482
|
+
type: "implementation" /* CommandTypes.Implementation */,
|
|
483
|
+
params,
|
|
524
484
|
});
|
|
525
485
|
}
|
|
526
|
-
typeDefinition(params) {
|
|
527
|
-
return
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
params
|
|
531
|
-
});
|
|
486
|
+
async typeDefinition(params) {
|
|
487
|
+
return this.getSymbolLocations({
|
|
488
|
+
type: "typeDefinition" /* CommandTypes.TypeDefinition */,
|
|
489
|
+
params,
|
|
532
490
|
});
|
|
533
491
|
}
|
|
534
|
-
getDefinition({ type, params }) {
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
492
|
+
async getDefinition({ type, params }) {
|
|
493
|
+
const file = uriToPath(params.textDocument.uri);
|
|
494
|
+
this.logger.log(type, params, file);
|
|
495
|
+
if (!file) {
|
|
496
|
+
return undefined;
|
|
497
|
+
}
|
|
498
|
+
if (type === "definitionAndBoundSpan" /* CommandTypes.DefinitionAndBoundSpan */) {
|
|
499
|
+
const args = Position.toFileLocationRequestArgs(file, params.position);
|
|
500
|
+
const response = await this.tspClient.request(type, args);
|
|
501
|
+
if (response.type !== 'response' || !response.body) {
|
|
502
|
+
return undefined;
|
|
540
503
|
}
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
504
|
+
// `textSpan` can be undefined in older TypeScript versions, despite type saying otherwise.
|
|
505
|
+
const span = response.body.textSpan ? Range.fromTextSpan(response.body.textSpan) : undefined;
|
|
506
|
+
return response.body.definitions
|
|
507
|
+
.map((location) => {
|
|
508
|
+
const target = toLocation(location, this.documents);
|
|
509
|
+
const targetRange = location.contextStart && location.contextEnd
|
|
510
|
+
? Range.fromLocations(location.contextStart, location.contextEnd)
|
|
511
|
+
: target.range;
|
|
512
|
+
return {
|
|
513
|
+
originSelectionRange: span,
|
|
514
|
+
targetRange,
|
|
515
|
+
targetUri: target.uri,
|
|
516
|
+
targetSelectionRange: target.range,
|
|
517
|
+
};
|
|
545
518
|
});
|
|
546
|
-
|
|
547
|
-
});
|
|
519
|
+
}
|
|
520
|
+
return this.getSymbolLocations({ type: "definition" /* CommandTypes.Definition */, params });
|
|
548
521
|
}
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
522
|
+
async getSymbolLocations({ type, params }) {
|
|
523
|
+
const file = uriToPath(params.textDocument.uri);
|
|
524
|
+
this.logger.log(type, params, file);
|
|
525
|
+
if (!file) {
|
|
526
|
+
return [];
|
|
527
|
+
}
|
|
528
|
+
const args = Position.toFileLocationRequestArgs(file, params.position);
|
|
529
|
+
const response = await this.tspClient.request(type, args);
|
|
530
|
+
if (response.type !== 'response' || !response.body) {
|
|
531
|
+
return undefined;
|
|
532
|
+
}
|
|
533
|
+
return response.body.map(fileSpan => toLocation(fileSpan, this.documents));
|
|
534
|
+
}
|
|
535
|
+
async documentSymbol(params) {
|
|
536
|
+
const file = uriToPath(params.textDocument.uri);
|
|
537
|
+
this.logger.log('symbol', params, file);
|
|
538
|
+
if (!file) {
|
|
539
|
+
return [];
|
|
540
|
+
}
|
|
541
|
+
const response = await this.tspClient.request("navtree" /* CommandTypes.NavTree */, {
|
|
542
|
+
file,
|
|
543
|
+
});
|
|
544
|
+
const tree = response.body;
|
|
545
|
+
if (!tree || !tree.childItems) {
|
|
546
|
+
return [];
|
|
547
|
+
}
|
|
548
|
+
if (this.supportHierarchicalDocumentSymbol) {
|
|
570
549
|
const symbols = [];
|
|
571
550
|
for (const item of tree.childItems) {
|
|
572
|
-
|
|
551
|
+
collectDocumentSymbols(item, symbols);
|
|
573
552
|
}
|
|
574
553
|
return symbols;
|
|
575
|
-
}
|
|
554
|
+
}
|
|
555
|
+
const symbols = [];
|
|
556
|
+
for (const item of tree.childItems) {
|
|
557
|
+
collectSymbolInformation(params.textDocument.uri, item, symbols);
|
|
558
|
+
}
|
|
559
|
+
return symbols;
|
|
576
560
|
}
|
|
577
561
|
get supportHierarchicalDocumentSymbol() {
|
|
578
|
-
const textDocument = this.initializeParams
|
|
562
|
+
const textDocument = this.initializeParams?.capabilities.textDocument;
|
|
579
563
|
const documentSymbol = textDocument && textDocument.documentSymbol;
|
|
580
564
|
return !!documentSymbol && !!documentSymbol.hierarchicalDocumentSymbolSupport;
|
|
581
565
|
}
|
|
@@ -583,541 +567,477 @@ export class LspServer {
|
|
|
583
567
|
* implemented based on
|
|
584
568
|
* https://github.com/Microsoft/vscode/blob/master/extensions/typescript-language-features/src/features/completions.ts
|
|
585
569
|
*/
|
|
586
|
-
completion(params) {
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
const completions = (body ? body.entries : [])
|
|
610
|
-
.filter(entry => entry.kind !== 'warning')
|
|
611
|
-
.map(entry => asCompletionItem(entry, file, params.position, document, this.features));
|
|
612
|
-
return lsp.CompletionList.create(completions, body === null || body === void 0 ? void 0 : body.isIncomplete);
|
|
613
|
-
}
|
|
614
|
-
catch (error) {
|
|
615
|
-
if (error.message === 'No content available.') {
|
|
616
|
-
this.logger.info('No content was available for completion request');
|
|
617
|
-
return null;
|
|
570
|
+
async completion(params) {
|
|
571
|
+
const file = uriToPath(params.textDocument.uri);
|
|
572
|
+
this.logger.log('completion', params, file);
|
|
573
|
+
if (!file) {
|
|
574
|
+
return lsp.CompletionList.create([]);
|
|
575
|
+
}
|
|
576
|
+
const document = this.documents.get(file);
|
|
577
|
+
if (!document) {
|
|
578
|
+
throw new Error('The document should be opened for completion, file: ' + file);
|
|
579
|
+
}
|
|
580
|
+
try {
|
|
581
|
+
const result = await this.interuptDiagnostics(() => this.tspClient.request("completionInfo" /* CommandTypes.CompletionInfo */, {
|
|
582
|
+
file,
|
|
583
|
+
line: params.position.line + 1,
|
|
584
|
+
offset: params.position.character + 1,
|
|
585
|
+
triggerCharacter: getCompletionTriggerCharacter(params.context?.triggerCharacter),
|
|
586
|
+
triggerKind: params.context?.triggerKind,
|
|
587
|
+
}));
|
|
588
|
+
const { body } = result;
|
|
589
|
+
const completions = [];
|
|
590
|
+
for (const entry of body?.entries ?? []) {
|
|
591
|
+
if (entry.kind === 'warning') {
|
|
592
|
+
continue;
|
|
618
593
|
}
|
|
619
|
-
|
|
620
|
-
|
|
594
|
+
const completion = asCompletionItem(entry, file, params.position, document, this.features);
|
|
595
|
+
if (!completion) {
|
|
596
|
+
continue;
|
|
621
597
|
}
|
|
598
|
+
completions.push(completion);
|
|
622
599
|
}
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
formatOptions: this.getWorkspacePreferencesForDocument(item.data.file).format
|
|
630
|
-
});
|
|
631
|
-
const { body } = yield this.interuptDiagnostics(() => this.tspClient.request("completionEntryDetails" /* CommandTypes.CompletionDetails */, item.data));
|
|
632
|
-
const details = body && body.length && body[0];
|
|
633
|
-
if (!details) {
|
|
634
|
-
return item;
|
|
635
|
-
}
|
|
636
|
-
return asResolvedCompletionItem(item, details, this.tspClient, this.workspaceConfiguration.completions || {});
|
|
637
|
-
});
|
|
638
|
-
}
|
|
639
|
-
hover(params) {
|
|
640
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
641
|
-
const file = uriToPath(params.textDocument.uri);
|
|
642
|
-
this.logger.log('hover', params, file);
|
|
643
|
-
if (!file) {
|
|
644
|
-
return { contents: [] };
|
|
645
|
-
}
|
|
646
|
-
const result = yield this.interuptDiagnostics(() => this.getQuickInfo(file, params.position));
|
|
647
|
-
if (!result || !result.body) {
|
|
648
|
-
return { contents: [] };
|
|
600
|
+
return lsp.CompletionList.create(completions, body?.isIncomplete);
|
|
601
|
+
}
|
|
602
|
+
catch (error) {
|
|
603
|
+
if (error.message === 'No content available.') {
|
|
604
|
+
this.logger.info('No content was available for completion request');
|
|
605
|
+
return null;
|
|
649
606
|
}
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
if (result.body.displayString) {
|
|
653
|
-
contents.push({ language: 'typescript', value: result.body.displayString });
|
|
607
|
+
else {
|
|
608
|
+
throw error;
|
|
654
609
|
}
|
|
655
|
-
|
|
656
|
-
const documentation = asPlainText(result.body.documentation);
|
|
657
|
-
contents.push(documentation + (tags ? '\n\n' + tags : ''));
|
|
658
|
-
return {
|
|
659
|
-
contents,
|
|
660
|
-
range
|
|
661
|
-
};
|
|
662
|
-
});
|
|
610
|
+
}
|
|
663
611
|
}
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
catch (err) {
|
|
674
|
-
return undefined;
|
|
675
|
-
}
|
|
676
|
-
});
|
|
612
|
+
async completionResolve(item) {
|
|
613
|
+
this.logger.log('completion/resolve', item);
|
|
614
|
+
await this.configurationManager.configureGloballyFromDocument(item.data.file);
|
|
615
|
+
const { body } = await this.interuptDiagnostics(() => this.tspClient.request("completionEntryDetails" /* CommandTypes.CompletionDetails */, item.data));
|
|
616
|
+
const details = body && body.length && body[0];
|
|
617
|
+
if (!details) {
|
|
618
|
+
return item;
|
|
619
|
+
}
|
|
620
|
+
return asResolvedCompletionItem(item, details, this.tspClient, this.configurationManager.workspaceConfiguration.completions || {}, this.features);
|
|
677
621
|
}
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
622
|
+
async hover(params) {
|
|
623
|
+
const file = uriToPath(params.textDocument.uri);
|
|
624
|
+
this.logger.log('hover', params, file);
|
|
625
|
+
if (!file) {
|
|
626
|
+
return { contents: [] };
|
|
627
|
+
}
|
|
628
|
+
const result = await this.interuptDiagnostics(() => this.getQuickInfo(file, params.position));
|
|
629
|
+
if (!result || !result.body) {
|
|
630
|
+
return { contents: [] };
|
|
631
|
+
}
|
|
632
|
+
const range = Range.fromTextSpan(result.body);
|
|
633
|
+
const contents = [];
|
|
634
|
+
if (result.body.displayString) {
|
|
635
|
+
contents.push({ language: 'typescript', value: result.body.displayString });
|
|
636
|
+
}
|
|
637
|
+
const tags = asTagsDocumentation(result.body.tags);
|
|
638
|
+
const documentation = asPlainText(result.body.documentation);
|
|
639
|
+
contents.push(documentation + (tags ? '\n\n' + tags : ''));
|
|
640
|
+
return {
|
|
641
|
+
contents,
|
|
642
|
+
range,
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
async getQuickInfo(file, position) {
|
|
646
|
+
try {
|
|
647
|
+
return await this.tspClient.request("quickinfo" /* CommandTypes.Quickinfo */, {
|
|
686
648
|
file,
|
|
687
|
-
line:
|
|
688
|
-
offset:
|
|
649
|
+
line: position.line + 1,
|
|
650
|
+
offset: position.character + 1,
|
|
689
651
|
});
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
652
|
+
}
|
|
653
|
+
catch (err) {
|
|
654
|
+
return undefined;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
async rename(params) {
|
|
658
|
+
const file = uriToPath(params.textDocument.uri);
|
|
659
|
+
this.logger.log('onRename', params, file);
|
|
660
|
+
if (!file) {
|
|
661
|
+
return undefined;
|
|
662
|
+
}
|
|
663
|
+
const result = await this.tspClient.request("rename" /* CommandTypes.Rename */, {
|
|
664
|
+
file,
|
|
665
|
+
line: params.position.line + 1,
|
|
666
|
+
offset: params.position.character + 1,
|
|
667
|
+
});
|
|
668
|
+
if (!result.body || !result.body.info.canRename || result.body.locs.length === 0) {
|
|
669
|
+
return undefined;
|
|
670
|
+
}
|
|
671
|
+
const workspaceEdit = {};
|
|
672
|
+
result.body.locs
|
|
673
|
+
.forEach((spanGroup) => {
|
|
674
|
+
const uri = pathToUri(spanGroup.file, this.documents);
|
|
675
|
+
if (!workspaceEdit.changes) {
|
|
676
|
+
workspaceEdit.changes = {};
|
|
677
|
+
}
|
|
678
|
+
const textEdits = workspaceEdit.changes[uri] || (workspaceEdit.changes[uri] = []);
|
|
679
|
+
spanGroup.locs.forEach((textSpan) => {
|
|
680
|
+
textEdits.push({
|
|
681
|
+
newText: `${textSpan.prefixText || ''}${params.newName}${textSpan.suffixText || ''}`,
|
|
682
|
+
range: {
|
|
683
|
+
start: Position.fromLocation(textSpan.start),
|
|
684
|
+
end: Position.fromLocation(textSpan.end),
|
|
685
|
+
},
|
|
707
686
|
});
|
|
708
687
|
});
|
|
709
|
-
return workspaceEdit;
|
|
710
688
|
});
|
|
689
|
+
return workspaceEdit;
|
|
711
690
|
}
|
|
712
|
-
references(params) {
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
offset: params.position.character + 1
|
|
723
|
-
});
|
|
724
|
-
if (!result.body) {
|
|
725
|
-
return [];
|
|
726
|
-
}
|
|
727
|
-
return result.body.refs
|
|
728
|
-
.filter(fileSpan => params.context.includeDeclaration || !fileSpan.isDefinition)
|
|
729
|
-
.map(fileSpan => toLocation(fileSpan, this.documents));
|
|
691
|
+
async references(params) {
|
|
692
|
+
const file = uriToPath(params.textDocument.uri);
|
|
693
|
+
this.logger.log('onReferences', params, file);
|
|
694
|
+
if (!file) {
|
|
695
|
+
return [];
|
|
696
|
+
}
|
|
697
|
+
const result = await this.tspClient.request("references" /* CommandTypes.References */, {
|
|
698
|
+
file,
|
|
699
|
+
line: params.position.line + 1,
|
|
700
|
+
offset: params.position.character + 1,
|
|
730
701
|
});
|
|
702
|
+
if (!result.body) {
|
|
703
|
+
return [];
|
|
704
|
+
}
|
|
705
|
+
return result.body.refs
|
|
706
|
+
.filter(fileSpan => params.context.includeDeclaration || !fileSpan.isDefinition)
|
|
707
|
+
.map(fileSpan => toLocation(fileSpan, this.documents));
|
|
731
708
|
}
|
|
732
|
-
documentFormatting(params) {
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
if (!file) {
|
|
737
|
-
return [];
|
|
738
|
-
}
|
|
739
|
-
const formatOptions = this.getFormattingOptions(file, params.options);
|
|
740
|
-
// options are not yet supported in tsserver, but we can send a configure request first
|
|
741
|
-
yield this.tspClient.request("configure" /* CommandTypes.Configure */, {
|
|
742
|
-
formatOptions
|
|
743
|
-
});
|
|
744
|
-
const response = yield this.tspClient.request("format" /* CommandTypes.Format */, {
|
|
745
|
-
file,
|
|
746
|
-
line: 1,
|
|
747
|
-
offset: 1,
|
|
748
|
-
endLine: Number.MAX_SAFE_INTEGER,
|
|
749
|
-
endOffset: Number.MAX_SAFE_INTEGER,
|
|
750
|
-
options: formatOptions
|
|
751
|
-
});
|
|
752
|
-
if (response.body) {
|
|
753
|
-
return response.body.map(e => toTextEdit(e));
|
|
754
|
-
}
|
|
709
|
+
async documentFormatting(params) {
|
|
710
|
+
const file = uriToPath(params.textDocument.uri);
|
|
711
|
+
this.logger.log('documentFormatting', params, file);
|
|
712
|
+
if (!file) {
|
|
755
713
|
return [];
|
|
714
|
+
}
|
|
715
|
+
const formatOptions = params.options;
|
|
716
|
+
await this.configurationManager.configureGloballyFromDocument(file, formatOptions);
|
|
717
|
+
const response = await this.tspClient.request("format" /* CommandTypes.Format */, {
|
|
718
|
+
file,
|
|
719
|
+
line: 1,
|
|
720
|
+
offset: 1,
|
|
721
|
+
endLine: Number.MAX_SAFE_INTEGER,
|
|
722
|
+
endOffset: Number.MAX_SAFE_INTEGER,
|
|
723
|
+
options: formatOptions,
|
|
756
724
|
});
|
|
725
|
+
if (response.body) {
|
|
726
|
+
return response.body.map(e => toTextEdit(e));
|
|
727
|
+
}
|
|
728
|
+
return [];
|
|
757
729
|
}
|
|
758
|
-
documentRangeFormatting(params) {
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
if (!file) {
|
|
763
|
-
return [];
|
|
764
|
-
}
|
|
765
|
-
const formatOptions = this.getFormattingOptions(file, params.options);
|
|
766
|
-
// options are not yet supported in tsserver, but we can send a configure request first
|
|
767
|
-
yield this.tspClient.request("configure" /* CommandTypes.Configure */, {
|
|
768
|
-
formatOptions
|
|
769
|
-
});
|
|
770
|
-
const response = yield this.tspClient.request("format" /* CommandTypes.Format */, {
|
|
771
|
-
file,
|
|
772
|
-
line: params.range.start.line + 1,
|
|
773
|
-
offset: params.range.start.character + 1,
|
|
774
|
-
endLine: params.range.end.line + 1,
|
|
775
|
-
endOffset: params.range.end.character + 1,
|
|
776
|
-
options: formatOptions
|
|
777
|
-
});
|
|
778
|
-
if (response.body) {
|
|
779
|
-
return response.body.map(e => toTextEdit(e));
|
|
780
|
-
}
|
|
730
|
+
async documentRangeFormatting(params) {
|
|
731
|
+
const file = uriToPath(params.textDocument.uri);
|
|
732
|
+
this.logger.log('documentRangeFormatting', params, file);
|
|
733
|
+
if (!file) {
|
|
781
734
|
return [];
|
|
735
|
+
}
|
|
736
|
+
const formatOptions = params.options;
|
|
737
|
+
await this.configurationManager.configureGloballyFromDocument(file, formatOptions);
|
|
738
|
+
const response = await this.tspClient.request("format" /* CommandTypes.Format */, {
|
|
739
|
+
file,
|
|
740
|
+
line: params.range.start.line + 1,
|
|
741
|
+
offset: params.range.start.character + 1,
|
|
742
|
+
endLine: params.range.end.line + 1,
|
|
743
|
+
endOffset: params.range.end.character + 1,
|
|
744
|
+
options: formatOptions,
|
|
782
745
|
});
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
const workspacePreference = this.getWorkspacePreferencesForDocument(file);
|
|
786
|
-
let opts = Object.assign(Object.assign({}, (workspacePreference === null || workspacePreference === void 0 ? void 0 : workspacePreference.format) || {}), requestOptions);
|
|
787
|
-
// translate
|
|
788
|
-
if (opts.convertTabsToSpaces === undefined) {
|
|
789
|
-
opts.convertTabsToSpaces = requestOptions.insertSpaces;
|
|
746
|
+
if (response.body) {
|
|
747
|
+
return response.body.map(e => toTextEdit(e));
|
|
790
748
|
}
|
|
791
|
-
|
|
792
|
-
|
|
749
|
+
return [];
|
|
750
|
+
}
|
|
751
|
+
async signatureHelp(params) {
|
|
752
|
+
const file = uriToPath(params.textDocument.uri);
|
|
753
|
+
this.logger.log('signatureHelp', params, file);
|
|
754
|
+
if (!file) {
|
|
755
|
+
return undefined;
|
|
793
756
|
}
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
}
|
|
798
|
-
catch (err) {
|
|
799
|
-
this.logger.log(`No formatting options found ${err}`);
|
|
800
|
-
}
|
|
757
|
+
const response = await this.interuptDiagnostics(() => this.getSignatureHelp(file, params));
|
|
758
|
+
if (!response || !response.body) {
|
|
759
|
+
return undefined;
|
|
801
760
|
}
|
|
802
|
-
return
|
|
803
|
-
}
|
|
804
|
-
signatureHelp(params) {
|
|
805
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
806
|
-
const file = uriToPath(params.textDocument.uri);
|
|
807
|
-
this.logger.log('signatureHelp', params, file);
|
|
808
|
-
if (!file) {
|
|
809
|
-
return undefined;
|
|
810
|
-
}
|
|
811
|
-
const response = yield this.interuptDiagnostics(() => this.getSignatureHelp(file, params.position));
|
|
812
|
-
if (!response || !response.body) {
|
|
813
|
-
return undefined;
|
|
814
|
-
}
|
|
815
|
-
return asSignatureHelp(response.body);
|
|
816
|
-
});
|
|
761
|
+
return asSignatureHelp(response.body, params.context);
|
|
817
762
|
}
|
|
818
|
-
getSignatureHelp(file,
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
}
|
|
763
|
+
async getSignatureHelp(file, params) {
|
|
764
|
+
try {
|
|
765
|
+
const { position, context } = params;
|
|
766
|
+
return await this.tspClient.request("signatureHelp" /* CommandTypes.SignatureHelp */, {
|
|
767
|
+
file,
|
|
768
|
+
line: position.line + 1,
|
|
769
|
+
offset: position.character + 1,
|
|
770
|
+
triggerReason: context ? toTsTriggerReason(context) : undefined,
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
catch (err) {
|
|
774
|
+
return undefined;
|
|
775
|
+
}
|
|
831
776
|
}
|
|
832
|
-
codeAction(params) {
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
const
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
//
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
if (
|
|
869
|
-
|
|
870
|
-
if (diagnostics.length) {
|
|
871
|
-
actions.push(...yield this.typeScriptAutoFixProvider.provideCodeActions(kinds, file, diagnostics, this.documents));
|
|
872
|
-
}
|
|
777
|
+
async codeAction(params) {
|
|
778
|
+
const file = uriToPath(params.textDocument.uri);
|
|
779
|
+
this.logger.log('codeAction', params, file);
|
|
780
|
+
if (!file) {
|
|
781
|
+
return [];
|
|
782
|
+
}
|
|
783
|
+
const args = Range.toFileRangeRequestArgs(file, params.range);
|
|
784
|
+
const actions = [];
|
|
785
|
+
const kinds = params.context.only?.map(kind => new CodeActionKind(kind));
|
|
786
|
+
if (!kinds || kinds.some(kind => kind.contains(CodeActionKind.QuickFix))) {
|
|
787
|
+
const errorCodes = params.context.diagnostics.map(diagnostic => Number(diagnostic.code));
|
|
788
|
+
actions.push(...provideQuickFix(await this.getCodeFixes({ ...args, errorCodes }), this.documents));
|
|
789
|
+
}
|
|
790
|
+
if (!kinds || kinds.some(kind => kind.contains(CodeActionKind.Refactor))) {
|
|
791
|
+
actions.push(...provideRefactors(await this.getRefactors(args), args));
|
|
792
|
+
}
|
|
793
|
+
// organize import is provided by tsserver for any line, so we only get it if explicitly requested
|
|
794
|
+
if (kinds?.some(kind => kind.contains(CodeActionKind.SourceOrganizeImportsTs))) {
|
|
795
|
+
// see this issue for more context about how this argument is used
|
|
796
|
+
// https://github.com/microsoft/TypeScript/issues/43051
|
|
797
|
+
const skipDestructiveCodeActions = params.context.diagnostics.some(
|
|
798
|
+
// assume no severity is an error
|
|
799
|
+
d => (d.severity ?? 0) <= 2);
|
|
800
|
+
const response = await this.getOrganizeImports({
|
|
801
|
+
scope: { type: 'file', args },
|
|
802
|
+
skipDestructiveCodeActions,
|
|
803
|
+
});
|
|
804
|
+
actions.push(...provideOrganizeImports(response, this.documents));
|
|
805
|
+
}
|
|
806
|
+
// TODO: Since we rely on diagnostics pointing at errors in the correct places, we can't proceed if we are not
|
|
807
|
+
// sure that diagnostics are up-to-date. Thus we check `pendingDebouncedRequest` to see if there are *any*
|
|
808
|
+
// pending diagnostic requests (regardless of for which file).
|
|
809
|
+
// In general would be better to replace the whole diagnostics handling logic with the one from
|
|
810
|
+
// bufferSyncSupport.ts in VSCode's typescript language features.
|
|
811
|
+
if (kinds && !this.pendingDebouncedRequest) {
|
|
812
|
+
const diagnostics = this.diagnosticQueue?.getDiagnosticsForFile(file) || [];
|
|
813
|
+
if (diagnostics.length) {
|
|
814
|
+
actions.push(...await this.typeScriptAutoFixProvider.provideCodeActions(kinds, file, diagnostics, this.documents));
|
|
873
815
|
}
|
|
874
|
-
|
|
875
|
-
|
|
816
|
+
}
|
|
817
|
+
return actions;
|
|
876
818
|
}
|
|
877
|
-
getCodeFixes(args) {
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
}
|
|
885
|
-
});
|
|
819
|
+
async getCodeFixes(args) {
|
|
820
|
+
try {
|
|
821
|
+
return await this.tspClient.request("getCodeFixes" /* CommandTypes.GetCodeFixes */, args);
|
|
822
|
+
}
|
|
823
|
+
catch (err) {
|
|
824
|
+
return undefined;
|
|
825
|
+
}
|
|
886
826
|
}
|
|
887
|
-
getRefactors(args) {
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
}
|
|
895
|
-
});
|
|
827
|
+
async getRefactors(args) {
|
|
828
|
+
try {
|
|
829
|
+
return await this.tspClient.request("getApplicableRefactors" /* CommandTypes.GetApplicableRefactors */, args);
|
|
830
|
+
}
|
|
831
|
+
catch (err) {
|
|
832
|
+
return undefined;
|
|
833
|
+
}
|
|
896
834
|
}
|
|
897
|
-
getOrganizeImports(args) {
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
}
|
|
906
|
-
catch (err) {
|
|
907
|
-
return undefined;
|
|
908
|
-
}
|
|
909
|
-
});
|
|
835
|
+
async getOrganizeImports(args) {
|
|
836
|
+
try {
|
|
837
|
+
await this.configurationManager.configureGloballyFromDocument(args.scope.args.file);
|
|
838
|
+
return await this.tspClient.request("organizeImports" /* CommandTypes.OrganizeImports */, args);
|
|
839
|
+
}
|
|
840
|
+
catch (err) {
|
|
841
|
+
return undefined;
|
|
842
|
+
}
|
|
910
843
|
}
|
|
911
|
-
executeCommand(arg) {
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
if (codeAction.commands && codeAction.commands.length) {
|
|
926
|
-
for (const command of codeAction.commands) {
|
|
927
|
-
yield this.tspClient.request("applyCodeActionCommand" /* CommandTypes.ApplyCodeActionCommand */, { command });
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
|
-
}
|
|
931
|
-
else if (arg.command === Commands.APPLY_REFACTORING && arg.arguments) {
|
|
932
|
-
const args = arg.arguments[0];
|
|
933
|
-
const { body } = yield this.tspClient.request("getEditsForRefactor" /* CommandTypes.GetEditsForRefactor */, args);
|
|
934
|
-
if (!body || !body.edits.length) {
|
|
935
|
-
return;
|
|
936
|
-
}
|
|
937
|
-
for (const edit of body.edits) {
|
|
938
|
-
yield fs.ensureFile(edit.fileName);
|
|
939
|
-
}
|
|
940
|
-
if (!(yield this.applyFileCodeEdits(body.edits))) {
|
|
941
|
-
return;
|
|
942
|
-
}
|
|
943
|
-
const renameLocation = body.renameLocation;
|
|
944
|
-
if (renameLocation) {
|
|
945
|
-
yield this.options.lspClient.rename({
|
|
946
|
-
textDocument: {
|
|
947
|
-
uri: pathToUri(args.file, this.documents)
|
|
948
|
-
},
|
|
949
|
-
position: toPosition(renameLocation)
|
|
950
|
-
});
|
|
844
|
+
async executeCommand(arg, token, workDoneProgress) {
|
|
845
|
+
this.logger.log('executeCommand', arg);
|
|
846
|
+
if (arg.command === Commands.APPLY_WORKSPACE_EDIT && arg.arguments) {
|
|
847
|
+
const edit = arg.arguments[0];
|
|
848
|
+
await this.options.lspClient.applyWorkspaceEdit({ edit });
|
|
849
|
+
}
|
|
850
|
+
else if (arg.command === Commands.APPLY_CODE_ACTION && arg.arguments) {
|
|
851
|
+
const codeAction = arg.arguments[0];
|
|
852
|
+
if (!await this.applyFileCodeEdits(codeAction.changes)) {
|
|
853
|
+
return;
|
|
854
|
+
}
|
|
855
|
+
if (codeAction.commands && codeAction.commands.length) {
|
|
856
|
+
for (const command of codeAction.commands) {
|
|
857
|
+
await this.tspClient.request("applyCodeActionCommand" /* CommandTypes.ApplyCodeActionCommand */, { command });
|
|
951
858
|
}
|
|
952
859
|
}
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
860
|
+
}
|
|
861
|
+
else if (arg.command === Commands.APPLY_REFACTORING && arg.arguments) {
|
|
862
|
+
const args = arg.arguments[0];
|
|
863
|
+
const { body } = await this.tspClient.request("getEditsForRefactor" /* CommandTypes.GetEditsForRefactor */, args);
|
|
864
|
+
if (!body || !body.edits.length) {
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
for (const edit of body.edits) {
|
|
868
|
+
await fs.ensureFile(edit.fileName);
|
|
869
|
+
}
|
|
870
|
+
if (!await this.applyFileCodeEdits(body.edits)) {
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
const renameLocation = body.renameLocation;
|
|
874
|
+
if (renameLocation) {
|
|
875
|
+
await this.options.lspClient.rename({
|
|
876
|
+
textDocument: {
|
|
877
|
+
uri: pathToUri(args.file, this.documents),
|
|
963
878
|
},
|
|
964
|
-
|
|
879
|
+
position: Position.fromLocation(renameLocation),
|
|
965
880
|
});
|
|
966
|
-
yield this.applyFileCodeEdits(body);
|
|
967
|
-
}
|
|
968
|
-
else if (arg.command === Commands.APPLY_RENAME_FILE && arg.arguments) {
|
|
969
|
-
const { sourceUri, targetUri } = arg.arguments[0];
|
|
970
|
-
this.applyRenameFile(sourceUri, targetUri);
|
|
971
881
|
}
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
882
|
+
}
|
|
883
|
+
else if (arg.command === Commands.ORGANIZE_IMPORTS && arg.arguments) {
|
|
884
|
+
const file = arg.arguments[0];
|
|
885
|
+
const additionalArguments = arg.arguments[1] || {};
|
|
886
|
+
await this.configurationManager.configureGloballyFromDocument(file);
|
|
887
|
+
const { body } = await this.tspClient.request("organizeImports" /* CommandTypes.OrganizeImports */, {
|
|
888
|
+
scope: {
|
|
889
|
+
type: 'file',
|
|
890
|
+
args: { file },
|
|
891
|
+
},
|
|
892
|
+
skipDestructiveCodeActions: additionalArguments.skipDestructiveCodeActions,
|
|
893
|
+
});
|
|
894
|
+
await this.applyFileCodeEdits(body);
|
|
895
|
+
}
|
|
896
|
+
else if (arg.command === Commands.APPLY_RENAME_FILE && arg.arguments) {
|
|
897
|
+
const { sourceUri, targetUri } = arg.arguments[0];
|
|
898
|
+
this.applyRenameFile(sourceUri, targetUri);
|
|
899
|
+
}
|
|
900
|
+
else if (arg.command === Commands.APPLY_COMPLETION_CODE_ACTION && arg.arguments) {
|
|
901
|
+
const [_, codeActions] = arg.arguments;
|
|
902
|
+
for (const codeAction of codeActions) {
|
|
903
|
+
await this.applyFileCodeEdits(codeAction.changes);
|
|
904
|
+
if (codeAction.commands && codeAction.commands.length) {
|
|
905
|
+
for (const command of codeAction.commands) {
|
|
906
|
+
await this.tspClient.request("applyCodeActionCommand" /* CommandTypes.ApplyCodeActionCommand */, { command });
|
|
980
907
|
}
|
|
981
|
-
// Execute only the first code action.
|
|
982
|
-
break;
|
|
983
908
|
}
|
|
909
|
+
// Execute only the first code action.
|
|
910
|
+
break;
|
|
984
911
|
}
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
912
|
+
}
|
|
913
|
+
else if (arg.command === Commands.SOURCE_DEFINITION) {
|
|
914
|
+
const [uri, position] = (arg.arguments || []);
|
|
915
|
+
const reporter = await this.options.lspClient.createProgressReporter(token, workDoneProgress);
|
|
916
|
+
return SourceDefinitionCommand.execute(uri, position, this.documents, this.tspClient, this.options.lspClient, reporter);
|
|
917
|
+
}
|
|
918
|
+
else {
|
|
919
|
+
this.logger.error(`Unknown command ${arg.command}.`);
|
|
920
|
+
}
|
|
989
921
|
}
|
|
990
|
-
applyFileCodeEdits(edits) {
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
edit: { changes }
|
|
1001
|
-
});
|
|
1002
|
-
return applied;
|
|
922
|
+
async applyFileCodeEdits(edits) {
|
|
923
|
+
if (!edits.length) {
|
|
924
|
+
return false;
|
|
925
|
+
}
|
|
926
|
+
const changes = {};
|
|
927
|
+
for (const edit of edits) {
|
|
928
|
+
changes[pathToUri(edit.fileName, this.documents)] = edit.textChanges.map(toTextEdit);
|
|
929
|
+
}
|
|
930
|
+
const { applied } = await this.options.lspClient.applyWorkspaceEdit({
|
|
931
|
+
edit: { changes },
|
|
1003
932
|
});
|
|
933
|
+
return applied;
|
|
1004
934
|
}
|
|
1005
|
-
applyRenameFile(sourceUri, targetUri) {
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
this.applyFileCodeEdits(edits);
|
|
1009
|
-
});
|
|
935
|
+
async applyRenameFile(sourceUri, targetUri) {
|
|
936
|
+
const edits = await this.getEditsForFileRename(sourceUri, targetUri);
|
|
937
|
+
this.applyFileCodeEdits(edits);
|
|
1010
938
|
}
|
|
1011
|
-
getEditsForFileRename(sourceUri, targetUri) {
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
}
|
|
1028
|
-
});
|
|
939
|
+
async getEditsForFileRename(sourceUri, targetUri) {
|
|
940
|
+
const newFilePath = uriToPath(targetUri);
|
|
941
|
+
const oldFilePath = uriToPath(sourceUri);
|
|
942
|
+
if (!newFilePath || !oldFilePath) {
|
|
943
|
+
return [];
|
|
944
|
+
}
|
|
945
|
+
try {
|
|
946
|
+
const { body } = await this.tspClient.request("getEditsForFileRename" /* CommandTypes.GetEditsForFileRename */, {
|
|
947
|
+
oldFilePath,
|
|
948
|
+
newFilePath,
|
|
949
|
+
});
|
|
950
|
+
return body;
|
|
951
|
+
}
|
|
952
|
+
catch (err) {
|
|
953
|
+
return [];
|
|
954
|
+
}
|
|
1029
955
|
}
|
|
1030
|
-
documentHighlight(arg) {
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
result.push(...highlights);
|
|
1059
|
-
}
|
|
956
|
+
async documentHighlight(arg) {
|
|
957
|
+
const file = uriToPath(arg.textDocument.uri);
|
|
958
|
+
this.logger.log('documentHighlight', arg, file);
|
|
959
|
+
if (!file) {
|
|
960
|
+
return [];
|
|
961
|
+
}
|
|
962
|
+
let response;
|
|
963
|
+
try {
|
|
964
|
+
response = await this.tspClient.request("documentHighlights" /* CommandTypes.DocumentHighlights */, {
|
|
965
|
+
file,
|
|
966
|
+
line: arg.position.line + 1,
|
|
967
|
+
offset: arg.position.character + 1,
|
|
968
|
+
filesToSearch: [file],
|
|
969
|
+
});
|
|
970
|
+
}
|
|
971
|
+
catch (err) {
|
|
972
|
+
return [];
|
|
973
|
+
}
|
|
974
|
+
if (!response.body) {
|
|
975
|
+
return [];
|
|
976
|
+
}
|
|
977
|
+
const result = [];
|
|
978
|
+
for (const item of response.body) {
|
|
979
|
+
// tsp returns item.file with POSIX path delimiters, whereas file is platform specific.
|
|
980
|
+
// Converting to a URI and back to a path ensures consistency.
|
|
981
|
+
if (normalizePath(item.file) === file) {
|
|
982
|
+
const highlights = toDocumentHighlight(item);
|
|
983
|
+
result.push(...highlights);
|
|
1060
984
|
}
|
|
1061
|
-
|
|
1062
|
-
|
|
985
|
+
}
|
|
986
|
+
return result;
|
|
1063
987
|
}
|
|
1064
988
|
lastFileOrDummy() {
|
|
1065
989
|
return this.documents.files[0] || this.workspaceRoot;
|
|
1066
990
|
}
|
|
1067
|
-
workspaceSymbol(params) {
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
return
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
end: toPosition(item.end)
|
|
1083
|
-
}
|
|
991
|
+
async workspaceSymbol(params) {
|
|
992
|
+
const result = await this.tspClient.request("navto" /* CommandTypes.Navto */, {
|
|
993
|
+
file: this.lastFileOrDummy(),
|
|
994
|
+
searchValue: params.query,
|
|
995
|
+
});
|
|
996
|
+
if (!result.body) {
|
|
997
|
+
return [];
|
|
998
|
+
}
|
|
999
|
+
return result.body.map(item => {
|
|
1000
|
+
return {
|
|
1001
|
+
location: {
|
|
1002
|
+
uri: pathToUri(item.file, this.documents),
|
|
1003
|
+
range: {
|
|
1004
|
+
start: Position.fromLocation(item.start),
|
|
1005
|
+
end: Position.fromLocation(item.end),
|
|
1084
1006
|
},
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
}
|
|
1007
|
+
},
|
|
1008
|
+
kind: toSymbolKind(item.kind),
|
|
1009
|
+
name: item.name,
|
|
1010
|
+
};
|
|
1089
1011
|
});
|
|
1090
1012
|
}
|
|
1091
1013
|
/**
|
|
1092
1014
|
* implemented based on https://github.com/Microsoft/vscode/blob/master/extensions/typescript-language-features/src/features/folding.ts
|
|
1093
1015
|
*/
|
|
1094
|
-
foldingRanges(params) {
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
foldingRanges.push(foldingRange);
|
|
1114
|
-
}
|
|
1016
|
+
async foldingRanges(params) {
|
|
1017
|
+
const file = uriToPath(params.textDocument.uri);
|
|
1018
|
+
this.logger.log('foldingRanges', params, file);
|
|
1019
|
+
if (!file) {
|
|
1020
|
+
return undefined;
|
|
1021
|
+
}
|
|
1022
|
+
const document = this.documents.get(file);
|
|
1023
|
+
if (!document) {
|
|
1024
|
+
throw new Error("The document should be opened for foldingRanges', file: " + file);
|
|
1025
|
+
}
|
|
1026
|
+
const { body } = await this.tspClient.request("getOutliningSpans" /* CommandTypes.GetOutliningSpans */, { file });
|
|
1027
|
+
if (!body) {
|
|
1028
|
+
return undefined;
|
|
1029
|
+
}
|
|
1030
|
+
const foldingRanges = [];
|
|
1031
|
+
for (const span of body) {
|
|
1032
|
+
const foldingRange = this.asFoldingRange(span, document);
|
|
1033
|
+
if (foldingRange) {
|
|
1034
|
+
foldingRanges.push(foldingRange);
|
|
1115
1035
|
}
|
|
1116
|
-
|
|
1117
|
-
|
|
1036
|
+
}
|
|
1037
|
+
return foldingRanges;
|
|
1118
1038
|
}
|
|
1119
1039
|
asFoldingRange(span, document) {
|
|
1120
|
-
const range =
|
|
1040
|
+
const range = Range.fromTextSpan(span.textSpan);
|
|
1121
1041
|
const kind = this.asFoldingRangeKind(span);
|
|
1122
1042
|
// workaround for https://github.com/Microsoft/vscode/issues/49904
|
|
1123
1043
|
if (span.kind === 'comment') {
|
|
@@ -1132,7 +1052,7 @@ export class LspServer {
|
|
|
1132
1052
|
return {
|
|
1133
1053
|
startLine,
|
|
1134
1054
|
endLine,
|
|
1135
|
-
kind
|
|
1055
|
+
kind,
|
|
1136
1056
|
};
|
|
1137
1057
|
}
|
|
1138
1058
|
asFoldingRangeKind(span) {
|
|
@@ -1144,150 +1064,136 @@ export class LspServer {
|
|
|
1144
1064
|
default: return undefined;
|
|
1145
1065
|
}
|
|
1146
1066
|
}
|
|
1147
|
-
onTsEvent(event) {
|
|
1148
|
-
var _a;
|
|
1067
|
+
async onTsEvent(event) {
|
|
1149
1068
|
if (event.event === "semanticDiag" /* EventTypes.SementicDiag */ ||
|
|
1150
1069
|
event.event === "syntaxDiag" /* EventTypes.SyntaxDiag */ ||
|
|
1151
1070
|
event.event === "suggestionDiag" /* EventTypes.SuggestionDiag */) {
|
|
1152
|
-
|
|
1071
|
+
this.diagnosticQueue?.updateDiagnostics(event.event, event);
|
|
1153
1072
|
}
|
|
1154
1073
|
else if (event.event === "projectLoadingStart" /* EventTypes.ProjectLoadingStart */) {
|
|
1155
|
-
this.loadingIndicator.startedLoadingProject(event.body.projectName);
|
|
1074
|
+
await this.loadingIndicator.startedLoadingProject(event.body.projectName);
|
|
1156
1075
|
}
|
|
1157
1076
|
else if (event.event === "projectLoadingFinish" /* EventTypes.ProjectLoadingFinish */) {
|
|
1158
1077
|
this.loadingIndicator.finishedLoadingProject(event.body.projectName);
|
|
1159
1078
|
}
|
|
1160
1079
|
else {
|
|
1161
1080
|
this.logger.log('Ignored event', {
|
|
1162
|
-
event: event.event
|
|
1081
|
+
event: event.event,
|
|
1163
1082
|
});
|
|
1164
1083
|
}
|
|
1165
1084
|
}
|
|
1166
|
-
calls(params) {
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
if (!file) {
|
|
1172
|
-
return callsResult;
|
|
1173
|
-
}
|
|
1174
|
-
if (params.direction === lspcalls.CallDirection.Outgoing) {
|
|
1175
|
-
const documentProvider = (file) => this.documents.get(file);
|
|
1176
|
-
callsResult = yield computeCallees(this.tspClient, params, documentProvider);
|
|
1177
|
-
}
|
|
1178
|
-
else {
|
|
1179
|
-
callsResult = yield computeCallers(this.tspClient, params);
|
|
1180
|
-
}
|
|
1085
|
+
async calls(params) {
|
|
1086
|
+
let callsResult = { calls: [] };
|
|
1087
|
+
const file = uriToPath(params.textDocument.uri);
|
|
1088
|
+
this.logger.log('calls', params, file);
|
|
1089
|
+
if (!file) {
|
|
1181
1090
|
return callsResult;
|
|
1182
|
-
}
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
this.
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
}
|
|
1192
|
-
yield this.tspClient.request("configure" /* CommandTypes.Configure */, {
|
|
1193
|
-
preferences: this.getInlayHintsOptions(file)
|
|
1194
|
-
});
|
|
1195
|
-
const doc = this.documents.get(file);
|
|
1196
|
-
if (!doc) {
|
|
1197
|
-
return { inlayHints: [] };
|
|
1198
|
-
}
|
|
1199
|
-
const start = doc.offsetAt((_b = (_a = params.range) === null || _a === void 0 ? void 0 : _a.start) !== null && _b !== void 0 ? _b : {
|
|
1200
|
-
line: 0,
|
|
1201
|
-
character: 0
|
|
1202
|
-
});
|
|
1203
|
-
const end = doc.offsetAt((_d = (_c = params.range) === null || _c === void 0 ? void 0 : _c.end) !== null && _d !== void 0 ? _d : {
|
|
1204
|
-
line: doc.lineCount + 1,
|
|
1205
|
-
character: 0
|
|
1206
|
-
});
|
|
1207
|
-
try {
|
|
1208
|
-
const result = yield this.tspClient.request("provideInlayHints" /* CommandTypes.ProvideInlayHints */, {
|
|
1209
|
-
file,
|
|
1210
|
-
start: start,
|
|
1211
|
-
length: end - start
|
|
1212
|
-
});
|
|
1213
|
-
return {
|
|
1214
|
-
inlayHints: (_f = (_e = result.body) === null || _e === void 0 ? void 0 : _e.map((item) => ({
|
|
1215
|
-
text: item.text,
|
|
1216
|
-
position: toPosition(item.position),
|
|
1217
|
-
whitespaceAfter: item.whitespaceAfter,
|
|
1218
|
-
whitespaceBefore: item.whitespaceBefore,
|
|
1219
|
-
kind: item.kind
|
|
1220
|
-
}))) !== null && _f !== void 0 ? _f : []
|
|
1221
|
-
};
|
|
1222
|
-
}
|
|
1223
|
-
catch (_g) {
|
|
1224
|
-
return {
|
|
1225
|
-
inlayHints: []
|
|
1226
|
-
};
|
|
1227
|
-
}
|
|
1228
|
-
});
|
|
1091
|
+
}
|
|
1092
|
+
if (params.direction === lspcalls.CallDirection.Outgoing) {
|
|
1093
|
+
const documentProvider = (file) => this.documents.get(file);
|
|
1094
|
+
callsResult = await computeCallees(this.tspClient, params, documentProvider);
|
|
1095
|
+
}
|
|
1096
|
+
else {
|
|
1097
|
+
callsResult = await computeCallers(this.tspClient, params);
|
|
1098
|
+
}
|
|
1099
|
+
return callsResult;
|
|
1229
1100
|
}
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
const workspacePreference = this.getWorkspacePreferencesForDocument(file);
|
|
1233
|
-
const userPreferences = ((_a = this.initializeParams.initializationOptions) === null || _a === void 0 ? void 0 : _a.preferences) || {};
|
|
1234
|
-
return Object.assign(Object.assign({}, userPreferences), (_b = workspacePreference.inlayHints) !== null && _b !== void 0 ? _b : {});
|
|
1101
|
+
async inlayHints(params) {
|
|
1102
|
+
return await TypeScriptInlayHintsProvider.provideInlayHints(params.textDocument.uri, params.range, this.documents, this.tspClient, this.options.lspClient, this.configurationManager);
|
|
1235
1103
|
}
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
if (!file) {
|
|
1241
|
-
return { data: [] };
|
|
1242
|
-
}
|
|
1243
|
-
const doc = this.documents.get(file);
|
|
1244
|
-
if (!doc) {
|
|
1245
|
-
return { data: [] };
|
|
1246
|
-
}
|
|
1247
|
-
const start = doc.offsetAt({
|
|
1248
|
-
line: 0,
|
|
1249
|
-
character: 0
|
|
1250
|
-
});
|
|
1251
|
-
const end = doc.offsetAt({
|
|
1252
|
-
line: doc.lineCount,
|
|
1253
|
-
character: 0
|
|
1254
|
-
});
|
|
1255
|
-
return this.getSemanticTokens(doc, file, start, end);
|
|
1104
|
+
async inlayHintsLegacy(params) {
|
|
1105
|
+
this.options.lspClient.logMessage({
|
|
1106
|
+
message: 'Support for experimental "typescript/inlayHints" request is deprecated. Use spec-compliant "textDocument/inlayHint" instead.',
|
|
1107
|
+
type: lsp.MessageType.Warning,
|
|
1256
1108
|
});
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1109
|
+
const file = uriToPath(params.textDocument.uri);
|
|
1110
|
+
this.logger.log('inlayHints', params, file);
|
|
1111
|
+
if (!file) {
|
|
1112
|
+
return { inlayHints: [] };
|
|
1113
|
+
}
|
|
1114
|
+
await this.configurationManager.configureGloballyFromDocument(file);
|
|
1115
|
+
const doc = this.documents.get(file);
|
|
1116
|
+
if (!doc) {
|
|
1117
|
+
return { inlayHints: [] };
|
|
1118
|
+
}
|
|
1119
|
+
const start = doc.offsetAt(params.range?.start ?? {
|
|
1120
|
+
line: 0,
|
|
1121
|
+
character: 0,
|
|
1122
|
+
});
|
|
1123
|
+
const end = doc.offsetAt(params.range?.end ?? {
|
|
1124
|
+
line: doc.lineCount + 1,
|
|
1125
|
+
character: 0,
|
|
1272
1126
|
});
|
|
1127
|
+
try {
|
|
1128
|
+
const result = await this.tspClient.request("provideInlayHints" /* CommandTypes.ProvideInlayHints */, {
|
|
1129
|
+
file,
|
|
1130
|
+
start: start,
|
|
1131
|
+
length: end - start,
|
|
1132
|
+
});
|
|
1133
|
+
return {
|
|
1134
|
+
inlayHints: result.body?.map((item) => ({
|
|
1135
|
+
text: item.text,
|
|
1136
|
+
position: Position.fromLocation(item.position),
|
|
1137
|
+
whitespaceAfter: item.whitespaceAfter,
|
|
1138
|
+
whitespaceBefore: item.whitespaceBefore,
|
|
1139
|
+
kind: item.kind,
|
|
1140
|
+
})) ?? [],
|
|
1141
|
+
};
|
|
1142
|
+
}
|
|
1143
|
+
catch {
|
|
1144
|
+
return {
|
|
1145
|
+
inlayHints: [],
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1273
1148
|
}
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1149
|
+
async semanticTokensFull(params) {
|
|
1150
|
+
const file = uriToPath(params.textDocument.uri);
|
|
1151
|
+
this.logger.log('semanticTokensFull', params, file);
|
|
1152
|
+
if (!file) {
|
|
1153
|
+
return { data: [] };
|
|
1154
|
+
}
|
|
1155
|
+
const doc = this.documents.get(file);
|
|
1156
|
+
if (!doc) {
|
|
1157
|
+
return { data: [] };
|
|
1158
|
+
}
|
|
1159
|
+
const start = doc.offsetAt({
|
|
1160
|
+
line: 0,
|
|
1161
|
+
character: 0,
|
|
1162
|
+
});
|
|
1163
|
+
const end = doc.offsetAt({
|
|
1164
|
+
line: doc.lineCount,
|
|
1165
|
+
character: 0,
|
|
1290
1166
|
});
|
|
1167
|
+
return this.getSemanticTokens(doc, file, start, end);
|
|
1168
|
+
}
|
|
1169
|
+
async semanticTokensRange(params) {
|
|
1170
|
+
const file = uriToPath(params.textDocument.uri);
|
|
1171
|
+
this.logger.log('semanticTokensRange', params, file);
|
|
1172
|
+
if (!file) {
|
|
1173
|
+
return { data: [] };
|
|
1174
|
+
}
|
|
1175
|
+
const doc = this.documents.get(file);
|
|
1176
|
+
if (!doc) {
|
|
1177
|
+
return { data: [] };
|
|
1178
|
+
}
|
|
1179
|
+
const start = doc.offsetAt(params.range.start);
|
|
1180
|
+
const end = doc.offsetAt(params.range.end);
|
|
1181
|
+
return this.getSemanticTokens(doc, file, start, end);
|
|
1182
|
+
}
|
|
1183
|
+
async getSemanticTokens(doc, file, startOffset, endOffset) {
|
|
1184
|
+
try {
|
|
1185
|
+
const result = await this.tspClient.request("encodedSemanticClassifications-full" /* CommandTypes.EncodedSemanticClassificationsFull */, {
|
|
1186
|
+
file,
|
|
1187
|
+
start: startOffset,
|
|
1188
|
+
length: endOffset - startOffset,
|
|
1189
|
+
format: '2020',
|
|
1190
|
+
});
|
|
1191
|
+
const spans = result.body?.spans ?? [];
|
|
1192
|
+
return { data: lspsemanticTokens.transformSpans(doc, spans) };
|
|
1193
|
+
}
|
|
1194
|
+
catch {
|
|
1195
|
+
return { data: [] };
|
|
1196
|
+
}
|
|
1291
1197
|
}
|
|
1292
1198
|
}
|
|
1293
1199
|
//# sourceMappingURL=lsp-server.js.map
|