Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
fcaa941
Save Context History
rcosta358 Feb 18, 2026
a532c05
Save Context Vars by File and Scope
rcosta358 Feb 19, 2026
07a4c63
Fix NPE
rcosta358 Feb 19, 2026
dd127c6
Save Ghosts By File
rcosta358 Feb 20, 2026
eff7067
Use Annotation Position & Mark Parameters
rcosta358 Feb 24, 2026
8ee09ea
Fix
rcosta358 Feb 24, 2026
e74d105
Rename `fileScopeVars`
rcosta358 Feb 26, 2026
642ba0e
Store Refined Variable Annotation Position
rcosta358 Feb 28, 2026
0f6d354
Formatting
rcosta358 Feb 28, 2026
eb535e7
Renaming
rcosta358 Feb 28, 2026
152ec18
Merge branch 'main' into context-history-improvements
rcosta358 Mar 5, 2026
ea38850
Fix Merge
rcosta358 Mar 5, 2026
dd62da8
Release
rcosta358 Mar 5, 2026
73b79ac
Fix Scope Position
rcosta358 Mar 7, 2026
d05f418
Remove Error Position
rcosta358 Mar 6, 2026
4f0272b
Add File to GhostState
rcosta358 Mar 9, 2026
1d7b0c6
Add Variable Instance Regardless of Matching State
rcosta358 Mar 9, 2026
964aca2
Minor Change
rcosta358 Mar 9, 2026
3238fc1
Substitute `this` in `expectedStatesDisjunction`
rcosta358 Mar 9, 2026
816df6b
Remove Unused Imports
rcosta358 Mar 9, 2026
6b0574c
Save Scopes by File
rcosta358 Mar 9, 2026
758e963
Fix NullPointerException
rcosta358 Mar 11, 2026
5f5c148
Substitute New Instance Name In Found State
rcosta358 Mar 11, 2026
0294c7d
Fix Scope Positions
rcosta358 Mar 11, 2026
da035a8
Remove Unused Imports
rcosta358 Mar 11, 2026
9ffe9d9
Move Annotation Position from `RefinedVariable` to `PlacementInCode`
rcosta358 Mar 12, 2026
8ce21e1
Revert Previous Changes to `AuxStateHandler`
rcosta358 Mar 13, 2026
997375b
Formatting
rcosta358 Mar 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion liquidjava-verifier/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<groupId>io.github.liquid-java</groupId>
<artifactId>liquidjava-verifier</artifactId>
<version>0.0.14</version>
<version>0.0.15</version>
<name>liquidjava-verifier</name>
<description>LiquidJava Verifier</description>
<url>https://github.com/liquid-java/liquidjava</url>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ public class LJDiagnostic extends RuntimeException {
private final String accentColor;
private final String customMessage;
private String file;
private ErrorPosition position;
private SourcePosition position;
private static final String PIPE = " | ";

public LJDiagnostic(String title, String message, SourcePosition pos, String accentColor, String customMessage) {
this.title = title;
this.message = message;
this.file = (pos != null && pos.getFile() != null) ? pos.getFile().getPath() : null;
this.position = ErrorPosition.fromSpoonPosition(pos);
this.position = pos;
this.accentColor = accentColor;
this.customMessage = customMessage;
}
Expand All @@ -41,14 +41,14 @@ public String getDetails() {
return ""; // to be overridden by subclasses
}

public ErrorPosition getPosition() {
public SourcePosition getPosition() {
return position;
}

public void setPosition(SourcePosition pos) {
if (pos == null)
if (pos == null || pos.getFile() == null)
return;
this.position = ErrorPosition.fromSpoonPosition(pos);
this.position = pos;
this.file = pos.getFile().getPath();
}

Expand Down Expand Up @@ -82,7 +82,7 @@ public String toString() {

// location
if (file != null && position != null) {
sb.append("\n").append(file).append(":").append(position.lineStart()).append(Colors.RESET).append("\n");
sb.append("\n").append(file).append(":").append(position.getLine()).append(Colors.RESET).append("\n");
}

return sb.toString();
Expand All @@ -100,8 +100,8 @@ public String getSnippet() {
// before and after lines for context
int contextBefore = 2;
int contextAfter = 2;
int startLine = Math.max(1, position.lineStart() - contextBefore);
int endLine = Math.min(lines.size(), position.lineEnd() + contextAfter);
int startLine = Math.max(1, position.getLine() - contextBefore);
int endLine = Math.min(lines.size(), position.getEndLine() + contextAfter);

// calculate padding for line numbers
int padding = String.valueOf(endLine).length();
Expand All @@ -115,9 +115,9 @@ public String getSnippet() {
sb.append(Colors.GREY).append(lineNumStr).append(PIPE).append(line).append(Colors.RESET).append("\n");

// add error markers on the line(s) with the error
if (i >= position.lineStart() && i <= position.lineEnd()) {
int colStart = (i == position.lineStart()) ? position.colStart() : 1;
int colEnd = (i == position.lineEnd()) ? position.colEnd() : rawLine.length();
if (i >= position.getLine() && i <= position.getEndLine()) {
int colStart = (i == position.getLine()) ? position.getColumn() : 1;
int colEnd = (i == position.getEndLine()) ? position.getEndColumn() : rawLine.length();

if (colStart > 0 && colEnd > 0) {
int tabsBeforeStart = (int) rawLine.substring(0, Math.max(0, colStart - 1)).chars()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,32 +104,31 @@ public void addVarToContext(RefinedVariable var) {
var.addSuperTypes(type.getSuperclass(), type.getSuperInterfaces());
}

public RefinedVariable addVarToContext(String simpleName, CtTypeReference<?> type, Predicate c,
CtElement placementInCode) {
public RefinedVariable addVarToContext(String simpleName, CtTypeReference<?> type, Predicate c, CtElement element) {
RefinedVariable vi = new Variable(simpleName, type, c);
vi.addPlacementInCode(PlacementInCode.createPlacement(placementInCode));
vi.setPlacementInCode(element);
vi.addSuperTypes(type.getSuperclass(), type.getSuperInterfaces());
addVarToContext(vi);
return vi;
}

public RefinedVariable addInstanceToContext(String simpleName, CtTypeReference<?> type, Predicate c,
CtElement placementInCode) {
CtElement element) {
RefinedVariable vi = new VariableInstance(simpleName, type, c);
vi.addPlacementInCode(PlacementInCode.createPlacement(placementInCode));
vi.setPlacementInCode(element);
if (!ctxInstanceVars.contains(vi))
addInstanceVariable(vi);
return vi;
}

public void addRefinementToVariableInContext(String name, CtTypeReference<?> type, Predicate et,
CtElement placementInCode) {
CtElement element) {
if (hasVariable(name)) {
RefinedVariable vi = getVariableByName(name);
vi.setRefinement(et);
vi.addPlacementInCode(PlacementInCode.createPlacement(placementInCode));
vi.setPlacementInCode(element);
} else {
addVarToContext(name, type, et, placementInCode);
addVarToContext(name, type, et, element);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@
import java.util.Map;
import java.util.Set;

import liquidjava.utils.Utils;
import spoon.reflect.cu.SourcePosition;
import spoon.reflect.declaration.CtElement;
import spoon.reflect.declaration.CtExecutable;

public class ContextHistory {
private static ContextHistory instance;

private Map<String, Map<String, Set<RefinedVariable>>> fileScopeVars; // file -> (scope -> variables in scope)
private Set<RefinedVariable> instanceVars;
private Set<RefinedVariable> globalVars;
private Map<String, Set<String>> fileScopes;
private Set<RefinedVariable> localVars;
private Set<GhostState> ghosts;
private Set<AliasWrapper> aliases;
private Set<RefinedVariable> globalVars;

private ContextHistory() {
fileScopeVars = new HashMap<>();
instanceVars = new HashSet<>();
fileScopes = new HashMap<>();
localVars = new HashSet<>();
globalVars = new HashSet<>();
ghosts = new HashSet<>();
aliases = new HashSet<>();
Expand All @@ -33,48 +33,40 @@ public static ContextHistory getInstance() {
}

public void clearHistory() {
fileScopeVars.clear();
instanceVars.clear();
fileScopes.clear();
localVars.clear();
globalVars.clear();
ghosts.clear();
aliases.clear();
}

public void saveContext(CtElement element, Context context) {
SourcePosition pos = element.getPosition();
if (pos == null || pos.getFile() == null)
String file = Utils.getFile(element);
if (file == null)
return;

// add variables in scope for this position
String file = pos.getFile().getAbsolutePath();
// add scope
String scope = getScopePosition(element);
fileScopeVars.putIfAbsent(file, new HashMap<>());
fileScopeVars.get(file).put(scope, new HashSet<>(context.getCtxVars()));
fileScopes.putIfAbsent(file, new HashSet<>());
fileScopes.get(file).add(scope);

// add other elements in context
instanceVars.addAll(context.getCtxInstanceVars());
// add variables, ghosts and aliases
localVars.addAll(context.getCtxVars());
localVars.addAll(context.getCtxInstanceVars());
globalVars.addAll(context.getCtxGlobalVars());
ghosts.addAll(context.getGhostStates());
aliases.addAll(context.getAliases());
}

public String getScopePosition(CtElement element) {
SourcePosition pos = element.getPosition();
SourcePosition innerPosition = pos;
if (element instanceof CtExecutable<?> executable) {
if (executable.getBody() != null)
innerPosition = executable.getBody().getPosition();
}
return String.format("%d:%d-%d:%d", innerPosition.getLine(), innerPosition.getColumn() + 1, pos.getEndLine(),
pos.getEndColumn());
}

public Map<String, Map<String, Set<RefinedVariable>>> getFileScopeVars() {
return fileScopeVars;
private String getScopePosition(CtElement element) {
SourcePosition startPos = Utils.getRealPosition(element);
SourcePosition endPos = element.getPosition();
return String.format("%d:%d-%d:%d", startPos.getLine(), startPos.getColumn(), endPos.getEndLine(),
endPos.getEndColumn() - 1);
}

public Set<RefinedVariable> getInstanceVars() {
return instanceVars;
public Set<RefinedVariable> getLocalVars() {
return localVars;
}

public Set<RefinedVariable> getGlobalVars() {
Expand All @@ -88,4 +80,8 @@ public Set<GhostState> getGhosts() {
public Set<AliasWrapper> getAliases() {
return aliases;
}

public Map<String, Set<String>> getFileScopes() {
return fileScopes;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ public class GhostState extends GhostFunction {

private GhostFunction parent;
private Predicate refinement;
private final String file;

public GhostState(String name, List<CtTypeReference<?>> list, CtTypeReference<?> returnType, String prefix) {
public GhostState(String name, List<CtTypeReference<?>> list, CtTypeReference<?> returnType, String prefix,
String file) {
super(name, list, returnType, prefix);
this.file = file;
}

public void setGhostParent(GhostFunction parent) {
Expand All @@ -28,4 +31,8 @@ public GhostFunction getParent() {
public Predicate getRefinement() {
return refinement;
}

public String getFile() {
return file;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package liquidjava.processor.context;

import java.lang.annotation.Annotation;

import liquidjava.utils.Utils;
import spoon.reflect.code.CtComment;
import spoon.reflect.cu.SourcePosition;
import spoon.reflect.declaration.CtAnnotation;
Expand All @@ -9,10 +11,12 @@
public class PlacementInCode {
private final String text;
private final SourcePosition position;
private final SourcePosition annotationPosition;

private PlacementInCode(String text, SourcePosition pos) {
private PlacementInCode(String text, SourcePosition pos, SourcePosition annotationPosition) {
this.text = text;
this.position = pos;
this.annotationPosition = annotationPosition;
}

public String getText() {
Expand All @@ -23,6 +27,10 @@ public SourcePosition getPosition() {
return position;
}

public SourcePosition getAnnotationPosition() {
return annotationPosition;
}

public static PlacementInCode createPlacement(CtElement elem) {
CtElement elemCopy = elem.clone();
// cleanup annotations
Expand All @@ -38,7 +46,8 @@ public static PlacementInCode createPlacement(CtElement elem) {
}
}
String elemText = elemCopy.toString();
return new PlacementInCode(elemText, elem.getPosition());
SourcePosition annotationPosition = Utils.getFirstLJAnnotationPosition(elem);
return new PlacementInCode(elemText, elem.getPosition(), annotationPosition);
}

public String toString() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.List;
import java.util.Set;
import liquidjava.rj_language.Predicate;
import spoon.reflect.declaration.CtElement;
import spoon.reflect.reference.CtTypeReference;

public abstract class RefinedVariable extends Refined {
Expand Down Expand Up @@ -34,8 +35,12 @@ public void addSuperTypes(CtTypeReference<?> ts, Set<CtTypeReference<?>> sts) {
supertypes.add(ct);
}

public void addPlacementInCode(PlacementInCode s) {
placementInCode = s;
public void setPlacementInCode(CtElement element) {
placementInCode = PlacementInCode.createPlacement(element);
}

public void setPlacementInScope(PlacementInCode placement) {
placementInCode = placement;
}

public PlacementInCode getPlacementInCode() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ else if (has(ifbeforeIndex)) // value before and in else
ref = createITEConstraint(nName, cond.negate(), get(ifelseIndex));
}
VariableInstance jointReturn = new VariableInstance(nName, super.getType(), ref, this);
jointReturn.addPlacementInCode(getPlacementInCode());
jointReturn.setPlacementInScope(getPlacementInCode());
return Optional.of(jointReturn);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import liquidjava.processor.facade.GhostDTO;
import liquidjava.processor.refinement_checker.general_checkers.MethodsFunctionsChecker;
import liquidjava.rj_language.Predicate;
import liquidjava.rj_language.parsing.RefinementsParser;
import liquidjava.utils.Utils;
import spoon.reflect.code.CtLiteral;
import spoon.reflect.cu.SourcePosition;
Expand All @@ -28,8 +27,8 @@
import spoon.reflect.reference.CtTypeReference;

public class ExternalRefinementTypeChecker extends TypeChecker {
String prefix;
Diagnostics diagnostics = Diagnostics.getInstance();
private String prefix;
private final Diagnostics diagnostics = Diagnostics.getInstance();

public ExternalRefinementTypeChecker(Context context, Factory factory) {
super(context, factory);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public Optional<Predicate> getRefinementFromAnnotation(CtElement element) throws
if (ref.isPresent()) {
Predicate p = new Predicate(ref.get(), element);
if (!p.getExpression().isBooleanExpression()) {
SourcePosition position = Utils.getAnnotationPosition(element, ref.get());
SourcePosition position = Utils.getLJAnnotationPosition(element, ref.get());
throw new InvalidRefinementError(position, "Refinement predicate must be a boolean expression",
ref.get());
}
Expand Down Expand Up @@ -152,7 +152,7 @@ private void createStateSet(CtNewArray<String> e, int set, CtElement element) th
CtLiteral<String> s = (CtLiteral<String>) ce;
String f = s.getValue();
GhostState gs = new GhostState(f, g.getParametersTypes(), factory.Type().BOOLEAN_PRIMITIVE,
g.getPrefix());
g.getPrefix(), Utils.getFile(element));
gs.setGhostParent(g);
gs.setRefinement(Predicate.createEquals(ip, Predicate.createLit(Integer.toString(order), Types.INT)));
// open(THIS) -> state1(THIS) == 1
Expand Down Expand Up @@ -189,7 +189,7 @@ private void createStateGhost(String string, CtElement element, SourcePosition p
List<CtTypeReference<?>> param = Collections.singletonList(factory.Type().createReference(qn));

CtTypeReference<?> r = factory.Type().createReference(gd.returnType());
GhostState gs = new GhostState(gd.name(), param, r, qn);
GhostState gs = new GhostState(gd.name(), param, r, qn, Utils.getFile(element));
context.addToGhostClass(sn, gs);
}

Expand Down
Loading
Loading