Skip to content

Commit f84d9c1

Browse files
authored
Add Counterexample DTO (#105)
1 parent e839694 commit f84d9c1

5 files changed

Lines changed: 50 additions & 16 deletions

File tree

‎client/src/types/diagnostics.ts‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,19 @@ export type RefinementError = BaseDiagnostic & {
6262
expected: string;
6363
found: VCSimplificationResult;
6464
customMessage: string;
65-
counterexample: string;
65+
counterexample: Counterexample;
6666
declarationPosition: SourcePosition | null;
6767
}
6868

69+
export type Counterexample = {
70+
assignments: CounterexampleAssignment[];
71+
}
72+
73+
export type CounterexampleAssignment = {
74+
variable: string;
75+
value: string;
76+
}
77+
6978
export type StateConflictError = BaseDiagnostic & {
7079
category: 'error';
7180
type: 'state-conflict-error';

‎client/src/webview/views/diagnostics/counterexample.ts‎

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,17 @@
1+
import type { Counterexample } from "../../../types/diagnostics";
12
import { renderHighlightedInlineExpression } from "../../highlighting";
23

3-
function getCounterexampleLines(counterexample: string): string[] {
4-
return counterexample
5-
.split("&&")
6-
.map(assignment => assignment.trim())
7-
.filter(Boolean);
8-
}
9-
10-
export function renderCounterexample(counterexample: string): string {
11-
const lines = getCounterexampleLines(counterexample);
12-
if (lines.length === 0) return "";
4+
export function renderCounterexample(counterexample: Counterexample): string {
5+
if (counterexample.assignments.length === 0) return "";
136

147
return /*html*/`
158
<div class="container vc-container counterexample-container">
169
<div class="vc-chain">
17-
${lines.map(line => /*html*/`
10+
${counterexample.assignments.map(assignment => /*html*/`
1811
<div class="counterexample-line">
19-
<span class="vc-node">${renderHighlightedInlineExpression(line)}</span>
12+
<span class="vc-node">${renderHighlightedInlineExpression(
13+
`${assignment.variable} == ${assignment.value}`
14+
)}</span>
2015
</div>
2116
`).join("")}
2217
</div>

‎client/src/webview/views/diagnostics/errors.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ const errorContentRenderers: ErrorRendererMap = {
4040
'refinement-error': (e: RefinementError) => /*html*/ `
4141
${renderExpressionSection('Expected', e.expected)}
4242
${renderCustomSection('Found', renderVCImplication(e, e.found))}
43-
${e.counterexample ? renderCustomSection('Counterexample', renderCounterexample(e.counterexample)) : ''}
43+
${e.counterexample.assignments.length > 0
44+
? renderCustomSection('Counterexample', renderCounterexample(e.counterexample))
45+
: ''}
4446
`,
4547
'state-refinement-error': (e: StateRefinementError) => /*html*/ `
4648
${renderExpressionSection('Expected', e.expected)}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package dtos.diagnostics;
2+
3+
import java.util.List;
4+
5+
import liquidjava.rj_language.ast.formatter.VariableFormatter;
6+
import liquidjava.smt.Counterexample;
7+
8+
/**
9+
* DTO for serializing counterexample assignments.
10+
*/
11+
public record CounterexampleDTO(List<AssignmentDTO> assignments) {
12+
13+
public static CounterexampleDTO from(Counterexample counterexample) {
14+
if (counterexample == null)
15+
return null;
16+
17+
List<AssignmentDTO> assignments = counterexample.assignments().stream()
18+
.map(assignment -> new AssignmentDTO(
19+
VariableFormatter.format(assignment.first()),
20+
assignment.second()))
21+
.toList();
22+
return new CounterexampleDTO(assignments);
23+
}
24+
25+
public record AssignmentDTO(String variable, String value) {
26+
}
27+
}

‎server/src/main/java/dtos/errors/RefinementErrorDTO.java‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package dtos.errors;
22

3+
import dtos.diagnostics.CounterexampleDTO;
34
import dtos.diagnostics.SourcePositionDTO;
45
import dtos.diagnostics.VCSimplificationResultDTO;
56
import liquidjava.diagnostics.errors.RefinementError;
@@ -13,15 +14,15 @@ public class RefinementErrorDTO extends LJErrorDTO {
1314
public final String expected;
1415
public final VCSimplificationResultDTO found;
1516
public final String customMessage;
16-
public final String counterexample;
17+
public final CounterexampleDTO counterexample;
1718
public final SourcePositionDTO declarationPosition;
1819

1920
public RefinementErrorDTO(RefinementError error) {
2021
super("refinement-error", error);
2122
this.expected = error.getExpected() == null ? null : ExpressionFormatter.format(error.getExpected());
2223
this.found = VCSimplificationResultDTO.from(error.getFound());
2324
this.customMessage = error.getCustomMessage();
24-
this.counterexample = error.getCounterExampleString();
25+
this.counterexample = CounterexampleDTO.from(error.getCounterexample());
2526
this.declarationPosition = SourcePositionDTO.from(error.getDeclarationPosition());
2627
}
2728

0 commit comments

Comments
 (0)