@@ -382,6 +382,8 @@ export class ProjectPanelProvider implements vscode.TreeDataProvider<TreeNode> {
382
382
}
383
383
384
384
observeTasks ( ctx : WorkspaceContext ) {
385
+ this . disposables . push ( new TaskPoller ( ( ) => this . didChangeTreeDataEmitter . fire ( ) ) ) ;
386
+
385
387
this . disposables . push (
386
388
vscode . tasks . onDidStartTask ( e => {
387
389
const taskId = e . execution . task . detail ?? e . execution . task . name ;
@@ -578,7 +580,8 @@ export class ProjectPanelProvider implements vscode.TreeDataProvider<TreeNode> {
578
580
// Plugin tasks are shown under the Commands header
579
581
. filter (
580
582
task =>
581
- task . definition . cwd === folderContext . folder . fsPath &&
583
+ ( ! task . definition . cwd ||
584
+ task . definition . cwd === folderContext . folder . fsPath ) &&
582
585
task . source !== "swift-plugin"
583
586
)
584
587
. map (
@@ -622,3 +625,53 @@ export class ProjectPanelProvider implements vscode.TreeDataProvider<TreeNode> {
622
625
. sort ( ( a , b ) => a . name . localeCompare ( b . name ) ) ;
623
626
}
624
627
}
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