typescript-language-server 5.1.1 → 5.1.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.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,21 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [5.1.3](https://github.com/typescript-language-server/typescript-language-server/compare/v5.1.2...v5.1.3) (2025-11-19)
5
+
6
+
7
+ ### Bug Fixes
8
+
9
+ * announce all supported commands ([#1053](https://github.com/typescript-language-server/typescript-language-server/issues/1053)) ([e9fe952](https://github.com/typescript-language-server/typescript-language-server/commit/e9fe952baee4030aad6fbc24fb55bf2b84ad98e8))
10
+ * don't send duplicate refactors when more than one context.only ([#1055](https://github.com/typescript-language-server/typescript-language-server/issues/1055)) ([6ca045a](https://github.com/typescript-language-server/typescript-language-server/commit/6ca045aede0931180077c43daa14d586bdccc38f))
11
+
12
+ ## [5.1.2](https://github.com/typescript-language-server/typescript-language-server/compare/v5.1.1...v5.1.2) (2025-11-18)
13
+
14
+
15
+ ### Refactors
16
+
17
+ * cache file formatting configuration requests ([#1048](https://github.com/typescript-language-server/typescript-language-server/issues/1048)) ([9a366df](https://github.com/typescript-language-server/typescript-language-server/commit/9a366dfc7a989829f4b9e53017c298b565a307fd))
18
+
4
19
  ## [5.1.1](https://github.com/typescript-language-server/typescript-language-server/compare/v5.1.0...v5.1.1) (2025-11-05)
5
20
 
6
21
 
package/README.md CHANGED
@@ -305,7 +305,7 @@ The `$/typescriptVersion` notification params include two properties:
305
305
 
306
306
  ### Workspace Configuration request for formatting settings
307
307
 
308
- Server asks the client for file-specific configuration options (`tabSize` and `insertSpaces`) that are required by `tsserver` to properly format file edits when for example using "Organize imports" or performing other file modifications. Those options have to be dynamically provided by the client/editor since the values can differ for each file. For this reason server sends a `workspace/configuration` request with `scopeUri` equal to file's URI and `section` equal to `formattingOptions`. The client is expected to return a configuration that includes the following properties:
308
+ Server asks the client (provided client supports `workspace/configuration` capability) for file-specific configuration options (`tabSize` and `insertSpaces`) that are required by `tsserver` to properly format file edits when for example using "Organize imports" or performing other file modifications. Those options have to be dynamically provided by the client/editor since the values can differ for each file. For this reason server sends a `workspace/configuration` request with `scopeUri` equal to file's URI and `section` equal to `formattingOptions`. The client is expected to return a configuration that includes the following properties:
309
309
 
310
310
  ```js
311
311
  {
package/lib/cli.mjs CHANGED
@@ -21442,17 +21442,32 @@ function areFileConfigurationsEqual(a, b) {
21442
21442
  }
21443
21443
 
21444
21444
  class FileConfigurationManager {
21445
- constructor(client, lspClient, onCaseInsensitiveFileSystem) {
21445
+ constructor(client, lspClient, features, onCaseInsensitiveFileSystem) {
21446
21446
  this.client = client;
21447
21447
  this.lspClient = lspClient;
21448
+ this.features = features;
21448
21449
  this.tsPreferences = deepmerge({}, DEFAULT_TSSERVER_PREFERENCES);
21449
21450
  this.workspaceConfiguration = deepmerge({}, DEFAULT_WORKSPACE_CONFIGURATION);
21450
- this.formatOptions = new ResourceMap(undefined, {
21451
+ this.fileOptionsCache = new ResourceMap(undefined, {
21452
+ onCaseInsensitiveFileSystem: onCaseInsensitiveFileSystem
21453
+ });
21454
+ this.formatOptionsCache = new ResourceMap(undefined, {
21455
+ onCaseInsensitiveFileSystem: onCaseInsensitiveFileSystem
21456
+ });
21457
+ this.initialConfigurationRequestsMap = new ResourceMap(undefined, {
21451
21458
  onCaseInsensitiveFileSystem: onCaseInsensitiveFileSystem
21452
21459
  });
21453
21460
  }
21461
+ onDidOpenTextDocument(document) {
21462
+ const cancellation = new lsp$1.CancellationTokenSource;
21463
+ this.initialConfigurationRequestsMap.set(document.uri, cancellation);
21464
+ this.ensureConfigurationForDocument(document, cancellation.token).then(() => {
21465
+ this.initialConfigurationRequestsMap.delete(document.uri);
21466
+ }).catch(() => {});
21467
+ }
21454
21468
  onDidCloseTextDocument(documentUri) {
21455
- this.formatOptions.delete(documentUri);
21469
+ this.fileOptionsCache.delete(documentUri);
21470
+ this.initialConfigurationRequestsMap.get(documentUri)?.cancel();
21456
21471
  }
21457
21472
  mergeTsPreferences(preferences) {
21458
21473
  this.tsPreferences = deepmerge(this.tsPreferences, preferences);
@@ -21493,7 +21508,11 @@ class FileConfigurationManager {
21493
21508
  return this.ensureConfigurationOptions(document, formattingOptions, token);
21494
21509
  }
21495
21510
  async getFormattingOptions(document) {
21496
- const formatConfiguration = await this.lspClient.getWorkspaceConfiguration(document.uri.toString(), 'formattingOptions') || {};
21511
+ const formatOptionsCached = this.formatOptionsCache.get(document.uri);
21512
+ if (formatOptionsCached) {
21513
+ return formatOptionsCached;
21514
+ }
21515
+ const formatConfiguration = this.features.workspaceConfigurationSuppport ? await this.lspClient.getWorkspaceConfiguration(document.uri.toString(), 'formattingOptions') || {} : {};
21497
21516
  const options = {};
21498
21517
  if (typeof formatConfiguration.tabSize === 'number') {
21499
21518
  options.tabSize = formatConfiguration.tabSize;
@@ -21501,11 +21520,12 @@ class FileConfigurationManager {
21501
21520
  if (typeof formatConfiguration.insertSpaces === 'boolean') {
21502
21521
  options.insertSpaces = formatConfiguration.insertSpaces;
21503
21522
  }
21523
+ this.formatOptionsCache.set(document.uri, options);
21504
21524
  return options;
21505
21525
  }
21506
21526
  async ensureConfigurationOptions(document, options, token) {
21507
21527
  const currentOptions = this.getFileOptions(document, options);
21508
- const cachedOptions = this.formatOptions.get(document.uri);
21528
+ const cachedOptions = this.fileOptionsCache.get(document.uri);
21509
21529
  if (cachedOptions) {
21510
21530
  const cachedOptionsValue = await cachedOptions;
21511
21531
  if (token?.isCancellationRequested) {
@@ -21526,7 +21546,7 @@ class FileConfigurationManager {
21526
21546
  return undefined;
21527
21547
  }
21528
21548
  })();
21529
- this.formatOptions.set(document.uri, task);
21549
+ this.fileOptionsCache.set(document.uri, task);
21530
21550
  await task;
21531
21551
  }
21532
21552
  async setGlobalConfigurationFromDocument(document, token) {
@@ -21537,7 +21557,9 @@ class FileConfigurationManager {
21537
21557
  await this.client.execute(CommandTypes.Configure, args, token);
21538
21558
  }
21539
21559
  reset() {
21540
- this.formatOptions.clear();
21560
+ this.fileOptionsCache.clear();
21561
+ this.formatOptionsCache.clear();
21562
+ this.initialConfigurationRequestsMap.clear();
21541
21563
  }
21542
21564
  getFileOptions(document, options) {
21543
21565
  return {
@@ -22454,6 +22476,9 @@ class CommandManager {
22454
22476
  this.commands.set(command.id, command);
22455
22477
  }
22456
22478
  }
22479
+ get registeredIds() {
22480
+ return Array.from(this.commands.keys());
22481
+ }
22457
22482
  async handle(commandId, ...args) {
22458
22483
  const entry = this.commands.get(commandId);
22459
22484
  if (entry) {
@@ -23173,7 +23198,7 @@ class LspServer {
23173
23198
  this.referencesCodeLensProvider = null;
23174
23199
  this.logger = new PrefixingLogger(options.logger, '[lspserver]');
23175
23200
  this.tsClient = new TsClient(onCaseInsensitiveFileSystem(), this.logger, options.lspClient);
23176
- this.fileConfigurationManager = new FileConfigurationManager(this.tsClient, this.options.lspClient, onCaseInsensitiveFileSystem());
23201
+ this.fileConfigurationManager = new FileConfigurationManager(this.tsClient, this.options.lspClient, this.features, onCaseInsensitiveFileSystem());
23177
23202
  this.commandManager = new CommandManager;
23178
23203
  this.diagnosticsManager = new DiagnosticsManager(diagnostics => this.options.lspClient.publishDiagnostics(diagnostics), this.tsClient, this.features, this.logger);
23179
23204
  this.codeActionsManager = new CodeActionManager(this.tsClient, this.fileConfigurationManager, this.commandManager, this.diagnosticsManager, this.features);
@@ -23211,7 +23236,7 @@ class LspServer {
23211
23236
  this.fileConfigurationManager.mergeTsPreferences(userInitializationOptions.preferences || {});
23212
23237
  this.features.completionDisableFilterText = userInitializationOptions.completionDisableFilterText ?? false;
23213
23238
  this.features.moveToFileCodeActionSupport = userInitializationOptions.supportsMoveToFileCodeAction && typescriptVersion.version?.gte(API.v520);
23214
- const {textDocument: textDocument} = clientCapabilities;
23239
+ const {textDocument: textDocument, workspace: workspace} = clientCapabilities;
23215
23240
  if (textDocument) {
23216
23241
  const {codeAction: codeAction, completion: completion, definition: definition, publishDiagnostics: publishDiagnostics} = textDocument;
23217
23242
  if (codeAction) {
@@ -23234,6 +23259,9 @@ class LspServer {
23234
23259
  this.features.diagnosticsSupport = Boolean(publishDiagnostics);
23235
23260
  this.features.diagnosticsTagSupport = Boolean(publishDiagnostics?.tagSupport);
23236
23261
  }
23262
+ if (workspace?.configuration) {
23263
+ this.features.workspaceConfigurationSuppport = true;
23264
+ }
23237
23265
  this.fileConfigurationManager.mergeTsPreferences({
23238
23266
  useLabelDetailsInCompletionEntries: this.features.completionLabelDetails
23239
23267
  });
@@ -23295,7 +23323,7 @@ class LspServer {
23295
23323
  documentHighlightProvider: true,
23296
23324
  documentSymbolProvider: true,
23297
23325
  executeCommandProvider: {
23298
- commands: [ Commands.APPLY_REFACTORING, Commands.CONFIGURE_PLUGIN, Commands.ORGANIZE_IMPORTS, Commands.APPLY_RENAME_FILE, Commands.SOURCE_DEFINITION, Commands.TS_SERVER_REQUEST ]
23326
+ commands: [ Commands.APPLY_REFACTORING, Commands.CONFIGURE_PLUGIN, Commands.ORGANIZE_IMPORTS, Commands.APPLY_RENAME_FILE, Commands.SOURCE_DEFINITION, Commands.TS_SERVER_REQUEST, ...this.commandManager.registeredIds ]
23299
23327
  },
23300
23328
  hoverProvider: true,
23301
23329
  inlayHintProvider: true,
@@ -23409,13 +23437,18 @@ class LspServer {
23409
23437
  this.tsClient.interruptGetErr(() => this.diagnosticsManager.updateIgnoredDiagnosticCodes(ignoredDiagnosticCodes));
23410
23438
  }
23411
23439
  didOpenTextDocument(params) {
23412
- if (this.tsClient.toOpenDocument(params.textDocument.uri, {
23440
+ const {uri: uri, languageId: languageId} = params.textDocument;
23441
+ if (this.tsClient.toOpenDocument(uri, {
23413
23442
  suppressAlertOnFailure: true
23414
23443
  })) {
23415
- throw new Error(`Can't open already open document: ${params.textDocument.uri}`);
23444
+ throw new Error(`Can't open already open document: ${uri}`);
23416
23445
  }
23417
23446
  if (!this.tsClient.openTextDocument(params.textDocument)) {
23418
- throw new Error(`Cannot open document '${params.textDocument.uri}' (languageId: ${params.textDocument.languageId}).`);
23447
+ throw new Error(`Cannot open document '${uri}' (languageId: ${languageId}).`);
23448
+ }
23449
+ const document = this.tsClient.toOpenDocument(uri);
23450
+ if (document) {
23451
+ this.fileConfigurationManager.onDidOpenTextDocument(document);
23419
23452
  }
23420
23453
  }
23421
23454
  didCloseTextDocument(params) {
@@ -23789,7 +23822,7 @@ class LspServer {
23789
23822
  return actions;
23790
23823
  }
23791
23824
  async getRefactors(fileRangeArgs, context, features, token) {
23792
- const kinds = context.only || [ undefined ];
23825
+ const kinds = (context.only || [ undefined ]).filter(kind => kind === undefined || CodeActionKind.Refactor.contains(new CodeActionKind(kind)));
23793
23826
  const responses = await Promise.all(kinds.map(async kind => {
23794
23827
  const args = {
23795
23828
  ...fileRangeArgs,