diff --git a/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiClassBuilderInterceptor.kt b/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiClassBuilderInterceptor.kt index 5eec5586898..7bb7051faa4 100644 --- a/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiClassBuilderInterceptor.kt +++ b/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiClassBuilderInterceptor.kt @@ -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, val prune: Boolean = false) : AbiClassInfo() + class Stripped(val memberInfo: Map, 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 var localOrAnonymousClass = false var keepClassAsIs = false - val methodInfos = mutableMapOf() - val maskedMethods = mutableSetOf() // Methods which should be stripped even if they are marked as KEEP + val memberInfos = mutableMapOf() + val maskedMethods = mutableSetOf() // 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 @@ -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? ): 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 +} diff --git a/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiCommandLineProcessor.kt b/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiCommandLineProcessor.kt index e6c39fdfbb6..c74b77fceb0 100644 --- a/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiCommandLineProcessor.kt +++ b/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiCommandLineProcessor.kt @@ -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}") } } diff --git a/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiComponentRegistrar.kt b/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiComponentRegistrar.kt index 48ee2c4b31b..e2f799c3490 100644 --- a/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiComponentRegistrar.kt +++ b/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiComponentRegistrar.kt @@ -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) diff --git a/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiConfigurationKeys.kt b/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiConfigurationKeys.kt index 8a20fd4ff20..c4704d2f64a 100644 --- a/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiConfigurationKeys.kt +++ b/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiConfigurationKeys.kt @@ -18,4 +18,6 @@ object JvmAbiConfigurationKeys { CompilerConfigurationKey.create(JvmAbiCommandLineProcessor.PRESERVE_DECLARATION_ORDER_OPTION.description) val REMOVE_PRIVATE_CLASSES: CompilerConfigurationKey = CompilerConfigurationKey.create(JvmAbiCommandLineProcessor.REMOVE_PRIVATE_CLASSES_OPTION.description) + val TREAT_INTERNAL_AS_PRIVATE: CompilerConfigurationKey = + CompilerConfigurationKey.create(JvmAbiCommandLineProcessor.TREAT_INTERNAL_AS_PRIVATE_OPTION.description) } diff --git a/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiMetadataProcessor.kt b/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiMetadataProcessor.kt index c9c811c2897..ff5e78c3ee5 100644 --- a/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiMetadataProcessor.kt +++ b/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiMetadataProcessor.kt @@ -21,6 +21,7 @@ fun abiMetadataProcessor( preserveDeclarationOrder: Boolean, classesToBeDeleted: Set, 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, 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) +} diff --git a/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiOutputExtension.kt b/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiOutputExtension.kt index d5f3b5c4ec2..610b4f9ba1a 100644 --- a/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiOutputExtension.kt +++ b/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiOutputExtension.kt @@ -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() - 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? ): 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, ) } diff --git a/plugins/jvm-abi-gen/test/org/jetbrains/kotlin/jvm/abi/BaseJvmAbiTest.kt b/plugins/jvm-abi-gen/test/org/jetbrains/kotlin/jvm/abi/BaseJvmAbiTest.kt index 02cc74ff8eb..290c3d59cc3 100644 --- a/plugins/jvm-abi-gen/test/org/jetbrains/kotlin/jvm/abi/BaseJvmAbiTest.kt +++ b/plugins/jvm-abi-gen/test/org/jetbrains/kotlin/jvm/abi/BaseJvmAbiTest.kt @@ -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 diff --git a/plugins/jvm-abi-gen/test/org/jetbrains/kotlin/jvm/abi/CompareJvmAbiTestGenerated.java b/plugins/jvm-abi-gen/test/org/jetbrains/kotlin/jvm/abi/CompareJvmAbiTestGenerated.java index 95558462df1..8ff70f478b1 100644 --- a/plugins/jvm-abi-gen/test/org/jetbrains/kotlin/jvm/abi/CompareJvmAbiTestGenerated.java +++ b/plugins/jvm-abi-gen/test/org/jetbrains/kotlin/jvm/abi/CompareJvmAbiTestGenerated.java @@ -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/"); diff --git a/plugins/jvm-abi-gen/test/org/jetbrains/kotlin/jvm/abi/JvmAbiContentTestGenerated.java b/plugins/jvm-abi-gen/test/org/jetbrains/kotlin/jvm/abi/JvmAbiContentTestGenerated.java index 0aa44224519..a57d9be010c 100644 --- a/plugins/jvm-abi-gen/test/org/jetbrains/kotlin/jvm/abi/JvmAbiContentTestGenerated.java +++ b/plugins/jvm-abi-gen/test/org/jetbrains/kotlin/jvm/abi/JvmAbiContentTestGenerated.java @@ -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/"); diff --git a/plugins/jvm-abi-gen/testData/compare/internalDeclarationsStrict/base/test.kt b/plugins/jvm-abi-gen/testData/compare/internalDeclarationsStrict/base/test.kt new file mode 100644 index 00000000000..8526e374381 --- /dev/null +++ b/plugins/jvm-abi-gen/testData/compare/internalDeclarationsStrict/base/test.kt @@ -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 +} diff --git a/plugins/jvm-abi-gen/testData/compare/internalDeclarationsStrict/directives.txt b/plugins/jvm-abi-gen/testData/compare/internalDeclarationsStrict/directives.txt new file mode 100644 index 00000000000..bd744dfe11b --- /dev/null +++ b/plugins/jvm-abi-gen/testData/compare/internalDeclarationsStrict/directives.txt @@ -0,0 +1,3 @@ +// TREAT_INTERNAL_AS_PRIVATE +// REMOVE_PRIVATE_CLASSES +// REMOVE_DATA_CLASS_COPY_IF_CONSTRUCTOR_IS_PRIVATE diff --git a/plugins/jvm-abi-gen/testData/compare/internalDeclarationsStrict/sameAbi/test.kt b/plugins/jvm-abi-gen/testData/compare/internalDeclarationsStrict/sameAbi/test.kt new file mode 100644 index 00000000000..7bde77c1a68 --- /dev/null +++ b/plugins/jvm-abi-gen/testData/compare/internalDeclarationsStrict/sameAbi/test.kt @@ -0,0 +1,11 @@ +package test + +fun emptyKtClassWorkaround() = Unit +class PublicOuterClass { + + internal interface TransitivelyPublicInterface + + data class Data internal constructor( + val couldNotBeRemoved: String + ): TransitivelyPublicInterface +} diff --git a/plugins/jvm-abi-gen/testData/compare/internalFields/base/test.kt b/plugins/jvm-abi-gen/testData/compare/internalFields/base/test.kt new file mode 100644 index 00000000000..09c5159d8f1 --- /dev/null +++ b/plugins/jvm-abi-gen/testData/compare/internalFields/base/test.kt @@ -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 = "" +} diff --git a/plugins/jvm-abi-gen/testData/compare/internalFields/directives.txt b/plugins/jvm-abi-gen/testData/compare/internalFields/directives.txt new file mode 100644 index 00000000000..bef5b0586d3 --- /dev/null +++ b/plugins/jvm-abi-gen/testData/compare/internalFields/directives.txt @@ -0,0 +1 @@ +// TREAT_INTERNAL_AS_PRIVATE diff --git a/plugins/jvm-abi-gen/testData/compare/internalFields/sameAbi/test.kt b/plugins/jvm-abi-gen/testData/compare/internalFields/sameAbi/test.kt new file mode 100644 index 00000000000..f37300b5acc --- /dev/null +++ b/plugins/jvm-abi-gen/testData/compare/internalFields/sameAbi/test.kt @@ -0,0 +1,4 @@ +package test + +fun emptyKtClassWorkaround() = Unit +class Class diff --git a/plugins/jvm-abi-gen/testData/content/internalClassAndCopyMethod/directives.txt b/plugins/jvm-abi-gen/testData/content/internalClassAndCopyMethod/directives.txt new file mode 100644 index 00000000000..bef5b0586d3 --- /dev/null +++ b/plugins/jvm-abi-gen/testData/content/internalClassAndCopyMethod/directives.txt @@ -0,0 +1 @@ +// TREAT_INTERNAL_AS_PRIVATE diff --git a/plugins/jvm-abi-gen/testData/content/internalClassAndCopyMethod/signatures.txt b/plugins/jvm-abi-gen/testData/content/internalClassAndCopyMethod/signatures.txt new file mode 100644 index 00000000000..15526b9a127 --- /dev/null +++ b/plugins/jvm-abi-gen/testData/content/internalClassAndCopyMethod/signatures.txt @@ -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 (): void +} diff --git a/plugins/jvm-abi-gen/testData/content/internalClassAndCopyMethod/test.kt b/plugins/jvm-abi-gen/testData/content/internalClassAndCopyMethod/test.kt new file mode 100644 index 00000000000..e1d071d2257 --- /dev/null +++ b/plugins/jvm-abi-gen/testData/content/internalClassAndCopyMethod/test.kt @@ -0,0 +1,5 @@ +package test + +class Test { + internal data class ConstructorToBeRemoved internal constructor(internal val fieldToBeRemoved: Any) +} diff --git a/plugins/jvm-abi-gen/testData/content/internalClassAndCopyMethodStrict/directives.txt b/plugins/jvm-abi-gen/testData/content/internalClassAndCopyMethodStrict/directives.txt new file mode 100644 index 00000000000..bd744dfe11b --- /dev/null +++ b/plugins/jvm-abi-gen/testData/content/internalClassAndCopyMethodStrict/directives.txt @@ -0,0 +1,3 @@ +// TREAT_INTERNAL_AS_PRIVATE +// REMOVE_PRIVATE_CLASSES +// REMOVE_DATA_CLASS_COPY_IF_CONSTRUCTOR_IS_PRIVATE diff --git a/plugins/jvm-abi-gen/testData/content/internalClassAndCopyMethodStrict/signatures.txt b/plugins/jvm-abi-gen/testData/content/internalClassAndCopyMethodStrict/signatures.txt new file mode 100644 index 00000000000..a42d86e19b4 --- /dev/null +++ b/plugins/jvm-abi-gen/testData/content/internalClassAndCopyMethodStrict/signatures.txt @@ -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 (): void +} diff --git a/plugins/jvm-abi-gen/testData/content/internalClassAndCopyMethodStrict/test.kt b/plugins/jvm-abi-gen/testData/content/internalClassAndCopyMethodStrict/test.kt new file mode 100644 index 00000000000..a481368ed18 --- /dev/null +++ b/plugins/jvm-abi-gen/testData/content/internalClassAndCopyMethodStrict/test.kt @@ -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) +}