Skip to content

Commit

Permalink
Update Kotlin to 2.0.0 (#519)
Browse files Browse the repository at this point in the history
Since Clikt uses a lot on lambdas, compiling with `invokedynamic` reduces the jvm jar size by ~20%
  • Loading branch information
ajalt committed May 22, 2024
1 parent 72dc9a2 commit 903fe2d
Show file tree
Hide file tree
Showing 10 changed files with 31 additions and 35 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ docs/api/
docs/changelog.md
docs/index.md
kotlin-js-store/
.kotlin/
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
- **Breaking Change:** `CliktCommand.main` and `CliktCommand.parse` are now extension functions rather than methods.
- **Breaking Change:** `Context.obj` and `Context.terminal`, and `OptionTransformContext.terminal` are now extension functions rather than properties.
- **Breaking Change:** The `RenderedSection` and `DefinitionRow` classes have moved to `AbstractHelpFormatter`.
- Updated Kotlin to 2.0.0

### Fixed
- Fixed excess arguments not being reported when `allowMultipleSubcommands=true` and a subcommand has excess arguments followed by another subcommand.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ class ContextTest {
}

@Test
@OptIn(ExperimentalStdlibApi::class)
@JsName("register_closeable_multiple_subcommands")
fun `register closeable multiple subcommands`() {
var parentCount = 0
Expand Down
4 changes: 2 additions & 2 deletions clikt/api/clikt.api
Original file line number Diff line number Diff line change
Expand Up @@ -1333,8 +1333,8 @@ public final class com/github/ajalt/clikt/parsers/CommandLineParser {
public static synthetic fun tokenize$default (Lcom/github/ajalt/clikt/parsers/CommandLineParser;Ljava/lang/String;Ljava/lang/String;Lcom/github/ajalt/clikt/output/Localization;ILjava/lang/Object;)Ljava/util/List;
}

public final class com/github/ajalt/clikt/parsers/FlatInvocations : kotlin/sequences/Sequence {
public final fun close ()V
public final class com/github/ajalt/clikt/parsers/FlatInvocations : java/lang/AutoCloseable, kotlin/sequences/Sequence {
public fun close ()V
public fun iterator ()Ljava/util/Iterator;
}

Expand Down
4 changes: 2 additions & 2 deletions clikt/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ kotlin {
// https://youtrack.jetbrains.com/issue/KT-63014
// https://github.com/Kotlin/kotlin-wasm-examples/blob/1b007347bf9f8a1ec3d420d30de1815768d5df02/nodejs-example/build.gradle.kts#L22
rootProject.the<NodeJsRootExtension>().apply {
nodeVersion = "22.0.0-nightly202404032241e8c5b3"
nodeDownloadBaseUrl = "https://nodejs.org/download/nightly"
version = "22.0.0-nightly202404032241e8c5b3"
downloadBaseUrl = "https://nodejs.org/download/nightly"
}

rootProject.tasks.withType<KotlinNpmInstallTask>().configureEach {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,6 @@ class Context private constructor(
* @return the closeable that was registered
* @see Context.callOnClose
*/
@ExperimentalStdlibApi
fun <T : AutoCloseable> Context.registerCloseable(closeable: T): T {
callOnClose { closeable.close() }
return closeable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,10 @@ object CommandLineParser {
rootInvocation: CommandInvocation<T>,
runCommand: (T) -> Unit,
) {
val invocations = rootInvocation.flatten()
try {
rootInvocation.flatten().use { invocations ->
for (invocation in invocations) {
runCommand(invocation.command)
}
} finally {
invocations.close()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,27 +87,24 @@ class CommandLineParseResult<T : BaseCliktCommand<T>>(
* ### Example
*
* ```
* val invocations = rootInvocation.flatten()
* try {
* for (inv in invocations) {
* run(inv.command)
* }
* } finally {
* invocations.close()
* rootInvocation.flatten().use { invocations ->
* for (invocation in invocations) {
* runCommand(invocation.command)
* }
* }
* ```
*
* @param finalize If true (the default), finalize all commands as they are emitted in the sequence. If false, you
* must call [CommandLineParser.finalize] on each invocation yourself before running the command.
* @param finalize If true (the default), finalize all commands as they are emitted in the sequence.
* If false, you must call [CommandLineParser.finalize] on each invocation yourself before running
* the command.
*/
fun <T : BaseCliktCommand<T>> CommandInvocation<T>.flatten(finalize: Boolean = true): FlatInvocations<T> {
return FlatInvocations(this, finalize)
}

// TODO: this should be an AutoClosable once that interface is stable
class FlatInvocations<T : BaseCliktCommand<T>> internal constructor(
root: CommandInvocation<T>, private val finalize: Boolean,
) : Sequence<CommandInvocation<T>> {
) : Sequence<CommandInvocation<T>>, AutoCloseable {
private val closables = mutableListOf<Context>()
private val seq = sequence {
suspend fun SequenceScope<CommandInvocation<T>>.yieldSubs(inv: CommandInvocation<T>) {
Expand All @@ -126,7 +123,7 @@ class FlatInvocations<T : BaseCliktCommand<T>> internal constructor(
/**
* [Close][Context.close] all open contexts of invoked commands.
*/
fun close() {
override fun close() {
closables.forEach { it.close() }
}
}
24 changes: 13 additions & 11 deletions docs/advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -489,45 +489,47 @@ soon as one of them returns a non-zero status code, you could implement it like
abstract class StatusCliktCommand : BaseCliktCommand<StatusCliktCommand>() {
abstract fun run(): Int
}

class ParentCommand : StatusCliktCommand() {
override val allowMultipleSubcommands: Boolean = true
override fun run(): Int {
echo("Parent")
return 0
}
}

class SuccessCommand : StatusCliktCommand() {
override fun run(): Int {
echo("Success")
return 0
}
}

class FailureCommand : StatusCliktCommand() {
override fun run(): Int {
echo("Failure")
return 1001
}
}

fun StatusCliktCommand.parse(argv: Array<String>): Int {
val parseResult = CommandLineParser.parse(this, argv.asList())
for (invocation in parseResult.invocation.flatten()) {
val status = invocation.command.run()
if (status != 0) {
return status
parseResult.invocation.flatten().use { invocations ->
for (invocation in invocations) {
val status = invocation.command.run()
if (status != 0) {
return status
}
}
}
return 0
}

fun StatusCliktCommand.main(argv: Array<String>) {
val status = CommandLineParser.mainReturningValue(this) { parse(argv) }
CliktUtil.exitProcess(status)
exitProcess(status)
}

fun main(argv: Array<String>) {
ParentCommand().subcommands(SuccessCommand(), FailureCommand()).main(argv)
}
Expand Down
4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[versions]
kotlin = "1.9.23"
coroutines = "1.8.0"
kotlin = "2.0.0"
coroutines = "1.8.1"

[libraries]
mordant = "com.github.ajalt.mordant:mordant:2.6.0"
Expand Down

0 comments on commit 903fe2d

Please sign in to comment.