Fix codegen for multifile class parts with type aliases only

#KT-20337 Fixed
This commit is contained in:
Alexander Udalov
2017-09-19 19:09:17 +03:00
parent 09f36927a5
commit 23d6690581
5 changed files with 56 additions and 49 deletions
@@ -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
@@ -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<DeclarationDescriptor>()
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
@@ -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<KtFile> {
@Override
protected void generateKotlinMetadataAnnotation() {
List<DeclarationDescriptor> 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<DescriptorSerializer, ProtoBuf.Package> 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<DescriptorSerializer, ProtoBuf.Package> serializePackagePartMembers(
@NotNull MemberCodegen<? extends KtFile> codegen,
@NotNull Type packagePartType
) {
BindingContext bindingContext = codegen.bindingContext;
List<DeclarationDescriptor> 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();
@@ -0,0 +1,16 @@
// IGNORE_BACKEND: NATIVE
// FILE: A.kt
@file:[JvmName("Test") JvmMultifileClass]
typealias S = String
typealias LS = List<S>
// FILE: B.kt
import java.util.Arrays
fun box(): S {
val l: LS = Arrays.asList("OK")
return l[0]
}
@@ -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");