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:
Denis Zharkov
2016-03-07 17:49:03 +03:00
parent b8b48c5f98
commit 151e55b2fa
22 changed files with 234 additions and 258 deletions
@@ -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
}
}
@@ -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
@@ -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,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!> {
@@ -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!
@@ -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!> {
@@ -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
@@ -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
@@ -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)
@@ -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?
}
@@ -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 {