mirror of
https://github.com/apple/pkl.git
synced 2026-01-11 22:30:54 +01:00
Make commands classes instead of objects (#946)
Making these classes caused native-image to statically initialize them at build time, which included CLI argument default values (like working dir). This turns them back into classes. Co-authored-by: Islon Scherer <islonscherer@gmail.com>
This commit is contained in:
@@ -22,5 +22,5 @@ import org.pkl.commons.cli.cliMain
|
||||
|
||||
/** Main method of the Pkl CLI (command-line evaluator and REPL). */
|
||||
internal fun main(args: Array<String>) {
|
||||
cliMain { RootCommand.main(args) }
|
||||
cliMain { RootCommand().main(args) }
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.pkl.cli.CliImportAnalyzerOptions
|
||||
import org.pkl.commons.cli.commands.ModulesCommand
|
||||
import org.pkl.commons.cli.commands.single
|
||||
|
||||
object AnalyzeCommand :
|
||||
class AnalyzeCommand :
|
||||
NoOpCliktCommand(
|
||||
name = "analyze",
|
||||
help = "Commands related to static analysis",
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.pkl.commons.cli.commands.ProjectOptions
|
||||
import org.pkl.commons.cli.commands.single
|
||||
import org.pkl.core.packages.PackageUri
|
||||
|
||||
object DownloadPackageCommand :
|
||||
class DownloadPackageCommand :
|
||||
BaseCommand(
|
||||
name = "download-package",
|
||||
helpLink = helpLink,
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.pkl.cli.CliEvaluatorOptions
|
||||
import org.pkl.commons.cli.commands.ModulesCommand
|
||||
import org.pkl.commons.cli.commands.single
|
||||
|
||||
object EvalCommand :
|
||||
class EvalCommand :
|
||||
ModulesCommand(name = "eval", help = "Render pkl module(s)", helpLink = helpLink) {
|
||||
private val outputPath: String? by
|
||||
option(
|
||||
|
||||
@@ -33,18 +33,18 @@ import org.pkl.commons.cli.commands.single
|
||||
|
||||
private const val NEWLINE = '\u0085'
|
||||
|
||||
object ProjectCommand :
|
||||
class ProjectCommand :
|
||||
NoOpCliktCommand(
|
||||
name = "project",
|
||||
help = "Run commands related to projects",
|
||||
epilog = "For more information, visit $helpLink",
|
||||
) {
|
||||
init {
|
||||
subcommands(ResolveCommand, PackageCommand)
|
||||
subcommands(ResolveCommand(), PackageCommand())
|
||||
}
|
||||
}
|
||||
|
||||
object ResolveCommand :
|
||||
class ResolveCommand :
|
||||
BaseCommand(
|
||||
name = "resolve",
|
||||
helpLink = helpLink,
|
||||
@@ -74,7 +74,7 @@ object ResolveCommand :
|
||||
}
|
||||
}
|
||||
|
||||
object PackageCommand :
|
||||
class PackageCommand :
|
||||
BaseCommand(
|
||||
name = "package",
|
||||
helpLink = helpLink,
|
||||
|
||||
@@ -21,8 +21,7 @@ import org.pkl.cli.CliRepl
|
||||
import org.pkl.commons.cli.commands.BaseCommand
|
||||
import org.pkl.commons.cli.commands.ProjectOptions
|
||||
|
||||
object ReplCommand :
|
||||
BaseCommand(name = "repl", help = "Start a REPL session", helpLink = helpLink) {
|
||||
class ReplCommand : BaseCommand(name = "repl", help = "Start a REPL session", helpLink = helpLink) {
|
||||
private val projectOptions by ProjectOptions()
|
||||
|
||||
override fun run() {
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.pkl.core.Release
|
||||
|
||||
internal val helpLink = "${Release.current().documentation.homepage}pkl-cli/index.html#usage"
|
||||
|
||||
object RootCommand :
|
||||
class RootCommand :
|
||||
NoOpCliktCommand(
|
||||
name = "pkl",
|
||||
printHelpOnEmptyArgs = true,
|
||||
@@ -41,13 +41,13 @@ object RootCommand :
|
||||
}
|
||||
|
||||
subcommands(
|
||||
EvalCommand,
|
||||
ReplCommand,
|
||||
ServerCommand,
|
||||
TestCommand,
|
||||
ProjectCommand,
|
||||
DownloadPackageCommand,
|
||||
AnalyzeCommand,
|
||||
EvalCommand(),
|
||||
ReplCommand(),
|
||||
ServerCommand(),
|
||||
TestCommand(),
|
||||
ProjectCommand(),
|
||||
DownloadPackageCommand(),
|
||||
AnalyzeCommand(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import com.github.ajalt.clikt.core.CliktCommand
|
||||
import org.pkl.cli.CliServer
|
||||
import org.pkl.commons.cli.CliBaseOptions
|
||||
|
||||
object ServerCommand :
|
||||
class ServerCommand :
|
||||
CliktCommand(
|
||||
name = "server",
|
||||
help = "Run as a server that communicates over standard input/output",
|
||||
|
||||
@@ -26,7 +26,7 @@ import org.pkl.commons.cli.commands.BaseOptions
|
||||
import org.pkl.commons.cli.commands.ProjectOptions
|
||||
import org.pkl.commons.cli.commands.TestOptions
|
||||
|
||||
object TestCommand :
|
||||
class TestCommand :
|
||||
BaseCommand(name = "test", help = "Run tests within the given module(s)", helpLink = helpLink) {
|
||||
val modules: List<URI> by
|
||||
argument(name = "<modules>", help = "Module paths or URIs to evaluate.")
|
||||
|
||||
@@ -32,28 +32,28 @@ import org.pkl.commons.writeString
|
||||
import org.pkl.core.Release
|
||||
|
||||
class CliMainTest {
|
||||
private val rootCmd = RootCommand()
|
||||
|
||||
@Test
|
||||
fun `duplicate CLI option produces meaningful error message`(@TempDir tempDir: Path) {
|
||||
val inputFile = tempDir.resolve("test.pkl").writeString("").toString()
|
||||
|
||||
assertThatCode {
|
||||
RootCommand.parse(
|
||||
rootCmd.parse(
|
||||
arrayOf("eval", "--output-path", "path1", "--output-path", "path2", inputFile)
|
||||
)
|
||||
}
|
||||
.hasMessage("Invalid value for \"--output-path\": Option cannot be repeated")
|
||||
|
||||
assertThatCode {
|
||||
RootCommand.parse(arrayOf("eval", "-o", "path1", "--output-path", "path2", inputFile))
|
||||
rootCmd.parse(arrayOf("eval", "-o", "path1", "--output-path", "path2", inputFile))
|
||||
}
|
||||
.hasMessage("Invalid value for \"--output-path\": Option cannot be repeated")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `eval requires at least one file`() {
|
||||
assertThatCode { RootCommand.parse(arrayOf("eval")) }
|
||||
.hasMessage("""Missing argument "<modules>"""")
|
||||
assertThatCode { rootCmd.parse(arrayOf("eval")) }.hasMessage("""Missing argument "<modules>"""")
|
||||
}
|
||||
|
||||
// Can't reliably create symlinks on Windows.
|
||||
@@ -74,7 +74,7 @@ class CliMainTest {
|
||||
val inputFile = tempDir.resolve("test.pkl").writeString(code).toString()
|
||||
val outputFile = makeSymdir(tempDir, "out", "linkOut").resolve("test.pkl").toString()
|
||||
|
||||
assertThatCode { RootCommand.parse(arrayOf("eval", inputFile, "-o", outputFile)) }
|
||||
assertThatCode { rootCmd.parse(arrayOf("eval", inputFile, "-o", outputFile)) }
|
||||
.doesNotThrowAnyException()
|
||||
}
|
||||
|
||||
@@ -85,24 +85,24 @@ class CliMainTest {
|
||||
val error =
|
||||
"""Invalid value for "--multiple-file-output-path": Option is mutually exclusive with -o, --output-path and -x, --expression."""
|
||||
|
||||
assertThatCode { RootCommand.parse(arrayOf("eval", "-m", testOut, "-x", "x", testIn)) }
|
||||
assertThatCode { rootCmd.parse(arrayOf("eval", "-m", testOut, "-x", "x", testIn)) }
|
||||
.hasMessage(error)
|
||||
|
||||
assertThatCode { RootCommand.parse(arrayOf("eval", "-m", testOut, "-o", "/tmp/test", testIn)) }
|
||||
assertThatCode { rootCmd.parse(arrayOf("eval", "-m", testOut, "-o", "/tmp/test", testIn)) }
|
||||
.hasMessage(error)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `showing version works`() {
|
||||
assertThatCode { RootCommand.parse(arrayOf("--version")) }
|
||||
.hasMessage(Release.current().versionInfo)
|
||||
assertThatCode { rootCmd.parse(arrayOf("--version")) }.hasMessage(Release.current().versionInfo)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `file paths get parsed into URIs`(@TempDir tempDir: Path) {
|
||||
RootCommand.parse(arrayOf("eval", makeInput(tempDir, "my file.txt")))
|
||||
val cmd = RootCommand()
|
||||
cmd.parse(arrayOf("eval", makeInput(tempDir, "my file.txt")))
|
||||
|
||||
val evalCmd = RootCommand.registeredSubcommands().filterIsInstance<EvalCommand>().first()
|
||||
val evalCmd = cmd.registeredSubcommands().filterIsInstance<EvalCommand>().first()
|
||||
val modules = evalCmd.baseOptions.baseOptions(evalCmd.modules).normalizedSourceModules
|
||||
assertThat(modules).hasSize(1)
|
||||
assertThat(modules[0].path).endsWith("my file.txt")
|
||||
@@ -110,8 +110,7 @@ class CliMainTest {
|
||||
|
||||
@Test
|
||||
fun `invalid URIs are not accepted`() {
|
||||
val ex =
|
||||
assertThrows<BadParameterValue> { RootCommand.parse(arrayOf("eval", "file:my file.txt")) }
|
||||
val ex = assertThrows<BadParameterValue> { rootCmd.parse(arrayOf("eval", "file:my file.txt")) }
|
||||
|
||||
assertThat(ex.message).contains("URI `file:my file.txt` has invalid syntax")
|
||||
}
|
||||
|
||||
@@ -388,7 +388,7 @@ class CliTestRunnerTest {
|
||||
@Test
|
||||
fun `no source modules specified has same message as pkl eval`() {
|
||||
val e1 = assertThrows<CliException> { CliTestRunner(CliBaseOptions(), CliTestOptions()).run() }
|
||||
val e2 = assertThrows<MissingArgument> { RootCommand.parse(listOf("eval")) }
|
||||
val e2 = assertThrows<MissingArgument> { RootCommand().parse(listOf("eval")) }
|
||||
assertThat(e1).hasMessageContaining("Missing argument \"<modules>\"")
|
||||
assertThat(e1.message!!.replace("test", "eval")).isEqualTo(e2.helpMessage())
|
||||
}
|
||||
|
||||
@@ -34,10 +34,10 @@ import org.pkl.core.Release
|
||||
|
||||
/** Main method for the Pkldoc CLI. */
|
||||
internal fun main(args: Array<String>) {
|
||||
cliMain { DocCommand.main(args) }
|
||||
cliMain { DocCommand().main(args) }
|
||||
}
|
||||
|
||||
object DocCommand :
|
||||
class DocCommand :
|
||||
BaseCommand(name = "pkldoc", helpLink = Release.current().documentation().homepage()) {
|
||||
|
||||
private val modules: List<URI> by
|
||||
|
||||
@@ -23,7 +23,8 @@ import org.pkl.commons.cli.CliException
|
||||
class CliMainTest {
|
||||
@Test
|
||||
fun `CLI run test`() {
|
||||
val e = assertThrows<CliException> { DocCommand.parse(arrayOf("foo", "--output-dir", "/tmp")) }
|
||||
val e =
|
||||
assertThrows<CliException> { DocCommand().parse(arrayOf("foo", "--output-dir", "/tmp")) }
|
||||
assertThat(e)
|
||||
.hasMessageContaining("must contain at least one module named `doc-package-info.pkl`")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user