1
+ import * as vscode from "vscode" ;
2
+ import { CancellationToken , Event , EventEmitter , ProviderResult , TreeView , TreeDataProvider , TreeItem , TreeItemCollapsibleState , commands , ThemeIcon } from "vscode" ;
3
+ import { ExplainNode } from "./nodes" ;
4
+ import { toDoveTreeDecorationProviderUri } from "./doveTreeDecorationProvider" ;
5
+
6
+ /**
7
+ * Icon labels as defined by the API, along with the name of the icon to display.
8
+ * Not surprisingly, the reference link does not provide a complete list of icons.
9
+ * TODO: Add missing icons
10
+ * @see https://www.ibm.com/docs/en/i/7.5?topic=ssw_ibm_i_75/apis/qqqvexpl.html#icon_labels
11
+ * @see https://code.visualstudio.com/api/references/icons-in-labels
12
+ */
13
+ const icons = {
14
+ "Bitmap Merge" : `merge` ,
15
+ "Cache" : `` ,
16
+ "Cache Probe" : `` ,
17
+ "Delete" : `trash` ,
18
+ "Distinct" : `list-flat` ,
19
+ "Dynamic Bitmap" : `symbol-misc` ,
20
+ "Encoded Vector Index" : `symbol-reference` ,
21
+ "Encoded Vector Index, Parallel" : `symbol-reference` ,
22
+ "Final Select" : `selection` ,
23
+ "Hash Grouping" : `group-by-ref-type` ,
24
+ "Hash Join" : `add` ,
25
+ "Hash Scan" : `search` ,
26
+ "Index Grouping" : `group-by-ref-type` ,
27
+ "Index Scan - Key Positioning" : `key` ,
28
+ "Index Scan - Key Positioning, Parallel" : `key` ,
29
+ "Index Scan - Key Selection" : `key` ,
30
+ "Index Scan - Key Selection, Parallel" : `key` ,
31
+ "Insert" : `insert` ,
32
+ "Nested Loop Join" : `add` ,
33
+ "Select" : `selection` ,
34
+ "Skip Sequential Table Scan" : `list-unordered` ,
35
+ "Skip Sequential Table Scan, Parallel" : `list-unordered` ,
36
+ "Sort" : `sort-precedence` ,
37
+ "Sorted List Scan" : `list-ordered` ,
38
+ "Subquery Merge" : `merge` ,
39
+ "Table Probe" : `list-selection` ,
40
+ "Table Scan" : `search` ,
41
+ "Table Scan, Parallel" : `search` ,
42
+ "Temporary Distinct Hash Table" : `new-file` ,
43
+ "Temporary Hash Table" : `new-file` ,
44
+ "Temporary Index" : `new-file` ,
45
+ "Temporary Sorted List" : `list-ordered` ,
46
+ "Temporary Table" : `new-file` ,
47
+ "Union Merge" : `merge` ,
48
+ "User Defined Table Function" : `symbol-function` ,
49
+ "Unknown" : `question` ,
50
+ "Update" : `replace` ,
51
+ "VALUES LIST" : `list-flat` ,
52
+ }
53
+
54
+ type ChangeTreeDataEventType = ExplainTreeItem | undefined | null | void ;
55
+
56
+ export class DoveResultsView implements TreeDataProvider < any > {
57
+ private _onDidChangeTreeData : EventEmitter < ChangeTreeDataEventType > = new EventEmitter < ChangeTreeDataEventType > ( ) ;
58
+ readonly onDidChangeTreeData : Event < ChangeTreeDataEventType > = this . _onDidChangeTreeData . event ;
59
+
60
+ private topNode : ExplainTreeItem ;
61
+
62
+ private treeView : TreeView < ExplainTreeItem > ;
63
+
64
+ constructor ( ) {
65
+ this . treeView = vscode . window . createTreeView ( `vscode-db2i.dove.nodes` , { treeDataProvider : this , showCollapseAll : true } ) ;
66
+ }
67
+
68
+ public getTreeView ( ) : TreeView < ExplainTreeItem > {
69
+ return this . treeView ;
70
+ }
71
+
72
+ setRootNode ( topNode : ExplainNode ) : ExplainTreeItem {
73
+ this . topNode = new ExplainTreeItem ( topNode ) ;
74
+ this . _onDidChangeTreeData . fire ( ) ;
75
+
76
+ // Show tree in the view
77
+ commands . executeCommand ( `setContext` , `vscode-db2i:explaining` , true ) ;
78
+ // Ensure that the tree is positioned such that the first element is visible
79
+ this . treeView . reveal ( this . topNode , { select : false } ) ;
80
+ return this . topNode ;
81
+ }
82
+ getRootNode ( ) : ExplainTreeItem {
83
+ return this . topNode ;
84
+ }
85
+
86
+ getRootExplainNode ( ) : ExplainNode {
87
+ return this . topNode . explainNode ;
88
+ }
89
+
90
+ close ( ) : void {
91
+ commands . executeCommand ( `setContext` , `vscode-db2i:explaining` , false ) ;
92
+ }
93
+
94
+ getTreeItem ( element : ExplainTreeItem ) : ExplainTreeItem | Thenable < ExplainTreeItem > {
95
+ return element ;
96
+ }
97
+
98
+ getChildren ( element ?: ExplainTreeItem ) : ProviderResult < ExplainTreeItem [ ] > {
99
+ if ( element ) {
100
+ return element . getChildren ( ) ;
101
+ } else if ( this . topNode ) {
102
+ return [ this . topNode ] ;
103
+ } else {
104
+ return [ ] ;
105
+ }
106
+ }
107
+
108
+ getParent ?( element : any ) {
109
+ throw new Error ( "Method not implemented." ) ;
110
+ }
111
+
112
+ resolveTreeItem ?( item : TreeItem , element : any , token : CancellationToken ) : ProviderResult < ExplainTreeItem > {
113
+ throw new Error ( "Method not implemented." ) ;
114
+ }
115
+ }
116
+
117
+ export class ExplainTreeItem extends TreeItem {
118
+ explainNode : ExplainNode ;
119
+ private children : ExplainTreeItem [ ] ;
120
+
121
+ constructor ( node : ExplainNode ) {
122
+ super ( node . title , node . childrenNodes > 0 ? TreeItemCollapsibleState . Expanded : TreeItemCollapsibleState . None ) ;
123
+ this . explainNode = node ;
124
+ this . contextValue = `explainTreeItem` ;
125
+
126
+ // If the node is associated with a DB object, display the qualified object name in the description
127
+ if ( node . objectSchema && node . objectName ) {
128
+ this . description = node . objectSchema + `.` + node . objectName ;
129
+ }
130
+
131
+ // TODO: ideally the tooltip would be built using a MarkdownString, but regardless of everything tried, 'Loading...' is always displayed
132
+ this . tooltip = [ node . title , node . tooltipProps . map < string > ( prop => prop . title + `: ` + prop . value ) . join ( `\n` ) , `` ] . join ( `\n` ) ;
133
+ this . resourceUri = toDoveTreeDecorationProviderUri ( node . highlights ) ;
134
+ this . iconPath = new ThemeIcon ( icons [ node . title ] || `server-process` , node . highlights . getPriorityColor ( ) ) ; // `circle-outline`
135
+ }
136
+
137
+ getChildren ( ) : ExplainTreeItem [ ] {
138
+ if ( ! this . children ) {
139
+ this . children = this . explainNode . children . map ( c => new ExplainTreeItem ( c ) ) ;
140
+ }
141
+ return this . children ;
142
+ }
143
+ }
0 commit comments