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
@@ -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);