diff --git a/liquidjava-verifier/pom.xml b/liquidjava-verifier/pom.xml index 43aa8422..f77a5e11 100644 --- a/liquidjava-verifier/pom.xml +++ b/liquidjava-verifier/pom.xml @@ -319,6 +319,11 @@ 2.10.1 + + info.picocli + picocli + 4.7.7 + diff --git a/liquidjava-verifier/src/main/java/liquidjava/api/CommandLineArgs.java b/liquidjava-verifier/src/main/java/liquidjava/api/CommandLineArgs.java new file mode 100644 index 00000000..9fe7d6d0 --- /dev/null +++ b/liquidjava-verifier/src/main/java/liquidjava/api/CommandLineArgs.java @@ -0,0 +1,20 @@ +package liquidjava.api; + +import java.util.List; +import java.util.concurrent.Callable; + +import picocli.CommandLine.Command; +import picocli.CommandLine.Option; +import picocli.CommandLine.Parameters; + +@Command(name = "liquidjava", mixinStandardHelpOptions = false, customSynopsis = "./liquidjava <...paths> ") +public class CommandLineArgs { + @Option(names = {"-h", "--help"}, usageHelp = true, description = "Display this help message") + public boolean help; + + @Option(names = { "-d", "--debug" }, description = "Enable debug mode for more detailed output") + public boolean debugMode; + + @Parameters(arity = "1..*", paramLabel = "<...paths>", description = "Paths to be verified by LiquidJava") + public List paths; +} diff --git a/liquidjava-verifier/src/main/java/liquidjava/api/CommandLineLauncher.java b/liquidjava-verifier/src/main/java/liquidjava/api/CommandLineLauncher.java index e473562c..796928c8 100644 --- a/liquidjava-verifier/src/main/java/liquidjava/api/CommandLineLauncher.java +++ b/liquidjava-verifier/src/main/java/liquidjava/api/CommandLineLauncher.java @@ -2,13 +2,13 @@ import java.io.File; import java.util.Arrays; -import java.util.List; import liquidjava.diagnostics.Diagnostics; import liquidjava.diagnostics.errors.CustomError; import liquidjava.diagnostics.warnings.CustomWarning; import liquidjava.processor.RefinementProcessor; import liquidjava.processor.context.ContextHistory; +import picocli.CommandLine; import spoon.Launcher; import spoon.compiler.Environment; import spoon.processing.ProcessingManager; @@ -20,18 +20,18 @@ public class CommandLineLauncher { private static final Diagnostics diagnostics = Diagnostics.getInstance(); private static final ContextHistory contextHistory = ContextHistory.getInstance(); + public static final CommandLineArgs cmdArgs = new CommandLineArgs(); public static void main(String[] args) { - if (args.length == 0) { - System.out.println("No input paths provided"); - System.out.println("\nUsage: ./liquidjava <...paths>"); - System.out.println(" <...paths>: Paths to be verified by LiquidJava"); - System.out.println( - "\nExample: ./liquidjava liquidjava-example/src/main/java/test liquidjava-example/src/main/java/testingInProgress/Account.java"); + CommandLine cmd = new CommandLine(cmdArgs); + cmd.parseArgs(args); + + if (cmd.isUsageHelpRequested()) { + cmd.usage(System.out); return; } - List paths = Arrays.asList(args); - launch(paths.toArray(new String[0])); + + launch(cmdArgs.paths.stream().toArray(String[]::new)); // print diagnostics if (diagnostics.foundWarning()) { @@ -39,9 +39,10 @@ public static void main(String[] args) { } if (diagnostics.foundError()) { System.out.println(diagnostics.getErrorOutput()); - } else { - System.out.println("Correct! Passed Verification."); + return; } + + System.out.println("Correct! Passed Verification."); } public static void launch(String... paths) { diff --git a/liquidjava-verifier/src/main/java/liquidjava/diagnostics/errors/RefinementError.java b/liquidjava-verifier/src/main/java/liquidjava/diagnostics/errors/RefinementError.java index 39a81d92..a1ba3c3c 100644 --- a/liquidjava-verifier/src/main/java/liquidjava/diagnostics/errors/RefinementError.java +++ b/liquidjava-verifier/src/main/java/liquidjava/diagnostics/errors/RefinementError.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.stream.Collectors; +import liquidjava.api.CommandLineLauncher; import liquidjava.diagnostics.TranslationTable; import liquidjava.rj_language.opt.derivation_node.ValDerivationNode; import liquidjava.smt.Counterexample; @@ -48,7 +49,7 @@ public String getCounterExampleString() { found.getValue().getVariableNames(foundVarNames); String counterexampleString = counterexample.assignments().stream() // only include variables that appear in the found value - .filter(a -> foundVarNames.contains(a.first())) + .filter(a -> CommandLineLauncher.cmdArgs.debugMode || foundVarNames.contains(a.first())) // format as "var == value" .map(a -> VariableFormatter.formatVariable(a.first()) + " == " + a.second()) // join with "&&" diff --git a/liquidjava-verifier/src/main/java/liquidjava/processor/refinement_checker/VCChecker.java b/liquidjava-verifier/src/main/java/liquidjava/processor/refinement_checker/VCChecker.java index d757f2a7..80014606 100644 --- a/liquidjava-verifier/src/main/java/liquidjava/processor/refinement_checker/VCChecker.java +++ b/liquidjava-verifier/src/main/java/liquidjava/processor/refinement_checker/VCChecker.java @@ -10,6 +10,7 @@ import java.util.stream.Collectors; import liquidjava.diagnostics.errors.*; +import liquidjava.api.CommandLineLauncher; import liquidjava.diagnostics.TranslationTable; import liquidjava.processor.VCImplication; import liquidjava.processor.context.*; @@ -22,6 +23,7 @@ import liquidjava.smt.SMTResult; import liquidjava.utils.Utils; import liquidjava.utils.constants.Keys; +import liquidjava.utils.Utils; import spoon.reflect.cu.SourcePosition; import spoon.reflect.declaration.CtElement; import spoon.reflect.factory.Factory; @@ -102,6 +104,12 @@ public void processSubtyping(Predicate type, Predicate expectedType, List