jvm-abi-gen: Remove internal declarations from ABI
#KT-65690 Fixed
This commit is contained in:
committed by
Space Team
parent
ebc2a18da5
commit
d2792533b8
+63
-18
@@ -10,18 +10,20 @@ import org.jetbrains.kotlin.backend.jvm.extensions.ClassGeneratorExtension
|
||||
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
|
||||
import org.jetbrains.kotlin.codegen.`when`.WhenByEnumsMapping
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.overrides.isEffectivelyPrivate
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI
|
||||
import org.jetbrains.kotlin.ir.util.isFileClass
|
||||
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
||||
import org.jetbrains.kotlin.ir.util.primaryConstructor
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.org.objectweb.asm.AnnotationVisitor
|
||||
import org.jetbrains.org.objectweb.asm.FieldVisitor
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
import kotlin.metadata.jvm.JvmFieldSignature
|
||||
import kotlin.metadata.jvm.JvmMemberSignature
|
||||
import kotlin.metadata.jvm.JvmMethodSignature
|
||||
|
||||
enum class AbiMethodInfo {
|
||||
KEEP,
|
||||
@@ -30,7 +32,7 @@ enum class AbiMethodInfo {
|
||||
|
||||
sealed class AbiClassInfo {
|
||||
object Public : AbiClassInfo()
|
||||
class Stripped(val methodInfo: Map<Method, AbiMethodInfo>, val prune: Boolean = false) : AbiClassInfo()
|
||||
class Stripped(val memberInfo: Map<JvmMemberSignature, AbiMethodInfo>, val prune: Boolean = false) : AbiClassInfo()
|
||||
object Deleted : AbiClassInfo()
|
||||
}
|
||||
|
||||
@@ -62,6 +64,7 @@ sealed class AbiClassInfo {
|
||||
class JvmAbiClassBuilderInterceptor(
|
||||
private val removeDataClassCopyIfConstructorIsPrivate: Boolean,
|
||||
private val removePrivateClasses: Boolean,
|
||||
private val treatInternalAsPrivate: Boolean,
|
||||
) : ClassGeneratorExtension {
|
||||
private var abiClassInfoBuilder = JvmAbiClassInfoBuilder(removePrivateClasses)
|
||||
|
||||
@@ -80,18 +83,22 @@ class JvmAbiClassBuilderInterceptor(
|
||||
) : ClassGenerator by delegate {
|
||||
private val isPrivateClass = irClass != null && DescriptorVisibilities.isPrivate(irClass.visibility)
|
||||
private val isDataClass = irClass != null && irClass.isData
|
||||
private val removeClassFromAbi = shouldRemoveFromAbi(irClass, removePrivateClasses)
|
||||
private val removeClassFromAbi = shouldRemoveFromAbi(irClass, removePrivateClasses, treatInternalAsPrivate)
|
||||
|
||||
@OptIn(UnsafeDuringIrConstructionAPI::class)
|
||||
private val primaryConstructorIsNotInAbi =
|
||||
irClass?.primaryConstructor?.visibility?.let(DescriptorVisibilities::isPrivate) == true
|
||||
private val primaryConstructorIsNotInAbi = irClass
|
||||
?.primaryConstructor
|
||||
?.visibility
|
||||
?.let {
|
||||
DescriptorVisibilities.isPrivate(it) || (treatInternalAsPrivate && it == DescriptorVisibilities.INTERNAL)
|
||||
} == true
|
||||
|
||||
lateinit var internalName: String
|
||||
lateinit var superInterfaces: List<String>
|
||||
var localOrAnonymousClass = false
|
||||
var keepClassAsIs = false
|
||||
val methodInfos = mutableMapOf<Method, AbiMethodInfo>()
|
||||
val maskedMethods = mutableSetOf<Method>() // Methods which should be stripped even if they are marked as KEEP
|
||||
val memberInfos = mutableMapOf<JvmMemberSignature, AbiMethodInfo>()
|
||||
val maskedMethods = mutableSetOf<JvmMethodSignature>() // Methods which should be stripped even if they are marked as KEEP
|
||||
|
||||
override fun defineClass(
|
||||
version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<out String>
|
||||
@@ -110,6 +117,32 @@ class JvmAbiClassBuilderInterceptor(
|
||||
delegate.visitEnclosingMethod(owner, name, desc)
|
||||
}
|
||||
|
||||
override fun newField(
|
||||
declaration: IrField?, access: Int, name: String, desc: String, signature: String?, value: Any?
|
||||
): FieldVisitor {
|
||||
if (keepClassAsIs || removeClassFromAbi) {
|
||||
// We don't care about fields when we remove or keep this class completely.
|
||||
return delegate.newField(declaration, access, name, desc, signature, value)
|
||||
}
|
||||
|
||||
val visibility = declaration?.visibility ?: DescriptorVisibilities.DEFAULT_VISIBILITY
|
||||
|
||||
if (DescriptorVisibilities.isPrivate(visibility)) {
|
||||
// Remove all private fields.
|
||||
return delegate.newField(declaration, access, name, desc, signature, value)
|
||||
}
|
||||
|
||||
if (treatInternalAsPrivate && visibility == DescriptorVisibilities.INTERNAL) {
|
||||
// Remove all internal fields.
|
||||
return delegate.newField(declaration, access, name, desc, signature, value)
|
||||
}
|
||||
|
||||
// Keep otherwise.
|
||||
memberInfos[JvmFieldSignature(name, desc)] = AbiMethodInfo.KEEP
|
||||
|
||||
return delegate.newField(declaration, access, name, desc, signature, value)
|
||||
}
|
||||
|
||||
override fun newMethod(
|
||||
declaration: IrFunction?, access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?
|
||||
): MethodVisitor {
|
||||
@@ -125,8 +158,8 @@ class JvmAbiClassBuilderInterceptor(
|
||||
// and then checks for `f` if this method doesn't exist) so we have to remember to strip the
|
||||
// original methods if there was a $$forInline version.
|
||||
if (name.endsWith(FOR_INLINE_SUFFIX) && !isPrivateClass) {
|
||||
methodInfos[Method(name, desc)] = AbiMethodInfo.KEEP
|
||||
maskedMethods += Method(name.removeSuffix(FOR_INLINE_SUFFIX), desc)
|
||||
memberInfos[JvmMethodSignature(name, desc)] = AbiMethodInfo.KEEP
|
||||
maskedMethods += JvmMethodSignature(name.removeSuffix(FOR_INLINE_SUFFIX), desc)
|
||||
return delegate.newMethod(declaration, access, name, desc, signature, exceptions)
|
||||
}
|
||||
|
||||
@@ -138,6 +171,11 @@ class JvmAbiClassBuilderInterceptor(
|
||||
return delegate.newMethod(declaration, access, name, desc, signature, exceptions)
|
||||
}
|
||||
|
||||
// Remove internal functions from the ABI jars
|
||||
if (treatInternalAsPrivate && declaration?.visibility == DescriptorVisibilities.INTERNAL) {
|
||||
return delegate.newMethod(declaration, access, name, desc, signature, exceptions)
|
||||
}
|
||||
|
||||
if (isDataClass && removeDataClassCopyIfConstructorIsPrivate &&
|
||||
(name == "copy" || name == "copy${JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX}")
|
||||
) {
|
||||
@@ -148,9 +186,9 @@ class JvmAbiClassBuilderInterceptor(
|
||||
|
||||
// Copy inline functions verbatim
|
||||
if (declaration?.isInline == true && !isPrivateClass) {
|
||||
methodInfos[Method(name, desc)] = AbiMethodInfo.KEEP
|
||||
memberInfos[JvmMethodSignature(name, desc)] = AbiMethodInfo.KEEP
|
||||
} else {
|
||||
methodInfos[Method(name, desc)] = AbiMethodInfo.STRIP
|
||||
memberInfos[JvmMethodSignature(name, desc)] = AbiMethodInfo.STRIP
|
||||
}
|
||||
return delegate.newMethod(declaration, access, name, desc, signature, exceptions)
|
||||
}
|
||||
@@ -186,9 +224,9 @@ class JvmAbiClassBuilderInterceptor(
|
||||
isWhenMappingClass -> AbiClassInfo.Deleted
|
||||
else -> {
|
||||
for (method in maskedMethods) {
|
||||
methodInfos[method] = AbiMethodInfo.STRIP
|
||||
memberInfos[method] = AbiMethodInfo.STRIP
|
||||
}
|
||||
AbiClassInfo.Stripped(methodInfos)
|
||||
AbiClassInfo.Stripped(memberInfos)
|
||||
}
|
||||
}
|
||||
abiClassInfoBuilder.recordInitialClassInfo(internalName, classInfo, superInterfaces)
|
||||
@@ -200,9 +238,16 @@ class JvmAbiClassBuilderInterceptor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun shouldRemoveFromAbi(irClass: IrClass?, removePrivateClasses: Boolean): Boolean = when {
|
||||
private fun shouldRemoveFromAbi(irClass: IrClass?, removePrivateClasses: Boolean, treatInternalAsPrivate: Boolean): Boolean = when {
|
||||
irClass == null -> false
|
||||
irClass.isFileClass -> false
|
||||
removePrivateClasses -> irClass.isEffectivelyPrivate()
|
||||
removePrivateClasses -> irClass.isVisibilityStrippedFromAbi(stripInternal = treatInternalAsPrivate)
|
||||
else -> false
|
||||
}
|
||||
|
||||
private fun IrDeclarationWithVisibility.isVisibilityStrippedFromAbi(stripInternal: Boolean): Boolean {
|
||||
val isInAbi = visibility == DescriptorVisibilities.PUBLIC
|
||||
|| visibility == DescriptorVisibilities.PROTECTED
|
||||
|| (!stripInternal && visibility == DescriptorVisibilities.INTERNAL)
|
||||
return !isInAbi || parentClassOrNull?.isVisibilityStrippedFromAbi(stripInternal) == true
|
||||
}
|
||||
|
||||
@@ -60,6 +60,17 @@ class JvmAbiCommandLineProcessor : CommandLineProcessor {
|
||||
"private top-level classes will no longer be available from Java classes in the same package.",
|
||||
false,
|
||||
)
|
||||
val TREAT_INTERNAL_AS_PRIVATE_OPTION: CliOption =
|
||||
CliOption(
|
||||
"treatInternalAsPrivate",
|
||||
"true/false",
|
||||
"""Treat internal declarations as private and remove from ABI. False by default due to backwards compatibility.
|
||||
|If enabled, internal functions are removed and will no longer be available from Java if it's compiled against abi.jar.
|
||||
|Works best in conjunction with flags:
|
||||
| * removePrivateClasses - internal classes are being removed too;
|
||||
| * removeDataClassCopyIfConstructorIsPrivate - copy method is removed along with internal constructor.""".trimMargin(),
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
override val pluginId: String
|
||||
@@ -72,6 +83,7 @@ class JvmAbiCommandLineProcessor : CommandLineProcessor {
|
||||
REMOVE_DATA_CLASS_COPY_IF_CONSTRUCTOR_IS_PRIVATE_OPTION,
|
||||
PRESERVE_DECLARATION_ORDER_OPTION,
|
||||
REMOVE_PRIVATE_CLASSES_OPTION,
|
||||
TREAT_INTERNAL_AS_PRIVATE_OPTION,
|
||||
)
|
||||
|
||||
override fun processOption(option: AbstractCliOption, value: String, configuration: CompilerConfiguration) {
|
||||
@@ -87,6 +99,10 @@ class JvmAbiCommandLineProcessor : CommandLineProcessor {
|
||||
JvmAbiConfigurationKeys.REMOVE_PRIVATE_CLASSES,
|
||||
value == "true"
|
||||
)
|
||||
TREAT_INTERNAL_AS_PRIVATE_OPTION -> configuration.put(
|
||||
JvmAbiConfigurationKeys.TREAT_INTERNAL_AS_PRIVATE,
|
||||
value == "true"
|
||||
)
|
||||
else -> throw CliOptionProcessingException("Unknown option: ${option.optionName}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,12 +23,14 @@ class JvmAbiComponentRegistrar : CompilerPluginRegistrar() {
|
||||
val builderExtension = JvmAbiClassBuilderInterceptor(
|
||||
removeDataClassCopy,
|
||||
configuration.getBoolean(JvmAbiConfigurationKeys.REMOVE_PRIVATE_CLASSES),
|
||||
configuration.getBoolean(JvmAbiConfigurationKeys.TREAT_INTERNAL_AS_PRIVATE),
|
||||
)
|
||||
val outputExtension = JvmAbiOutputExtension(
|
||||
File(outputPath), builderExtension::buildAbiClassInfoAndReleaseResources,
|
||||
messageCollector, configuration.getBoolean(JvmAbiConfigurationKeys.REMOVE_DEBUG_INFO),
|
||||
removeDataClassCopy,
|
||||
configuration.getBoolean(JvmAbiConfigurationKeys.PRESERVE_DECLARATION_ORDER),
|
||||
configuration.getBoolean(JvmAbiConfigurationKeys.TREAT_INTERNAL_AS_PRIVATE),
|
||||
)
|
||||
|
||||
ClassGeneratorExtension.registerExtension(builderExtension)
|
||||
|
||||
@@ -18,4 +18,6 @@ object JvmAbiConfigurationKeys {
|
||||
CompilerConfigurationKey.create(JvmAbiCommandLineProcessor.PRESERVE_DECLARATION_ORDER_OPTION.description)
|
||||
val REMOVE_PRIVATE_CLASSES: CompilerConfigurationKey<Boolean> =
|
||||
CompilerConfigurationKey.create(JvmAbiCommandLineProcessor.REMOVE_PRIVATE_CLASSES_OPTION.description)
|
||||
val TREAT_INTERNAL_AS_PRIVATE: CompilerConfigurationKey<Boolean> =
|
||||
CompilerConfigurationKey.create(JvmAbiCommandLineProcessor.TREAT_INTERNAL_AS_PRIVATE_OPTION.description)
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ fun abiMetadataProcessor(
|
||||
preserveDeclarationOrder: Boolean,
|
||||
classesToBeDeleted: Set<String>,
|
||||
pruneClass: Boolean,
|
||||
treatInternalAsPrivate: Boolean,
|
||||
): AnnotationVisitor =
|
||||
kotlinClassHeaderVisitor { header ->
|
||||
// kotlinx-metadata only supports writing Kotlin metadata of version >= 1.4, so we need to
|
||||
@@ -39,14 +40,15 @@ fun abiMetadataProcessor(
|
||||
removeDataClassCopyIfConstructorIsPrivate,
|
||||
preserveDeclarationOrder,
|
||||
classesToBeDeleted,
|
||||
pruneClass
|
||||
pruneClass,
|
||||
treatInternalAsPrivate,
|
||||
)
|
||||
}
|
||||
is KotlinClassMetadata.FileFacade -> {
|
||||
metadata.kmPackage.removePrivateDeclarations(preserveDeclarationOrder, pruneClass)
|
||||
metadata.kmPackage.removePrivateDeclarations(preserveDeclarationOrder, pruneClass, treatInternalAsPrivate)
|
||||
}
|
||||
is KotlinClassMetadata.MultiFileClassPart -> {
|
||||
metadata.kmPackage.removePrivateDeclarations(preserveDeclarationOrder, pruneClass)
|
||||
metadata.kmPackage.removePrivateDeclarations(preserveDeclarationOrder, pruneClass, treatInternalAsPrivate)
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
@@ -162,12 +164,14 @@ private fun KmClass.removePrivateDeclarations(
|
||||
preserveDeclarationOrder: Boolean,
|
||||
classesToBeDeleted: Set<String>,
|
||||
pruneClass: Boolean,
|
||||
treatInternalAsPrivate: Boolean,
|
||||
) {
|
||||
constructors.removeIf { pruneClass || it.visibility.isPrivate }
|
||||
constructors.removeIf { pruneClass || it.visibility.shouldRemove(treatInternalAsPrivate) }
|
||||
(this as KmDeclarationContainer).removePrivateDeclarations(
|
||||
copyFunShouldBeDeleted(removeCopyAlongWithConstructor),
|
||||
preserveDeclarationOrder,
|
||||
pruneClass,
|
||||
treatInternalAsPrivate,
|
||||
)
|
||||
nestedClasses.removeIf { "$name\$$it" in classesToBeDeleted }
|
||||
companionObject = companionObject.takeUnless { "$name\$$it" in classesToBeDeleted }
|
||||
@@ -175,8 +179,12 @@ private fun KmClass.removePrivateDeclarations(
|
||||
// TODO: do not serialize private type aliases once KT-17229 is fixed.
|
||||
}
|
||||
|
||||
private fun KmPackage.removePrivateDeclarations(preserveDeclarationOrder: Boolean, pruneClass: Boolean) {
|
||||
(this as KmDeclarationContainer).removePrivateDeclarations(false, preserveDeclarationOrder, pruneClass)
|
||||
private fun KmPackage.removePrivateDeclarations(
|
||||
preserveDeclarationOrder: Boolean,
|
||||
pruneClass: Boolean,
|
||||
treatInternalAsPrivate: Boolean,
|
||||
) {
|
||||
(this as KmDeclarationContainer).removePrivateDeclarations(false, preserveDeclarationOrder, pruneClass, treatInternalAsPrivate)
|
||||
localDelegatedProperties.clear()
|
||||
// TODO: do not serialize private type aliases once KT-17229 is fixed.
|
||||
}
|
||||
@@ -185,9 +193,10 @@ private fun KmDeclarationContainer.removePrivateDeclarations(
|
||||
copyFunShouldBeDeleted: Boolean,
|
||||
preserveDeclarationOrder: Boolean,
|
||||
pruneClass: Boolean,
|
||||
treatInternalAsPrivate: Boolean,
|
||||
) {
|
||||
functions.removeIf { pruneClass || it.visibility.isPrivate || (copyFunShouldBeDeleted && it.name == "copy") }
|
||||
properties.removeIf { pruneClass || it.visibility.isPrivate }
|
||||
functions.removeIf { pruneClass || it.visibility.shouldRemove(treatInternalAsPrivate) || (copyFunShouldBeDeleted && it.name == "copy") }
|
||||
properties.removeIf { pruneClass || it.visibility.shouldRemove(treatInternalAsPrivate) }
|
||||
|
||||
if (!preserveDeclarationOrder) {
|
||||
functions.sortWith(compareBy(KmFunction::name, { it.signature.toString() }))
|
||||
@@ -205,5 +214,9 @@ private fun KmDeclarationContainer.removePrivateDeclarations(
|
||||
private fun KmClass.copyFunShouldBeDeleted(removeDataClassCopy: Boolean): Boolean =
|
||||
removeDataClassCopy && isData && constructors.none { !it.isSecondary }
|
||||
|
||||
private val Visibility.isPrivate: Boolean
|
||||
get() = this == Visibility.PRIVATE || this == Visibility.PRIVATE_TO_THIS || this == Visibility.LOCAL
|
||||
private fun Visibility.shouldRemove(treatInternalAsPrivate: Boolean): Boolean {
|
||||
return this == Visibility.PRIVATE ||
|
||||
this == Visibility.PRIVATE_TO_THIS ||
|
||||
this == Visibility.LOCAL ||
|
||||
(treatInternalAsPrivate && this == Visibility.INTERNAL)
|
||||
}
|
||||
|
||||
@@ -16,11 +16,12 @@ import org.jetbrains.kotlin.codegen.extensions.ClassFileFactoryFinalizerExtensio
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
import org.jetbrains.org.objectweb.asm.commons.ClassRemapper
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
import org.jetbrains.org.objectweb.asm.commons.Remapper
|
||||
import org.jetbrains.org.objectweb.asm.tree.FieldNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
import java.io.File
|
||||
import kotlin.metadata.jvm.JvmFieldSignature
|
||||
import kotlin.metadata.jvm.JvmMethodSignature
|
||||
|
||||
class JvmAbiOutputExtension(
|
||||
private val outputPath: File,
|
||||
@@ -29,12 +30,20 @@ class JvmAbiOutputExtension(
|
||||
private val removeDebugInfo: Boolean,
|
||||
private val removeDataClassCopyIfConstructorIsPrivate: Boolean,
|
||||
private val preserveDeclarationOrder: Boolean,
|
||||
private val treatInternalAsPrivate: Boolean,
|
||||
) : ClassFileFactoryFinalizerExtension {
|
||||
override fun finalizeClassFactory(factory: ClassFileFactory) {
|
||||
// We need to wait until the end to produce any output in order to strip classes
|
||||
// from the InnerClasses attributes.
|
||||
val outputFiles =
|
||||
AbiOutputFiles(abiClassInfoBuilder(), factory, removeDebugInfo, removeDataClassCopyIfConstructorIsPrivate, preserveDeclarationOrder)
|
||||
AbiOutputFiles(
|
||||
abiClassInfoBuilder(),
|
||||
factory,
|
||||
removeDebugInfo,
|
||||
removeDataClassCopyIfConstructorIsPrivate,
|
||||
preserveDeclarationOrder,
|
||||
treatInternalAsPrivate,
|
||||
)
|
||||
if (outputPath.extension == "jar") {
|
||||
// We don't include the runtime or main class in interface jars and always reset time stamps.
|
||||
CompileEnvironmentUtil.writeToJar(
|
||||
@@ -59,6 +68,7 @@ class JvmAbiOutputExtension(
|
||||
val removeDebugInfo: Boolean,
|
||||
val removeCopyAlongWithConstructor: Boolean,
|
||||
val preserveDeclarationOrder: Boolean,
|
||||
val treatInternalAsPrivate: Boolean,
|
||||
) : OutputFileCollection {
|
||||
private val classesToBeDeleted = abiClassInfos.mapNotNullTo(mutableSetOf()) { (className, action) ->
|
||||
className.takeIf { action == AbiClassInfo.Deleted }
|
||||
@@ -82,9 +92,9 @@ class JvmAbiOutputExtension(
|
||||
is AbiClassInfo.Public -> outputFile // Copy verbatim
|
||||
is AbiClassInfo.Stripped -> {
|
||||
val prune = abiInfo.prune
|
||||
val methodInfo = abiInfo.methodInfo
|
||||
val memberInfo = abiInfo.memberInfo
|
||||
val innerClassesToKeep = mutableSetOf<String>()
|
||||
val noMethodsKept = methodInfo.values.none { it == AbiMethodInfo.KEEP }
|
||||
val noMethodsKept = memberInfo.none { it.value == AbiMethodInfo.KEEP && it.key is JvmMethodSignature }
|
||||
val writer = ClassWriter(0)
|
||||
val remapper = ClassRemapper(writer, object : Remapper() {
|
||||
override fun map(internalName: String): String =
|
||||
@@ -98,12 +108,12 @@ class JvmAbiOutputExtension(
|
||||
// Strip private fields.
|
||||
override fun visitField(
|
||||
access: Int,
|
||||
name: String?,
|
||||
descriptor: String?,
|
||||
name: String,
|
||||
descriptor: String,
|
||||
signature: String?,
|
||||
value: Any?,
|
||||
): FieldVisitor? {
|
||||
if (prune || access and Opcodes.ACC_PRIVATE != 0)
|
||||
if (prune || memberInfo[JvmFieldSignature(name, descriptor)] != AbiMethodInfo.KEEP)
|
||||
return null
|
||||
return FieldNode(access, name, descriptor, signature, value).also {
|
||||
keptFields += it
|
||||
@@ -118,7 +128,7 @@ class JvmAbiOutputExtension(
|
||||
exceptions: Array<out String>?
|
||||
): MethodVisitor? {
|
||||
if (prune) return null
|
||||
val info = methodInfo[Method(name, descriptor)] ?: return null
|
||||
val info = memberInfo[JvmMethodSignature(name, descriptor)] ?: return null
|
||||
|
||||
val node = MethodNode(access, name, descriptor, signature, exceptions).also {
|
||||
keptMethods += it
|
||||
@@ -164,7 +174,8 @@ class JvmAbiOutputExtension(
|
||||
removeCopyAlongWithConstructor,
|
||||
preserveDeclarationOrder,
|
||||
classesToBeDeleted,
|
||||
prune
|
||||
prune,
|
||||
treatInternalAsPrivate,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,9 @@ abstract class BaseJvmAbiTest : TestCase() {
|
||||
abiOption(JvmAbiCommandLineProcessor.REMOVE_PRIVATE_CLASSES_OPTION.optionName, true.toString()).takeIf {
|
||||
InTextDirectivesUtils.findStringWithPrefixes(directives, "// REMOVE_PRIVATE_CLASSES") != null
|
||||
},
|
||||
abiOption(JvmAbiCommandLineProcessor.TREAT_INTERNAL_AS_PRIVATE_OPTION.optionName, true.toString()).takeIf {
|
||||
InTextDirectivesUtils.findStringWithPrefixes(directives, "// TREAT_INTERNAL_AS_PRIVATE") != null
|
||||
},
|
||||
).toTypedArray()
|
||||
destination = compilation.destinationDir.canonicalPath
|
||||
noSourceDebugExtension = InTextDirectivesUtils.findStringWithPrefixes(directives, "// NO_SOURCE_DEBUG_EXTENSION") != null
|
||||
|
||||
+10
@@ -135,6 +135,16 @@ public class CompareJvmAbiTestGenerated extends AbstractCompareJvmAbiTest {
|
||||
runTest("plugins/jvm-abi-gen/testData/compare/inlineFunctionBody/");
|
||||
}
|
||||
|
||||
@TestMetadata("internalDeclarationsStrict")
|
||||
public void testInternalDeclarationsStrict() {
|
||||
runTest("plugins/jvm-abi-gen/testData/compare/internalDeclarationsStrict/");
|
||||
}
|
||||
|
||||
@TestMetadata("internalFields")
|
||||
public void testInternalFields() {
|
||||
runTest("plugins/jvm-abi-gen/testData/compare/internalFields/");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdas")
|
||||
public void testLambdas() {
|
||||
runTest("plugins/jvm-abi-gen/testData/compare/lambdas/");
|
||||
|
||||
+10
@@ -65,6 +65,16 @@ public class JvmAbiContentTestGenerated extends AbstractJvmAbiContentTest {
|
||||
runTest("plugins/jvm-abi-gen/testData/content/innerClasses/");
|
||||
}
|
||||
|
||||
@TestMetadata("internalClassAndCopyMethod")
|
||||
public void testInternalClassAndCopyMethod() {
|
||||
runTest("plugins/jvm-abi-gen/testData/content/internalClassAndCopyMethod/");
|
||||
}
|
||||
|
||||
@TestMetadata("internalClassAndCopyMethodStrict")
|
||||
public void testInternalClassAndCopyMethodStrict() {
|
||||
runTest("plugins/jvm-abi-gen/testData/content/internalClassAndCopyMethodStrict/");
|
||||
}
|
||||
|
||||
@TestMetadata("kt50005")
|
||||
public void testKt50005() {
|
||||
runTest("plugins/jvm-abi-gen/testData/content/kt50005/");
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package test
|
||||
|
||||
internal fun funToBeRemoved() = Unit
|
||||
|
||||
internal fun internalTopLevelInlineFun() = Unit
|
||||
|
||||
internal class TopLevelClassToBeRemoved
|
||||
|
||||
fun emptyKtClassWorkaround() = Unit
|
||||
class PublicOuterClass {
|
||||
|
||||
@JvmField
|
||||
internal val fieldToBeRemoved = Unit
|
||||
|
||||
internal interface InternalInterfaceToBeRemoved
|
||||
|
||||
internal class InnerClass: InternalInterfaceToBeRemoved {
|
||||
fun everyDeclarationShouldBeRemoved() = Unit
|
||||
|
||||
inline fun shouldBeRemoved() = Unit
|
||||
|
||||
class EffectivelyInternalClassRemoved
|
||||
}
|
||||
|
||||
internal interface TransitivelyPublicInterface
|
||||
|
||||
data class Data internal constructor(
|
||||
val couldNotBeRemoved: String,
|
||||
internal val shouldBeRemoved: Any,
|
||||
): TransitivelyPublicInterface
|
||||
|
||||
internal inline fun shouldBeRemoved() = Unit
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
// TREAT_INTERNAL_AS_PRIVATE
|
||||
// REMOVE_PRIVATE_CLASSES
|
||||
// REMOVE_DATA_CLASS_COPY_IF_CONSTRUCTOR_IS_PRIVATE
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package test
|
||||
|
||||
fun emptyKtClassWorkaround() = Unit
|
||||
class PublicOuterClass {
|
||||
|
||||
internal interface TransitivelyPublicInterface
|
||||
|
||||
data class Data internal constructor(
|
||||
val couldNotBeRemoved: String
|
||||
): TransitivelyPublicInterface
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package test
|
||||
|
||||
@JvmField
|
||||
internal val a: String = ""
|
||||
|
||||
internal val b: String = ""
|
||||
|
||||
fun emptyKtClassWorkaround() = Unit
|
||||
class Class {
|
||||
@JvmField
|
||||
internal val a: String = ""
|
||||
|
||||
internal val b: String = ""
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
// TREAT_INTERNAL_AS_PRIVATE
|
||||
@@ -0,0 +1,4 @@
|
||||
package test
|
||||
|
||||
fun emptyKtClassWorkaround() = Unit
|
||||
class Class
|
||||
+1
@@ -0,0 +1 @@
|
||||
// TREAT_INTERNAL_AS_PRIVATE
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
@kotlin.Metadata
|
||||
public final class test/Test$ConstructorToBeRemoved {
|
||||
// source: 'test.kt'
|
||||
public final inner class test/Test$ConstructorToBeRemoved
|
||||
public final @org.jetbrains.annotations.NotNull method copy(@org.jetbrains.annotations.NotNull p0: java.lang.Object): test.Test$ConstructorToBeRemoved
|
||||
public synthetic static method copy$default(p0: test.Test$ConstructorToBeRemoved, p1: java.lang.Object, p2: int, p3: java.lang.Object): test.Test$ConstructorToBeRemoved
|
||||
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||
public method hashCode(): int
|
||||
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||
}
|
||||
@kotlin.Metadata
|
||||
public final class test/Test {
|
||||
// source: 'test.kt'
|
||||
public final inner class test/Test$ConstructorToBeRemoved
|
||||
public method <init>(): void
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package test
|
||||
|
||||
class Test {
|
||||
internal data class ConstructorToBeRemoved internal constructor(internal val fieldToBeRemoved: Any)
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
// TREAT_INTERNAL_AS_PRIVATE
|
||||
// REMOVE_PRIVATE_CLASSES
|
||||
// REMOVE_DATA_CLASS_COPY_IF_CONSTRUCTOR_IS_PRIVATE
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
@kotlin.Metadata
|
||||
public final class test/Test$EverythingExceptTheClassAndPropertyToBeRemoved {
|
||||
// source: 'test.kt'
|
||||
public final inner class test/Test$EverythingExceptTheClassAndPropertyToBeRemoved
|
||||
public final @org.jetbrains.annotations.NotNull method component1(): java.lang.Object
|
||||
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||
public final @org.jetbrains.annotations.NotNull method getA(): java.lang.Object
|
||||
public method hashCode(): int
|
||||
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||
}
|
||||
@kotlin.Metadata
|
||||
public final class test/Test {
|
||||
// source: 'test.kt'
|
||||
public final inner class test/Test$EverythingExceptTheClassAndPropertyToBeRemoved
|
||||
public method <init>(): void
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
class Test {
|
||||
internal data class ClassToBeRemoved internal constructor(val a: Any)
|
||||
|
||||
data class EverythingExceptTheClassAndPropertyToBeRemoved internal constructor(val a: Any)
|
||||
}
|
||||
Reference in New Issue
Block a user