@@ -18,6 +18,7 @@ import { IDiskFileChange, normalizeFileChanges, ILogMessage } from 'vs/platform/
1818import { IWatcherRequest , IWatcherService , IWatcherOptions } from 'vs/platform/files/node/watcher/unix/watcher' ;
1919import { Emitter , Event } from 'vs/base/common/event' ;
2020import { equals } from 'vs/base/common/arrays' ;
21+ import { Disposable } from 'vs/base/common/lifecycle' ;
2122
2223process . noAsar = true ; // disable ASAR support in watcher process
2324
@@ -30,81 +31,76 @@ interface ExtendedWatcherRequest extends IWatcherRequest {
3031 parsedPattern ?: glob . ParsedPattern ;
3132}
3233
33- export class ChokidarWatcherService implements IWatcherService {
34+ export class ChokidarWatcherService extends Disposable implements IWatcherService {
3435
3536 private static readonly FS_EVENT_DELAY = 50 ; // aggregate and only emit events when changes have stopped for this duration (in ms)
3637 private static readonly EVENT_SPAM_WARNING_THRESHOLD = 60 * 1000 ; // warn after certain time span of event spam
3738
38- private _watchers : { [ watchPath : string ] : IWatcher } = Object . create ( null ) ;
39+ private readonly _onDidChangeFile = this . _register ( new Emitter < IDiskFileChange [ ] > ( ) ) ;
40+ readonly onDidChangeFile = this . _onDidChangeFile . event ;
41+
42+ private readonly _onDidLogMessage = this . _register ( new Emitter < ILogMessage > ( ) ) ;
43+ readonly onDidLogMessage : Event < ILogMessage > = this . _onDidLogMessage . event ;
44+
45+ private watchers = new Map < string , IWatcher > ( ) ;
46+
3947 private _watcherCount = 0 ;
48+ get wacherCount ( ) { return this . _watcherCount ; }
4049
41- private _pollingInterval ?: number ;
42- private _usePolling ?: boolean ;
43- private _verboseLogging : boolean | undefined ;
50+ private pollingInterval ?: number ;
51+ private usePolling ?: boolean ;
52+ private verboseLogging : boolean | undefined ;
4453
4554 private spamCheckStartTime : number | undefined ;
4655 private spamWarningLogged : boolean | undefined ;
4756 private enospcErrorLogged : boolean | undefined ;
4857
49- private readonly _onWatchEvent = new Emitter < IDiskFileChange [ ] > ( ) ;
50- readonly onWatchEvent = this . _onWatchEvent . event ;
51-
52- private readonly _onLogMessage = new Emitter < ILogMessage > ( ) ;
53- readonly onLogMessage : Event < ILogMessage > = this . _onLogMessage . event ;
54-
55- watch ( options : IWatcherOptions ) : Event < IDiskFileChange [ ] > {
56- this . _pollingInterval = options . pollingInterval ;
57- this . _usePolling = options . usePolling ;
58- this . _watchers = Object . create ( null ) ;
58+ async init ( options : IWatcherOptions ) : Promise < void > {
59+ this . pollingInterval = options . pollingInterval ;
60+ this . usePolling = options . usePolling ;
61+ this . watchers . clear ( ) ;
5962 this . _watcherCount = 0 ;
60-
61- return this . onWatchEvent ;
63+ this . verboseLogging = options . verboseLogging ;
6264 }
6365
6466 async setVerboseLogging ( enabled : boolean ) : Promise < void > {
65- this . _verboseLogging = enabled ;
67+ this . verboseLogging = enabled ;
6668 }
6769
6870 async setRoots ( requests : IWatcherRequest [ ] ) : Promise < void > {
69- const watchers = Object . create ( null ) ;
71+ const watchers = new Map < string , IWatcher > ( ) ;
7072 const newRequests : string [ ] = [ ] ;
7173
7274 const requestsByBasePath = normalizeRoots ( requests ) ;
7375
7476 // evaluate new & remaining watchers
7577 for ( const basePath in requestsByBasePath ) {
76- const watcher = this . _watchers [ basePath ] ;
78+ const watcher = this . watchers . get ( basePath ) ;
7779 if ( watcher && isEqualRequests ( watcher . requests , requestsByBasePath [ basePath ] ) ) {
78- watchers [ basePath ] = watcher ;
79- delete this . _watchers [ basePath ] ;
80+ watchers . set ( basePath , watcher ) ;
81+ this . watchers . delete ( basePath ) ;
8082 } else {
8183 newRequests . push ( basePath ) ;
8284 }
8385 }
8486
8587 // stop all old watchers
86- for ( const path in this . _watchers ) {
87- await this . _watchers [ path ] . stop ( ) ;
88+ for ( const [ , watcher ] of this . watchers ) {
89+ await watcher . stop ( ) ;
8890 }
8991
9092 // start all new watchers
9193 for ( const basePath of newRequests ) {
9294 const requests = requestsByBasePath [ basePath ] ;
93- watchers [ basePath ] = this . _watch ( basePath , requests ) ;
95+ watchers . set ( basePath , this . watch ( basePath , requests ) ) ;
9496 }
9597
96- this . _watchers = watchers ;
98+ this . watchers = watchers ;
9799 }
98100
99- // for test purposes
100- get wacherCount ( ) {
101- return this . _watcherCount ;
102- }
103-
104- private _watch ( basePath : string , requests : IWatcherRequest [ ] ) : IWatcher {
105-
106- const pollingInterval = this . _pollingInterval || 5000 ;
107- const usePolling = this . _usePolling ;
101+ private watch ( basePath : string , requests : IWatcherRequest [ ] ) : IWatcher {
102+ const pollingInterval = this . pollingInterval || 5000 ;
103+ const usePolling = this . usePolling ;
108104
109105 const watcherOpts : chokidar . WatchOptions = {
110106 ignoreInitial : true ,
@@ -120,8 +116,7 @@ export class ChokidarWatcherService implements IWatcherService {
120116
121117 const isSingleFolder = requests . length === 1 ;
122118 if ( isSingleFolder ) {
123- // if there's only one request, use the built-in ignore-filterering
124- excludes . push ( ...requests [ 0 ] . excludes ) ;
119+ excludes . push ( ...requests [ 0 ] . excludes ) ; // if there's only one request, use the built-in ignore-filterering
125120 }
126121
127122 if ( ( isMacintosh || isLinux ) && ( basePath . length === 0 || basePath === '/' ) ) {
@@ -146,7 +141,7 @@ export class ChokidarWatcherService implements IWatcherService {
146141 this . warn ( `Watcher basePath does not match version on disk and was corrected (original: ${ basePath } , real: ${ realBasePath } )` ) ;
147142 }
148143
149- if ( this . _verboseLogging ) {
144+ if ( this . verboseLogging ) {
150145 this . log ( `Start watching with chockidar: ${ realBasePath } , excludes: ${ excludes . join ( ',' ) } , usePolling: ${ usePolling ? 'true, interval ' + pollingInterval : 'false' } ` ) ;
151146 }
152147
@@ -165,7 +160,7 @@ export class ChokidarWatcherService implements IWatcherService {
165160 requests,
166161 stop : async ( ) => {
167162 try {
168- if ( this . _verboseLogging ) {
163+ if ( this . verboseLogging ) {
169164 this . log ( `Stop watching: ${ basePath } ]` ) ;
170165 }
171166 if ( chokidarWatcher ) {
@@ -227,7 +222,7 @@ export class ChokidarWatcherService implements IWatcherService {
227222 const event = { type : eventType , path } ;
228223
229224 // Logging
230- if ( this . _verboseLogging ) {
225+ if ( this . verboseLogging ) {
231226 this . log ( `${ eventType === FileChangeType . ADDED ? '[ADDED]' : eventType === FileChangeType . DELETED ? '[DELETED]' : '[CHANGED]' } ${ path } ` ) ;
232227 }
233228
@@ -253,10 +248,10 @@ export class ChokidarWatcherService implements IWatcherService {
253248
254249 // Broadcast to clients normalized
255250 const res = normalizeFileChanges ( events ) ;
256- this . _onWatchEvent . fire ( res ) ;
251+ this . _onDidChangeFile . fire ( res ) ;
257252
258253 // Logging
259- if ( this . _verboseLogging ) {
254+ if ( this . verboseLogging ) {
260255 res . forEach ( r => {
261256 this . log ( ` >> normalized ${ r . type === FileChangeType . ADDED ? '[ADDED]' : r . type === FileChangeType . DELETED ? '[DELETED]' : '[CHANGED]' } ${ r . path } ` ) ;
262257 } ) ;
@@ -290,24 +285,23 @@ export class ChokidarWatcherService implements IWatcherService {
290285 }
291286
292287 async stop ( ) : Promise < void > {
293- for ( const path in this . _watchers ) {
294- const watcher = this . _watchers [ path ] ;
288+ for ( const [ , watcher ] of this . watchers ) {
295289 await watcher . stop ( ) ;
296290 }
297291
298- this . _watchers = Object . create ( null ) ;
292+ this . watchers . clear ( ) ;
299293 }
300294
301295 private log ( message : string ) {
302- this . _onLogMessage . fire ( { type : 'trace' , message : `[File Watcher (chokidar)] ` + message } ) ;
296+ this . _onDidLogMessage . fire ( { type : 'trace' , message : `[File Watcher (chokidar)] ` + message } ) ;
303297 }
304298
305299 private warn ( message : string ) {
306- this . _onLogMessage . fire ( { type : 'warn' , message : `[File Watcher (chokidar)] ` + message } ) ;
300+ this . _onDidLogMessage . fire ( { type : 'warn' , message : `[File Watcher (chokidar)] ` + message } ) ;
307301 }
308302
309303 private error ( message : string ) {
310- this . _onLogMessage . fire ( { type : 'error' , message : `[File Watcher (chokidar)] ` + message } ) ;
304+ this . _onDidLogMessage . fire ( { type : 'error' , message : `[File Watcher (chokidar)] ` + message } ) ;
311305 }
312306}
313307
0 commit comments