44const chokidar = require ( 'chokidar' ) ;
55const fs = require ( 'fs-extra' ) ;
66const escapeRegex = require ( 'escape-string-regexp' ) ;
7- const debug = require ( 'debug' ) ( 'ember-cli-typescript:tsc:trace' ) ;
7+ const path = require ( 'path' ) ;
8+ const glob = require ( 'glob' ) ;
9+
10+ const trace = require ( 'debug' ) ( 'ember-cli-typescript:tsc:trace' ) ;
11+ const debug = require ( 'debug' ) ( 'ember-cli-typescript:watcher' ) ;
812
913module . exports = function compile ( project , tsOptions , callbacks ) {
1014 // Ensure the output directory is created even if no files are generated
@@ -14,8 +18,8 @@ module.exports = function compile(project, tsOptions, callbacks) {
1418 rootDir : project . root ,
1519 allowJs : false ,
1620 noEmit : false ,
17- diagnostics : debug . enabled ,
18- extendedDiagnostics : debug . enabled
21+ diagnostics : trace . enabled ,
22+ extendedDiagnostics : trace . enabled
1923 } , tsOptions ) ;
2024
2125 let ts = project . require ( 'typescript' ) ;
@@ -30,7 +34,7 @@ function createWatchCompilerHost(ts, options, project, callbacks) {
3034 let host = ts . createWatchCompilerHost (
3135 configPath ,
3236 options ,
33- buildWatchHooks ( project , ts . sys , callbacks ) ,
37+ buildWatchHooks ( project , ts , callbacks ) ,
3438 createProgram ,
3539 diagnosticCallback ( callbacks . reportDiagnostic ) ,
3640 diagnosticCallback ( callbacks . reportWatchStatus )
@@ -46,8 +50,8 @@ function createWatchCompilerHost(ts, options, project, callbacks) {
4650 }
4751 } ;
4852
49- if ( debug . enabled ) {
50- host . trace = str => debug ( str . trim ( ) ) ;
53+ if ( trace . enabled ) {
54+ host . trace = str => trace ( str . trim ( ) ) ;
5155 }
5256
5357 return host ;
@@ -64,28 +68,53 @@ function diagnosticCallback(callback) {
6468 }
6569}
6670
67- function buildWatchHooks ( project , sys , callbacks ) {
68- let root = escapeRegex ( project . root ) ;
69- let sep = `[/\\\\]` ;
70- let patterns = [ '\\..*?' , 'dist' , 'node_modules' , 'tmp' ] ;
71- let ignored = new RegExp ( `^${ root } ${ sep } (${ patterns . join ( '|' ) } )${ sep } ` ) ;
71+ function buildWatchHooks ( project , ts , callbacks ) {
72+ let ignorePatterns = [ '\\..*?' , 'dist' , 'tmp' , 'node_modules' ] ;
7273
73- return Object . assign ( { } , sys , {
74+ return Object . assign ( { } , ts . sys , {
7475 watchFile : null ,
75- watchDirectory ( dir , callback ) {
76- if ( ! fs . existsSync ( dir ) ) return ;
77-
76+ watchDirectory ( rawDir , callback ) {
77+ if ( ! fs . existsSync ( rawDir ) ) {
78+ debug ( `skipping watch for nonexistent directory %s` , rawDir ) ;
79+ return ;
80+ }
81+
82+ let dir = getCanonicalCapitalization ( path . resolve ( rawDir ) ) ;
83+ let ignored = buildIgnoreRegex ( dir , ignorePatterns ) ;
7884 let watcher = chokidar . watch ( dir , { ignored, ignoreInitial : true } ) ;
85+ debug ( `watching directory %s %o` , dir , { ignored } ) ;
7986
80- watcher . on ( 'all' , ( type , path ) => {
81- callback ( path ) ;
87+ watcher . on ( 'all' , ( type , rawPath ) => {
88+ let resolvedPath = path . resolve ( rawPath ) ;
8289
83- if ( path . endsWith ( '.ts' ) && callbacks . watchedFileChanged ) {
90+ debug ( `%s: %s (for directory watch on %s)` , type , resolvedPath , dir ) ;
91+ callback ( resolvedPath ) ;
92+
93+ if ( resolvedPath . endsWith ( '.ts' ) && callbacks . watchedFileChanged ) {
8494 callbacks . watchedFileChanged ( ) ;
8595 }
8696 } ) ;
8797
88- return watcher ;
98+ return {
99+ close ( ) {
100+ debug ( 'closing watcher for %s' , dir ) ;
101+ watcher . close ( ) ;
102+ }
103+ } ;
89104 }
90105 } ) ;
91106}
107+
108+ function buildIgnoreRegex ( rootDir , patterns ) {
109+ let base = escapeRegex ( rootDir ) ;
110+ let 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 ] ;
120+ }
0 commit comments