Browse Source

Extract a common `DiagnosticsAdapter`

Alex Dima 3 years ago
parent
commit
0312af769b
5 changed files with 163 additions and 237 deletions
  1. 151 0
      src/common/lspLanguageFeatures.ts
  2. 1 1
      src/css/cssMode.ts
  3. 5 120
      src/css/languageFeatures.ts
  4. 1 1
      src/json/jsonMode.ts
  5. 5 115
      src/json/languageFeatures.ts

+ 151 - 0
src/common/lspLanguageFeatures.ts

@@ -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

+ 1 - 1
src/css/cssMode.ts

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

+ 5 - 120
src/css/languageFeatures.ts

@@ -14,10 +14,9 @@ import {
 	Position,
 	Position,
 	IRange,
 	IRange,
 	Range,
 	Range,
-	CancellationToken,
-	IDisposable,
-	MarkerSeverity
+	CancellationToken
 } from '../fillers/monaco-editor-core';
 } from '../fillers/monaco-editor-core';
+import { DiagnosticsAdapter } from '../common/lspLanguageFeatures';
 
 
 export interface WorkerAccessor {
 export interface WorkerAccessor {
 	(first: Uri, ...more: Uri[]): Promise<CSSWorker>;
 	(first: Uri, ...more: Uri[]): Promise<CSSWorker>;
@@ -25,124 +24,10 @@ export interface WorkerAccessor {
 
 
 // --- diagnostics --- ---
 // --- 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);
-	}
-
-	public dispose(): void {
-		this._disposables.forEach((d) => d && d.dispose());
-		this._disposables = [];
+export class CSSDiagnosticsAdapter extends DiagnosticsAdapter<CSSWorker> {
+	constructor(languageId: string, worker: WorkerAccessor, defaults: LanguageServiceDefaults) {
+		super(languageId, worker, defaults.onDidChange);
 	}
 	}
-
-	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 ------
 // --- completion ------

+ 1 - 1
src/json/jsonMode.ts

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

+ 5 - 115
src/json/languageFeatures.ts

@@ -14,10 +14,9 @@ import {
 	Position,
 	Position,
 	IRange,
 	IRange,
 	Range,
 	Range,
-	CancellationToken,
-	IDisposable,
-	MarkerSeverity
+	CancellationToken
 } from '../fillers/monaco-editor-core';
 } from '../fillers/monaco-editor-core';
+import { DiagnosticsAdapter } from '../common/lspLanguageFeatures';
 
 
 export interface WorkerAccessor {
 export interface WorkerAccessor {
 	(...more: Uri[]): Promise<JSONWorker>;
 	(...more: Uri[]): Promise<JSONWorker>;
@@ -25,82 +24,20 @@ export interface WorkerAccessor {
 
 
 // --- diagnostics --- ---
 // --- 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);
-		};
+export class JSONDiagnosticsAdapter extends DiagnosticsAdapter<JSONWorker> {
+	constructor(languageId: string, worker: WorkerAccessor, defaults: LanguageServiceDefaults) {
+		super(languageId, worker, defaults.onDidChange);
 
 
-		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(
 		this._disposables.push(
 			editor.onWillDisposeModel((model) => {
 			editor.onWillDisposeModel((model) => {
-				onModelRemoved(model);
 				this._resetSchema(model.uri);
 				this._resetSchema(model.uri);
 			})
 			})
 		);
 		);
 		this._disposables.push(
 		this._disposables.push(
 			editor.onDidChangeModelLanguage((event) => {
 			editor.onDidChangeModelLanguage((event) => {
-				onModelRemoved(event.model);
-				onModelAdd(event.model);
 				this._resetSchema(event.model.uri);
 				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 {
 	private _resetSchema(resource: Uri): void {
@@ -108,53 +45,6 @@ export class DiagnosticsAdapter {
 			worker.resetSchema(resource.toString());
 			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 ------
 // --- completion ------