Ts suggest diagnostics (#45433)

* Support basic suggest diagnostics from TS

* Removing duplicate diagnostic paths

* Avoid duplicate code around handling multiple diagnostic kinds
This commit is contained in:
Matt Bierner
2018-03-20 10:35:46 -07:00
committed by GitHub
parent 4bc4466da5
commit aee00a209b
6 changed files with 78 additions and 67 deletions
@@ -30,18 +30,27 @@ class DiagnosticSet {
}
}
export default class DiagnosticsManager {
export enum DiagnosticKind {
Syntax,
Semantic,
Suggestion
}
private readonly syntaxDiagnostics: DiagnosticSet;
private readonly semanticDiagnostics: DiagnosticSet;
const allDiagnosticKinds = [DiagnosticKind.Syntax, DiagnosticKind.Semantic, DiagnosticKind.Suggestion];
export class DiagnosticsManager {
private readonly diagnostics = new Map<DiagnosticKind, DiagnosticSet>();
private readonly currentDiagnostics: DiagnosticCollection;
private _validate: boolean = true;
constructor(
language: string
) {
this.syntaxDiagnostics = new DiagnosticSet();
this.semanticDiagnostics = new DiagnosticSet();
for (const kind of allDiagnosticKinds) {
this.diagnostics.set(kind, new DiagnosticSet());
}
this.currentDiagnostics = languages.createDiagnosticCollection(language);
}
@@ -51,8 +60,10 @@ export default class DiagnosticsManager {
public reInitialize(): void {
this.currentDiagnostics.clear();
this.syntaxDiagnostics.clear();
this.semanticDiagnostics.clear();
for (const diagnosticSet of this.diagnostics.values()) {
diagnosticSet.clear();
}
}
public set validate(value: boolean) {
@@ -65,14 +76,16 @@ export default class DiagnosticsManager {
}
}
public syntaxDiagnosticsReceived(file: Uri, syntaxDiagnostics: Diagnostic[]): void {
this.syntaxDiagnostics.set(file, syntaxDiagnostics);
this.updateCurrentDiagnostics(file);
}
public semanticDiagnosticsReceived(file: Uri, semanticDiagnostics: Diagnostic[]): void {
this.semanticDiagnostics.set(file, semanticDiagnostics);
this.updateCurrentDiagnostics(file);
public diagnosticsReceived(
kind: DiagnosticKind,
file: Uri,
syntaxDiagnostics: Diagnostic[]
): void {
const diagnostics = this.diagnostics.get(kind);
if (diagnostics) {
diagnostics.set(file, syntaxDiagnostics);
this.updateCurrentDiagnostics(file);
}
}
public configFileDiagnosticsReceived(file: Uri, diagnostics: Diagnostic[]): void {
@@ -88,9 +101,11 @@ export default class DiagnosticsManager {
return;
}
const semanticDiagnostics = this.semanticDiagnostics.get(file);
const syntaxDiagnostics = this.syntaxDiagnostics.get(file);
this.currentDiagnostics.set(file, semanticDiagnostics.concat(syntaxDiagnostics));
const allDiagnostics = allDiagnosticKinds.reduce((sum, kind) => {
sum.push(...this.diagnostics.get(kind)!.get(file));
return sum;
}, [] as Diagnostic[]);
this.currentDiagnostics.set(file, allDiagnostics);
}
public getDiagnostics(file: Uri): Diagnostic[] {
@@ -11,7 +11,7 @@ import * as typeConverters from '../utils/typeConverters';
import FormattingConfigurationManager from './formattingConfigurationManager';
import { getEditForCodeAction, applyCodeActionCommands } from '../utils/codeAction';
import { Command, CommandManager } from '../utils/commandManager';
import DiagnosticsManager from './diagnostics';
import { DiagnosticsManager } from './diagnostics';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
@@ -14,7 +14,7 @@ import TypingsStatus from './utils/typingsStatus';
import FormattingConfigurationManager from './features/formattingConfigurationManager';
import * as languageConfigurations from './utils/languageConfigurations';
import { CommandManager } from './utils/commandManager';
import DiagnosticsManager from './features/diagnostics';
import { DiagnosticsManager, DiagnosticKind } from './features/diagnostics';
import { LanguageDescription } from './utils/languageDescription';
import * as fileSchemes from './utils/fileSchemes';
import { CachedNavTreeResponse } from './features/baseCodeLensProvider';
@@ -233,12 +233,8 @@ export default class LanguageProvider {
this.bufferSyncSupport.requestAllDiagnostics();
}
public syntaxDiagnosticsReceived(file: Uri, syntaxDiagnostics: Diagnostic[]): void {
this.diagnosticsManager.syntaxDiagnosticsReceived(file, syntaxDiagnostics);
}
public semanticDiagnosticsReceived(file: Uri, semanticDiagnostics: Diagnostic[]): void {
this.diagnosticsManager.semanticDiagnosticsReceived(file, semanticDiagnostics);
public diagnosticsReceived(diagnosticsKind: DiagnosticKind, file: Uri, syntaxDiagnostics: Diagnostic[]): void {
this.diagnosticsManager.diagnosticsReceived(diagnosticsKind, file, syntaxDiagnostics);
}
public configFileDiagnosticsReceived(file: Uri, diagnostics: Diagnostic[]): void {
+1 -1
View File
@@ -36,6 +36,6 @@ export class Kind {
export class DiagnosticCategory {
public static readonly error = 'error';
public static readonly warning = 'warning';
public static readonly suggestion = 'suggestion';
}
@@ -24,6 +24,7 @@ import { CommandManager } from './utils/commandManager';
import { LanguageDescription } from './utils/languageDescription';
import LogDirectoryProvider from './utils/logDirectoryProvider';
import { disposeAll } from './utils/dipose';
import { DiagnosticKind } from './features/diagnostics';
// Style check diagnostics that can be reported as warnings
const styleCheckDiagnostics = [
@@ -70,8 +71,10 @@ export default class TypeScriptServiceClientHost {
this.client = new TypeScriptServiceClient(workspaceState, version => this.versionStatus.onDidChangeTypeScriptVersion(version), plugins, logDirectoryProvider);
this.disposables.push(this.client);
this.client.onSyntaxDiagnosticsReceived(({ resource, diagnostics }) => this.syntaxDiagnosticsReceived(resource, diagnostics), null, this.disposables);
this.client.onSemanticDiagnosticsReceived(({ resource, diagnostics }) => this.semanticDiagnosticsReceived(resource, diagnostics), null, this.disposables);
this.client.onDiagnosticsReceived(({ kind, resource, diagnostics }) => {
this.diagnosticsReceived(kind, resource, diagnostics);
}, null, this.disposables);
this.client.onConfigDiagnosticsReceived(diag => this.configFileDiagnosticsReceived(diag), null, this.disposables);
this.client.onResendModelsRequested(() => this.populateService(), null, this.disposables);
@@ -170,19 +173,15 @@ export default class TypeScriptServiceClientHost {
});
}
private async syntaxDiagnosticsReceived(resource: Uri, diagnostics: Proto.Diagnostic[]): Promise<void> {
private async diagnosticsReceived(
kind: DiagnosticKind,
resource: Uri,
diagnostics: Proto.Diagnostic[]
): Promise<void> {
const language = await this.findLanguage(resource);
if (language) {
language.syntaxDiagnosticsReceived(
resource,
this.createMarkerDatas(diagnostics, language.diagnosticSource));
}
}
private async semanticDiagnosticsReceived(resource: Uri, diagnostics: Proto.Diagnostic[]): Promise<void> {
const language = await this.findLanguage(resource);
if (language) {
language.semanticDiagnosticsReceived(
language.diagnosticsReceived(
kind,
resource,
this.createMarkerDatas(diagnostics, language.diagnosticSource));
}
@@ -267,6 +266,9 @@ export default class TypeScriptServiceClientHost {
case PConst.DiagnosticCategory.warning:
return DiagnosticSeverity.Warning;
case PConst.DiagnosticCategory.suggestion:
return DiagnosticSeverity.Hint;
default:
return DiagnosticSeverity.Error;
}
@@ -29,6 +29,7 @@ import * as fileSchemes from './utils/fileSchemes';
import { inferredProjectConfig } from './utils/tsconfig';
import LogDirectoryProvider from './utils/logDirectoryProvider';
import { disposeAll } from './utils/dipose';
import { DiagnosticKind } from './features/diagnostics';
const localize = nls.loadMessageBundle();
@@ -140,6 +141,7 @@ class ForkedTsServerProcess {
}
export interface TsDiagnostics {
readonly kind: DiagnosticKind;
readonly resource: Uri;
readonly diagnostics: Proto.Diagnostic[];
}
@@ -237,11 +239,8 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
this.disposables.push(this.telemetryReporter);
}
private _onSyntaxDiagnosticsReceived = new EventEmitter<TsDiagnostics>();
public get onSyntaxDiagnosticsReceived(): Event<TsDiagnostics> { return this._onSyntaxDiagnosticsReceived.event; }
private _onSemanticDiagnosticsReceived = new EventEmitter<TsDiagnostics>();
public get onSemanticDiagnosticsReceived(): Event<TsDiagnostics> { return this._onSemanticDiagnosticsReceived.event; }
private _onDiagnosticsReceived = new EventEmitter<TsDiagnostics>();
public get onDiagnosticsReceived(): Event<TsDiagnostics> { return this._onDiagnosticsReceived.event; }
private _onConfigDiagnosticsReceived = new EventEmitter<Proto.ConfigFileDiagnosticEvent>();
public get onConfigDiagnosticsReceived(): Event<Proto.ConfigFileDiagnosticEvent> { return this._onConfigDiagnosticsReceived.event; }
@@ -266,8 +265,7 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
}
disposeAll(this.disposables);
this._onSyntaxDiagnosticsReceived.dispose();
this._onSemanticDiagnosticsReceived.dispose();
this._onDiagnosticsReceived.dispose();
this._onConfigDiagnosticsReceived.dispose();
this._onResendModelsRequested.dispose();
}
@@ -803,27 +801,18 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
private dispatchEvent(event: Proto.Event) {
switch (event.event) {
case 'syntaxDiag':
{
const diagnosticEvent: Proto.DiagnosticEvent = event;
if (diagnosticEvent.body && diagnosticEvent.body.diagnostics) {
this._onSyntaxDiagnosticsReceived.fire({
resource: this.asUrl(diagnosticEvent.body.file),
diagnostics: diagnosticEvent.body.diagnostics
});
}
break;
}
case 'semanticDiag':
{
const diagnosticEvent: Proto.DiagnosticEvent = event;
if (diagnosticEvent.body && diagnosticEvent.body.diagnostics) {
this._onSemanticDiagnosticsReceived.fire({
resource: this.asUrl(diagnosticEvent.body.file),
diagnostics: diagnosticEvent.body.diagnostics
});
}
break;
case 'suggestionDiag':
const diagnosticEvent: Proto.DiagnosticEvent = event;
if (diagnosticEvent.body && diagnosticEvent.body.diagnostics) {
this._onDiagnosticsReceived.fire({
kind: getDignosticsKind(event),
resource: this.asUrl(diagnosticEvent.body.file),
diagnostics: diagnosticEvent.body.diagnostics
});
}
break;
case 'configFileDiag':
this._onConfigDiagnosticsReceived.fire(event as Proto.ConfigFileDiagnosticEvent);
break;
@@ -994,4 +983,13 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
const getTsLocale = (configuration: TypeScriptServiceConfiguration): string | undefined =>
(configuration.locale
? configuration.locale
: env.language);
: env.language);
function getDignosticsKind(event: Proto.Event) {
switch (event.event) {
case 'syntaxDiag': return DiagnosticKind.Syntax;
case 'semanticDiag': return DiagnosticKind.Semantic;
case 'suggestionDiag': return DiagnosticKind.Suggestion;
}
throw new Error('Unknown dignostics kind');
}