Skip to content

Commit a3b04c6

Browse files
authored
Added enum types and verification (#168)
1 parent f790481 commit a3b04c6

File tree

18 files changed

+373
-7
lines changed

18 files changed

+373
-7
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package testSuite;
2+
3+
import liquidjava.specification.Refinement;
4+
5+
@SuppressWarnings("unused")
6+
class CorrectEnumField {
7+
enum Color {
8+
Red, Green, Blue
9+
}
10+
11+
@Refinement("color != Color.Blue")
12+
Color color;
13+
14+
void setColor(@Refinement("c != Color.Blue") Color c) {
15+
color = c;
16+
}
17+
18+
public static void main(String[] args) {
19+
CorrectEnumField cef = new CorrectEnumField();
20+
cef.setColor(Color.Red); // correct
21+
cef.setColor(Color.Green); // correct
22+
}
23+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package testSuite;
2+
3+
import liquidjava.specification.Refinement;
4+
5+
@SuppressWarnings("unused")
6+
class CorrectEnumParam {
7+
enum Status {
8+
Active, Inactive, Pending
9+
}
10+
11+
Status process(@Refinement("status == Status.Inactive") Status status) {
12+
return Status.Active;
13+
}
14+
15+
public static void main(String[] args) {
16+
CorrectEnumParam cep = new CorrectEnumParam();
17+
cep.process(Status.Inactive); // correct
18+
}
19+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package testSuite;
2+
3+
import liquidjava.specification.Refinement;
4+
5+
class CorrectEnumRefinement {
6+
enum Lever {
7+
Up, Down, Middle
8+
}
9+
10+
public static void main(String[] args) {
11+
@Refinement("_==Lever.Up || _==Lever.Down")
12+
Lever lever = Lever.Up;
13+
System.out.println(lever);
14+
}
15+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package testSuite;
2+
3+
import liquidjava.specification.StateRefinement;
4+
import liquidjava.specification.StateSet;
5+
6+
@SuppressWarnings("unused")
7+
@StateSet({"photoMode", "videoMode", "noMode"})
8+
class CorrectEnumUsage {
9+
enum Mode {
10+
Photo, Video, Unknown
11+
}
12+
13+
Mode mode;
14+
@StateRefinement(to="noMode(this)")
15+
public CorrectEnumUsage() {}
16+
17+
@StateRefinement(from="noMode(this) && mode == Mode.Photo", to="photoMode(this)")
18+
@StateRefinement(from="noMode(this) && mode == Mode.Video", to="videoMode(this)")
19+
public void setMode(Mode mode) {
20+
this.mode = mode;
21+
}
22+
23+
@StateRefinement(from="photoMode(this)", to="noMode(this)")
24+
@StateRefinement(from="videoMode(this)", to="noMode(this)")
25+
public void resetMode() {
26+
this.mode = null;
27+
}
28+
29+
@StateRefinement(from="photoMode(this)")
30+
public void takePhoto() {}
31+
32+
@StateRefinement(from="videoMode(this)")
33+
public void takeVideo() {}
34+
35+
36+
public static void main(String[] args) {
37+
// Correct
38+
CorrectEnumUsage st = new CorrectEnumUsage();
39+
st.setMode(Mode.Photo); // noMode -> photoMode
40+
st.takePhoto();
41+
st.resetMode(); // photoMode -> noMode
42+
st.setMode(Mode.Video); // noMode -> videoMode
43+
st.takeVideo();
44+
}
45+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package testSuite;
2+
3+
import liquidjava.specification.Refinement;
4+
5+
@SuppressWarnings("unused")
6+
class ErrorEnumFunctionRefinement {
7+
enum Color {
8+
Red, Green, Blue
9+
}
10+
11+
Color c;
12+
13+
Color changeColor(@Refinement("newColor == Color.Red || newColor == Color.Green") Color newColor) {
14+
c = newColor;
15+
return c;
16+
}
17+
18+
public static void main(String[] args) {
19+
ErrorEnumFunctionRefinement e = new ErrorEnumFunctionRefinement();
20+
e.changeColor(Color.Red);
21+
e.changeColor(Color.Blue); // Refinement Error
22+
}
23+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package testSuite;
2+
3+
import liquidjava.specification.Refinement;
4+
5+
@SuppressWarnings("unused")
6+
class ErrorEnumNegation {
7+
enum Status {
8+
Active, Inactive, Pending
9+
}
10+
11+
void process(@Refinement("status != Status.Inactive") Status status) {}
12+
13+
public static void main(String[] args) {
14+
ErrorEnumNegation e = new ErrorEnumNegation();
15+
e.process(Status.Active);
16+
e.process(Status.Inactive); // Refinement Error
17+
}
18+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package testSuite;
2+
3+
import liquidjava.specification.Refinement;
4+
5+
@SuppressWarnings("unused")
6+
class ErrorEnumNull {
7+
enum Color {
8+
Red, Green, Blue
9+
}
10+
11+
public static void main(String[] args) {
12+
@Refinement("c == Color.Red || c == Color.Green")
13+
Color c = null; // Refinement Error
14+
}
15+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package testSuite;
2+
3+
import liquidjava.specification.StateRefinement;
4+
import liquidjava.specification.StateSet;
5+
6+
@SuppressWarnings("unused")
7+
@StateSet({"photoMode", "videoMode", "noMode"})
8+
class ErrorEnumUsage {
9+
enum Mode {
10+
Photo, Video, Unknown
11+
}
12+
13+
Mode mode;
14+
@StateRefinement(to="noMode(this)")
15+
public ErrorEnumUsage() {}
16+
17+
@StateRefinement(from="noMode(this) && mode == Mode.Photo", to="photoMode(this)")
18+
@StateRefinement(from="noMode(this) && mode == Mode.Video", to="videoMode(this)")
19+
public void setMode(Mode mode) {
20+
this.mode = mode;
21+
}
22+
23+
@StateRefinement(from="photoMode(this)")
24+
public void takePhoto() {}
25+
26+
27+
public static void main(String[] args) {
28+
// Correct
29+
ErrorEnumUsage st = new ErrorEnumUsage();
30+
st.setMode(Mode.Video);
31+
st.takePhoto(); // State Refinement Error
32+
}
33+
}

liquidjava-verifier/src/main/antlr4/rj/grammar/RJ.g4

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,14 @@ literalExpression:
3838
| literal #lit
3939
| ID #var
4040
| functionCall #invocation
41+
| enumerate #enum
4142
;
4243

43-
functionCall:
44+
functionCall:
4445
ghostCall
4546
| aliasCall
46-
| dotCall;
47+
| dotCall
48+
;
4749

4850
dotCall:
4951
OBJECT_TYPE '(' args? ')'
@@ -55,6 +57,9 @@ ghostCall:
5557
aliasCall:
5658
ID_UPPER '(' args? ')';
5759

60+
enumerate:
61+
ENUM;
62+
5863
args: pred (',' pred)* ;
5964

6065

@@ -94,6 +99,7 @@ ARITHOP : '+'|'*'|'/'|'%';//|'-';
9499

95100
BOOL : 'true' | 'false';
96101
ID_UPPER: ([A-Z][a-zA-Z0-9]*);
102+
ENUM: [A-Z][a-zA-Z0-9_]* '.' [A-Z][a-zA-Z0-9_]*;
97103
OBJECT_TYPE:
98104
(([a-zA-Z][a-zA-Z0-9]+) ('.' [a-zA-Z][a-zA-Z0-9]*)+);
99105
ID : '#'*[a-zA-Z_][a-zA-Z0-9_#]*;

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,13 @@
77
import liquidjava.diagnostics.errors.LJError;
88
import liquidjava.processor.context.Context;
99
import liquidjava.processor.refinement_checker.general_checkers.MethodsFunctionsChecker;
10+
import liquidjava.rj_language.Predicate;
11+
import liquidjava.utils.constants.Formats;
12+
import liquidjava.utils.constants.Types;
1013
import spoon.reflect.declaration.CtClass;
1114
import spoon.reflect.declaration.CtConstructor;
15+
import spoon.reflect.declaration.CtEnum;
16+
import spoon.reflect.declaration.CtEnumValue;
1217
import spoon.reflect.declaration.CtInterface;
1318
import spoon.reflect.declaration.CtMethod;
1419
import spoon.reflect.declaration.CtType;
@@ -116,4 +121,15 @@ public <R> void visitCtMethod(CtMethod<R> method) {
116121
}
117122
context.exitContext();
118123
}
124+
125+
@Override
126+
public <T extends Enum<?>> void visitCtEnum(CtEnum<T> enumRead) {
127+
String enumName = enumRead.getSimpleName();
128+
String qualifiedEnumName = enumRead.getQualifiedName();
129+
for (CtEnumValue<?> ev : enumRead.getEnumValues()) {
130+
String varName = String.format(Formats.ENUM, enumName, ev.getSimpleName());
131+
context.addGlobalVariableToContext(varName, qualifiedEnumName, enumRead.getReference(), null);
132+
}
133+
super.visitCtEnum(enumRead);
134+
}
119135
}

0 commit comments

Comments
 (0)