typescript-language-server 3.0.1 → 3.0.3

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.
Files changed (220) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/lib/cli.mjs +3 -0
  3. package/lib/cli.mjs.map +1 -0
  4. package/package.json +37 -31
  5. package/lib/cli.d.ts +0 -3
  6. package/lib/cli.d.ts.map +0 -1
  7. package/lib/cli.js +0 -37
  8. package/lib/cli.js.map +0 -1
  9. package/lib/commands.d.ts +0 -13
  10. package/lib/commands.d.ts.map +0 -1
  11. package/lib/commands.js +0 -20
  12. package/lib/commands.js.map +0 -1
  13. package/lib/completion.d.ts +0 -10
  14. package/lib/completion.d.ts.map +0 -1
  15. package/lib/completion.js +0 -388
  16. package/lib/completion.js.map +0 -1
  17. package/lib/configuration-manager.d.ts +0 -48
  18. package/lib/configuration-manager.d.ts.map +0 -1
  19. package/lib/configuration-manager.js +0 -138
  20. package/lib/configuration-manager.js.map +0 -1
  21. package/lib/diagnostic-queue.d.ts +0 -31
  22. package/lib/diagnostic-queue.d.ts.map +0 -1
  23. package/lib/diagnostic-queue.js +0 -70
  24. package/lib/diagnostic-queue.js.map +0 -1
  25. package/lib/document-symbol.d.ts +0 -6
  26. package/lib/document-symbol.d.ts.map +0 -1
  27. package/lib/document-symbol.js +0 -85
  28. package/lib/document-symbol.js.map +0 -1
  29. package/lib/document.d.ts +0 -34
  30. package/lib/document.d.ts.map +0 -1
  31. package/lib/document.js +0 -115
  32. package/lib/document.js.map +0 -1
  33. package/lib/features/call-hierarchy.d.ts +0 -7
  34. package/lib/features/call-hierarchy.d.ts.map +0 -1
  35. package/lib/features/call-hierarchy.js +0 -81
  36. package/lib/features/call-hierarchy.js.map +0 -1
  37. package/lib/features/call-hierarchy.spec.d.ts +0 -2
  38. package/lib/features/call-hierarchy.spec.d.ts.map +0 -1
  39. package/lib/features/call-hierarchy.spec.js +0 -107
  40. package/lib/features/call-hierarchy.spec.js.map +0 -1
  41. package/lib/features/fix-all.d.ts +0 -12
  42. package/lib/features/fix-all.d.ts.map +0 -1
  43. package/lib/features/fix-all.js +0 -156
  44. package/lib/features/fix-all.js.map +0 -1
  45. package/lib/features/inlay-hints.d.ts +0 -11
  46. package/lib/features/inlay-hints.d.ts.map +0 -1
  47. package/lib/features/inlay-hints.js +0 -71
  48. package/lib/features/inlay-hints.js.map +0 -1
  49. package/lib/features/semantic-tokens.d.ts +0 -9
  50. package/lib/features/semantic-tokens.d.ts.map +0 -1
  51. package/lib/features/semantic-tokens.js +0 -43
  52. package/lib/features/semantic-tokens.js.map +0 -1
  53. package/lib/features/source-definition.d.ts +0 -11
  54. package/lib/features/source-definition.d.ts.map +0 -1
  55. package/lib/features/source-definition.js +0 -51
  56. package/lib/features/source-definition.js.map +0 -1
  57. package/lib/file-lsp-server.spec.d.ts +0 -2
  58. package/lib/file-lsp-server.spec.d.ts.map +0 -1
  59. package/lib/file-lsp-server.spec.js +0 -64
  60. package/lib/file-lsp-server.spec.js.map +0 -1
  61. package/lib/hover.d.ts +0 -6
  62. package/lib/hover.d.ts.map +0 -1
  63. package/lib/hover.js +0 -80
  64. package/lib/hover.js.map +0 -1
  65. package/lib/lsp-client.d.ts +0 -26
  66. package/lib/lsp-client.d.ts.map +0 -1
  67. package/lib/lsp-client.js +0 -51
  68. package/lib/lsp-client.js.map +0 -1
  69. package/lib/lsp-connection.d.ts +0 -9
  70. package/lib/lsp-connection.d.ts.map +0 -1
  71. package/lib/lsp-connection.js +0 -54
  72. package/lib/lsp-connection.js.map +0 -1
  73. package/lib/lsp-server.d.ts +0 -86
  74. package/lib/lsp-server.d.ts.map +0 -1
  75. package/lib/lsp-server.js +0 -1168
  76. package/lib/lsp-server.js.map +0 -1
  77. package/lib/lsp-server.spec.d.ts +0 -2
  78. package/lib/lsp-server.spec.d.ts.map +0 -1
  79. package/lib/lsp-server.spec.js +0 -2106
  80. package/lib/lsp-server.spec.js.map +0 -1
  81. package/lib/organize-imports.d.ts +0 -5
  82. package/lib/organize-imports.d.ts.map +0 -1
  83. package/lib/organize-imports.js +0 -19
  84. package/lib/organize-imports.js.map +0 -1
  85. package/lib/organize-imports.spec.d.ts +0 -2
  86. package/lib/organize-imports.spec.d.ts.map +0 -1
  87. package/lib/organize-imports.spec.js +0 -38
  88. package/lib/organize-imports.spec.js.map +0 -1
  89. package/lib/protocol-translation.d.ts +0 -26
  90. package/lib/protocol-translation.d.ts.map +0 -1
  91. package/lib/protocol-translation.js +0 -184
  92. package/lib/protocol-translation.js.map +0 -1
  93. package/lib/quickfix.d.ts +0 -5
  94. package/lib/quickfix.d.ts.map +0 -1
  95. package/lib/quickfix.js +0 -20
  96. package/lib/quickfix.js.map +0 -1
  97. package/lib/refactor.d.ts +0 -6
  98. package/lib/refactor.d.ts.map +0 -1
  99. package/lib/refactor.js +0 -58
  100. package/lib/refactor.js.map +0 -1
  101. package/lib/test-utils.d.ts +0 -45
  102. package/lib/test-utils.d.ts.map +0 -1
  103. package/lib/test-utils.js +0 -185
  104. package/lib/test-utils.js.map +0 -1
  105. package/lib/ts-protocol.d.ts +0 -93
  106. package/lib/ts-protocol.d.ts.map +0 -1
  107. package/lib/ts-protocol.js +0 -66
  108. package/lib/ts-protocol.js.map +0 -1
  109. package/lib/tsServer/callbackMap.d.ts +0 -17
  110. package/lib/tsServer/callbackMap.d.ts.map +0 -1
  111. package/lib/tsServer/callbackMap.js +0 -47
  112. package/lib/tsServer/callbackMap.js.map +0 -1
  113. package/lib/tsServer/cancellation.d.ts +0 -22
  114. package/lib/tsServer/cancellation.d.ts.map +0 -1
  115. package/lib/tsServer/cancellation.js +0 -51
  116. package/lib/tsServer/cancellation.js.map +0 -1
  117. package/lib/tsServer/logDirectoryProvider.d.ts +0 -13
  118. package/lib/tsServer/logDirectoryProvider.d.ts.map +0 -1
  119. package/lib/tsServer/logDirectoryProvider.js +0 -49
  120. package/lib/tsServer/logDirectoryProvider.js.map +0 -1
  121. package/lib/tsServer/requestQueue.d.ts +0 -34
  122. package/lib/tsServer/requestQueue.d.ts.map +0 -1
  123. package/lib/tsServer/requestQueue.js +0 -74
  124. package/lib/tsServer/requestQueue.js.map +0 -1
  125. package/lib/tsServer/requests.d.ts +0 -73
  126. package/lib/tsServer/requests.d.ts.map +0 -1
  127. package/lib/tsServer/requests.js +0 -30
  128. package/lib/tsServer/requests.js.map +0 -1
  129. package/lib/tsServer/server.d.ts +0 -100
  130. package/lib/tsServer/server.d.ts.map +0 -1
  131. package/lib/tsServer/server.js +0 -216
  132. package/lib/tsServer/server.js.map +0 -1
  133. package/lib/tsServer/serverError.d.ts +0 -18
  134. package/lib/tsServer/serverError.d.ts.map +0 -1
  135. package/lib/tsServer/serverError.js +0 -53
  136. package/lib/tsServer/serverError.js.map +0 -1
  137. package/lib/tsServer/serverProcess.d.ts +0 -7
  138. package/lib/tsServer/serverProcess.d.ts.map +0 -1
  139. package/lib/tsServer/serverProcess.js +0 -244
  140. package/lib/tsServer/serverProcess.js.map +0 -1
  141. package/lib/tsServer/spawner.d.ts +0 -19
  142. package/lib/tsServer/spawner.d.ts.map +0 -1
  143. package/lib/tsServer/spawner.js +0 -130
  144. package/lib/tsServer/spawner.js.map +0 -1
  145. package/lib/tsServer/tracer.d.ts +0 -26
  146. package/lib/tsServer/tracer.d.ts.map +0 -1
  147. package/lib/tsServer/tracer.js +0 -80
  148. package/lib/tsServer/tracer.js.map +0 -1
  149. package/lib/tsServer/versionProvider.d.ts +0 -29
  150. package/lib/tsServer/versionProvider.d.ts.map +0 -1
  151. package/lib/tsServer/versionProvider.js +0 -161
  152. package/lib/tsServer/versionProvider.js.map +0 -1
  153. package/lib/tsp-client.d.ts +0 -53
  154. package/lib/tsp-client.d.ts.map +0 -1
  155. package/lib/tsp-client.js +0 -228
  156. package/lib/tsp-client.js.map +0 -1
  157. package/lib/tsp-client.spec.d.ts +0 -2
  158. package/lib/tsp-client.spec.d.ts.map +0 -1
  159. package/lib/tsp-client.spec.js +0 -113
  160. package/lib/tsp-client.spec.js.map +0 -1
  161. package/lib/utils/MarkdownString.d.ts +0 -15
  162. package/lib/utils/MarkdownString.d.ts.map +0 -1
  163. package/lib/utils/MarkdownString.js +0 -45
  164. package/lib/utils/MarkdownString.js.map +0 -1
  165. package/lib/utils/SnippetString.d.ts +0 -12
  166. package/lib/utils/SnippetString.d.ts.map +0 -1
  167. package/lib/utils/SnippetString.js +0 -66
  168. package/lib/utils/SnippetString.js.map +0 -1
  169. package/lib/utils/api.d.ts +0 -49
  170. package/lib/utils/api.d.ts.map +0 -1
  171. package/lib/utils/api.js +0 -77
  172. package/lib/utils/api.js.map +0 -1
  173. package/lib/utils/configuration.d.ts +0 -20
  174. package/lib/utils/configuration.d.ts.map +0 -1
  175. package/lib/utils/configuration.js +0 -47
  176. package/lib/utils/configuration.js.map +0 -1
  177. package/lib/utils/errorCodes.d.ts +0 -12
  178. package/lib/utils/errorCodes.d.ts.map +0 -1
  179. package/lib/utils/errorCodes.js +0 -16
  180. package/lib/utils/errorCodes.js.map +0 -1
  181. package/lib/utils/fixNames.d.ts +0 -14
  182. package/lib/utils/fixNames.d.ts.map +0 -1
  183. package/lib/utils/fixNames.js +0 -18
  184. package/lib/utils/fixNames.js.map +0 -1
  185. package/lib/utils/logger.d.ts +0 -65
  186. package/lib/utils/logger.d.ts.map +0 -1
  187. package/lib/utils/logger.js +0 -187
  188. package/lib/utils/logger.js.map +0 -1
  189. package/lib/utils/modules-resolver.d.ts +0 -2
  190. package/lib/utils/modules-resolver.d.ts.map +0 -1
  191. package/lib/utils/modules-resolver.js +0 -17
  192. package/lib/utils/modules-resolver.js.map +0 -1
  193. package/lib/utils/modules-resolver.spec.d.ts +0 -2
  194. package/lib/utils/modules-resolver.spec.d.ts.map +0 -1
  195. package/lib/utils/modules-resolver.spec.js +0 -18
  196. package/lib/utils/modules-resolver.spec.js.map +0 -1
  197. package/lib/utils/previewer.d.ts +0 -15
  198. package/lib/utils/previewer.d.ts.map +0 -1
  199. package/lib/utils/previewer.js +0 -185
  200. package/lib/utils/previewer.js.map +0 -1
  201. package/lib/utils/previewer.spec.d.ts +0 -2
  202. package/lib/utils/previewer.spec.d.ts.map +0 -1
  203. package/lib/utils/previewer.spec.js +0 -123
  204. package/lib/utils/previewer.spec.js.map +0 -1
  205. package/lib/utils/tsconfig.d.ts +0 -4
  206. package/lib/utils/tsconfig.d.ts.map +0 -1
  207. package/lib/utils/tsconfig.js +0 -41
  208. package/lib/utils/tsconfig.js.map +0 -1
  209. package/lib/utils/typeConverters.d.ts +0 -29
  210. package/lib/utils/typeConverters.d.ts.map +0 -1
  211. package/lib/utils/typeConverters.js +0 -118
  212. package/lib/utils/typeConverters.js.map +0 -1
  213. package/lib/utils/types.d.ts +0 -41
  214. package/lib/utils/types.d.ts.map +0 -1
  215. package/lib/utils/types.js +0 -55
  216. package/lib/utils/types.js.map +0 -1
  217. package/lib/utils.d.ts +0 -6
  218. package/lib/utils.d.ts.map +0 -1
  219. package/lib/utils.js +0 -17
  220. package/lib/utils.js.map +0 -1
package/lib/lsp-server.js DELETED
@@ -1,1168 +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 path from 'node:path';
8
- import fs from 'fs-extra';
9
- import debounce from 'p-debounce';
10
- import * as lsp from 'vscode-languageserver';
11
- import API from './utils/api.js';
12
- import { LogLevel, PrefixingLogger } from './utils/logger.js';
13
- import { TspClient } from './tsp-client.js';
14
- import { DiagnosticEventQueue } from './diagnostic-queue.js';
15
- import { toDocumentHighlight, uriToPath, toSymbolKind, toLocation, toSelectionRange, pathToUri, toTextEdit, normalizePath } from './protocol-translation.js';
16
- import { LspDocuments } from './document.js';
17
- import { asCompletionItem, asResolvedCompletionItem, getCompletionTriggerCharacter } from './completion.js';
18
- import { asSignatureHelp, toTsTriggerReason } from './hover.js';
19
- import { Commands } from './commands.js';
20
- import { provideQuickFix } from './quickfix.js';
21
- import { provideRefactors } from './refactor.js';
22
- import { provideOrganizeImports } from './organize-imports.js';
23
- import { tsp } from './ts-protocol.js';
24
- import { collectDocumentSymbols, collectSymbolInformation } from './document-symbol.js';
25
- import { TsServerLogLevel } from './utils/configuration.js';
26
- import { fromProtocolCallHierarchyItem, fromProtocolCallHierarchyIncomingCall, fromProtocolCallHierarchyOutgoingCall } from './features/call-hierarchy.js';
27
- import { TypeScriptAutoFixProvider } from './features/fix-all.js';
28
- import { TypeScriptInlayHintsProvider } from './features/inlay-hints.js';
29
- import * as SemanticTokens from './features/semantic-tokens.js';
30
- import { SourceDefinitionCommand } from './features/source-definition.js';
31
- import { LogDirectoryProvider } from './tsServer/logDirectoryProvider.js';
32
- import { Trace } from './tsServer/tracer.js';
33
- import { TypeScriptVersionProvider } from './tsServer/versionProvider.js';
34
- import { MarkdownString } from './utils/MarkdownString.js';
35
- import * as Previewer from './utils/previewer.js';
36
- import { getInferredProjectCompilerOptions } from './utils/tsconfig.js';
37
- import { Position, Range } from './utils/typeConverters.js';
38
- import { CodeActionKind } from './utils/types.js';
39
- import { ConfigurationManager } from './configuration-manager.js';
40
- var CommandTypes = tsp.CommandTypes;
41
- export class LspServer {
42
- constructor(options) {
43
- this.options = options;
44
- this._tspClient = null;
45
- this.initializeParams = null;
46
- this.typeScriptAutoFixProvider = null;
47
- this.features = {};
48
- this.documents = new LspDocuments();
49
- // True if diagnostic request is currently debouncing or the request is in progress. False only if there are
50
- // no pending requests.
51
- this.pendingDebouncedRequest = false;
52
- this.doRequestDiagnosticsDebounced = debounce(() => this.doRequestDiagnostics(), 200);
53
- this.configurationManager = new ConfigurationManager(this.documents);
54
- this.logger = new PrefixingLogger(options.logger, '[lspserver]');
55
- }
56
- closeAll() {
57
- for (const file of [...this.documents.files]) {
58
- this.closeDocument(file);
59
- }
60
- }
61
- shutdown() {
62
- if (this._tspClient) {
63
- this._tspClient.shutdown();
64
- this._tspClient = null;
65
- }
66
- }
67
- get tspClient() {
68
- if (!this._tspClient) {
69
- throw new Error('TS client not created. Did you forget to send the "initialize" request?');
70
- }
71
- return this._tspClient;
72
- }
73
- async initialize(params) {
74
- this.logger.log('initialize', params);
75
- if (this._tspClient) {
76
- throw new Error('The "initialize" request has already called before.');
77
- }
78
- this.initializeParams = params;
79
- const clientCapabilities = this.initializeParams.capabilities;
80
- this.workspaceRoot = this.initializeParams.rootUri ? uriToPath(this.initializeParams.rootUri) : this.initializeParams.rootPath || undefined;
81
- const userInitializationOptions = this.initializeParams.initializationOptions || {};
82
- const { disableAutomaticTypingAcquisition, hostInfo, maxTsServerMemory, npmLocation, locale, tsserver } = userInitializationOptions;
83
- const { plugins } = {
84
- plugins: userInitializationOptions.plugins || [],
85
- };
86
- const globalPlugins = [];
87
- const pluginProbeLocations = [];
88
- for (const plugin of plugins) {
89
- globalPlugins.push(plugin.name);
90
- pluginProbeLocations.push(plugin.location);
91
- }
92
- const typescriptVersion = this.findTypescriptVersion(tsserver?.path);
93
- if (typescriptVersion) {
94
- this.logger.logIgnoringVerbosity(LogLevel.Info, `Using Typescript version (${typescriptVersion.source}) ${typescriptVersion.versionString} from path "${typescriptVersion.tsServerPath}"`);
95
- }
96
- else {
97
- 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.');
98
- }
99
- this.configurationManager.mergeTsPreferences(userInitializationOptions.preferences || {});
100
- // Setup supported features.
101
- const { textDocument } = clientCapabilities;
102
- if (textDocument) {
103
- const completionCapabilities = textDocument.completion;
104
- this.features.codeActionDisabledSupport = textDocument.codeAction?.disabledSupport;
105
- this.features.definitionLinkSupport = textDocument.definition?.linkSupport && typescriptVersion.version?.gte(API.v270);
106
- this.features.completionInsertReplaceSupport = completionCapabilities?.completionItem?.insertReplaceSupport;
107
- if (completionCapabilities?.completionItem) {
108
- if (this.configurationManager.tsPreferences.useLabelDetailsInCompletionEntries
109
- && completionCapabilities.completionItem.labelDetailsSupport
110
- && typescriptVersion.version?.gte(API.v470)) {
111
- this.features.completionLabelDetails = true;
112
- }
113
- if (completionCapabilities.completionItem.snippetSupport) {
114
- this.features.completionSnippets = true;
115
- }
116
- if (textDocument.publishDiagnostics?.tagSupport) {
117
- this.features.diagnosticsTagSupport = true;
118
- }
119
- }
120
- }
121
- this.configurationManager.mergeTsPreferences({
122
- useLabelDetailsInCompletionEntries: this.features.completionLabelDetails,
123
- });
124
- this.diagnosticQueue = new DiagnosticEventQueue(diagnostics => this.options.lspClient.publishDiagnostics(diagnostics), this.documents, this.features, this.logger);
125
- const tsserverLogVerbosity = tsserver?.logVerbosity && TsServerLogLevel.fromString(tsserver?.logVerbosity);
126
- this._tspClient = new TspClient({
127
- lspClient: this.options.lspClient,
128
- trace: Trace.fromString(tsserver?.trace || 'off'),
129
- typescriptVersion,
130
- logDirectoryProvider: new LogDirectoryProvider(this.getLogDirectoryPath(userInitializationOptions)),
131
- logVerbosity: tsserverLogVerbosity ?? this.options.tsserverLogVerbosity,
132
- disableAutomaticTypingAcquisition,
133
- maxTsServerMemory,
134
- npmLocation,
135
- locale,
136
- globalPlugins,
137
- pluginProbeLocations,
138
- logger: this.options.logger,
139
- onEvent: this.onTsEvent.bind(this),
140
- onExit: (exitCode, signal) => {
141
- this.shutdown();
142
- if (exitCode) {
143
- throw new Error(`tsserver process has exited (exit code: ${exitCode}, signal: ${signal}). Stopping the server.`);
144
- }
145
- },
146
- });
147
- const started = this.tspClient.start();
148
- if (!started) {
149
- throw new Error('tsserver process has failed to start.');
150
- }
151
- process.on('exit', () => {
152
- this.shutdown();
153
- });
154
- process.on('SIGINT', () => {
155
- process.exit();
156
- });
157
- this.typeScriptAutoFixProvider = new TypeScriptAutoFixProvider(this.tspClient);
158
- this.configurationManager.setAndConfigureTspClient(this.workspaceRoot, this._tspClient, hostInfo);
159
- this.setCompilerOptionsForInferredProjects();
160
- const prepareSupport = textDocument?.rename?.prepareSupport && this.tspClient.apiVersion.gte(API.v310);
161
- const initializeResult = {
162
- capabilities: {
163
- textDocumentSync: lsp.TextDocumentSyncKind.Incremental,
164
- completionProvider: {
165
- triggerCharacters: ['.', '"', '\'', '/', '@', '<'],
166
- resolveProvider: true,
167
- },
168
- codeActionProvider: clientCapabilities.textDocument?.codeAction?.codeActionLiteralSupport
169
- ? { codeActionKinds: [
170
- ...TypeScriptAutoFixProvider.kinds.map(kind => kind.value),
171
- CodeActionKind.SourceOrganizeImportsTs.value,
172
- CodeActionKind.QuickFix.value,
173
- CodeActionKind.Refactor.value,
174
- ] } : true,
175
- definitionProvider: true,
176
- documentFormattingProvider: true,
177
- documentRangeFormattingProvider: true,
178
- documentHighlightProvider: true,
179
- documentSymbolProvider: true,
180
- executeCommandProvider: {
181
- commands: [
182
- Commands.APPLY_WORKSPACE_EDIT,
183
- Commands.APPLY_CODE_ACTION,
184
- Commands.APPLY_REFACTORING,
185
- Commands.CONFIGURE_PLUGIN,
186
- Commands.ORGANIZE_IMPORTS,
187
- Commands.APPLY_RENAME_FILE,
188
- Commands.SOURCE_DEFINITION,
189
- ],
190
- },
191
- hoverProvider: true,
192
- inlayHintProvider: true,
193
- renameProvider: prepareSupport ? { prepareProvider: true } : true,
194
- referencesProvider: true,
195
- selectionRangeProvider: true,
196
- signatureHelpProvider: {
197
- triggerCharacters: ['(', ',', '<'],
198
- retriggerCharacters: [')'],
199
- },
200
- workspaceSymbolProvider: true,
201
- implementationProvider: true,
202
- typeDefinitionProvider: true,
203
- foldingRangeProvider: true,
204
- semanticTokensProvider: {
205
- documentSelector: null,
206
- legend: {
207
- // list taken from: https://github.com/microsoft/TypeScript/blob/main/src/services/classifier2020.ts#L10
208
- tokenTypes: [
209
- 'class',
210
- 'enum',
211
- 'interface',
212
- 'namespace',
213
- 'typeParameter',
214
- 'type',
215
- 'parameter',
216
- 'variable',
217
- 'enumMember',
218
- 'property',
219
- 'function',
220
- 'member',
221
- ],
222
- // token from: https://github.com/microsoft/TypeScript/blob/main/src/services/classifier2020.ts#L14
223
- tokenModifiers: [
224
- 'declaration',
225
- 'static',
226
- 'async',
227
- 'readonly',
228
- 'defaultLibrary',
229
- 'local',
230
- ],
231
- },
232
- full: true,
233
- range: true,
234
- },
235
- },
236
- };
237
- if (textDocument?.callHierarchy && typescriptVersion.version?.gte(API.v380)) {
238
- initializeResult.capabilities.callHierarchyProvider = true;
239
- }
240
- this.logger.log('onInitialize result', initializeResult);
241
- return initializeResult;
242
- }
243
- findTypescriptVersion(userTsserverPath) {
244
- const typescriptVersionProvider = new TypeScriptVersionProvider(userTsserverPath || this.options.tsserverPath, this.logger);
245
- // User-provided tsserver path.
246
- const userSettingVersion = typescriptVersionProvider.getUserSettingVersion();
247
- if (userSettingVersion) {
248
- if (userSettingVersion.isValid) {
249
- return userSettingVersion;
250
- }
251
- this.logger.logIgnoringVerbosity(LogLevel.Warning, `Typescript specified through user setting ignored due to invalid path "${userSettingVersion.path}"`);
252
- }
253
- // Workspace version.
254
- if (this.workspaceRoot) {
255
- const workspaceVersion = typescriptVersionProvider.getWorkspaceVersion([this.workspaceRoot]);
256
- if (workspaceVersion) {
257
- return workspaceVersion;
258
- }
259
- }
260
- // Bundled version
261
- const bundledVersion = typescriptVersionProvider.bundledVersion();
262
- if (bundledVersion?.isValid) {
263
- return bundledVersion;
264
- }
265
- return null;
266
- }
267
- getLogDirectoryPath(initializationOptions) {
268
- if (initializationOptions.tsserver?.logDirectory) {
269
- return initializationOptions.tsserver.logDirectory;
270
- }
271
- if (this.workspaceRoot) {
272
- return path.join(this.workspaceRoot, '.log');
273
- }
274
- return undefined;
275
- }
276
- setCompilerOptionsForInferredProjects() {
277
- const args = {
278
- options: {
279
- ...getInferredProjectCompilerOptions(this.configurationManager.workspaceConfiguration.implicitProjectConfiguration),
280
- allowJs: true,
281
- allowNonTsExtensions: true,
282
- allowSyntheticDefaultImports: true,
283
- resolveJsonModule: true,
284
- },
285
- };
286
- this.tspClient.executeWithoutWaitingForResponse(CommandTypes.CompilerOptionsForInferredProjects, args);
287
- }
288
- didChangeConfiguration(params) {
289
- this.configurationManager.setWorkspaceConfiguration(params.settings || {});
290
- this.setCompilerOptionsForInferredProjects();
291
- const ignoredDiagnosticCodes = this.configurationManager.workspaceConfiguration.diagnostics?.ignoredCodes || [];
292
- this.diagnosticQueue?.updateIgnoredDiagnosticCodes(ignoredDiagnosticCodes);
293
- }
294
- interuptDiagnostics(f) {
295
- if (!this.diagnosticsTokenSource) {
296
- return f();
297
- }
298
- this.cancelDiagnostics();
299
- const result = f();
300
- this.requestDiagnostics();
301
- return result;
302
- }
303
- async requestDiagnostics() {
304
- this.pendingDebouncedRequest = true;
305
- await this.doRequestDiagnosticsDebounced();
306
- }
307
- async doRequestDiagnostics() {
308
- this.cancelDiagnostics();
309
- const geterrTokenSource = new lsp.CancellationTokenSource();
310
- this.diagnosticsTokenSource = geterrTokenSource;
311
- const { files } = this.documents;
312
- try {
313
- return await this.tspClient.requestGeterr({ delay: 0, files }, this.diagnosticsTokenSource.token);
314
- }
315
- finally {
316
- if (this.diagnosticsTokenSource === geterrTokenSource) {
317
- this.diagnosticsTokenSource = undefined;
318
- this.pendingDebouncedRequest = false;
319
- }
320
- }
321
- }
322
- cancelDiagnostics() {
323
- if (this.diagnosticsTokenSource) {
324
- this.diagnosticsTokenSource.cancel();
325
- this.diagnosticsTokenSource = undefined;
326
- }
327
- }
328
- didOpenTextDocument(params) {
329
- const file = uriToPath(params.textDocument.uri);
330
- this.logger.log('onDidOpenTextDocument', params, file);
331
- if (!file) {
332
- return;
333
- }
334
- if (this.documents.open(file, params.textDocument)) {
335
- this.tspClient.notify(CommandTypes.Open, {
336
- file,
337
- fileContent: params.textDocument.text,
338
- scriptKindName: this.getScriptKindName(params.textDocument.languageId),
339
- projectRootPath: this.workspaceRoot,
340
- });
341
- this.requestDiagnostics();
342
- }
343
- else {
344
- this.logger.log(`Cannot open already opened doc '${params.textDocument.uri}'.`);
345
- this.didChangeTextDocument({
346
- textDocument: params.textDocument,
347
- contentChanges: [
348
- {
349
- text: params.textDocument.text,
350
- },
351
- ],
352
- });
353
- }
354
- }
355
- getScriptKindName(languageId) {
356
- switch (languageId) {
357
- case 'typescript': return 'TS';
358
- case 'typescriptreact': return 'TSX';
359
- case 'javascript': return 'JS';
360
- case 'javascriptreact': return 'JSX';
361
- }
362
- return undefined;
363
- }
364
- didCloseTextDocument(params) {
365
- const file = uriToPath(params.textDocument.uri);
366
- this.logger.log('onDidCloseTextDocument', params, file);
367
- if (!file) {
368
- return;
369
- }
370
- this.closeDocument(file);
371
- }
372
- closeDocument(file) {
373
- const document = this.documents.close(file);
374
- if (!document) {
375
- return;
376
- }
377
- this.tspClient.notify(CommandTypes.Close, { file });
378
- // We won't be updating diagnostics anymore for that file, so clear them
379
- // so we don't leave stale ones.
380
- this.options.lspClient.publishDiagnostics({
381
- uri: document.uri,
382
- diagnostics: [],
383
- });
384
- }
385
- didChangeTextDocument(params) {
386
- const { textDocument } = params;
387
- const file = uriToPath(textDocument.uri);
388
- this.logger.log('onDidChangeTextDocument', params, file);
389
- if (!file) {
390
- return;
391
- }
392
- const document = this.documents.get(file);
393
- if (!document) {
394
- this.logger.error(`Received change on non-opened document ${textDocument.uri}`);
395
- throw new Error(`Received change on non-opened document ${textDocument.uri}`);
396
- }
397
- if (textDocument.version === null) {
398
- throw new Error(`Received document change event for ${textDocument.uri} without valid version identifier`);
399
- }
400
- for (const change of params.contentChanges) {
401
- let line = 0;
402
- let offset = 0;
403
- let endLine = 0;
404
- let endOffset = 0;
405
- if (lsp.TextDocumentContentChangeEvent.isIncremental(change)) {
406
- line = change.range.start.line + 1;
407
- offset = change.range.start.character + 1;
408
- endLine = change.range.end.line + 1;
409
- endOffset = change.range.end.character + 1;
410
- }
411
- else {
412
- line = 1;
413
- offset = 1;
414
- const endPos = document.positionAt(document.getText().length);
415
- endLine = endPos.line + 1;
416
- endOffset = endPos.character + 1;
417
- }
418
- this.tspClient.notify(CommandTypes.Change, {
419
- file,
420
- line,
421
- offset,
422
- endLine,
423
- endOffset,
424
- insertString: change.text,
425
- });
426
- document.applyEdit(textDocument.version, change);
427
- }
428
- this.requestDiagnostics();
429
- }
430
- didSaveTextDocument(_params) {
431
- // do nothing
432
- }
433
- async definition(params) {
434
- return this.getDefinition({
435
- type: this.features.definitionLinkSupport ? CommandTypes.DefinitionAndBoundSpan : CommandTypes.Definition,
436
- params,
437
- });
438
- }
439
- async implementation(params) {
440
- return this.getSymbolLocations({
441
- type: CommandTypes.Implementation,
442
- params,
443
- });
444
- }
445
- async typeDefinition(params) {
446
- return this.getSymbolLocations({
447
- type: CommandTypes.TypeDefinition,
448
- params,
449
- });
450
- }
451
- async getDefinition({ type, params }) {
452
- const file = uriToPath(params.textDocument.uri);
453
- this.logger.log(type, params, file);
454
- if (!file) {
455
- return undefined;
456
- }
457
- if (type === CommandTypes.DefinitionAndBoundSpan) {
458
- const args = Position.toFileLocationRequestArgs(file, params.position);
459
- const response = await this.tspClient.request(type, args);
460
- if (response.type !== 'response' || !response.body) {
461
- return undefined;
462
- }
463
- // `textSpan` can be undefined in older TypeScript versions, despite type saying otherwise.
464
- const span = response.body.textSpan ? Range.fromTextSpan(response.body.textSpan) : undefined;
465
- return response.body.definitions
466
- .map((location) => {
467
- const target = toLocation(location, this.documents);
468
- const targetRange = location.contextStart && location.contextEnd
469
- ? Range.fromLocations(location.contextStart, location.contextEnd)
470
- : target.range;
471
- return {
472
- originSelectionRange: span,
473
- targetRange,
474
- targetUri: target.uri,
475
- targetSelectionRange: target.range,
476
- };
477
- });
478
- }
479
- return this.getSymbolLocations({ type: CommandTypes.Definition, params });
480
- }
481
- async getSymbolLocations({ type, params }) {
482
- const file = uriToPath(params.textDocument.uri);
483
- this.logger.log(type, params, file);
484
- if (!file) {
485
- return [];
486
- }
487
- const args = Position.toFileLocationRequestArgs(file, params.position);
488
- const response = await this.tspClient.request(type, args);
489
- if (response.type !== 'response' || !response.body) {
490
- return undefined;
491
- }
492
- return response.body.map(fileSpan => toLocation(fileSpan, this.documents));
493
- }
494
- async documentSymbol(params) {
495
- const file = uriToPath(params.textDocument.uri);
496
- this.logger.log('symbol', params, file);
497
- if (!file) {
498
- return [];
499
- }
500
- const response = await this.tspClient.request(CommandTypes.NavTree, {
501
- file,
502
- });
503
- const tree = response.body;
504
- if (!tree?.childItems) {
505
- return [];
506
- }
507
- if (this.supportHierarchicalDocumentSymbol) {
508
- const symbols = [];
509
- for (const item of tree.childItems) {
510
- collectDocumentSymbols(item, symbols);
511
- }
512
- return symbols;
513
- }
514
- const symbols = [];
515
- for (const item of tree.childItems) {
516
- collectSymbolInformation(params.textDocument.uri, item, symbols);
517
- }
518
- return symbols;
519
- }
520
- get supportHierarchicalDocumentSymbol() {
521
- const textDocument = this.initializeParams?.capabilities.textDocument;
522
- const documentSymbol = textDocument?.documentSymbol;
523
- return !!documentSymbol && !!documentSymbol.hierarchicalDocumentSymbolSupport;
524
- }
525
- /*
526
- * implemented based on
527
- * https://github.com/Microsoft/vscode/blob/master/extensions/typescript-language-features/src/features/completions.ts
528
- */
529
- async completion(params) {
530
- const file = uriToPath(params.textDocument.uri);
531
- this.logger.log('completion', params, file);
532
- if (!file) {
533
- return lsp.CompletionList.create([]);
534
- }
535
- const document = this.documents.get(file);
536
- if (!document) {
537
- throw new Error(`The document should be opened for completion, file: ${file}`);
538
- }
539
- const completionOptions = this.configurationManager.workspaceConfiguration.completions || {};
540
- try {
541
- const result = await this.interuptDiagnostics(() => this.tspClient.request(CommandTypes.CompletionInfo, {
542
- file,
543
- line: params.position.line + 1,
544
- offset: params.position.character + 1,
545
- triggerCharacter: getCompletionTriggerCharacter(params.context?.triggerCharacter),
546
- triggerKind: params.context?.triggerKind,
547
- }));
548
- const { body } = result;
549
- if (!body) {
550
- return lsp.CompletionList.create();
551
- }
552
- const { entries, isIncomplete, optionalReplacementSpan } = body;
553
- const completions = [];
554
- for (const entry of entries || []) {
555
- if (entry.kind === 'warning') {
556
- continue;
557
- }
558
- const completion = asCompletionItem(entry, optionalReplacementSpan, file, params.position, document, this.documents, completionOptions, this.features);
559
- if (!completion) {
560
- continue;
561
- }
562
- completions.push(completion);
563
- }
564
- return lsp.CompletionList.create(completions, isIncomplete);
565
- }
566
- catch (error) {
567
- if (error.message === 'No content available.') {
568
- this.logger.info('No content was available for completion request');
569
- return null;
570
- }
571
- else {
572
- throw error;
573
- }
574
- }
575
- }
576
- async completionResolve(item) {
577
- this.logger.log('completion/resolve', item);
578
- const document = item.data?.file ? this.documents.get(item.data.file) : undefined;
579
- await this.configurationManager.configureGloballyFromDocument(item.data.file);
580
- const { body } = await this.interuptDiagnostics(() => this.tspClient.request(CommandTypes.CompletionDetails, item.data));
581
- const details = body?.length && body[0];
582
- if (!details) {
583
- return item;
584
- }
585
- return asResolvedCompletionItem(item, details, document, this.tspClient, this.documents, this.configurationManager.workspaceConfiguration.completions || {}, this.features);
586
- }
587
- async hover(params) {
588
- const file = uriToPath(params.textDocument.uri);
589
- this.logger.log('hover', params, file);
590
- if (!file) {
591
- return { contents: [] };
592
- }
593
- const result = await this.interuptDiagnostics(() => this.getQuickInfo(file, params.position));
594
- if (!result?.body) {
595
- return { contents: [] };
596
- }
597
- const contents = new MarkdownString();
598
- const { displayString, documentation, tags } = result.body;
599
- if (displayString) {
600
- contents.appendCodeblock('typescript', displayString);
601
- }
602
- Previewer.addMarkdownDocumentation(contents, documentation, tags, this.documents);
603
- return {
604
- contents: contents.toMarkupContent(),
605
- range: Range.fromTextSpan(result.body),
606
- };
607
- }
608
- async getQuickInfo(file, position) {
609
- try {
610
- return await this.tspClient.request(CommandTypes.Quickinfo, {
611
- file,
612
- line: position.line + 1,
613
- offset: position.character + 1,
614
- });
615
- }
616
- catch (err) {
617
- return undefined;
618
- }
619
- }
620
- async prepareRename(params) {
621
- const file = uriToPath(params.textDocument.uri);
622
- if (!file) {
623
- return null;
624
- }
625
- const result = await this.tspClient.request(CommandTypes.Rename, Position.toFileLocationRequestArgs(file, params.position));
626
- const renameInfo = result.body?.info;
627
- if (!renameInfo) {
628
- return null;
629
- }
630
- if (!renameInfo.canRename) {
631
- throw new Error(renameInfo.localizedErrorMessage);
632
- }
633
- return Range.fromTextSpan(renameInfo.triggerSpan);
634
- }
635
- async rename(params) {
636
- const file = uriToPath(params.textDocument.uri);
637
- this.logger.log('onRename', params, file);
638
- if (!file) {
639
- return null;
640
- }
641
- const result = await this.tspClient.request(CommandTypes.Rename, Position.toFileLocationRequestArgs(file, params.position));
642
- if (!result.body?.info.canRename || result.body.locs.length === 0) {
643
- return null;
644
- }
645
- const workspaceEdit = {};
646
- result.body.locs
647
- .forEach((spanGroup) => {
648
- const uri = pathToUri(spanGroup.file, this.documents);
649
- if (!workspaceEdit.changes) {
650
- workspaceEdit.changes = {};
651
- }
652
- const textEdits = workspaceEdit.changes[uri] || (workspaceEdit.changes[uri] = []);
653
- spanGroup.locs.forEach((textSpan) => {
654
- textEdits.push({
655
- newText: `${textSpan.prefixText || ''}${params.newName}${textSpan.suffixText || ''}`,
656
- range: {
657
- start: Position.fromLocation(textSpan.start),
658
- end: Position.fromLocation(textSpan.end),
659
- },
660
- });
661
- });
662
- });
663
- return workspaceEdit;
664
- }
665
- async references(params) {
666
- const file = uriToPath(params.textDocument.uri);
667
- this.logger.log('onReferences', params, file);
668
- if (!file) {
669
- return [];
670
- }
671
- const result = await this.tspClient.request(CommandTypes.References, {
672
- file,
673
- line: params.position.line + 1,
674
- offset: params.position.character + 1,
675
- });
676
- if (!result.body) {
677
- return [];
678
- }
679
- return result.body.refs
680
- .filter(fileSpan => params.context.includeDeclaration || !fileSpan.isDefinition)
681
- .map(fileSpan => toLocation(fileSpan, this.documents));
682
- }
683
- async documentFormatting(params) {
684
- const file = uriToPath(params.textDocument.uri);
685
- this.logger.log('documentFormatting', params, file);
686
- if (!file) {
687
- return [];
688
- }
689
- const formatOptions = params.options;
690
- await this.configurationManager.configureGloballyFromDocument(file, formatOptions);
691
- const response = await this.tspClient.request(CommandTypes.Format, {
692
- file,
693
- line: 1,
694
- offset: 1,
695
- endLine: Number.MAX_SAFE_INTEGER,
696
- endOffset: Number.MAX_SAFE_INTEGER,
697
- options: formatOptions,
698
- });
699
- if (response.body) {
700
- return response.body.map(e => toTextEdit(e));
701
- }
702
- return [];
703
- }
704
- async documentRangeFormatting(params) {
705
- const file = uriToPath(params.textDocument.uri);
706
- this.logger.log('documentRangeFormatting', params, file);
707
- if (!file) {
708
- return [];
709
- }
710
- const formatOptions = params.options;
711
- await this.configurationManager.configureGloballyFromDocument(file, formatOptions);
712
- const response = await this.tspClient.request(CommandTypes.Format, {
713
- file,
714
- line: params.range.start.line + 1,
715
- offset: params.range.start.character + 1,
716
- endLine: params.range.end.line + 1,
717
- endOffset: params.range.end.character + 1,
718
- options: formatOptions,
719
- });
720
- if (response.body) {
721
- return response.body.map(e => toTextEdit(e));
722
- }
723
- return [];
724
- }
725
- async selectionRanges(params) {
726
- const file = uriToPath(params.textDocument.uri);
727
- if (!file) {
728
- return null;
729
- }
730
- const response = await this.tspClient.request(CommandTypes.SelectionRange, {
731
- file,
732
- locations: params.positions.map(Position.toLocation),
733
- });
734
- if (response.type !== 'response' || !response.body) {
735
- return null;
736
- }
737
- return response.body.map(toSelectionRange);
738
- }
739
- async signatureHelp(params) {
740
- const file = uriToPath(params.textDocument.uri);
741
- this.logger.log('signatureHelp', params, file);
742
- if (!file) {
743
- return undefined;
744
- }
745
- const response = await this.interuptDiagnostics(() => this.getSignatureHelp(file, params));
746
- if (!response?.body) {
747
- return undefined;
748
- }
749
- return asSignatureHelp(response.body, params.context, this.documents);
750
- }
751
- async getSignatureHelp(file, params) {
752
- try {
753
- const { position, context } = params;
754
- return await this.tspClient.request(CommandTypes.SignatureHelp, {
755
- file,
756
- line: position.line + 1,
757
- offset: position.character + 1,
758
- triggerReason: context ? toTsTriggerReason(context) : undefined,
759
- });
760
- }
761
- catch (err) {
762
- return undefined;
763
- }
764
- }
765
- async codeAction(params) {
766
- const file = uriToPath(params.textDocument.uri);
767
- this.logger.log('codeAction', params, file);
768
- if (!file) {
769
- return [];
770
- }
771
- const fileRangeArgs = Range.toFileRangeRequestArgs(file, params.range);
772
- const actions = [];
773
- const kinds = params.context.only?.map(kind => new CodeActionKind(kind));
774
- if (!kinds || kinds.some(kind => kind.contains(CodeActionKind.QuickFix))) {
775
- actions.push(...provideQuickFix(await this.getCodeFixes(fileRangeArgs, params.context), this.documents));
776
- }
777
- if (!kinds || kinds.some(kind => kind.contains(CodeActionKind.Refactor))) {
778
- actions.push(...provideRefactors(await this.getRefactors(fileRangeArgs, params.context), fileRangeArgs, this.features));
779
- }
780
- // organize import is provided by tsserver for any line, so we only get it if explicitly requested
781
- if (kinds?.some(kind => kind.contains(CodeActionKind.SourceOrganizeImportsTs))) {
782
- // see this issue for more context about how this argument is used
783
- // https://github.com/microsoft/TypeScript/issues/43051
784
- const skipDestructiveCodeActions = params.context.diagnostics.some(
785
- // assume no severity is an error
786
- d => (d.severity ?? 0) <= 2);
787
- const response = await this.getOrganizeImports({
788
- scope: { type: 'file', args: fileRangeArgs },
789
- skipDestructiveCodeActions,
790
- });
791
- actions.push(...provideOrganizeImports(response, this.documents));
792
- }
793
- // TODO: Since we rely on diagnostics pointing at errors in the correct places, we can't proceed if we are not
794
- // sure that diagnostics are up-to-date. Thus we check `pendingDebouncedRequest` to see if there are *any*
795
- // pending diagnostic requests (regardless of for which file).
796
- // In general would be better to replace the whole diagnostics handling logic with the one from
797
- // bufferSyncSupport.ts in VSCode's typescript language features.
798
- if (kinds && !this.pendingDebouncedRequest) {
799
- const diagnostics = this.diagnosticQueue?.getDiagnosticsForFile(file) || [];
800
- if (diagnostics.length) {
801
- actions.push(...await this.typeScriptAutoFixProvider.provideCodeActions(kinds, file, diagnostics, this.documents));
802
- }
803
- }
804
- return actions;
805
- }
806
- async getCodeFixes(fileRangeArgs, context) {
807
- const errorCodes = context.diagnostics.map(diagnostic => Number(diagnostic.code));
808
- const args = {
809
- ...fileRangeArgs,
810
- errorCodes,
811
- };
812
- try {
813
- return await this.tspClient.request(CommandTypes.GetCodeFixes, args);
814
- }
815
- catch (err) {
816
- return undefined;
817
- }
818
- }
819
- async getRefactors(fileRangeArgs, context) {
820
- const args = {
821
- ...fileRangeArgs,
822
- triggerReason: context.triggerKind === lsp.CodeActionTriggerKind.Invoked ? 'invoked' : undefined,
823
- kind: context.only?.length === 1 ? context.only[0] : undefined,
824
- };
825
- try {
826
- return await this.tspClient.request(CommandTypes.GetApplicableRefactors, args);
827
- }
828
- catch (err) {
829
- return undefined;
830
- }
831
- }
832
- async getOrganizeImports(args) {
833
- try {
834
- await this.configurationManager.configureGloballyFromDocument(args.scope.args.file);
835
- return await this.tspClient.request(CommandTypes.OrganizeImports, args);
836
- }
837
- catch (err) {
838
- return undefined;
839
- }
840
- }
841
- async executeCommand(arg, token, workDoneProgress) {
842
- this.logger.log('executeCommand', arg);
843
- if (arg.command === Commands.APPLY_WORKSPACE_EDIT && arg.arguments) {
844
- const edit = arg.arguments[0];
845
- await this.options.lspClient.applyWorkspaceEdit({ edit });
846
- }
847
- else if (arg.command === Commands.APPLY_CODE_ACTION && arg.arguments) {
848
- const codeAction = arg.arguments[0];
849
- if (!await this.applyFileCodeEdits(codeAction.changes)) {
850
- return;
851
- }
852
- if (codeAction.commands?.length) {
853
- for (const command of codeAction.commands) {
854
- await this.tspClient.request(CommandTypes.ApplyCodeActionCommand, { command });
855
- }
856
- }
857
- }
858
- else if (arg.command === Commands.APPLY_REFACTORING && arg.arguments) {
859
- const args = arg.arguments[0];
860
- const { body } = await this.tspClient.request(CommandTypes.GetEditsForRefactor, args);
861
- if (!body?.edits.length) {
862
- return;
863
- }
864
- for (const edit of body.edits) {
865
- await fs.ensureFile(edit.fileName);
866
- }
867
- if (!await this.applyFileCodeEdits(body.edits)) {
868
- return;
869
- }
870
- const renameLocation = body.renameLocation;
871
- if (renameLocation) {
872
- await this.options.lspClient.rename({
873
- textDocument: {
874
- uri: pathToUri(args.file, this.documents),
875
- },
876
- position: Position.fromLocation(renameLocation),
877
- });
878
- }
879
- }
880
- else if (arg.command === Commands.CONFIGURE_PLUGIN && arg.arguments) {
881
- const [pluginName, configuration] = arg.arguments;
882
- if (this.tspClient?.apiVersion.gte(API.v314)) {
883
- this.tspClient.executeWithoutWaitingForResponse(CommandTypes.ConfigurePlugin, {
884
- configuration,
885
- pluginName,
886
- });
887
- }
888
- }
889
- else if (arg.command === Commands.ORGANIZE_IMPORTS && arg.arguments) {
890
- const file = arg.arguments[0];
891
- const additionalArguments = arg.arguments[1] || {};
892
- await this.configurationManager.configureGloballyFromDocument(file);
893
- const { body } = await this.tspClient.request(CommandTypes.OrganizeImports, {
894
- scope: {
895
- type: 'file',
896
- args: { file },
897
- },
898
- skipDestructiveCodeActions: additionalArguments.skipDestructiveCodeActions,
899
- });
900
- await this.applyFileCodeEdits(body);
901
- }
902
- else if (arg.command === Commands.APPLY_RENAME_FILE && arg.arguments) {
903
- const { sourceUri, targetUri } = arg.arguments[0];
904
- this.applyRenameFile(sourceUri, targetUri);
905
- }
906
- else if (arg.command === Commands.APPLY_COMPLETION_CODE_ACTION && arg.arguments) {
907
- const [_, codeActions] = arg.arguments;
908
- for (const codeAction of codeActions) {
909
- await this.applyFileCodeEdits(codeAction.changes);
910
- if (codeAction.commands?.length) {
911
- for (const command of codeAction.commands) {
912
- await this.tspClient.request(CommandTypes.ApplyCodeActionCommand, { command });
913
- }
914
- }
915
- // Execute only the first code action.
916
- break;
917
- }
918
- }
919
- else if (arg.command === Commands.SOURCE_DEFINITION) {
920
- const [uri, position] = (arg.arguments || []);
921
- const reporter = await this.options.lspClient.createProgressReporter(token, workDoneProgress);
922
- return SourceDefinitionCommand.execute(uri, position, this.documents, this.tspClient, this.options.lspClient, reporter);
923
- }
924
- else {
925
- this.logger.error(`Unknown command ${arg.command}.`);
926
- }
927
- }
928
- async applyFileCodeEdits(edits) {
929
- if (!edits.length) {
930
- return false;
931
- }
932
- const changes = {};
933
- for (const edit of edits) {
934
- changes[pathToUri(edit.fileName, this.documents)] = edit.textChanges.map(toTextEdit);
935
- }
936
- const { applied } = await this.options.lspClient.applyWorkspaceEdit({
937
- edit: { changes },
938
- });
939
- return applied;
940
- }
941
- async applyRenameFile(sourceUri, targetUri) {
942
- const edits = await this.getEditsForFileRename(sourceUri, targetUri);
943
- this.applyFileCodeEdits(edits);
944
- }
945
- async getEditsForFileRename(sourceUri, targetUri) {
946
- const newFilePath = uriToPath(targetUri);
947
- const oldFilePath = uriToPath(sourceUri);
948
- if (!newFilePath || !oldFilePath) {
949
- return [];
950
- }
951
- try {
952
- const { body } = await this.tspClient.request(CommandTypes.GetEditsForFileRename, {
953
- oldFilePath,
954
- newFilePath,
955
- });
956
- return body;
957
- }
958
- catch (err) {
959
- return [];
960
- }
961
- }
962
- async documentHighlight(arg) {
963
- const file = uriToPath(arg.textDocument.uri);
964
- this.logger.log('documentHighlight', arg, file);
965
- if (!file) {
966
- return [];
967
- }
968
- let response;
969
- try {
970
- response = await this.tspClient.request(CommandTypes.DocumentHighlights, {
971
- file,
972
- line: arg.position.line + 1,
973
- offset: arg.position.character + 1,
974
- filesToSearch: [file],
975
- });
976
- }
977
- catch (err) {
978
- return [];
979
- }
980
- if (!response.body) {
981
- return [];
982
- }
983
- const result = [];
984
- for (const item of response.body) {
985
- // tsp returns item.file with POSIX path delimiters, whereas file is platform specific.
986
- // Converting to a URI and back to a path ensures consistency.
987
- if (normalizePath(item.file) === file) {
988
- const highlights = toDocumentHighlight(item);
989
- result.push(...highlights);
990
- }
991
- }
992
- return result;
993
- }
994
- lastFileOrDummy() {
995
- return this.documents.files[0] || this.workspaceRoot;
996
- }
997
- async workspaceSymbol(params) {
998
- const result = await this.tspClient.request(CommandTypes.Navto, {
999
- file: this.lastFileOrDummy(),
1000
- searchValue: params.query,
1001
- });
1002
- if (!result.body) {
1003
- return [];
1004
- }
1005
- return result.body.map(item => {
1006
- return {
1007
- location: {
1008
- uri: pathToUri(item.file, this.documents),
1009
- range: {
1010
- start: Position.fromLocation(item.start),
1011
- end: Position.fromLocation(item.end),
1012
- },
1013
- },
1014
- kind: toSymbolKind(item.kind),
1015
- name: item.name,
1016
- };
1017
- });
1018
- }
1019
- /**
1020
- * implemented based on https://github.com/Microsoft/vscode/blob/master/extensions/typescript-language-features/src/features/folding.ts
1021
- */
1022
- async foldingRanges(params) {
1023
- const file = uriToPath(params.textDocument.uri);
1024
- this.logger.log('foldingRanges', params, file);
1025
- if (!file) {
1026
- return undefined;
1027
- }
1028
- const document = this.documents.get(file);
1029
- if (!document) {
1030
- throw new Error(`The document should be opened for foldingRanges', file: ${file}`);
1031
- }
1032
- const { body } = await this.tspClient.request(CommandTypes.GetOutliningSpans, { file });
1033
- if (!body) {
1034
- return undefined;
1035
- }
1036
- const foldingRanges = [];
1037
- for (const span of body) {
1038
- const foldingRange = this.asFoldingRange(span, document);
1039
- if (foldingRange) {
1040
- foldingRanges.push(foldingRange);
1041
- }
1042
- }
1043
- return foldingRanges;
1044
- }
1045
- asFoldingRange(span, document) {
1046
- const range = Range.fromTextSpan(span.textSpan);
1047
- const kind = this.asFoldingRangeKind(span);
1048
- // workaround for https://github.com/Microsoft/vscode/issues/49904
1049
- if (span.kind === 'comment') {
1050
- const line = document.getLine(range.start.line);
1051
- if (line.match(/\/\/\s*#endregion/gi)) {
1052
- return undefined;
1053
- }
1054
- }
1055
- const startLine = range.start.line;
1056
- // workaround for https://github.com/Microsoft/vscode/issues/47240
1057
- const endLine = range.end.character > 0 && document.getText(lsp.Range.create(lsp.Position.create(range.end.line, range.end.character - 1), range.end)) === '}' ? Math.max(range.end.line - 1, range.start.line) : range.end.line;
1058
- return {
1059
- startLine,
1060
- endLine,
1061
- kind,
1062
- };
1063
- }
1064
- asFoldingRangeKind(span) {
1065
- switch (span.kind) {
1066
- case 'comment': return lsp.FoldingRangeKind.Comment;
1067
- case 'region': return lsp.FoldingRangeKind.Region;
1068
- case 'imports': return lsp.FoldingRangeKind.Imports;
1069
- case 'code':
1070
- default: return undefined;
1071
- }
1072
- }
1073
- async onTsEvent(event) {
1074
- if (event.event === "semanticDiag" /* EventTypes.SementicDiag */ || event.event === "syntaxDiag" /* EventTypes.SyntaxDiag */ || event.event === "suggestionDiag" /* EventTypes.SuggestionDiag */) {
1075
- this.diagnosticQueue?.updateDiagnostics(event.event, event);
1076
- }
1077
- }
1078
- async prepareCallHierarchy(params) {
1079
- const file = uriToPath(params.textDocument.uri);
1080
- if (!file) {
1081
- return null;
1082
- }
1083
- const args = Position.toFileLocationRequestArgs(file, params.position);
1084
- const response = await this.tspClient.request(CommandTypes.PrepareCallHierarchy, args);
1085
- if (response.type !== 'response' || !response.body) {
1086
- return null;
1087
- }
1088
- const items = Array.isArray(response.body) ? response.body : [response.body];
1089
- return items.map(item => fromProtocolCallHierarchyItem(item, this.documents, this.workspaceRoot));
1090
- }
1091
- async callHierarchyIncomingCalls(params) {
1092
- const file = uriToPath(params.item.uri);
1093
- if (!file) {
1094
- return null;
1095
- }
1096
- const args = Position.toFileLocationRequestArgs(file, params.item.selectionRange.start);
1097
- const response = await this.tspClient.request(CommandTypes.ProvideCallHierarchyIncomingCalls, args);
1098
- if (response.type !== 'response' || !response.body) {
1099
- return null;
1100
- }
1101
- return response.body.map(item => fromProtocolCallHierarchyIncomingCall(item, this.documents, this.workspaceRoot));
1102
- }
1103
- async callHierarchyOutgoingCalls(params) {
1104
- const file = uriToPath(params.item.uri);
1105
- if (!file) {
1106
- return null;
1107
- }
1108
- const args = Position.toFileLocationRequestArgs(file, params.item.selectionRange.start);
1109
- const response = await this.tspClient.request(CommandTypes.ProvideCallHierarchyOutgoingCalls, args);
1110
- if (response.type !== 'response' || !response.body) {
1111
- return null;
1112
- }
1113
- return response.body.map(item => fromProtocolCallHierarchyOutgoingCall(item, this.documents, this.workspaceRoot));
1114
- }
1115
- async inlayHints(params) {
1116
- return await TypeScriptInlayHintsProvider.provideInlayHints(params.textDocument.uri, params.range, this.documents, this.tspClient, this.options.lspClient, this.configurationManager);
1117
- }
1118
- async semanticTokensFull(params) {
1119
- const file = uriToPath(params.textDocument.uri);
1120
- this.logger.log('semanticTokensFull', params, file);
1121
- if (!file) {
1122
- return { data: [] };
1123
- }
1124
- const doc = this.documents.get(file);
1125
- if (!doc) {
1126
- return { data: [] };
1127
- }
1128
- const start = doc.offsetAt({
1129
- line: 0,
1130
- character: 0,
1131
- });
1132
- const end = doc.offsetAt({
1133
- line: doc.lineCount,
1134
- character: 0,
1135
- });
1136
- return this.getSemanticTokens(doc, file, start, end);
1137
- }
1138
- async semanticTokensRange(params) {
1139
- const file = uriToPath(params.textDocument.uri);
1140
- this.logger.log('semanticTokensRange', params, file);
1141
- if (!file) {
1142
- return { data: [] };
1143
- }
1144
- const doc = this.documents.get(file);
1145
- if (!doc) {
1146
- return { data: [] };
1147
- }
1148
- const start = doc.offsetAt(params.range.start);
1149
- const end = doc.offsetAt(params.range.end);
1150
- return this.getSemanticTokens(doc, file, start, end);
1151
- }
1152
- async getSemanticTokens(doc, file, startOffset, endOffset) {
1153
- try {
1154
- const result = await this.tspClient.request(CommandTypes.EncodedSemanticClassificationsFull, {
1155
- file,
1156
- start: startOffset,
1157
- length: endOffset - startOffset,
1158
- format: '2020',
1159
- });
1160
- const spans = result.body?.spans ?? [];
1161
- return { data: SemanticTokens.transformSpans(doc, spans) };
1162
- }
1163
- catch {
1164
- return { data: [] };
1165
- }
1166
- }
1167
- }
1168
- //# sourceMappingURL=lsp-server.js.map