Skip to content

Commit 5452c6a

Browse files
authored
Eagerly delete diagnostic on quick fix (microsoft#166417)
Fixes microsoft#166415
1 parent e688782 commit 5452c6a

File tree

3 files changed

+53
-22
lines changed

3 files changed

+53
-22
lines changed

extensions/typescript-language-features/src/languageFeatures/diagnostics.ts

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export const enum DiagnosticKind {
3434
}
3535

3636
class FileDiagnostics {
37+
3738
private readonly _diagnostics = new Map<DiagnosticKind, ReadonlyArray<vscode.Diagnostic>>();
3839

3940
constructor(
@@ -61,7 +62,7 @@ class FileDiagnostics {
6162
return true;
6263
}
6364

64-
public getDiagnostics(settings: DiagnosticSettings): vscode.Diagnostic[] {
65+
public getAllDiagnostics(settings: DiagnosticSettings): vscode.Diagnostic[] {
6566
if (!settings.getValidate(this.language)) {
6667
return [];
6768
}
@@ -73,6 +74,12 @@ class FileDiagnostics {
7374
];
7475
}
7576

77+
public delete(toDelete: vscode.Diagnostic): void {
78+
for (const [type, diags] of this._diagnostics) {
79+
this._diagnostics.set(type, diags.filter(diag => !diagnosticsEquals(diag, toDelete)));
80+
}
81+
}
82+
7683
private getSuggestionDiagnostics(settings: DiagnosticSettings) {
7784
const enableSuggestions = settings.getEnableSuggestions(this.language);
7885
return this.get(DiagnosticKind.Suggestion).filter(x => {
@@ -177,14 +184,14 @@ export class DiagnosticsManager extends Disposable {
177184
public setValidate(language: DiagnosticLanguage, value: boolean) {
178185
const didUpdate = this._settings.setValidate(language, value);
179186
if (didUpdate) {
180-
this.rebuild();
187+
this.rebuildAll();
181188
}
182189
}
183190

184191
public setEnableSuggestions(language: DiagnosticLanguage, value: boolean) {
185192
const didUpdate = this._settings.setEnableSuggestions(language, value);
186193
if (didUpdate) {
187-
this.rebuild();
194+
this.rebuildAll();
188195
}
189196
}
190197

@@ -217,11 +224,19 @@ export class DiagnosticsManager extends Disposable {
217224
this._currentDiagnostics.set(file, diagnostics);
218225
}
219226

220-
public delete(resource: vscode.Uri): void {
227+
public deleteAllDiagnosticsInFile(resource: vscode.Uri): void {
221228
this._currentDiagnostics.delete(resource);
222229
this._diagnostics.delete(resource);
223230
}
224231

232+
public deleteDiagnostic(resource: vscode.Uri, diagnostic: vscode.Diagnostic): void {
233+
const fileDiagnostics = this._diagnostics.get(resource);
234+
if (fileDiagnostics) {
235+
fileDiagnostics.delete(diagnostic);
236+
this.rebuildFile(fileDiagnostics);
237+
}
238+
}
239+
225240
public getDiagnostics(file: vscode.Uri): ReadonlyArray<vscode.Diagnostic> {
226241
return this._currentDiagnostics.get(file) || [];
227242
}
@@ -239,13 +254,17 @@ export class DiagnosticsManager extends Disposable {
239254
}
240255

241256
const fileDiagnostics = this._diagnostics.get(file);
242-
this._currentDiagnostics.set(file, fileDiagnostics ? fileDiagnostics.getDiagnostics(this._settings) : []);
257+
this._currentDiagnostics.set(file, fileDiagnostics ? fileDiagnostics.getAllDiagnostics(this._settings) : []);
243258
}
244259

245-
private rebuild(): void {
260+
private rebuildAll(): void {
246261
this._currentDiagnostics.clear();
247262
for (const fileDiagnostic of this._diagnostics.values) {
248-
this._currentDiagnostics.set(fileDiagnostic.file, fileDiagnostic.getDiagnostics(this._settings));
263+
this.rebuildFile(fileDiagnostic);
249264
}
250265
}
266+
267+
private rebuildFile(fileDiagnostic: FileDiagnostics) {
268+
this._currentDiagnostics.set(fileDiagnostic.file, fileDiagnostic.getAllDiagnostics(this._settings));
269+
}
251270
}

extensions/typescript-language-features/src/languageFeatures/quickFix.ts

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,23 @@ import * as typeConverters from '../utils/typeConverters';
2020
import { DiagnosticsManager } from './diagnostics';
2121
import FileConfigurationManager from './fileConfigurationManager';
2222

23+
type ApplyCodeActionCommand_args = {
24+
readonly resource: vscode.Uri;
25+
readonly diagnostic: vscode.Diagnostic;
26+
readonly action: Proto.CodeFixAction;
27+
};
2328

2429
class ApplyCodeActionCommand implements Command {
2530
public static readonly ID = '_typescript.applyCodeActionCommand';
2631
public readonly id = ApplyCodeActionCommand.ID;
2732

2833
constructor(
2934
private readonly client: ITypeScriptServiceClient,
35+
private readonly diagnosticManager: DiagnosticsManager,
3036
private readonly telemetryReporter: TelemetryReporter,
3137
) { }
3238

33-
public async execute(
34-
action: Proto.CodeFixAction
35-
): Promise<boolean> {
39+
public async execute({ resource, action, diagnostic }: ApplyCodeActionCommand_args): Promise<boolean> {
3640
/* __GDPR__
3741
"quickFix.execute" : {
3842
"owner": "mjbvz",
@@ -46,6 +50,7 @@ class ApplyCodeActionCommand implements Command {
4650
fixName: action.fixName
4751
});
4852

53+
this.diagnosticManager.deleteDiagnostic(resource, diagnostic);
4954
return applyCodeActionCommands(this.client, action.commands, nulToken);
5055
}
5156
}
@@ -212,7 +217,7 @@ class TypeScriptQuickFixProvider implements vscode.CodeActionProvider<VsCodeCode
212217
private readonly diagnosticsManager: DiagnosticsManager,
213218
telemetryReporter: TelemetryReporter
214219
) {
215-
commandManager.register(new ApplyCodeActionCommand(client, telemetryReporter));
220+
commandManager.register(new ApplyCodeActionCommand(client, diagnosticsManager, telemetryReporter));
216221
commandManager.register(new ApplyFixAllCodeAction(client, telemetryReporter));
217222

218223
this.supportedCodeActionProvider = new SupportedCodeActionProvider(client);
@@ -223,26 +228,32 @@ class TypeScriptQuickFixProvider implements vscode.CodeActionProvider<VsCodeCode
223228
_range: vscode.Range,
224229
context: vscode.CodeActionContext,
225230
token: vscode.CancellationToken
226-
): Promise<VsCodeCodeAction[]> {
231+
): Promise<VsCodeCodeAction[] | undefined> {
227232
const file = this.client.toOpenedFilePath(document);
228233
if (!file) {
229-
return [];
234+
return;
230235
}
231236

232237
const fixableDiagnostics = await this.supportedCodeActionProvider.getFixableDiagnosticsForContext(context);
233-
if (!fixableDiagnostics.size) {
234-
return [];
238+
if (!fixableDiagnostics.size || token.isCancellationRequested) {
239+
return;
235240
}
236241

237242
if (this.client.bufferSyncSupport.hasPendingDiagnostics(document.uri)) {
238-
return [];
243+
return;
239244
}
240245

241246
await this.formattingConfigurationManager.ensureConfigurationForDocument(document, token);
247+
if (token.isCancellationRequested) {
248+
return;
249+
}
242250

243251
const results = new CodeActionSet();
244252
for (const diagnostic of fixableDiagnostics.values) {
245253
await this.getFixesForDiagnostic(document, file, diagnostic, results, token);
254+
if (token.isCancellationRequested) {
255+
return;
256+
}
246257
}
247258

248259
const allActions = Array.from(results.values);
@@ -303,12 +314,13 @@ class TypeScriptQuickFixProvider implements vscode.CodeActionProvider<VsCodeCode
303314
diagnostic: vscode.Diagnostic,
304315
tsAction: Proto.CodeFixAction
305316
): CodeActionSet {
306-
results.addAction(this.getSingleFixForTsCodeAction(diagnostic, tsAction));
307-
this.addFixAllForTsCodeAction(results, document, file, diagnostic, tsAction as Proto.CodeFixAction);
317+
results.addAction(this.getSingleFixForTsCodeAction(document.uri, diagnostic, tsAction));
318+
this.addFixAllForTsCodeAction(results, document.uri, file, diagnostic, tsAction as Proto.CodeFixAction);
308319
return results;
309320
}
310321

311322
private getSingleFixForTsCodeAction(
323+
resource: vscode.Uri,
312324
diagnostic: vscode.Diagnostic,
313325
tsAction: Proto.CodeFixAction
314326
): VsCodeCodeAction {
@@ -317,15 +329,15 @@ class TypeScriptQuickFixProvider implements vscode.CodeActionProvider<VsCodeCode
317329
codeAction.diagnostics = [diagnostic];
318330
codeAction.command = {
319331
command: ApplyCodeActionCommand.ID,
320-
arguments: [tsAction],
332+
arguments: [<ApplyCodeActionCommand_args>{ action: tsAction, diagnostic, resource }],
321333
title: ''
322334
};
323335
return codeAction;
324336
}
325337

326338
private addFixAllForTsCodeAction(
327339
results: CodeActionSet,
328-
document: vscode.TextDocument,
340+
resource: vscode.Uri,
329341
file: string,
330342
diagnostic: vscode.Diagnostic,
331343
tsAction: Proto.CodeFixAction,
@@ -335,7 +347,7 @@ class TypeScriptQuickFixProvider implements vscode.CodeActionProvider<VsCodeCode
335347
}
336348

337349
// Make sure there are multiple diagnostics of the same type in the file
338-
if (!this.diagnosticsManager.getDiagnostics(document.uri).some(x => {
350+
if (!this.diagnosticsManager.getDiagnostics(resource).some(x => {
339351
if (x === diagnostic) {
340352
return false;
341353
}

extensions/typescript-language-features/src/typescriptServiceClient.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
178178
this.diagnosticsManager = new DiagnosticsManager('typescript', onCaseInsenitiveFileSystem);
179179
this.bufferSyncSupport.onDelete(resource => {
180180
this.cancelInflightRequestsForResource(resource);
181-
this.diagnosticsManager.delete(resource);
181+
this.diagnosticsManager.deleteAllDiagnosticsInFile(resource);
182182
}, null, this._disposables);
183183

184184
this.bufferSyncSupport.onWillChange(resource => {

0 commit comments

Comments
 (0)