diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/KotlinCodegenFacade.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/KotlinCodegenFacade.java index 142b8940ba6..ed36e85bf45 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/KotlinCodegenFacade.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/KotlinCodegenFacade.java @@ -63,32 +63,37 @@ public class KotlinCodegenFacade { ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); - MultiMap packageFqNameToFiles = new MultiMap(); - MultiMap multifileClassFqNameToFiles = new MultiMap(); + MultiMap filesInPackageClasses = new MultiMap(); + MultiMap filesInMultifileClasses = new MultiMap(); for (JetFile file : state.getFiles()) { if (file == null) throw new IllegalArgumentException("A null file given for compilation"); + JvmFileClassInfo fileClassInfo = state.getFileClassesProvider().getFileClassInfo(file); + if (fileClassInfo.getIsMultifileClass()) { - multifileClassFqNameToFiles.putValue(fileClassInfo.getFacadeClassFqName(), file); + filesInMultifileClasses.putValue(fileClassInfo.getFacadeClassFqName(), file); } - else if (state.getPackageFacadesAsMultifileClasses()) { - multifileClassFqNameToFiles.putValue(PackageClassUtils.getPackageClassFqName(file.getPackageFqName()), file); + + if (state.getPackageFacadesAsMultifileClasses()) { + if (!fileClassInfo.getIsMultifileClass()) { + filesInMultifileClasses.putValue(PackageClassUtils.getPackageClassFqName(file.getPackageFqName()), file); + } } else { - packageFqNameToFiles.putValue(file.getPackageFqName(), file); + filesInPackageClasses.putValue(file.getPackageFqName(), file); } } Set packagesWithObsoleteParts = new HashSet(state.getPackagesWithObsoleteParts()); - for (FqName packageFqName : Sets.union(packagesWithObsoleteParts, packageFqNameToFiles.keySet())) { + for (FqName packageFqName : Sets.union(packagesWithObsoleteParts, filesInPackageClasses.keySet())) { ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); - generatePackage(state, packageFqName, packageFqNameToFiles.get(packageFqName), errorHandler); + generatePackage(state, packageFqName, filesInPackageClasses.get(packageFqName), errorHandler); } - for (FqName multifileClassFqName : multifileClassFqNameToFiles.keySet()) { + for (FqName multifileClassFqName : filesInMultifileClasses.keySet()) { ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); - generateMultifileClass(state, multifileClassFqName, multifileClassFqNameToFiles.get(multifileClassFqName), errorHandler); + generateMultifileClass(state, multifileClassFqName, filesInMultifileClasses.get(multifileClassFqName), errorHandler); } ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PackageCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PackageCodegen.java index 98bec291a00..4d1c195e8ee 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PackageCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PackageCodegen.java @@ -25,7 +25,6 @@ import com.intellij.util.ArrayUtil; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import kotlin.jvm.functions.Function0; -import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.Mutable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -40,6 +39,7 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor; import org.jetbrains.kotlin.diagnostics.DiagnosticUtils; import org.jetbrains.kotlin.fileClasses.FileClassesPackage; +import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo; import org.jetbrains.kotlin.load.java.JvmAbi; import org.jetbrains.kotlin.load.java.JvmAnnotationNames; import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils; @@ -87,7 +87,11 @@ public class PackageCodegen { private final PackageParts packageParts; - public PackageCodegen(@NotNull GenerationState state, @NotNull Collection files, @NotNull FqName fqName) { + public PackageCodegen( + @NotNull GenerationState state, + @NotNull Collection files, + @NotNull FqName fqName + ) { this.state = state; this.files = files; this.packageFragment = getOnlyPackageFragment(fqName); @@ -219,7 +223,7 @@ public class PackageCodegen { for (JetFile file : files) { ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); try { - ClassBuilder builder = generatePart(file, generateCallableMemberTasks); + ClassBuilder builder = generateFile(file, generateCallableMemberTasks); if (builder != null) { bindings.add(builder.getSerializationBindings()); } @@ -284,14 +288,7 @@ public class PackageCodegen { Collection packageFragments = Lists.newArrayList(); ContainerUtil.addIfNotNull(packageFragments, packageFragment); ContainerUtil.addIfNotNull(packageFragments, compiledPackageFragment); - ProtoBuf.Package packageProto = serializer.packageProto(packageFragments, new Function1() { - @Override - public Boolean invoke(DeclarationDescriptor descriptor) { - return true; - } - }).build(); - - //if (packageProto.getMemberCount() == 0) return; + ProtoBuf.Package packageProto = serializer.packageProtoWithoutDescriptors().build(); AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_PACKAGE), true); JvmCodegenUtil.writeAbiVersion(av); @@ -309,10 +306,19 @@ public class PackageCodegen { } @Nullable - private ClassBuilder generatePart(@NotNull JetFile file, @NotNull Map generateCallableMemberTasks) { + private ClassBuilder generateFile(@NotNull JetFile file, @NotNull Map generateCallableMemberTasks) { + JvmFileClassInfo fileClassInfo = state.getFileClassesProvider().getFileClassInfo(file); + + if (fileClassInfo.getIsMultifileClass()) { + Type fileFacadeType = AsmUtil.asmTypeByFqNameWithoutInnerClasses(fileClassInfo.getFacadeClassFqName()); + addDelegateToFileClassMemberTasks(file, generateCallableMemberTasks, fileFacadeType); + return null; + } + + Type fileClassType = AsmUtil.asmTypeByFqNameWithoutInnerClasses(fileClassInfo.getFileClassFqName()); + PackageContext packagePartContext = state.getRootContext().intoPackagePart(packageFragment, fileClassType); + boolean generatePackagePart = false; - Type packagePartType = FileClassesPackage.getFileClassType(state.getFileClassesProvider(), file); - PackageContext packagePartContext = state.getRootContext().intoPackagePart(packageFragment, packagePartType); for (JetDeclaration declaration : file.getDeclarations()) { if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) { @@ -327,7 +333,7 @@ public class PackageCodegen { else if (declaration instanceof JetScript) { JetScript script = (JetScript) declaration; - // SCRIPT: generate script code, should be separate execution branch + // SCRIPT: generate script code, should be separate execution branch if (state.getGenerateDeclaredClassFilter().shouldGenerateScript(script)) { ScriptCodegen.createScriptCodegen(script, state, packagePartContext).generate(); } @@ -336,15 +342,24 @@ public class PackageCodegen { if (!generatePackagePart || !state.getGenerateDeclaredClassFilter().shouldGeneratePackagePart(file)) return null; - String name = packagePartType.getInternalName(); + String name = fileClassType.getInternalName(); packageParts.getParts().add(name.substring(name.lastIndexOf('/') + 1)); - ClassBuilder builder = state.getFactory().newVisitor(PackagePart(file, packageFragment), packagePartType, file); + ClassBuilder builder = state.getFactory().newVisitor(PackagePart(file, packageFragment), fileClassType, file); - new PackagePartCodegen(builder, file, packagePartType, packagePartContext, state).generate(); + new PackagePartCodegen(builder, file, fileClassType, packagePartContext, state).generate(); - FieldOwnerContext packageFacade = state.getRootContext().intoPackageFacade(packagePartType, packageFragment); + addDelegateToFileClassMemberTasks(file, generateCallableMemberTasks, fileClassType); + return builder; + } + + private void addDelegateToFileClassMemberTasks( + @NotNull JetFile file, + @NotNull Map generateCallableMemberTasks, + @NotNull Type fileClassType + ) { + FieldOwnerContext packageFacade = state.getRootContext().intoPackageFacade(fileClassType, packageFragment); final MemberCodegen memberCodegen = createCodegenForPartOfPackageFacade(packageFacade); for (final JetDeclaration declaration : file.getDeclarations()) { @@ -363,8 +378,6 @@ public class PackageCodegen { ); } } - - return builder; } private MemberCodegen createCodegenForPartOfPackageFacade(@NotNull FieldOwnerContext packageFacade) { diff --git a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.java b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.java index 4c1c53f9202..7af4185d99f 100644 --- a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.java +++ b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.java @@ -437,6 +437,15 @@ public class DescriptorSerializer { return packageProto(fragments, null); } + @NotNull + public ProtoBuf.Package.Builder packageProtoWithoutDescriptors() { + ProtoBuf.Package.Builder builder = ProtoBuf.Package.newBuilder(); + + extension.serializePackage(Collections.emptyList(), builder, stringTable); + + return builder; + } + @NotNull public ProtoBuf.Package.Builder packageProto(@NotNull Collection fragments, @Nullable Function1 skip) { ProtoBuf.Package.Builder builder = ProtoBuf.Package.newBuilder(); diff --git a/compiler/testData/codegen/boxMultiFile/inlineMultifileClassMemberFromOtherPackage/foo.kt b/compiler/testData/codegen/boxMultiFile/inlineMultifileClassMemberFromOtherPackage/foo.kt index c70e6391c18..5b08cf7e9ad 100644 --- a/compiler/testData/codegen/boxMultiFile/inlineMultifileClassMemberFromOtherPackage/foo.kt +++ b/compiler/testData/codegen/boxMultiFile/inlineMultifileClassMemberFromOtherPackage/foo.kt @@ -1,4 +1,4 @@ -@file:[JvmName("APackage") JvmMultifileClass] +@file:[JvmName("A") JvmMultifileClass] package a inline fun foo(body: () -> String): String = zee(body()) \ No newline at end of file diff --git a/compiler/testData/codegen/boxMultiFile/inlineMultifileClassMemberFromOtherPackage/zee.kt b/compiler/testData/codegen/boxMultiFile/inlineMultifileClassMemberFromOtherPackage/zee.kt index a4356fb9a72..d7bf0ca4b3c 100644 --- a/compiler/testData/codegen/boxMultiFile/inlineMultifileClassMemberFromOtherPackage/zee.kt +++ b/compiler/testData/codegen/boxMultiFile/inlineMultifileClassMemberFromOtherPackage/zee.kt @@ -1,4 +1,4 @@ -@file:[JvmName("APackage") JvmMultifileClass] +@file:[JvmName("A") JvmMultifileClass] package a public fun zee(x: String): String = x \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithJava/fileClasses/withPackageFacade/Baz.java b/compiler/testData/codegen/boxWithJava/fileClasses/withPackageFacade/Baz.java new file mode 100644 index 00000000000..f02dbe34860 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/fileClasses/withPackageFacade/Baz.java @@ -0,0 +1,7 @@ +import test.TestPackage; + +public class Baz { + public static String baz() { + return TestPackage.foo() + TestPackage.bar(); + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithJava/fileClasses/withPackageFacade/bar.kt b/compiler/testData/codegen/boxWithJava/fileClasses/withPackageFacade/bar.kt new file mode 100644 index 00000000000..d19dde90558 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/fileClasses/withPackageFacade/bar.kt @@ -0,0 +1,5 @@ +@file:JvmName("Util") +@file:JvmMultifileClass +package test + +public fun bar(): String = "K" \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithJava/fileClasses/withPackageFacade/foo.kt b/compiler/testData/codegen/boxWithJava/fileClasses/withPackageFacade/foo.kt new file mode 100644 index 00000000000..f0241dce786 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/fileClasses/withPackageFacade/foo.kt @@ -0,0 +1,4 @@ +@file:[JvmName("Util") JvmMultifileClass] +package test + +public fun foo(): String = "O" \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithJava/fileClasses/withPackageFacade/withPackageFacade.kt b/compiler/testData/codegen/boxWithJava/fileClasses/withPackageFacade/withPackageFacade.kt new file mode 100644 index 00000000000..e47c68a7a8f --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/fileClasses/withPackageFacade/withPackageFacade.kt @@ -0,0 +1,5 @@ +package test + +import Baz + +fun box(): String = Baz.baz() \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithStdlib/platformNames/multifileClass.kt b/compiler/testData/codegen/boxWithStdlib/platformNames/multifileClass.kt index 5f5a1bf24ab..f39b36ea291 100644 --- a/compiler/testData/codegen/boxWithStdlib/platformNames/multifileClass.kt +++ b/compiler/testData/codegen/boxWithStdlib/platformNames/multifileClass.kt @@ -1,5 +1,4 @@ -// NB this multifile class should be called "TestPackage" due to the way codegen box tests work. -@file:JvmName("TestPackage") +@file:JvmName("Test") @file:JvmMultifileClass package test diff --git a/compiler/testData/codegen/boxWithStdlib/platformNames/multifileClassWithLocalClass.kt b/compiler/testData/codegen/boxWithStdlib/platformNames/multifileClassWithLocalClass.kt index 71556525580..134bf63d551 100644 --- a/compiler/testData/codegen/boxWithStdlib/platformNames/multifileClassWithLocalClass.kt +++ b/compiler/testData/codegen/boxWithStdlib/platformNames/multifileClassWithLocalClass.kt @@ -1,4 +1,4 @@ -@file:JvmName("TestPackage") +@file:JvmName("Test") @file:JvmMultifileClass package test diff --git a/compiler/testData/codegen/boxWithStdlib/platformNames/multifileClassWithLocalGeneric.kt b/compiler/testData/codegen/boxWithStdlib/platformNames/multifileClassWithLocalGeneric.kt index a03b6aa00fc..32528c422d4 100644 --- a/compiler/testData/codegen/boxWithStdlib/platformNames/multifileClassWithLocalGeneric.kt +++ b/compiler/testData/codegen/boxWithStdlib/platformNames/multifileClassWithLocalGeneric.kt @@ -1,4 +1,4 @@ -@file:JvmName("TestPackage") +@file:JvmName("Test") @file:JvmMultifileClass package test diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java index 0807eb97f83..d83ff7309bc 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java @@ -175,6 +175,12 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege doTestWithJava(fileName); } + @TestMetadata("withPackageFacade") + public void testWithPackageFacade() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/fileClasses/withPackageFacade/"); + doTestWithJava(fileName); + } + } @TestMetadata("compiler/testData/codegen/boxWithJava/interfaces")