提交 8fe9de1d 编写于 作者: D Dmitry Petrov

Generate toArray methods defined in classes inherited from collections as...

Generate toArray methods defined in classes inherited from collections as public even if they are declared with different visibility in Kotlin.
上级 c5d03578
......@@ -63,6 +63,7 @@ import java.util.Set;
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isBoolean;
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isPrimitiveClass;
import static org.jetbrains.kotlin.codegen.CodegenUtilKt.isToArrayFromCollection;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConstOrHasJvmFieldAnnotation;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isInlineOnlyOrReified;
......@@ -354,6 +355,10 @@ public class AsmUtil {
return NO_FLAG_PACKAGE_PRIVATE;
}
if (isToArrayFromCollection(memberDescriptor)) {
return ACC_PUBLIC;
}
if (memberDescriptor instanceof ConstructorDescriptor && isAnonymousObject(memberDescriptor.getContainingDeclaration())) {
return getVisibilityAccessFlagForAnonymous((ClassDescriptor) memberDescriptor.getContainingDeclaration());
}
......
......@@ -62,7 +62,6 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver;
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver;
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
import org.jetbrains.org.objectweb.asm.FieldVisitor;
import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
......@@ -74,6 +73,8 @@ import java.util.*;
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES;
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
import static org.jetbrains.kotlin.codegen.CodegenUtilKt.isGenericToArray;
import static org.jetbrains.kotlin.codegen.CodegenUtilKt.isNonGenericToArray;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall;
......@@ -397,35 +398,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
private boolean isGenericToArray(@NotNull FunctionDescriptor function) {
if (function.getValueParameters().size() != 1 || function.getTypeParameters().size() != 1) {
return false;
}
KotlinType returnType = function.getReturnType();
assert returnType != null : function.toString();
KotlinType paramType = function.getValueParameters().get(0).getType();
if (KotlinBuiltIns.isArray(returnType) && KotlinBuiltIns.isArray(paramType)) {
KotlinType elementType = function.getTypeParameters().get(0).getDefaultType();
KotlinBuiltIns builtIns = DescriptorUtilsKt.getBuiltIns(descriptor);
if (KotlinTypeChecker.DEFAULT.equalTypes(elementType, builtIns.getArrayElementType(returnType))
&& KotlinTypeChecker.DEFAULT.equalTypes(elementType, builtIns.getArrayElementType(paramType))) {
return true;
}
}
return false;
}
private static boolean isNonGenericToArray(@NotNull FunctionDescriptor function) {
if (!function.getValueParameters().isEmpty() || !function.getTypeParameters().isEmpty()) {
return false;
}
KotlinType returnType = function.getReturnType();
return returnType != null && KotlinBuiltIns.isArray(returnType);
}
private void generateToArray() {
if (descriptor.getKind() == ClassKind.INTERFACE) return;
......
......@@ -38,15 +38,18 @@ import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils.isSubclass
import org.jetbrains.kotlin.resolve.annotations.hasJvmStaticAnnotation
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.serialization.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.utils.DFS
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
import org.jetbrains.org.objectweb.asm.Label
......@@ -297,3 +300,34 @@ fun KtExpression?.asmType(typeMapper: KotlinTypeMapper, bindingContext: BindingC
fun KtExpression?.kotlinType(bindingContext: BindingContext) = this?.let(bindingContext::getType)
fun FunctionDescriptor.isGenericToArray(): Boolean {
if (valueParameters.size != 1 || typeParameters.size != 1) return false
val returnType = returnType ?: throw AssertionError(toString())
val paramType = valueParameters[0].type
if (!KotlinBuiltIns.isArray(returnType) || !KotlinBuiltIns.isArray(paramType)) return false
val elementType = typeParameters[0].defaultType
return KotlinTypeChecker.DEFAULT.equalTypes(elementType, builtIns.getArrayElementType(returnType)) &&
KotlinTypeChecker.DEFAULT.equalTypes(elementType, builtIns.getArrayElementType(paramType))
}
fun FunctionDescriptor.isNonGenericToArray(): Boolean {
if (!valueParameters.isEmpty() || !typeParameters.isEmpty()) return false
val returnType = returnType
return returnType != null && KotlinBuiltIns.isArray(returnType)
}
fun MemberDescriptor.isToArrayFromCollection(): Boolean {
if (this !is FunctionDescriptor) return false
val containingClassDescriptor = containingDeclaration as? ClassDescriptor ?: return false
if (containingClassDescriptor.source == SourceElement.NO_SOURCE) return false
val collectionClass = builtIns.collection
if (!isSubclass(containingClassDescriptor, collectionClass)) return false
return isGenericToArray() || isNonGenericToArray()
}
\ No newline at end of file
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// FILE: SingletonCollection.kt
package test
open class SingletonCollection<T>(val value: T) : AbstractCollection<T>() {
override val size = 1
override fun iterator(): Iterator<T> = listOf(value).iterator()
protected fun toArray(): Array<Any?> =
arrayOf<Any?>(value)
protected fun <E> toArray(a: Array<E>): Array<E> {
a[0] = value as E
return a
}
}
// FILE: DerivedSingletonCollection.kt
package test2
import test.*
class DerivedSingletonCollection<T>(value: T) : SingletonCollection<T>(value)
// FILE: box.kt
import test.*
import test2.*
fun box(): String {
val sc = SingletonCollection(42)
val test1 = (sc as java.util.Collection<Int>).toArray()
if (test1[0] != 42) return "Failed #1"
val test2 = arrayOf<Any?>(0)
(sc as java.util.Collection<Int>).toArray(test2)
if (test2[0] != 42) return "Failed #2"
val dsc = DerivedSingletonCollection(42)
val test3 = (dsc as java.util.Collection<Int>).toArray()
if (test3[0] != 42) return "Failed #3"
val test4 = arrayOf<Any?>(0)
(dsc as java.util.Collection<Int>).toArray(test4)
if (test4[0] != 42) return "Failed #4"
return "OK"
}
\ No newline at end of file
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// FILE: SingletonCollection.kt
package test
open class SingletonCollection<T>(val value: T) : AbstractCollection<T>() {
override val size = 1
override fun iterator(): Iterator<T> = listOf(value).iterator()
protected open fun toArray(): Array<Any?> =
arrayOf<Any?>(value)
protected open fun <E> toArray(a: Array<E>): Array<E> {
a[0] = value as E
return a
}
}
// FILE: JavaSingletonCollection.java
import test.*;
public class JavaSingletonCollection<T> extends SingletonCollection<T> {
public JavaSingletonCollection(T value) {
super(value);
}
}
// FILE: JavaSingletonCollection2.java
import test.*;
public class JavaSingletonCollection2<T> extends SingletonCollection<T> {
public JavaSingletonCollection2(T value) {
super(value);
}
public Object[] toArray() {
return super.toArray();
}
public <E> E[] toArray(E[] arr) {
return super.toArray(arr);
}
}
// FILE: box.kt
import test.*
fun box(): String {
val jsc = JavaSingletonCollection(42) as java.util.Collection<Int>
val test3 = jsc.toArray()
if (test3[0] != 42) return "Failed #3"
val test4 = arrayOf<Any?>(0)
jsc.toArray(test4)
if (test4[0] != 42) return "Failed #4"
val jsc2 = JavaSingletonCollection2(42) as java.util.Collection<Int>
val test5 = jsc2.toArray()
if (test5[0] != 42) return "Failed #5"
val test6 = arrayOf<Any?>(0)
jsc2.toArray(test6)
if (test6[0] != 42) return "Failed #6"
return "OK"
}
\ No newline at end of file
public final class BoxKt {
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
}
public class test/SingletonCollection {
private final field size: int
private final field value: java.lang.Object
public method <init>(p0: java.lang.Object): void
public method getSize(): int
public final method getValue(): java.lang.Object
public @org.jetbrains.annotations.NotNull method iterator(): java.util.Iterator
public final @org.jetbrains.annotations.NotNull method toArray(): java.lang.Object[]
public final @org.jetbrains.annotations.NotNull method toArray(@org.jetbrains.annotations.NotNull p0: java.lang.Object[]): java.lang.Object[]
}
public final class test2/DerivedSingletonCollection {
public method <init>(p0: java.lang.Object): void
}
public final class BoxKt {
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
}
public class test/SingletonCollection {
private final field size: int
private final field value: java.lang.Object
public method <init>(p0: java.lang.Object): void
public method getSize(): int
public final method getValue(): java.lang.Object
public @org.jetbrains.annotations.NotNull method iterator(): java.util.Iterator
public @org.jetbrains.annotations.NotNull method toArray(): java.lang.Object[]
public @org.jetbrains.annotations.NotNull method toArray(@org.jetbrains.annotations.NotNull p0: java.lang.Object[]): java.lang.Object[]
}
......@@ -16367,6 +16367,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
doTest(fileName);
}
@TestMetadata("toArrayShouldBePublic.kt")
public void testToArrayShouldBePublic() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/toArray/toArrayShouldBePublic.kt");
doTest(fileName);
}
@TestMetadata("toArrayShouldBePublicWithJava.kt")
public void testToArrayShouldBePublicWithJava() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/toArray/toArrayShouldBePublicWithJava.kt");
doTest(fileName);
}
@TestMetadata("toTypedArray.kt")
public void testToTypedArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/toArray/toTypedArray.kt");
......
......@@ -16367,6 +16367,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("toArrayShouldBePublic.kt")
public void testToArrayShouldBePublic() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/toArray/toArrayShouldBePublic.kt");
doTest(fileName);
}
@TestMetadata("toArrayShouldBePublicWithJava.kt")
public void testToArrayShouldBePublicWithJava() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/toArray/toArrayShouldBePublicWithJava.kt");
doTest(fileName);
}
@TestMetadata("toTypedArray.kt")
public void testToTypedArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/toArray/toTypedArray.kt");
......
......@@ -16367,6 +16367,18 @@ public class LightAnalysisModeCodegenTestGenerated extends AbstractLightAnalysis
doTest(fileName);
}
@TestMetadata("toArrayShouldBePublic.kt")
public void testToArrayShouldBePublic() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/toArray/toArrayShouldBePublic.kt");
doTest(fileName);
}
@TestMetadata("toArrayShouldBePublicWithJava.kt")
public void testToArrayShouldBePublicWithJava() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/toArray/toArrayShouldBePublicWithJava.kt");
doTest(fileName);
}
@TestMetadata("toTypedArray.kt")
public void testToTypedArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/toArray/toTypedArray.kt");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册