Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public <T> void visitCtInterface(CtInterface<T> intrface) {
this.prefix = literal.getValue();
if (!classExists(prefix)) {
String message = String.format("Could not find class '%s'", prefix);
diagnostics.add(new ExternalClassNotFoundWarning(externalRef.get().getPosition(), message, prefix));
diagnostics.add(new ExternalClassNotFoundWarning(literal.getPosition(), message, prefix));
return;
}
getRefinementFromAnnotation(intrface);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,14 @@ public Optional<Predicate> getRefinementFromAnnotation(CtElement element) throws
ref = Optional.of(value);

} else if (an.contentEquals("liquidjava.specification.RefinementPredicate")) {
String value = getStringFromAnnotation(ann.getValue("value"));
getGhostFunction(value, element, ann.getPosition());
CtExpression<String> rawValue = ann.getValue("value");
String value = getStringFromAnnotation(rawValue);
getGhostFunction(value, element, rawValue.getPosition());

} else if (an.contentEquals("liquidjava.specification.RefinementAlias")) {
String value = getStringFromAnnotation(ann.getValue("value"));
handleAlias(value, element, ann.getPosition());
CtExpression<String> rawValue = ann.getValue("value");
String value = getStringFromAnnotation(rawValue);
handleAlias(value, element, rawValue.getPosition());
}
}
if (ref.isPresent()) {
Expand Down Expand Up @@ -116,7 +118,7 @@ public void handleStateSetsFromAnnotation(CtElement element) throws LJError {
}
if (an.contentEquals("liquidjava.specification.Ghost")) {
CtLiteral<String> s = (CtLiteral<String>) ann.getAllValues().get("value");
createStateGhost(s.getValue(), element, ann.getPosition());
createStateGhost(s.getValue(), element, s.getPosition());
}
}
}
Expand Down Expand Up @@ -167,7 +169,8 @@ protected GhostDTO getGhostDeclaration(String value, SourcePosition position) th
return RefinementsParser.parseGhostDeclaration(value);
} catch (LJError e) {
// add location info to error
e.setPosition(position);
if (e.getPosition() == null)
e.setPosition(position);
throw e;
}
}
Expand Down Expand Up @@ -259,7 +262,8 @@ protected void handleAlias(String ref, CtElement element, SourcePosition positio
}
} catch (LJError e) {
// add location info to error
e.setPosition(position);
if (e.getPosition() == null)
e.setPosition(position);
throw e;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import liquidjava.smt.Counterexample;
import liquidjava.smt.SMTEvaluator;
import liquidjava.smt.SMTResult;
import liquidjava.utils.Utils;
import liquidjava.utils.constants.Keys;
import spoon.reflect.cu.SourcePosition;
import spoon.reflect.declaration.CtElement;
Expand Down Expand Up @@ -53,10 +54,14 @@ public void processSubtyping(Predicate expectedType, List<GhostState> list, CtEl
expected = expectedType.changeStatesToRefinements(filtered, s).changeAliasToRefinement(context, f);
} catch (LJError e) {
// add location info to error
e.setPosition(element.getPosition());
if (e.getPosition() == null) {
SourcePosition pos = Utils.getFirstLJAnnotationValuePosition(element);
e.setPosition(pos);
}
throw e;
}
SMTResult result = verifySMTSubtype(expected, premises, element.getPosition());
SourcePosition annotationValuePos = Utils.getFirstLJAnnotationValuePosition(element);
SMTResult result = verifySMTSubtype(expected, premises, annotationValuePos);
if (result.isError()) {
throw new RefinementError(element.getPosition(), expectedType.simplify(), premisesBeforeChange.simplify(),
map, result.getCounterexample(), customMessage);
Expand Down Expand Up @@ -94,7 +99,9 @@ public SMTResult verifySMTSubtype(Predicate expected, Predicate found, SourcePos
try {
return new SMTEvaluator().verifySubtype(found, expected, context);
} catch (LJError e) {
e.setPosition(position);
if (e.getPosition() == null) {
e.setPosition(position);
}
throw e;
} catch (Exception e) {
throw new CustomError(e.getMessage(), position);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,8 @@ private static Predicate createStatePredicate(String value, String targetClass,
c = c.changeOldMentions(nameOld, name);
boolean ok = tc.checkStateSMT(new Predicate(), c.negate(), e.getPosition());
if (ok) {
tc.throwStateConflictError(e.getPosition(), p);
SourcePosition pos = Utils.getLJAnnotationPosition(e, value);
tc.throwStateConflictError(pos, p);
}
return c1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,10 @@ protected Expression parse(String ref, CtElement element) throws LJError {
return RefinementsParser.createAST(ref, prefix);
} catch (LJError e) {
// add location info to error
SourcePosition pos = Utils.getLJAnnotationPosition(element, ref);
e.setPosition(pos);
if (e.getPosition() == null) {
SourcePosition pos = Utils.getLJAnnotationPosition(element, ref);
e.setPosition(pos);
}
throw e;
}
}
Expand Down
42 changes: 29 additions & 13 deletions liquidjava-verifier/src/main/java/liquidjava/utils/Utils.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package liquidjava.utils;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;
Expand All @@ -22,6 +23,7 @@
public class Utils {

private static final Set<String> DEFAULT_NAMES = Set.of("old", "length", "addToIndex", "getFromIndex");
private static final List<String> REFINEMENT_KEYS = List.of("value", "to", "from");

public static CtTypeReference<?> getType(String type, Factory factory) {
// TODO: complete with other types
Expand Down Expand Up @@ -54,28 +56,42 @@ public static String getFile(CtElement element) {
return pos.getFile().getAbsolutePath();
}

public static SourcePosition getLJAnnotationPosition(CtElement element, String refinement) {
return element.getAnnotations().stream()
.filter(a -> isLiquidJavaAnnotation(a) && hasRefinementValue(a, "\"" + refinement + "\"")).findFirst()
.map(CtElement::getPosition).orElse(element.getPosition());
// Get the position of the annotation with the given value
public static SourcePosition getLJAnnotationPosition(CtElement element, String value) {
String quotedValue = "\"" + value + "\"";
return getLiquidJavaAnnotations(element)
.flatMap(annotation -> getLJAnnotationValues(annotation)
.filter(expr -> quotedValue.equals(expr.toString()))
.map(expr -> expr.getPosition() != null ? expr.getPosition() : annotation.getPosition()))
.findFirst().orElse(element.getPosition());
}

// Get the position of the first LJ annotation on the element
public static SourcePosition getFirstLJAnnotationPosition(CtElement element) {
return element.getAnnotations().stream().filter(Utils::isLiquidJavaAnnotation).map(CtElement::getPosition)
.min((p1, p2) -> {
if (p1.getLine() != p2.getLine())
return Integer.compare(p1.getLine(), p2.getLine());
return Integer.compare(p1.getColumn(), p2.getColumn());
}).orElse(element.getPosition());
return getLiquidJavaAnnotations(element).map(CtAnnotation::getPosition).filter(pos -> pos != null).findFirst()
.orElse(element.getPosition());
}

// Get the position of the first value of the first LJ annotation on the element
public static SourcePosition getFirstLJAnnotationValuePosition(CtElement element) {
return getLiquidJavaAnnotations(element)
.map(annotation -> getLJAnnotationValues(annotation).map(CtElement::getPosition)
.filter(pos -> pos != null).findFirst()
.orElse(annotation.getPosition() != null ? annotation.getPosition() : element.getPosition()))
.findFirst().orElse(element.getPosition());
}

private static Stream<CtAnnotation<?>> getLiquidJavaAnnotations(CtElement element) {
return element.getAnnotations().stream().filter(Utils::isLiquidJavaAnnotation);
}

private static boolean isLiquidJavaAnnotation(CtAnnotation<?> annotation) {
return annotation.getAnnotationType().getQualifiedName().startsWith("liquidjava.specification");
}

private static boolean hasRefinementValue(CtAnnotation<?> annotation, String refinement) {
Map<String, ?> values = annotation.getValues();
return Stream.of("value", "to", "from").anyMatch(key -> refinement.equals(String.valueOf(values.get(key))));
private static Stream<CtElement> getLJAnnotationValues(CtAnnotation<?> annotation) {
Map<String, ?> values = annotation.getAllValues();
return REFINEMENT_KEYS.stream().map(values::get).filter(CtElement.class::isInstance).map(CtElement.class::cast);
}

public static SourcePosition getRealPosition(CtElement element) {
Expand Down
Loading