Skip to content

Commit aee00a2

Browse files
authored
Ts suggest diagnostics (#45433)
* Support basic suggest diagnostics from TS * Removing duplicate diagnostic paths * Avoid duplicate code around handling multiple diagnostic kinds
1 parent 4bc4466 commit aee00a2

File tree

6 files changed

+78
-67
lines changed

6 files changed

+78
-67
lines changed

extensions/typescript/src/features/diagnostics.ts

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,27 @@ class DiagnosticSet {
3030
}
3131
}
3232

33-
export default class DiagnosticsManager {
33+
export enum DiagnosticKind {
34+
Syntax,
35+
Semantic,
36+
Suggestion
37+
}
38+
39+
const allDiagnosticKinds = [DiagnosticKind.Syntax, DiagnosticKind.Semantic, DiagnosticKind.Suggestion];
40+
41+
export class DiagnosticsManager {
3442

35-
private readonly syntaxDiagnostics: DiagnosticSet;
36-
private readonly semanticDiagnostics: DiagnosticSet;
43+
private readonly diagnostics = new Map<DiagnosticKind, DiagnosticSet>();
3744
private readonly currentDiagnostics: DiagnosticCollection;
3845
private _validate: boolean = true;
3946

4047
constructor(
4148
language: string
4249
) {
43-
this.syntaxDiagnostics = new DiagnosticSet();
44-
this.semanticDiagnostics = new DiagnosticSet();
50+
for (const kind of allDiagnosticKinds) {
51+
this.diagnostics.set(kind, new DiagnosticSet());
52+
}
53+
4554
this.currentDiagnostics = languages.createDiagnosticCollection(language);
4655
}
4756

@@ -51,8 +60,10 @@ export default class DiagnosticsManager {
5160

5261
public reInitialize(): void {
5362
this.currentDiagnostics.clear();
54-
this.syntaxDiagnostics.clear();
55-
this.semanticDiagnostics.clear();
63+
64+
for (const diagnosticSet of this.diagnostics.values()) {
65+
diagnosticSet.clear();
66+
}
5667
}
5768

5869
public set validate(value: boolean) {
@@ -65,14 +76,16 @@ export default class DiagnosticsManager {
6576
}
6677
}
6778

68-
public syntaxDiagnosticsReceived(file: Uri, syntaxDiagnostics: Diagnostic[]): void {
69-
this.syntaxDiagnostics.set(file, syntaxDiagnostics);
70-
this.updateCurrentDiagnostics(file);
71-
}
72-
73-
public semanticDiagnosticsReceived(file: Uri, semanticDiagnostics: Diagnostic[]): void {
74-
this.semanticDiagnostics.set(file, semanticDiagnostics);
75-
this.updateCurrentDiagnostics(file);
79+
public diagnosticsReceived(
80+
kind: DiagnosticKind,
81+
file: Uri,
82+
syntaxDiagnostics: Diagnostic[]
83+
): void {
84+
const diagnostics = this.diagnostics.get(kind);
85+
if (diagnostics) {
86+
diagnostics.set(file, syntaxDiagnostics);
87+
this.updateCurrentDiagnostics(file);
88+
}
7689
}
7790

7891
public configFileDiagnosticsReceived(file: Uri, diagnostics: Diagnostic[]): void {
@@ -88,9 +101,11 @@ export default class DiagnosticsManager {
88101
return;
89102
}
90103

91-
const semanticDiagnostics = this.semanticDiagnostics.get(file);
92-
const syntaxDiagnostics = this.syntaxDiagnostics.get(file);
93-
this.currentDiagnostics.set(file, semanticDiagnostics.concat(syntaxDiagnostics));
104+
const allDiagnostics = allDiagnosticKinds.reduce((sum, kind) => {
105+
sum.push(...this.diagnostics.get(kind)!.get(file));
106+
return sum;
107+
}, [] as Diagnostic[]);
108+
this.currentDiagnostics.set(file, allDiagnostics);
94109
}
95110

96111
public getDiagnostics(file: Uri): Diagnostic[] {

extensions/typescript/src/features/quickFixProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import * as typeConverters from '../utils/typeConverters';
1111
import FormattingConfigurationManager from './formattingConfigurationManager';
1212
import { getEditForCodeAction, applyCodeActionCommands } from '../utils/codeAction';
1313
import { Command, CommandManager } from '../utils/commandManager';
14-
import DiagnosticsManager from './diagnostics';
14+
import { DiagnosticsManager } from './diagnostics';
1515

1616
import * as nls from 'vscode-nls';
1717
const localize = nls.loadMessageBundle();

extensions/typescript/src/languageProvider.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import TypingsStatus from './utils/typingsStatus';
1414
import FormattingConfigurationManager from './features/formattingConfigurationManager';
1515
import * as languageConfigurations from './utils/languageConfigurations';
1616
import { CommandManager } from './utils/commandManager';
17-
import DiagnosticsManager from './features/diagnostics';
17+
import { DiagnosticsManager, DiagnosticKind } from './features/diagnostics';
1818
import { LanguageDescription } from './utils/languageDescription';
1919
import * as fileSchemes from './utils/fileSchemes';
2020
import { CachedNavTreeResponse } from './features/baseCodeLensProvider';
@@ -233,12 +233,8 @@ export default class LanguageProvider {
233233
this.bufferSyncSupport.requestAllDiagnostics();
234234
}
235235

236-
public syntaxDiagnosticsReceived(file: Uri, syntaxDiagnostics: Diagnostic[]): void {
237-
this.diagnosticsManager.syntaxDiagnosticsReceived(file, syntaxDiagnostics);
238-
}
239-
240-
public semanticDiagnosticsReceived(file: Uri, semanticDiagnostics: Diagnostic[]): void {
241-
this.diagnosticsManager.semanticDiagnosticsReceived(file, semanticDiagnostics);
236+
public diagnosticsReceived(diagnosticsKind: DiagnosticKind, file: Uri, syntaxDiagnostics: Diagnostic[]): void {
237+
this.diagnosticsManager.diagnosticsReceived(diagnosticsKind, file, syntaxDiagnostics);
242238
}
243239

244240
public configFileDiagnosticsReceived(file: Uri, diagnostics: Diagnostic[]): void {

extensions/typescript/src/protocol.const.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,6 @@ export class Kind {
3636

3737
export class DiagnosticCategory {
3838
public static readonly error = 'error';
39-
4039
public static readonly warning = 'warning';
40+
public static readonly suggestion = 'suggestion';
4141
}

extensions/typescript/src/typeScriptServiceClientHost.ts

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { CommandManager } from './utils/commandManager';
2424
import { LanguageDescription } from './utils/languageDescription';
2525
import LogDirectoryProvider from './utils/logDirectoryProvider';
2626
import { disposeAll } from './utils/dipose';
27+
import { DiagnosticKind } from './features/diagnostics';
2728

2829
// Style check diagnostics that can be reported as warnings
2930
const styleCheckDiagnostics = [
@@ -70,8 +71,10 @@ export default class TypeScriptServiceClientHost {
7071
this.client = new TypeScriptServiceClient(workspaceState, version => this.versionStatus.onDidChangeTypeScriptVersion(version), plugins, logDirectoryProvider);
7172
this.disposables.push(this.client);
7273

73-
this.client.onSyntaxDiagnosticsReceived(({ resource, diagnostics }) => this.syntaxDiagnosticsReceived(resource, diagnostics), null, this.disposables);
74-
this.client.onSemanticDiagnosticsReceived(({ resource, diagnostics }) => this.semanticDiagnosticsReceived(resource, diagnostics), null, this.disposables);
74+
this.client.onDiagnosticsReceived(({ kind, resource, diagnostics }) => {
75+
this.diagnosticsReceived(kind, resource, diagnostics);
76+
}, null, this.disposables);
77+
7578
this.client.onConfigDiagnosticsReceived(diag => this.configFileDiagnosticsReceived(diag), null, this.disposables);
7679
this.client.onResendModelsRequested(() => this.populateService(), null, this.disposables);
7780

@@ -170,19 +173,15 @@ export default class TypeScriptServiceClientHost {
170173
});
171174
}
172175

173-
private async syntaxDiagnosticsReceived(resource: Uri, diagnostics: Proto.Diagnostic[]): Promise<void> {
176+
private async diagnosticsReceived(
177+
kind: DiagnosticKind,
178+
resource: Uri,
179+
diagnostics: Proto.Diagnostic[]
180+
): Promise<void> {
174181
const language = await this.findLanguage(resource);
175182
if (language) {
176-
language.syntaxDiagnosticsReceived(
177-
resource,
178-
this.createMarkerDatas(diagnostics, language.diagnosticSource));
179-
}
180-
}
181-
182-
private async semanticDiagnosticsReceived(resource: Uri, diagnostics: Proto.Diagnostic[]): Promise<void> {
183-
const language = await this.findLanguage(resource);
184-
if (language) {
185-
language.semanticDiagnosticsReceived(
183+
language.diagnosticsReceived(
184+
kind,
186185
resource,
187186
this.createMarkerDatas(diagnostics, language.diagnosticSource));
188187
}
@@ -267,6 +266,9 @@ export default class TypeScriptServiceClientHost {
267266
case PConst.DiagnosticCategory.warning:
268267
return DiagnosticSeverity.Warning;
269268

269+
case PConst.DiagnosticCategory.suggestion:
270+
return DiagnosticSeverity.Hint;
271+
270272
default:
271273
return DiagnosticSeverity.Error;
272274
}

extensions/typescript/src/typescriptServiceClient.ts

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import * as fileSchemes from './utils/fileSchemes';
2929
import { inferredProjectConfig } from './utils/tsconfig';
3030
import LogDirectoryProvider from './utils/logDirectoryProvider';
3131
import { disposeAll } from './utils/dipose';
32+
import { DiagnosticKind } from './features/diagnostics';
3233

3334
const localize = nls.loadMessageBundle();
3435

@@ -140,6 +141,7 @@ class ForkedTsServerProcess {
140141
}
141142

142143
export interface TsDiagnostics {
144+
readonly kind: DiagnosticKind;
143145
readonly resource: Uri;
144146
readonly diagnostics: Proto.Diagnostic[];
145147
}
@@ -237,11 +239,8 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
237239
this.disposables.push(this.telemetryReporter);
238240
}
239241

240-
private _onSyntaxDiagnosticsReceived = new EventEmitter<TsDiagnostics>();
241-
public get onSyntaxDiagnosticsReceived(): Event<TsDiagnostics> { return this._onSyntaxDiagnosticsReceived.event; }
242-
243-
private _onSemanticDiagnosticsReceived = new EventEmitter<TsDiagnostics>();
244-
public get onSemanticDiagnosticsReceived(): Event<TsDiagnostics> { return this._onSemanticDiagnosticsReceived.event; }
242+
private _onDiagnosticsReceived = new EventEmitter<TsDiagnostics>();
243+
public get onDiagnosticsReceived(): Event<TsDiagnostics> { return this._onDiagnosticsReceived.event; }
245244

246245
private _onConfigDiagnosticsReceived = new EventEmitter<Proto.ConfigFileDiagnosticEvent>();
247246
public get onConfigDiagnosticsReceived(): Event<Proto.ConfigFileDiagnosticEvent> { return this._onConfigDiagnosticsReceived.event; }
@@ -266,8 +265,7 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
266265
}
267266

268267
disposeAll(this.disposables);
269-
this._onSyntaxDiagnosticsReceived.dispose();
270-
this._onSemanticDiagnosticsReceived.dispose();
268+
this._onDiagnosticsReceived.dispose();
271269
this._onConfigDiagnosticsReceived.dispose();
272270
this._onResendModelsRequested.dispose();
273271
}
@@ -803,27 +801,18 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
803801
private dispatchEvent(event: Proto.Event) {
804802
switch (event.event) {
805803
case 'syntaxDiag':
806-
{
807-
const diagnosticEvent: Proto.DiagnosticEvent = event;
808-
if (diagnosticEvent.body && diagnosticEvent.body.diagnostics) {
809-
this._onSyntaxDiagnosticsReceived.fire({
810-
resource: this.asUrl(diagnosticEvent.body.file),
811-
diagnostics: diagnosticEvent.body.diagnostics
812-
});
813-
}
814-
break;
815-
}
816804
case 'semanticDiag':
817-
{
818-
const diagnosticEvent: Proto.DiagnosticEvent = event;
819-
if (diagnosticEvent.body && diagnosticEvent.body.diagnostics) {
820-
this._onSemanticDiagnosticsReceived.fire({
821-
resource: this.asUrl(diagnosticEvent.body.file),
822-
diagnostics: diagnosticEvent.body.diagnostics
823-
});
824-
}
825-
break;
805+
case 'suggestionDiag':
806+
const diagnosticEvent: Proto.DiagnosticEvent = event;
807+
if (diagnosticEvent.body && diagnosticEvent.body.diagnostics) {
808+
this._onDiagnosticsReceived.fire({
809+
kind: getDignosticsKind(event),
810+
resource: this.asUrl(diagnosticEvent.body.file),
811+
diagnostics: diagnosticEvent.body.diagnostics
812+
});
826813
}
814+
break;
815+
827816
case 'configFileDiag':
828817
this._onConfigDiagnosticsReceived.fire(event as Proto.ConfigFileDiagnosticEvent);
829818
break;
@@ -994,4 +983,13 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
994983
const getTsLocale = (configuration: TypeScriptServiceConfiguration): string | undefined =>
995984
(configuration.locale
996985
? configuration.locale
997-
: env.language);
986+
: env.language);
987+
988+
function getDignosticsKind(event: Proto.Event) {
989+
switch (event.event) {
990+
case 'syntaxDiag': return DiagnosticKind.Syntax;
991+
case 'semanticDiag': return DiagnosticKind.Semantic;
992+
case 'suggestionDiag': return DiagnosticKind.Suggestion;
993+
}
994+
throw new Error('Unknown dignostics kind');
995+
}

0 commit comments

Comments
 (0)