From 23d6690581d4aae0c87f5669560b9c1950f33264 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 19 Sep 2017 19:09:17 +0300 Subject: [PATCH] Fix codegen for multifile class parts with type aliases only #KT-20337 Fixed --- .../kotlin/codegen/MultifileClassCodegen.kt | 2 +- .../codegen/MultifileClassPartCodegen.kt | 24 +------- .../kotlin/codegen/PackagePartCodegen.java | 57 +++++++++++-------- .../multifileClassWithTypealias.kt | 16 ++++++ ...mpileKotlinAgainstKotlinTestGenerated.java | 6 ++ 5 files changed, 56 insertions(+), 49 deletions(-) create mode 100644 compiler/testData/compileKotlinAgainstKotlin/multifileClassWithTypealias.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassCodegen.kt index 0b3c6a0b45b..bd17339567c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassCodegen.kt @@ -368,7 +368,7 @@ class MultifileClassCodegenImpl( } private fun KtFile.hasDeclarationsForPartClass() = - CodegenUtil.getActualDeclarations(this).any { it is KtProperty || it is KtFunction } + CodegenUtil.getActualDeclarations(this).any { it is KtProperty || it is KtFunction || it is KtTypeAlias } private fun getCompiledPackageFragment( facadeFqName: FqName, state: GenerationState diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassPartCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassPartCodegen.kt index bad8b7e4975..f782c31de52 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassPartCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassPartCodegen.kt @@ -19,7 +19,6 @@ package org.jetbrains.kotlin.codegen import com.intellij.util.ArrayUtil import org.jetbrains.kotlin.backend.common.CodegenUtil import org.jetbrains.kotlin.codegen.context.MultifileClassPartContext -import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor @@ -29,16 +28,13 @@ import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.psi.KtTypeAlias -import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.jvm.diagnostics.MultifileClass import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin -import org.jetbrains.kotlin.serialization.DescriptorSerializer import org.jetbrains.org.objectweb.asm.MethodVisitor import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode -import java.util.* class MultifileClassPartCodegen( v: ClassBuilder, @@ -162,25 +158,7 @@ class MultifileClassPartCodegen( } override fun generateKotlinMetadataAnnotation() { - val members = ArrayList() - for (declaration in CodegenUtil.getActualDeclarations(element)) { - when (declaration) { - is KtNamedFunction -> { - val functionDescriptor = bindingContext.get(BindingContext.FUNCTION, declaration) - members.add(functionDescriptor ?: throw AssertionError("Function ${declaration.name} is not bound in ${element.name}")) - } - is KtProperty -> { - val property = bindingContext.get(BindingContext.VARIABLE, declaration) - members.add(property ?: throw AssertionError("Property ${declaration.name} is not bound in ${element.name}")) - } - } - } - - val extension = JvmSerializerExtension(v.serializationBindings, state) - val serializer = DescriptorSerializer.createTopLevel(extension) - val builder = serializer.packagePartProto(packageFragment.fqName, members) - extension.serializeJvmPackage(builder, partType) - val packageProto = builder.build() + val (serializer, packageProto) = PackagePartCodegen.serializePackagePartMembers(this, partType) val extraFlags = if (shouldGeneratePartHierarchy) JvmAnnotationNames.METADATA_MULTIFILE_PARTS_INHERIT_FLAG else 0 diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PackagePartCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PackagePartCodegen.java index c9d8fd6ea34..7df705e0c07 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PackagePartCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PackagePartCodegen.java @@ -17,7 +17,9 @@ package org.jetbrains.kotlin.codegen; import com.intellij.util.ArrayUtil; +import kotlin.Pair; import kotlin.Unit; +import kotlin.collections.CollectionsKt; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.backend.common.CodegenUtil; import org.jetbrains.kotlin.codegen.annotation.AnnotatedSimple; @@ -25,9 +27,6 @@ import org.jetbrains.kotlin.codegen.context.FieldOwnerContext; import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension; import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; -import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor; -import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor; -import org.jetbrains.kotlin.descriptors.VariableDescriptor; import org.jetbrains.kotlin.descriptors.annotations.Annotated; import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl; @@ -101,34 +100,42 @@ public class PackagePartCodegen extends MemberCodegen { @Override protected void generateKotlinMetadataAnnotation() { - List members = new ArrayList<>(); - for (KtDeclaration declaration : CodegenUtil.getActualDeclarations(element)) { - if (declaration instanceof KtNamedFunction) { - SimpleFunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, declaration); - members.add(functionDescriptor); - } - else if (declaration instanceof KtProperty) { - VariableDescriptor property = bindingContext.get(BindingContext.VARIABLE, declaration); - members.add(property); - } - else if (declaration instanceof KtTypeAlias) { - TypeAliasDescriptor typeAlias = bindingContext.get(BindingContext.TYPE_ALIAS, declaration); - members.add(typeAlias); - } - } - - JvmSerializerExtension extension = new JvmSerializerExtension(v.getSerializationBindings(), state); - DescriptorSerializer serializer = DescriptorSerializer.createTopLevel(extension); - ProtoBuf.Package.Builder builder = serializer.packagePartProto(element.getPackageFqName(), members); - extension.serializeJvmPackage(builder, packagePartType); - ProtoBuf.Package packageProto = builder.build(); + Pair serializedPart = serializePackagePartMembers(this, packagePartType); WriteAnnotationUtilKt.writeKotlinMetadata(v, state, KotlinClassHeader.Kind.FILE_FACADE, 0, av -> { - writeAnnotationData(av, serializer, packageProto); + writeAnnotationData(av, serializedPart.getFirst(), serializedPart.getSecond()); return Unit.INSTANCE; }); } + @NotNull + protected static Pair serializePackagePartMembers( + @NotNull MemberCodegen codegen, + @NotNull Type packagePartType + ) { + BindingContext bindingContext = codegen.bindingContext; + List members = CollectionsKt.mapNotNull(CodegenUtil.getActualDeclarations(codegen.element), declaration -> { + if (declaration instanceof KtNamedFunction) { + return bindingContext.get(BindingContext.FUNCTION, declaration); + } + else if (declaration instanceof KtProperty) { + return bindingContext.get(BindingContext.VARIABLE, declaration); + } + else if (declaration instanceof KtTypeAlias) { + return bindingContext.get(BindingContext.TYPE_ALIAS, declaration); + } + + return null; + }); + + JvmSerializerExtension extension = new JvmSerializerExtension(codegen.v.getSerializationBindings(), codegen.state); + DescriptorSerializer serializer = DescriptorSerializer.createTopLevel(extension); + ProtoBuf.Package.Builder builder = serializer.packagePartProto(codegen.element.getPackageFqName(), members); + extension.serializeJvmPackage(builder, packagePartType); + + return new Pair<>(serializer, builder.build()); + } + @Override protected void generateSyntheticPartsAfterBody() { generateSyntheticAccessors(); diff --git a/compiler/testData/compileKotlinAgainstKotlin/multifileClassWithTypealias.kt b/compiler/testData/compileKotlinAgainstKotlin/multifileClassWithTypealias.kt new file mode 100644 index 00000000000..f7ed63a5c3f --- /dev/null +++ b/compiler/testData/compileKotlinAgainstKotlin/multifileClassWithTypealias.kt @@ -0,0 +1,16 @@ +// IGNORE_BACKEND: NATIVE +// FILE: A.kt + +@file:[JvmName("Test") JvmMultifileClass] + +typealias S = String +typealias LS = List + +// FILE: B.kt + +import java.util.Arrays + +fun box(): S { + val l: LS = Arrays.asList("OK") + return l[0] +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java index 73cf7c74e51..6ce011f1092 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java @@ -168,6 +168,12 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl doTest(fileName); } + @TestMetadata("multifileClassWithTypealias.kt") + public void testMultifileClassWithTypealias() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstKotlin/multifileClassWithTypealias.kt"); + doTest(fileName); + } + @TestMetadata("nestedClass.kt") public void testNestedClass() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstKotlin/nestedClass.kt");