Skip to content

Commit f790481

Browse files
authored
CLI flags (#187)
1 parent c68a166 commit f790481

File tree

8 files changed

+92
-14
lines changed

8 files changed

+92
-14
lines changed

liquidjava-verifier/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,11 @@
319319
<version>2.10.1</version>
320320
</dependency>
321321

322+
<dependency>
323+
<groupId>info.picocli</groupId>
324+
<artifactId>picocli</artifactId>
325+
<version>4.7.7</version>
326+
</dependency>
322327
</dependencies>
323328
<dependencyManagement>
324329
<dependencies>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package liquidjava.api;
2+
3+
import java.io.FileReader;
4+
import java.nio.file.Path;
5+
import java.util.List;
6+
7+
import org.apache.maven.model.Model;
8+
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
9+
10+
import picocli.CommandLine.Command;
11+
import picocli.CommandLine.Option;
12+
import picocli.CommandLine.Parameters;
13+
14+
@Command(name = "liquidjava", mixinStandardHelpOptions = false, customSynopsis = "./liquidjava <...paths> <options>")
15+
public class CommandLineArgs {
16+
@Option(names = {"-h", "--help"}, usageHelp = true, description = "Display this help message")
17+
public boolean help;
18+
19+
@Option(names = { "-v", "--version" }, versionHelp = true, description = "Display the version of LiquidJava")
20+
public boolean version;
21+
22+
@Option(names = { "-d", "--debug" }, description = "Enable debug mode for more detailed output")
23+
public boolean debugMode;
24+
25+
@Parameters(arity = "1..*", paramLabel = "<...paths>", description = "Paths to be verified by LiquidJava")
26+
public List<String> paths;
27+
28+
public String getVersionString() {
29+
Path pomPath = Path.of("liquidjava-verifier", "pom.xml");
30+
try (FileReader fileReader = new FileReader(pomPath.toFile())) {
31+
Model model = new MavenXpp3Reader().read(fileReader);
32+
return model.getVersion();
33+
} catch (Exception ignored) {
34+
return "unknown";
35+
}
36+
}
37+
}

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

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
import java.io.File;
44
import java.util.Arrays;
5-
import java.util.List;
65

76
import liquidjava.diagnostics.Diagnostics;
87
import liquidjava.diagnostics.errors.CustomError;
98
import liquidjava.diagnostics.warnings.CustomWarning;
109
import liquidjava.processor.RefinementProcessor;
1110
import liquidjava.processor.context.ContextHistory;
11+
import picocli.CommandLine;
1212
import spoon.Launcher;
1313
import spoon.compiler.Environment;
1414
import spoon.processing.ProcessingManager;
@@ -20,28 +20,34 @@ public class CommandLineLauncher {
2020

2121
private static final Diagnostics diagnostics = Diagnostics.getInstance();
2222
private static final ContextHistory contextHistory = ContextHistory.getInstance();
23+
public static final CommandLineArgs cmdArgs = new CommandLineArgs();
2324

2425
public static void main(String[] args) {
25-
if (args.length == 0) {
26-
System.out.println("No input paths provided");
27-
System.out.println("\nUsage: ./liquidjava <...paths>");
28-
System.out.println(" <...paths>: Paths to be verified by LiquidJava");
29-
System.out.println(
30-
"\nExample: ./liquidjava liquidjava-example/src/main/java/test liquidjava-example/src/main/java/testingInProgress/Account.java");
26+
CommandLine cmd = new CommandLine(cmdArgs);
27+
cmd.parseArgs(args);
28+
29+
if (cmd.isUsageHelpRequested()) {
30+
cmd.usage(System.out);
31+
return;
32+
}
33+
34+
if (cmd.isVersionHelpRequested()) {
35+
System.out.println("liquidjava " + cmdArgs.getVersionString());
3136
return;
3237
}
33-
List<String> paths = Arrays.asList(args);
34-
launch(paths.toArray(new String[0]));
38+
39+
launch(cmdArgs.paths.stream().toArray(String[]::new));
3540

3641
// print diagnostics
3742
if (diagnostics.foundWarning()) {
3843
System.out.println(diagnostics.getWarningOutput());
3944
}
4045
if (diagnostics.foundError()) {
4146
System.out.println(diagnostics.getErrorOutput());
42-
} else {
43-
System.out.println("Correct! Passed Verification.");
47+
return;
4448
}
49+
50+
System.out.println("Correct! Passed Verification.");
4551
}
4652

4753
public static void launch(String... paths) {

liquidjava-verifier/src/main/java/liquidjava/diagnostics/errors/RefinementError.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.util.List;
55
import java.util.stream.Collectors;
66

7+
import liquidjava.api.CommandLineLauncher;
78
import liquidjava.diagnostics.TranslationTable;
89
import liquidjava.rj_language.opt.derivation_node.ValDerivationNode;
910
import liquidjava.smt.Counterexample;
@@ -48,7 +49,7 @@ public String getCounterExampleString() {
4849
found.getValue().getVariableNames(foundVarNames);
4950
String counterexampleString = counterexample.assignments().stream()
5051
// only include variables that appear in the found value
51-
.filter(a -> foundVarNames.contains(a.first()))
52+
.filter(a -> CommandLineLauncher.cmdArgs.debugMode || foundVarNames.contains(a.first()))
5253
// format as "var == value"
5354
.map(a -> VariableFormatter.formatVariable(a.first()) + " == " + a.second())
5455
// join with "&&"

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import java.util.stream.Collectors;
1111

1212
import liquidjava.diagnostics.errors.*;
13+
import liquidjava.api.CommandLineLauncher;
1314
import liquidjava.diagnostics.TranslationTable;
1415
import liquidjava.processor.VCImplication;
1516
import liquidjava.processor.context.*;
@@ -22,6 +23,7 @@
2223
import liquidjava.smt.SMTResult;
2324
import liquidjava.utils.Utils;
2425
import liquidjava.utils.constants.Keys;
26+
import liquidjava.utils.Utils;
2527
import spoon.reflect.cu.SourcePosition;
2628
import spoon.reflect.declaration.CtElement;
2729
import spoon.reflect.factory.Factory;
@@ -102,6 +104,12 @@ public void processSubtyping(Predicate type, Predicate expectedType, List<GhostS
102104
*/
103105
public SMTResult verifySMTSubtype(Predicate expected, Predicate found, SourcePosition position) throws LJError {
104106
try {
107+
if (CommandLineLauncher.cmdArgs.debugMode) {
108+
String exp = Utils.getExpressionFromPosition(position);
109+
System.out.println(String.format("%s <: %s %s at %s", expected, found,
110+
exp != null ? String.format("on expression '%s'", exp) : "",
111+
position.getFile().getName() + ":" + position.getLine()));
112+
}
105113
return new SMTEvaluator().verifySubtype(found, expected, context);
106114
} catch (LJError e) {
107115
if (e.getPosition() == null) {

liquidjava-verifier/src/main/java/liquidjava/rj_language/Predicate.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.util.Map;
77
import java.util.stream.Collectors;
88

9+
import liquidjava.api.CommandLineLauncher;
910
import liquidjava.diagnostics.errors.LJError;
1011
import liquidjava.processor.context.AliasWrapper;
1112
import liquidjava.processor.context.Context;
@@ -207,6 +208,9 @@ public ValDerivationNode simplify(Context context) {
207208
for (AliasWrapper aw : context.getAliases()) {
208209
aliases.put(aw.getName(), aw.createAliasDTO());
209210
}
211+
if (CommandLineLauncher.cmdArgs.debugMode) {
212+
return new ValDerivationNode(exp.clone(), null);
213+
}
210214
// simplify expression
211215
return ExpressionSimplifier.simplify(exp.clone(), aliases);
212216
}

liquidjava-verifier/src/main/java/liquidjava/smt/SMTEvaluator.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package liquidjava.smt;
22

3-
import java.util.Set;
4-
53
import com.martiansoftware.jsap.SyntaxException;
64
import com.microsoft.z3.Expr;
75
import com.microsoft.z3.Model;

liquidjava-verifier/src/main/java/liquidjava/utils/Utils.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.List;
44
import java.util.Map;
5+
import java.util.Scanner;
56
import java.util.Set;
67
import java.util.stream.Stream;
78

@@ -108,4 +109,22 @@ public static SourcePosition getRealPosition(CtElement element) {
108109
}
109110
return element.getPosition();
110111
}
112+
113+
public static String getExpressionFromPosition(SourcePosition position) {
114+
if (position == null || position.getFile() == null)
115+
return null;
116+
try (Scanner scanner = new Scanner(position.getFile())) {
117+
int currentLine = 1;
118+
while (scanner.hasNextLine()) {
119+
String line = scanner.nextLine();
120+
if (currentLine == position.getLine()) {
121+
return line.substring(position.getColumn() - 2).trim();
122+
}
123+
currentLine++;
124+
}
125+
} catch (Exception e) {
126+
// ignore
127+
}
128+
return null;
129+
}
111130
}

0 commit comments

Comments
 (0)