Make infix modifier diagnostic message more informative (KT-12589)
(cherry picked from commit 2744309)
This commit is contained in:
@@ -621,7 +621,7 @@ public interface Errors {
|
|||||||
DiagnosticFactory1<PsiElement, String> INVALID_CHARACTERS = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<PsiElement, String> INVALID_CHARACTERS = DiagnosticFactory1.create(ERROR);
|
||||||
|
|
||||||
DiagnosticFactory1<PsiElement, String> INAPPLICABLE_OPERATOR_MODIFIER = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<PsiElement, String> INAPPLICABLE_OPERATOR_MODIFIER = DiagnosticFactory1.create(ERROR);
|
||||||
DiagnosticFactory0<PsiElement> INAPPLICABLE_INFIX_MODIFIER = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory1<PsiElement, String> INAPPLICABLE_INFIX_MODIFIER = DiagnosticFactory1.create(ERROR);
|
||||||
|
|
||||||
DiagnosticFactory2<PsiElement, FunctionDescriptor, String> OPERATOR_MODIFIER_REQUIRED = DiagnosticFactory2.create(ERROR);
|
DiagnosticFactory2<PsiElement, FunctionDescriptor, String> OPERATOR_MODIFIER_REQUIRED = DiagnosticFactory2.create(ERROR);
|
||||||
DiagnosticFactory2<KtOperationReferenceExpression, FunctionDescriptor, String> INFIX_MODIFIER_REQUIRED = DiagnosticFactory2.create(ERROR);
|
DiagnosticFactory2<KtOperationReferenceExpression, FunctionDescriptor, String> INFIX_MODIFIER_REQUIRED = DiagnosticFactory2.create(ERROR);
|
||||||
|
|||||||
+1
-1
@@ -379,7 +379,7 @@ public class DefaultErrorMessages {
|
|||||||
MAP.put(INVALID_CHARACTERS, "Name {0}", STRING);
|
MAP.put(INVALID_CHARACTERS, "Name {0}", STRING);
|
||||||
|
|
||||||
MAP.put(INAPPLICABLE_OPERATOR_MODIFIER, "''operator'' modifier is inapplicable on this function: {0}", STRING);
|
MAP.put(INAPPLICABLE_OPERATOR_MODIFIER, "''operator'' modifier is inapplicable on this function: {0}", STRING);
|
||||||
MAP.put(INAPPLICABLE_INFIX_MODIFIER, "'infix' modifier is inapplicable on this function");
|
MAP.put(INAPPLICABLE_INFIX_MODIFIER, "'infix' modifier is inapplicable on this function: {0}", STRING);
|
||||||
|
|
||||||
MAP.put(OPERATOR_MODIFIER_REQUIRED, "''operator'' modifier is required on ''{0}'' in ''{1}''", NAME, STRING);
|
MAP.put(OPERATOR_MODIFIER_REQUIRED, "''operator'' modifier is required on ''{0}'' in ''{1}''", NAME, STRING);
|
||||||
MAP.put(INFIX_MODIFIER_REQUIRED, "''infix'' modifier is required on ''{0}'' in ''{1}''", NAME, STRING);
|
MAP.put(INFIX_MODIFIER_REQUIRED, "''infix'' modifier is required on ''{0}'' in ''{1}''", NAME, STRING);
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
|||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
|
import org.jetbrains.kotlin.util.CheckResult
|
||||||
|
import org.jetbrains.kotlin.util.InfixChecks
|
||||||
|
|
||||||
class InfixModifierChecker : SimpleDeclarationChecker {
|
class InfixModifierChecker : SimpleDeclarationChecker {
|
||||||
|
|
||||||
@@ -36,17 +37,9 @@ class InfixModifierChecker : SimpleDeclarationChecker {
|
|||||||
if (!functionDescriptor.isInfix) return
|
if (!functionDescriptor.isInfix) return
|
||||||
val modifier = declaration.modifierList?.getModifier(KtTokens.INFIX_KEYWORD) ?: return
|
val modifier = declaration.modifierList?.getModifier(KtTokens.INFIX_KEYWORD) ?: return
|
||||||
|
|
||||||
if (!isApplicable(functionDescriptor)) {
|
val checkResult = InfixChecks.check(functionDescriptor)
|
||||||
diagnosticHolder.report(Errors.INAPPLICABLE_INFIX_MODIFIER.on(modifier))
|
if (checkResult !is CheckResult.IllegalSignature) return
|
||||||
}
|
|
||||||
|
diagnosticHolder.report(Errors.INAPPLICABLE_INFIX_MODIFIER.on(modifier, checkResult.error))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isApplicable(descriptor: FunctionDescriptor): Boolean {
|
|
||||||
if (descriptor.dispatchReceiverParameter == null && descriptor.extensionReceiverParameter == null) return false
|
|
||||||
if (descriptor.valueParameters.size != 1) return false
|
|
||||||
|
|
||||||
val singleParameter = descriptor.valueParameters.first()
|
|
||||||
return !singleParameter.hasDefaultValue() && singleParameter.varargElementType == null
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ object OperatorModifierChecker {
|
|||||||
if (!functionDescriptor.isOperator) return
|
if (!functionDescriptor.isOperator) return
|
||||||
val modifier = declaration.modifierList?.getModifier(KtTokens.OPERATOR_KEYWORD) ?: return
|
val modifier = declaration.modifierList?.getModifier(KtTokens.OPERATOR_KEYWORD) ?: return
|
||||||
|
|
||||||
val checkResult = OperatorChecks.checkOperator(functionDescriptor)
|
val checkResult = OperatorChecks.check(functionDescriptor)
|
||||||
if (checkResult.isSuccess) {
|
if (checkResult.isSuccess) {
|
||||||
if (functionDescriptor.name in COROUTINE_OPERATOR_NAMES
|
if (functionDescriptor.name in COROUTINE_OPERATOR_NAMES
|
||||||
&& !languageFeatureSettings.supportsFeature(LanguageFeature.Coroutines)) {
|
&& !languageFeatureSettings.supportsFeature(LanguageFeature.Coroutines)) {
|
||||||
|
|||||||
@@ -3,20 +3,25 @@
|
|||||||
class Pair<A, B>(val a: A, val b: B)
|
class Pair<A, B>(val a: A, val b: B)
|
||||||
infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)
|
infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)
|
||||||
|
|
||||||
infix fun String.o1(o: String) = o
|
// OK
|
||||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix<!> fun String.o2(o: String, o2: String? = null) = o
|
infix fun String.ok1(o: String) {}
|
||||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix<!> fun String.o3(o: String = "", o2: String? = null) = o
|
class OkTest {
|
||||||
|
infix fun ok2(o: String) {}
|
||||||
|
infix fun String.ok3(o: String) {}
|
||||||
|
}
|
||||||
|
|
||||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix<!> fun w1() {}
|
// Errors
|
||||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix<!> fun w2(s: String) {}
|
<!INAPPLICABLE_INFIX_MODIFIER(must have a single value parameter)!>infix<!> fun String.e1(o: String, o2: String? = null) = o
|
||||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix<!> fun String.w3() {}
|
<!INAPPLICABLE_INFIX_MODIFIER(must have a single value parameter)!>infix<!> fun String.e2(o: String = "", o2: String? = null) = o
|
||||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix<!> fun String.w4(a: Int, b: Int) {}
|
|
||||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix<!> fun w5(a: Int, b: Int) {}
|
<!INAPPLICABLE_INFIX_MODIFIER(must be a member of an extension function)!>infix<!> fun e3() {}
|
||||||
|
<!INAPPLICABLE_INFIX_MODIFIER(must be a member of an extension function)!>infix<!> fun e4(s: String) {}
|
||||||
|
<!INAPPLICABLE_INFIX_MODIFIER(must have a single value parameter)!>infix<!> fun String.e5() {}
|
||||||
|
<!INAPPLICABLE_INFIX_MODIFIER(must have a single value parameter)!>infix<!> fun String.e6(a: Int, b: Int) {}
|
||||||
|
<!INAPPLICABLE_INFIX_MODIFIER(must be a member of an extension function)!>infix<!> fun e7(a: Int, b: Int) {}
|
||||||
|
|
||||||
class Example {
|
class Example {
|
||||||
infix fun c1(s: String) {}
|
<!INAPPLICABLE_INFIX_MODIFIER(must have a single value parameter)!>infix<!> fun e8(s: String, a: Int = 0) {}
|
||||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix<!> fun c2(s: String, a: Int = 0) {}
|
<!INAPPLICABLE_INFIX_MODIFIER(must have a single value parameter)!>infix<!> fun e9(s: String, a: Int) {}
|
||||||
|
<!INAPPLICABLE_INFIX_MODIFIER(must have a single value parameter)!>infix<!> fun e10() {}
|
||||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix<!> fun cw1(s: String, a: Int) {}
|
|
||||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix<!> fun sw2() {}
|
|
||||||
}
|
}
|
||||||
@@ -1,26 +1,34 @@
|
|||||||
package
|
package
|
||||||
|
|
||||||
public infix fun w1(): kotlin.Unit
|
public infix fun e3(): kotlin.Unit
|
||||||
public infix fun w2(/*0*/ s: kotlin.String): kotlin.Unit
|
public infix fun e4(/*0*/ s: kotlin.String): kotlin.Unit
|
||||||
public infix fun w5(/*0*/ a: kotlin.Int, /*1*/ b: kotlin.Int): kotlin.Unit
|
public infix fun e7(/*0*/ a: kotlin.Int, /*1*/ b: kotlin.Int): kotlin.Unit
|
||||||
public infix fun kotlin.String.o1(/*0*/ o: kotlin.String): kotlin.String
|
public infix fun kotlin.String.e1(/*0*/ o: kotlin.String, /*1*/ o2: kotlin.String? = ...): kotlin.String
|
||||||
public infix fun kotlin.String.o2(/*0*/ o: kotlin.String, /*1*/ o2: kotlin.String? = ...): kotlin.String
|
public infix fun kotlin.String.e2(/*0*/ o: kotlin.String = ..., /*1*/ o2: kotlin.String? = ...): kotlin.String
|
||||||
public infix fun kotlin.String.o3(/*0*/ o: kotlin.String = ..., /*1*/ o2: kotlin.String? = ...): kotlin.String
|
public infix fun kotlin.String.e5(): kotlin.Unit
|
||||||
|
public infix fun kotlin.String.e6(/*0*/ a: kotlin.Int, /*1*/ b: kotlin.Int): kotlin.Unit
|
||||||
|
public infix fun kotlin.String.ok1(/*0*/ o: kotlin.String): kotlin.Unit
|
||||||
public infix fun </*0*/ A, /*1*/ B> A.to(/*0*/ that: B): Pair<A, B>
|
public infix fun </*0*/ A, /*1*/ B> A.to(/*0*/ that: B): Pair<A, B>
|
||||||
public infix fun kotlin.String.w3(): kotlin.Unit
|
|
||||||
public infix fun kotlin.String.w4(/*0*/ a: kotlin.Int, /*1*/ b: kotlin.Int): kotlin.Unit
|
|
||||||
|
|
||||||
public final class Example {
|
public final class Example {
|
||||||
public constructor Example()
|
public constructor Example()
|
||||||
public final infix fun c1(/*0*/ s: kotlin.String): kotlin.Unit
|
public final infix fun e10(): kotlin.Unit
|
||||||
public final infix fun c2(/*0*/ s: kotlin.String, /*1*/ a: kotlin.Int = ...): kotlin.Unit
|
public final infix fun e8(/*0*/ s: kotlin.String, /*1*/ a: kotlin.Int = ...): kotlin.Unit
|
||||||
public final infix fun cw1(/*0*/ s: kotlin.String, /*1*/ a: kotlin.Int): kotlin.Unit
|
public final infix fun e9(/*0*/ s: kotlin.String, /*1*/ a: kotlin.Int): kotlin.Unit
|
||||||
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 open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public final infix fun sw2(): kotlin.Unit
|
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class OkTest {
|
||||||
|
public constructor OkTest()
|
||||||
|
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 final infix fun ok2(/*0*/ o: kotlin.String): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
public final infix fun kotlin.String.ok3(/*0*/ o: kotlin.String): kotlin.Unit
|
||||||
|
}
|
||||||
|
|
||||||
public final class Pair</*0*/ A, /*1*/ B> {
|
public final class Pair</*0*/ A, /*1*/ B> {
|
||||||
public constructor Pair</*0*/ A, /*1*/ B>(/*0*/ a: A, /*1*/ b: B)
|
public constructor Pair</*0*/ A, /*1*/ B>(/*0*/ a: A, /*1*/ b: B)
|
||||||
public final val a: A
|
public final val a: A
|
||||||
|
|||||||
+1
-1
@@ -87,7 +87,7 @@ public class JavaMethodDescriptor extends SimpleFunctionDescriptorImpl implement
|
|||||||
SimpleFunctionDescriptorImpl descriptor = super.initialize(
|
SimpleFunctionDescriptorImpl descriptor = super.initialize(
|
||||||
receiverParameterType, dispatchReceiverParameter, typeParameters, unsubstitutedValueParameters,
|
receiverParameterType, dispatchReceiverParameter, typeParameters, unsubstitutedValueParameters,
|
||||||
unsubstitutedReturnType, modality, visibility);
|
unsubstitutedReturnType, modality, visibility);
|
||||||
setOperator(OperatorChecks.INSTANCE.checkOperator(descriptor).isSuccess());
|
setOperator(OperatorChecks.INSTANCE.check(descriptor).isSuccess());
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+34
-16
@@ -68,11 +68,11 @@ interface Check {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sealed class MemberKindCheck(override val description: String) : 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) =
|
override fun check(functionDescriptor: FunctionDescriptor) =
|
||||||
functionDescriptor.isExtension || functionDescriptor.containingDeclaration is ClassDescriptor
|
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
|
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 {
|
private object NoDefaultAndVarargsCheck : Check {
|
||||||
override val description = "should not have varargs or parameters with default values"
|
override val description = "should not have varargs or parameters with default values"
|
||||||
override fun check(functionDescriptor: FunctionDescriptor) =
|
override fun check(functionDescriptor: FunctionDescriptor) =
|
||||||
@@ -120,7 +127,7 @@ sealed class ReturnsCheck(val name: String, val type: KotlinBuiltIns.() -> Kotli
|
|||||||
object ReturnsUnit : ReturnsCheck("Unit", { unitType })
|
object ReturnsUnit : ReturnsCheck("Unit", { unitType })
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Checks private constructor(
|
internal class Checks private constructor(
|
||||||
val name: Name?,
|
val name: Name?,
|
||||||
val regex: Regex?,
|
val regex: Regex?,
|
||||||
val nameList: Collection<Name>?,
|
val nameList: Collection<Name>?,
|
||||||
@@ -150,6 +157,8 @@ private class Checks private constructor(
|
|||||||
return CheckResult.SuccessCheck
|
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 })
|
constructor(name: Name, vararg checks: Check, additionalChecks: FunctionDescriptor.() -> String? = { null })
|
||||||
: this(name, null, null, additionalChecks, *checks)
|
: this(name, null, null, additionalChecks, *checks)
|
||||||
constructor(regex: Regex, vararg checks: Check, additionalChecks: FunctionDescriptor.() -> String? = { null })
|
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)
|
: this(null, null, nameList, additionalChecks, *checks)
|
||||||
}
|
}
|
||||||
|
|
||||||
object OperatorChecks {
|
abstract class AbstractModifierChecks {
|
||||||
private inline fun ensure(cond: Boolean, msg: () -> String) = if (!cond) msg() else null
|
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(GET, MemberOrExtension, ValueParameterCountCheck.AtLeast(1)),
|
||||||
Checks(SET, MemberOrExtension, ValueParameterCountCheck.AtLeast(2)) {
|
Checks(SET, MemberOrExtension, ValueParameterCountCheck.AtLeast(2)) {
|
||||||
val lastIsOk = valueParameters.lastOrNull()?.let { !it.hasDefaultValue() && it.varargElementType == null } ?: false
|
val lastIsOk = valueParameters.lastOrNull()?.let { !it.hasDefaultValue() && it.varargElementType == null } ?: false
|
||||||
@@ -212,15 +234,11 @@ object OperatorChecks {
|
|||||||
"Second parameter should be Continuation<Nothing>"
|
"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
|
||||||
@@ -28,7 +28,7 @@ class AddOperatorModifierIntention : SelfTargetingRangeIntention<KtNamedFunction
|
|||||||
override fun applicabilityRange(element: KtNamedFunction): TextRange? {
|
override fun applicabilityRange(element: KtNamedFunction): TextRange? {
|
||||||
val nameIdentifier = element.nameIdentifier ?: return null
|
val nameIdentifier = element.nameIdentifier ?: return null
|
||||||
val functionDescriptor = element.resolveToDescriptor() as? FunctionDescriptor ?: return null
|
val functionDescriptor = element.resolveToDescriptor() as? FunctionDescriptor ?: return null
|
||||||
if (functionDescriptor.isOperator || !OperatorChecks.checkOperator(functionDescriptor).isSuccess) return null
|
if (functionDescriptor.isOperator || !OperatorChecks.check(functionDescriptor).isSuccess) return null
|
||||||
return nameIdentifier.textRange
|
return nameIdentifier.textRange
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -51,7 +51,7 @@ class ReplaceContainsIntention : SelfTargetingRangeIntention<KtDotQualifiedExpre
|
|||||||
if (!element.isReceiverExpressionWithValue()) return null
|
if (!element.isReceiverExpressionWithValue()) return null
|
||||||
|
|
||||||
val functionDescriptor = getFunctionDescriptor(element) ?: return null
|
val functionDescriptor = getFunctionDescriptor(element) ?: return null
|
||||||
if (!functionDescriptor.isOperator || !OperatorChecks.checkOperator(functionDescriptor).isSuccess) return null
|
if (!functionDescriptor.isOperator || !OperatorChecks.check(functionDescriptor).isSuccess) return null
|
||||||
|
|
||||||
return element.callExpression!!.calleeExpression!!.textRange
|
return element.callExpression!!.calleeExpression!!.textRange
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
// IS_APPLICABLE: false
|
// IS_APPLICABLE: false
|
||||||
// ERROR: 'operator' modifier is inapplicable on this function: must be a member or an extension
|
// ERROR: 'operator' modifier is inapplicable on this function: must be a member or an extension function
|
||||||
|
|
||||||
package p
|
package p
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// IS_APPLICABLE: false
|
// IS_APPLICABLE: false
|
||||||
// ERROR: 'infix' modifier is inapplicable on this function
|
// ERROR: infix modifier is inapplicable on this function: must have a single value parameter
|
||||||
interface Foo {
|
interface Foo {
|
||||||
infix fun foo(a: Int, b: Int)
|
infix fun foo(a: Int, b: Int)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
// IS_APPLICABLE: false
|
// IS_APPLICABLE: false
|
||||||
// ERROR: 'infix' modifier is inapplicable on this function
|
// ERROR: infix modifier is inapplicable on this function: must have a single value parameter
|
||||||
fun foo(x: Foo) {
|
fun foo(x: Foo) {
|
||||||
x.<caret>foo(bar = x)
|
x.<caret>foo(bar = x)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// IS_APPLICABLE: false
|
// IS_APPLICABLE: false
|
||||||
// ERROR: 'infix' modifier is inapplicable on this function
|
// ERROR: infix modifier is inapplicable on this function: must be a member of an extension function
|
||||||
infix fun id(s: String) = s
|
infix fun id(s: String) = s
|
||||||
val x = <caret>id("0").get(0)
|
val x = <caret>id("0").get(0)
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
// IS_APPLICABLE: false
|
// IS_APPLICABLE: false
|
||||||
// ERROR: 'infix' modifier is inapplicable on this function
|
// ERROR: infix modifier is inapplicable on this function: must be a member of an extension function
|
||||||
package ppp
|
package ppp
|
||||||
|
|
||||||
infix fun foo(p: String){}
|
infix fun foo(p: String){}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// IS_APPLICABLE: false
|
// IS_APPLICABLE: false
|
||||||
// ERROR: 'infix' modifier is inapplicable on this function
|
// ERROR: infix modifier is inapplicable on this function: must have a single value parameter
|
||||||
|
|
||||||
class Foo {
|
class Foo {
|
||||||
infix fun foo(x: Int = 0, y: Int = 0) {
|
infix fun foo(x: Int = 0, y: Int = 0) {
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
// IS_APPLICABLE: false
|
// IS_APPLICABLE: false
|
||||||
// ERROR: 'infix' modifier is inapplicable on this function
|
// ERROR: infix modifier is inapplicable on this function: must have a single value parameter
|
||||||
|
|
||||||
fun foo(x: Foo) {
|
fun foo(x: Foo) {
|
||||||
x.<caret>foo(1) { it * 2 }
|
x.<caret>foo(1) { it * 2 }
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// IS_APPLICABLE: false
|
// IS_APPLICABLE: false
|
||||||
// ERROR: 'infix' modifier is inapplicable on this function
|
// ERROR: infix modifier is inapplicable on this function: must be a member of an extension function
|
||||||
|
|
||||||
package demo
|
package demo
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// "Replace with 'newFun(p, this)'" "true"
|
// "Replace with 'newFun(p, this)'" "true"
|
||||||
// ERROR: 'infix' modifier is inapplicable on this function
|
// ERROR: infix modifier is inapplicable on this function: must be a member of an extension function
|
||||||
|
|
||||||
@Deprecated("", ReplaceWith("newFun(p, this)"))
|
@Deprecated("", ReplaceWith("newFun(p, this)"))
|
||||||
infix fun String.oldFun(p: Int) {
|
infix fun String.oldFun(p: Int) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// "Replace with 'newFun(p, this)'" "true"
|
// "Replace with 'newFun(p, this)'" "true"
|
||||||
// ERROR: 'infix' modifier is inapplicable on this function
|
// ERROR: infix modifier is inapplicable on this function: must be a member of an extension function
|
||||||
|
|
||||||
@Deprecated("", ReplaceWith("newFun(p, this)"))
|
@Deprecated("", ReplaceWith("newFun(p, this)"))
|
||||||
infix fun String.oldFun(p: Int) {
|
infix fun String.oldFun(p: Int) {
|
||||||
|
|||||||
Reference in New Issue
Block a user