Extract a common DiagnosticsAdapter

This commit is contained in:
Alex Dima 2021-11-17 10:32:04 +01:00
parent 54a4ae36e8
commit 0312af769b
No known key found for this signature in database
GPG key ID: 39563C1504FDD0C9
5 changed files with 163 additions and 237 deletions

View file

@ -0,0 +1,151 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as lsTypes from 'vscode-languageserver-types';
import {
languages,
editor,
IMarkdownString,
Uri,
Position,
IRange,
Range,
CancellationToken,
IDisposable,
MarkerSeverity,
IEvent
} from '../fillers/monaco-editor-core';
export interface WorkerAccessor<T> {
(...more: Uri[]): Promise<T>;
}
//#region DiagnosticsAdapter
export interface ILanguageWorkerWithDiagnostics {
doValidation(uri: string): Promise<lsTypes.Diagnostic[]>;
}
export class DiagnosticsAdapter<T extends ILanguageWorkerWithDiagnostics> {
protected _disposables: IDisposable[] = [];
private _listener: { [uri: string]: IDisposable } = Object.create(null);
constructor(
private _languageId: string,
protected _worker: WorkerAccessor<T>,
configChangeEvent: IEvent<any>
) {
const onModelAdd = (model: editor.IModel): void => {
let modeId = model.getLanguageId();
if (modeId !== this._languageId) {
return;
}
let handle: number;
this._listener[model.uri.toString()] = model.onDidChangeContent(() => {
window.clearTimeout(handle);
handle = window.setTimeout(() => this._doValidate(model.uri, modeId), 500);
});
this._doValidate(model.uri, modeId);
};
const onModelRemoved = (model: editor.IModel): void => {
editor.setModelMarkers(model, this._languageId, []);
let uriStr = model.uri.toString();
let listener = this._listener[uriStr];
if (listener) {
listener.dispose();
delete this._listener[uriStr];
}
};
this._disposables.push(editor.onDidCreateModel(onModelAdd));
this._disposables.push(editor.onWillDisposeModel(onModelRemoved));
this._disposables.push(
editor.onDidChangeModelLanguage((event) => {
onModelRemoved(event.model);
onModelAdd(event.model);
})
);
this._disposables.push(
configChangeEvent((_) => {
editor.getModels().forEach((model) => {
if (model.getLanguageId() === this._languageId) {
onModelRemoved(model);
onModelAdd(model);
}
});
})
);
this._disposables.push({
dispose: () => {
editor.getModels().forEach(onModelRemoved);
for (let key in this._listener) {
this._listener[key].dispose();
}
}
});
editor.getModels().forEach(onModelAdd);
}
public dispose(): void {
this._disposables.forEach((d) => d && d.dispose());
this._disposables = [];
}
private _doValidate(resource: Uri, languageId: string): void {
this._worker(resource)
.then((worker) => {
return worker.doValidation(resource.toString());
})
.then((diagnostics) => {
const markers = diagnostics.map((d) => toDiagnostics(resource, d));
let model = editor.getModel(resource);
if (model && model.getLanguageId() === languageId) {
editor.setModelMarkers(model, languageId, markers);
}
})
.then(undefined, (err) => {
console.error(err);
});
}
}
function toSeverity(lsSeverity: number | undefined): MarkerSeverity {
switch (lsSeverity) {
case lsTypes.DiagnosticSeverity.Error:
return MarkerSeverity.Error;
case lsTypes.DiagnosticSeverity.Warning:
return MarkerSeverity.Warning;
case lsTypes.DiagnosticSeverity.Information:
return MarkerSeverity.Info;
case lsTypes.DiagnosticSeverity.Hint:
return MarkerSeverity.Hint;
default:
return MarkerSeverity.Info;
}
}
function toDiagnostics(resource: Uri, diag: lsTypes.Diagnostic): editor.IMarkerData {
let code = typeof diag.code === 'number' ? String(diag.code) : <string>diag.code;
return {
severity: toSeverity(diag.severity),
startLineNumber: diag.range.start.line + 1,
startColumn: diag.range.start.character + 1,
endLineNumber: diag.range.end.line + 1,
endColumn: diag.range.end.character + 1,
message: diag.message,
code: code,
source: diag.source
};
}
//#endregion

View file

@ -92,7 +92,7 @@ export function setupMode(defaults: LanguageServiceDefaults): IDisposable {
);
}
if (modeConfiguration.diagnostics) {
providers.push(new languageFeatures.DiagnosticsAdapter(languageId, worker, defaults));
providers.push(new languageFeatures.CSSDiagnosticsAdapter(languageId, worker, defaults));
}
if (modeConfiguration.selectionRanges) {
providers.push(

View file

@ -14,10 +14,9 @@ import {
Position,
IRange,
Range,
CancellationToken,
IDisposable,
MarkerSeverity
CancellationToken
} from '../fillers/monaco-editor-core';
import { DiagnosticsAdapter } from '../common/lspLanguageFeatures';
export interface WorkerAccessor {
(first: Uri, ...more: Uri[]): Promise<CSSWorker>;
@ -25,124 +24,10 @@ export interface WorkerAccessor {
// --- diagnostics --- ---
export class DiagnosticsAdapter {
private _disposables: IDisposable[] = [];
private _listener: { [uri: string]: IDisposable } = Object.create(null);
constructor(
private _languageId: string,
private _worker: WorkerAccessor,
defaults: LanguageServiceDefaults
) {
const onModelAdd = (model: editor.IModel): void => {
let modeId = model.getLanguageId();
if (modeId !== this._languageId) {
return;
}
let handle: number;
this._listener[model.uri.toString()] = model.onDidChangeContent(() => {
window.clearTimeout(handle);
handle = window.setTimeout(() => this._doValidate(model.uri, modeId), 500);
});
this._doValidate(model.uri, modeId);
};
const onModelRemoved = (model: editor.IModel): void => {
editor.setModelMarkers(model, this._languageId, []);
let uriStr = model.uri.toString();
let listener = this._listener[uriStr];
if (listener) {
listener.dispose();
delete this._listener[uriStr];
}
};
this._disposables.push(editor.onDidCreateModel(onModelAdd));
this._disposables.push(editor.onWillDisposeModel(onModelRemoved));
this._disposables.push(
editor.onDidChangeModelLanguage((event) => {
onModelRemoved(event.model);
onModelAdd(event.model);
})
);
this._disposables.push(
defaults.onDidChange((_) => {
editor.getModels().forEach((model) => {
if (model.getLanguageId() === this._languageId) {
onModelRemoved(model);
onModelAdd(model);
}
});
})
);
this._disposables.push({
dispose: () => {
editor.getModels().forEach(onModelRemoved);
for (let key in this._listener) {
this._listener[key].dispose();
}
}
});
editor.getModels().forEach(onModelAdd);
export class CSSDiagnosticsAdapter extends DiagnosticsAdapter<CSSWorker> {
constructor(languageId: string, worker: WorkerAccessor, defaults: LanguageServiceDefaults) {
super(languageId, worker, defaults.onDidChange);
}
public dispose(): void {
this._disposables.forEach((d) => d && d.dispose());
this._disposables = [];
}
private _doValidate(resource: Uri, languageId: string): void {
this._worker(resource)
.then((worker) => {
return worker.doValidation(resource.toString());
})
.then((diagnostics) => {
const markers = diagnostics.map((d) => toDiagnostics(resource, d));
let model = editor.getModel(resource);
if (model && model.getLanguageId() === languageId) {
editor.setModelMarkers(model, languageId, markers);
}
})
.then(undefined, (err) => {
console.error(err);
});
}
}
function toSeverity(lsSeverity: number | undefined): MarkerSeverity {
switch (lsSeverity) {
case lsTypes.DiagnosticSeverity.Error:
return MarkerSeverity.Error;
case lsTypes.DiagnosticSeverity.Warning:
return MarkerSeverity.Warning;
case lsTypes.DiagnosticSeverity.Information:
return MarkerSeverity.Info;
case lsTypes.DiagnosticSeverity.Hint:
return MarkerSeverity.Hint;
default:
return MarkerSeverity.Info;
}
}
function toDiagnostics(resource: Uri, diag: lsTypes.Diagnostic): editor.IMarkerData {
let code = typeof diag.code === 'number' ? String(diag.code) : <string>diag.code;
return {
severity: toSeverity(diag.severity),
startLineNumber: diag.range.start.line + 1,
startColumn: diag.range.start.character + 1,
endLineNumber: diag.range.end.line + 1,
endColumn: diag.range.end.character + 1,
message: diag.message,
code: code,
source: diag.source
};
}
// --- completion ------

View file

@ -83,7 +83,7 @@ export function setupMode(defaults: LanguageServiceDefaults): IDisposable {
);
}
if (modeConfiguration.diagnostics) {
providers.push(new languageFeatures.DiagnosticsAdapter(languageId, worker, defaults));
providers.push(new languageFeatures.JSONDiagnosticsAdapter(languageId, worker, defaults));
}
if (modeConfiguration.selectionRanges) {
providers.push(

View file

@ -14,10 +14,9 @@ import {
Position,
IRange,
Range,
CancellationToken,
IDisposable,
MarkerSeverity
CancellationToken
} from '../fillers/monaco-editor-core';
import { DiagnosticsAdapter } from '../common/lspLanguageFeatures';
export interface WorkerAccessor {
(...more: Uri[]): Promise<JSONWorker>;
@ -25,82 +24,20 @@ export interface WorkerAccessor {
// --- diagnostics --- ---
export class DiagnosticsAdapter {
private _disposables: IDisposable[] = [];
private _listener: { [uri: string]: IDisposable } = Object.create(null);
export class JSONDiagnosticsAdapter extends DiagnosticsAdapter<JSONWorker> {
constructor(languageId: string, worker: WorkerAccessor, defaults: LanguageServiceDefaults) {
super(languageId, worker, defaults.onDidChange);
constructor(
private _languageId: string,
private _worker: WorkerAccessor,
defaults: LanguageServiceDefaults
) {
const onModelAdd = (model: editor.IModel): void => {
let modeId = model.getLanguageId();
if (modeId !== this._languageId) {
return;
}
let handle: number;
this._listener[model.uri.toString()] = model.onDidChangeContent(() => {
window.clearTimeout(handle);
handle = window.setTimeout(() => this._doValidate(model.uri, modeId), 500);
});
this._doValidate(model.uri, modeId);
};
const onModelRemoved = (model: editor.IModel): void => {
editor.setModelMarkers(model, this._languageId, []);
let uriStr = model.uri.toString();
let listener = this._listener[uriStr];
if (listener) {
listener.dispose();
delete this._listener[uriStr];
}
};
this._disposables.push(editor.onDidCreateModel(onModelAdd));
this._disposables.push(
editor.onWillDisposeModel((model) => {
onModelRemoved(model);
this._resetSchema(model.uri);
})
);
this._disposables.push(
editor.onDidChangeModelLanguage((event) => {
onModelRemoved(event.model);
onModelAdd(event.model);
this._resetSchema(event.model.uri);
})
);
this._disposables.push(
defaults.onDidChange((_) => {
editor.getModels().forEach((model) => {
if (model.getLanguageId() === this._languageId) {
onModelRemoved(model);
onModelAdd(model);
}
});
})
);
this._disposables.push({
dispose: () => {
editor.getModels().forEach(onModelRemoved);
for (let key in this._listener) {
this._listener[key].dispose();
}
}
});
editor.getModels().forEach(onModelAdd);
}
public dispose(): void {
this._disposables.forEach((d) => d && d.dispose());
this._disposables = [];
}
private _resetSchema(resource: Uri): void {
@ -108,53 +45,6 @@ export class DiagnosticsAdapter {
worker.resetSchema(resource.toString());
});
}
private _doValidate(resource: Uri, languageId: string): void {
this._worker(resource)
.then((worker) => {
return worker.doValidation(resource.toString());
})
.then((diagnostics) => {
const markers = diagnostics.map((d) => toDiagnostics(resource, d));
let model = editor.getModel(resource);
if (model && model.getLanguageId() === languageId) {
editor.setModelMarkers(model, languageId, markers);
}
})
.then(undefined, (err) => {
console.error(err);
});
}
}
function toSeverity(lsSeverity: number | undefined): MarkerSeverity {
switch (lsSeverity) {
case lsTypes.DiagnosticSeverity.Error:
return MarkerSeverity.Error;
case lsTypes.DiagnosticSeverity.Warning:
return MarkerSeverity.Warning;
case lsTypes.DiagnosticSeverity.Information:
return MarkerSeverity.Info;
case lsTypes.DiagnosticSeverity.Hint:
return MarkerSeverity.Hint;
default:
return MarkerSeverity.Info;
}
}
function toDiagnostics(resource: Uri, diag: lsTypes.Diagnostic): editor.IMarkerData {
let code = typeof diag.code === 'number' ? String(diag.code) : <string>diag.code;
return {
severity: toSeverity(diag.severity),
startLineNumber: diag.range.start.line + 1,
startColumn: diag.range.start.character + 1,
endLineNumber: diag.range.end.line + 1,
endColumn: diag.range.end.character + 1,
message: diag.message,
code: code,
source: diag.source
};
}
// --- completion ------