typescript-language-server 5.0.0 → 5.0.1

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/lib/cli.mjs CHANGED
@@ -12990,6 +12990,28 @@ function requireStat() {
12990
12990
  return stat;
12991
12991
  }
12992
12992
 
12993
+ var async;
12994
+
12995
+ var hasRequiredAsync;
12996
+
12997
+ function requireAsync() {
12998
+ if (hasRequiredAsync) return async;
12999
+ hasRequiredAsync = 1;
13000
+ async function asyncIteratorConcurrentProcess(iterator, fn) {
13001
+ const promises = [];
13002
+ for await (const item of iterator) {
13003
+ promises.push(fn(item).then(() => null, err => err ?? new Error('unknown error')));
13004
+ }
13005
+ await Promise.all(promises.map(promise => promise.then(possibleErr => {
13006
+ if (possibleErr !== null) throw possibleErr;
13007
+ })));
13008
+ }
13009
+ async = {
13010
+ asyncIteratorConcurrentProcess: asyncIteratorConcurrentProcess
13011
+ };
13012
+ return async;
13013
+ }
13014
+
12993
13015
  var copy_1;
12994
13016
 
12995
13017
  var hasRequiredCopy$1;
@@ -13003,6 +13025,7 @@ function requireCopy$1() {
13003
13025
  const {pathExists: pathExists} = requirePathExists();
13004
13026
  const {utimesMillis: utimesMillis} = requireUtimes();
13005
13027
  const stat = requireStat();
13028
+ const {asyncIteratorConcurrentProcess: asyncIteratorConcurrentProcess} = requireAsync();
13006
13029
  async function copy(src, dest, opts = {}) {
13007
13030
  if (typeof opts === 'function') {
13008
13031
  opts = {
@@ -13070,17 +13093,15 @@ function requireCopy$1() {
13070
13093
  if (!destStat) {
13071
13094
  await fs.mkdir(dest);
13072
13095
  }
13073
- const promises = [];
13074
- for await (const item of await fs.opendir(src)) {
13096
+ await asyncIteratorConcurrentProcess(await fs.opendir(src), async item => {
13075
13097
  const srcItem = path.join(src, item.name);
13076
13098
  const destItem = path.join(dest, item.name);
13077
- promises.push(runFilter(srcItem, destItem, opts).then(include => {
13078
- if (include) {
13079
- return stat.checkPaths(srcItem, destItem, 'copy', opts).then(({destStat: destStat}) => getStatsAndPerformCopy(destStat, srcItem, destItem, opts));
13080
- }
13081
- }));
13082
- }
13083
- await Promise.all(promises);
13099
+ const include = await runFilter(srcItem, destItem, opts);
13100
+ if (include) {
13101
+ const {destStat: destStat} = await stat.checkPaths(srcItem, destItem, 'copy', opts);
13102
+ await getStatsAndPerformCopy(destStat, srcItem, destItem, opts);
13103
+ }
13104
+ });
13084
13105
  if (!destStat) {
13085
13106
  await fs.chmod(dest, srcStat.mode);
13086
13107
  }
@@ -18191,7 +18212,7 @@ class SingleTsServer {
18191
18212
  tryCancelRequest(seq, command) {
18192
18213
  try {
18193
18214
  if (this._requestQueue.tryDeletePendingRequest(seq)) {
18194
- this.logTrace(`Canceled request with sequence number ${seq}`);
18215
+ this.logTrace(`Canceled pending request with sequence number ${seq}`);
18195
18216
  return true;
18196
18217
  }
18197
18218
  if (this._requestCanceller.tryCancelOngoingRequest(seq)) {
@@ -19305,7 +19326,8 @@ class TsClient {
19305
19326
  executions[0].catch(err => this.fatalError(command, err));
19306
19327
  }
19307
19328
  if (command === CommandTypes.UpdateOpen) {
19308
- Promise.all(executions).then(() => {
19329
+ const executionsWithResults = executions.filter(e => e !== undefined);
19330
+ Promise.all(executionsWithResults).then(() => {
19309
19331
  this.loadingIndicator.reset();
19310
19332
  });
19311
19333
  }
@@ -19375,30 +19397,73 @@ class TsClient {
19375
19397
  }
19376
19398
  }
19377
19399
 
19378
- const pDebounce = (fn, wait, options = {}) => {
19400
+ const pDebounce = (function_, wait, options = {}) => {
19379
19401
  if (!Number.isFinite(wait)) {
19380
19402
  throw new TypeError('Expected `wait` to be a finite number');
19381
19403
  }
19382
19404
  let leadingValue;
19383
19405
  let timeout;
19384
19406
  let resolveList = [];
19407
+ let rejectList = [];
19408
+ const onAbort = () => {
19409
+ clearTimeout(timeout);
19410
+ timeout = null;
19411
+ try {
19412
+ options.signal?.throwIfAborted();
19413
+ } catch (error) {
19414
+ for (const reject of rejectList) {
19415
+ reject(error);
19416
+ }
19417
+ resolveList = [];
19418
+ rejectList = [];
19419
+ }
19420
+ };
19385
19421
  return function(...arguments_) {
19386
- return new Promise(resolve => {
19422
+ return new Promise((resolve, reject) => {
19423
+ try {
19424
+ options.signal?.throwIfAborted();
19425
+ } catch (error) {
19426
+ reject(error);
19427
+ return;
19428
+ }
19387
19429
  const shouldCallNow = options.before && !timeout;
19388
19430
  clearTimeout(timeout);
19389
- timeout = setTimeout(() => {
19431
+ timeout = setTimeout(async () => {
19390
19432
  timeout = null;
19391
- const result = options.before ? leadingValue : fn.apply(this, arguments_);
19392
- for (resolve of resolveList) {
19393
- resolve(result);
19394
- }
19433
+ const currentResolveList = resolveList;
19434
+ const currentRejectList = rejectList;
19395
19435
  resolveList = [];
19436
+ rejectList = [];
19437
+ try {
19438
+ const result = options.before ? leadingValue : await function_.apply(this, arguments_);
19439
+ for (const resolveFunction of currentResolveList) {
19440
+ resolveFunction(result);
19441
+ }
19442
+ } catch (error) {
19443
+ for (const rejectFunction of currentRejectList) {
19444
+ rejectFunction(error);
19445
+ }
19446
+ }
19447
+ leadingValue = undefined;
19448
+ options.signal?.removeEventListener('abort', onAbort);
19396
19449
  }, wait);
19397
19450
  if (shouldCallNow) {
19398
- leadingValue = fn.apply(this, arguments_);
19399
- resolve(leadingValue);
19451
+ (async () => {
19452
+ try {
19453
+ leadingValue = await function_.apply(this, arguments_);
19454
+ resolve(leadingValue);
19455
+ } catch (error) {
19456
+ reject(error);
19457
+ }
19458
+ })();
19400
19459
  } else {
19401
19460
  resolveList.push(resolve);
19461
+ rejectList.push(reject);
19462
+ if (options.signal && resolveList.length === 1) {
19463
+ options.signal.addEventListener('abort', onAbort, {
19464
+ once: true
19465
+ });
19466
+ }
19402
19467
  }
19403
19468
  });
19404
19469
  };
@@ -19741,7 +19806,7 @@ class FileDiagnostics {
19741
19806
  }
19742
19807
  }
19743
19808
 
19744
- class DiagnosticEventQueue {
19809
+ class DiagnosticsManager {
19745
19810
  constructor(publishDiagnostics, client, features, logger) {
19746
19811
  this.publishDiagnostics = publishDiagnostics;
19747
19812
  this.client = client;
@@ -19858,8 +19923,6 @@ class TSServerRequestCommand {
19858
19923
  TSServerRequestCommand.id = 'typescript.tsserverRequest';
19859
19924
 
19860
19925
  const Commands = {
19861
- APPLY_WORKSPACE_EDIT: '_typescript.applyWorkspaceEdit',
19862
- APPLY_CODE_ACTION: '_typescript.applyCodeAction',
19863
19926
  APPLY_REFACTORING: '_typescript.applyRefactoring',
19864
19927
  CONFIGURE_PLUGIN: '_typescript.configurePlugin',
19865
19928
  ORGANIZE_IMPORTS: '_typescript.organizeImports',
@@ -20682,19 +20745,6 @@ function toTsTriggerReason(context) {
20682
20745
  }
20683
20746
  }
20684
20747
 
20685
- function provideQuickFix(response, client) {
20686
- if (!response?.body) {
20687
- return [];
20688
- }
20689
- return response.body.map(fix => mainExports$2.CodeAction.create(fix.description, {
20690
- title: fix.description,
20691
- command: Commands.APPLY_WORKSPACE_EDIT,
20692
- arguments: [ {
20693
- documentChanges: fix.changes.map(c => toTextDocumentEdit(c, client))
20694
- } ]
20695
- }, mainExports$2.CodeActionKind.QuickFix));
20696
- }
20697
-
20698
20748
  var CodeActionKind$1;
20699
20749
 
20700
20750
  (function(CodeActionKind) {
@@ -21440,187 +21490,6 @@ class FileConfigurationManager {
21440
21490
  }
21441
21491
  }
21442
21492
 
21443
- const variableDeclaredButNeverUsed = new Set([ 6196, 6133 ]);
21444
-
21445
- const unreachableCode$1 = new Set([ 7027 ]);
21446
-
21447
- const incorrectlyImplementsInterface = new Set([ 2420 ]);
21448
-
21449
- const cannotFindName = new Set([ 2552, 2304 ]);
21450
-
21451
- const asyncOnlyAllowedInAsyncFunctions = new Set([ 1308 ]);
21452
-
21453
- const awaitInSyncFunction = 'fixAwaitInSyncFunction';
21454
-
21455
- const classIncorrectlyImplementsInterface = 'fixClassIncorrectlyImplementsInterface';
21456
-
21457
- const unreachableCode = 'fixUnreachableCode';
21458
-
21459
- const unusedIdentifier = 'unusedIdentifier';
21460
-
21461
- const fixImport = 'import';
21462
-
21463
- async function buildIndividualFixes(fixes, client, file, diagnostics) {
21464
- const edits = [];
21465
- for (const diagnostic of diagnostics) {
21466
- for (const {codes: codes, fixName: fixName} of fixes) {
21467
- if (!codes.has(diagnostic.code)) {
21468
- continue;
21469
- }
21470
- const args = {
21471
- ...Range.toFileRangeRequestArgs(file, diagnostic.range),
21472
- errorCodes: [ +diagnostic.code ]
21473
- };
21474
- const response = await client.execute(CommandTypes.GetCodeFixes, args);
21475
- if (response.type !== 'response') {
21476
- continue;
21477
- }
21478
- const fix = response.body?.find(fix => fix.fixName === fixName);
21479
- if (fix) {
21480
- edits.push(...fix.changes.map(change => toTextDocumentEdit(change, client)));
21481
- break;
21482
- }
21483
- }
21484
- }
21485
- return edits;
21486
- }
21487
-
21488
- async function buildCombinedFix(fixes, client, file, diagnostics) {
21489
- const edits = [];
21490
- for (const diagnostic of diagnostics) {
21491
- for (const {codes: codes, fixName: fixName} of fixes) {
21492
- if (!codes.has(diagnostic.code)) {
21493
- continue;
21494
- }
21495
- const args = {
21496
- ...Range.toFileRangeRequestArgs(file, diagnostic.range),
21497
- errorCodes: [ +diagnostic.code ]
21498
- };
21499
- const response = await client.execute(CommandTypes.GetCodeFixes, args);
21500
- if (response.type !== 'response' || !response.body?.length) {
21501
- continue;
21502
- }
21503
- const fix = response.body?.find(fix => fix.fixName === fixName);
21504
- if (!fix) {
21505
- continue;
21506
- }
21507
- if (!fix.fixId) {
21508
- edits.push(...fix.changes.map(change => toTextDocumentEdit(change, client)));
21509
- return edits;
21510
- }
21511
- const combinedArgs = {
21512
- scope: {
21513
- type: 'file',
21514
- args: {
21515
- file: file
21516
- }
21517
- },
21518
- fixId: fix.fixId
21519
- };
21520
- const combinedResponse = await client.execute(CommandTypes.GetCombinedCodeFix, combinedArgs);
21521
- if (combinedResponse.type !== 'response' || !combinedResponse.body) {
21522
- return edits;
21523
- }
21524
- edits.push(...combinedResponse.body.changes.map(change => toTextDocumentEdit(change, client)));
21525
- return edits;
21526
- }
21527
- }
21528
- return edits;
21529
- }
21530
-
21531
- class SourceAction {}
21532
-
21533
- class SourceFixAll extends SourceAction {
21534
- constructor() {
21535
- super(...arguments);
21536
- this.title = 'Fix all';
21537
- }
21538
- async build(client, file, diagnostics) {
21539
- const edits = [];
21540
- edits.push(...await buildIndividualFixes([ {
21541
- codes: incorrectlyImplementsInterface,
21542
- fixName: classIncorrectlyImplementsInterface
21543
- }, {
21544
- codes: asyncOnlyAllowedInAsyncFunctions,
21545
- fixName: awaitInSyncFunction
21546
- } ], client, file, diagnostics));
21547
- edits.push(...await buildCombinedFix([ {
21548
- codes: unreachableCode$1,
21549
- fixName: unreachableCode
21550
- } ], client, file, diagnostics));
21551
- if (!edits.length) {
21552
- return null;
21553
- }
21554
- return mainExports$2.CodeAction.create(this.title, {
21555
- documentChanges: edits
21556
- }, SourceFixAll.kind.value);
21557
- }
21558
- }
21559
-
21560
- SourceFixAll.kind = CodeActionKind.SourceFixAllTs;
21561
-
21562
- class SourceRemoveUnused extends SourceAction {
21563
- constructor() {
21564
- super(...arguments);
21565
- this.title = 'Remove all unused code';
21566
- }
21567
- async build(client, file, diagnostics) {
21568
- const edits = await buildCombinedFix([ {
21569
- codes: variableDeclaredButNeverUsed,
21570
- fixName: unusedIdentifier
21571
- } ], client, file, diagnostics);
21572
- if (!edits.length) {
21573
- return null;
21574
- }
21575
- return mainExports$2.CodeAction.create(this.title, {
21576
- documentChanges: edits
21577
- }, SourceRemoveUnused.kind.value);
21578
- }
21579
- }
21580
-
21581
- SourceRemoveUnused.kind = CodeActionKind.SourceRemoveUnusedTs;
21582
-
21583
- class SourceAddMissingImports extends SourceAction {
21584
- constructor() {
21585
- super(...arguments);
21586
- this.title = 'Add all missing imports';
21587
- }
21588
- async build(client, file, diagnostics) {
21589
- const edits = await buildCombinedFix([ {
21590
- codes: cannotFindName,
21591
- fixName: fixImport
21592
- } ], client, file, diagnostics);
21593
- if (!edits.length) {
21594
- return null;
21595
- }
21596
- return mainExports$2.CodeAction.create(this.title, {
21597
- documentChanges: edits
21598
- }, SourceAddMissingImports.kind.value);
21599
- }
21600
- }
21601
-
21602
- SourceAddMissingImports.kind = CodeActionKind.SourceAddMissingImportsTs;
21603
-
21604
- class TypeScriptAutoFixProvider {
21605
- static get kinds() {
21606
- return TypeScriptAutoFixProvider.kindProviders.map(provider => provider.kind);
21607
- }
21608
- constructor(client) {
21609
- this.client = client;
21610
- }
21611
- async provideCodeActions(kinds, file, diagnostics) {
21612
- const results = [];
21613
- for (const provider of TypeScriptAutoFixProvider.kindProviders) {
21614
- if (kinds.some(kind => kind.contains(provider.kind))) {
21615
- results.push((new provider).build(this.client, file, diagnostics));
21616
- }
21617
- }
21618
- return (await Promise.all(results)).flatMap(result => result || []);
21619
- }
21620
- }
21621
-
21622
- TypeScriptAutoFixProvider.kindProviders = [ SourceFixAll, SourceRemoveUnused, SourceAddMissingImports ];
21623
-
21624
21493
  function escapeRegExp(text) {
21625
21494
  return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
21626
21495
  }
@@ -22465,60 +22334,783 @@ class TypeScriptVersionProvider {
22465
22334
  }
22466
22335
  }
22467
22336
 
22468
- class LspServer {
22469
- constructor(options) {
22470
- this.options = options;
22471
- this.initializeParams = null;
22472
- this.completionDataCache = new CompletionDataCache;
22473
- this.typeScriptAutoFixProvider = null;
22474
- this.features = {};
22475
- this.cachedNavTreeResponse = new CachedResponse;
22476
- this.implementationsCodeLensProvider = null;
22477
- this.referencesCodeLensProvider = null;
22478
- this.logger = new PrefixingLogger(options.logger, '[lspserver]');
22479
- this.tsClient = new TsClient(onCaseInsensitiveFileSystem(), this.logger, options.lspClient);
22480
- this.fileConfigurationManager = new FileConfigurationManager(this.tsClient, onCaseInsensitiveFileSystem());
22481
- this.diagnosticQueue = new DiagnosticEventQueue(diagnostics => this.options.lspClient.publishDiagnostics(diagnostics), this.tsClient, this.features, this.logger);
22337
+ class CommandManager {
22338
+ constructor() {
22339
+ this.commands = new Map;
22482
22340
  }
22483
- closeAllForTesting() {
22484
- for (const document of this.tsClient.documentsForTesting.values()) {
22485
- this.closeDocument(document.uri.toString());
22341
+ dispose() {
22342
+ this.commands.clear();
22343
+ }
22344
+ register(command) {
22345
+ const entry = this.commands.get(command.id);
22346
+ if (!entry) {
22347
+ this.commands.set(command.id, command);
22486
22348
  }
22487
22349
  }
22488
- async waitForDiagnosticsForFile(uri) {
22489
- const document = this.tsClient.toOpenDocument(uri);
22490
- if (!document) {
22491
- throw new Error(`Document not open: ${uri}`);
22350
+ async handle(commandId, ...args) {
22351
+ const entry = this.commands.get(commandId);
22352
+ if (entry) {
22353
+ await entry.execute(...args);
22354
+ return true;
22492
22355
  }
22493
- await this.diagnosticQueue.waitForDiagnosticsForTesting(document.filepath);
22356
+ return false;
22494
22357
  }
22495
- shutdown() {
22496
- this.tsClient.shutdown();
22358
+ }
22359
+
22360
+ const variableDeclaredButNeverUsed = new Set([ 6196, 6133 ]);
22361
+
22362
+ const unreachableCode$1 = new Set([ 7027 ]);
22363
+
22364
+ const incorrectlyImplementsInterface = new Set([ 2420 ]);
22365
+
22366
+ const cannotFindName = new Set([ 2552, 2304 ]);
22367
+
22368
+ const asyncOnlyAllowedInAsyncFunctions = new Set([ 1308 ]);
22369
+
22370
+ const addMissingAwait = 'addMissingAwait';
22371
+
22372
+ const addMissingNewOperator = 'addMissingNewOperator';
22373
+
22374
+ const addMissingOverride = 'fixOverrideModifier';
22375
+
22376
+ const annotateWithTypeFromJSDoc = 'annotateWithTypeFromJSDoc';
22377
+
22378
+ const awaitInSyncFunction = 'fixAwaitInSyncFunction';
22379
+
22380
+ const classDoesntImplementInheritedAbstractMember = 'fixClassDoesntImplementInheritedAbstractMember';
22381
+
22382
+ const classIncorrectlyImplementsInterface = 'fixClassIncorrectlyImplementsInterface';
22383
+
22384
+ const constructorForDerivedNeedSuperCall = 'constructorForDerivedNeedSuperCall';
22385
+
22386
+ const extendsInterfaceBecomesImplements = 'extendsInterfaceBecomesImplements';
22387
+
22388
+ const fixImport = 'import';
22389
+
22390
+ const forgottenThisPropertyAccess = 'forgottenThisPropertyAccess';
22391
+
22392
+ const removeUnnecessaryAwait = 'removeUnnecessaryAwait';
22393
+
22394
+ const spelling = 'spelling';
22395
+
22396
+ const unreachableCode = 'fixUnreachableCode';
22397
+
22398
+ const unusedIdentifier = 'unusedIdentifier';
22399
+
22400
+ class TsCodeAction {
22401
+ constructor(title, kind) {
22402
+ this.title = title;
22403
+ this.kind = kind;
22497
22404
  }
22498
- initialize(params) {
22499
- this.initializeParams = params;
22500
- const clientCapabilities = this.initializeParams.capabilities;
22501
- this.workspaceRoot = this.initializeParams.rootUri ? URI.parse(this.initializeParams.rootUri).fsPath : this.initializeParams.rootPath || undefined;
22502
- const userInitializationOptions = this.initializeParams.initializationOptions || {};
22503
- const {disableAutomaticTypingAcquisition: disableAutomaticTypingAcquisition, hostInfo: hostInfo, maxTsServerMemory: maxTsServerMemory, npmLocation: npmLocation, locale: locale, plugins: plugins, tsserver: tsserver} = userInitializationOptions;
22504
- const typescriptVersion = this.findTypescriptVersion(tsserver?.path, tsserver?.fallbackPath);
22505
- if (typescriptVersion) {
22506
- this.options.lspClient.logMessage({
22507
- type: mainExports$2.MessageType.Info,
22508
- message: `Using Typescript version (${typescriptVersion.source}) ${typescriptVersion.versionString} from path "${typescriptVersion.tsServerPath}"`
22509
- });
22510
- } else {
22511
- 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.');
22405
+ toLspCodeAction() {
22406
+ const codeAction = mainExports$2.CodeAction.create(this.title, this.kind);
22407
+ if (this.command !== undefined) {
22408
+ codeAction.command = this.command;
22512
22409
  }
22513
- this.fileConfigurationManager.mergeTsPreferences(userInitializationOptions.preferences || {});
22514
- this.features.completionDisableFilterText = userInitializationOptions.completionDisableFilterText ?? false;
22515
- this.features.moveToFileCodeActionSupport = userInitializationOptions.supportsMoveToFileCodeAction && typescriptVersion.version?.gte(API.v520);
22516
- const {textDocument: textDocument} = clientCapabilities;
22517
- if (textDocument) {
22518
- const {codeAction: codeAction, completion: completion, definition: definition, publishDiagnostics: publishDiagnostics} = textDocument;
22519
- if (codeAction) {
22520
- this.features.codeActionDisabledSupport = codeAction.disabledSupport;
22521
- }
22410
+ if (this.diagnostics !== undefined) {
22411
+ codeAction.diagnostics = this.diagnostics;
22412
+ }
22413
+ if (this.disabled !== undefined) {
22414
+ codeAction.disabled = this.disabled;
22415
+ }
22416
+ if (this.edit !== undefined) {
22417
+ codeAction.edit = this.edit;
22418
+ }
22419
+ if (this.isPreferred !== undefined) {
22420
+ codeAction.isPreferred = this.isPreferred;
22421
+ }
22422
+ return codeAction;
22423
+ }
22424
+ }
22425
+
22426
+ async function buildIndividualFixes(fixes, client, file, diagnostics, token) {
22427
+ const documentChanges = [];
22428
+ for (const diagnostic of diagnostics) {
22429
+ for (const {codes: codes, fixName: fixName} of fixes) {
22430
+ if (token.isCancellationRequested) {
22431
+ return;
22432
+ }
22433
+ if (!codes.has(diagnostic.code)) {
22434
+ continue;
22435
+ }
22436
+ const args = {
22437
+ ...Range.toFileRangeRequestArgs(file, diagnostic.range),
22438
+ errorCodes: [ +diagnostic.code ]
22439
+ };
22440
+ const response = await client.execute(CommandTypes.GetCodeFixes, args, token);
22441
+ if (response.type !== 'response') {
22442
+ continue;
22443
+ }
22444
+ const fix = response.body?.find(fix => fix.fixName === fixName);
22445
+ if (fix) {
22446
+ documentChanges.push(...fix.changes.map(change => toTextDocumentEdit(change, client)));
22447
+ break;
22448
+ }
22449
+ }
22450
+ }
22451
+ return {
22452
+ documentChanges: documentChanges
22453
+ };
22454
+ }
22455
+
22456
+ async function buildCombinedFix(fixes, client, file, diagnostics, token) {
22457
+ for (const diagnostic of diagnostics) {
22458
+ for (const {codes: codes, fixName: fixName} of fixes) {
22459
+ if (token.isCancellationRequested) {
22460
+ return;
22461
+ }
22462
+ if (!codes.has(diagnostic.code)) {
22463
+ continue;
22464
+ }
22465
+ const args = {
22466
+ ...Range.toFileRangeRequestArgs(file, diagnostic.range),
22467
+ errorCodes: [ +diagnostic.code ]
22468
+ };
22469
+ const response = await client.execute(CommandTypes.GetCodeFixes, args, token);
22470
+ if (response.type !== 'response' || !response.body?.length) {
22471
+ continue;
22472
+ }
22473
+ const fix = response.body?.find(fix => fix.fixName === fixName);
22474
+ if (!fix) {
22475
+ continue;
22476
+ }
22477
+ if (!fix.fixId) {
22478
+ return {
22479
+ documentChanges: fix.changes.map(change => toTextDocumentEdit(change, client))
22480
+ };
22481
+ }
22482
+ const combinedArgs = {
22483
+ scope: {
22484
+ type: 'file',
22485
+ args: {
22486
+ file: file
22487
+ }
22488
+ },
22489
+ fixId: fix.fixId
22490
+ };
22491
+ const combinedResponse = await client.execute(CommandTypes.GetCombinedCodeFix, combinedArgs, token);
22492
+ if (combinedResponse.type !== 'response' || !combinedResponse.body) {
22493
+ return;
22494
+ }
22495
+ return {
22496
+ documentChanges: combinedResponse.body.changes.map(change => toTextDocumentEdit(change, client))
22497
+ };
22498
+ }
22499
+ }
22500
+ }
22501
+
22502
+ class SourceAction extends TsCodeAction {}
22503
+
22504
+ class SourceFixAll extends SourceAction {
22505
+ constructor() {
22506
+ super('Fix all fixable JS/TS issues', SourceFixAll.kind.value);
22507
+ }
22508
+ async build(client, file, diagnostics, token) {
22509
+ this.edit = await buildIndividualFixes([ {
22510
+ codes: incorrectlyImplementsInterface,
22511
+ fixName: classIncorrectlyImplementsInterface
22512
+ }, {
22513
+ codes: asyncOnlyAllowedInAsyncFunctions,
22514
+ fixName: awaitInSyncFunction
22515
+ } ], client, file, diagnostics, token);
22516
+ const edits = await buildCombinedFix([ {
22517
+ codes: unreachableCode$1,
22518
+ fixName: unreachableCode
22519
+ } ], client, file, diagnostics, token);
22520
+ if (edits?.documentChanges) {
22521
+ this.edit?.documentChanges?.push(...edits.documentChanges);
22522
+ }
22523
+ }
22524
+ }
22525
+
22526
+ SourceFixAll.kind = CodeActionKind.SourceFixAllTs;
22527
+
22528
+ class SourceRemoveUnused extends SourceAction {
22529
+ constructor() {
22530
+ super('Remove all unused code', SourceRemoveUnused.kind.value);
22531
+ }
22532
+ async build(client, file, diagnostics, token) {
22533
+ this.edit = await buildCombinedFix([ {
22534
+ codes: variableDeclaredButNeverUsed,
22535
+ fixName: unusedIdentifier
22536
+ } ], client, file, diagnostics, token);
22537
+ }
22538
+ }
22539
+
22540
+ SourceRemoveUnused.kind = CodeActionKind.SourceRemoveUnusedTs;
22541
+
22542
+ class SourceAddMissingImports extends SourceAction {
22543
+ constructor() {
22544
+ super('Add all missing imports', SourceAddMissingImports.kind.value);
22545
+ }
22546
+ async build(client, file, diagnostics, token) {
22547
+ this.edit = await buildCombinedFix([ {
22548
+ codes: cannotFindName,
22549
+ fixName: fixImport
22550
+ } ], client, file, diagnostics, token);
22551
+ }
22552
+ }
22553
+
22554
+ SourceAddMissingImports.kind = CodeActionKind.SourceAddMissingImportsTs;
22555
+
22556
+ class TypeScriptAutoFixProvider {
22557
+ constructor(client, fileConfigurationManager, diagnosticsManager) {
22558
+ this.client = client;
22559
+ this.fileConfigurationManager = fileConfigurationManager;
22560
+ this.diagnosticsManager = diagnosticsManager;
22561
+ }
22562
+ getMetadata() {
22563
+ return {
22564
+ providedCodeActionKinds: TypeScriptAutoFixProvider.kindProviders.map(x => x.kind.value)
22565
+ };
22566
+ }
22567
+ async provideCodeActions(document, _range, context, token) {
22568
+ if (!context.only?.length) {
22569
+ return undefined;
22570
+ }
22571
+ const sourceKinds = context.only.map(kind => new CodeActionKind(kind)).filter(codeActionKind => CodeActionKind.Source.intersects(codeActionKind));
22572
+ if (!sourceKinds.length) {
22573
+ return undefined;
22574
+ }
22575
+ if (this.client.hasPendingDiagnostics(document.uri)) {
22576
+ return undefined;
22577
+ }
22578
+ const actions = this.getFixAllActions(sourceKinds);
22579
+ const diagnostics = this.diagnosticsManager.getDiagnosticsForFile(document.filepath);
22580
+ if (!diagnostics.length) {
22581
+ return actions;
22582
+ }
22583
+ await this.fileConfigurationManager.ensureConfigurationForDocument(document, token);
22584
+ if (token.isCancellationRequested) {
22585
+ return undefined;
22586
+ }
22587
+ await Promise.all(actions.map(action => action.build(this.client, document.filepath, diagnostics, token)));
22588
+ return actions;
22589
+ }
22590
+ isCodeActionResolvable(_codeAction) {
22591
+ return false;
22592
+ }
22593
+ getFixAllActions(kinds) {
22594
+ return TypeScriptAutoFixProvider.kindProviders.filter(provider => kinds.some(only => only.intersects(provider.kind))).map(provider => new provider);
22595
+ }
22596
+ }
22597
+
22598
+ TypeScriptAutoFixProvider.kindProviders = [ SourceFixAll, SourceRemoveUnused, SourceAddMissingImports ];
22599
+
22600
+ class Lazy {
22601
+ constructor(executor) {
22602
+ this.executor = executor;
22603
+ this._didRun = false;
22604
+ }
22605
+ get hasValue() {
22606
+ return this._didRun;
22607
+ }
22608
+ get value() {
22609
+ if (!this._didRun) {
22610
+ try {
22611
+ this._value = this.executor();
22612
+ } catch (err) {
22613
+ this._error = err;
22614
+ } finally {
22615
+ this._didRun = true;
22616
+ }
22617
+ }
22618
+ if (this._error) {
22619
+ throw this._error;
22620
+ }
22621
+ return this._value;
22622
+ }
22623
+ get rawValue() {
22624
+ return this._value;
22625
+ }
22626
+ }
22627
+
22628
+ function getEditForCodeAction(client, action) {
22629
+ return action.changes?.length ? {
22630
+ documentChanges: action.changes.map(change => toTextDocumentEdit(change, client))
22631
+ } : undefined;
22632
+ }
22633
+
22634
+ async function applyCodeActionCommands(client, commands, token) {
22635
+ if (commands?.length) {
22636
+ for (const command of commands) {
22637
+ await client.execute(CommandTypes.ApplyCodeActionCommand, {
22638
+ command: command
22639
+ }, token);
22640
+ }
22641
+ }
22642
+ return true;
22643
+ }
22644
+
22645
+ class ApplyCodeActionCommand {
22646
+ constructor(client) {
22647
+ this.client = client;
22648
+ this.id = ApplyCodeActionCommand.ID;
22649
+ }
22650
+ async execute({action: action}) {
22651
+ const codeActionResult = await applyCodeActionCommands(this.client, action.commands);
22652
+ return codeActionResult;
22653
+ }
22654
+ }
22655
+
22656
+ ApplyCodeActionCommand.ID = '_typescript.applyCodeActionCommand';
22657
+
22658
+ class ApplyFixAllCodeAction {
22659
+ constructor(client, tsCodeActionProvider) {
22660
+ this.client = client;
22661
+ this.tsCodeActionProvider = tsCodeActionProvider;
22662
+ this.id = ApplyFixAllCodeAction.ID;
22663
+ }
22664
+ async execute(args) {
22665
+ const tsAction = this.tsCodeActionProvider.getQuickFixAllTsCodeActionByFixName(args.tsActionId);
22666
+ if (tsAction instanceof TsQuickFixAllCodeAction && tsAction.combinedResponse) {
22667
+ await applyCodeActionCommands(this.client, tsAction.combinedResponse.body.commands);
22668
+ }
22669
+ }
22670
+ }
22671
+
22672
+ ApplyFixAllCodeAction.ID = '_typescript.applyFixAllCodeAction';
22673
+
22674
+ class DiagnosticsSet {
22675
+ static from(diagnostics) {
22676
+ const values = new Map;
22677
+ for (const diagnostic of diagnostics) {
22678
+ values.set(DiagnosticsSet.key(diagnostic), diagnostic);
22679
+ }
22680
+ return new DiagnosticsSet(values);
22681
+ }
22682
+ static key(diagnostic) {
22683
+ const {start: start, end: end} = diagnostic.range;
22684
+ return `${diagnostic.code}-${start.line},${start.character}-${end.line},${end.character}`;
22685
+ }
22686
+ constructor(_values) {
22687
+ this._values = _values;
22688
+ }
22689
+ get values() {
22690
+ return this._values.values();
22691
+ }
22692
+ get size() {
22693
+ return this._values.size;
22694
+ }
22695
+ }
22696
+
22697
+ class TsQuickFixCodeAction extends TsCodeAction {
22698
+ constructor(tsAction, title, kind) {
22699
+ super(title, kind);
22700
+ this.tsAction = tsAction;
22701
+ }
22702
+ }
22703
+
22704
+ class TsQuickFixAllCodeAction extends TsQuickFixCodeAction {
22705
+ constructor(tsAction, file, title, kind) {
22706
+ super(tsAction, title, kind);
22707
+ this.file = file;
22708
+ }
22709
+ }
22710
+
22711
+ class CodeActionSet {
22712
+ constructor() {
22713
+ this._actions = new Set;
22714
+ this._fixAllActions = new Map;
22715
+ this._aiActions = new Set;
22716
+ }
22717
+ * values() {
22718
+ yield* this._actions;
22719
+ yield* this._aiActions;
22720
+ }
22721
+ addAction(action) {
22722
+ for (const existing of this._actions) {
22723
+ if (action.tsAction.fixName === existing.tsAction.fixName && equals(action.edit, existing.edit)) {
22724
+ this._actions.delete(existing);
22725
+ }
22726
+ }
22727
+ this._actions.add(action);
22728
+ if (action.tsAction.fixId) {
22729
+ const existingFixAll = this._fixAllActions.get(action.tsAction.fixId);
22730
+ if (existingFixAll) {
22731
+ this._actions.delete(existingFixAll);
22732
+ this._actions.add(existingFixAll);
22733
+ }
22734
+ }
22735
+ }
22736
+ addFixAllAction(fixId, action) {
22737
+ const existing = this._fixAllActions.get(fixId);
22738
+ if (existing) {
22739
+ this._actions.delete(existing);
22740
+ }
22741
+ this.addAction(action);
22742
+ this._fixAllActions.set(fixId, action);
22743
+ }
22744
+ hasFixAllAction(fixId) {
22745
+ return this._fixAllActions.has(fixId);
22746
+ }
22747
+ }
22748
+
22749
+ class SupportedCodeActionProvider {
22750
+ constructor(client) {
22751
+ this.client = client;
22752
+ this.fixableDiagnosticCodes = new Lazy(() => this.client.execute(CommandTypes.GetSupportedCodeFixes, null).then(response => response.type === 'response' ? response.body || [] : []).then(codes => new Set(codes)));
22753
+ }
22754
+ async getFixableDiagnosticsForContext(diagnostics) {
22755
+ const fixableCodes = await this.fixableDiagnosticCodes.value;
22756
+ return DiagnosticsSet.from(diagnostics.filter(diagnostic => typeof diagnostic.code !== 'undefined' && fixableCodes.has(diagnostic.code + '')));
22757
+ }
22758
+ }
22759
+
22760
+ class TypeScriptQuickFixProvider {
22761
+ constructor(client, fileConfigurationManager, commandManager, diagnosticsManager, features) {
22762
+ this.client = client;
22763
+ this.fileConfigurationManager = fileConfigurationManager;
22764
+ this.diagnosticsManager = diagnosticsManager;
22765
+ this.features = features;
22766
+ this._quickFixAllTsCodeActionMap = new Map;
22767
+ commandManager.register(new ApplyCodeActionCommand(client));
22768
+ commandManager.register(new ApplyFixAllCodeAction(client, this));
22769
+ this.supportedCodeActionProvider = new SupportedCodeActionProvider(client);
22770
+ }
22771
+ getMetadata() {
22772
+ return {
22773
+ providedCodeActionKinds: [ CodeActionKind.QuickFix.value ]
22774
+ };
22775
+ }
22776
+ async provideCodeActions(document, range, context, token) {
22777
+ this._quickFixAllTsCodeActionMap.clear();
22778
+ let diagnostics = context.diagnostics;
22779
+ if (this.client.hasPendingDiagnostics(document.uri)) {
22780
+ await new Promise(resolve => {
22781
+ setTimeout(resolve, 500);
22782
+ });
22783
+ if (token.isCancellationRequested) {
22784
+ return;
22785
+ }
22786
+ const allDiagnostics = [];
22787
+ for (const diagnostic of this.diagnosticsManager.getDiagnosticsForFile(document.filepath)) {
22788
+ if (Range.intersection(range, diagnostic.range)) {
22789
+ const newLen = allDiagnostics.push(diagnostic);
22790
+ if (newLen > TypeScriptQuickFixProvider._maxCodeActionsPerFile) {
22791
+ break;
22792
+ }
22793
+ }
22794
+ }
22795
+ diagnostics = allDiagnostics;
22796
+ }
22797
+ const fixableDiagnostics = await this.supportedCodeActionProvider.getFixableDiagnosticsForContext(diagnostics);
22798
+ if (!fixableDiagnostics.size || token.isCancellationRequested) {
22799
+ return;
22800
+ }
22801
+ await this.fileConfigurationManager.ensureConfigurationForDocument(document, token);
22802
+ if (token.isCancellationRequested) {
22803
+ return;
22804
+ }
22805
+ const results = new CodeActionSet;
22806
+ for (const diagnostic of fixableDiagnostics.values) {
22807
+ await this.getFixesForDiagnostic(document, diagnostic, results, token);
22808
+ if (token.isCancellationRequested) {
22809
+ return;
22810
+ }
22811
+ }
22812
+ const allActions = Array.from(results.values());
22813
+ for (const action of allActions) {
22814
+ action.isPreferred = isPreferredFix(action, allActions);
22815
+ }
22816
+ return allActions;
22817
+ }
22818
+ isCodeActionResolvable(codeAction) {
22819
+ return codeAction instanceof TsQuickFixAllCodeAction;
22820
+ }
22821
+ async resolveCodeAction(codeAction, token) {
22822
+ if (!this.isCodeActionResolvable(codeAction) || !codeAction.tsAction.fixId) {
22823
+ return codeAction;
22824
+ }
22825
+ const arg = {
22826
+ scope: {
22827
+ type: 'file',
22828
+ args: {
22829
+ file: codeAction.file
22830
+ }
22831
+ },
22832
+ fixId: codeAction.tsAction.fixId
22833
+ };
22834
+ const response = await this.client.execute(CommandTypes.GetCombinedCodeFix, arg, token);
22835
+ if (response.type === 'response') {
22836
+ codeAction.combinedResponse = response;
22837
+ codeAction.edit = {
22838
+ documentChanges: response.body.changes.map(change => toTextDocumentEdit(change, this.client))
22839
+ };
22840
+ }
22841
+ return codeAction;
22842
+ }
22843
+ getQuickFixAllTsCodeActionByFixName(fixName) {
22844
+ return this._quickFixAllTsCodeActionMap.get(fixName);
22845
+ }
22846
+ async getFixesForDiagnostic(document, diagnostic, results, token) {
22847
+ const args = {
22848
+ ...Range.toFileRangeRequestArgs(document.filepath, diagnostic.range),
22849
+ errorCodes: [ +diagnostic.code ]
22850
+ };
22851
+ const response = await this.client.execute(CommandTypes.GetCodeFixes, args, token);
22852
+ if (response.type !== 'response' || !response.body) {
22853
+ return results;
22854
+ }
22855
+ for (const tsCodeFix of response.body) {
22856
+ for (const action of this.getFixesForTsCodeAction(document, diagnostic, tsCodeFix)) {
22857
+ results.addAction(action);
22858
+ }
22859
+ if (this.features.codeActionResolveSupport) {
22860
+ this.addFixAllForTsCodeAction(results, document.uri, document.filepath, diagnostic, tsCodeFix);
22861
+ }
22862
+ }
22863
+ return results;
22864
+ }
22865
+ getFixesForTsCodeAction(document, diagnostic, action) {
22866
+ const actions = [];
22867
+ const codeAction = new TsQuickFixCodeAction(action, action.description, mainExports$2.CodeActionKind.QuickFix);
22868
+ codeAction.edit = getEditForCodeAction(this.client, action);
22869
+ codeAction.diagnostics = [ diagnostic ];
22870
+ codeAction.command = {
22871
+ command: ApplyCodeActionCommand.ID,
22872
+ arguments: [ {
22873
+ action: action,
22874
+ diagnostic: diagnostic,
22875
+ documentUri: document.uri.toString()
22876
+ } ],
22877
+ title: ''
22878
+ };
22879
+ actions.push(codeAction);
22880
+ return actions;
22881
+ }
22882
+ addFixAllForTsCodeAction(results, _resource, file, diagnostic, tsAction) {
22883
+ if (!tsAction.fixId || results.hasFixAllAction(tsAction.fixId)) {
22884
+ return results;
22885
+ }
22886
+ if (!this.diagnosticsManager.getDiagnosticsForFile(file).some(x => {
22887
+ if (x === diagnostic) {
22888
+ return false;
22889
+ }
22890
+ return x.code === diagnostic.code || fixAllErrorCodes.has(x.code) && fixAllErrorCodes.get(x.code) === fixAllErrorCodes.get(diagnostic.code);
22891
+ })) {
22892
+ return results;
22893
+ }
22894
+ const action = new TsQuickFixAllCodeAction(tsAction, file, tsAction.fixAllDescription || `${tsAction.description} (Fix all in file)`, mainExports$2.CodeActionKind.QuickFix);
22895
+ action.diagnostics = [ diagnostic ];
22896
+ action.command = {
22897
+ command: ApplyFixAllCodeAction.ID,
22898
+ arguments: [ {
22899
+ tsActionId: tsAction.fixName
22900
+ } ],
22901
+ title: ''
22902
+ };
22903
+ this._quickFixAllTsCodeActionMap.set(tsAction.fixName, action);
22904
+ results.addFixAllAction(tsAction.fixId, action);
22905
+ return results;
22906
+ }
22907
+ }
22908
+
22909
+ TypeScriptQuickFixProvider._maxCodeActionsPerFile = 1e3;
22910
+
22911
+ const fixAllErrorCodes = new Map([ [ 2339, 2339 ], [ 2345, 2339 ] ]);
22912
+
22913
+ const preferredFixes = new Map([ [ annotateWithTypeFromJSDoc, {
22914
+ priority: 2
22915
+ } ], [ constructorForDerivedNeedSuperCall, {
22916
+ priority: 2
22917
+ } ], [ extendsInterfaceBecomesImplements, {
22918
+ priority: 2
22919
+ } ], [ awaitInSyncFunction, {
22920
+ priority: 2
22921
+ } ], [ removeUnnecessaryAwait, {
22922
+ priority: 2
22923
+ } ], [ classIncorrectlyImplementsInterface, {
22924
+ priority: 3
22925
+ } ], [ classDoesntImplementInheritedAbstractMember, {
22926
+ priority: 3
22927
+ } ], [ unreachableCode, {
22928
+ priority: 2
22929
+ } ], [ unusedIdentifier, {
22930
+ priority: 2
22931
+ } ], [ forgottenThisPropertyAccess, {
22932
+ priority: 2
22933
+ } ], [ spelling, {
22934
+ priority: 0
22935
+ } ], [ addMissingAwait, {
22936
+ priority: 2
22937
+ } ], [ addMissingOverride, {
22938
+ priority: 2
22939
+ } ], [ addMissingNewOperator, {
22940
+ priority: 2
22941
+ } ], [ fixImport, {
22942
+ priority: 1,
22943
+ thereCanOnlyBeOne: true
22944
+ } ] ]);
22945
+
22946
+ function isPreferredFix(action, allActions) {
22947
+ if (action instanceof TsQuickFixAllCodeAction) {
22948
+ return false;
22949
+ }
22950
+ const fixPriority = preferredFixes.get(action.tsAction.fixName);
22951
+ if (!fixPriority) {
22952
+ return false;
22953
+ }
22954
+ return allActions.every(otherAction => {
22955
+ if (otherAction === action) {
22956
+ return true;
22957
+ }
22958
+ if (otherAction instanceof TsQuickFixAllCodeAction) {
22959
+ return true;
22960
+ }
22961
+ const otherFixPriority = preferredFixes.get(otherAction.tsAction.fixName);
22962
+ if (!otherFixPriority || otherFixPriority.priority < fixPriority.priority) {
22963
+ return true;
22964
+ } else if (otherFixPriority.priority > fixPriority.priority) {
22965
+ return false;
22966
+ }
22967
+ if (fixPriority.thereCanOnlyBeOne && action.tsAction.fixName === otherAction.tsAction.fixName) {
22968
+ return false;
22969
+ }
22970
+ return true;
22971
+ });
22972
+ }
22973
+
22974
+ const noopDisposable = mainExports$2.Disposable.create(() => {});
22975
+
22976
+ const nulToken = {
22977
+ isCancellationRequested: false,
22978
+ onCancellationRequested: () => noopDisposable
22979
+ };
22980
+
22981
+ class CodeActionManager {
22982
+ constructor(client, fileConfigurationManager, commandManager, diagnosticsManager, features) {
22983
+ this.features = features;
22984
+ this.providerMap = new Map;
22985
+ this.nextProviderId = 1;
22986
+ this.resolveCodeActionsMap = new Map;
22987
+ this.nextGlobalCodeActionId = 1;
22988
+ this.addProvider(new TypeScriptAutoFixProvider(client, fileConfigurationManager, diagnosticsManager));
22989
+ this.addProvider(new TypeScriptQuickFixProvider(client, fileConfigurationManager, commandManager, diagnosticsManager, features));
22990
+ }
22991
+ get kinds() {
22992
+ const allKinds = [];
22993
+ for (const [_, provider] of this.providerMap) {
22994
+ allKinds.push(...provider.getMetadata().providedCodeActionKinds || []);
22995
+ }
22996
+ return allKinds;
22997
+ }
22998
+ async provideCodeActions(document, range, context, token) {
22999
+ this.resolveCodeActionsMap.clear();
23000
+ const allCodeActions = [];
23001
+ for (const [providerId, provider] of this.providerMap.entries()) {
23002
+ const codeActions = await provider.provideCodeActions(document, range, context, token || nulToken);
23003
+ if (!codeActions) {
23004
+ continue;
23005
+ }
23006
+ for (const action of codeActions) {
23007
+ if (mainExports$2.Command.is(action)) {
23008
+ allCodeActions.push(action);
23009
+ continue;
23010
+ }
23011
+ const lspCodeAction = action.toLspCodeAction();
23012
+ if (provider.isCodeActionResolvable(action)) {
23013
+ const globalId = this.nextGlobalCodeActionId++;
23014
+ this.resolveCodeActionsMap.set(globalId, action);
23015
+ lspCodeAction.data = {
23016
+ globalId: globalId,
23017
+ providerId: providerId
23018
+ };
23019
+ }
23020
+ allCodeActions.push(lspCodeAction);
23021
+ }
23022
+ }
23023
+ return allCodeActions;
23024
+ }
23025
+ async resolveCodeAction(codeAction, token) {
23026
+ if (!this.features.codeActionResolveSupport) {
23027
+ return codeAction;
23028
+ }
23029
+ const {globalId: globalId, providerId: providerId} = codeAction.data || {};
23030
+ if (globalId === undefined || providerId === undefined) {
23031
+ return codeAction;
23032
+ }
23033
+ const provider = this.providerMap.get(providerId);
23034
+ if (!provider || !provider.resolveCodeAction) {
23035
+ return codeAction;
23036
+ }
23037
+ const tsCodeAction = this.resolveCodeActionsMap.get(globalId);
23038
+ if (!tsCodeAction || !providerId) {
23039
+ return codeAction;
23040
+ }
23041
+ const resolvedTsCodeAction = await provider.resolveCodeAction(tsCodeAction, token || nulToken);
23042
+ if (!resolvedTsCodeAction) {
23043
+ return codeAction;
23044
+ }
23045
+ const lspCodeAction = resolvedTsCodeAction.toLspCodeAction();
23046
+ for (const property of this.features.codeActionResolveSupport.properties) {
23047
+ if (property in lspCodeAction) {
23048
+ codeAction[property] = lspCodeAction[property];
23049
+ }
23050
+ }
23051
+ return codeAction;
23052
+ }
23053
+ addProvider(provider) {
23054
+ this.providerMap.set(this.nextProviderId++, provider);
23055
+ }
23056
+ }
23057
+
23058
+ class LspServer {
23059
+ constructor(options) {
23060
+ this.options = options;
23061
+ this.initializeParams = null;
23062
+ this.completionDataCache = new CompletionDataCache;
23063
+ this.features = {};
23064
+ this.cachedNavTreeResponse = new CachedResponse;
23065
+ this.implementationsCodeLensProvider = null;
23066
+ this.referencesCodeLensProvider = null;
23067
+ this.logger = new PrefixingLogger(options.logger, '[lspserver]');
23068
+ this.tsClient = new TsClient(onCaseInsensitiveFileSystem(), this.logger, options.lspClient);
23069
+ this.fileConfigurationManager = new FileConfigurationManager(this.tsClient, onCaseInsensitiveFileSystem());
23070
+ this.commandManager = new CommandManager;
23071
+ this.diagnosticsManager = new DiagnosticsManager(diagnostics => this.options.lspClient.publishDiagnostics(diagnostics), this.tsClient, this.features, this.logger);
23072
+ this.codeActionsManager = new CodeActionManager(this.tsClient, this.fileConfigurationManager, this.commandManager, this.diagnosticsManager, this.features);
23073
+ }
23074
+ closeAllForTesting() {
23075
+ for (const document of this.tsClient.documentsForTesting.values()) {
23076
+ this.closeDocument(document.uri.toString());
23077
+ }
23078
+ }
23079
+ async waitForDiagnosticsForFile(uri) {
23080
+ const document = this.tsClient.toOpenDocument(uri);
23081
+ if (!document) {
23082
+ throw new Error(`Document not open: ${uri}`);
23083
+ }
23084
+ await this.diagnosticsManager.waitForDiagnosticsForTesting(document.filepath);
23085
+ }
23086
+ shutdown() {
23087
+ this.tsClient.shutdown();
23088
+ }
23089
+ initialize(params) {
23090
+ this.initializeParams = params;
23091
+ const clientCapabilities = this.initializeParams.capabilities;
23092
+ this.workspaceRoot = this.initializeParams.rootUri ? URI.parse(this.initializeParams.rootUri).fsPath : this.initializeParams.rootPath || undefined;
23093
+ const userInitializationOptions = this.initializeParams.initializationOptions || {};
23094
+ const {disableAutomaticTypingAcquisition: disableAutomaticTypingAcquisition, hostInfo: hostInfo, maxTsServerMemory: maxTsServerMemory, npmLocation: npmLocation, locale: locale, plugins: plugins, tsserver: tsserver} = userInitializationOptions;
23095
+ const typescriptVersion = this.findTypescriptVersion(tsserver?.path, tsserver?.fallbackPath);
23096
+ if (typescriptVersion) {
23097
+ this.options.lspClient.logMessage({
23098
+ type: mainExports$2.MessageType.Info,
23099
+ message: `Using Typescript version (${typescriptVersion.source}) ${typescriptVersion.versionString} from path "${typescriptVersion.tsServerPath}"`
23100
+ });
23101
+ } else {
23102
+ 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.');
23103
+ }
23104
+ this.fileConfigurationManager.mergeTsPreferences(userInitializationOptions.preferences || {});
23105
+ this.features.completionDisableFilterText = userInitializationOptions.completionDisableFilterText ?? false;
23106
+ this.features.moveToFileCodeActionSupport = userInitializationOptions.supportsMoveToFileCodeAction && typescriptVersion.version?.gte(API.v520);
23107
+ const {textDocument: textDocument} = clientCapabilities;
23108
+ if (textDocument) {
23109
+ const {codeAction: codeAction, completion: completion, definition: definition, publishDiagnostics: publishDiagnostics} = textDocument;
23110
+ if (codeAction) {
23111
+ this.features.codeActionDisabledSupport = codeAction.disabledSupport;
23112
+ this.features.codeActionResolveSupport = codeAction.resolveSupport;
23113
+ }
22522
23114
  if (completion) {
22523
23115
  const {completionItem: completionItem} = completion;
22524
23116
  if (completionItem) {
@@ -22568,10 +23160,10 @@ class LspServer {
22568
23160
  process.on('SIGINT', () => {
22569
23161
  process.exit();
22570
23162
  });
22571
- this.typeScriptAutoFixProvider = new TypeScriptAutoFixProvider(this.tsClient);
22572
23163
  this.fileConfigurationManager.setGlobalConfiguration(this.workspaceRoot, hostInfo);
22573
23164
  this.registerHandlers();
22574
23165
  const prepareSupport = textDocument?.rename?.prepareSupport && this.tsClient.apiVersion.gte(API.v310);
23166
+ const {codeActionLiteralSupport: codeActionLiteralSupport, resolveSupport: codeActionResolveSupport} = textDocument?.codeAction || {};
22575
23167
  const initializeResult = {
22576
23168
  capabilities: {
22577
23169
  textDocumentSync: mainExports$2.TextDocumentSyncKind.Incremental,
@@ -22579,8 +23171,13 @@ class LspServer {
22579
23171
  triggerCharacters: [ '.', '"', '\'', '/', '@', '<' ],
22580
23172
  resolveProvider: true
22581
23173
  },
22582
- codeActionProvider: clientCapabilities.textDocument?.codeAction?.codeActionLiteralSupport ? {
22583
- codeActionKinds: [ ...TypeScriptAutoFixProvider.kinds.map(kind => kind.value), CodeActionKind.SourceOrganizeImportsTs.value, CodeActionKind.SourceRemoveUnusedImportsTs.value, CodeActionKind.SourceSortImportsTs.value, CodeActionKind.QuickFix.value, CodeActionKind.Refactor.value ]
23174
+ codeActionProvider: codeActionLiteralSupport || codeActionResolveSupport ? {
23175
+ ...codeActionLiteralSupport ? {
23176
+ codeActionKinds: [ ...this.codeActionsManager.kinds, CodeActionKind.SourceOrganizeImportsTs.value, CodeActionKind.SourceRemoveUnusedImportsTs.value, CodeActionKind.SourceSortImportsTs.value, CodeActionKind.Refactor.value ]
23177
+ } : {},
23178
+ ...codeActionResolveSupport ? {
23179
+ resolveProvider: true
23180
+ } : {}
22584
23181
  } : true,
22585
23182
  codeLensProvider: {
22586
23183
  resolveProvider: true
@@ -22591,7 +23188,7 @@ class LspServer {
22591
23188
  documentHighlightProvider: true,
22592
23189
  documentSymbolProvider: true,
22593
23190
  executeCommandProvider: {
22594
- commands: [ Commands.APPLY_WORKSPACE_EDIT, Commands.APPLY_CODE_ACTION, Commands.APPLY_REFACTORING, Commands.CONFIGURE_PLUGIN, Commands.ORGANIZE_IMPORTS, Commands.APPLY_RENAME_FILE, Commands.SOURCE_DEFINITION, Commands.TS_SERVER_REQUEST ]
23191
+ commands: [ Commands.APPLY_REFACTORING, Commands.CONFIGURE_PLUGIN, Commands.ORGANIZE_IMPORTS, Commands.APPLY_RENAME_FILE, Commands.SOURCE_DEFINITION, Commands.TS_SERVER_REQUEST ]
22595
23192
  },
22596
23193
  hoverProvider: true,
22597
23194
  inlayHintProvider: true,
@@ -22702,7 +23299,7 @@ class LspServer {
22702
23299
  didChangeConfiguration(params) {
22703
23300
  this.fileConfigurationManager.setWorkspaceConfiguration(params.settings || {});
22704
23301
  const ignoredDiagnosticCodes = this.fileConfigurationManager.workspaceConfiguration.diagnostics?.ignoredCodes || [];
22705
- this.tsClient.interruptGetErr(() => this.diagnosticQueue.updateIgnoredDiagnosticCodes(ignoredDiagnosticCodes));
23302
+ this.tsClient.interruptGetErr(() => this.diagnosticsManager.updateIgnoredDiagnosticCodes(ignoredDiagnosticCodes));
22706
23303
  }
22707
23304
  didOpenTextDocument(params) {
22708
23305
  if (this.tsClient.toOpenDocument(params.textDocument.uri, {
@@ -22724,7 +23321,7 @@ class LspServer {
22724
23321
  }
22725
23322
  this.cachedNavTreeResponse.onDocumentClose(document);
22726
23323
  this.tsClient.onDidCloseTextDocument(uri);
22727
- this.diagnosticQueue.onDidCloseFile(document.filepath);
23324
+ this.diagnosticsManager.onDidCloseFile(document.filepath);
22728
23325
  this.fileConfigurationManager.onDidCloseTextDocument(document.uri);
22729
23326
  }
22730
23327
  didChangeTextDocument(params) {
@@ -23048,13 +23645,9 @@ class LspServer {
23048
23645
  if (!document) {
23049
23646
  return [];
23050
23647
  }
23051
- await this.tsClient.interruptGetErr(() => this.fileConfigurationManager.ensureConfigurationForDocument(document));
23648
+ const actions = await this.codeActionsManager.provideCodeActions(document, params.range, params.context, token);
23052
23649
  const fileRangeArgs = Range.toFileRangeRequestArgs(document.filepath, params.range);
23053
- const actions = [];
23054
23650
  const kinds = params.context.only?.map(kind => new CodeActionKind(kind));
23055
- if (!kinds || kinds.some(kind => CodeActionKind.QuickFix.contains(kind))) {
23056
- actions.push(...provideQuickFix(await this.getCodeFixes(fileRangeArgs, params.context, token), this.tsClient));
23057
- }
23058
23651
  if (!kinds || kinds.some(kind => CodeActionKind.Refactor.contains(kind))) {
23059
23652
  actions.push(...provideRefactors(await this.getRefactors(fileRangeArgs, params.context, this.features, token), fileRangeArgs, this.features));
23060
23653
  }
@@ -23084,23 +23677,8 @@ class LspServer {
23084
23677
  }
23085
23678
  }
23086
23679
  }
23087
- if (kinds && !this.tsClient.hasPendingDiagnostics(document.uri)) {
23088
- const diagnostics = this.diagnosticQueue.getDiagnosticsForFile(document.filepath) || [];
23089
- if (diagnostics.length) {
23090
- actions.push(...await this.typeScriptAutoFixProvider.provideCodeActions(kinds, document.filepath, diagnostics));
23091
- }
23092
- }
23093
23680
  return actions;
23094
23681
  }
23095
- async getCodeFixes(fileRangeArgs, context, token) {
23096
- const errorCodes = context.diagnostics.map(diagnostic => Number(diagnostic.code));
23097
- const args = {
23098
- ...fileRangeArgs,
23099
- errorCodes: errorCodes
23100
- };
23101
- const response = await this.tsClient.execute(CommandTypes.GetCodeFixes, args, token);
23102
- return response.type === 'response' ? response : undefined;
23103
- }
23104
23682
  async getRefactors(fileRangeArgs, context, features, token) {
23105
23683
  const kinds = context.only || [ undefined ];
23106
23684
  const responses = await Promise.all(kinds.map(async kind => {
@@ -23115,25 +23693,11 @@ class LspServer {
23115
23693
  }));
23116
23694
  return responses.flat();
23117
23695
  }
23696
+ async codeActionResolve(params, _token) {
23697
+ return this.codeActionsManager.resolveCodeAction(params);
23698
+ }
23118
23699
  async executeCommand(params, token, workDoneProgress) {
23119
- if (params.command === Commands.APPLY_WORKSPACE_EDIT && params.arguments) {
23120
- const edit = params.arguments[0];
23121
- await this.options.lspClient.applyWorkspaceEdit({
23122
- edit: edit
23123
- });
23124
- } else if (params.command === Commands.APPLY_CODE_ACTION && params.arguments) {
23125
- const codeAction = params.arguments[0];
23126
- if (!await this.applyFileCodeEdits(codeAction.changes)) {
23127
- return;
23128
- }
23129
- if (codeAction.commands?.length) {
23130
- for (const command of codeAction.commands) {
23131
- await this.tsClient.execute(CommandTypes.ApplyCodeActionCommand, {
23132
- command: command
23133
- }, token);
23134
- }
23135
- }
23136
- } else if (params.command === Commands.APPLY_REFACTORING && params.arguments) {
23700
+ if (await this.commandManager.handle(params.command, ...params.arguments || [])) ; else if (params.command === Commands.APPLY_REFACTORING && params.arguments) {
23137
23701
  const args = params.arguments[0];
23138
23702
  const response = await this.tsClient.execute(CommandTypes.GetEditsForRefactor, args, token);
23139
23703
  if (response.type !== 'response' || !response.body) {
@@ -23388,7 +23952,7 @@ class LspServer {
23388
23952
  const diagnosticEvent = event;
23389
23953
  if (diagnosticEvent.body?.diagnostics) {
23390
23954
  const {file: file, diagnostics: diagnostics} = diagnosticEvent.body;
23391
- this.diagnosticQueue.updateDiagnostics(getDignosticsKind(event), file, diagnostics);
23955
+ this.diagnosticsManager.updateDiagnostics(getDignosticsKind(event), file, diagnostics);
23392
23956
  }
23393
23957
  }
23394
23958
  }
@@ -23559,6 +24123,7 @@ function createLspConnection(options) {
23559
24123
  connection.onDidCloseTextDocument(server.didCloseTextDocument.bind(server));
23560
24124
  connection.onDidChangeTextDocument(server.didChangeTextDocument.bind(server));
23561
24125
  connection.onCodeAction(server.codeAction.bind(server));
24126
+ connection.onCodeActionResolve(server.codeActionResolve.bind(server));
23562
24127
  connection.onCodeLens(server.codeLens.bind(server));
23563
24128
  connection.onCodeLensResolve(server.codeLensResolve.bind(server));
23564
24129
  connection.onCompletion(server.completion.bind(server));