Use descriptors for building SAM constructors
It helps to get rid of semantics duplicating and fixes known bugs - SOE in OnlyAbstractMethodFinder.find - type enhancement for SAM constructors #KT-11287 Fixed #KT-11322 Fixed EA-77989 Fixed
This commit is contained in:
+2
-42
@@ -19,20 +19,13 @@ package org.jetbrains.kotlin.load.java.sam
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.load.java.components.SamConversionResolver
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaConstructorDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor
|
||||
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaClassDescriptor
|
||||
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaMethod
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import java.util.*
|
||||
|
||||
object SamConversionResolverImpl : SamConversionResolver {
|
||||
override fun resolveSamConstructor(constructorOwner: DeclarationDescriptor, classifier: () -> ClassifierDescriptor?): SamConstructorDescriptor? {
|
||||
@@ -51,41 +44,8 @@ object SamConversionResolverImpl : SamConversionResolver {
|
||||
}
|
||||
}
|
||||
|
||||
override fun resolveFunctionTypeIfSamInterface(
|
||||
classDescriptor: JavaClassDescriptor,
|
||||
resolveMethod: (JavaMethod) -> FunctionDescriptor
|
||||
): KotlinType? {
|
||||
val jClass = (classDescriptor.source as? JavaSourceElement)?.javaElement as? JavaClass ?: return null
|
||||
val samInterfaceMethod = SingleAbstractMethodUtils.getSamInterfaceMethod(jClass) ?: return null
|
||||
val abstractMethod = if (jClass.fqName == samInterfaceMethod.containingClass.fqName) {
|
||||
resolveMethod(samInterfaceMethod)
|
||||
}
|
||||
else {
|
||||
findFunctionWithMostSpecificReturnType(TypeUtils.getAllSupertypes(classDescriptor.defaultType))
|
||||
}
|
||||
override fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): KotlinType? {
|
||||
val abstractMethod = SingleAbstractMethodUtils.getSingleAbstractMethodOrNull(classDescriptor) ?: return null
|
||||
return SingleAbstractMethodUtils.getFunctionTypeForAbstractMethod(abstractMethod)
|
||||
}
|
||||
|
||||
private fun findFunctionWithMostSpecificReturnType(supertypes: Set<KotlinType>): SimpleFunctionDescriptor {
|
||||
val candidates = ArrayList<SimpleFunctionDescriptor>(supertypes.size)
|
||||
for (supertype in supertypes) {
|
||||
val abstractMembers = SingleAbstractMethodUtils.getAbstractMembers(supertype)
|
||||
if (!abstractMembers.isEmpty()) {
|
||||
candidates.add((abstractMembers[0] as SimpleFunctionDescriptor))
|
||||
}
|
||||
}
|
||||
if (candidates.isEmpty()) {
|
||||
throw IllegalStateException("Couldn't find abstract method in supertypes " + supertypes)
|
||||
}
|
||||
var currentMostSpecificType = candidates[0]
|
||||
for (candidate in candidates) {
|
||||
val candidateReturnType = candidate.returnType
|
||||
val currentMostSpecificReturnType = currentMostSpecificType.returnType
|
||||
assert(candidateReturnType != null && currentMostSpecificReturnType != null) { "$candidate, $currentMostSpecificReturnType" }
|
||||
if (KotlinTypeChecker.DEFAULT.isSubtypeOf(candidateReturnType!!, currentMostSpecificReturnType!!)) {
|
||||
currentMostSpecificType = candidate
|
||||
}
|
||||
}
|
||||
return currentMostSpecificType
|
||||
}
|
||||
}
|
||||
|
||||
+13
-118
@@ -18,26 +18,23 @@ package org.jetbrains.kotlin.load.java.sam;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl;
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl;
|
||||
import org.jetbrains.kotlin.load.java.components.DescriptorResolverUtils;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.*;
|
||||
import org.jetbrains.kotlin.load.java.lazy.types.LazyJavaTypeResolver;
|
||||
import org.jetbrains.kotlin.load.java.structure.*;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.CapturedTypeConstructorKt;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JavaResolverUtils;
|
||||
import org.jetbrains.kotlin.types.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.kotlin.types.Variance.INVARIANT;
|
||||
import static org.jetbrains.kotlin.types.Variance.IN_VARIANCE;
|
||||
|
||||
public class SingleAbstractMethodUtils {
|
||||
@@ -95,19 +92,23 @@ public class SingleAbstractMethodUtils {
|
||||
return DescriptorUtilsKt.getBuiltIns(function).getFunctionType(Annotations.Companion.getEMPTY(), null, parameterTypes, returnType);
|
||||
}
|
||||
|
||||
private static boolean isSamInterface(@NotNull ClassDescriptor klass) {
|
||||
@Nullable
|
||||
public static FunctionDescriptor getSingleAbstractMethodOrNull(@NotNull ClassDescriptor klass) {
|
||||
if (klass.getKind() != ClassKind.INTERFACE) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
List<CallableMemberDescriptor> abstractMembers = getAbstractMembers(klass.getDefaultType());
|
||||
if (abstractMembers.size() == 1) {
|
||||
CallableMemberDescriptor member = abstractMembers.get(0);
|
||||
if (member instanceof SimpleFunctionDescriptor) {
|
||||
return member.getTypeParameters().isEmpty();
|
||||
return member.getTypeParameters().isEmpty()
|
||||
? (FunctionDescriptor) member
|
||||
: null;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -115,7 +116,7 @@ public class SingleAbstractMethodUtils {
|
||||
@NotNull DeclarationDescriptor owner,
|
||||
@NotNull JavaClassDescriptor samInterface
|
||||
) {
|
||||
assert isSamInterface(samInterface) : samInterface;
|
||||
assert getSingleAbstractMethodOrNull(samInterface) != null : samInterface;
|
||||
|
||||
SamConstructorDescriptor result = new SamConstructorDescriptor(owner, samInterface);
|
||||
|
||||
@@ -282,29 +283,6 @@ public class SingleAbstractMethodUtils {
|
||||
return new TypeParameters(typeParameters, typeParametersSubstitutor);
|
||||
}
|
||||
|
||||
// Returns null if not SAM interface
|
||||
@Nullable
|
||||
public static JavaMethod getSamInterfaceMethod(@NotNull JavaClass javaClass) {
|
||||
FqName fqName = javaClass.getFqName();
|
||||
if (fqName == null || fqName.toUnsafe().startsWith(KotlinBuiltIns.BUILT_INS_PACKAGE_NAME)) {
|
||||
return null;
|
||||
}
|
||||
if (!javaClass.isInterface() || javaClass.isAnnotationType()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return findOnlyAbstractMethod(javaClass);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static JavaMethod findOnlyAbstractMethod(@NotNull JavaClass javaClass) {
|
||||
OnlyAbstractMethodFinder finder = new OnlyAbstractMethodFinder();
|
||||
if (finder.find(javaClass.getDefaultType())) {
|
||||
return finder.getFoundMethod();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class TypeParameters {
|
||||
public final List<TypeParameterDescriptor> descriptors;
|
||||
public final TypeSubstitutor substitutor;
|
||||
@@ -323,88 +301,5 @@ public class SingleAbstractMethodUtils {
|
||||
);
|
||||
}
|
||||
|
||||
private static class OnlyAbstractMethodFinder {
|
||||
private static final FqName OBJECT_FQ_NAME = new FqName("java.lang.Object");
|
||||
|
||||
private JavaMethod foundMethod;
|
||||
private JavaTypeSubstitutor foundClassSubstitutor;
|
||||
|
||||
private boolean find(@NotNull JavaClassifierType classifierType) {
|
||||
JavaTypeSubstitutor classSubstitutor = classifierType.getSubstitutor();
|
||||
JavaClassifier classifier = classifierType.getClassifier();
|
||||
if (classifier == null) {
|
||||
return false; // can't resolve class -> not a SAM interface
|
||||
}
|
||||
assert classifier instanceof JavaClass : "Classifier should be a class here: " + classifier;
|
||||
JavaClass javaClass = (JavaClass) classifier;
|
||||
if (OBJECT_FQ_NAME.equals(javaClass.getFqName())) {
|
||||
return true;
|
||||
}
|
||||
for (JavaMethod method : javaClass.getMethods()) {
|
||||
|
||||
//skip java 8 default methods
|
||||
if (!method.isAbstract()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (DescriptorResolverUtils.isObjectMethod(method)) { // e.g., ignore toString() declared in interface
|
||||
continue;
|
||||
}
|
||||
if (!method.getTypeParameters().isEmpty()) {
|
||||
return false; // if interface has generic methods, it is not a SAM interface
|
||||
}
|
||||
|
||||
if (foundMethod == null) {
|
||||
foundMethod = method;
|
||||
foundClassSubstitutor = classSubstitutor;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!areSignaturesErasureEqual(method, classSubstitutor, foundMethod, foundClassSubstitutor)) {
|
||||
return false; // different signatures
|
||||
}
|
||||
}
|
||||
|
||||
for (JavaClassifierType t : classifierType.getSupertypes()) {
|
||||
if (!find(t)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.intellij.psi.util.MethodSignatureUtil#areSignaturesErasureEqual
|
||||
*/
|
||||
private static boolean areSignaturesErasureEqual(
|
||||
@NotNull JavaMethod method1,
|
||||
@NotNull JavaTypeSubstitutor substitutor1,
|
||||
@NotNull JavaMethod method2,
|
||||
@NotNull JavaTypeSubstitutor substitutor2
|
||||
) {
|
||||
if (!method1.getName().equals(method2.getName())) return false;
|
||||
|
||||
Collection<JavaValueParameter> parameters1 = method1.getValueParameters();
|
||||
Collection<JavaValueParameter> parameters2 = method2.getValueParameters();
|
||||
if (parameters1.size() != parameters2.size()) return false;
|
||||
|
||||
for (Iterator<JavaValueParameter> it1 = parameters1.iterator(), it2 = parameters2.iterator(); it1.hasNext(); ) {
|
||||
JavaValueParameter param1 = it1.next();
|
||||
JavaValueParameter param2 = it2.next();
|
||||
if (param1.isVararg() != param2.isVararg()) return false;
|
||||
|
||||
JavaType type1 = JavaResolverUtils.erasure(substitutor1.substitute(param1.getType()), substitutor1);
|
||||
JavaType type2 = JavaResolverUtils.erasure(substitutor2.substitute(param2.getType()), substitutor2);
|
||||
if (!(type1 == null ? type2 == null : type1.equals(type2))) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JavaMethod getFoundMethod() {
|
||||
return foundMethod;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,81 +34,6 @@ public class JavaResolverUtils {
|
||||
private JavaResolverUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.intellij.psi.util.TypeConversionUtil#erasure(com.intellij.psi.PsiType)
|
||||
*/
|
||||
@Nullable
|
||||
public static JavaType erasure(@NotNull JavaType type) {
|
||||
return erasure(type, JavaTypeSubstitutor.EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.intellij.psi.util.TypeConversionUtil#erasure(com.intellij.psi.PsiType, com.intellij.psi.PsiSubstitutor)
|
||||
*/
|
||||
@Nullable
|
||||
public static JavaType erasure(@NotNull JavaType type, @NotNull JavaTypeSubstitutor substitutor) {
|
||||
if (type instanceof JavaClassifierType) {
|
||||
JavaClassifier classifier = ((JavaClassifierType) type).getClassifier();
|
||||
if (classifier instanceof JavaClass) {
|
||||
return ((JavaClass) classifier).getDefaultType();
|
||||
}
|
||||
else if (classifier instanceof JavaTypeParameter) {
|
||||
JavaTypeParameter typeParameter = (JavaTypeParameter) classifier;
|
||||
return typeParameterErasure(typeParameter, new HashSet<JavaTypeParameter>(), substitutor);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else if (type instanceof JavaPrimitiveType) {
|
||||
return type;
|
||||
}
|
||||
else if (type instanceof JavaArrayType) {
|
||||
JavaType erasure = erasure(((JavaArrayType) type).getComponentType(), substitutor);
|
||||
return erasure == null ? null : erasure.createArrayType();
|
||||
}
|
||||
else if (type instanceof JavaWildcardType) {
|
||||
JavaWildcardType wildcardType = (JavaWildcardType) type;
|
||||
JavaType bound = wildcardType.getBound();
|
||||
if (bound != null && wildcardType.isExtends()) {
|
||||
return erasure(bound, substitutor);
|
||||
}
|
||||
return wildcardType.getTypeProvider().createJavaLangObjectType();
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Unsupported type: " + type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.intellij.psi.util.TypeConversionUtil#typeParameterErasure(com.intellij.psi.PsiTypeParameter)
|
||||
*/
|
||||
@Nullable
|
||||
private static JavaType typeParameterErasure(
|
||||
@NotNull JavaTypeParameter typeParameter,
|
||||
@NotNull HashSet<JavaTypeParameter> visited,
|
||||
@NotNull JavaTypeSubstitutor substitutor
|
||||
) {
|
||||
Collection<JavaClassifierType> upperBounds = typeParameter.getUpperBounds();
|
||||
if (!upperBounds.isEmpty()) {
|
||||
JavaClassifier classifier = upperBounds.iterator().next().getClassifier();
|
||||
if (classifier instanceof JavaTypeParameter && !visited.contains(classifier)) {
|
||||
JavaTypeParameter typeParameterBound = (JavaTypeParameter) classifier;
|
||||
visited.add(typeParameterBound);
|
||||
JavaType substitutedType = substitutor.substitute(typeParameterBound);
|
||||
if (substitutedType != null) {
|
||||
return erasure(substitutedType);
|
||||
}
|
||||
return typeParameterErasure(typeParameterBound, visited, substitutor);
|
||||
}
|
||||
else if (classifier instanceof JavaClass) {
|
||||
return ((JavaClass) classifier).getDefaultType();
|
||||
}
|
||||
}
|
||||
return typeParameter.getTypeProvider().createJavaLangObjectType();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> recreateTypeParametersAndReturnMapping(
|
||||
@NotNull List<TypeParameterDescriptor> originalParameters,
|
||||
@Nullable DeclarationDescriptor newOwner
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// FILE: A.java
|
||||
|
||||
public interface A extends A {
|
||||
int getFoo();
|
||||
}
|
||||
|
||||
// FILE: B.java
|
||||
|
||||
public class B {
|
||||
interface B1 extends B2 {
|
||||
int getFoo();
|
||||
}
|
||||
interface B2 extends B3 {
|
||||
int getFoo();
|
||||
}
|
||||
interface B3 extends B2 {
|
||||
int getFoo();
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun foo() {
|
||||
object : A { override fun getFoo() = 1 }
|
||||
object : B.B1 { override fun getFoo() = 1 }
|
||||
object : B.B2 { override fun getFoo() = 1 }
|
||||
object : B.B3 { override fun getFoo() = 1 }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package
|
||||
|
||||
public /*synthesized*/ fun A(/*0*/ function: () -> kotlin.Int): A
|
||||
public fun foo(): kotlin.Unit
|
||||
|
||||
public interface A {
|
||||
public abstract fun getFoo(): kotlin.Int
|
||||
}
|
||||
|
||||
public open class B {
|
||||
public constructor B()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
public/*package*/ interface B1 : B.B2 {
|
||||
public abstract override /*1*/ fun getFoo(): kotlin.Int
|
||||
}
|
||||
|
||||
public/*package*/ interface B2 {
|
||||
public abstract fun getFoo(): kotlin.Int
|
||||
}
|
||||
|
||||
public/*package*/ interface B3 {
|
||||
public abstract fun getFoo(): kotlin.Int
|
||||
}
|
||||
|
||||
// Static members
|
||||
public/*package*/ final /*synthesized*/ fun B1(/*0*/ function: () -> kotlin.Int): B.B1
|
||||
public/*package*/ final /*synthesized*/ fun B2(/*0*/ function: () -> kotlin.Int): B.B2
|
||||
public/*package*/ final /*synthesized*/ fun B3(/*0*/ function: () -> kotlin.Int): B.B3
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// FILE: A.java
|
||||
|
||||
public interface A extends A.B {
|
||||
interface B extends A { public int getFoo() { return 1; } }
|
||||
}
|
||||
|
||||
// FILE: A0.java
|
||||
public interface A0 extends A0.B {
|
||||
interface B { public int getFoo() { return 1; } }
|
||||
}
|
||||
|
||||
// FILE: B.java
|
||||
|
||||
public class B extends D {
|
||||
public int getFoo() { return 1; }
|
||||
public static class C {
|
||||
public int getFoo() { return 1; }
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: D.java
|
||||
public class D extends B.C {
|
||||
public int getFoo() { return 1; }
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package
|
||||
|
||||
public interface A {
|
||||
|
||||
public interface B {
|
||||
public abstract fun getFoo(): kotlin.Int
|
||||
}
|
||||
|
||||
// Static members
|
||||
public final /*synthesized*/ fun B(/*0*/ function: () -> kotlin.Int): A.B
|
||||
}
|
||||
|
||||
public interface A0 {
|
||||
|
||||
public interface B {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract fun getFoo(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
// Static members
|
||||
public final /*synthesized*/ fun B(/*0*/ function: () -> kotlin.Int): A0.B
|
||||
}
|
||||
|
||||
public open class B {
|
||||
public constructor B()
|
||||
public open fun getFoo(): kotlin.Int
|
||||
|
||||
public open class C {
|
||||
public constructor C()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun getFoo(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
public open class D {
|
||||
public constructor D()
|
||||
public open fun getFoo(): kotlin.Int
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package
|
||||
|
||||
public/*package*/ /*synthesized*/ fun A(/*0*/ function: () -> kotlin.Unit): A
|
||||
public/*package*/ /*synthesized*/ fun C(/*0*/ function: () -> kotlin.Unit): C
|
||||
|
||||
public/*package*/ interface A {
|
||||
public abstract fun foo(): kotlin.Unit
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// FILE: J.java
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
public interface J {
|
||||
@NotNull
|
||||
String foo(@Nullable String x);
|
||||
}
|
||||
|
||||
// FILE: J2.java
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface J2 extends J {
|
||||
String foo(String x);
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun main() {
|
||||
J { <!EXPECTED_PARAMETER_TYPE_MISMATCH!>s: String<!> -> s} // should be prohibited, because SAM value parameter has nullable type
|
||||
J { "" + it<!UNSAFE_CALL!>.<!>length }
|
||||
J { <!NULL_FOR_NONNULL_TYPE!>null<!> }
|
||||
J { <!TYPE_MISMATCH!>it?.length?.toString()<!> }
|
||||
|
||||
J2 { <!EXPECTED_PARAMETER_TYPE_MISMATCH!>s: String<!> -> s}
|
||||
J2 { "" + it<!UNSAFE_CALL!>.<!>length }
|
||||
J2 { <!NULL_FOR_NONNULL_TYPE!>null<!> }
|
||||
J2 { <!TYPE_MISMATCH!>it?.length?.toString()<!> }
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package
|
||||
|
||||
public /*synthesized*/ fun J(/*0*/ function: (kotlin.String?) -> kotlin.String): J
|
||||
public /*synthesized*/ fun J2(/*0*/ function: (kotlin.String?) -> kotlin.String): J2
|
||||
public fun main(): kotlin.Unit
|
||||
|
||||
public interface J {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
@org.jetbrains.annotations.NotNull() public abstract fun foo(/*0*/ @org.jetbrains.annotations.Nullable() x: kotlin.String?): kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface J2 : J {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract override /*1*/ fun foo(/*0*/ x: kotlin.String?): kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package
|
||||
|
||||
public/*package*/ /*synthesized*/ fun J(/*0*/ function: () -> kotlin.collections.(Mutable)List<kotlin.String!>!): J
|
||||
public/*package*/ /*synthesized*/ fun J(/*0*/ function: () -> kotlin.collections.List<kotlin.String>): J
|
||||
|
||||
public/*package*/ interface J : K {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
package
|
||||
|
||||
public /*synthesized*/ fun J1(/*0*/ function: () -> In<kotlin.String!>!): J1
|
||||
public /*synthesized*/ fun J2(/*0*/ function: () -> In<kotlin.String!>!): J2
|
||||
public /*synthesized*/ fun J3(/*0*/ function: () -> In<kotlin.String!>!): J3
|
||||
public /*synthesized*/ fun J2(/*0*/ function: () -> In<kotlin.String!>): J2
|
||||
public /*synthesized*/ fun J3(/*0*/ function: () -> In<kotlin.String!>?): J3
|
||||
|
||||
public interface In</*0*/ in T> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package
|
||||
|
||||
public /*synthesized*/ fun </*0*/ T : kotlin.Any!> A(/*0*/ function: (T!) -> kotlin.Boolean): A<T>
|
||||
public /*synthesized*/ fun </*0*/ T : kotlin.Any!> A(/*0*/ function: (T?) -> kotlin.Boolean): A<T>
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public interface A</*0*/ T : kotlin.Any!> {
|
||||
|
||||
compiler/testData/diagnostics/tests/platformTypes/notNullTypeParameter/enhancementFromAnnotation.txt
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
package
|
||||
|
||||
public /*synthesized*/ fun </*0*/ T : kotlin.Any!> A(/*0*/ function: (T!) -> kotlin.Unit): A<T>
|
||||
public /*synthesized*/ fun </*0*/ T : kotlin.Any!> A(/*0*/ function: (T) -> kotlin.Unit): A<T>
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public interface A</*0*/ T : kotlin.Any!> {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package
|
||||
|
||||
public /*synthesized*/ fun B(/*0*/ function: (kotlin.Any!, kotlin.collections.(Mutable)List<(raw) kotlin.Any?>!) -> kotlin.String!): B
|
||||
|
||||
public interface A</*0*/ T : kotlin.Any!> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract fun </*0*/ E : kotlin.CharSequence!> foo(/*0*/ x: T!, /*1*/ y: (kotlin.collections.MutableList<out T!>..kotlin.collections.List<T!>?)): E!
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
package
|
||||
|
||||
public /*synthesized*/ fun </*0*/ T : kotlin.Any!> A(/*0*/ function: (T!, T!) -> kotlin.Unit): A<T>
|
||||
public /*synthesized*/ fun </*0*/ T : kotlin.Any!> A(/*0*/ function: (T, T?) -> kotlin.Unit): A<T>
|
||||
public /*synthesized*/ fun B1(/*0*/ function: (kotlin.String, kotlin.String?) -> kotlin.Unit): B1
|
||||
public /*synthesized*/ fun B2(/*0*/ function: (kotlin.String!, kotlin.String!) -> kotlin.Unit): B2
|
||||
public /*synthesized*/ fun B2(/*0*/ function: (kotlin.String, kotlin.String?) -> kotlin.Unit): B2
|
||||
public /*synthesized*/ fun B3(/*0*/ function: (kotlin.String!, kotlin.String!) -> kotlin.Unit): B3
|
||||
|
||||
public interface A</*0*/ T : kotlin.Any!> {
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
package
|
||||
|
||||
public /*synthesized*/ fun A(/*0*/ function: (kotlin.String!) -> kotlin.Unit): A
|
||||
public /*synthesized*/ fun B(/*0*/ function: (kotlin.String!) -> kotlin.Unit): B
|
||||
public /*synthesized*/ fun A(/*0*/ function: (kotlin.String?) -> kotlin.Unit): A
|
||||
public /*synthesized*/ fun B(/*0*/ function: (kotlin.String) -> kotlin.Unit): B
|
||||
|
||||
public interface A {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
package
|
||||
|
||||
public /*synthesized*/ fun A(/*0*/ function: () -> kotlin.String!): A
|
||||
public /*synthesized*/ fun B(/*0*/ function: () -> kotlin.String!): B
|
||||
public /*synthesized*/ fun A(/*0*/ function: () -> kotlin.String?): A
|
||||
public /*synthesized*/ fun B(/*0*/ function: () -> kotlin.String): B
|
||||
|
||||
public interface A {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
package
|
||||
|
||||
public /*synthesized*/ fun JavaInterface(/*0*/ function: (kotlin.String!, java.lang.Runnable!) -> kotlin.Unit): JavaInterface
|
||||
public /*synthesized*/ fun JavaInterface(/*0*/ function: (kotlin.String, java.lang.Runnable) -> kotlin.Unit): JavaInterface
|
||||
public fun foo(/*0*/ javaInterface: JavaInterface): kotlin.Unit
|
||||
|
||||
public interface JavaInterface {
|
||||
|
||||
@@ -3585,6 +3585,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("javaJavaCycle.kt")
|
||||
public void testJavaJavaCycle() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/cyclicHierarchy/javaJavaCycle.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("javaJavaNested.kt")
|
||||
public void testJavaJavaNested() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/cyclicHierarchy/javaJavaNested.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("javaKotlinJavaCycle.kt")
|
||||
public void testJavaKotlinJavaCycle() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/cyclicHierarchy/javaKotlinJavaCycle.kt");
|
||||
@@ -10476,6 +10488,21 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/j+k/sam")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Sam extends AbstractDiagnosticsTest {
|
||||
public void testAllFilesPresentInSam() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/j+k/sam"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("enhancedSamConstructor.kt")
|
||||
public void testEnhancedSamConstructor() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/sam/enhancedSamConstructor.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/j+k/samByProjectedType")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+2
-8
@@ -21,24 +21,18 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaMethod
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
interface SamConversionResolver {
|
||||
companion object EMPTY : SamConversionResolver {
|
||||
override fun <D : FunctionDescriptor> resolveSamAdapter(original: D) = null
|
||||
override fun resolveSamConstructor(constructorOwner: DeclarationDescriptor, classifier: () -> ClassifierDescriptor?) = null
|
||||
override fun resolveFunctionTypeIfSamInterface(
|
||||
classDescriptor: JavaClassDescriptor, resolveMethod: (JavaMethod) -> FunctionDescriptor
|
||||
): KotlinType? = null
|
||||
override fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): KotlinType? = null
|
||||
}
|
||||
|
||||
fun resolveSamConstructor(constructorOwner: DeclarationDescriptor, classifier: () -> ClassifierDescriptor?): SamConstructorDescriptor?
|
||||
|
||||
fun <D : FunctionDescriptor> resolveSamAdapter(original: D): D?
|
||||
|
||||
fun resolveFunctionTypeIfSamInterface(
|
||||
classDescriptor: JavaClassDescriptor,
|
||||
resolveMethod: (JavaMethod) -> FunctionDescriptor
|
||||
): KotlinType?
|
||||
fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): KotlinType?
|
||||
}
|
||||
|
||||
+1
-3
@@ -107,9 +107,7 @@ class LazyJavaClassDescriptor(
|
||||
override fun getAnnotations() = annotations()
|
||||
|
||||
private val functionTypeForSamInterface = c.storageManager.createNullableLazyValue {
|
||||
c.components.samConversionResolver.resolveFunctionTypeIfSamInterface(this) { method ->
|
||||
unsubstitutedMemberScope.resolveMethodToFunctionDescriptor(method)
|
||||
}
|
||||
c.components.samConversionResolver.resolveFunctionTypeIfSamInterface(this)
|
||||
}
|
||||
|
||||
private val declaredParameters = c.storageManager.createLazyValue {
|
||||
|
||||
Reference in New Issue
Block a user