@@ -382,6 +382,8 @@ export class ProjectPanelProvider implements vscode.TreeDataProvider<TreeNode> {
382382 }
383383
384384 observeTasks ( ctx : WorkspaceContext ) {
385+ this . disposables . push ( new TaskPoller ( ( ) => this . didChangeTreeDataEmitter . fire ( ) ) ) ;
386+
385387 this . disposables . push (
386388 vscode . tasks . onDidStartTask ( e => {
387389 const taskId = e . execution . task . detail ?? e . execution . task . name ;
@@ -578,7 +580,8 @@ export class ProjectPanelProvider implements vscode.TreeDataProvider<TreeNode> {
578580 // Plugin tasks are shown under the Commands header
579581 . filter (
580582 task =>
581- task . definition . cwd === folderContext . folder . fsPath &&
583+ ( ! task . definition . cwd ||
584+ task . definition . cwd === folderContext . folder . fsPath ) &&
582585 task . source !== "swift-plugin"
583586 )
584587 . map (
@@ -622,3 +625,53 @@ export class ProjectPanelProvider implements vscode.TreeDataProvider<TreeNode> {
622625 . sort ( ( a , b ) => a . name . localeCompare ( b . name ) ) ;
623626 }
624627}
628+
629+ /*
630+ * A simple task poller that checks for changes in the tasks every 5 seconds.
631+ * This is a workaround for the lack of an event when tasks are added or removed.
632+ */
633+ class TaskPoller implements vscode . Disposable {
634+ private previousTasks : vscode . Task [ ] = [ ] ;
635+ private timeout ?: NodeJS . Timeout ;
636+ private static POLL_INTERVAL = 5000 ;
637+
638+ constructor ( private onTasksChanged : ( ) => void ) {
639+ this . pollTasks ( ) ;
640+ }
641+
642+ private async pollTasks ( ) {
643+ try {
644+ const tasks = await vscode . tasks . fetchTasks ( ) ;
645+ const tasksChanged =
646+ tasks . length !== this . previousTasks . length ||
647+ tasks . some ( ( task , i ) => {
648+ const prev = this . previousTasks [ i ] ;
649+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
650+ const c1 = ( task . execution as any ) . command ;
651+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
652+ const c2 = ( prev . execution as any ) . command ;
653+ return (
654+ ! prev ||
655+ task . name !== prev . name ||
656+ task . source !== prev . source ||
657+ task . definition . cwd !== prev . definition . cwd ||
658+ task . detail !== prev . detail ||
659+ c1 !== c2
660+ ) ;
661+ } ) ;
662+ if ( tasksChanged ) {
663+ this . previousTasks = tasks ;
664+ this . onTasksChanged ( ) ;
665+ }
666+ } catch {
667+ // ignore errors
668+ }
669+ this . timeout = setTimeout ( ( ) => this . pollTasks ( ) , TaskPoller . POLL_INTERVAL ) ;
670+ }
671+
672+ dispose ( ) {
673+ if ( this . timeout ) {
674+ clearTimeout ( this . timeout ) ;
675+ }
676+ }
677+ }
0 commit comments