Skip to content

Commit

Permalink
Adding a way to validate if a script is valid or not (#79)
Browse files Browse the repository at this point in the history
* Adding a way to validate if a script is valid or not

* Update readme
  • Loading branch information
machaval authored Mar 31, 2023
1 parent de6a1cd commit 28520c5
Show file tree
Hide file tree
Showing 11 changed files with 172 additions and 16 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ dw help
```

```bash
____ __ ____ __ _ _ ____ __ _ _ ____
____ __ ____ __ _ _ ____ __ _ _ ____
( \ / _\(_ _)/ _\ / )( \( __) / _\ / )( \( __)
) D (/ \ )( / \\ /\ / ) _) / \\ \/ / ) _)
(____/\_/\_/(__)\_/\_/(_/\_)(____)\_/\_/ \__/ (____)
Expand All @@ -94,7 +94,9 @@ Usage: <main class> [-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.
Expand Down
5 changes: 4 additions & 1 deletion native-cli/src/main/java/org/mule/weave/cli/DWCLI.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public static <A, B> Map<A, B> toScalaMap(java.util.Map<A, B> m) {
);
}

public String fileToString(File f) {
public static String fileToString(File f) {
try {
return Files.readString(f.toPath(), StandardCharsets.UTF_8);
} catch (IOException e) {
Expand All @@ -73,19 +73,19 @@ public Integer call() {
return doCall();
}

protected Option<DataWeaveVersion> calculateRuntimeVersion() {
public static Option<DataWeaveVersion> calculateRuntimeVersion(String languageLevel1, CommandLine.Model.CommandSpec spec1) {
Option<DataWeaveVersion> 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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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."

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ protected Integer doCall() {
Optional.ofNullable(inputs).map((s) -> toScalaMap(s)).orElse(Map$.MODULE$.<String, File>empty()),
Optional.ofNullable(literalInput).map((s) -> toScalaMap(s)).orElse(Map$.MODULE$.<String, String>empty()),
Option.apply(privileges).map((s) -> JavaConverters.asScalaBuffer(s).toSeq()),
calculateRuntimeVersion()
calculateRuntimeVersion(languageLevel, spec)
);
ReplCommand replCommand = new ReplCommand(replConfiguration, console);
return replCommand.exec();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@

@CommandLine.Command(
name = "run",
description =
"Runs provided DW script."

description = "Runs provided DW script."
)
public class PicoRunScript extends AbstractPicoRunCommand {

Expand Down Expand Up @@ -55,7 +53,7 @@ protected Integer doCall() {
throw new CommandLine.ParameterException(spec.commandLine(), msg);
}

Option<DataWeaveVersion> dataWeaveVersionOption = calculateRuntimeVersion();
Option<DataWeaveVersion> dataWeaveVersionOption = calculateRuntimeVersion(languageLevel, spec);
final WeaveRunnerConfig config = new WeaveRunnerConfig(
new String[0],
eval,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ protected Integer doCall() {
final SpellDependencyManager manager = new SpellDependencyManager(spellFolder, console);
final Function1<NativeRuntime, DependencyResolutionResult[]> resolver = (nr) -> manager.resolveDependencies(nr);

Option<DataWeaveVersion> dataWeaveVersionOption = calculateRuntimeVersion();
Option<DataWeaveVersion> dataWeaveVersionOption = calculateRuntimeVersion(languageLevel, spec);

final WeaveRunnerConfig config = WeaveRunnerConfig.apply(
new String[]{srcFolder.getAbsolutePath()},
Expand Down
Original file line number Diff line number Diff line change
@@ -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<Integer> {

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<DataWeaveVersion> 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();
}


}
21 changes: 21 additions & 0 deletions native-cli/src/main/java/org/mule/weave/cli/pico/PicoWizard.java
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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]
)

0 comments on commit 28520c5

Please sign in to comment.