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