Skip to content

Commit 1d7505b

Browse files
authored
Add all interface's class-level annotations to its DefaultImpls class. (Kotlin#161)
Fixes Kotlin#155
1 parent 066e01e commit 1d7505b

File tree

5 files changed

+36
-5
lines changed

5 files changed

+36
-5
lines changed

src/main/kotlin/api/AsmMetadataLoading.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ private const val publishedApiAnnotationName = "kotlin/PublishedApi"
5151
private fun ClassNode.isPublishedApi() = findAnnotation(publishedApiAnnotationName, includeInvisible = true) != null
5252
internal fun List<AnnotationNode>.isPublishedApi() = firstOrNull { it.refersToName(publishedApiAnnotationName) } != null
5353

54-
internal fun ClassNode.isDefaultImpls(metadata: KotlinClassMetadata?) = isInner() && name.endsWith("\$DefaultImpls") && metadata.isSyntheticClass()
54+
internal const val DefaultImplsNameSuffix = "\$DefaultImpls"
55+
internal fun ClassNode.isDefaultImpls(metadata: KotlinClassMetadata?) =
56+
isInner() && name.endsWith(DefaultImplsNameSuffix) && metadata.isSyntheticClass()
5557

5658
internal fun ClassNode.findAnnotation(annotationName: String, includeInvisible: Boolean = false) =
5759
findAnnotation(annotationName, visibleAnnotations, invisibleAnnotations, includeInvisible)

src/main/kotlin/api/KotlinSignaturesLoading.kt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,22 @@ public fun Sequence<InputStream>.loadApiFromJvmClasses(visibilityFilter: (String
6363
val methodSignatures = methods.map { it.buildMethodSignature(mVisibility, this) }
6464
.filter { it.isEffectivelyPublic(classAccess, mVisibility) }
6565

66+
/**
67+
* For synthetic $DefaultImpls classes copy annotations from the original interface
68+
*/
69+
val inheritedAnnotations = mutableListOf<AnnotationNode>().apply {
70+
if (classNode.isDefaultImpls(kotlinMetadata)) {
71+
val originalInterface = classNodeMap[classNode.name.dropLast(DefaultImplsNameSuffix.length)]
72+
addAll(originalInterface?.visibleAnnotations.orEmpty())
73+
addAll(originalInterface?.invisibleAnnotations.orEmpty())
74+
}
75+
}
76+
6677
ClassBinarySignature(
6778
name, superName, outerClassName, supertypes, fieldSignatures + methodSignatures, classAccess,
6879
isEffectivelyPublic(mVisibility),
6980
metadata.isFileOrMultipartFacade() || isDefaultImpls(metadata),
70-
annotations(visibleAnnotations, invisibleAnnotations)
81+
annotations(visibleAnnotations, invisibleAnnotations) + inheritedAnnotations
7182
)
7283
}
7384
}
@@ -182,7 +193,7 @@ public fun List<ClassBinarySignature>.filterOutAnnotated(targetAnnotations: Set<
182193
}
183194

184195
signature.copy(memberSignatures = notAnnotatedMemberSignatures)
185-
}
196+
}.filterNot { it.isNotUsedWhenEmpty && it.memberSignatures.isEmpty() }
186197
}
187198

188199
private fun List<ClassBinarySignature>.filterOutNotAnnotated(

src/test/kotlin/cases/default/default.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ public final class cases/default/InterfaceFunctions$DefaultImpls {
1515
public static synthetic fun withSomeDefaults$default (Lcases/default/InterfaceFunctions;ILjava/lang/String;ILjava/lang/Object;)V
1616
}
1717

18+
public abstract interface class cases/default/PublicInterfaceWithAllFunctionsFilteredOut {
19+
}
20+
1821
public final class cases/default/PublishedApiWithDefaultsKt {
1922
public static final fun twoDefaults (ILjava/lang/Object;Ljava/lang/String;)V
2023
public static synthetic fun twoDefaults$default (ILjava/lang/Object;Ljava/lang/String;ILjava/lang/Object;)V

src/test/kotlin/cases/default/functions.kt

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,19 @@ interface InterfaceFunctions {
2121

2222
fun withSomeDefaults(par1: Int, par2: String? = null)
2323

24-
}
24+
}
25+
26+
@PrivateApi
27+
annotation class PrivateApi
28+
29+
@PrivateApi
30+
interface PrivateInterfaceWithDefaultMethod {
31+
fun foo() {}
32+
33+
fun bar() {}
34+
}
35+
36+
interface PublicInterfaceWithAllFunctionsFilteredOut {
37+
@PrivateApi
38+
fun foo() {}
39+
}

src/test/kotlin/tests/CasesPublicAPITest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class CasesPublicAPITest {
2929

3030
@Test fun companions() { snapshotAPIAndCompare(testName.methodName, setOf("cases/companions/PrivateApi")) }
3131

32-
@Test fun default() { snapshotAPIAndCompare(testName.methodName) }
32+
@Test fun default() { snapshotAPIAndCompare(testName.methodName, setOf("cases/default/PrivateApi")) }
3333

3434
@Test fun inline() { snapshotAPIAndCompare(testName.methodName) }
3535

0 commit comments

Comments
 (0)