@@ -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,22 +105,28 @@ 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 ( ) ;
93116
94117 constructor ( ctx : ExtensionContext ) {
95118 ctx . subscriptions . push ( this . _onDidChangeTreeData = new EventEmitter ( ) ) ;
96119 window . onDidChangeActiveTextEditor ( editor => {
97- // this event is called twice by vscode . Ignore deactivation of the old editor.
98- if ( ! editor ) {
120+ // event is called twice. Ignore deactivation of the previous editor.
121+ if ( editor === undefined ) {
99122 return ;
100123 }
101124
102- this . refreshBugList ( ) ;
125+ if ( editor . document . uri . scheme !== 'file' ) {
126+ return ;
127+ }
128+
129+ this . updateStatus ( ) ;
103130 } , this , ctx . subscriptions ) ;
104131
105132 ExtensionApi . diagnostics . diagnosticsUpdated ( ( ) => {
@@ -120,6 +147,23 @@ export class ReportsView implements TreeDataProvider<ReportTreeItem> {
120147 ) ) ;
121148
122149 this . init ( ) ;
150+ this . updateStatus ( ) ;
151+ }
152+
153+ public addDynamicNode ( id : string , node : ReportTreeItem ) {
154+ this . dynamicTreeItems . set ( id , node ) ;
155+ }
156+
157+ public getNodeById ( id : string ) : ReportTreeItem | undefined {
158+ return this . dynamicTreeItems . get ( id ) ;
159+ }
160+
161+ public getAllNodes ( ) : Map < string , ReportTreeItem > {
162+ return this . treeItems ;
163+ }
164+
165+ public refreshNode ( ) {
166+ this . _onDidChangeTreeData . fire ( ) ;
123167 }
124168
125169 protected init ( ) {
@@ -128,6 +172,15 @@ export class ReportsView implements TreeDataProvider<ReportTreeItem> {
128172 this . tree ?. onDidChangeSelection ( ( item : TreeViewSelectionChangeEvent < ReportTreeItem > ) => {
129173 this . selectedTreeItems = item . selection ;
130174 } ) ;
175+
176+ workspace . onDidChangeTextDocument ( event => {
177+ if ( event . document . uri . scheme !== 'file' ) {
178+ return ;
179+ }
180+ if ( event ?. document === window . activeTextEditor ?. document ) {
181+ this . updateStatus ( ) ;
182+ }
183+ } ) ;
131184 }
132185
133186 private _onDidChangeTreeData : EventEmitter < void > ;
@@ -166,6 +219,24 @@ export class ReportsView implements TreeDataProvider<ReportTreeItem> {
166219 this . _onDidChangeTreeData . fire ( ) ;
167220 }
168221
222+ updateStatus ( ) {
223+ if ( window ?. activeTextEditor ?. document ?. isDirty ) {
224+ const statusNode = SidebarContainer . reportsView . getNodeById ( 'statusItem' ) ;
225+ if ( statusNode ) {
226+ statusNode ?. setLabelAndIcon ( 'Outdated (file is modified in the editor)' , new ThemeIcon ( 'edit' ) ) ;
227+ if ( statusNode . children ) {
228+ statusNode . children . forEach ( child => {
229+ child . setLabelAndIcon ( undefined , new ThemeIcon ( 'edit' ) ) ;
230+ } ) ;
231+ }
232+ }
233+ } else {
234+ const executorBridge = ExtensionApi . executorBridge ;
235+ executorBridge . getFileAnalysisStatus ( ) ;
236+ }
237+ this . _onDidChangeTreeData . fire ( ) ;
238+ }
239+
169240 revealSelectedItems ( ) {
170241 const selectedIds = new Set ( this . selectedTreeItems . map ( item => item . id ) ) ;
171242 this . treeItems . forEach ( root => root . traverse ( item => {
@@ -308,7 +379,10 @@ export class ReportsView implements TreeDataProvider<ReportTreeItem> {
308379 // Get root level items.
309380 getRootItems ( ) : ReportTreeItem [ ] | undefined {
310381 if ( ! this . currentEntryList ?. length ) {
311- return [ new ReportTreeItem ( 'noReportsFound' , 'No reports found' , new ThemeIcon ( 'pass' ) ) ] ;
382+ const statusNode = SidebarContainer . reportsView . getNodeById ( 'statusItem' ) ;
383+ statusNode ?. setLabelAndIcon ( 'Not in compilation database' ,
384+ new ThemeIcon ( 'question' , new ThemeColor ( 'charts.orange' ) ) ) ;
385+ return statusNode ? [ statusNode ] : undefined ;
312386 }
313387
314388 const severityItems : { [ key : string ] : TreeDiagnosticReport [ ] } = { } ;
@@ -322,6 +396,13 @@ export class ReportsView implements TreeDataProvider<ReportTreeItem> {
322396
323397 const rootItems : ReportTreeItem [ ] = [ ] ;
324398
399+ let status = SidebarContainer . reportsView . getNodeById ( 'statusItem' ) ;
400+ if ( ! status ) {
401+ status = new ReportTreeItem ( 'statusItem' , 'Status' , new ThemeIcon ( 'warning' ) ) ;
402+ SidebarContainer . reportsView . addDynamicNode ( 'statusItem' , status ) ;
403+ }
404+ rootItems . push ( status ) ;
405+
325406 rootItems . push ( ...Object . entries ( severityItems )
326407 . sort ( ( [ severityA ] : [ string , TreeDiagnosticReport [ ] ] , [ severityB ] : [ string , TreeDiagnosticReport [ ] ] ) =>
327408 severityOrder [ severityA ] - severityOrder [ severityB ] )
0 commit comments