11import * as vscode from 'vscode' ;
22import * as models from '../models' ;
33
4+ const namespaceSeparator = ':' ;
5+
46export class Tasks implements vscode . TreeDataProvider < TaskTreeItem > {
57 private _onDidChangeTreeData : vscode . EventEmitter < TaskTreeItem | undefined > = new vscode . EventEmitter < TaskTreeItem | undefined > ( ) ;
68 readonly onDidChangeTreeData : vscode . Event < TaskTreeItem | undefined > = this . _onDidChangeTreeData . event ;
@@ -10,12 +12,34 @@ export class Tasks implements vscode.TreeDataProvider<TaskTreeItem> {
1012 return element ;
1113 }
1214
13- getChildren ( element ?: TaskTreeItem ) : Thenable < TaskTreeItem [ ] > {
15+ getChildren ( parent ?: TaskTreeItem ) : Thenable < TaskTreeItem [ ] > {
1416 var taskTreeItems : TaskTreeItem [ ] = [ ] ;
17+ var namespaceTreeItems : TaskTreeItem [ ] = [ ] ;
18+
19+ // Loop over each task
1520 this . _taskfile ?. tasks . forEach ( task => {
16- taskTreeItems . push ( new TaskTreeItem ( task , vscode . TreeItemCollapsibleState . None ) ) ;
21+
22+ // Split the task's name into a namespace and label
23+ var namespace = task . name . substring ( 0 , task . name . lastIndexOf ( namespaceSeparator ) ) ;
24+ var taskLabel = task . name . substring ( task . name . lastIndexOf ( namespaceSeparator ) + 1 , task . name . length ) ;
25+
26+ // If the task's namespace is the same as the parent's namespace
27+ // add the task to the tree
28+ if ( ( parent && parent . namespace === namespace ) || ( ! parent && namespace === "" ) ) {
29+ taskTreeItems . push ( new TaskTreeItem ( taskLabel , namespace , task , vscode . TreeItemCollapsibleState . None ) ) ;
30+ return ;
31+ }
32+
33+ // If the namespace is a direct child of the parent namespace
34+ // and the namespace doesn't already exist in the tree
35+ // add the namespace to the tree
36+ if ( ! namespaceExistsInTree ( namespaceTreeItems , namespace ) && namespaceIsDirectChild ( namespace , parent ?. namespace ) ) {
37+ let namespaceLabel = trimNamespacePrefix ( namespace , parent ?. namespace ) ;
38+ namespaceTreeItems . push ( new TaskTreeItem ( namespaceLabel , namespace , undefined , vscode . TreeItemCollapsibleState . Collapsed ) ) ;
39+ return ;
40+ }
1741 } ) ;
18- return Promise . resolve ( taskTreeItems ) ;
42+ return Promise . resolve ( namespaceTreeItems . concat ( taskTreeItems ) ) ;
1943 }
2044
2145 refresh ( taskfile ?: models . Taskfile ) : void {
@@ -24,15 +48,36 @@ export class Tasks implements vscode.TreeDataProvider<TaskTreeItem> {
2448 }
2549}
2650
51+ function namespaceExistsInTree ( tree : TaskTreeItem [ ] , namespace : string ) {
52+ return tree . find ( item => item . namespace === namespace ) !== undefined ;
53+ }
54+
55+ function namespaceIsDirectChild ( namespace : string , parentNamespace : string = "" ) {
56+ return namespace . startsWith ( parentNamespace ) && ! trimNamespacePrefix ( namespace , parentNamespace ) . includes ( namespaceSeparator ) ;
57+ }
58+
59+ function trimNamespacePrefix ( str : string , prefix ?: string ) {
60+ if ( ! prefix ) {
61+ return str ;
62+ }
63+ if ( str . startsWith ( prefix ) ) {
64+ return str . substring ( prefix . length + 1 ) ;
65+ }
66+ return str ;
67+ }
68+
2769class TaskTreeItem extends vscode . TreeItem {
2870 constructor (
29- private task : models . Task ,
71+ readonly label : string ,
72+ readonly namespace : string ,
73+ readonly task : models . Task | undefined ,
3074 public readonly collapsibleState : vscode . TreeItemCollapsibleState
3175 ) {
32- super ( task . name , collapsibleState ) ;
33- this . tooltip = `${ this . task . desc } ` ;
34- this . description = this . task . desc ;
35- if ( this . task . up_to_date ) {
76+ super ( label , collapsibleState ) ;
77+ this . description = this . task ?. desc ;
78+ if ( ! this . task ) {
79+ this . iconPath = new vscode . ThemeIcon ( 'symbol-namespace' , new vscode . ThemeColor ( 'vscodetask.namespace' ) ) ;
80+ } else if ( this . task . up_to_date ) {
3681 this . iconPath = new vscode . ThemeIcon ( 'debug-breakpoint-log-unverified' , new vscode . ThemeColor ( 'vscodetask.upToDate' ) ) ;
3782 } else {
3883 this . iconPath = new vscode . ThemeIcon ( 'debug-breakpoint-data-unverified' , new vscode . ThemeColor ( 'vscodetask.outOfDate' ) ) ;
0 commit comments