@@ -18,26 +18,41 @@ import {
1818} from 'vscode' ;
1919import { ExtensionApi } from '../../backend' ;
2020import { DiagnosticReport } from '../../backend/types' ;
21+ import { SidebarContainer } from '../sidebar_container' ;
2122
2223export class ReportTreeItem extends TreeItem {
2324 parent : ReportTreeItem | undefined ;
2425
2526 constructor (
2627 public readonly _id : string ,
27- public readonly label : string | TreeItemLabel ,
28- public readonly iconPath : ThemeIcon ,
29- public readonly children ?: ReportTreeItem [ ] | undefined
28+ label : string | TreeItemLabel ,
29+ iconPath : ThemeIcon ,
30+ public children ?: ReportTreeItem [ ]
3031 ) {
31- super ( label , children ?. length ? TreeItemCollapsibleState . Collapsed : TreeItemCollapsibleState . None ) ;
32+ super ( label , ( children ?. length ) ?
33+ TreeItemCollapsibleState . Collapsed : TreeItemCollapsibleState . None ) ;
3234 this . _id = _id ;
3335 this . label = label ;
34- this . iconPath = this . iconPath ;
36+ this . iconPath = iconPath ;
3537 this . children = children ;
3638
3739 // Set parent for children automatically.
3840 this . children ?. forEach ( c => c . parent = this ) ;
3941 }
4042
43+ setLabelAndIcon ( label ?: string , iconPath ?: ThemeIcon ) {
44+ if ( label ) {
45+ this . label = label ;
46+ }
47+ if ( iconPath ) {
48+ this . iconPath = iconPath ;
49+ }
50+ }
51+
52+ setChildren ( children : ReportTreeItem [ ] | undefined ) {
53+ this . children = children ;
54+ }
55+
4156 // This function can be used to set ID attribute of a tree item and all the children of it based on the parent id.
4257 setId ( ) {
4358 this . id = `${ this . parent ?. id ?? 'root' } _${ this . _id } ` ;
@@ -55,6 +70,12 @@ export class ReportTreeItem extends TreeItem {
5570 }
5671 }
5772
73+ collapse ( ) {
74+ if ( this . collapsibleState === TreeItemCollapsibleState . Expanded ) {
75+ this . collapsibleState = TreeItemCollapsibleState . Collapsed ;
76+ }
77+ }
78+
5879 traverse ( cb : ( item : ReportTreeItem ) => void ) {
5980 cb ( this ) ;
6081 this . children ?. forEach ( c => c . traverse ( cb ) ) ;
@@ -84,16 +105,26 @@ const severityOrder: { [key: string]: number } = {
84105
85106export class ReportsView implements TreeDataProvider < ReportTreeItem > {
86107 protected currentFile ?: Uri ;
108+ protected isDirty : boolean = false ;
87109 protected currentEntryList ?: DiagnosticReport [ ] ;
88110
89111 protected tree ?: TreeView < ReportTreeItem > ;
90112 // Contains [fullpath => item] entries
91113 private treeItems : Map < string , ReportTreeItem > = new Map ( ) ;
92114 private selectedTreeItems : ReportTreeItem [ ] = [ ] ;
115+ private dynamicTreeItems : Map < string , ReportTreeItem > = new Map ( ) ;
116+ private rootItems : ReportTreeItem [ ] = [ ] ;
93117
94118 constructor ( ctx : ExtensionContext ) {
95119 ctx . subscriptions . push ( this . _onDidChangeTreeData = new EventEmitter ( ) ) ;
96- window . onDidChangeActiveTextEditor ( this . refreshBugList , this , ctx . subscriptions ) ;
120+ window . onDidChangeActiveTextEditor ( editor => {
121+ // event is called twice. Ignore deactivation of the previous editor.
122+ if ( editor === undefined ) {
123+ return ;
124+ }
125+ // this.refreshBugList();
126+ this . updateStatus ( ) ;
127+ } , this , ctx . subscriptions ) ;
97128
98129 ExtensionApi . diagnostics . diagnosticsUpdated ( ( ) => {
99130 // FIXME: fired twice when a file is opened freshly.
@@ -113,6 +144,23 @@ export class ReportsView implements TreeDataProvider<ReportTreeItem> {
113144 ) ) ;
114145
115146 this . init ( ) ;
147+ this . updateStatus ( ) ;
148+ }
149+
150+ public addDynamicNode ( id : string , node : ReportTreeItem ) {
151+ this . dynamicTreeItems . set ( id , node ) ;
152+ }
153+
154+ public getNodeById ( id : string ) : ReportTreeItem | undefined {
155+ return this . dynamicTreeItems . get ( id ) ;
156+ }
157+
158+ public getAllNodes ( ) : Map < string , ReportTreeItem > {
159+ return this . treeItems ;
160+ }
161+
162+ public refreshNode ( ) {
163+ this . _onDidChangeTreeData . fire ( ) ;
116164 }
117165
118166 protected init ( ) {
@@ -121,6 +169,12 @@ export class ReportsView implements TreeDataProvider<ReportTreeItem> {
121169 this . tree ?. onDidChangeSelection ( ( item : TreeViewSelectionChangeEvent < ReportTreeItem > ) => {
122170 this . selectedTreeItems = item . selection ;
123171 } ) ;
172+
173+ workspace . onDidChangeTextDocument ( event => {
174+ if ( event ?. document === window . activeTextEditor ?. document ) {
175+ this . updateStatus ( ) ;
176+ }
177+ } ) ;
124178 }
125179
126180 private _onDidChangeTreeData : EventEmitter < void > ;
@@ -159,6 +213,24 @@ export class ReportsView implements TreeDataProvider<ReportTreeItem> {
159213 this . _onDidChangeTreeData . fire ( ) ;
160214 }
161215
216+ updateStatus ( ) {
217+ if ( window ?. activeTextEditor ?. document ?. isDirty ) {
218+ const statusNode = SidebarContainer . reportsView . getNodeById ( 'statusItem' ) ;
219+ if ( statusNode ) {
220+ statusNode ?. setLabelAndIcon ( 'Outdated (file is modified in the editor)' , new ThemeIcon ( 'edit' ) ) ;
221+ if ( statusNode . children ) {
222+ statusNode . children . forEach ( child => {
223+ child . setLabelAndIcon ( undefined , new ThemeIcon ( 'edit' ) ) ;
224+ } ) ;
225+ }
226+ }
227+ } else {
228+ const executorBridge = ExtensionApi . executorBridge ;
229+ executorBridge . getFileAnalysisStatus ( ) ;
230+ }
231+ this . _onDidChangeTreeData . fire ( ) ;
232+ }
233+
162234 revealSelectedItems ( ) {
163235 const selectedIds = new Set ( this . selectedTreeItems . map ( item => item . id ) ) ;
164236 this . treeItems . forEach ( root => root . traverse ( item => {
@@ -301,7 +373,10 @@ export class ReportsView implements TreeDataProvider<ReportTreeItem> {
301373 // Get root level items.
302374 getRootItems ( ) : ReportTreeItem [ ] | undefined {
303375 if ( ! this . currentEntryList ?. length ) {
304- return [ new ReportTreeItem ( 'noReportsFound' , 'No reports found' , new ThemeIcon ( 'pass' ) ) ] ;
376+ const statusNode = SidebarContainer . reportsView . getNodeById ( 'statusItem' ) ;
377+ statusNode ?. setLabelAndIcon ( 'Not in compilation database' ,
378+ new ThemeIcon ( 'question' , new ThemeColor ( 'charts.orange' ) ) ) ;
379+ return statusNode ? [ statusNode ] : undefined ;
305380 }
306381
307382 const severityItems : { [ key : string ] : TreeDiagnosticReport [ ] } = { } ;
@@ -315,6 +390,13 @@ export class ReportsView implements TreeDataProvider<ReportTreeItem> {
315390
316391 const rootItems : ReportTreeItem [ ] = [ ] ;
317392
393+ let status = SidebarContainer . reportsView . getNodeById ( 'statusItem' ) ;
394+ if ( ! status ) {
395+ status = new ReportTreeItem ( 'statusItem' , 'Status' , new ThemeIcon ( 'warning' ) ) ;
396+ SidebarContainer . reportsView . addDynamicNode ( 'statusItem' , status ) ;
397+ }
398+ rootItems . push ( status ) ;
399+
318400 rootItems . push ( ...Object . entries ( severityItems )
319401 . sort ( ( [ severityA ] : [ string , TreeDiagnosticReport [ ] ] , [ severityB ] : [ string , TreeDiagnosticReport [ ] ] ) =>
320402 severityOrder [ severityA ] - severityOrder [ severityB ] )
0 commit comments