From 1586a2df8e34b8d1b6050d088d1d5398258d6937 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Fri, 11 Sep 2015 19:14:10 +0300 Subject: [PATCH] Make stdlib work with -Xmultifile-package-facades. Fixed wrong owner mapping in presence of -Xmultifile-package-facades. Fixed backing field mapping issue. Added more tests. --- build.xml | 1 + .../codegen/CodegenFileClassesProvider.kt | 18 ++-- .../kotlin/codegen/MemberCodegen.java | 3 +- .../kotlin/codegen/MultifileClassCodegen.kt | 1 + .../kotlin/codegen/PackageCodegen.java | 5 +- .../binding/CodegenAnnotatingVisitor.java | 5 +- .../codegen/binding/PsiCodegenPredictor.java | 7 +- .../codegen/inline/InlineCodegenUtil.java | 7 +- .../kotlin/codegen/state/GenerationState.kt | 2 +- .../kotlin/codegen/state/JetTypeMapper.java | 89 +++++++++++++------ .../kotlin/fileClasses/JvmFileClassUtil.kt | 9 ++ .../fileClasses/JvmFileClassesProvider.kt | 40 ++++----- .../load/kotlin/PackagePartClassUtils.kt | 3 - .../inlineFromOtherPackage.2.kt | 4 +- .../box.kt | 5 ++ .../foo.kt | 4 + .../zee.kt | 4 + .../multifileClassPartsInitialization/box.kt | 3 + .../part1.kt | 4 + .../part2.kt | 4 + .../part3.kt | 4 + .../calls/valFromOtherPackage.1.kt | 3 + .../calls/valFromOtherPackage.2.kt | 4 + .../calls/varFromOtherPackage.1.kt | 6 ++ .../calls/varFromOtherPackage.2.kt | 4 + .../againstMultifileStdlib/useStdlib.kt | 2 + .../bytecodeText/inlineFromOtherModule.kt | 5 +- .../partMembersInline/otherFile.kt | 4 + .../partMembersInline/thisFile.kt | 18 ++++ .../BytecodeTextMultifileTestGenerated.java | 6 ++ .../kotlin/codegen/InlineTestUtil.kt | 6 +- ...BlackBoxMultiFileCodegenTestGenerated.java | 12 +++ ...lackBoxWithStdlibCodegenTestGenerated.java | 15 ++++ ...stractBlackBoxMultifileClassCodegenTest.kt | 30 +++++++ ...CompileKotlinAgainstMultifileKotlinTest.kt | 3 +- ...kBoxMultifileClassKotlinTestGenerated.java | 64 +++++++++++++ ...inAgainstMultifileKotlinTestGenerated.java | 12 +++ .../lazy/descriptors/LazyJavaPackageScope.kt | 2 +- .../DeserializedDescriptorResolver.java | 19 ++-- .../kotlin/load/kotlin/JavaClassDataFinder.kt | 2 +- .../kotlin/generators/tests/GenerateTests.kt | 6 +- .../outs/stepIntoStdlibFacadeClass.out | 2 +- libraries/stdlib/pom.xml | 6 ++ 43 files changed, 363 insertions(+), 90 deletions(-) create mode 100644 compiler/testData/codegen/boxMultiFile/inlineMultifileClassMemberFromOtherPackage/box.kt create mode 100644 compiler/testData/codegen/boxMultiFile/inlineMultifileClassMemberFromOtherPackage/foo.kt create mode 100644 compiler/testData/codegen/boxMultiFile/inlineMultifileClassMemberFromOtherPackage/zee.kt create mode 100644 compiler/testData/codegen/boxMultiFile/multifileClassPartsInitialization/box.kt create mode 100644 compiler/testData/codegen/boxMultiFile/multifileClassPartsInitialization/part1.kt create mode 100644 compiler/testData/codegen/boxMultiFile/multifileClassPartsInitialization/part2.kt create mode 100644 compiler/testData/codegen/boxMultiFile/multifileClassPartsInitialization/part3.kt create mode 100644 compiler/testData/codegen/boxMultifileClasses/calls/valFromOtherPackage.1.kt create mode 100644 compiler/testData/codegen/boxMultifileClasses/calls/valFromOtherPackage.2.kt create mode 100644 compiler/testData/codegen/boxMultifileClasses/calls/varFromOtherPackage.1.kt create mode 100644 compiler/testData/codegen/boxMultifileClasses/calls/varFromOtherPackage.2.kt create mode 100644 compiler/testData/codegen/boxWithStdlib/againstMultifileStdlib/useStdlib.kt create mode 100644 compiler/testData/codegen/bytecodeTextMultifile/partMembersInline/otherFile.kt create mode 100644 compiler/testData/codegen/bytecodeTextMultifile/partMembersInline/thisFile.kt create mode 100644 compiler/tests/org/jetbrains/kotlin/jvm/compiler/AbstractBlackBoxMultifileClassCodegenTest.kt create mode 100644 compiler/tests/org/jetbrains/kotlin/jvm/compiler/BlackBoxMultifileClassKotlinTestGenerated.java diff --git a/build.xml b/build.xml index ae08d9d5fb4..dbe83fb2a3a 100644 --- a/build.xml +++ b/build.xml @@ -702,6 +702,7 @@ + diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/CodegenFileClassesProvider.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/CodegenFileClassesProvider.kt index fcdf493e0f0..7822282596e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/CodegenFileClassesProvider.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/CodegenFileClassesProvider.kt @@ -19,14 +19,16 @@ package org.jetbrains.kotlin.codegen import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.JetFile -import org.jetbrains.kotlin.resolve.BindingContext -import java.util.* -public class CodegenFileClassesProvider() : JvmFileClassesProvider { - private val fileParts = hashMapOf() - - override public fun getFileClassInfo(file: JetFile): JvmFileClassInfo = - fileParts.getOrPut(file) { JvmFileClassUtil.getFileClassInfoNoResolve(file) } +public class CodegenFileClassesProvider(private val packageFacadesAsMultifileClasses: Boolean) : JvmFileClassesProvider { + override public fun getFileClassInfo(file: JetFile): JvmFileClassInfo { + val fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(file) + if (packageFacadesAsMultifileClasses && !fileClassInfo.isMultifileClass) { + return JvmFileClassUtil.getMultifilePackageFacadePartInfo(file) + } + else { + return fileClassInfo + } + } } \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index ca868659281..edec5aa6376 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.codegen.state.JetTypeMapper; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl; +import org.jetbrains.kotlin.fileClasses.FileClassesPackage; import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider; import org.jetbrains.kotlin.load.java.JvmAbi; import org.jetbrains.kotlin.name.Name; @@ -295,7 +296,7 @@ public abstract class MemberCodegen generateCallableMemberTasks) { boolean generatePackagePart = false; - Type packagePartType = state.getFileClassesProvider().getFileClassType(file); + Type packagePartType = FileClassesPackage.getFileClassType(state.getFileClassesProvider(), file); PackageContext packagePartContext = state.getRootContext().intoPackagePart(packageFragment, packagePartType); for (JetDeclaration declaration : file.getDeclarations()) { @@ -414,7 +415,7 @@ public class PackageCodegen { public void generateClassOrObject(@NotNull JetClassOrObject classOrObject) { JetFile file = classOrObject.getContainingJetFile(); - Type packagePartType = state.getFileClassesProvider().getFileClassType(file); + Type packagePartType = FileClassesPackage.getFileClassType(state.getFileClassesProvider(), file); CodegenContext context = state.getRootContext().intoPackagePart(packageFragment, packagePartType); MemberCodegen.genClassOrObject(context, classOrObject, state, null); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java index 27946f0adfb..174d9323749 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil; import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl; +import org.jetbrains.kotlin.fileClasses.FileClassesPackage; import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider; import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor; import org.jetbrains.kotlin.name.Name; @@ -394,7 +395,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { else if (containingDeclaration instanceof PackageFragmentDescriptor) { JetFile containingFile = DescriptorToSourceUtils.getContainingFile(descriptor); assert containingFile != null : "File not found for " + descriptor; - return fileClassesProvider.getFileClassInternalName(containingFile) + '$' + name; + return FileClassesPackage.getFileClassInternalName(fileClassesProvider, containingFile) + '$' + name; } return null; @@ -575,7 +576,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { } } - return fileClassesProvider.getFileClassInternalName(file); + return FileClassesPackage.getFacadeClassInternalName(fileClassesProvider, file); } private static T peekFromStack(@NotNull Stack stack) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/PsiCodegenPredictor.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/PsiCodegenPredictor.java index 8132262102b..06e9d24b1dc 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/PsiCodegenPredictor.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/PsiCodegenPredictor.java @@ -22,6 +22,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.codegen.AsmUtil; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; +import org.jetbrains.kotlin.fileClasses.FileClassesPackage; import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.*; @@ -55,7 +56,7 @@ public final class PsiCodegenPredictor { @Nullable public static String getPredefinedJvmInternalName( @NotNull JetDeclaration declaration, - @NotNull JvmFileClassesProvider fileClassesManager + @NotNull JvmFileClassesProvider fileClassesProvider ) { // TODO: Method won't work for declarations inside companion objects // TODO: Method won't give correct class name for traits implementations @@ -64,7 +65,7 @@ public final class PsiCodegenPredictor { String parentInternalName; if (parentDeclaration != null) { - parentInternalName = getPredefinedJvmInternalName(parentDeclaration, fileClassesManager); + parentInternalName = getPredefinedJvmInternalName(parentDeclaration, fileClassesProvider); if (parentInternalName == null) { return null; } @@ -74,7 +75,7 @@ public final class PsiCodegenPredictor { if (declaration instanceof JetNamedFunction) { Name name = ((JetNamedFunction) declaration).getNameAsName(); - return name == null ? null : fileClassesManager.getFileClassInternalName(containingFile) + "$" + name.asString(); + return name == null ? null : FileClassesPackage.getFileClassInternalName(fileClassesProvider, containingFile) + "$" + name.asString(); } parentInternalName = AsmUtil.internalNameByFqNameWithoutInnerClasses(containingFile.getPackageFqName()); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java index 6969c9e35e8..9bbbe84bcfa 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.codegen.context.*; import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.JetTypeMapper; import org.jetbrains.kotlin.descriptors.*; +import org.jetbrains.kotlin.fileClasses.FileClassesPackage; import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider; import org.jetbrains.kotlin.load.java.JvmAbi; import org.jetbrains.kotlin.load.kotlin.JvmVirtualFileFinder; @@ -214,7 +215,7 @@ public class InlineCodegenUtil { @NotNull CodegenContext codegenContext, @NotNull DeclarationDescriptor currentDescriptor, @NotNull JetTypeMapper typeMapper, - @NotNull JvmFileClassesProvider fileClassesManager + @NotNull JvmFileClassesProvider fileClassesProvider ) { if (currentDescriptor instanceof PackageFragmentDescriptor) { PsiFile file = getContainingFile(codegenContext); @@ -223,7 +224,7 @@ public class InlineCodegenUtil { if (file == null) { implementationOwnerType = CodegenContextUtil.getImplementationOwnerClassType(codegenContext); } else { - implementationOwnerType = fileClassesManager.getFileClassType((JetFile) file); + implementationOwnerType = FileClassesPackage.getFileClassType(fileClassesProvider, (JetFile) file); } if (implementationOwnerType == null) { @@ -252,7 +253,7 @@ public class InlineCodegenUtil { String suffix = currentDescriptor.getName().isSpecial() ? "" : currentDescriptor.getName().asString(); //noinspection ConstantConditions - return getInlineName(codegenContext, currentDescriptor.getContainingDeclaration(), typeMapper, fileClassesManager) + "$" + suffix; + return getInlineName(codegenContext, currentDescriptor.getContainingDeclaration(), typeMapper, fileClassesProvider) + "$" + suffix; } public static boolean isInvokeOnLambda(@NotNull String owner, @NotNull String name) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt index 65c29cd7265..c71438e4878 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt @@ -82,7 +82,7 @@ public class GenerationState jvmOverloads constructor( } } - public val fileClassesProvider: CodegenFileClassesProvider = CodegenFileClassesProvider() + public val fileClassesProvider: CodegenFileClassesProvider = CodegenFileClassesProvider(packageFacadesAsMultifileClasses) public val classBuilderMode: ClassBuilderMode = builderFactory.getClassBuilderMode() public val bindingTrace: BindingTrace = DelegatingBindingTrace(bindingContext, "trace in GenerationState") diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java index ae94af3113d..f3340b6371f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java @@ -20,6 +20,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.builtins.BuiltinsPackageFragment; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.builtins.PrimitiveType; import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor; @@ -30,12 +31,14 @@ import org.jetbrains.kotlin.codegen.binding.PsiCodegenPredictor; import org.jetbrains.kotlin.codegen.context.CodegenContext; import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter; import org.jetbrains.kotlin.descriptors.*; +import org.jetbrains.kotlin.fileClasses.FileClassesPackage; import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil; import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider; import org.jetbrains.kotlin.load.java.JvmAbi; import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor; import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor; import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageScope; +import org.jetbrains.kotlin.load.kotlin.PackageClassUtils; import org.jetbrains.kotlin.name.*; import org.jetbrains.kotlin.platform.JavaToKotlinClassMap; import org.jetbrains.kotlin.psi.JetExpression; @@ -56,8 +59,8 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind; import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature; import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature; import org.jetbrains.kotlin.resolve.scopes.AbstractScopeAdapter; -import org.jetbrains.kotlin.serialization.deserialization.DeserializedType; import org.jetbrains.kotlin.resolve.scopes.JetScope; +import org.jetbrains.kotlin.serialization.deserialization.DeserializedType; import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor; import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope; import org.jetbrains.kotlin.types.*; @@ -160,46 +163,78 @@ public class JetTypeMapper { JetFile file = DescriptorToSourceUtils.getContainingFile(descriptor); if (file != null) { Visibility visibility = descriptor.getVisibility(); - if (Visibilities.isPrivate(visibility)) { - return fileClassesProvider.getFileClassInternalName(file); + if (descriptor instanceof PropertyDescriptor || Visibilities.isPrivate(visibility)) { + return FileClassesPackage.getFileClassInternalName(fileClassesProvider, file); } else { - return fileClassesProvider.getFacadeClassInternalName(file); + return FileClassesPackage.getFacadeClassInternalName(fileClassesProvider, file); } } CallableMemberDescriptor directMember = getDirectMember(descriptor); if (directMember instanceof DeserializedCallableMemberDescriptor) { - Name implClassName = JvmFileClassUtil.getImplClassName((DeserializedCallableMemberDescriptor) directMember); - DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); - if (containingDeclaration instanceof PackageFragmentDescriptor) { - PackageFragmentDescriptor packageFragmentDescriptor = (PackageFragmentDescriptor) containingDeclaration; - JetScope scope = packageFragmentDescriptor.getMemberScope(); - if (scope instanceof AbstractScopeAdapter) { - scope = ((AbstractScopeAdapter) scope).getActualScope(); - } - if (scope instanceof LazyJavaPackageScope) { - String facadeShortName = ((LazyJavaPackageScope) scope).getFacadeSimpleNameForPartSimpleName(implClassName.asString()); - if (facadeShortName != null) { - FqName facadeFqName = packageFragmentDescriptor.getFqName().child(Name.identifier(facadeShortName)); - return internalNameByFqNameWithoutInnerClasses(facadeFqName); - } - } - else if (scope instanceof DeserializedPackageMemberScope) { - FqName implClassFqName = packageFragmentDescriptor.getFqName().child(implClassName); - return internalNameByFqNameWithoutInnerClasses(implClassFqName); - } - else { - throw new AssertionError("Unexpected member scope for deserialized callable: " + scope); - } - } + String facadeFqName = getPackageMemberOwnerInternalName((DeserializedCallableMemberDescriptor) directMember); + if (facadeFqName != null) return facadeFqName; } throw new RuntimeException("Unreachable state"); //return PackageClassUtils.getPackageClassInternalName(packageFragment.getFqName()); } + @Nullable + private static String getPackageMemberOwnerInternalName(@NotNull DeserializedCallableMemberDescriptor descriptor) { + // XXX This method (and getPackageMemberOwnerShortName) is a dirty hack + // introduced to make stdlib work with package facades built as multifile facades for M13. + // We need some safe, concise way to identify multifile facade and multifile part + // from a deserialized package member descriptor. + // Possible approaches: + // - create a special instance of DeserializedPackageFragmentDescriptor for each facade class (multifile or single-file), + // keep related mapping information there; + // - provide a proper SourceElement for such descriptors (similar to KotlinJvmBinarySourceElement). + DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); + assert containingDeclaration instanceof PackageFragmentDescriptor : "Not a top-level member: " + descriptor; + PackageFragmentDescriptor packageFragmentDescriptor = (PackageFragmentDescriptor) containingDeclaration; + + String facadeShortName = getPackageMemberOwnerShortName(descriptor); + if (facadeShortName == null) { + return null; + } + + FqName facadeFqName = packageFragmentDescriptor.getFqName().child(Name.identifier(facadeShortName)); + return internalNameByFqNameWithoutInnerClasses(facadeFqName); + } + + @Nullable + private static String getPackageMemberOwnerShortName(@NotNull DeserializedCallableMemberDescriptor descriptor) { + // XXX Dirty hack; see getPAckageMemberOwnerInternalName above for more details. + DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); + if (containingDeclaration instanceof PackageFragmentDescriptor) { + PackageFragmentDescriptor packageFragmentDescriptor = (PackageFragmentDescriptor) containingDeclaration; + JetScope scope = packageFragmentDescriptor.getMemberScope(); + if (scope instanceof AbstractScopeAdapter) { + scope = ((AbstractScopeAdapter) scope).getActualScope(); + } + if (scope instanceof LazyJavaPackageScope) { + Name implClassName = JvmFileClassUtil.getImplClassName(descriptor); + return ((LazyJavaPackageScope) scope).getFacadeSimpleNameForPartSimpleName(implClassName.asString()); + } + else if (packageFragmentDescriptor instanceof BuiltinsPackageFragment) { + return PackageClassUtils.getPackageClassFqName(packageFragmentDescriptor.getFqName()).shortName().asString(); + } + else if (scope instanceof DeserializedPackageMemberScope) { + // XXX IncrementalPackageScope + Name implClassName = JvmFileClassUtil.getImplClassName(descriptor); + return implClassName.asString(); + } + else { + throw new AssertionError("Unexpected member scope for deserialized callable: " + scope + + "; descriptor: " + descriptor); + } + } + return null; + } + @NotNull public Type mapReturnType(@NotNull CallableDescriptor descriptor) { return mapReturnType(descriptor, null); diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassUtil.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassUtil.kt index 778b734b056..b6b55b017a3 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassUtil.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassUtil.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.fileClasses import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor +import org.jetbrains.kotlin.load.kotlin.PackageClassUtils import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -63,6 +64,14 @@ public object JvmFileClassUtil { public @JvmStatic fun getHiddenPartFqName(file: JetFile, jvmFileClassAnnotations: ParsedJmvFileClassAnnotations): FqName = file.packageFqName.child(Name.identifier(manglePartName(jvmFileClassAnnotations.name, file.name))) + public @JvmStatic fun getMultifilePackageFacadePartInfo(file: JetFile): JvmFileClassInfo { + val packageFqName = file.packageFqName + val packageFacadeFqName = PackageClassUtils.getPackageClassFqName(packageFqName) + val filePartName = manglePartName(packageFacadeFqName.shortName().asString(), file.name) + val filePartFqName = packageFqName.child(Name.identifier(filePartName)) + return JvmMultifileClassPartInfo(filePartFqName, packageFacadeFqName) + } + public @JvmStatic fun manglePartName(facadeName: String, fileName: String): String = "${facadeName}__${PackagePartClassUtils.getFilePartShortName(fileName)}" diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassesProvider.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassesProvider.kt index 774d9969f46..ae1289af785 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassesProvider.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassesProvider.kt @@ -23,28 +23,28 @@ import org.jetbrains.org.objectweb.asm.Type public interface JvmFileClassesProvider { public fun getFileClassInfo(file: JetFile): JvmFileClassInfo - - public fun getFileClassFqName(file: JetFile): FqName = - getFileClassInfo(file).fileClassFqName - - public fun getFileClassInternalName(file: JetFile): String = - getFileClassFqName(file).getInternalName() - - public fun getFileClassType(file: JetFile): Type = - getFileClassFqName(file).getClassType() - - public fun getFacadeClassFqName(file: JetFile): FqName = - getFileClassInfo(file).facadeClassFqName - - public fun getFacadeClassInternalName(file: JetFile): String = - getFacadeClassFqName(file).getInternalName() - - public fun getFacadeClassType(file: JetFile): Type = - getFacadeClassFqName(file).getClassType() } -private fun FqName.getInternalName(): String = +public fun FqName.getInternalName(): String = JvmClassName.byFqNameWithoutInnerClasses(this).internalName -private fun FqName.getClassType(): Type = +public fun FqName.getClassType(): Type = Type.getObjectType(getInternalName()) + +public fun JvmFileClassesProvider.getFileClassFqName(file: JetFile): FqName = + getFileClassInfo(file).fileClassFqName + +public fun JvmFileClassesProvider.getFileClassInternalName(file: JetFile): String = + getFileClassFqName(file).getInternalName() + +public fun JvmFileClassesProvider.getFileClassType(file: JetFile): Type = + getFileClassFqName(file).getClassType() + +public fun JvmFileClassesProvider.getFacadeClassFqName(file: JetFile): FqName = + getFileClassInfo(file).facadeClassFqName + +public fun JvmFileClassesProvider.getFacadeClassInternalName(file: JetFile): String = + getFacadeClassFqName(file).getInternalName() + +public fun JvmFileClassesProvider.getFacadeClassType(file: JetFile): Type = + getFacadeClassFqName(file).getClassType() \ No newline at end of file diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/PackagePartClassUtils.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/PackagePartClassUtils.kt index 425654d7e9b..7d6609ca075 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/PackagePartClassUtils.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/PackagePartClassUtils.kt @@ -82,9 +82,6 @@ public object PackagePartClassUtils { public @JvmStatic fun fileHasTopLevelCallables(file: JetFile): Boolean = file.declarations.any { it is JetProperty || it is JetNamedFunction } - public @JvmStatic fun getFilesForPart(partFqName: FqName, files: Collection): List = - getFilesWithCallables(files).filter { getPackagePartFqName(it) == partFqName } - public @JvmStatic fun getFilePartShortName(fileName: String): String = getPartClassName(FileUtil.getNameWithoutExtension(fileName)) diff --git a/compiler/testData/codegen/boxInline/multifileClasses/inlineFromOtherPackage.2.kt b/compiler/testData/codegen/boxInline/multifileClasses/inlineFromOtherPackage.2.kt index 074c3891b42..9b67fc98b71 100644 --- a/compiler/testData/codegen/boxInline/multifileClasses/inlineFromOtherPackage.2.kt +++ b/compiler/testData/codegen/boxInline/multifileClasses/inlineFromOtherPackage.2.kt @@ -1,4 +1,6 @@ @file:[JvmName("MultifileClass") JvmMultifileClass] package a -inline fun foo(body: () -> String): String = body() \ No newline at end of file +inline fun foo(body: () -> String): String = bar(body()) + +public fun bar(x: String): String = x \ No newline at end of file diff --git a/compiler/testData/codegen/boxMultiFile/inlineMultifileClassMemberFromOtherPackage/box.kt b/compiler/testData/codegen/boxMultiFile/inlineMultifileClassMemberFromOtherPackage/box.kt new file mode 100644 index 00000000000..e12d247c2e1 --- /dev/null +++ b/compiler/testData/codegen/boxMultiFile/inlineMultifileClassMemberFromOtherPackage/box.kt @@ -0,0 +1,5 @@ +package test + +import a.foo + +fun box(): String = foo { "OK" } \ No newline at end of file diff --git a/compiler/testData/codegen/boxMultiFile/inlineMultifileClassMemberFromOtherPackage/foo.kt b/compiler/testData/codegen/boxMultiFile/inlineMultifileClassMemberFromOtherPackage/foo.kt new file mode 100644 index 00000000000..c70e6391c18 --- /dev/null +++ b/compiler/testData/codegen/boxMultiFile/inlineMultifileClassMemberFromOtherPackage/foo.kt @@ -0,0 +1,4 @@ +@file:[JvmName("APackage") 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 new file mode 100644 index 00000000000..a4356fb9a72 --- /dev/null +++ b/compiler/testData/codegen/boxMultiFile/inlineMultifileClassMemberFromOtherPackage/zee.kt @@ -0,0 +1,4 @@ +@file:[JvmName("APackage") JvmMultifileClass] +package a + +public fun zee(x: String): String = x \ No newline at end of file diff --git a/compiler/testData/codegen/boxMultiFile/multifileClassPartsInitialization/box.kt b/compiler/testData/codegen/boxMultiFile/multifileClassPartsInitialization/box.kt new file mode 100644 index 00000000000..cc7fc172275 --- /dev/null +++ b/compiler/testData/codegen/boxMultiFile/multifileClassPartsInitialization/box.kt @@ -0,0 +1,3 @@ +import a.* + +fun box(): String = OK \ No newline at end of file diff --git a/compiler/testData/codegen/boxMultiFile/multifileClassPartsInitialization/part1.kt b/compiler/testData/codegen/boxMultiFile/multifileClassPartsInitialization/part1.kt new file mode 100644 index 00000000000..34fdf81546b --- /dev/null +++ b/compiler/testData/codegen/boxMultiFile/multifileClassPartsInitialization/part1.kt @@ -0,0 +1,4 @@ +@file:[JvmName("MultifileClass") JvmMultifileClass] +package a + +val O: String = "O" \ No newline at end of file diff --git a/compiler/testData/codegen/boxMultiFile/multifileClassPartsInitialization/part2.kt b/compiler/testData/codegen/boxMultiFile/multifileClassPartsInitialization/part2.kt new file mode 100644 index 00000000000..aa95ebb6637 --- /dev/null +++ b/compiler/testData/codegen/boxMultiFile/multifileClassPartsInitialization/part2.kt @@ -0,0 +1,4 @@ +@file:[JvmName("MultifileClass") JvmMultifileClass] +package a + +val K: String = "K" \ No newline at end of file diff --git a/compiler/testData/codegen/boxMultiFile/multifileClassPartsInitialization/part3.kt b/compiler/testData/codegen/boxMultiFile/multifileClassPartsInitialization/part3.kt new file mode 100644 index 00000000000..f39e13de085 --- /dev/null +++ b/compiler/testData/codegen/boxMultiFile/multifileClassPartsInitialization/part3.kt @@ -0,0 +1,4 @@ +@file:[JvmName("MultifileClass") JvmMultifileClass] +package a + +val OK: String = O + K \ No newline at end of file diff --git a/compiler/testData/codegen/boxMultifileClasses/calls/valFromOtherPackage.1.kt b/compiler/testData/codegen/boxMultifileClasses/calls/valFromOtherPackage.1.kt new file mode 100644 index 00000000000..5209a8c94e9 --- /dev/null +++ b/compiler/testData/codegen/boxMultifileClasses/calls/valFromOtherPackage.1.kt @@ -0,0 +1,3 @@ +import a.OK + +fun box(): String = OK \ No newline at end of file diff --git a/compiler/testData/codegen/boxMultifileClasses/calls/valFromOtherPackage.2.kt b/compiler/testData/codegen/boxMultifileClasses/calls/valFromOtherPackage.2.kt new file mode 100644 index 00000000000..e495105ce66 --- /dev/null +++ b/compiler/testData/codegen/boxMultifileClasses/calls/valFromOtherPackage.2.kt @@ -0,0 +1,4 @@ +@file:[JvmName("MultifileClass") JvmMultifileClass] +package a + +val OK: String = "OK" \ No newline at end of file diff --git a/compiler/testData/codegen/boxMultifileClasses/calls/varFromOtherPackage.1.kt b/compiler/testData/codegen/boxMultifileClasses/calls/varFromOtherPackage.1.kt new file mode 100644 index 00000000000..89984371091 --- /dev/null +++ b/compiler/testData/codegen/boxMultifileClasses/calls/varFromOtherPackage.1.kt @@ -0,0 +1,6 @@ +import a.OK + +fun box(): String { + OK = "OK" + return OK +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxMultifileClasses/calls/varFromOtherPackage.2.kt b/compiler/testData/codegen/boxMultifileClasses/calls/varFromOtherPackage.2.kt new file mode 100644 index 00000000000..a5eadef7399 --- /dev/null +++ b/compiler/testData/codegen/boxMultifileClasses/calls/varFromOtherPackage.2.kt @@ -0,0 +1,4 @@ +@file:[JvmName("MultifileClass") JvmMultifileClass] +package a + +var OK: String = "Hmmm?" \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithStdlib/againstMultifileStdlib/useStdlib.kt b/compiler/testData/codegen/boxWithStdlib/againstMultifileStdlib/useStdlib.kt new file mode 100644 index 00000000000..d73f9537f8d --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/againstMultifileStdlib/useStdlib.kt @@ -0,0 +1,2 @@ +fun box(): String = + listOf("a").map { "OK" }.get(0) \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/inlineFromOtherModule.kt b/compiler/testData/codegen/bytecodeText/inlineFromOtherModule.kt index df5a7c62cea..dd1a5560e31 100644 --- a/compiler/testData/codegen/bytecodeText/inlineFromOtherModule.kt +++ b/compiler/testData/codegen/bytecodeText/inlineFromOtherModule.kt @@ -2,6 +2,5 @@ fun foo() { assert(1 == 1) { "Hahaha" } } -// assert function will be inlined, and we assure that there are no calls via package part, but is call via package facade in inlined code -// 0 INVOKESTATIC kotlin\/KotlinPackage.+\.getASSERTIONS_ENABLED \(\)Z -// 1 INVOKESTATIC kotlin\/AssertionsJVMKt\.getASSERTIONS_ENABLED \(\)Z +// 1 INVOKESTATIC kotlin\/KotlinPackage\.getASSERTIONS_ENABLED +// 0 INVOKESTATIC kotlin\/AssertionsJVMKt\.getASSERTIONS_ENABLED diff --git a/compiler/testData/codegen/bytecodeTextMultifile/partMembersInline/otherFile.kt b/compiler/testData/codegen/bytecodeTextMultifile/partMembersInline/otherFile.kt new file mode 100644 index 00000000000..bb6752862fc --- /dev/null +++ b/compiler/testData/codegen/bytecodeTextMultifile/partMembersInline/otherFile.kt @@ -0,0 +1,4 @@ +@file:[JvmName("Util") JvmMultifileClass] +package test + +public fun publicInOtherFile() {} diff --git a/compiler/testData/codegen/bytecodeTextMultifile/partMembersInline/thisFile.kt b/compiler/testData/codegen/bytecodeTextMultifile/partMembersInline/thisFile.kt new file mode 100644 index 00000000000..fda23aef6d6 --- /dev/null +++ b/compiler/testData/codegen/bytecodeTextMultifile/partMembersInline/thisFile.kt @@ -0,0 +1,18 @@ +@file:[JvmName("Util") JvmMultifileClass] +package test + +inline fun foo(body: () -> Unit) { + publicInThisFile() + publicInOtherFile() + body() +} + +public fun publicInThisFile() {} + +fun bar() { + foo {} +} + +// @test/Util__ThisFileKt.class: +// 2 INVOKESTATIC test/Util.publicInThisFile +// 2 INVOKESTATIC test/Util.publicInOtherFile \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextMultifileTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextMultifileTestGenerated.java index 9d0838b4687..edb2fb2e70c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextMultifileTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextMultifileTestGenerated.java @@ -40,4 +40,10 @@ public class BytecodeTextMultifileTestGenerated extends AbstractBytecodeTextTest String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeTextMultifile/partMembersCall/"); doTestMultiFile(fileName); } + + @TestMetadata("partMembersInline") + public void testPartMembersInline() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeTextMultifile/partMembersInline/"); + doTestMultiFile(fileName); + } } diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt b/compiler/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt index 0007b4289c6..4d08ae2dad8 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt +++ b/compiler/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt @@ -34,11 +34,13 @@ import kotlin.properties.Delegates public object InlineTestUtil { public val INLINE_ANNOTATION_CLASS: String = "kotlin/inline" + private val KOTLIN_PACKAGE_DESC = "L" + AsmUtil.internalNameByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_PACKAGE) + ";" + private val KOTLIN_MULTIFILE_CLASS_DESC = "L" + AsmUtil.internalNameByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_MULTIFILE_CLASS) + ";" public fun checkNoCallsToInline(files: Iterable, sourceFiles: List) { val inlineInfo = obtainInlineInfo(files) val inlineMethods = inlineInfo.inlineMethods - assert(!inlineMethods.isEmpty(), "There are no inline methods") + assert(!inlineMethods.isEmpty()) { "There are no inline methods" } val notInlinedCalls = checkInlineMethodNotInvoked(files, inlineMethods) assert(notInlinedCalls.isEmpty()) { "All inline methods should be inlined but:\n" + notInlinedCalls.joinToString("\n") } @@ -94,7 +96,7 @@ public object InlineTestUtil { private var skipMethodsOfThisClass = false override fun visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor? { - if (desc.endsWith("KotlinPackage;") || desc.endsWith("KotlinMultifileClass;")) { + if (desc == KOTLIN_PACKAGE_DESC || desc == KOTLIN_MULTIFILE_CLASS_DESC) { skipMethodsOfThisClass = true } return null diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxMultiFileCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxMultiFileCodegenTestGenerated.java index 3244e8a9c00..ea00b54ea2b 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxMultiFileCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxMultiFileCodegenTestGenerated.java @@ -53,6 +53,12 @@ public class BlackBoxMultiFileCodegenTestGenerated extends AbstractBlackBoxCodeg doTestMultiFile(fileName); } + @TestMetadata("inlineMultifileClassMemberFromOtherPackage") + public void testInlineMultifileClassMemberFromOtherPackage() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxMultiFile/inlineMultifileClassMemberFromOtherPackage/"); + doTestMultiFile(fileName); + } + @TestMetadata("internalVisibility") public void testInternalVisibility() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxMultiFile/internalVisibility/"); @@ -89,6 +95,12 @@ public class BlackBoxMultiFileCodegenTestGenerated extends AbstractBlackBoxCodeg doTestMultiFile(fileName); } + @TestMetadata("multifileClassPartsInitialization") + public void testMultifileClassPartsInitialization() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxMultiFile/multifileClassPartsInitialization/"); + doTestMultiFile(fileName); + } + @TestMetadata("packageLocalClassNotImportedWithDefaultImport") public void testPackageLocalClassNotImportedWithDefaultImport() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxMultiFile/packageLocalClassNotImportedWithDefaultImport/"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index 5f2f736e5be..2a5517e81a3 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -35,6 +35,21 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithStdlib"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("compiler/testData/codegen/boxWithStdlib/againstMultifileStdlib") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class AgainstMultifileStdlib extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInAgainstMultifileStdlib() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithStdlib/againstMultifileStdlib"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("useStdlib.kt") + public void testUseStdlib() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/againstMultifileStdlib/useStdlib.kt"); + doTestWithStdlib(fileName); + } + } + @TestMetadata("compiler/testData/codegen/boxWithStdlib/annotations") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/AbstractBlackBoxMultifileClassCodegenTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/AbstractBlackBoxMultifileClassCodegenTest.kt new file mode 100644 index 00000000000..3cfe4031164 --- /dev/null +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/AbstractBlackBoxMultifileClassCodegenTest.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.jvm.compiler + +import org.jetbrains.kotlin.codegen.generated.AbstractBlackBoxCodegenTest +import java.io.File + + +public abstract class AbstractBlackBoxMultifileClassCodegenTest: AbstractBlackBoxCodegenTest() { + public fun doTestMultifileClassAgainstSources(firstFileName: String) { + val fileName = relativePath(File(firstFileName)) + val inputFiles = listOf(fileName, fileName.substringBeforeLast("1.kt") + "2.kt") + + doTestMultiFile(inputFiles) + } +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/AbstractCompileKotlinAgainstMultifileKotlinTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/AbstractCompileKotlinAgainstMultifileKotlinTest.kt index 79bd9b6b273..62b700653f7 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/AbstractCompileKotlinAgainstMultifileKotlinTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/AbstractCompileKotlinAgainstMultifileKotlinTest.kt @@ -26,8 +26,7 @@ public abstract class AbstractCompileKotlinAgainstMultifileKotlinTest : Abstract public fun doBoxTest(firstFileName: String) { val inputFiles = listOf(firstFileName, firstFileName.substringBeforeLast("1.kt") + "2.kt") - - val (factory1, factory2) = doBoxTest(inputFiles) + doBoxTest(inputFiles) } private fun doBoxTest(files: List): Pair { diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/BlackBoxMultifileClassKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/BlackBoxMultifileClassKotlinTestGenerated.java new file mode 100644 index 00000000000..b33231a1612 --- /dev/null +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/BlackBoxMultifileClassKotlinTestGenerated.java @@ -0,0 +1,64 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.jvm.compiler; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.JetTestUtils; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("compiler/testData/codegen/boxMultifileClasses") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class BlackBoxMultifileClassKotlinTestGenerated extends AbstractBlackBoxMultifileClassCodegenTest { + public void testAllFilesPresentInBoxMultifileClasses() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxMultifileClasses"), Pattern.compile("^(.+)\\.1.kt$"), true); + } + + @TestMetadata("compiler/testData/codegen/boxMultifileClasses/calls") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Calls extends AbstractBlackBoxMultifileClassCodegenTest { + public void testAllFilesPresentInCalls() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxMultifileClasses/calls"), Pattern.compile("^(.+)\\.1.kt$"), true); + } + + @TestMetadata("callFromOtherPackage.1.kt") + public void testCallFromOtherPackage() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxMultifileClasses/calls/callFromOtherPackage.1.kt"); + doTestMultifileClassAgainstSources(fileName); + } + + @TestMetadata("valFromOtherPackage.1.kt") + public void testValFromOtherPackage() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxMultifileClasses/calls/valFromOtherPackage.1.kt"); + doTestMultifileClassAgainstSources(fileName); + } + + @TestMetadata("varFromOtherPackage.1.kt") + public void testVarFromOtherPackage() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxMultifileClasses/calls/varFromOtherPackage.1.kt"); + doTestMultifileClassAgainstSources(fileName); + } + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstMultifileKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstMultifileKotlinTestGenerated.java index 3ebccef8abc..b4443fc2478 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstMultifileKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstMultifileKotlinTestGenerated.java @@ -48,5 +48,17 @@ public class CompileKotlinAgainstMultifileKotlinTestGenerated extends AbstractCo String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxMultifileClasses/calls/callFromOtherPackage.1.kt"); doBoxTest(fileName); } + + @TestMetadata("valFromOtherPackage.1.kt") + public void testValFromOtherPackage() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxMultifileClasses/calls/valFromOtherPackage.1.kt"); + doBoxTest(fileName); + } + + @TestMetadata("varFromOtherPackage.1.kt") + public void testVarFromOtherPackage() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxMultifileClasses/calls/varFromOtherPackage.1.kt"); + doBoxTest(fileName); + } } } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaPackageScope.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaPackageScope.kt index 6e4ee9a4eb1..83718b368f8 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaPackageScope.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaPackageScope.kt @@ -63,7 +63,7 @@ public class LazyJavaPackageScope( val result = hashMapOf() kotlinClasses@for (kotlinClass in kotlinBinaryClasses()) { val header = kotlinClass.classHeader - when (header.kind ) { + when (header.kind) { KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> { val partName = kotlinClass.classId.shortClassName.asString() val facadeName = header.multifileClassName ?: continue@kotlinClasses diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.java index 38ad66e2e5b..804b8577fcc 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.java @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.load.kotlin; +import kotlin.KotlinPackage; import kotlin.jvm.functions.Function0; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -34,17 +35,19 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil; import javax.inject.Inject; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; +import java.util.*; import static org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader.Kind.CLASS; +import static org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader.Kind.MULTIFILE_CLASS_PART; public final class DeserializedDescriptorResolver { private final ErrorReporter errorReporter; private DeserializationComponents components; + public static final Set KOTLIN_CLASS = KotlinPackage.setOf(CLASS); + public static final Set KOTLIN_FILE_FACADE_OR_MULTIFILE_CLASS_PART = + KotlinPackage.setOf(KotlinClassHeader.Kind.FILE_FACADE, MULTIFILE_CLASS_PART); + public DeserializedDescriptorResolver(@NotNull ErrorReporter errorReporter) { this.errorReporter = errorReporter; } @@ -57,7 +60,7 @@ public final class DeserializedDescriptorResolver { @Nullable public ClassDescriptor resolveClass(@NotNull KotlinJvmBinaryClass kotlinClass) { - String[] data = readData(kotlinClass, CLASS); + String[] data = readData(kotlinClass, KOTLIN_CLASS); if (data != null) { ClassData classData = JvmProtoBufUtil.readClassDataFrom(data); KotlinJvmBinarySourceElement sourceElement = new KotlinJvmBinarySourceElement(kotlinClass); @@ -69,7 +72,7 @@ public final class DeserializedDescriptorResolver { @Nullable public JetScope createKotlinPackagePartScope(@NotNull PackageFragmentDescriptor descriptor, @NotNull KotlinJvmBinaryClass kotlinClass) { - String[] data = readData(kotlinClass, null); + String[] data = readData(kotlinClass, KOTLIN_FILE_FACADE_OR_MULTIFILE_CLASS_PART); if (data != null) { //all classes are included in java scope PackageData packageData = JvmProtoBufUtil.readPackageDataFrom(data); @@ -102,12 +105,12 @@ public final class DeserializedDescriptorResolver { } @Nullable - public String[] readData(@NotNull KotlinJvmBinaryClass kotlinClass, @Nullable KotlinClassHeader.Kind expectedKind) { + public String[] readData(@NotNull KotlinJvmBinaryClass kotlinClass, @NotNull Set expectedKinds) { KotlinClassHeader header = kotlinClass.getClassHeader(); if (!header.getIsCompatibleAbiVersion()) { errorReporter.reportIncompatibleAbiVersion(kotlinClass.getClassId(), kotlinClass.getLocation(), header.getVersion()); } - else if (expectedKind == null || header.getKind() == expectedKind) { + else if (expectedKinds.contains(header.getKind())) { return header.getAnnotationData(); } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JavaClassDataFinder.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JavaClassDataFinder.kt index cf81a967bde..d75f34adf01 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JavaClassDataFinder.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JavaClassDataFinder.kt @@ -31,7 +31,7 @@ public class JavaClassDataFinder( assert(kotlinJvmBinaryClass.getClassId() == classId) { "Class with incorrect id found: expected $classId, actual ${kotlinJvmBinaryClass.getClassId()}" } - val data = deserializedDescriptorResolver.readData(kotlinJvmBinaryClass, KotlinClassHeader.Kind.CLASS) ?: return null + val data = deserializedDescriptorResolver.readData(kotlinJvmBinaryClass, DeserializedDescriptorResolver.KOTLIN_CLASS) ?: return null val classData = JvmProtoBufUtil.readClassDataFrom(data) return ClassDataProvider(classData, KotlinJvmBinarySourceElement(kotlinJvmBinaryClass)) } diff --git a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index 0c78e20a243..ff4ceb730e6 100644 --- a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -183,7 +183,11 @@ fun main(args: Array) { model("codegen/boxInline", extension = "1.kt", testMethod = "doBoxTestWithInlineCheck") } - testClass(javaClass(), "CompileKotlinAgainstMultifileKotlinTestGenerated") { + testClass(AbstractBlackBoxMultifileClassCodegenTest::class.java, "BlackBoxMultifileClassKotlinTestGenerated") { + model("codegen/boxMultifileClasses", extension = "1.kt", testMethod = "doTestMultifileClassAgainstSources") + } + + testClass(AbstractCompileKotlinAgainstMultifileKotlinTest::class.java, "CompileKotlinAgainstMultifileKotlinTestGenerated") { model("codegen/boxMultifileClasses", extension = "1.kt", testMethod = "doBoxTest") } diff --git a/idea/testData/debugger/tinyApp/outs/stepIntoStdlibFacadeClass.out b/idea/testData/debugger/tinyApp/outs/stepIntoStdlibFacadeClass.out index 4abd2229886..8fde5157a9a 100644 --- a/idea/testData/debugger/tinyApp/outs/stepIntoStdlibFacadeClass.out +++ b/idea/testData/debugger/tinyApp/outs/stepIntoStdlibFacadeClass.out @@ -2,8 +2,8 @@ LineBreakpoint created at stepIntoStdlibFacadeClass.kt:6 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! stepIntoStdlibFacadeClass.StepIntoStdlibFacadeClassPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' stepIntoStdlibFacadeClass.kt:6 +KotlinPackage.!EXT! _Mapping.!EXT! -Iterators.!EXT! Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/libraries/stdlib/pom.xml b/libraries/stdlib/pom.xml index 0b03eac4279..d48bfbd40c5 100644 --- a/libraries/stdlib/pom.xml +++ b/libraries/stdlib/pom.xml @@ -31,6 +31,12 @@ kotlin-maven-plugin ${project.version} + + + -Xmultifile-package-facades + + + compile