Skip to content

Commit a60c15f

Browse files
authored
Verification Gutter Status (#147)
Features implemented: - Renders the linear verification statuses in the left gutter with static and animated icons - That same diagnostics are also rendered in the right scrollbar for a preview of the entire file - Option to deactivate verification gutter status (on by default) - Parse errors will gray out the gutter display after 2 seconds the first time, and immediately after every subsequent resolution or parsing errors - The first "obsolete" line diagnostics is not shown until 2 seconds after it is first set up, so that there is less flickering for the current method being edited
1 parent b914632 commit a60c15f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+474
-2
lines changed

images/error-obsolete.png

383 Bytes

images/error-obsolete_gray.png

462 Bytes

images/error-range-end-obsolete.png

653 Bytes
587 Bytes

images/error-range-end-verifying.png

585 Bytes

images/error-range-end.png

284 Bytes

images/error-range-end_gray.png

605 Bytes

images/error-range-obsolete.png

461 Bytes

images/error-range-obsolete_gray.png

520 Bytes

images/error-range-start-obsolete.png

625 Bytes
621 Bytes
596 Bytes

images/error-range-start.png

292 Bytes

images/error-range-start_gray.png

608 Bytes
747 Bytes
692 Bytes
746 Bytes
735 Bytes

images/error-range-verified.png

534 Bytes

images/error-range-verifying-2.png

469 Bytes

images/error-range-verifying.png

461 Bytes

images/error-range-verifying_gray.png

526 Bytes

images/error-range.png

227 Bytes

images/error-range_gray.png

226 Bytes

images/error-verifying-2.png

363 Bytes

images/error-verifying.png

365 Bytes

images/error-verifying_gray.png

430 Bytes

images/error.png

171 Bytes

images/error_gray.png

229 Bytes

images/resolution-error.png

435 Bytes

images/scheduled.png

419 Bytes

images/verified-obsolete.png

649 Bytes

images/verified-verifying-2.png

463 Bytes

images/verified-verifying.png

444 Bytes

images/verified.png

239 Bytes

images/verified_gray.png

233 Bytes

images/verifying-2.png

373 Bytes

images/verifying.png

366 Bytes

package.json

+5
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,11 @@
155155
"default": "true",
156156
"description": "Mark ghost statements in the code (requires restart and Dafny 3.4.0+)"
157157
},
158+
"dafny.displayGutterStatus": {
159+
"type": "boolean",
160+
"default": "true",
161+
"description": "Display verification status in the gutter (requires restart and Dafny 3.7.0+)"
162+
},
158163
"dafny.dafnyPlugins": {
159164
"type": "array",
160165
"items": {

src/constants.ts

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export namespace ConfigurationConstants {
2424
export const VerificationCachingPolicy = 'verificationCachingPolicy';
2525
export const MarkGhostStatements = 'markGhostStatements';
2626
export const DafnyPlugins = 'dafnyPlugins';
27+
export const DisplayGutterStatus = 'displayGutterStatus';
2728
}
2829

2930
export namespace Compiler {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { DocumentUri, integer } from 'vscode-languageclient';
2+
3+
export interface IVerificationGutterStatusParams {
4+
uri: DocumentUri;
5+
version?: integer;
6+
perLineStatus: LineVerificationStatus[];
7+
}
8+
9+
// Except for cosmetics, this enumeration is a copy-paste from Dafny's
10+
// Source/DafnyLanguageServer/Workspace/Notifications/VerificationDiagnosticsParams.cs
11+
export enum LineVerificationStatus {
12+
// Default value for every line, before the renderer figures it out.
13+
Nothing = 0,
14+
// For first-time computation not actively computing but soon. Synonym of "obsolete"
15+
// (scheduledComputation)
16+
Scheduled = 1,
17+
// For first-time computations, actively computing
18+
Verifying = 2,
19+
VerifiedObsolete = 201,
20+
VerifiedVerifying = 202,
21+
// Also applicable for empty spaces if they are not surrounded by errors.
22+
Verified = 200,
23+
// For trees containing children with errors (e.g. methods)
24+
ErrorContextObsolete = 301,
25+
ErrorContextVerifying = 302,
26+
ErrorContext = 300,
27+
// For individual assertions in error ranges
28+
AssertionVerifiedInErrorContextObsolete = 351,
29+
AssertionVerifiedInErrorContextVerifying = 352,
30+
AssertionVerifiedInErrorContext = 350,
31+
// For specific lines which have errors on it. They take over verified assertions
32+
AssertionFailedObsolete = 401,
33+
AssertionFailedVerifying = 402,
34+
AssertionFailed = 400,
35+
// For lines containing resolution or parse errors
36+
ResolutionError = 500,
37+
// Cosmetics, not part of server's output
38+
ErrorContextStart = 310,
39+
ErrorContextStartObsolete = 311,
40+
ErrorContextStartVerifying = 312,
41+
ErrorContextEnd = 320,
42+
ErrorContextEndObsolete = 321,
43+
ErrorContextEndVerifying = 322
44+
}
45+
46+
export enum ScrollColor {
47+
Unknown = '#00000000',
48+
Error = '#fe536aa0',
49+
ErrorActive = '#fe536ad0',
50+
ErrorRange = '#fad00080',
51+
Verified = '#62b45580'
52+
}
53+
54+
export const obsoleteLineVerificationStatus: LineVerificationStatus[] = [
55+
LineVerificationStatus.AssertionFailedObsolete,
56+
LineVerificationStatus.VerifiedObsolete,
57+
LineVerificationStatus.ErrorContextObsolete,
58+
LineVerificationStatus.ErrorContextStartObsolete,
59+
LineVerificationStatus.ErrorContextEndObsolete
60+
];
61+
export const verifyingLineVerificationStatus: LineVerificationStatus[] = [
62+
LineVerificationStatus.Verifying,
63+
LineVerificationStatus.AssertionFailedVerifying,
64+
LineVerificationStatus.ErrorContextEndVerifying,
65+
LineVerificationStatus.ErrorContextVerifying,
66+
LineVerificationStatus.ErrorContextStartVerifying,
67+
LineVerificationStatus.VerifiedVerifying,
68+
LineVerificationStatus.AssertionVerifiedInErrorContextVerifying
69+
];
70+
export const nonErrorLineVerificationStatus: LineVerificationStatus[] = [
71+
LineVerificationStatus.Scheduled,
72+
LineVerificationStatus.Nothing,
73+
LineVerificationStatus.Verified,
74+
LineVerificationStatus.VerifiedObsolete,
75+
LineVerificationStatus.VerifiedVerifying,
76+
LineVerificationStatus.Verifying
77+
];

src/language/dafnyLanguageClient.ts

+10
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { DafnyDocumentFilter } from '../tools/vscode';
88
import { ICompilationStatusParams, IVerificationCompletedParams, IVerificationStartedParams } from './api/compilationStatus';
99
import { ICounterExampleItem, ICounterExampleParams } from './api/counterExample';
1010
import { IGhostDiagnosticsParams } from './api/ghostDiagnostics';
11+
import { IVerificationGutterStatusParams as IVerificationGutterStatusParams } from './api/verificationGutterStatusParams';
1112
import { getLanguageServerRuntimePath } from './dafnyInstallation';
1213

1314
const LanguageServerId = 'dafny-vscode';
@@ -21,6 +22,7 @@ function getLanguageServerLaunchArgs(): string[] {
2122
getVerifierCachingPolicy(),
2223
getVerifierVirtualCoresArgument(),
2324
getMarkGhostStatementsArgument(),
25+
getDisplayGutterStatusArgument(),
2426
...getDafnyPluginsArgument(),
2527
...launchArgs
2628
];
@@ -48,6 +50,10 @@ function getVerifierVirtualCoresArgument(): string {
4850
return `--verifier:vcscores=${Configuration.get<string>(ConfigurationConstants.LanguageServer.VerificationVirtualCores)}`;
4951
}
5052

53+
function getDisplayGutterStatusArgument(): string {
54+
return `--verifier:gutterStatus=${Configuration.get<string>(ConfigurationConstants.LanguageServer.DisplayGutterStatus)}`;
55+
}
56+
5157
function getMarkGhostStatementsArgument(): string {
5258
return `--ghost:markStatements=${Configuration.get<string>(ConfigurationConstants.LanguageServer.MarkGhostStatements)}`;
5359
}
@@ -101,6 +107,10 @@ export class DafnyLanguageClient extends LanguageClient {
101107
return this.onNotification('dafny/ghost/diagnostics', callback);
102108
}
103109

110+
public onVerificationStatusGutter(callback: (params: IVerificationGutterStatusParams) => void): Disposable {
111+
return this.onNotification('dafny/verification/status/gutter', callback);
112+
}
113+
104114
public onCompilationStatus(callback: (params: ICompilationStatusParams) => void): Disposable {
105115
return this.onNotification('dafny/compilation/status', callback);
106116
}

src/ui/compilationStatusView.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { StatusBarAlignment, StatusBarItem, TextDocument, window, workspace, ExtensionContext } from 'vscode';
2-
32
import { CompilationStatus, ICompilationStatusParams, IVerificationCompletedParams, IVerificationStartedParams } from '../language/api/compilationStatus';
43
import { DafnyLanguageClient } from '../language/dafnyLanguageClient';
54
import { getVsDocumentPath } from '../tools/vscode';
@@ -23,7 +22,9 @@ function toStatusMessage(status: CompilationStatus, message?: string | null): st
2322
case CompilationStatus.VerificationSucceeded:
2423
return Messages.CompilationStatus.VerificationSucceeded;
2524
case CompilationStatus.VerificationFailed:
26-
return Messages.CompilationStatus.VerificationFailed;
25+
return message != null
26+
? `${Messages.CompilationStatus.VerificationFailed} ${message}`
27+
: `${Messages.CompilationStatus.VerificationFailed}`;
2728
}
2829
}
2930

src/ui/dafnyIntegration.ts

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import CompileCommands from './compileCommands';
66
import CounterExamplesView from './counterExamplesView';
77
import DafnyVersionView from './dafnyVersionView';
88
import GhostDiagnosticsView from './ghostDiagnosticsView';
9+
import VerificationGutterStatusView from './verificationGutterStatusView';
910

1011
export default async function createAndRegisterDafnyIntegration(
1112
context: ExtensionContext,
@@ -14,6 +15,7 @@ export default async function createAndRegisterDafnyIntegration(
1415
): Promise<void> {
1516
CounterExamplesView.createAndRegister(context, languageClient);
1617
GhostDiagnosticsView.createAndRegister(context, languageClient);
18+
VerificationGutterStatusView.createAndRegister(context, languageClient);
1719
CompileCommands.createAndRegister(context);
1820
CompilationStatusView.createAndRegister(context, languageClient);
1921
await DafnyVersionView.createAndRegister(context, languageServerVersion);

0 commit comments

Comments
 (0)