Skip to content

Commit b57ae7d

Browse files
authored
Add Existence Checks to Classes & Methods in External Refinements (#66)
1 parent 758650d commit b57ae7d

File tree

4 files changed

+54
-3
lines changed

4 files changed

+54
-3
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package testSuite;
2+
3+
import liquidjava.specification.ExternalRefinementsFor;
4+
5+
@ExternalRefinementsFor("non.existent.Class")
6+
public interface ErrorExtRefNonExistentClass {
7+
public void NonExistentClass();
8+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package testSuite;
2+
3+
import liquidjava.specification.ExternalRefinementsFor;
4+
import liquidjava.specification.RefinementPredicate;
5+
import liquidjava.specification.StateRefinement;
6+
7+
@ExternalRefinementsFor("java.util.ArrayList")
8+
public interface ErrorExtRefNonExistentMethod<E> {
9+
10+
@RefinementPredicate("int size(ArrayList l)")
11+
@StateRefinement(to = "size(this) == 0")
12+
public void ArrayList();
13+
14+
@StateRefinement(to = "size(this) == (size(old(this)) + 1)")
15+
public void adddd(E e);
16+
}

liquidjava-example/src/main/java/testSuite/math/correctInvocation/MathRefinements.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,6 @@ public interface MathRefinements {
5757
@Refinement("(a > b)? (_ == b):(_ == a)")
5858
public int min(int a, int b);
5959

60-
@Refinement(" _ > 0.0 && _ < 1.0")
61-
public long random(long a, long b);
62-
6360
@Refinement("((sig > 0)?(_ > 0):(_ < 0)) && (( _ == arg)||(_ == -arg))")
6461
public float copySign(float arg, float sig);
6562
}

liquidjava-verifier/src/main/java/liquidjava/processor/refinement_checker/ExternalRefinementTypeChecker.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import spoon.reflect.declaration.CtField;
1919
import spoon.reflect.declaration.CtInterface;
2020
import spoon.reflect.declaration.CtMethod;
21+
import spoon.reflect.declaration.CtType;
22+
import spoon.reflect.declaration.CtTypeParameter;
2123
import spoon.reflect.factory.Factory;
2224
import spoon.reflect.reference.CtTypeReference;
2325

@@ -42,6 +44,10 @@ public <T> void visitCtInterface(CtInterface<T> intrface) {
4244
Optional<String> externalRefinements = getExternalRefinement(intrface);
4345
if (externalRefinements.isPresent()) {
4446
this.prefix = externalRefinements.get();
47+
if (!classExists(prefix)) {
48+
ErrorHandler.printCostumeError(intrface, "Could not find class '" + prefix + "'", errorEmitter);
49+
return;
50+
}
4551
try {
4652
getRefinementFromAnnotation(intrface);
4753
} catch (ParsingException e) {
@@ -72,6 +78,11 @@ public <R> void visitCtMethod(CtMethod<R> method) {
7278
if (errorEmitter.foundError())
7379
return;
7480

81+
if (!methodExists(method)) {
82+
ErrorHandler.printCostumeError(method,
83+
"Could not find method '" + method.getSignature() + "' in class '" + prefix + "'", errorEmitter);
84+
return;
85+
}
7586
MethodsFunctionsChecker mfc = new MethodsFunctionsChecker(this);
7687
try {
7788
mfc.getMethodRefinements(method, prefix);
@@ -122,4 +133,23 @@ protected String getQualifiedClassName(CtElement elem) {
122133
protected String getSimpleClassName(CtElement elem) {
123134
return Utils.getSimpleName(prefix);
124135
}
136+
137+
private boolean classExists(String className) {
138+
return factory.Type().createReference(className).getTypeDeclaration() != null;
139+
}
140+
141+
private boolean methodExists(CtMethod<?> method) {
142+
CtType<?> targetType = factory.Type().createReference(prefix).getTypeDeclaration();
143+
144+
// find a method with matching name and parameter count
145+
boolean methodFound = targetType.getMethods().stream()
146+
.anyMatch(m -> m.getSimpleName().equals(method.getSimpleName())
147+
&& m.getParameters().size() == method.getParameters().size());
148+
149+
if (!methodFound) {
150+
// check if constructor method
151+
return method.getSimpleName().equals(targetType.getSimpleName());
152+
}
153+
return true;
154+
}
125155
}

0 commit comments

Comments
 (0)