Fixed nullability for return and parameter types in SAM-adapters

This commit is contained in:
Valentin Kipyatkov
2015-07-29 14:37:17 +03:00
parent 321bf40b65
commit cb9ef9e1f0
12 changed files with 143 additions and 18 deletions
@@ -100,14 +100,14 @@ public class SingleAbstractMethodUtils {
if (substitute == null) return null;
JetType fixedProjections = fixProjections(substitute);
if (fixedProjections == null) return null;
JetType type = fixProjections(substitute);
if (type == null) return null;
if (JvmPackage.getPLATFORM_TYPES() && !isSamConstructor) {
return LazyJavaTypeResolver.FlexibleJavaClassifierTypeCapabilities.create(fixedProjections, TypeUtils.makeNullable(fixedProjections));
if (JvmPackage.getPLATFORM_TYPES() && !isSamConstructor && TypesPackage.isNullabilityFlexible(samType)) {
return LazyJavaTypeResolver.FlexibleJavaClassifierTypeCapabilities.create(type, TypeUtils.makeNullable(type));
}
return TypeUtils.makeNullableAsSpecified(fixedProjections, !isSamConstructor && samType.isMarkedNullable());
return TypeUtils.makeNullableAsSpecified(type, !isSamConstructor && samType.isMarkedNullable());
}
}
return null;
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils
import org.jetbrains.kotlin.load.java.typeEnhacement.enhanceSignature
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
@@ -46,8 +47,10 @@ class SamAdapterFunctionsScope(storageManager: StorageManager) : JetScope by Jet
if (function.visibility == Visibilities.PRIVATE || function.visibility == Visibilities.PRIVATE_TO_THIS || function.visibility == Visibilities.INVISIBLE_FAKE) return null
if (!function.hasJavaOriginInHierarchy()) return null //TODO: should we go into base at all?
if (!SingleAbstractMethodUtils.isSamAdapterNecessary(function)) return null
val returnType = function.returnType ?: return null
return MyFunctionDescriptor(function, returnType)
if (function.returnType == null) return null
//TODO: it's a temporary hack while original returns a function with platform types
val enhancedFunction = function.enhanceSignature()
return MyFunctionDescriptor(enhancedFunction)
}
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<JetType>, name: Name): Collection<FunctionDescriptor> {
@@ -71,8 +74,7 @@ class SamAdapterFunctionsScope(storageManager: StorageManager) : JetScope by Jet
}
private class MyFunctionDescriptor(
override val originalFunction: FunctionDescriptor,
originalReturnType: JetType
override val originalFunction: FunctionDescriptor
) : SamAdapterExtensionFunctionDescriptor, SimpleFunctionDescriptorImpl(
DescriptorUtils.getContainingModule(originalFunction),
null,
@@ -94,7 +96,7 @@ class SamAdapterFunctionsScope(storageManager: StorageManager) : JetScope by Jet
val typeParameters = ArrayList<TypeParameterDescriptor>(typeParamsSum.size())
val typeSubstitutor = DescriptorSubstitutor.substituteTypeParameters(typeParamsSum, TypeSubstitution.EMPTY, this, typeParameters)
val returnType = typeSubstitutor.safeSubstitute(originalReturnType, Variance.OUT_VARIANCE)
val returnType = typeSubstitutor.safeSubstitute(originalFunction.returnType!!, Variance.OUT_VARIANCE)
val receiverType = typeSubstitutor.safeSubstitute(ownerClass.defaultType, Variance.INVARIANT)
val valueParameters = SingleAbstractMethodUtils.createValueParametersForSamAdapter(originalFunction, this, typeSubstitutor)
initialize(receiverType, null, typeParameters, valueParameters, returnType, Modality.FINAL, Visibilities.PUBLIC)
@@ -0,0 +1,13 @@
// FILE: KotlinFile.kt
fun foo(javaClass: JavaClass) {
javaClass.getSomething()<!UNSAFE_CALL!>.<!>length()
javaClass.something<!UNSAFE_CALL!>.<!>length()
}
// FILE: JavaClass.java
import org.jetbrains.annotations.*;
public class JavaClass {
@Nullable
public String getSomething() { return null; }
}
@@ -0,0 +1,11 @@
package
internal fun foo(/*0*/ javaClass: JavaClass): kotlin.Unit
public open class JavaClass {
public constructor JavaClass()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
org.jetbrains.annotations.Nullable() public open fun getSomething(): kotlin.String?
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,12 @@
// FILE: KotlinFile.kt
fun foo(javaInterface: JavaInterface) {
javaInterface.doIt(<!NULL_FOR_NONNULL_TYPE!>null<!>) <!TYPE_MISMATCH!>{ }<!>
javaInterface.doIt("", <!NULL_FOR_NONNULL_TYPE!>null<!>)
}
// FILE: JavaInterface.java
import org.jetbrains.annotations.*;
public interface JavaInterface {
void doIt(@NotNull String s, @NotNull Runnable runnable);
}
@@ -0,0 +1,11 @@
package
public /*synthesized*/ fun JavaInterface(/*0*/ function: (kotlin.String!, java.lang.Runnable!) -> kotlin.Unit): JavaInterface
internal fun foo(/*0*/ javaInterface: JavaInterface): kotlin.Unit
public interface JavaInterface {
public abstract fun doIt(/*0*/ org.jetbrains.annotations.NotNull() s: kotlin.String, /*1*/ org.jetbrains.annotations.NotNull() runnable: java.lang.Runnable): kotlin.Unit
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
}
@@ -0,0 +1,10 @@
// FILE: KotlinFile.kt
fun foo(javaInterface: JavaInterface) {
javaInterface.doIt(null, null) { }
javaInterface.doIt("", { }, null)
}
// FILE: JavaInterface.java
public interface JavaInterface {
void doIt(String s, Runnable runnable1, Runnable runnable2);
}
@@ -0,0 +1,11 @@
package
public /*synthesized*/ fun JavaInterface(/*0*/ function: (kotlin.String!, java.lang.Runnable!, java.lang.Runnable!) -> kotlin.Unit): JavaInterface
internal fun foo(/*0*/ javaInterface: JavaInterface): kotlin.Unit
public interface JavaInterface {
public abstract fun doIt(/*0*/ s: kotlin.String!, /*1*/ runnable1: java.lang.Runnable!, /*2*/ runnable2: java.lang.Runnable!): kotlin.Unit
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
}
@@ -0,0 +1,19 @@
// FILE: KotlinFile.kt
fun foo(javaInterface: JavaInterface) {
val value: String?
value = javaInterface.compute { "" }
value<!UNSAFE_CALL!>.<!>length()
}
// FILE: JavaInterface.java
import org.jetbrains.annotations.*;
public interface JavaInterface {
@Nullable
<T> String compute(@NotNull Provider<T> provider);
}
// FILE: Provider.java
public interface Provider<T> {
public T compute();
}
@@ -0,0 +1,18 @@
package
public /*synthesized*/ fun </*0*/ T : kotlin.Any!> Provider(/*0*/ function: () -> T!): Provider<T>
internal fun foo(/*0*/ javaInterface: JavaInterface): kotlin.Unit
public interface JavaInterface {
org.jetbrains.annotations.Nullable() public abstract fun </*0*/ T : kotlin.Any!> compute(/*0*/ org.jetbrains.annotations.NotNull() provider: Provider<T!>): kotlin.String?
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 interface Provider</*0*/ T : kotlin.Any!> {
public abstract fun compute(): T!
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
}
@@ -14384,6 +14384,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("TypeAnnotation.kt")
public void testTypeAnnotation() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/TypeAnnotation.kt");
doTest(fileName);
}
@TestMetadata("TypeParameterReceiver.kt")
public void testTypeParameterReceiver() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/TypeParameterReceiver.kt");
@@ -14429,6 +14435,24 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("ParameterTypeAnnotation.kt")
public void testParameterTypeAnnotation() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/ParameterTypeAnnotation.kt");
doTest(fileName);
}
@TestMetadata("PassNull.kt")
public void testPassNull() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/PassNull.kt");
doTest(fileName);
}
@TestMetadata("ReturnTypeAnnotation.kt")
public void testReturnTypeAnnotation() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/ReturnTypeAnnotation.kt");
doTest(fileName);
}
@TestMetadata("Simple.kt")
public void testSimple() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/Simple.kt");
@@ -16,23 +16,17 @@
package org.jetbrains.kotlin.load.java.typeEnhacement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.load.java.typeEnhacement.computeIndexedQualifiersForOverride
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
import org.jetbrains.kotlin.types.JetType
public fun <D : CallableMemberDescriptor> enhanceSignatures(platformSignatures: Collection<D>): Collection<D> {
return platformSignatures.map {
it.enhance()
it.enhanceSignature()
}
}
private fun <D : CallableMemberDescriptor> D.enhance(): D {
public fun <D : CallableMemberDescriptor> D.enhanceSignature(): D {
// TODO type parameters
// TODO use new type parameters while enhancing other types
// TODO Propagation into generic type arguments