-
Notifications
You must be signed in to change notification settings - Fork 11
Add analysis status info #163
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -168,6 +168,7 @@ export class NotificationHandler { | |
| }); | ||
| this.activeNotifications.delete(process.commandLine); | ||
|
|
||
| SidebarContainer.reportsView.updateStatus(); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this one is the cause of the issues? this one can spawn a new process if the status is not up-to-date when the process is finished - including when status processes are finished. |
||
| break; | ||
| } | ||
| case ProcessStatusType.warning: { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,26 +18,41 @@ import { | |
| } from 'vscode'; | ||
| import { ExtensionApi } from '../../backend'; | ||
| import { DiagnosticReport } from '../../backend/types'; | ||
| import { SidebarContainer } from '../sidebar_container'; | ||
|
|
||
| export class ReportTreeItem extends TreeItem { | ||
| parent: ReportTreeItem | undefined; | ||
|
|
||
| constructor( | ||
| public readonly _id: string, | ||
| public readonly label: string | TreeItemLabel, | ||
| public readonly iconPath: ThemeIcon, | ||
| public readonly children?: ReportTreeItem[] | undefined | ||
| label: string | TreeItemLabel, | ||
| iconPath: ThemeIcon, | ||
| public children?: ReportTreeItem[] | ||
| ) { | ||
| super(label, children?.length ? TreeItemCollapsibleState.Collapsed : TreeItemCollapsibleState.None); | ||
| super(label, (children?.length) ? | ||
| TreeItemCollapsibleState.Collapsed : TreeItemCollapsibleState.None); | ||
| this._id = _id; | ||
| this.label = label; | ||
| this.iconPath = this.iconPath; | ||
| this.iconPath = iconPath; | ||
| this.children = children; | ||
|
|
||
| // Set parent for children automatically. | ||
| this.children?.forEach(c => c.parent = this); | ||
| } | ||
|
|
||
| setLabelAndIcon(label?: string, iconPath?: ThemeIcon) { | ||
| if (label) { | ||
| this.label = label; | ||
| } | ||
| if (iconPath) { | ||
| this.iconPath = iconPath; | ||
| } | ||
| } | ||
|
|
||
| setChildren(children: ReportTreeItem[] | undefined) { | ||
| this.children = children; | ||
| } | ||
|
|
||
| // This function can be used to set ID attribute of a tree item and all the children of it based on the parent id. | ||
| setId() { | ||
| this.id = `${this.parent?.id ?? 'root'}_${this._id}`; | ||
|
|
@@ -55,6 +70,12 @@ export class ReportTreeItem extends TreeItem { | |
| } | ||
| } | ||
|
|
||
| collapse() { | ||
| if (this.collapsibleState === TreeItemCollapsibleState.Expanded) { | ||
| this.collapsibleState = TreeItemCollapsibleState.Collapsed; | ||
| } | ||
| } | ||
|
|
||
| traverse(cb: (item: ReportTreeItem) => void) { | ||
| cb(this); | ||
| this.children?.forEach(c => c.traverse(cb)); | ||
|
|
@@ -84,16 +105,26 @@ const severityOrder: { [key: string]: number } = { | |
|
|
||
| export class ReportsView implements TreeDataProvider<ReportTreeItem> { | ||
| protected currentFile?: Uri; | ||
| protected isDirty: boolean = false; | ||
| protected currentEntryList?: DiagnosticReport[]; | ||
|
|
||
| protected tree?: TreeView<ReportTreeItem>; | ||
| // Contains [fullpath => item] entries | ||
| private treeItems: Map<string, ReportTreeItem> = new Map(); | ||
| private selectedTreeItems: ReportTreeItem[] = []; | ||
| private dynamicTreeItems: Map<string, ReportTreeItem> = new Map(); | ||
| private rootItems: ReportTreeItem[] = []; | ||
|
|
||
| constructor(ctx: ExtensionContext) { | ||
| ctx.subscriptions.push(this._onDidChangeTreeData = new EventEmitter()); | ||
| window.onDidChangeActiveTextEditor(this.refreshBugList, this, ctx.subscriptions); | ||
| window.onDidChangeActiveTextEditor(editor => { | ||
| // event is called twice. Ignore deactivation of the previous editor. | ||
| if (editor === undefined) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Already covered by #162. |
||
| return; | ||
| } | ||
| // this.refreshBugList(); | ||
| this.updateStatus(); | ||
| }, this, ctx.subscriptions); | ||
|
|
||
| ExtensionApi.diagnostics.diagnosticsUpdated(() => { | ||
| // FIXME: fired twice when a file is opened freshly. | ||
|
|
@@ -113,6 +144,23 @@ export class ReportsView implements TreeDataProvider<ReportTreeItem> { | |
| )); | ||
|
|
||
| this.init(); | ||
| this.updateStatus(); | ||
| } | ||
|
|
||
| public addDynamicNode(id: string, node: ReportTreeItem) { | ||
| this.dynamicTreeItems.set(id, node); | ||
| } | ||
|
|
||
| public getNodeById(id: string): ReportTreeItem | undefined { | ||
| return this.dynamicTreeItems.get(id); | ||
| } | ||
|
|
||
| public getAllNodes(): Map<string, ReportTreeItem> { | ||
| return this.treeItems; | ||
| } | ||
|
|
||
| public refreshNode() { | ||
| this._onDidChangeTreeData.fire(); | ||
| } | ||
|
|
||
| protected init() { | ||
|
|
@@ -121,6 +169,12 @@ export class ReportsView implements TreeDataProvider<ReportTreeItem> { | |
| this.tree?.onDidChangeSelection((item: TreeViewSelectionChangeEvent<ReportTreeItem>) => { | ||
| this.selectedTreeItems = item.selection; | ||
| }); | ||
|
|
||
| workspace.onDidChangeTextDocument(event => { | ||
| if (event?.document === window.activeTextEditor?.document) { | ||
| this.updateStatus(); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| private _onDidChangeTreeData: EventEmitter<void>; | ||
|
|
@@ -159,6 +213,24 @@ export class ReportsView implements TreeDataProvider<ReportTreeItem> { | |
| this._onDidChangeTreeData.fire(); | ||
| } | ||
|
|
||
| updateStatus() { | ||
| if (window?.activeTextEditor?.document?.isDirty) { | ||
| const statusNode = SidebarContainer.reportsView.getNodeById('statusItem'); | ||
| if (statusNode) { | ||
| statusNode?.setLabelAndIcon('Outdated (file is modified in the editor)', new ThemeIcon('edit')); | ||
| if (statusNode.children) { | ||
| statusNode.children.forEach(child => { | ||
| child.setLabelAndIcon(undefined, new ThemeIcon('edit')); | ||
| }); | ||
| } | ||
| } | ||
| } else { | ||
| const executorBridge = ExtensionApi.executorBridge; | ||
| executorBridge.getFileAnalysisStatus(); | ||
| } | ||
| this._onDidChangeTreeData.fire(); | ||
| } | ||
|
|
||
| revealSelectedItems() { | ||
| const selectedIds = new Set(this.selectedTreeItems.map(item => item.id)); | ||
| this.treeItems.forEach(root => root.traverse(item => { | ||
|
|
@@ -301,7 +373,10 @@ export class ReportsView implements TreeDataProvider<ReportTreeItem> { | |
| // Get root level items. | ||
| getRootItems(): ReportTreeItem[] | undefined { | ||
| if (!this.currentEntryList?.length) { | ||
| return [new ReportTreeItem('noReportsFound', 'No reports found', new ThemeIcon('pass'))]; | ||
| const statusNode = SidebarContainer.reportsView.getNodeById('statusItem'); | ||
| statusNode?.setLabelAndIcon('Not in compilation database', | ||
| new ThemeIcon('question', new ThemeColor('charts.orange'))); | ||
| return statusNode ? [ statusNode ] : undefined; | ||
| } | ||
|
|
||
| const severityItems: { [key: string]: TreeDiagnosticReport[] } = {}; | ||
|
|
@@ -315,6 +390,13 @@ export class ReportsView implements TreeDataProvider<ReportTreeItem> { | |
|
|
||
| const rootItems: ReportTreeItem[] = []; | ||
|
|
||
| let status = SidebarContainer.reportsView.getNodeById('statusItem'); | ||
| if (!status) { | ||
| status = new ReportTreeItem('statusItem', 'Status', new ThemeIcon('warning')); | ||
| SidebarContainer.reportsView.addDynamicNode('statusItem', status); | ||
| } | ||
| rootItems.push(status); | ||
|
|
||
| rootItems.push(...Object.entries(severityItems) | ||
| .sort(([severityA]: [string, TreeDiagnosticReport[]], [severityB]: [string, TreeDiagnosticReport[]]) => | ||
| severityOrder[severityA] - severityOrder[severityB]) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make this hideable somehow? if it's not supported, I don't need to have it persistently on the top, all the time.
Preferably place it somewhere else, maybe the Overview area?