diff --git a/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiAnalysisHandlerExtension.kt b/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiAnalysisHandlerExtension.kt index 4a107988bb1..ff4fc896914 100644 --- a/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiAnalysisHandlerExtension.kt +++ b/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiAnalysisHandlerExtension.kt @@ -16,7 +16,14 @@ import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.diagnostics.Severity +import org.jetbrains.kotlin.incremental.LocalFileKotlinClass +import org.jetbrains.kotlin.incremental.isClassFile import org.jetbrains.kotlin.jvm.abi.asm.AbiClassBuilder +import org.jetbrains.kotlin.jvm.abi.asm.FilterInnerClassesVisitor +import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader +import org.jetbrains.kotlin.metadata.ProtoBuf +import org.jetbrains.kotlin.metadata.deserialization.Flags +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil import org.jetbrains.kotlin.modules.TargetId import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.BindingTrace @@ -53,13 +60,43 @@ class JvmAbiAnalysisHandlerExtension( KotlinCodegenFacade.compileCorrectFiles(generationState, CompilationErrorHandler.THROW_EXCEPTION) val outputDir = compilerConfiguration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY)!! + val outputFiles = arrayListOf() generationState.factory.writeAll( outputDir, fun(file: OutputFile, sources: List, output: File) { // todo report + outputFiles.add(output) } ) + val classFiles = HashSet() + val removedClasses = HashSet() + for (file in outputFiles) { + if (!file.isClassFile()) continue + + classFiles.add(file) + val localFileKotlinClass = LocalFileKotlinClass.create(file) ?: continue + val header = localFileKotlinClass.classHeader + if (header.kind == KotlinClassHeader.Kind.CLASS) { + val (_, classProto) = JvmProtoBufUtil.readClassDataFrom(header.data!!, header.strings!!) + + val visibility = Flags.VISIBILITY.get(classProto.flags) + if (visibility == ProtoBuf.Visibility.PRIVATE || visibility == ProtoBuf.Visibility.LOCAL) { + file.delete() + classFiles.remove(file) + removedClasses.add(localFileKotlinClass.className.internalName) + } + } + } + + for (file in classFiles) { + val reader = ClassReader(file.readBytes()) + val writer = ClassWriter(reader, 0) + val visitor = FilterInnerClassesVisitor(removedClasses, Opcodes.ASM6, writer) + reader.accept(visitor, 0) + file.writeBytes(writer.toByteArray()) + } + return null } diff --git a/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/asm/FilterInnerClassesVisitor.kt b/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/asm/FilterInnerClassesVisitor.kt new file mode 100644 index 00000000000..4f6c283ca13 --- /dev/null +++ b/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/asm/FilterInnerClassesVisitor.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.jvm.abi.asm + +import org.jetbrains.org.objectweb.asm.ClassVisitor + +internal class FilterInnerClassesVisitor( + private val innerClassesToFilter: Set, + api: Int, + cv: ClassVisitor +) : ClassVisitor(api, cv) { + override fun visitInnerClass(name: String, outerName: String?, innerName: String?, access: Int) { + if (name in innerClassesToFilter) return + + super.visitInnerClass(name, outerName, innerName, access) + } +} \ No newline at end of file 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 d9ecb4f9483..9c29e97e678 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 @@ -44,6 +44,16 @@ public class CompareJvmAbiTestGenerated extends AbstractCompareJvmAbiTest { runTest("plugins/jvm-abi-gen/testData/compare/inlineFunctionBody/"); } + @TestMetadata("localClass") + public void testLocalClass() throws Exception { + runTest("plugins/jvm-abi-gen/testData/compare/localClass/"); + } + + @TestMetadata("privateClass") + public void testPrivateClass() throws Exception { + runTest("plugins/jvm-abi-gen/testData/compare/privateClass/"); + } + @TestMetadata("topLevelPrivateMembers") public void testTopLevelPrivateMembers() throws Exception { runTest("plugins/jvm-abi-gen/testData/compare/topLevelPrivateMembers/"); diff --git a/plugins/jvm-abi-gen/testData/compare/localClass/base/Class.kt b/plugins/jvm-abi-gen/testData/compare/localClass/base/Class.kt new file mode 100644 index 00000000000..57d7d8b89e7 --- /dev/null +++ b/plugins/jvm-abi-gen/testData/compare/localClass/base/Class.kt @@ -0,0 +1,7 @@ +package test + +class Class { + fun method() { + class MethodLocalClass + } +} \ No newline at end of file diff --git a/plugins/jvm-abi-gen/testData/compare/localClass/base/function.kt b/plugins/jvm-abi-gen/testData/compare/localClass/base/function.kt new file mode 100644 index 00000000000..91e4a2c7fec --- /dev/null +++ b/plugins/jvm-abi-gen/testData/compare/localClass/base/function.kt @@ -0,0 +1,5 @@ +package test + +fun function() { + class FunctionLocalClass +} \ No newline at end of file diff --git a/plugins/jvm-abi-gen/testData/compare/localClass/sameAbi/Class.kt b/plugins/jvm-abi-gen/testData/compare/localClass/sameAbi/Class.kt new file mode 100644 index 00000000000..192676f9a79 --- /dev/null +++ b/plugins/jvm-abi-gen/testData/compare/localClass/sameAbi/Class.kt @@ -0,0 +1,6 @@ +package test + +class Class { + fun method() { + } +} \ No newline at end of file diff --git a/plugins/jvm-abi-gen/testData/compare/localClass/sameAbi/function.kt b/plugins/jvm-abi-gen/testData/compare/localClass/sameAbi/function.kt new file mode 100644 index 00000000000..92f421c23ff --- /dev/null +++ b/plugins/jvm-abi-gen/testData/compare/localClass/sameAbi/function.kt @@ -0,0 +1,4 @@ +package test + +fun function() { +} \ No newline at end of file diff --git a/plugins/jvm-abi-gen/testData/compare/privateClass/base/classes.kt b/plugins/jvm-abi-gen/testData/compare/privateClass/base/classes.kt new file mode 100644 index 00000000000..c5b914f5538 --- /dev/null +++ b/plugins/jvm-abi-gen/testData/compare/privateClass/base/classes.kt @@ -0,0 +1,5 @@ +package test + +class PublicClass +internal class InternalClass +private class PrivateClass \ No newline at end of file diff --git a/plugins/jvm-abi-gen/testData/compare/privateClass/sameAbi/classes.kt b/plugins/jvm-abi-gen/testData/compare/privateClass/sameAbi/classes.kt new file mode 100644 index 00000000000..ef3fc325d30 --- /dev/null +++ b/plugins/jvm-abi-gen/testData/compare/privateClass/sameAbi/classes.kt @@ -0,0 +1,4 @@ +package test + +class PublicClass +internal class InternalClass \ No newline at end of file