import { FSWatcher , watch } from 'chokidar' ; import { debounce } from 'lodash' ; import { join } from 'path' ; import { DidChangeWatchedFilesParams , FileChangeType , FileEvent } from 'vscode-languageserver' ; import { pathToUrl } from '../utils' ; type DidChangeHandler = ( para : DidChangeWatchedFilesParams ) => void ; const DELAY = 50 ; export class FallbackWatcher { private readonly watcher : FSWatcher ; private readonly callbacks : DidChangeHandler [ ] = [ ] ; private undeliveredFileEvents : FileEvent [ ] = [ ] ; constructor ( glob , workspacePaths ) { const gitOrNodeModules = /\.git|node_modules/ ; this . watcher = watch ( workspacePaths . map ( ( workspacePath ) => join ( workspacePath , glob ) ) , { ignored : ( path ) => gitOrNodeModules . test ( path ) && ! path . includes ( 'src/node_modules' ) && ! path . includes ( 'src\\node_modules' ) , ignoreInitial : true , ignorePermissionErrors : true } ) ; this . watcher . on ( 'add' , ( path ) => this . onFSEvent ( path , FileChangeType . Created ) ) . on ( 'unlink' , ( path ) => this . onFSEvent ( path , FileChangeType . Deleted ) ) . on ( 'change' , ( path ) => this . onFSEvent ( path , FileChangeType . Changed ) ) ; } private convert ( path , type ) { return { type , uri : pathToUrl ( path ) } ; } private onFSEvent ( path , type ) { const fileEvent = this . convert ( path , type ) ; this . undeliveredFileEvents . push ( fileEvent ) ; this . scheduleTrigger ( ) ; } private readonly scheduleTrigger = debounce ( ( ) => { const para = { changes : this . undeliveredFileEvents } ; this . undeliveredFileEvents = [ ] ; this . callbacks . forEach ( ( callback ) => callback ( para ) ) ; } , DELAY ) ; onDidChangeWatchedFiles ( callback ) { this . callbacks . push ( callback ) ; } dispose ( ) { this . watcher . close ( ) ; } }