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.
This commit is contained in:
Dmitry Petrov
2015-09-11 19:14:10 +03:00
parent 838433ba8a
commit 1586a2df8e
43 changed files with 363 additions and 90 deletions
+1
View File
@@ -702,6 +702,7 @@
<arg value="-d"/>
<arg value="@{output}"/>
<arg value="-no-stdlib"/>
<arg value="-Xmultifile-package-facades"/>
<arg value="-classpath"/>
<arg value="${toString:classpath.path}"/>
<arg value="-module-name"/>
@@ -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<JetFile, JvmFileClassInfo>()
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
}
}
}
@@ -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<T extends JetElement/* TODO: & JetDeclaratio
return implementationOwnerType;
}
else {
return fileClassesProvider.getFileClassType(element.getContainingJetFile());
return FileClassesPackage.getFileClassType(fileClassesProvider, element.getContainingJetFile());
}
}
/*disabled cause of KT-7775
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
import org.jetbrains.kotlin.fileClasses.getFileClassType
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.kotlin.PackageParts
import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentProvider
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
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;
@@ -313,7 +314,7 @@ public class PackageCodegen {
@Nullable
private ClassBuilder generate(@NotNull JetFile file, @NotNull Map<CallableMemberDescriptor, Runnable> 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);
}
@@ -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> T peekFromStack(@NotNull Stack<T> stack) {
@@ -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());
@@ -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) {
@@ -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")
@@ -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);
@@ -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)}"
@@ -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()
@@ -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<JetFile>): List<JetFile> =
getFilesWithCallables(files).filter { getPackagePartFqName(it) == partFqName }
public @JvmStatic fun getFilePartShortName(fileName: String): String =
getPartClassName(FileUtil.getNameWithoutExtension(fileName))
@@ -1,4 +1,6 @@
@file:[JvmName("MultifileClass") JvmMultifileClass]
package a
inline fun foo(body: () -> String): String = body()
inline fun foo(body: () -> String): String = bar(body())
public fun bar(x: String): String = x
@@ -0,0 +1,5 @@
package test
import a.foo
fun box(): String = foo { "OK" }
@@ -0,0 +1,4 @@
@file:[JvmName("APackage") JvmMultifileClass]
package a
inline fun foo(body: () -> String): String = zee(body())
@@ -0,0 +1,4 @@
@file:[JvmName("APackage") JvmMultifileClass]
package a
public fun zee(x: String): String = x
@@ -0,0 +1,3 @@
import a.*
fun box(): String = OK
@@ -0,0 +1,4 @@
@file:[JvmName("MultifileClass") JvmMultifileClass]
package a
val O: String = "O"
@@ -0,0 +1,4 @@
@file:[JvmName("MultifileClass") JvmMultifileClass]
package a
val K: String = "K"
@@ -0,0 +1,4 @@
@file:[JvmName("MultifileClass") JvmMultifileClass]
package a
val OK: String = O + K
@@ -0,0 +1,3 @@
import a.OK
fun box(): String = OK
@@ -0,0 +1,4 @@
@file:[JvmName("MultifileClass") JvmMultifileClass]
package a
val OK: String = "OK"
@@ -0,0 +1,6 @@
import a.OK
fun box(): String {
OK = "OK"
return OK
}
@@ -0,0 +1,4 @@
@file:[JvmName("MultifileClass") JvmMultifileClass]
package a
var OK: String = "Hmmm?"
@@ -0,0 +1,2 @@
fun box(): String =
listOf("a").map { "OK" }.get(0)
@@ -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
@@ -0,0 +1,4 @@
@file:[JvmName("Util") JvmMultifileClass]
package test
public fun publicInOtherFile() {}
@@ -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
@@ -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);
}
}
@@ -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<OutputFile>, sourceFiles: List<JetFile>) {
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
@@ -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/");
@@ -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)
@@ -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)
}
}
@@ -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<String>): Pair<ClassFileFactory, ClassFileFactory> {
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -63,7 +63,7 @@ public class LazyJavaPackageScope(
val result = hashMapOf<String, String>()
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
@@ -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<KotlinClassHeader.Kind> KOTLIN_CLASS = KotlinPackage.setOf(CLASS);
public static final Set<KotlinClassHeader.Kind> 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<KotlinClassHeader.Kind> 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();
}
@@ -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))
}
@@ -183,7 +183,11 @@ fun main(args: Array<String>) {
model("codegen/boxInline", extension = "1.kt", testMethod = "doBoxTestWithInlineCheck")
}
testClass(javaClass<AbstractCompileKotlinAgainstMultifileKotlinTest>(), "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")
}
@@ -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
+6
View File
@@ -31,6 +31,12 @@
<artifactId>kotlin-maven-plugin</artifactId>
<version>${project.version}</version>
<configuration>
<args>
<arg>-Xmultifile-package-facades</arg>
</args>
</configuration>
<executions>
<execution>
<id>compile</id>