diff --git a/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/Kotlinp.kt b/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/Kotlinp.kt index 81805e62ff0..8c4bba289b0 100644 --- a/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/Kotlinp.kt +++ b/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/Kotlinp.kt @@ -45,5 +45,6 @@ class Kotlinp(private val settings: KotlinpSettings) { } data class KotlinpSettings( - val isVerbose: Boolean + val isVerbose: Boolean, + val sortDeclarations: Boolean ) diff --git a/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/Main.kt b/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/Main.kt index 38ae578c748..6e156ff01b7 100644 --- a/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/Main.kt +++ b/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/Main.kt @@ -14,6 +14,7 @@ object Main { private fun run(args: Array) { val paths = arrayListOf() var verbose = false + var sort = false var i = 0 while (true) { @@ -21,6 +22,8 @@ object Main { if (arg == "-help" || arg == "-h") { printUsageAndExit() + } else if (arg == "-sort") { + sort = true } else if (arg == "-verbose") { verbose = true } else if (arg == "-version") { @@ -32,7 +35,7 @@ object Main { } } - val kotlinp = Kotlinp(KotlinpSettings(verbose)) + val kotlinp = Kotlinp(KotlinpSettings(isVerbose = verbose, sortDeclarations = sort)) for (path in paths) { val file = File(path) @@ -72,6 +75,7 @@ object Main { Usage: kotlinp where possible options include: + -sort Sort declarations in the output by signature and/or name -verbose Display information in more detail, minimizing ambiguities but worsening readability -version Display Kotlin version -help (-h) Print a synopsis of options diff --git a/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/printers.kt b/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/printers.kt index 39b94337adf..5ec0fcfe8c9 100644 --- a/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/printers.kt +++ b/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/printers.kt @@ -371,6 +371,10 @@ private fun StringBuilder.appendDeclarationContainerExtensions( } } +private fun > Iterable.sortIfNeededBy(settings: KotlinpSettings, selector: (T) -> R?): Iterable { + return if (settings.sortDeclarations) sortedBy(selector) else this +} + @ExperimentalContracts private fun printContract(kmContract: KmContract): String = buildString { appendLine("contract {") @@ -546,7 +550,7 @@ class ClassPrinter(private val settings: KotlinpSettings) : AbstractPrinter + kclass.localDelegatedProperties.sortIfNeededBy(settings) { it.getterSignature?.toString() ?: it.name }.forEach { p -> visitProperty( p, settings, StringBuilder().also { localDelegatedProperties.add(it) } ) @@ -572,14 +576,16 @@ class ClassPrinter(private val settings: KotlinpSettings) : AbstractPrinter() val moduleName: String? = kmPackage.moduleName - kmPackage.localDelegatedProperties.forEach { p -> + kmPackage.localDelegatedProperties.sortIfNeededBy(settings) { it.getterSignature?.toString() ?: it.name }.forEach { p -> visitProperty(p, settings, StringBuilder().also { localDelegatedProperties.add(it) }) } sb.appendDeclarationContainerExtensions(settings, localDelegatedProperties, moduleName) } fun print(kmPackage: KmPackage) { - kmPackage.functions.forEach { visitFunction(it, settings, sb) } - kmPackage.properties.forEach { visitProperty(it, settings, sb) } - kmPackage.typeAliases.forEach { visitTypeAlias(it, settings, sb) } + kmPackage.functions.sortIfNeededBy(settings) { it.signature.toString() }.forEach { visitFunction(it, settings, sb) } + kmPackage.properties.sortIfNeededBy(settings) { + it.getterSignature?.toString() ?: it.name + }.forEach { visitProperty(it, settings, sb) } + kmPackage.typeAliases.sortIfNeededBy(settings) { it.name }.forEach { visitTypeAlias(it, settings, sb) } visitExtensions(kmPackage) sb.appendLine("}") } diff --git a/libraries/tools/kotlinp/test/org/jetbrains/kotlin/kotlinp/test/KotlinpTestUtils.kt b/libraries/tools/kotlinp/test/org/jetbrains/kotlin/kotlinp/test/KotlinpTestUtils.kt index ae39668be12..a9a3d17b11b 100644 --- a/libraries/tools/kotlinp/test/org/jetbrains/kotlin/kotlinp/test/KotlinpTestUtils.kt +++ b/libraries/tools/kotlinp/test/org/jetbrains/kotlin/kotlinp/test/KotlinpTestUtils.kt @@ -39,7 +39,7 @@ fun compileAndPrintAllFiles( val afterVisitors = StringBuilder() val afterNodes = StringBuilder() - val kotlinp = Kotlinp(KotlinpSettings(isVerbose = true)) + val kotlinp = Kotlinp(KotlinpSettings(isVerbose = true, sortDeclarations = true)) @OptIn(UnstableMetadataApi::class) compile(file, disposable, tmpdir, useK2) { outputFile -> diff --git a/libraries/tools/kotlinp/testData/Contracts.txt b/libraries/tools/kotlinp/testData/Contracts.txt index 7dbd52da289..3c3a438ea0c 100644 --- a/libraries/tools/kotlinp/testData/Contracts.txt +++ b/libraries/tools/kotlinp/testData/Contracts.txt @@ -40,6 +40,12 @@ package { returns() implies (p#1 !is kotlin/collections/List<*> && p#2 && p#3 == null) } + // signature: receiverIsNotNull(Ljava/lang/Object;)Z + public final fun kotlin/Any?.receiverIsNotNull(): kotlin/Boolean + contract { + returns(true) implies (p#0 != null) + } + // signature: returnsNotNull(Z)V public final fun returnsNotNull(condition: kotlin/Boolean): kotlin/Unit contract { @@ -58,12 +64,6 @@ package { returns(true) implies (p#1) } - // signature: receiverIsNotNull(Ljava/lang/Object;)Z - public final fun kotlin/Any?.receiverIsNotNull(): kotlin/Boolean - contract { - returns(true) implies (p#0 != null) - } - // module name: test-module } // META-INF/test-module.kotlin_module diff --git a/libraries/tools/kotlinp/testData/Properties.txt b/libraries/tools/kotlinp/testData/Properties.txt index e6a133f4ed4..711bba698e9 100644 --- a/libraries/tools/kotlinp/testData/Properties.txt +++ b/libraries/tools/kotlinp/testData/Properties.txt @@ -19,6 +19,11 @@ public final class C : kotlin/Any { public final val constructorParam: kotlin/String public final get + // getter: getDelegated(Ljava/lang/Number;)Ljava/util/List; + // synthetic method for delegate: getDelegated$delegate(LC;Ljava/lang/Number;)Ljava/lang/Object; + public final /* delegated */ val T#0.delegated: kotlin/collections/List + public final /* non-default */ get + // getter: getGetterOnlyVal()D public final val getterOnlyVal: kotlin/Double public final /* non-default */ get @@ -35,11 +40,6 @@ public final class C : kotlin/Any { public final /* delegated */ val withOptimizedDelegate: kotlin/Double public final /* non-default */ get - // getter: getDelegated(Ljava/lang/Number;)Ljava/util/List; - // synthetic method for delegate: getDelegated$delegate(LC;Ljava/lang/Number;)Ljava/lang/Object; - public final /* delegated */ val T#0.delegated: kotlin/collections/List - public final /* non-default */ get - // module name: test-module } // META-INF/test-module.kotlin_module diff --git a/libraries/tools/kotlinp/testData/SimpleClass.txt b/libraries/tools/kotlinp/testData/SimpleClass.txt index fb4d10a3e71..e8464cdeec6 100644 --- a/libraries/tools/kotlinp/testData/SimpleClass.txt +++ b/libraries/tools/kotlinp/testData/SimpleClass.txt @@ -2,19 +2,19 @@ // ------------------------------------------ public final class SimpleClass : kotlin/Any { + // signature: (I)V + public constructor(p: kotlin/Int /* = ... */) + // signature: ([Ljava/lang/String;)V public /* secondary */ constructor(s: kotlin/Array?) - // signature: (I)V - public constructor(p: kotlin/Int /* = ... */) + // signature: f$test_module(Ljava/lang/Object;[Ljava/util/Map;)Ljava/util/Set; + internal final fun T#3.f(vararg z: kotlin/collections/Map /* kotlin/Array> */): kotlin/collections/Set<*> // requires language version 1.3.0 (level=ERROR) // signature: g(Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; protected final inline suspend fun g(crossinline a: kotlin/Function0, noinline b: suspend kotlin/Function1, kotlin/Any?>): kotlin/Unit - // signature: f$test_module(Ljava/lang/Object;[Ljava/util/Map;)Ljava/util/Set; - internal final fun T#3.f(vararg z: kotlin/collections/Map /* kotlin/Array> */): kotlin/collections/Set<*> - // field: p:I // getter: getP()I public final val p: kotlin/Int