Skip to content

Commit

Permalink
Filter out $suspendImpl functions from dumps (#271)
Browse files Browse the repository at this point in the history
* Enable default interface methods generation
* Filter out $suspendImpl methods.

Closes #270
  • Loading branch information
fzhinkin authored Oct 18, 2024
1 parent 7b12744 commit 91dc2a9
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 3 deletions.
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ kotlin {
tasks.compileTestKotlin {
compilerOptions {
languageVersion.set(KotlinVersion.KOTLIN_1_9)
freeCompilerArgs.add("-Xjvm-default=all-compatibility")
}
}

Expand Down
9 changes: 9 additions & 0 deletions src/main/kotlin/api/KotlinMetadataSignature.kt
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ internal data class MethodBinarySignature(
super.isEffectivelyPublic(classAccess, classVisibility)
&& !isAccessOrAnnotationsMethod()
&& !isDummyDefaultConstructor()
&& !isSuspendImplMethod()

override fun findMemberVisibility(classVisibility: ClassVisibility?): MemberVisibility? {
return super.findMemberVisibility(classVisibility)
Expand All @@ -71,6 +72,14 @@ internal data class MethodBinarySignature(

private fun isDummyDefaultConstructor() =
access.isSynthetic && name == "<init>" && desc == "(Lkotlin/jvm/internal/DefaultConstructorMarker;)V"

/**
* Kotlin compiler emits special `<originalFunctionName>$suspendImpl` methods for open
* suspendable functions. These synthetic functions could only be invoked from original function,
* or from a corresponding continuation. They don't constitute class's public ABI, but in some cases
* they might be declared public (namely, in case of default interface methods).
*/
private fun isSuspendImplMethod() = access.isSynthetic && name.endsWith("\$suspendImpl")
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/test/kotlin/cases/default/default.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ public class cases/default/ClassFunctions {

public abstract interface class cases/default/InterfaceFunctions {
public abstract fun withAllDefaults (ILjava/lang/String;)V
public static synthetic fun withAllDefaults$default (Lcases/default/InterfaceFunctions;ILjava/lang/String;ILjava/lang/Object;)V
public abstract fun withSomeDefaults (ILjava/lang/String;)V
public static synthetic fun withSomeDefaults$default (Lcases/default/InterfaceFunctions;ILjava/lang/String;ILjava/lang/Object;)V
}

public final class cases/default/InterfaceFunctions$DefaultImpls {
Expand Down
4 changes: 2 additions & 2 deletions src/test/kotlin/cases/interfaces/interfaces.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
public abstract interface class cases/interfaces/BaseWithImpl {
public abstract fun foo ()I
public fun foo ()I
}

public final class cases/interfaces/BaseWithImpl$DefaultImpls {
public static fun foo (Lcases/interfaces/BaseWithImpl;)I
}

public abstract interface class cases/interfaces/DerivedWithImpl : cases/interfaces/BaseWithImpl {
public abstract fun foo ()I
public fun foo ()I
}

public final class cases/interfaces/DerivedWithImpl$DefaultImpls {
Expand Down
22 changes: 22 additions & 0 deletions src/test/kotlin/cases/suspend/suspend.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright 2016-2024 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
*/

package cases.suspend

public interface I {
suspend fun openFunction(): Int = 42
}

public interface II : I {
override suspend fun openFunction(): Int {
return super.openFunction() + 1
}
}

public open class C : II {
override suspend fun openFunction(): Int {
return super.openFunction() + 2
}
}
21 changes: 21 additions & 0 deletions src/test/kotlin/cases/suspend/suspend.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
public class cases/suspend/C : cases/suspend/II {
public fun <init> ()V
public fun openFunction (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public abstract interface class cases/suspend/I {
public fun openFunction (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public final class cases/suspend/I$DefaultImpls {
public static fun openFunction (Lcases/suspend/I;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public abstract interface class cases/suspend/II : cases/suspend/I {
public fun openFunction (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public final class cases/suspend/II$DefaultImpls {
public static fun openFunction (Lcases/suspend/II;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

4 changes: 3 additions & 1 deletion src/test/kotlin/tests/CasesPublicAPITest.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2020 JetBrains s.r.o.
* Copyright 2016-2024 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
*/

Expand Down Expand Up @@ -58,6 +58,8 @@ class CasesPublicAPITest {

@Test fun special() { snapshotAPIAndCompare(testName.methodName) }

@Test fun suspend() { snapshotAPIAndCompare(testName.methodName) }

@Test fun whenMappings() { snapshotAPIAndCompare(testName.methodName) }

@Test fun enums() { snapshotAPIAndCompare(testName.methodName) }
Expand Down

0 comments on commit 91dc2a9

Please sign in to comment.