@@ -25,6 +25,7 @@ import { getPlatformConfig, resolveTaskCwd } from "../utilities/tasks";
2525import { SwiftTask , TaskPlatformSpecificConfig } from "../tasks/SwiftTaskProvider" ;
2626import { convertPathToPattern , glob } from "fast-glob" ;
2727import { Version } from "../utilities/version" ;
28+ import { existsSync } from "fs" ;
2829
2930const LOADING_ICON = "loading~spin" ;
3031
@@ -504,6 +505,7 @@ export class ProjectPanelProvider implements vscode.TreeDataProvider<TreeNode> {
504505 private activeTasks : Set < string > = new Set ( ) ;
505506 private lastComputedNodes : TreeNode [ ] = [ ] ;
506507 private buildPluginOutputWatcher ?: vscode . FileSystemWatcher ;
508+ private buildPluginFolderWatcher ?: vscode . Disposable ;
507509
508510 onDidChangeTreeData = this . didChangeTreeDataEmitter . event ;
509511
@@ -611,13 +613,27 @@ export class ProjectPanelProvider implements vscode.TreeDataProvider<TreeNode> {
611613 if ( this . buildPluginOutputWatcher ) {
612614 this . buildPluginOutputWatcher . dispose ( ) ;
613615 }
614- this . buildPluginOutputWatcher = vscode . workspace . createFileSystemWatcher (
615- new vscode . RelativePattern ( folderContext . folder , ".build/plugins/outputs/{*,*/*}" )
616- ) ;
616+ if ( this . buildPluginFolderWatcher ) {
617+ this . buildPluginFolderWatcher . dispose ( ) ;
618+ }
619+
617620 const fire = ( ) => this . didChangeTreeDataEmitter . fire ( ) ;
618- this . buildPluginOutputWatcher . onDidCreate ( fire ) ;
619- this . buildPluginOutputWatcher . onDidDelete ( fire ) ;
620- this . buildPluginOutputWatcher . onDidChange ( fire ) ;
621+ const buildPath = path . join ( folderContext . folder . fsPath , ".build/plugins/outputs" ) ;
622+ this . buildPluginFolderWatcher = watchForFolder (
623+ buildPath ,
624+ ( ) => {
625+ this . buildPluginOutputWatcher = vscode . workspace . createFileSystemWatcher (
626+ new vscode . RelativePattern ( buildPath , "{*,*/*}" )
627+ ) ;
628+ this . buildPluginOutputWatcher . onDidCreate ( fire ) ;
629+ this . buildPluginOutputWatcher . onDidDelete ( fire ) ;
630+ this . buildPluginOutputWatcher . onDidChange ( fire ) ;
631+ } ,
632+ ( ) => {
633+ this . buildPluginOutputWatcher ?. dispose ( ) ;
634+ fire ( ) ;
635+ }
636+ ) ;
621637 }
622638
623639 getTreeItem ( element : TreeNode ) : vscode . TreeItem {
@@ -636,7 +652,6 @@ export class ProjectPanelProvider implements vscode.TreeDataProvider<TreeNode> {
636652 ...this . lastComputedNodes ,
637653 ] ;
638654 }
639-
640655 const nodes = await this . computeChildren ( folderContext , element ) ;
641656
642657 // If we're fetching the root nodes then save them in case we have an error later,
@@ -840,3 +855,35 @@ class TaskPoller implements vscode.Disposable {
840855 }
841856 }
842857}
858+
859+ /**
860+ * Polls for the existence of a folder at the given path every 2.5 seconds.
861+ * Notifies via the provided callbacks when the folder becomes available or is deleted.
862+ */
863+ function watchForFolder (
864+ folderPath : string ,
865+ onAvailable : ( ) => void ,
866+ onDeleted : ( ) => void
867+ ) : vscode . Disposable {
868+ const POLL_INTERVAL = 2500 ;
869+ let folderExists = existsSync ( folderPath ) ;
870+
871+ if ( folderExists ) {
872+ onAvailable ( ) ;
873+ }
874+
875+ const interval = setInterval ( ( ) => {
876+ const nowExists = existsSync ( folderPath ) ;
877+ if ( nowExists && ! folderExists ) {
878+ folderExists = true ;
879+ onAvailable ( ) ;
880+ } else if ( ! nowExists && folderExists ) {
881+ folderExists = false ;
882+ onDeleted ( ) ;
883+ }
884+ } , POLL_INTERVAL ) ;
885+
886+ return {
887+ dispose : ( ) => clearInterval ( interval ) ,
888+ } ;
889+ }
0 commit comments