Make infix modifier diagnostic message more informative (KT-12589)

(cherry picked from commit 2744309)
This commit is contained in:
Yan Zhulanow
2016-06-10 22:45:57 +03:00
parent a434055b55
commit 6752df189d
20 changed files with 94 additions and 70 deletions
@@ -87,7 +87,7 @@ public class JavaMethodDescriptor extends SimpleFunctionDescriptorImpl implement
SimpleFunctionDescriptorImpl descriptor = super.initialize(
receiverParameterType, dispatchReceiverParameter, typeParameters, unsubstitutedValueParameters,
unsubstitutedReturnType, modality, visibility);
setOperator(OperatorChecks.INSTANCE.checkOperator(descriptor).isSuccess());
setOperator(OperatorChecks.INSTANCE.check(descriptor).isSuccess());
return descriptor;
}
@@ -68,11 +68,11 @@ interface Check {
}
sealed class MemberKindCheck(override val description: String) : Check {
object MemberOrExtension : MemberKindCheck("must be a member or an extension") {
object MemberOrExtension : MemberKindCheck("must be a member or an extension function") {
override fun check(functionDescriptor: FunctionDescriptor) =
functionDescriptor.isExtension || functionDescriptor.containingDeclaration is ClassDescriptor
}
object Member : MemberKindCheck("must be a member") {
object Member : MemberKindCheck("must be a member function") {
override fun check(functionDescriptor: FunctionDescriptor) = functionDescriptor.containingDeclaration is ClassDescriptor
}
}
@@ -92,6 +92,13 @@ sealed class ValueParameterCountCheck(override val description: String) : Check
}
}
private object HasDispatchOrExtensionReceiverParameter : Check {
override val description = "must be a member of an extension function"
override fun check(functionDescriptor: FunctionDescriptor): Boolean {
return functionDescriptor.dispatchReceiverParameter != null || functionDescriptor.extensionReceiverParameter != null
}
}
private object NoDefaultAndVarargsCheck : Check {
override val description = "should not have varargs or parameters with default values"
override fun check(functionDescriptor: FunctionDescriptor) =
@@ -120,7 +127,7 @@ sealed class ReturnsCheck(val name: String, val type: KotlinBuiltIns.() -> Kotli
object ReturnsUnit : ReturnsCheck("Unit", { unitType })
}
private class Checks private constructor(
internal class Checks private constructor(
val name: Name?,
val regex: Regex?,
val nameList: Collection<Name>?,
@@ -150,6 +157,8 @@ private class Checks private constructor(
return CheckResult.SuccessCheck
}
constructor(vararg checks: Check, additionalChecks: FunctionDescriptor.() -> String? = { null })
: this(null, null, null, additionalChecks, *checks)
constructor(name: Name, vararg checks: Check, additionalChecks: FunctionDescriptor.() -> String? = { null })
: this(name, null, null, additionalChecks, *checks)
constructor(regex: Regex, vararg checks: Check, additionalChecks: FunctionDescriptor.() -> String? = { null })
@@ -158,10 +167,23 @@ private class Checks private constructor(
: this(null, null, nameList, additionalChecks, *checks)
}
object OperatorChecks {
private inline fun ensure(cond: Boolean, msg: () -> String) = if (!cond) msg() else null
abstract class AbstractModifierChecks {
abstract internal val checks: List<Checks>
inline fun ensure(cond: Boolean, msg: () -> String) = if (!cond) msg() else null
private val CHECKS = listOf(
fun check(functionDescriptor: FunctionDescriptor): CheckResult {
for (check in checks) {
if (!check.isApplicable(functionDescriptor)) continue
return check.checkAll(functionDescriptor)
}
return CheckResult.IllegalFunctionName
}
}
object OperatorChecks : AbstractModifierChecks() {
override val checks = listOf(
Checks(GET, MemberOrExtension, ValueParameterCountCheck.AtLeast(1)),
Checks(SET, MemberOrExtension, ValueParameterCountCheck.AtLeast(2)) {
val lastIsOk = valueParameters.lastOrNull()?.let { !it.hasDefaultValue() && it.varargElementType == null } ?: false
@@ -212,15 +234,11 @@ object OperatorChecks {
"Second parameter should be Continuation<Nothing>"
}
}
fun checkOperator(functionDescriptor: FunctionDescriptor): CheckResult {
for (check in CHECKS) {
if (!check.isApplicable(functionDescriptor)) continue
return check.checkAll(functionDescriptor)
}
return CheckResult.IllegalFunctionName
}
}
fun FunctionDescriptor.isValidOperator() = isOperator && OperatorChecks.checkOperator(this).isSuccess
object InfixChecks : AbstractModifierChecks() {
override val checks = listOf(
Checks(HasDispatchOrExtensionReceiverParameter, SingleValueParameter, NoDefaultAndVarargsCheck))
}
fun FunctionDescriptor.isValidOperator() = isOperator && OperatorChecks.check(this).isSuccess