@@ -253,29 +253,19 @@ namespace ts.projectSystem {
253253 entries : FSEntry [ ] ;
254254 }
255255
256- export function isFolder ( s : FSEntry ) : s is Folder {
256+ export function isFolder ( s : FSEntry | undefined ) : s is Folder {
257257 return s && isArray ( ( < Folder > s ) . entries ) ;
258258 }
259259
260- export function isFile ( s : FSEntry ) : s is File {
260+ export function isFile ( s : FSEntry | undefined ) : s is File {
261261 return s && typeof ( < File > s ) . content === "string" ;
262262 }
263263
264- function invokeDirectoryWatcher ( callbacks : DirectoryWatcherCallback [ ] , getRelativeFilePath : ( ) => string ) {
264+ function invokeWatcherCallbacks < T > ( callbacks : T [ ] , invokeCallback : ( cb : T ) => void ) : void {
265265 if ( callbacks ) {
266266 const cbs = callbacks . slice ( ) ;
267267 for ( const cb of cbs ) {
268- const fileName = getRelativeFilePath ( ) ;
269- cb ( fileName ) ;
270- }
271- }
272- }
273-
274- function invokeFileWatcher ( callbacks : FileWatcherCallback [ ] , fileName : string , eventId : FileWatcherEventKind ) {
275- if ( callbacks ) {
276- const cbs = callbacks . slice ( ) ;
277- for ( const cb of cbs ) {
278- cb ( fileName , eventId ) ;
268+ invokeCallback ( cb ) ;
279269 }
280270 }
281271 }
@@ -380,7 +370,7 @@ namespace ts.projectSystem {
380370
381371 private readonly output : string [ ] = [ ] ;
382372
383- private fs : Map < FSEntry > = createMap < FSEntry > ( ) ;
373+ private fs = createMap < FSEntry > ( ) ;
384374 private getCanonicalFileName : ( s : string ) => string ;
385375 private toPath : ( f : string ) => Path ;
386376 private timeoutCallbacks = new Callbacks ( ) ;
@@ -510,8 +500,12 @@ namespace ts.projectSystem {
510500 }
511501 else {
512502 Debug . assert ( fileOrFolder . entries . length === 0 ) ;
513- invokeDirectoryWatcher ( this . watchedDirectories . get ( fileOrFolder . path ) , ( ) => this . getRelativePathToDirectory ( fileOrFolder . fullPath , fileOrFolder . fullPath ) ) ;
514- invokeDirectoryWatcher ( this . watchedDirectoriesRecursive . get ( fileOrFolder . path ) , ( ) => this . getRelativePathToDirectory ( fileOrFolder . fullPath , fileOrFolder . fullPath ) ) ;
503+ const relativePath = this . getRelativePathToDirectory ( fileOrFolder . fullPath , fileOrFolder . fullPath ) ;
504+ // Invoke directory and recursive directory watcher for the folder
505+ // Here we arent invoking recursive directory watchers for the base folders
506+ // since that is something we would want to do for both file as well as folder we are deleting
507+ invokeWatcherCallbacks ( this . watchedDirectories . get ( fileOrFolder . path ) , cb => cb ( relativePath ) ) ;
508+ invokeWatcherCallbacks ( this . watchedDirectoriesRecursive . get ( fileOrFolder . path ) , cb => cb ( relativePath ) ) ;
515509 }
516510
517511 if ( basePath !== fileOrFolder . path ) {
@@ -524,22 +518,31 @@ namespace ts.projectSystem {
524518 }
525519 }
526520
527- private invokeFileWatcher ( fileFullPath : string , eventId : FileWatcherEventKind ) {
521+ private invokeFileWatcher ( fileFullPath : string , eventKind : FileWatcherEventKind ) {
528522 const callbacks = this . watchedFiles . get ( this . toPath ( fileFullPath ) ) ;
529- invokeFileWatcher ( callbacks , getBaseFileName ( fileFullPath ) , eventId ) ;
523+ const fileName = getBaseFileName ( fileFullPath ) ;
524+ invokeWatcherCallbacks ( callbacks , cb => cb ( fileName , eventKind ) ) ;
530525 }
531526
532527 private getRelativePathToDirectory ( directoryFullPath : string , fileFullPath : string ) {
533528 return getRelativePathToDirectoryOrUrl ( directoryFullPath , fileFullPath , this . currentDirectory , this . getCanonicalFileName , /*isAbsolutePathAnUrl*/ false ) ;
534529 }
535530
531+ /**
532+ * This will call the directory watcher for the foldeFullPath and recursive directory watchers for this and base folders
533+ */
536534 private invokeDirectoryWatcher ( folderFullPath : string , fileName : string ) {
537- invokeDirectoryWatcher ( this . watchedDirectories . get ( this . toPath ( folderFullPath ) ) , ( ) => this . getRelativePathToDirectory ( folderFullPath , fileName ) ) ;
535+ const relativePath = this . getRelativePathToDirectory ( folderFullPath , fileName ) ;
536+ invokeWatcherCallbacks ( this . watchedDirectories . get ( this . toPath ( folderFullPath ) ) , cb => cb ( relativePath ) ) ;
538537 this . invokeRecursiveDirectoryWatcher ( folderFullPath , fileName ) ;
539538 }
540539
540+ /**
541+ * This will call the recursive directory watcher for this directory as well as all the base directories
542+ */
541543 private invokeRecursiveDirectoryWatcher ( fullPath : string , fileName : string ) {
542- invokeDirectoryWatcher ( this . watchedDirectoriesRecursive . get ( this . toPath ( fullPath ) ) , ( ) => this . getRelativePathToDirectory ( fullPath , fileName ) ) ;
544+ const relativePath = this . getRelativePathToDirectory ( fullPath , fileName ) ;
545+ invokeWatcherCallbacks ( this . watchedDirectoriesRecursive . get ( this . toPath ( fullPath ) ) , cb => cb ( relativePath ) ) ;
543546 const basePath = getDirectoryPath ( fullPath ) ;
544547 if ( this . getCanonicalFileName ( fullPath ) !== this . getCanonicalFileName ( basePath ) ) {
545548 this . invokeRecursiveDirectoryWatcher ( basePath , fileName ) ;
@@ -885,6 +888,45 @@ namespace ts.projectSystem {
885888 checkWatchedDirectories ( host , [ getDirectoryPath ( configFile . path ) ] , /*recursive*/ true ) ;
886889 } ) ;
887890
891+ it ( "create configured project with the file list" , ( ) => {
892+ const configFile : FileOrFolder = {
893+ path : "/a/b/tsconfig.json" ,
894+ content : `
895+ {
896+ "compilerOptions": {},
897+ "include": ["*.ts"]
898+ }`
899+ } ;
900+ const file1 : FileOrFolder = {
901+ path : "/a/b/f1.ts" ,
902+ content : "let x = 1"
903+ } ;
904+ const file2 : FileOrFolder = {
905+ path : "/a/b/f2.ts" ,
906+ content : "let y = 1"
907+ } ;
908+ const file3 : FileOrFolder = {
909+ path : "/a/b/c/f3.ts" ,
910+ content : "let z = 1"
911+ } ;
912+
913+ const host = createServerHost ( [ configFile , libFile , file1 , file2 , file3 ] ) ;
914+ const projectService = createProjectService ( host ) ;
915+ const { configFileName, configFileErrors } = projectService . openClientFile ( file1 . path ) ;
916+
917+ assert ( configFileName , "should find config file" ) ;
918+ assert . isTrue ( ! configFileErrors , `expect no errors in config file, got ${ JSON . stringify ( configFileErrors ) } ` ) ;
919+ checkNumberOfInferredProjects ( projectService , 0 ) ;
920+ checkNumberOfConfiguredProjects ( projectService , 1 ) ;
921+
922+ const project = configuredProjectAt ( projectService , 0 ) ;
923+ checkProjectActualFiles ( project , [ file1 . path , libFile . path , file2 . path , configFile . path ] ) ;
924+ checkProjectRootFiles ( project , [ file1 . path , file2 . path ] ) ;
925+ // watching all files except one that was open
926+ checkWatchedFiles ( host , [ configFile . path , file2 . path , libFile . path ] ) ;
927+ checkWatchedDirectories ( host , [ getDirectoryPath ( configFile . path ) ] , /*recursive*/ false ) ;
928+ } ) ;
929+
888930 it ( "add and then remove a config file in a folder with loose files" , ( ) => {
889931 const configFile : FileOrFolder = {
890932 path : "/a/b/tsconfig.json" ,
0 commit comments