From 0f054d5c1080d42328ff516a241b861dd84f5dee Mon Sep 17 00:00:00 2001 From: Kushal Pisavadia Date: Fri, 27 Feb 2026 21:33:00 +0000 Subject: [PATCH] Fix command `typealias` unwrapping in `resolveType` (#1449) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The loop unwraps nullables and constraints but breaks straight away after a `typealias`. This means the nullable is missed. Removing the `break` fixes it. ## Exception ``` org.pkl.core.PklException: –– Pkl Error –– Command option property `foo` has unsupported type `String?`. 11 | foo: OptionalString ^^^^^^^^^^^^^^^^^^^ at (file:///var/folders/xh/lmp1n6qj4m13t53cfmbqnkwh0000gn/T/junit-1378070630576324311/cmd.pkl) Use a supported type or define a transformEach and/or transformAll function ``` --- .../pkl/core/runtime/CommandSpecParser.java | 1 - .../pkl/core/runtime/CommandSpecParserTest.kt | 24 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/pkl-core/src/main/java/org/pkl/core/runtime/CommandSpecParser.java b/pkl-core/src/main/java/org/pkl/core/runtime/CommandSpecParser.java index b80c934a..12399fc2 100644 --- a/pkl-core/src/main/java/org/pkl/core/runtime/CommandSpecParser.java +++ b/pkl-core/src/main/java/org/pkl/core/runtime/CommandSpecParser.java @@ -407,7 +407,6 @@ public final class CommandSpecParser { } else if (typeNode instanceof TypeNode.TypeAliasTypeNode typeAliasTypeNode) { if (typeAliasTypeNode.getVmTypeAlias() == BaseModule.getCharTypeAlias()) break; typeNode = typeAliasTypeNode.getAliasedTypeNode(); - break; } else { break; } diff --git a/pkl-core/src/test/kotlin/org/pkl/core/runtime/CommandSpecParserTest.kt b/pkl-core/src/test/kotlin/org/pkl/core/runtime/CommandSpecParserTest.kt index 05aaa1d1..ecf9179b 100644 --- a/pkl-core/src/test/kotlin/org/pkl/core/runtime/CommandSpecParserTest.kt +++ b/pkl-core/src/test/kotlin/org/pkl/core/runtime/CommandSpecParserTest.kt @@ -814,4 +814,28 @@ class CommandSpecParserTest { assertThat(apply.message).contains("invalid choice") assertThat(apply.message).contains("xml") } + + @Test + fun `typealias of nullable is resolved as optional`() { + val moduleUri = + writePklFile( + "cmd.pkl", + renderOptions + + """ + typealias OptionalString = String? + class Options { + foo: OptionalString + } + """ + .trimIndent(), + ) + + val spec = parse(moduleUri) + + assertThat(spec.options.toList()[0]).isInstanceOf(CommandSpec.Flag::class.java) + (spec.options.toList()[0] as CommandSpec.Flag).apply { + assertThat(this.name).isEqualTo("foo") + assertThat(this.showAsRequired).isFalse() + } + } }