typescript-language-server 5.1.0 → 5.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 CHANGED
@@ -1,6 +1,20 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [5.1.2](https://github.com/typescript-language-server/typescript-language-server/compare/v5.1.1...v5.1.2) (2025-11-18)
5
+
6
+
7
+ ### Refactors
8
+
9
+ * 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))
10
+
11
+ ## [5.1.1](https://github.com/typescript-language-server/typescript-language-server/compare/v5.1.0...v5.1.1) (2025-11-05)
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * don't override formatting options with undefined values ([#1041](https://github.com/typescript-language-server/typescript-language-server/issues/1041)) ([4645124](https://github.com/typescript-language-server/typescript-language-server/commit/464512454a1f68bb6f1e270cf5c0c2be13cdaa54))
17
+
4
18
  ## [5.1.0](https://github.com/typescript-language-server/typescript-language-server/compare/v5.0.1...v5.1.0) (2025-10-31)
5
19
 
6
20
 
package/README.md CHANGED
@@ -156,7 +156,7 @@ Request:
156
156
  {
157
157
  command: '_typescript.organizeImports'
158
158
  arguments: [
159
- string, // file URI
159
+ string, // file path
160
160
  // Optional options:
161
161
  {
162
162
  // @deprecated - use "mode". Supported from Typescript 4.4+.
@@ -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 the 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, {
21451
21452
  onCaseInsensitiveFileSystem: onCaseInsensitiveFileSystem
21452
21453
  });
21454
+ this.formatOptionsCache = new ResourceMap(undefined, {
21455
+ onCaseInsensitiveFileSystem: onCaseInsensitiveFileSystem
21456
+ });
21457
+ this.initialConfigurationRequestsMap = new ResourceMap(undefined, {
21458
+ onCaseInsensitiveFileSystem: onCaseInsensitiveFileSystem
21459
+ });
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(() => {});
21453
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,15 +21508,24 @@ 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') || {};
21497
- return {
21498
- tabSize: typeof formatConfiguration.tabSize === 'number' ? formatConfiguration.tabSize : undefined,
21499
- insertSpaces: typeof formatConfiguration.insertSpaces === 'boolean' ? formatConfiguration.insertSpaces : undefined
21500
- };
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') || {} : {};
21516
+ const options = {};
21517
+ if (typeof formatConfiguration.tabSize === 'number') {
21518
+ options.tabSize = formatConfiguration.tabSize;
21519
+ }
21520
+ if (typeof formatConfiguration.insertSpaces === 'boolean') {
21521
+ options.insertSpaces = formatConfiguration.insertSpaces;
21522
+ }
21523
+ this.formatOptionsCache.set(document.uri, options);
21524
+ return options;
21501
21525
  }
21502
21526
  async ensureConfigurationOptions(document, options, token) {
21503
21527
  const currentOptions = this.getFileOptions(document, options);
21504
- const cachedOptions = this.formatOptions.get(document.uri);
21528
+ const cachedOptions = this.fileOptionsCache.get(document.uri);
21505
21529
  if (cachedOptions) {
21506
21530
  const cachedOptionsValue = await cachedOptions;
21507
21531
  if (token?.isCancellationRequested) {
@@ -21522,7 +21546,7 @@ class FileConfigurationManager {
21522
21546
  return undefined;
21523
21547
  }
21524
21548
  })();
21525
- this.formatOptions.set(document.uri, task);
21549
+ this.fileOptionsCache.set(document.uri, task);
21526
21550
  await task;
21527
21551
  }
21528
21552
  async setGlobalConfigurationFromDocument(document, token) {
@@ -21533,7 +21557,9 @@ class FileConfigurationManager {
21533
21557
  await this.client.execute(CommandTypes.Configure, args, token);
21534
21558
  }
21535
21559
  reset() {
21536
- this.formatOptions.clear();
21560
+ this.fileOptionsCache.clear();
21561
+ this.formatOptionsCache.clear();
21562
+ this.initialConfigurationRequestsMap.clear();
21537
21563
  }
21538
21564
  getFileOptions(document, options) {
21539
21565
  return {
@@ -23169,7 +23195,7 @@ class LspServer {
23169
23195
  this.referencesCodeLensProvider = null;
23170
23196
  this.logger = new PrefixingLogger(options.logger, '[lspserver]');
23171
23197
  this.tsClient = new TsClient(onCaseInsensitiveFileSystem(), this.logger, options.lspClient);
23172
- this.fileConfigurationManager = new FileConfigurationManager(this.tsClient, this.options.lspClient, onCaseInsensitiveFileSystem());
23198
+ this.fileConfigurationManager = new FileConfigurationManager(this.tsClient, this.options.lspClient, this.features, onCaseInsensitiveFileSystem());
23173
23199
  this.commandManager = new CommandManager;
23174
23200
  this.diagnosticsManager = new DiagnosticsManager(diagnostics => this.options.lspClient.publishDiagnostics(diagnostics), this.tsClient, this.features, this.logger);
23175
23201
  this.codeActionsManager = new CodeActionManager(this.tsClient, this.fileConfigurationManager, this.commandManager, this.diagnosticsManager, this.features);
@@ -23207,7 +23233,7 @@ class LspServer {
23207
23233
  this.fileConfigurationManager.mergeTsPreferences(userInitializationOptions.preferences || {});
23208
23234
  this.features.completionDisableFilterText = userInitializationOptions.completionDisableFilterText ?? false;
23209
23235
  this.features.moveToFileCodeActionSupport = userInitializationOptions.supportsMoveToFileCodeAction && typescriptVersion.version?.gte(API.v520);
23210
- const {textDocument: textDocument} = clientCapabilities;
23236
+ const {textDocument: textDocument, workspace: workspace} = clientCapabilities;
23211
23237
  if (textDocument) {
23212
23238
  const {codeAction: codeAction, completion: completion, definition: definition, publishDiagnostics: publishDiagnostics} = textDocument;
23213
23239
  if (codeAction) {
@@ -23230,6 +23256,9 @@ class LspServer {
23230
23256
  this.features.diagnosticsSupport = Boolean(publishDiagnostics);
23231
23257
  this.features.diagnosticsTagSupport = Boolean(publishDiagnostics?.tagSupport);
23232
23258
  }
23259
+ if (workspace?.configuration) {
23260
+ this.features.workspaceConfigurationSuppport = true;
23261
+ }
23233
23262
  this.fileConfigurationManager.mergeTsPreferences({
23234
23263
  useLabelDetailsInCompletionEntries: this.features.completionLabelDetails
23235
23264
  });
@@ -23405,13 +23434,18 @@ class LspServer {
23405
23434
  this.tsClient.interruptGetErr(() => this.diagnosticsManager.updateIgnoredDiagnosticCodes(ignoredDiagnosticCodes));
23406
23435
  }
23407
23436
  didOpenTextDocument(params) {
23408
- if (this.tsClient.toOpenDocument(params.textDocument.uri, {
23437
+ const {uri: uri, languageId: languageId} = params.textDocument;
23438
+ if (this.tsClient.toOpenDocument(uri, {
23409
23439
  suppressAlertOnFailure: true
23410
23440
  })) {
23411
- throw new Error(`Can't open already open document: ${params.textDocument.uri}`);
23441
+ throw new Error(`Can't open already open document: ${uri}`);
23412
23442
  }
23413
23443
  if (!this.tsClient.openTextDocument(params.textDocument)) {
23414
- throw new Error(`Cannot open document '${params.textDocument.uri}' (languageId: ${params.textDocument.languageId}).`);
23444
+ throw new Error(`Cannot open document '${uri}' (languageId: ${languageId}).`);
23445
+ }
23446
+ const document = this.tsClient.toOpenDocument(uri);
23447
+ if (document) {
23448
+ this.fileConfigurationManager.onDidOpenTextDocument(document);
23415
23449
  }
23416
23450
  }
23417
23451
  didCloseTextDocument(params) {
@@ -23580,7 +23614,6 @@ class LspServer {
23580
23614
  const uri = this.tsClient.toResourceUri(cachedData.file);
23581
23615
  document = this.tsClient.toOpenDocument(uri);
23582
23616
  if (document) {
23583
- await this.fileConfigurationManager.ensureConfigurationForDocument(document, token);
23584
23617
  const response = await this.tsClient.interruptGetErr(() => this.tsClient.execute(CommandTypes.CompletionDetails, cachedData, token));
23585
23618
  if (response.type !== 'response' || !response.body?.length) {
23586
23619
  return item;