Implement operator checks for controller's handleResult
This commit is contained in:
@@ -17,25 +17,14 @@
|
|||||||
package org.jetbrains.kotlin.coroutines
|
package org.jetbrains.kotlin.coroutines
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
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
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
@JvmField
|
|
||||||
val CONTINUATION_INTERFACE_FQ_NAME = FqName("kotlin.coroutines.Continuation")
|
|
||||||
|
|
||||||
@JvmField
|
|
||||||
val HANDLE_RESULT_NAME = Name.identifier("handleResult")
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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? {
|
fun SimpleFunctionDescriptor.getExpectedTypeForCoroutineControllerHandleResult(): KotlinType? {
|
||||||
if (name != HANDLE_RESULT_NAME) return null
|
if (!isOperator || name != OperatorNameConventions.COROUTINE_HANDLE_RESULT) return null
|
||||||
if (valueParameters.size != 2) return null
|
|
||||||
|
|
||||||
if (valueParameters[1].type.constructor.declarationDescriptor?.fqNameUnsafe != CONTINUATION_INTERFACE_FQ_NAME.toUnsafe()) return null
|
return valueParameters.getOrNull(0)?.type
|
||||||
|
|
||||||
return valueParameters[0].type
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -179,7 +179,9 @@ fun getEffectiveExpectedType(parameterDescriptor: ValueParameterDescriptor, argu
|
|||||||
|
|
||||||
val newExpectedLambdaReturnType =
|
val newExpectedLambdaReturnType =
|
||||||
receiverType.memberScope
|
receiverType.memberScope
|
||||||
.getContributedFunctions(HANDLE_RESULT_NAME, KotlinLookupLocation(argument.asElement())).mapNotNull {
|
.getContributedFunctions(
|
||||||
|
OperatorNameConventions.COROUTINE_HANDLE_RESULT, KotlinLookupLocation(argument.asElement())
|
||||||
|
).mapNotNull {
|
||||||
it.getExpectedTypeForCoroutineControllerHandleResult()
|
it.getExpectedTypeForCoroutineControllerHandleResult()
|
||||||
}.singleOrNull()
|
}.singleOrNull()
|
||||||
// If no handleResult function found, then expected return type for lambda is Unit
|
// If no handleResult function found, then expected return type for lambda is Unit
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
// !CHECK_TYPE
|
// !CHECK_TYPE
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -UNUSED_VARIABLE
|
// !DIAGNOSTICS: -UNUSED_PARAMETER -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -UNUSED_VARIABLE
|
||||||
class IntController {
|
class IntController {
|
||||||
fun handleResult(x: Int, c: Continuation<Nothing>) { }
|
operator fun handleResult(x: Int, c: Continuation<Nothing>) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
class GenericController<T> {
|
class GenericController<T> {
|
||||||
fun handleResult(x: T, c: Continuation<Nothing>) { }
|
operator fun handleResult(x: T, c: Continuation<Nothing>) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
class UnitController {
|
class UnitController {
|
||||||
fun handleResult(x: Unit, c: Continuation<Nothing>) { }
|
operator fun handleResult(x: Unit, c: Continuation<Nothing>) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
class EmptyController
|
class EmptyController
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public final class EmptyController {
|
|||||||
public final class GenericController</*0*/ T> {
|
public final class GenericController</*0*/ T> {
|
||||||
public constructor GenericController</*0*/ T>()
|
public constructor GenericController</*0*/ T>()
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
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 hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
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 final class IntController {
|
||||||
public constructor IntController()
|
public constructor IntController()
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
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 hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
}
|
}
|
||||||
@@ -34,7 +34,7 @@ public final class IntController {
|
|||||||
public final class UnitController {
|
public final class UnitController {
|
||||||
public constructor UnitController()
|
public constructor UnitController()
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
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 hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
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");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/lambdaExpectedType.kt");
|
||||||
doTest(fileName);
|
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")
|
@TestMetadata("compiler/testData/diagnostics/tests/cyclicHierarchy")
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ public class DescriptorUtils {
|
|||||||
public static final FqName JVM_NAME = new FqName("kotlin.jvm.JvmName");
|
public static final FqName JVM_NAME = new FqName("kotlin.jvm.JvmName");
|
||||||
public static final FqName VOLATILE = new FqName("kotlin.jvm.Volatile");
|
public static final FqName VOLATILE = new FqName("kotlin.jvm.Volatile");
|
||||||
public static final FqName SYNCHRONIZED = new FqName("kotlin.jvm.Synchronized");
|
public static final FqName SYNCHRONIZED = new FqName("kotlin.jvm.Synchronized");
|
||||||
|
public static final FqName CONTINUATION_INTERFACE_FQ_NAME = new FqName("kotlin.coroutines.Continuation");
|
||||||
|
|
||||||
private DescriptorUtils() {
|
private DescriptorUtils() {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,23 +22,20 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
|
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||||
import org.jetbrains.kotlin.util.MemberKindCheck.Member
|
import org.jetbrains.kotlin.util.MemberKindCheck.Member
|
||||||
import org.jetbrains.kotlin.util.MemberKindCheck.MemberOrExtension
|
import org.jetbrains.kotlin.util.MemberKindCheck.MemberOrExtension
|
||||||
import org.jetbrains.kotlin.util.ReturnsCheck.*
|
|
||||||
import org.jetbrains.kotlin.util.ValueParameterCountCheck.NoValueParameters
|
|
||||||
import org.jetbrains.kotlin.util.ValueParameterCountCheck.SingleValueParameter
|
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions.ASSIGNMENT_OPERATIONS
|
import org.jetbrains.kotlin.util.OperatorNameConventions.ASSIGNMENT_OPERATIONS
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions.BINARY_OPERATION_NAMES
|
import org.jetbrains.kotlin.util.OperatorNameConventions.BINARY_OPERATION_NAMES
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions.COMPARE_TO
|
import org.jetbrains.kotlin.util.OperatorNameConventions.COMPARE_TO
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions.COMPONENT_REGEX
|
import org.jetbrains.kotlin.util.OperatorNameConventions.COMPONENT_REGEX
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions.CONTAINS
|
import org.jetbrains.kotlin.util.OperatorNameConventions.CONTAINS
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions.COROUTINE_HANDLE_RESULT
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions.DEC
|
import org.jetbrains.kotlin.util.OperatorNameConventions.DEC
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions.EQUALS
|
import org.jetbrains.kotlin.util.OperatorNameConventions.EQUALS
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions.GET
|
import org.jetbrains.kotlin.util.OperatorNameConventions.GET
|
||||||
@@ -52,6 +49,9 @@ import org.jetbrains.kotlin.util.OperatorNameConventions.RANGE_TO
|
|||||||
import org.jetbrains.kotlin.util.OperatorNameConventions.SET
|
import org.jetbrains.kotlin.util.OperatorNameConventions.SET
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions.SET_VALUE
|
import org.jetbrains.kotlin.util.OperatorNameConventions.SET_VALUE
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions.SIMPLE_UNARY_OPERATION_NAMES
|
import org.jetbrains.kotlin.util.OperatorNameConventions.SIMPLE_UNARY_OPERATION_NAMES
|
||||||
|
import org.jetbrains.kotlin.util.ReturnsCheck.*
|
||||||
|
import org.jetbrains.kotlin.util.ValueParameterCountCheck.NoValueParameters
|
||||||
|
import org.jetbrains.kotlin.util.ValueParameterCountCheck.SingleValueParameter
|
||||||
|
|
||||||
sealed class CheckResult(val isSuccess: Boolean) {
|
sealed class CheckResult(val isSuccess: Boolean) {
|
||||||
class IllegalSignature(val error: String) : CheckResult(false)
|
class IllegalSignature(val error: String) : CheckResult(false)
|
||||||
@@ -85,6 +85,9 @@ sealed class ValueParameterCountCheck(override val description: String) : Check
|
|||||||
class AtLeast(val n: Int) : ValueParameterCountCheck("must have at least $n value parameter" + (if (n > 1) "s" else "")) {
|
class AtLeast(val n: Int) : ValueParameterCountCheck("must have at least $n value parameter" + (if (n > 1) "s" else "")) {
|
||||||
override fun check(functionDescriptor: FunctionDescriptor) = functionDescriptor.valueParameters.size >= n
|
override fun check(functionDescriptor: FunctionDescriptor) = functionDescriptor.valueParameters.size >= n
|
||||||
}
|
}
|
||||||
|
class Equals(val n: Int) : ValueParameterCountCheck("must have exactly $n value parameters") {
|
||||||
|
override fun check(functionDescriptor: FunctionDescriptor) = functionDescriptor.valueParameters.size == n
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private object NoDefaultAndVarargsCheck : Check {
|
private object NoDefaultAndVarargsCheck : Check {
|
||||||
@@ -93,6 +96,11 @@ private object NoDefaultAndVarargsCheck : Check {
|
|||||||
functionDescriptor.valueParameters.all { !it.hasDefaultValue() && it.varargElementType == null }
|
functionDescriptor.valueParameters.all { !it.hasDefaultValue() && it.varargElementType == null }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private object NoTypeParametersCheck : Check {
|
||||||
|
override val description = "should not have type parameters"
|
||||||
|
override fun check(functionDescriptor: FunctionDescriptor) = functionDescriptor.typeParameters.isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
private object IsKPropertyCheck : Check {
|
private object IsKPropertyCheck : Check {
|
||||||
override val description = "second parameter must have a KProperty type or its supertype"
|
override val description = "second parameter must have a KProperty type or its supertype"
|
||||||
override fun check(functionDescriptor: FunctionDescriptor): Boolean {
|
override fun check(functionDescriptor: FunctionDescriptor): Boolean {
|
||||||
@@ -179,7 +187,18 @@ object OperatorChecks {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Checks(ASSIGNMENT_OPERATIONS, MemberOrExtension, ReturnsUnit, SingleValueParameter, NoDefaultAndVarargsCheck),
|
Checks(ASSIGNMENT_OPERATIONS, MemberOrExtension, ReturnsUnit, SingleValueParameter, NoDefaultAndVarargsCheck),
|
||||||
Checks(COMPONENT_REGEX, MemberOrExtension, NoValueParameters)
|
Checks(COMPONENT_REGEX, MemberOrExtension, NoValueParameters),
|
||||||
|
Checks(
|
||||||
|
COROUTINE_HANDLE_RESULT, Member, ValueParameterCountCheck.Equals(2), ReturnsUnit,
|
||||||
|
NoDefaultAndVarargsCheck, NoTypeParametersCheck) {
|
||||||
|
val secondParameter = valueParameters[1]
|
||||||
|
ensure(
|
||||||
|
secondParameter.type.constructor.declarationDescriptor?.fqNameUnsafe == DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME.toUnsafe()
|
||||||
|
&& secondParameter.type.arguments[0].type.isNothing()
|
||||||
|
) {
|
||||||
|
"Second parameter should be Continuation<Nothing>"
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
fun checkOperator(functionDescriptor: FunctionDescriptor): CheckResult {
|
fun checkOperator(functionDescriptor: FunctionDescriptor): CheckResult {
|
||||||
@@ -192,4 +211,4 @@ object OperatorChecks {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun FunctionDescriptor.isValidOperator() = isOperator && OperatorChecks.checkOperator(this).isSuccess
|
fun FunctionDescriptor.isValidOperator() = isOperator && OperatorChecks.checkOperator(this).isSuccess
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ object OperatorNameConventions {
|
|||||||
@JvmField val MOD_ASSIGN = Name.identifier("modAssign")
|
@JvmField val MOD_ASSIGN = Name.identifier("modAssign")
|
||||||
@JvmField val PLUS_ASSIGN = Name.identifier("plusAssign")
|
@JvmField val PLUS_ASSIGN = Name.identifier("plusAssign")
|
||||||
@JvmField val MINUS_ASSIGN = Name.identifier("minusAssign")
|
@JvmField val MINUS_ASSIGN = Name.identifier("minusAssign")
|
||||||
|
@JvmField val COROUTINE_HANDLE_RESULT = Name.identifier("handleResult")
|
||||||
|
|
||||||
// If you add new unary, binary or assignment operators, add it to OperatorConventions as well
|
// If you add new unary, binary or assignment operators, add it to OperatorConventions as well
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user