mirror of
https://github.com/apple/pkl.git
synced 2026-04-24 17:28:37 +02:00
Fix command error and import handling (#1436)
This commit is contained in:
@@ -819,14 +819,25 @@ class CliCommandRunnerTest {
|
|||||||
val moduleUri =
|
val moduleUri =
|
||||||
writePklFile(
|
writePklFile(
|
||||||
"cmd.pkl",
|
"cmd.pkl",
|
||||||
renderOptions +
|
"""
|
||||||
"""
|
extends "pkl:Command"
|
||||||
|
|
||||||
|
options: Options
|
||||||
|
|
||||||
|
output {
|
||||||
|
value = (options) {
|
||||||
|
fromImport {
|
||||||
|
baz = true // assert that imported modules are not forced
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class Options {
|
class Options {
|
||||||
@Argument { convert = (it) -> new Import{ uri = it } }
|
@Argument { convert = (it) -> new Import{ uri = it } }
|
||||||
fromImport: Module
|
fromImport: Module
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
.trimIndent(),
|
.trimIndent(),
|
||||||
)
|
)
|
||||||
|
|
||||||
val importUri =
|
val importUri =
|
||||||
@@ -835,6 +846,7 @@ class CliCommandRunnerTest {
|
|||||||
"""
|
"""
|
||||||
foo = 1
|
foo = 1
|
||||||
bar = "baz"
|
bar = "baz"
|
||||||
|
baz: Boolean
|
||||||
"""
|
"""
|
||||||
.trimIndent(),
|
.trimIndent(),
|
||||||
)
|
)
|
||||||
@@ -847,6 +859,7 @@ class CliCommandRunnerTest {
|
|||||||
fromImport {
|
fromImport {
|
||||||
foo = 1
|
foo = 1
|
||||||
bar = "baz"
|
bar = "baz"
|
||||||
|
baz = true
|
||||||
}
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -866,7 +879,13 @@ class CliCommandRunnerTest {
|
|||||||
options: Options
|
options: Options
|
||||||
|
|
||||||
output {
|
output {
|
||||||
value = options
|
value = (options) {
|
||||||
|
fromGlobImport {
|
||||||
|
[[true]] {
|
||||||
|
baz = true // assert that imported modules are not forced
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Options {
|
class Options {
|
||||||
@@ -883,6 +902,7 @@ class CliCommandRunnerTest {
|
|||||||
"""
|
"""
|
||||||
foo: Int
|
foo: Int
|
||||||
bar: String
|
bar: String
|
||||||
|
baz: Boolean
|
||||||
"""
|
"""
|
||||||
.trimIndent(),
|
.trimIndent(),
|
||||||
)
|
)
|
||||||
@@ -919,10 +939,12 @@ class CliCommandRunnerTest {
|
|||||||
["file:/<dir>/glob1.pkl"] {
|
["file:/<dir>/glob1.pkl"] {
|
||||||
foo = 1
|
foo = 1
|
||||||
bar = "baz"
|
bar = "baz"
|
||||||
|
baz = true
|
||||||
}
|
}
|
||||||
["file:/<dir>/glob2.pkl"] {
|
["file:/<dir>/glob2.pkl"] {
|
||||||
foo = 2
|
foo = 2
|
||||||
bar = "qux"
|
bar = "qux"
|
||||||
|
baz = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ class CliCommandTest {
|
|||||||
amends "pkl:Project"
|
amends "pkl:Project"
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
["foo"] = import("$depDir/PklProject")
|
["foo"] = import("${depDir.toUri().resolve("PklProject")}")
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
.trimIndent()
|
.trimIndent()
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ public final class CommandSpecParser {
|
|||||||
// instance of CommandSpec.State previously returned from a prior invocation
|
// instance of CommandSpec.State previously returned from a prior invocation
|
||||||
// of CommandSpec.apply.
|
// of CommandSpec.apply.
|
||||||
parent == null ? null : (SubcommandState) parent.contents()),
|
parent == null ? null : (SubcommandState) parent.contents()),
|
||||||
(it) -> evaluateResult(command, (SubcommandState) it)));
|
(it) -> handleErrors(() -> evaluateResult(command, (SubcommandState) it))));
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<CommandSpec> collectSubcommands(VmTyped commandInfo) {
|
private List<CommandSpec> collectSubcommands(VmTyped commandInfo) {
|
||||||
@@ -488,12 +488,12 @@ public final class CommandSpecParser {
|
|||||||
? null
|
? null
|
||||||
: VmUtils.readMember(annotation, Identifier.CONVERT) instanceof VmFunction func
|
: VmUtils.readMember(annotation, Identifier.CONVERT) instanceof VmFunction func
|
||||||
? (rawValue, workingDirUri) ->
|
? (rawValue, workingDirUri) ->
|
||||||
handleErrors(() -> handleImports(func.apply(rawValue), workingDirUri))
|
handleBadValue(() -> handleImports(func.apply(rawValue), workingDirUri))
|
||||||
: null,
|
: null,
|
||||||
annotation == null
|
annotation == null
|
||||||
? null
|
? null
|
||||||
: VmUtils.readMember(annotation, Identifier.TRANSFORM_ALL) instanceof VmFunction func
|
: VmUtils.readMember(annotation, Identifier.TRANSFORM_ALL) instanceof VmFunction func
|
||||||
? (it) -> handleErrors(() -> func.apply(VmList.create(it)))
|
? (it) -> handleBadValue(() -> func.apply(VmList.create(it)))
|
||||||
: null,
|
: null,
|
||||||
annotation == null
|
annotation == null
|
||||||
? null
|
? null
|
||||||
@@ -957,7 +957,6 @@ public final class CommandSpecParser {
|
|||||||
private SubcommandState buildExecutionModule(
|
private SubcommandState buildExecutionModule(
|
||||||
VmTyped module, VmTyped options, @Nullable SubcommandState parent) {
|
VmTyped module, VmTyped options, @Nullable SubcommandState parent) {
|
||||||
EconomicMap<Object, ObjectMember> properties = EconomicMaps.create(parent != null ? 2 : 1);
|
EconomicMap<Object, ObjectMember> properties = EconomicMaps.create(parent != null ? 2 : 1);
|
||||||
options.force(false, true);
|
|
||||||
properties.put(
|
properties.put(
|
||||||
Identifier.OPTIONS, VmUtils.createSyntheticObjectProperty(Identifier.OPTIONS, "", options));
|
Identifier.OPTIONS, VmUtils.createSyntheticObjectProperty(Identifier.OPTIONS, "", options));
|
||||||
|
|
||||||
@@ -1079,31 +1078,35 @@ public final class CommandSpecParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle errors from convert/transformAll and correctly format them for the CLI
|
// handle errors from convert/transformAll and correctly format them for the CLI
|
||||||
private Object handleErrors(Supplier<Object> f) {
|
private Object handleBadValue(Supplier<Object> f) {
|
||||||
try {
|
try {
|
||||||
try {
|
return handleErrors(f);
|
||||||
return f.get();
|
|
||||||
} catch (VmStackOverflowException e) {
|
|
||||||
if (VmUtils.isPklBug(e)) {
|
|
||||||
throw new VmExceptionBuilder()
|
|
||||||
.bug("Stack overflow")
|
|
||||||
.withCause(e.getCause())
|
|
||||||
.build()
|
|
||||||
.toPklException(frameTransformer, color);
|
|
||||||
}
|
|
||||||
throw e.toPklException(frameTransformer, color);
|
|
||||||
} catch (VmException e) {
|
|
||||||
throw e.toPklException(frameTransformer, color);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new PklBugException(e);
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
// add a newline so this prints nicely under "Error: invalid value for <name>:"
|
// add a newline so this prints nicely under "Error: invalid value for <name>:"
|
||||||
throw new BadValue("\n" + e.getMessage());
|
throw new BadValue("\n" + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// for convert handle imports by replace Command.Import values
|
private <T> T handleErrors(Supplier<T> f) {
|
||||||
|
try {
|
||||||
|
return f.get();
|
||||||
|
} catch (VmStackOverflowException e) {
|
||||||
|
if (VmUtils.isPklBug(e)) {
|
||||||
|
throw new VmExceptionBuilder()
|
||||||
|
.bug("Stack overflow")
|
||||||
|
.withCause(e.getCause())
|
||||||
|
.build()
|
||||||
|
.toPklException(frameTransformer, color);
|
||||||
|
}
|
||||||
|
throw e.toPklException(frameTransformer, color);
|
||||||
|
} catch (VmException e) {
|
||||||
|
throw e.toPklException(frameTransformer, color);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new PklBugException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// for convert, handle imports by replacing Command.Import values
|
||||||
// with imported module or Mapping<String, Module> values
|
// with imported module or Mapping<String, Module> values
|
||||||
// Command.Import instances in returned Pair, List, Set, or Map values are replaced as well
|
// Command.Import instances in returned Pair, List, Set, or Map values are replaced as well
|
||||||
// other types or nested instances of the above are not affected
|
// other types or nested instances of the above are not affected
|
||||||
@@ -1158,13 +1161,13 @@ public final class CommandSpecParser {
|
|||||||
try {
|
try {
|
||||||
// Can't just use URI constructor, because URI(null, null, "C:/foo/bar", null) turns
|
// Can't just use URI constructor, because URI(null, null, "C:/foo/bar", null) turns
|
||||||
// into `URI("C", null, "/foo/bar", null)`.
|
// into `URI("C", null, "/foo/bar", null)`.
|
||||||
var modulePath = Path.of(moduleName);
|
@SuppressWarnings("DuplicateExpressions")
|
||||||
var uri =
|
var uri =
|
||||||
IoUtils.isUriLike(moduleName)
|
IoUtils.isUriLike(moduleName)
|
||||||
? new URI(moduleName)
|
? new URI(moduleName)
|
||||||
: IoUtils.isWindowsAbsolutePath(moduleName)
|
: IoUtils.isWindowsAbsolutePath(moduleName)
|
||||||
? modulePath.toUri()
|
? Path.of(moduleName).toUri()
|
||||||
: new URI(null, null, IoUtils.toNormalizedPathString(modulePath), null);
|
: new URI(null, null, IoUtils.toNormalizedPathString(Path.of(moduleName)), null);
|
||||||
uriString =
|
uriString =
|
||||||
uri.isAbsolute() ? uri.toString() : IoUtils.resolve(workingDirUri, uri).toString();
|
uri.isAbsolute() ? uri.toString() : IoUtils.resolve(workingDirUri, uri).toString();
|
||||||
} catch (URISyntaxException e) {
|
} catch (URISyntaxException e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user