From e0f16ee5449b6ab7ca8304bf76fdd3f200860bb2 Mon Sep 17 00:00:00 2001 From: Catherine Date: Fri, 15 Nov 2024 01:08:57 +0000 Subject: [PATCH] Focus important diagnostics (break, assert, assume) after moving cursor. --- example/design.sv | 3 +++ src/debug/session.ts | 1 - src/model/source.ts | 3 ++- src/ui/diagnostic.ts | 57 +++++++++++++++++++++++++++++++++++--------- 4 files changed, 51 insertions(+), 13 deletions(-) diff --git a/example/design.sv b/example/design.sv index e1776d4..a954e9b 100644 --- a/example/design.sv +++ b/example/design.sv @@ -60,4 +60,7 @@ module top( always @(posedge clk) assert (timer < 5); + always @(posedge clk) + assert (timer < 7); // two asserts at once + endmodule diff --git a/src/debug/session.ts b/src/debug/session.ts index 055b014..4de5a3e 100644 --- a/src/debug/session.ts +++ b/src/debug/session.ts @@ -366,7 +366,6 @@ export class Session { if (this.simulationStatus.status === 'paused') { const nextSampleTime = this.simulationStatus.nextSampleTime!; await this.runSimulation({ untilTime: nextSampleTime }); - await this.querySimulationStatus(); if (!nextSampleTime.greaterThan(this.simulationStatus.latestTime)) { this.timeCursor = nextSampleTime; } diff --git a/src/model/source.ts b/src/model/source.ts index f6ea1eb..c9ad631 100644 --- a/src/model/source.ts +++ b/src/model/source.ts @@ -40,7 +40,7 @@ export class Location { ); } - private openCommandArguments(): [vscode.Uri, vscode.TextDocumentShowOptions] { + openCommandArguments(): [vscode.Uri, vscode.TextDocumentShowOptions] { const position = new vscode.Position(this.startLine, this.startColumn ?? 0); return [ this.fileUri, @@ -60,6 +60,7 @@ export class Location { }; } + // Really? *Three* different command representations depending on the API? VS Code please. asOpenCommandUri(): vscode.Uri { const args = this.openCommandArguments(); return vscode.Uri.parse(`command:rtlDebugger.openDocument?${encodeURIComponent(JSON.stringify(args))}`); diff --git a/src/ui/diagnostic.ts b/src/ui/diagnostic.ts index 04dfe7f..4f3b9c9 100644 --- a/src/ui/diagnostic.ts +++ b/src/ui/diagnostic.ts @@ -10,10 +10,18 @@ export class DiagnosticProvider { private diagnosticCollection: vscode.DiagnosticCollection, ) { rtlDebugger.onDidChangeSession((session) => { - this.update(session); - if (session !== null) { - session.onDidChangeSimulationStatus((_simulationStatus) => this.update(session)); - session.onDidChangeTimeCursor((_timeCursor) => this.update(session)); + if (session === null) { + this.clear(); + } else { + session.onDidChangeSimulationStatus((simulationStatus) => { + if (simulationStatus.status === 'running') { + this.clear(); + } + }); + session.onDidChangeTimeCursor((_timeCursor) => { + this.request(session); + }); + this.request(session); } }); } @@ -22,17 +30,20 @@ export class DiagnosticProvider { this.diagnosticCollection.dispose(); } - private async update(session: Session | null) { - if (session === null || session?.simulationStatus.status === 'running') { - this.apply([]); - } else { - const sample = await session.queryAtCursor({ diagnostics: true }); - this.apply(sample.diagnostics!); - } + private async clear() { + this.apply([]); + } + + private async request(session: Session) { + const sample = await session.queryAtCursor({ diagnostics: true }); + this.apply(sample.diagnostics!); } private apply(diagnostics: Diagnostic[]) { const diagnosticMap = new Map(); + let mostImportantDiagnostic = null; + let mostImportantDiagnosticSeverity = vscode.DiagnosticSeverity.Hint; + let multipleImportantDiagnostics = false; for (const diagnostic of diagnostics) { if (diagnostic.location === null) { continue; @@ -85,6 +96,17 @@ export class DiagnosticProvider { severity = vscode.DiagnosticSeverity.Error; break; } + if (severity !== vscode.DiagnosticSeverity.Information && diagnostic.location !== null) { + // Prioritize assertions/assumptions over breakpoints. (It's unclear whether this + // specific prioritization is the best one, but one of them should probably take + // priority over the other.) + multipleImportantDiagnostics = (mostImportantDiagnostic !== null); + if (severity < mostImportantDiagnosticSeverity) { + mostImportantDiagnostic = diagnostic; + mostImportantDiagnosticSeverity = severity; + } + } + if (message !== '') { const mappedDiagnostic = new vscode.Diagnostic(range, message, severity); mappedDiagnostic.code = diagnostic.type; @@ -95,5 +117,18 @@ export class DiagnosticProvider { this.diagnosticCollection.clear(); this.diagnosticCollection.set(Array.from(diagnosticMap.entries())); + + if (mostImportantDiagnostic !== null) { + this.focus(mostImportantDiagnostic, multipleImportantDiagnostics); + } + } + + private async focus(diagnostic: Diagnostic, showDiagnosticsPane: boolean = false) { + if (showDiagnosticsPane) { + await vscode.commands.executeCommand('workbench.actions.view.problems'); + } + // 2024-11-14: Upsettingly, this is the best (and, more or less, only) way to expand a diagnostic. + await vscode.window.showTextDocument(...diagnostic.location!.openCommandArguments()); + await vscode.commands.executeCommand('editor.action.marker.next'); } }