Skip to content

Commit 6018353

Browse files
Multiple args (#49)
1 parent 69b00ca commit 6018353

File tree

8 files changed

+112
-42
lines changed

8 files changed

+112
-42
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ To run LiquidJava, use the Maven command below, replacing `/path/to/your/project
5555
```bash
5656
mvn exec:java -pl liquidjava-verifier -Dexec.mainClass="liquidjava.api.CommandLineLauncher" -Dexec.args="/path/to/your/project"
5757
```
58+
*Warning: Any change to LiquidJava requires rebuilding the jar.*
59+
5860

5961
If you're on Linux/macOS, you can use the `liquidjava` script (from the repository root) to simplify the process.
6062

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package testBooleanGhost;
2+
3+
import liquidjava.specification.Ghost;
4+
import liquidjava.specification.StateRefinement;
5+
6+
@Ghost("boolean opened")
7+
@Ghost("boolean closed")
8+
public class BooleanGhostClass {
9+
10+
boolean opened;
11+
boolean closed;
12+
13+
@StateRefinement(from = "!opened(this) && !closed(this)", to = "opened(this) && !closed(this)")
14+
void open() {
15+
opened = true;
16+
}
17+
18+
@StateRefinement(from = "opened(this) && !closed(this)")
19+
void execute() {
20+
// System.out.println("opened:" + open + "\nclosed::" + closed); // lança
21+
// exceção
22+
23+
System.out.println("opened: ");
24+
System.out.println(opened);
25+
System.out.println("\nclosed: ");
26+
System.out.println(closed);
27+
28+
}
29+
30+
@StateRefinement(from = "opened(this) && !closed(this)", to = "opened(this) && closed(this)")
31+
void close() {
32+
closed = true;
33+
}
34+
35+
@StateRefinement(from = "opened(this) && closed(this)")
36+
void terminate() {
37+
System.out.println("Terminating\n");
38+
}
39+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package testBooleanGhost;
2+
3+
public class BooleanGhostTest {
4+
public static void main(String[] args) {
5+
BooleanGhostClass bgc = new BooleanGhostClass();
6+
7+
bgc.open(); // ccomment out for error
8+
bgc.execute();
9+
bgc.close(); // comment out for error
10+
bgc.terminate();
11+
}
12+
}

liquidjava-verifier/src/main/java/liquidjava/api/CommandLineLauncher.java

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package liquidjava.api;
22

33
import java.io.File;
4-
4+
import java.util.Arrays;
5+
import java.util.List;
56
import liquidjava.errors.ErrorEmitter;
67
import liquidjava.processor.RefinementProcessor;
78
import spoon.Launcher;
@@ -12,35 +13,36 @@
1213

1314
public class CommandLineLauncher {
1415
public static void main(String[] args) {
15-
String allPath = "./liquidjava-example/src/main/java/test/currentlyTesting";
16-
1716
// String allPath = "C://Regen/test-projects/src/Main.java";
1817
// In eclipse only needed this:"../liquidjava-example/src/main/java/"
1918
// In VSCode needs:
2019
// "../liquidjava/liquidjava-umbrella/liquidjava-example/src/main/java/liquidjava/test/project";
21-
String path = args.length == 0 ? allPath : args[0];
22-
ErrorEmitter ee = launch(path);
20+
21+
if (args.length == 0) {
22+
System.out.println("No input files or directories provided");
23+
System.out.println("\nUsage: ./liquidjava <...paths>");
24+
System.out.println(" <...paths>: Paths to files or directories to be verified by LiquidJava");
25+
System.out.println(
26+
"\nExample: ./liquidjava liquidjava-example/src/main/java/test/currentlyTesting liquidjava-example/src/main/java/testingInProgress/Account.java");
27+
return;
28+
}
29+
List<String> paths = Arrays.asList(args);
30+
ErrorEmitter ee = launch(paths.toArray(new String[0]));
2331
System.out.println(ee.foundError() ? (ee.getFullMessage()) : ("Correct! Passed Verification."));
2432
}
2533

26-
public static ErrorEmitter launchTest(String path) {
27-
ErrorEmitter ee = launch(path);
28-
return ee;
29-
}
34+
public static ErrorEmitter launch(String... paths) {
35+
System.out.println("Running LiquidJava on: " + Arrays.toString(paths).replaceAll("[\\[\\]]", ""));
3036

31-
public static ErrorEmitter launch(String path) {
32-
System.out.println("Running LiquidJava on: " + path);
3337
ErrorEmitter ee = new ErrorEmitter();
34-
35-
// check if the path exists
36-
File f = new File(path);
37-
if (!f.exists()) {
38-
ee.addError("Path not found", "The path " + path + " does not exist", 1);
39-
return ee;
40-
}
41-
4238
Launcher launcher = new Launcher();
43-
launcher.addInputResource(path);
39+
for (String path : paths) {
40+
if (!new File(path).exists()) {
41+
ee.addError("Path not found", "The path " + path + " does not exist", 1);
42+
return ee;
43+
}
44+
launcher.addInputResource(path);
45+
}
4446
launcher.getEnvironment().setNoClasspath(true);
4547

4648
// Get the current classpath from the system
@@ -51,12 +53,10 @@ public static ErrorEmitter launch(String path) {
5153
// launcher.getEnvironment().setSourceClasspath(
5254
// "lib1.jar:lib2.jar".split(":"));
5355
launcher.getEnvironment().setComplianceLevel(8);
54-
5556
launcher.run();
5657

5758
final Factory factory = launcher.getFactory();
5859
final ProcessingManager processingManager = new QueueProcessingManager(factory);
59-
6060
final RefinementProcessor processor = new RefinementProcessor(factory, ee);
6161
processingManager.addProcessor(processor);
6262

liquidjava-verifier/src/main/java/liquidjava/errors/ErrorHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ public static void printCostumeError(CtElement element, String msg, ErrorEmitter
181181
sb.append(element + "\n\n");
182182
sb.append("Location: " + element.getPosition() + "\n");
183183
sb.append("______________________________________________________\n");
184-
184+
185185
errorl.addError(s, sb.toString(), element.getPosition(), 1);
186186
}
187187

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ private void createStateSet(CtNewArray<String> e, int set, CtElement element) {
119119
CtLiteral<String> s = (CtLiteral<String>) ce;
120120
String f = s.getValue();
121121
if (Character.isUpperCase(f.charAt(0))) {
122-
ErrorHandler.printCostumeError(s, "State name must start with lowercase in '" + f + "'", errorEmitter);
122+
ErrorHandler.printCostumeError(s, "State name must start with lowercase in '" + f + "'",
123+
errorEmitter);
123124
}
124125
}
125126
}

liquidjava-verifier/src/main/java/liquidjava/processor/refinement_checker/object_checkers/AuxStateHandler.java

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -551,24 +551,21 @@ private static String addInstanceWithState(TypeChecker tc, String superName, Str
551551
prevInstance.getRefinement(), invocation);
552552
// vi2.setState(transitionedState);
553553
vi2.setRefinement(transitionedState);
554-
RefinedVariable rv = superName != null ? tc.getContext().getVariableByName(superName) : null;
555-
if (rv != null) {
556-
// propagate supertypes from the refined variable
557-
for (CtTypeReference<?> t : rv.getSuperTypes())
554+
Context ctx = tc.getContext();
555+
if (ctx.hasVariable(superName)) {
556+
RefinedVariable rv = ctx.getVariableByName(superName);
557+
for (CtTypeReference<?> t : rv.getSuperTypes()) {
558558
vi2.addSuperType(t);
559-
} else {
560-
// propagate supertypes from the previous instance
561-
for (CtTypeReference<?> t : prevInstance.getSuperTypes())
562-
vi2.addSuperType(t);
563-
}
559+
}
564560

565-
// if the variable is a parent (not a VariableInstance) we need to check that
566-
// this refinement
567-
// is a subtype of the variable's main refinement
568-
if (rv instanceof Variable) {
569-
Predicate superC = rv.getMainRefinement().substituteVariable(rv.getName(), vi2.getName());
570-
tc.checkSMT(superC, invocation);
571-
tc.getContext().addRefinementInstanceToVariable(superName, name2);
561+
// if the variable is a parent (not a VariableInstance) we need to check that
562+
// this refinement
563+
// is a subtype of the variable's main refinement
564+
if (rv instanceof Variable) {
565+
Predicate superC = rv.getMainRefinement().substituteVariable(rv.getName(), vi2.getName());
566+
tc.checkSMT(superC, invocation);
567+
tc.getContext().addRefinementInstanceToVariable(superName, name2);
568+
}
572569
}
573570

574571
invocation.putMetadata(tc.TARGET_KEY, vi2);
@@ -634,4 +631,4 @@ private static List<CtAnnotation<? extends Annotation>> getStateAnnotation(CtEle
634631
// }
635632
// return l;
636633
}
637-
}
634+
}

liquidjava-verifier/src/test/java/liquidjava/api/tests/TestExamples.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import java.util.stream.Stream;
1010
import liquidjava.api.CommandLineLauncher;
1111
import liquidjava.errors.ErrorEmitter;
12+
13+
import org.junit.Test;
1214
import org.junit.jupiter.params.ParameterizedTest;
1315
import org.junit.jupiter.params.provider.MethodSource;
1416

@@ -27,7 +29,7 @@ public void testFile(final Path filePath) {
2729
String fileName = filePath.getFileName().toString();
2830

2931
// 1. Run the verifier on the file or package
30-
ErrorEmitter errorEmitter = CommandLineLauncher.launchTest(filePath.toAbsolutePath().toString());
32+
ErrorEmitter errorEmitter = CommandLineLauncher.launch(filePath.toAbsolutePath().toString());
3133

3234
// 2. Check if the file is correct or contains an error
3335
if ((fileName.startsWith("Correct") && errorEmitter.foundError())
@@ -68,4 +70,21 @@ private static Stream<Path> fileNameSource() throws IOException {
6870
return isFileStartingWithCorrectOrError || isDirectoryWithCorrectOrError;
6971
});
7072
}
73+
74+
/**
75+
* Test multiple paths at once, including both files and directories. This test ensures that the verifier can handle
76+
* multiple inputs correctly and that no errors are found in files/directories that are expected to be correct.
77+
*/
78+
@Test
79+
public void testMultiplePaths() {
80+
String[] paths = { "../liquidjava-example/src/main/java/testSuite/SimpleTest.java",
81+
"../liquidjava-example/src/main/java/testSuite/classes/arraylist_correct", };
82+
ErrorEmitter errorEmitter = CommandLineLauncher.launch(paths);
83+
84+
// Check if any of the paths that should be correct found an error
85+
if (errorEmitter.foundError()) {
86+
System.out.println("Error found in files that should be correct.");
87+
fail();
88+
}
89+
}
7190
}

0 commit comments

Comments
 (0)