@@ -5,6 +5,7 @@ const chokidar = require('chokidar');
55const fs = require ( 'fs-extra' ) ;
66const escapeRegex = require ( 'escape-string-regexp' ) ;
77const path = require ( 'path' ) ;
8+ const glob = require ( 'glob' ) ;
89
910const trace = require ( 'debug' ) ( 'ember-cli-typescript:tsc:trace' ) ;
1011const debug = require ( 'debug' ) ( 'ember-cli-typescript:watcher' ) ;
@@ -69,65 +70,51 @@ function diagnosticCallback(callback) {
6970
7071function buildWatchHooks ( project , ts , callbacks ) {
7172 let ignorePatterns = [ '\\..*?' , 'dist' , 'tmp' , 'node_modules' ] ;
72- let watchedFiles = new Map ( ) ;
7373
7474 return Object . assign ( { } , ts . sys , {
75- watchFile ( file , callback ) {
76- let key = path . resolve ( file ) ;
77- if ( ! watchedFiles . has ( key ) ) {
78- debug ( `watching file %s` , key ) ;
79- watchedFiles . set ( key , [ ] ) ;
80- }
81-
82- watchedFiles . get ( key ) . push ( callback ) ;
83-
84- return {
85- close ( ) {
86- let callbacks = watchedFiles . get ( key ) ;
87- if ( callbacks . length === 1 ) {
88- debug ( `unwatching file %s` , key ) ;
89- watchedFiles . delete ( key ) ;
90- } else {
91- callbacks . splice ( callbacks . indexOf ( callback ) , 1 ) ;
92- }
93- }
94- } ;
95- } ,
96-
97- watchDirectory ( dir , callback ) {
98- if ( ! fs . existsSync ( dir ) ) {
99- debug ( `skipping watch for nonexistent directory %s` , dir ) ;
75+ watchFile : null ,
76+ watchDirectory ( rawDir , callback ) {
77+ if ( ! fs . existsSync ( rawDir ) ) {
78+ debug ( `skipping watch for nonexistent directory %s` , rawDir ) ;
10079 return ;
10180 }
10281
82+ let dir = getCanonicalCapitalization ( path . resolve ( rawDir ) ) ;
10383 let ignored = buildIgnoreRegex ( dir , ignorePatterns ) ;
10484 let watcher = chokidar . watch ( dir , { ignored, ignoreInitial : true } ) ;
10585 debug ( `watching directory %s %o` , dir , { ignored } ) ;
10686
10787 watcher . on ( 'all' , ( type , rawPath ) => {
10888 let resolvedPath = path . resolve ( rawPath ) ;
10989
110- if ( watchedFiles . has ( resolvedPath ) && ( type === 'change' || type === 'unlink' ) ) {
111- debug ( `%s: watched path %s` , type , resolvedPath ) ;
112- let kind = type === 'change' ? ts . FileWatcherEventKind . Changed : ts . FileWatcherEventKind . Deleted ;
113- watchedFiles . get ( resolvedPath ) . forEach ( callback => callback ( resolvedPath , kind ) ) ;
114- } else {
115- debug ( `%s: unwatched path %s (for directory watch on %s)` , type , resolvedPath , dir ) ;
116- callback ( resolvedPath ) ;
117- }
90+ debug ( `%s: %s (for directory watch on %s)` , type , resolvedPath , dir ) ;
91+ callback ( resolvedPath ) ;
11892
11993 if ( resolvedPath . endsWith ( '.ts' ) && callbacks . watchedFileChanged ) {
12094 callbacks . watchedFileChanged ( ) ;
12195 }
12296 } ) ;
12397
124- return watcher ;
98+ return {
99+ close ( ) {
100+ debug ( 'closing watcher for %s' , dir ) ;
101+ watcher . close ( ) ;
102+ }
103+ } ;
125104 }
126105 } ) ;
127106}
128107
129108function buildIgnoreRegex ( rootDir , patterns ) {
130109 let base = escapeRegex ( rootDir ) ;
131110 let sep = `[/\\\\]` ;
132- return new RegExp ( `^${ base } ${ sep } (${ patterns . join ( '|' ) } )${ sep } ` ) ;
111+ return new RegExp ( `^${ base } ${ sep } (${ patterns . join ( '|' ) } )${ sep } ` , 'i' ) ;
112+ }
113+
114+ // On case-insensitive file systems, tsc will normalize paths to be all lowercase,
115+ // but chokidar expects the paths it's given to watch to exactly match what it's
116+ // delivered in fs events.
117+ function getCanonicalCapitalization ( rawPath ) {
118+ let normalized = rawPath . replace ( / \\ / g, '/' ) . replace ( / ^ [ a - z ] : / i, '' ) ;
119+ return glob . sync ( normalized , { nocase : true } ) [ 0 ] ;
133120}
0 commit comments