From 28520c5abacf65ead8eccb4255731b7a2f682fa8 Mon Sep 17 00:00:00 2001 From: Mariano de Achaval Date: Fri, 31 Mar 2023 13:11:23 -0300 Subject: [PATCH] Adding a way to validate if a script is valid or not (#79) * Adding a way to validate if a script is valid or not * Update readme --- README.md | 6 +- .../main/java/org/mule/weave/cli/DWCLI.java | 5 +- .../cli/pico/AbstractPicoExecCommand.java | 10 +-- .../mule/weave/cli/pico/PicoAddWizard.java | 4 +- .../org/mule/weave/cli/pico/PicoRepl.java | 2 +- .../mule/weave/cli/pico/PicoRunScript.java | 6 +- .../org/mule/weave/cli/pico/PicoRunSpell.java | 2 +- .../weave/cli/pico/PicoValidateScript.java | 85 +++++++++++++++++++ .../org/mule/weave/cli/pico/PicoWizard.java | 21 +++++ .../mule/weave/dwnative/NativeRuntime.scala | 2 +- .../cli/commands/VerifyWeaveCommand.scala | 45 ++++++++++ 11 files changed, 172 insertions(+), 16 deletions(-) create mode 100644 native-cli/src/main/java/org/mule/weave/cli/pico/PicoValidateScript.java create mode 100644 native-cli/src/main/java/org/mule/weave/cli/pico/PicoWizard.java create mode 100644 native-cli/src/main/scala/org/mule/weave/dwnative/cli/commands/VerifyWeaveCommand.scala diff --git a/README.md b/README.md index 706153d..f60e2dd 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ dw help ``` ```bash - ____ __ ____ __ _ _ ____ __ _ _ ____ + ____ __ ____ __ _ _ ____ __ _ _ ____ ( \ / _\(_ _)/ _\ / )( \( __) / _\ / )( \( __) ) D (/ \ )( / \\ /\ / ) _) / \\ \/ / ) _) (____/\_/\_/(__)\_/\_/(_/\_)(____)\_/\_/ \__/ (____) @@ -94,7 +94,9 @@ Usage:
[-hV] [COMMAND] -V, --version Print version information and exit. Commands: run Runs provided DW script. - add-wizard Adds a new Wizard to your network of trusted wizards. + wizard Wizard actions. + add Adds a new Wizard to your network of trusted wizards. + validate Validate if a script is valid or not. migrate Translates a DW1 script into a DW2 script. spell Runs the specified Spell. create Creates a new spell with the given name. diff --git a/native-cli/src/main/java/org/mule/weave/cli/DWCLI.java b/native-cli/src/main/java/org/mule/weave/cli/DWCLI.java index c3166cf..48e4896 100644 --- a/native-cli/src/main/java/org/mule/weave/cli/DWCLI.java +++ b/native-cli/src/main/java/org/mule/weave/cli/DWCLI.java @@ -9,7 +9,9 @@ import org.mule.weave.cli.pico.PicoRunSpell; import org.mule.weave.cli.pico.PicoMigrate; import org.mule.weave.cli.pico.PicoUpdateSpells; +import org.mule.weave.cli.pico.PicoValidateScript; import org.mule.weave.cli.pico.PicoVersionProvider; +import org.mule.weave.cli.pico.PicoWizard; import org.mule.weave.dwnative.cli.Console; import org.mule.weave.dwnative.cli.DefaultConsole$; import picocli.CommandLine; @@ -44,7 +46,8 @@ public void run(String[] args, Console console) { mixinStandardHelpOptions = true, subcommands = { PicoRunScript.class, - PicoAddWizard.class, + PicoWizard.class, + PicoValidateScript.class, PicoMigrate.class, PicoRunSpell.class, CommandLine.HelpCommand.class, diff --git a/native-cli/src/main/java/org/mule/weave/cli/pico/AbstractPicoExecCommand.java b/native-cli/src/main/java/org/mule/weave/cli/pico/AbstractPicoExecCommand.java index f973bf4..490cec7 100644 --- a/native-cli/src/main/java/org/mule/weave/cli/pico/AbstractPicoExecCommand.java +++ b/native-cli/src/main/java/org/mule/weave/cli/pico/AbstractPicoExecCommand.java @@ -51,7 +51,7 @@ public static Map toScalaMap(java.util.Map m) { ); } - public String fileToString(File f) { + public static String fileToString(File f) { try { return Files.readString(f.toPath(), StandardCharsets.UTF_8); } catch (IOException e) { @@ -73,19 +73,19 @@ public Integer call() { return doCall(); } - protected Option calculateRuntimeVersion() { + public static Option calculateRuntimeVersion(String languageLevel1, CommandLine.Model.CommandSpec spec1) { Option dataWeaveVersionOption; try { - dataWeaveVersionOption = Option.apply(languageLevel).map((s) -> DataWeaveVersion.apply(s)); + dataWeaveVersionOption = Option.apply(languageLevel1).map((s) -> DataWeaveVersion.apply(s)); if (dataWeaveVersionOption.isDefined()) { DataWeaveVersion dataWeaveVersion = dataWeaveVersionOption.get(); DataWeaveVersion currentVersion = DataWeaveVersion.apply(); if (dataWeaveVersion.$greater(currentVersion)) { - throw new CommandLine.ParameterException(spec.commandLine(), "Invalid language level, cannot be higher than " + currentVersion.toString()); + throw new CommandLine.ParameterException(spec1.commandLine(), "Invalid language level, cannot be higher than " + currentVersion.toString()); } } } catch (NumberFormatException e) { - throw new CommandLine.ParameterException(spec.commandLine(), "Invalid language-level option value : `" + languageLevel + "`."); + throw new CommandLine.ParameterException(spec1.commandLine(), "Invalid language-level option value : `" + languageLevel1 + "`."); } return dataWeaveVersionOption; } diff --git a/native-cli/src/main/java/org/mule/weave/cli/pico/PicoAddWizard.java b/native-cli/src/main/java/org/mule/weave/cli/pico/PicoAddWizard.java index 539dd0e..ab28b7f 100644 --- a/native-cli/src/main/java/org/mule/weave/cli/pico/PicoAddWizard.java +++ b/native-cli/src/main/java/org/mule/weave/cli/pico/PicoAddWizard.java @@ -8,8 +8,10 @@ import java.util.concurrent.Callable; + + @CommandLine.Command( - name = "add-wizard", + name = "add", description = "Adds a new Wizard to your network of trusted wizards." diff --git a/native-cli/src/main/java/org/mule/weave/cli/pico/PicoRepl.java b/native-cli/src/main/java/org/mule/weave/cli/pico/PicoRepl.java index 1aa358f..d41b8aa 100644 --- a/native-cli/src/main/java/org/mule/weave/cli/pico/PicoRepl.java +++ b/native-cli/src/main/java/org/mule/weave/cli/pico/PicoRepl.java @@ -31,7 +31,7 @@ protected Integer doCall() { Optional.ofNullable(inputs).map((s) -> toScalaMap(s)).orElse(Map$.MODULE$.empty()), Optional.ofNullable(literalInput).map((s) -> toScalaMap(s)).orElse(Map$.MODULE$.empty()), Option.apply(privileges).map((s) -> JavaConverters.asScalaBuffer(s).toSeq()), - calculateRuntimeVersion() + calculateRuntimeVersion(languageLevel, spec) ); ReplCommand replCommand = new ReplCommand(replConfiguration, console); return replCommand.exec(); diff --git a/native-cli/src/main/java/org/mule/weave/cli/pico/PicoRunScript.java b/native-cli/src/main/java/org/mule/weave/cli/pico/PicoRunScript.java index 4bf5fe1..add645f 100644 --- a/native-cli/src/main/java/org/mule/weave/cli/pico/PicoRunScript.java +++ b/native-cli/src/main/java/org/mule/weave/cli/pico/PicoRunScript.java @@ -19,9 +19,7 @@ @CommandLine.Command( name = "run", - description = - "Runs provided DW script." - + description = "Runs provided DW script." ) public class PicoRunScript extends AbstractPicoRunCommand { @@ -55,7 +53,7 @@ protected Integer doCall() { throw new CommandLine.ParameterException(spec.commandLine(), msg); } - Option dataWeaveVersionOption = calculateRuntimeVersion(); + Option dataWeaveVersionOption = calculateRuntimeVersion(languageLevel, spec); final WeaveRunnerConfig config = new WeaveRunnerConfig( new String[0], eval, diff --git a/native-cli/src/main/java/org/mule/weave/cli/pico/PicoRunSpell.java b/native-cli/src/main/java/org/mule/weave/cli/pico/PicoRunSpell.java index eae5200..24f1fac 100644 --- a/native-cli/src/main/java/org/mule/weave/cli/pico/PicoRunSpell.java +++ b/native-cli/src/main/java/org/mule/weave/cli/pico/PicoRunSpell.java @@ -127,7 +127,7 @@ protected Integer doCall() { final SpellDependencyManager manager = new SpellDependencyManager(spellFolder, console); final Function1 resolver = (nr) -> manager.resolveDependencies(nr); - Option dataWeaveVersionOption = calculateRuntimeVersion(); + Option dataWeaveVersionOption = calculateRuntimeVersion(languageLevel, spec); final WeaveRunnerConfig config = WeaveRunnerConfig.apply( new String[]{srcFolder.getAbsolutePath()}, diff --git a/native-cli/src/main/java/org/mule/weave/cli/pico/PicoValidateScript.java b/native-cli/src/main/java/org/mule/weave/cli/pico/PicoValidateScript.java new file mode 100644 index 0000000..d22a902 --- /dev/null +++ b/native-cli/src/main/java/org/mule/weave/cli/pico/PicoValidateScript.java @@ -0,0 +1,85 @@ +package org.mule.weave.cli.pico; + +import org.mule.weave.dwnative.cli.Console; +import org.mule.weave.dwnative.cli.DefaultConsole$; +import org.mule.weave.dwnative.cli.commands.VerifyWeaveCommand; +import org.mule.weave.dwnative.cli.commands.WeaveModule; +import org.mule.weave.dwnative.cli.commands.WeaveVerifyConfig; +import org.mule.weave.v2.io.FileHelper; +import org.mule.weave.v2.parser.ast.variables.NameIdentifier; +import org.mule.weave.v2.utils.DataWeaveVersion; +import picocli.CommandLine; +import scala.Option; + +import java.io.File; +import java.util.concurrent.Callable; + +import static org.mule.weave.cli.pico.AbstractPicoExecCommand.calculateRuntimeVersion; +import static org.mule.weave.cli.pico.AbstractPicoExecCommand.fileToString; + +@CommandLine.Command( + name = "validate", + description = "Validate if a script is valid or not." +) +public class PicoValidateScript implements Callable { + + Console console; + + @CommandLine.Option(names = {"--language-level"}, description = {"The version of DW to be supported."}) + protected String languageLevel = null; + + @CommandLine.Parameters( + index = "0", + arity = "0..1", + description = "The DW script to be used", + paramLabel = "SCRIPT" + ) + String script = null; + + @CommandLine.Option(names = {"--file", "-f"}, description = "The Path to the dw file to run.") + File dwFile = null; + + @CommandLine.Option(names = {"--input", "-i"}, description = "The name of an in implicit input.") + String[] inputs = new String[0]; + + @CommandLine.Spec + CommandLine.Model.CommandSpec spec = null; + + + public PicoValidateScript() { + this.console = DefaultConsole$.MODULE$; + } + + public PicoValidateScript(Console console) { + this.console = console; + } + + @Override + public Integer call() { + if ((script == null && dwFile == null) || (script != null && dwFile != null)) { + String msg = "The script and file parameters are mutually exclusive, but one is required."; + throw new CommandLine.ParameterException(spec.commandLine(), msg); + } + Option dataWeaveVersionOption = calculateRuntimeVersion(languageLevel, spec); + + WeaveVerifyConfig config = new WeaveVerifyConfig( + + ((nr) -> { + if (script != null) { + return new WeaveModule(script, NameIdentifier.ANONYMOUS_NAME().name()); + } else if (dwFile != null) { + return new WeaveModule(fileToString(dwFile), FileHelper.baseName(dwFile)); + } else { + throw new RuntimeException("Missing dw script or main file"); + } + }), + dataWeaveVersionOption, + inputs + + ); + final VerifyWeaveCommand command = new VerifyWeaveCommand(config, console); + return command.exec(); + } + + +} diff --git a/native-cli/src/main/java/org/mule/weave/cli/pico/PicoWizard.java b/native-cli/src/main/java/org/mule/weave/cli/pico/PicoWizard.java new file mode 100644 index 0000000..ad869c9 --- /dev/null +++ b/native-cli/src/main/java/org/mule/weave/cli/pico/PicoWizard.java @@ -0,0 +1,21 @@ +package org.mule.weave.cli.pico; + +import picocli.CommandLine; + +@CommandLine.Command( + name = "wizard", + description = "Wizard actions.", + subcommands = { + PicoAddWizard.class + } +) +public class PicoWizard implements Runnable { + + @CommandLine.Spec + CommandLine.Model.CommandSpec spec; + + @Override + public void run() { + spec.commandLine().usage(System.out); + } +} diff --git a/native-cli/src/main/scala/org/mule/weave/dwnative/NativeRuntime.scala b/native-cli/src/main/scala/org/mule/weave/dwnative/NativeRuntime.scala index 4742432..ef98306 100644 --- a/native-cli/src/main/scala/org/mule/weave/dwnative/NativeRuntime.scala +++ b/native-cli/src/main/scala/org/mule/weave/dwnative/NativeRuntime.scala @@ -101,7 +101,7 @@ class NativeRuntime(libDir: File, path: Array[File], console: Console, maybeLang } } - private def compileScript(script: String, inputs: ScriptingBindings, nameIdentifier: NameIdentifier, defaultOutputMimeType: String) = { + def compileScript(script: String, inputs: ScriptingBindings, nameIdentifier: NameIdentifier, defaultOutputMimeType: String): DataWeaveScript = { var config = weaveScriptingEngine.newConfig() .withScript(script) .withInputs(inputs.entries().map(wi => new InputType(wi, None)).toArray) diff --git a/native-cli/src/main/scala/org/mule/weave/dwnative/cli/commands/VerifyWeaveCommand.scala b/native-cli/src/main/scala/org/mule/weave/dwnative/cli/commands/VerifyWeaveCommand.scala new file mode 100644 index 0000000..591da53 --- /dev/null +++ b/native-cli/src/main/scala/org/mule/weave/dwnative/cli/commands/VerifyWeaveCommand.scala @@ -0,0 +1,45 @@ +package org.mule.weave.dwnative.cli.commands + +import org.mule.weave.dwnative.NativeRuntime +import org.mule.weave.dwnative.cli.Console +import org.mule.weave.dwnative.utils.DataWeaveUtils +import org.mule.weave.v2.parser.ast.variables.NameIdentifier +import org.mule.weave.v2.parser.phase.CompilationException +import org.mule.weave.v2.runtime.ScriptingBindings +import org.mule.weave.v2.utils.DataWeaveVersion + +class VerifyWeaveCommand(val config: WeaveVerifyConfig, console: Console) extends WeaveCommand { + val weaveUtils = new DataWeaveUtils(console) + + def exec(): Int = { + var exitCode: Int = ExitCodes.SUCCESS + val nativeRuntime: NativeRuntime = new NativeRuntime(weaveUtils.getLibPathHome(), Array(), console, config.maybeLanguageLevel) + val weaveModule = config.scriptToRun(nativeRuntime) + try { + console.info(s"Compiling `${weaveModule.nameIdentifier}`...") + val bindings = ScriptingBindings() + config.inputs.foreach((input) => { + bindings.addBinding(input, "") + }) + nativeRuntime.compileScript(weaveModule.content, bindings, NameIdentifier(weaveModule.nameIdentifier), "") + console.info(s"No errors found.") + } catch { + case ce: CompilationException => { + val ee = ce.getErrorMessages() + ee.foreach((em) => { + console.error(em) + }) + console.info(s"${ee.length} errors found") + exitCode = ExitCodes.FAILURE + } + } + exitCode + } +} + +case class WeaveVerifyConfig( + scriptToRun: NativeRuntime => WeaveModule, + maybeLanguageLevel: Option[DataWeaveVersion], + inputs: Array[String] + ) +