import { debounce , LanguageServiceDefaults } from './_.contribution' ; import { editor , Uri , IDisposable , MarkerSeverity } from './fillers/monaco-editor-core' ; export interface WorkerAccessor < T > { ( first , ... more ) : Promise < T > ; } export interface IWorker { doValidation ( uri ) : Promise < any > ; valid ( code ) : Promise < any > ; parserTreeToString ( code ) : Promise < any > ; } export class DiagnosticsAdapter < T extends IWorker > { private _disposables : IDisposable [ ] = [ ] ; private _listener : { [ uri ] : IDisposable ; } = Object . create ( null ) ; constructor ( private _languageId , private _worker , defaults ) { const onModelAdd = ( model ) : void => { let modeId = model . getLanguageId ( ) ; if ( modeId !== this . _languageId ) { return ; } this . _listener [ model . uri . toString ( ) ] = model . onDidChangeContent ( debounce ( ( ) => { this . _doValidate ( model . uri , modeId ) ; } , 600 ) ) ; this . _doValidate ( model . uri , modeId ) ; } ; const onModelRemoved = ( model ) : 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 ) ; } ) ) ; defaults . onDidChange ( ( _ ) => { editor . getModels ( ) . forEach ( ( model ) => { if ( model . getLanguageId ( ) === this . _languageId ) { onModelRemoved ( model ) ; onModelAdd ( model ) ; } } ) ; } ) ; this . _disposables . push ( { dispose : ( ) => { for ( let key in this . _listener ) { this . _listener [ key ] . dispose ( ) ; } } } ) ; editor . getModels ( ) . forEach ( onModelAdd ) ; } public dispose ( ) { this . _disposables . forEach ( ( d ) => d && d . dispose ( ) ) ; this . _disposables = [ ] ; } private _doValidate ( resource , languageId ) { this . _worker ( resource ) . then ( ( worker ) => { return worker . doValidation ( editor . getModel ( resource ) ?. getValue ( ) || '' ) ; } ) . 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 ) { switch ( lsSeverity ) { default : return MarkerSeverity . Error ; } } function toDiagnostics ( resource , diag ) { let code = typeof diag . code === 'number' ? String ( diag . code ) : < string > diag . code ; return { severity : toSeverity ( diag . severity ) , startLineNumber : diag . startLine , startColumn : diag . startCol , endLineNumber : diag . endLine , endColumn : diag . endCol , message : diag . message , code : code , source : diag . source } ; }