Skip to content
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

fix: "Failing precondition" on tooltip instead of "return path" #2654

Merged
merged 8 commits into from
Aug 31, 2022
2 changes: 1 addition & 1 deletion RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
- feat: Support for the `{:opaque}` attibute on `const` (https://github.com/dafny-lang/dafny/pull/2545)
- feat: Support for plugin-based code actions on the IDE (https://github.com/dafny-lang/dafny/pull/2021)
- fix: Check all compiled expressions to be compilable (https://github.com/dafny-lang/dafny/pull/2641)

- fix: Better messages on hovering failing postconditions in IDE (https://github.com/dafny-lang/dafny/pull/2654)

# 3.8.0

Expand Down
28 changes: 22 additions & 6 deletions Source/DafnyLanguageServer.Test/Lookup/HoverVerificationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ This is the only assertion in [batch](???) #2 of 3 in method f
await AssertHoverMatches(documentItem, (2, 12),
@"<span style='color:green'>**Success:**</span> assertion always holds
This is the only assertion in [batch](???) #3 of 3 in method f
[Batch](???) #3 resource usage: ??? RU "
[Batch](???) #3 resource usage: ??? RU"
);
await AssertHoverMatches(documentItem, (0, 36),
@"**Verification performance metrics for method f**:
Expand Down Expand Up @@ -132,7 +132,7 @@ await AssertHoverMatches(documentItem, (2, 12),
await AssertHoverMatches(documentItem, (3, 26),
@"[**Error:**](???) assertion might not hold
This is assertion #1 of 2 in [batch](???) #2 of 2 in function f
[Batch](???) #2 resource usage: ??? RU "
[Batch](???) #2 resource usage: ??? RU"
);
await AssertHoverMatches(documentItem, (0, 36),
@"**Verification performance metrics for function f**:
Expand All @@ -150,7 +150,6 @@ public async Task MeaningfulMessageWhenMethodWithoutAssert() {
method f(x: int) {
print x;
}", "testfile.dfy", CompilationStatus.VerificationSucceeded);
await Task.Delay(100); // Just time for the diagnostics to be updated
await AssertHoverMatches(documentItem, (0, 7),
@"**Verification performance metrics for method f**:

Expand All @@ -161,13 +160,29 @@ await AssertHoverMatches(documentItem, (0, 10),
}


[TestMethod, Timeout(MaxTestExecutionTimeMs)]
public async Task MeaningfulMessageForFailingPreconditions() {
var documentItem = await GetDocumentItem(@"
method Test1() {
Test2(0); // Hover #1
}

method Test2(i: int)
requires i > 0 {

}", "testfile.dfy", CompilationStatus.VerificationFailed);
await AssertHoverMatches(documentItem, (1, 10),
@"???
Failing precondition:???"
);
}

[TestMethod, Timeout(MaxTestExecutionTimeMs)]
public async Task MeaningfulMessageWhenMethodWithOneAssert() {
var documentItem = await GetDocumentItem(@"
method f(x: int) {
assert false;
}", "testfile1.dfy", CompilationStatus.VerificationFailed);
await Task.Delay(100); // Just time for the diagnostics to be updated
await AssertHoverMatches(documentItem, (0, 7),
@"**Verification performance metrics for method f**:

Expand All @@ -184,7 +199,6 @@ method f(x: int) {
assert false;
assert false;
}", "testfile2.dfy", CompilationStatus.VerificationFailed);
await Task.Delay(100); // Just time for the diagnostics to be updated
await AssertHoverMatches(documentItem, (0, 7),
@"**Verification performance metrics for method f**:

Expand All @@ -211,7 +225,6 @@ requires p > 0 && q > 0
}
assert {:split_here} true;
} ", "testfileSlow.dfy", CompilationStatus.VerificationFailed);
await Task.Delay(100); // Just time for the diagnostics to be updated
await AssertHoverMatches(documentItem, (0, 22),
@"**Verification performance metrics for method SquareRoot2NotRational**:

Expand All @@ -229,6 +242,9 @@ private async Task<TextDocumentItem> GetDocumentItem(string source, string filen
await client.OpenDocumentAndWaitAsync(documentItem, CancellationToken);
var lastStatus = await WaitUntilDafnyFinishes(documentItem);
Assert.AreEqual(expectedStatus, lastStatus);
foreach (var document in Documents.Documents) {
await document.LastDocument;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@keyboardDrummer do your confirm it's the right way to wait for the final translated and verified document to be available?

Copy link
Member

@keyboardDrummer keyboardDrummer Aug 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If verification has been triggered, like through verification on change or manual verification, this will wait for verification to complete. If verification has not been triggered, this returns after translation.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, that's what I wanted to know.

}
return documentItem;
}

Expand Down
10 changes: 8 additions & 2 deletions Source/DafnyLanguageServer/Handlers/DafnyHoverHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,8 @@ private string GetAssertionInformation(Position position, AssertionVerificationT


var currentlyHoveringPostcondition =
!(assertionNode.GetCounterExample() is ReturnCounterexample returnCounterexample2 &&
returnCounterexample2.FailingReturn.tok.GetLspRange().Contains(position));
assertionNode.GetCounterExample() is ReturnCounterexample returnCounterexample2 &&
!returnCounterexample2.FailingReturn.tok.GetLspRange().Contains(position);

var obsolescence = assertionNode.StatusCurrent switch {
CurrentStatus.Current => "",
Expand Down Expand Up @@ -248,6 +248,12 @@ string GetDescription(Boogie.ProofObligationDescription? description) {
: "");
}

if (assertionNode.GetCounterExample() is CallCounterexample) {
information += " \n" + (assertionNode.SecondaryPosition != null
? $"Failing precondition: {Path.GetFileName(assertionNode.Filename)}({assertionNode.SecondaryPosition.Line + 1}, {assertionNode.SecondaryPosition.Character + 1})"
: "");
}

return information;
}

Expand Down