[K/N] keep internal members in header klibs

This is also the behavior of jvm-abi-gen and desired to support
friend modules.
^KT-65442
This commit is contained in:
Johan Bay
2024-01-09 15:32:15 +01:00
committed by Space Cloud
parent a2516548e4
commit 446db595ce
12 changed files with 27 additions and 35 deletions
@@ -6,12 +6,10 @@
package org.jetbrains.kotlin.fir.serialization
import org.jetbrains.kotlin.builtins.functions.FunctionTypeKind
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.nonSourceAnnotations
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
import org.jetbrains.kotlin.fir.declarations.utils.isInterface
import org.jetbrains.kotlin.fir.declarations.utils.visibility
@@ -60,9 +58,11 @@ fun FirMemberDeclaration.isNotExpectOrShouldBeSerialized(actualizedExpectDeclara
}
fun FirMemberDeclaration.isNotPrivateOrShouldBeSerialized(produceHeaderKlib: Boolean): Boolean {
return !produceHeaderKlib || visibility.isPublicAPI
return !produceHeaderKlib || visibility.isPublicAPI || visibility == Visibilities.Internal
// Always keep private interfaces as they can be part of public type hierarchies.
|| (this as? FirClass)?.isInterface == true
// We also keep private type aliases as they leak into public signatures (KT-17229).
// TODO: stop preserving private type aliases once KT-17229 is fixed.
|| (this as? FirClass)?.isInterface == true || this is FirTypeAlias
}
fun <
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.serialization.encodings.*
import org.jetbrains.kotlin.backend.common.serialization.proto.IrSimpleTypeNullability
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities.INTERNAL
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrFileEntry
import org.jetbrains.kotlin.ir.declarations.*
@@ -1107,9 +1108,9 @@ open class IrFileSerializer(
.setBase(serializeIrDeclarationBase(property, PropertyFlags.encode(property)))
.setName(serializeName(property.name))
property.backingField?.let { proto.backingField = serializeIrField(it) }
property.getter?.let { proto.getter = serializeIrFunction(it) }
property.setter?.let { proto.setter = serializeIrFunction(it) }
property.backingField?.takeUnless { skipIfPrivate(it) }?.let { proto.backingField = serializeIrField(it) }
property.getter?.takeUnless { skipIfPrivate(it) }?.let { proto.getter = serializeIrFunction(it) }
property.setter?.takeUnless { skipIfPrivate(it) }?.let { proto.setter = serializeIrFunction(it) }
return proto.build()
}
@@ -1269,9 +1270,9 @@ open class IrFileSerializer(
open fun backendSpecificMetadata(irFile: IrFile): FileBackendSpecificMetadata? = null
private fun skipIfPrivate(declaration: IrDeclaration) =
skipPrivateApi && (declaration as? IrDeclarationWithVisibility)?.visibility?.isPublicAPI != true
// Always keep private interfaces as they can be part of public type hierarchies.
&& (declaration as? IrClass)?.isInterface != true
skipPrivateApi && (declaration as? IrDeclarationWithVisibility)?.let { !it.visibility.isPublicAPI && it.visibility != INTERNAL } == true
// Always keep private interfaces and type aliases as they can be part of public type hierarchies.
&& (declaration as? IrClass)?.isInterface != true && declaration !is IrTypeAlias
open fun memberNeedsSerialization(member: IrDeclaration): Boolean {
val parent = member.parent
@@ -113,9 +113,10 @@ abstract class KlibMetadataSerializer(
private fun Sequence<DeclarationDescriptor>.filterPrivate(): Sequence<DeclarationDescriptor> =
if (produceHeaderKlib) {
// We keep all interfaces since publicly accessible classes can inherit from private interfaces.
this.filter {
it is ClassDescriptor && it.kind.isInterface || it is DeclarationDescriptorWithVisibility && it.effectiveVisibility().publicApi
val isPublicOrInternal = it is DeclarationDescriptorWithVisibility
&& (it.visibility.isPublicAPI || it.visibility.delegate == Visibilities.Internal)
it is ClassDescriptor && it.kind.isInterface || isPublicOrInternal
}
} else this
@@ -42,7 +42,7 @@ class KlibMetadataSerializerExtension(
DescriptorUtils.getAllDescriptors(classDescriptor.defaultType.memberScope)
.filterIsInstance<CallableMemberDescriptor>()
.filter { it.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE }
.filter { it.visibility.isPublicAPI || classDescriptor.isInlineClass() }
.filter { it.visibility.isPublicAPI || it.visibility.delegate == Visibilities.Internal || classDescriptor.isInlineClass() }
)
}
else super.customClassMembersProducer
@@ -4,8 +4,8 @@ class A {
val publicVal = 0
fun publicMethod() = 0
internal val internalVal = 42
internal fun internalMethod() = 42
internal val internalVal = 0
internal fun internalMethod() = 0
protected val protectedVal = 0
protected fun protectedMethod() = 0
@@ -1,7 +1,7 @@
package test
private interface A {
fun foo() = 0
fun foo(): Int { if (true) return 1 else return 0 }
fun bar(): String
}
@@ -1,7 +1,7 @@
package test
private interface A {
fun foo() = 42
fun foo(): Int { if (true) return 0 else return 1 }
fun bar(): String
}
@@ -4,4 +4,4 @@ private val x = 1
object A { fun f() = x }
val y = 2
val y = (0..20).random()
@@ -2,4 +2,4 @@ package test
object A { fun f() = 1 }
val y = 2
val y = (30..50).random()
@@ -1,12 +1,7 @@
package test
val publicVal = 0
const val publicConst = 0
fun publicFun() = 0
internal val internalVal = 0
internal const val internalConst = 0
internal fun internalFun() = 0
val publicVal = (0..10).random()
fun publicFun() = (0..10).random()
private val privateVal = 0
private const val privateConst = 0
@@ -1,9 +1,4 @@
package test
val publicVal = 0
const val publicConst = 0
fun publicFun() = 0
internal val internalVal = 0
internal const val internalConst = 0
internal fun internalFun() = 0
val publicVal = (0..20).random()
fun publicFun() = (0..20).random()