Implement operator checks for controller's handleResult

This commit is contained in:
Denis Zharkov
2016-05-19 11:45:03 +03:00
parent fcbff72f6f
commit 8f4ee0528e
10 changed files with 135 additions and 31 deletions
@@ -17,25 +17,14 @@
package org.jetbrains.kotlin.coroutines
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.types.KotlinType
@JvmField
val CONTINUATION_INTERFACE_FQ_NAME = FqName("kotlin.coroutines.Continuation")
@JvmField
val HANDLE_RESULT_NAME = Name.identifier("handleResult")
import org.jetbrains.kotlin.util.OperatorNameConventions
/**
* @returns type of first value parameter if function is 'operator handleResult' in coroutine controller
* @returns type of first value parameter if function is 'operator handleResult' in coroutines controller
*/
fun SimpleFunctionDescriptor.getExpectedTypeForCoroutineControllerHandleResult(): KotlinType? {
if (name != HANDLE_RESULT_NAME) return null
if (valueParameters.size != 2) return null
if (!isOperator || name != OperatorNameConventions.COROUTINE_HANDLE_RESULT) return null
if (valueParameters[1].type.constructor.declarationDescriptor?.fqNameUnsafe != CONTINUATION_INTERFACE_FQ_NAME.toUnsafe()) return null
return valueParameters[0].type
return valueParameters.getOrNull(0)?.type
}
@@ -179,7 +179,9 @@ fun getEffectiveExpectedType(parameterDescriptor: ValueParameterDescriptor, argu
val newExpectedLambdaReturnType =
receiverType.memberScope
.getContributedFunctions(HANDLE_RESULT_NAME, KotlinLookupLocation(argument.asElement())).mapNotNull {
.getContributedFunctions(
OperatorNameConventions.COROUTINE_HANDLE_RESULT, KotlinLookupLocation(argument.asElement())
).mapNotNull {
it.getExpectedTypeForCoroutineControllerHandleResult()
}.singleOrNull()
// If no handleResult function found, then expected return type for lambda is Unit
@@ -1,15 +1,15 @@
// !CHECK_TYPE
// !DIAGNOSTICS: -UNUSED_PARAMETER -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -UNUSED_VARIABLE
class IntController {
fun handleResult(x: Int, c: Continuation<Nothing>) { }
operator fun handleResult(x: Int, c: Continuation<Nothing>) { }
}
class GenericController<T> {
fun handleResult(x: T, c: Continuation<Nothing>) { }
operator fun handleResult(x: T, c: Continuation<Nothing>) { }
}
class UnitController {
fun handleResult(x: Unit, c: Continuation<Nothing>) { }
operator fun handleResult(x: Unit, c: Continuation<Nothing>) { }
}
class EmptyController
@@ -18,7 +18,7 @@ public final class EmptyController {
public final class GenericController</*0*/ T> {
public constructor GenericController</*0*/ T>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun handleResult(/*0*/ x: T, /*1*/ c: kotlin.coroutines.Continuation<kotlin.Nothing>): kotlin.Unit
public final operator fun handleResult(/*0*/ x: T, /*1*/ c: kotlin.coroutines.Continuation<kotlin.Nothing>): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -26,7 +26,7 @@ public final class GenericController</*0*/ T> {
public final class IntController {
public constructor IntController()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun handleResult(/*0*/ x: kotlin.Int, /*1*/ c: kotlin.coroutines.Continuation<kotlin.Nothing>): kotlin.Unit
public final operator fun handleResult(/*0*/ x: kotlin.Int, /*1*/ c: kotlin.coroutines.Continuation<kotlin.Nothing>): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -34,7 +34,7 @@ public final class IntController {
public final class UnitController {
public constructor UnitController()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun handleResult(/*0*/ x: kotlin.Unit, /*1*/ c: kotlin.coroutines.Continuation<kotlin.Nothing>): kotlin.Unit
public final operator fun handleResult(/*0*/ x: kotlin.Unit, /*1*/ c: kotlin.coroutines.Continuation<kotlin.Nothing>): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,34 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class A1 {
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun handleResult(x: Int) {
}
}
class A2 {
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun handleResult(x: Int, y: Int) {
}
}
class A3 {
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun handleResult(x: Int, y: Continuation<Any>) {
}
}
class A4 {
operator fun handleResult(x: Int, y: Continuation<Nothing>) {
}
}
class A5 {
// TODO: Allow?
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun handleResult(x: Int, y: Continuation<Nothing>): Int = 1
}
class A6 {
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun <T> handleResult(x: Int, y: Continuation<Nothing>) {
}
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun handleResult(x: String = "", y: Continuation<Nothing>) {}
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun handleResult(x: Double = 1.0, vararg y: Continuation<Nothing>) {}
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun handleResult(x: Double = 1.0, z: Int, y: Continuation<Nothing>) {}
}
@@ -0,0 +1,52 @@
package
public final class A1 {
public constructor A1()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final operator fun handleResult(/*0*/ x: kotlin.Int): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class A2 {
public constructor A2()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final operator fun handleResult(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class A3 {
public constructor A3()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final operator fun handleResult(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.coroutines.Continuation<kotlin.Any>): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class A4 {
public constructor A4()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final operator fun handleResult(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.coroutines.Continuation<kotlin.Nothing>): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class A5 {
public constructor A5()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final operator fun handleResult(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.coroutines.Continuation<kotlin.Nothing>): kotlin.Int
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class A6 {
public constructor A6()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final operator fun handleResult(/*0*/ x: kotlin.Double = ..., /*1*/ vararg y: kotlin.coroutines.Continuation<kotlin.Nothing> /*kotlin.Array<out kotlin.coroutines.Continuation<kotlin.Nothing>>*/): kotlin.Unit
public final operator fun handleResult(/*0*/ x: kotlin.Double = ..., /*1*/ z: kotlin.Int, /*2*/ y: kotlin.coroutines.Continuation<kotlin.Nothing>): kotlin.Unit
public final operator fun </*0*/ T> handleResult(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.coroutines.Continuation<kotlin.Nothing>): kotlin.Unit
public final operator fun handleResult(/*0*/ x: kotlin.String = ..., /*1*/ y: kotlin.coroutines.Continuation<kotlin.Nothing>): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -3878,6 +3878,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/lambdaExpectedType.kt");
doTest(fileName);
}
@TestMetadata("wrongHandleResult.kt")
public void testWrongHandleResult() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/wrongHandleResult.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/diagnostics/tests/cyclicHierarchy")