diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/infixFunctions.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/infixFunctions.kt index 8a9f51dffe1..f56d21199ee 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/infixFunctions.kt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/infixFunctions.kt @@ -1,10 +1,10 @@ infix fun Int.good(x: Int) {} -infix fun Int.foo(x: Int, y: Int) {} +infix fun Int.foo(x: Int, y: Int) {} -infix fun Int.bar() {} +infix fun Int.bar() {} -infix fun baz(x: Int, y: Int) {} +infix fun baz(x: Int, y: Int) {} infix class A @@ -16,9 +16,9 @@ class C { infix fun good(x: Int) {} infix fun Int.goodAsWell(x: Int) {} - infix fun Int.foo(x: Int, y: Int) {} + infix fun Int.foo(x: Int, y: Int) {} - infix fun Int.bar() {} + infix fun Int.bar() {} - infix fun baz(x: Int, y: Int) {} + infix fun baz(x: Int, y: Int) {} } diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index bb48aa391f3..c9184cb95c2 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -459,7 +459,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { } val MODIFIERS by object : DiagnosticGroup("Modifiers") { - val INAPPLICABLE_INFIX_MODIFIER by error() + val INAPPLICABLE_INFIX_MODIFIER by error(PositioningStrategy.INFIX_MODIFIER) val REPEATED_MODIFIER by error { parameter("modifier") } diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/model/RegularDiagnosticData.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/model/RegularDiagnosticData.kt index 01d078f77e2..934a1090b12 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/model/RegularDiagnosticData.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/model/RegularDiagnosticData.kt @@ -104,6 +104,7 @@ enum class PositioningStrategy(private val strategy: String? = null) { LABEL, COMMAS, OPERATOR_MODIFIER, + INFIX_MODIFIER, NON_FINAL_MODIFIER_OR_NAME, ENUM_MODIFIER, FIELD_KEYWORD, diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 0ea94ac1379..572e1770e58 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -333,7 +333,7 @@ object FirErrors { val EXPOSED_TYPE_PARAMETER_BOUND by error3, EffectiveVisibility>() // Modifiers - val INAPPLICABLE_INFIX_MODIFIER by error0() + val INAPPLICABLE_INFIX_MODIFIER by error0(SourceElementPositioningStrategies.INFIX_MODIFIER) val REPEATED_MODIFIER by error1() val REDUNDANT_MODIFIER by warning2() val DEPRECATED_MODIFIER by warning2() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInfixFunctionDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInfixFunctionDeclarationChecker.kt index 41538f744a0..a2af8125ca8 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInfixFunctionDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInfixFunctionDeclarationChecker.kt @@ -18,7 +18,11 @@ object FirInfixFunctionDeclarationChecker : FirBasicDeclarationChecker() { override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) { if ((declaration as? FirMemberDeclaration)?.status?.isInfix != true) return val simpleFunction = declaration as FirSimpleFunction - if (simpleFunction.valueParameters.size != 1 || !hasExtensionOrDispatchReceiver(simpleFunction, context)) { + if ( + (simpleFunction.valueParameters.size != 1) || + !hasExtensionOrDispatchReceiver(simpleFunction, context) || + simpleFunction.valueParameters.single().isVararg + ) { reporter.reportOn(declaration.source, FirErrors.INAPPLICABLE_INFIX_MODIFIER, context) } } diff --git a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/LightTreePositioningStrategies.kt b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/LightTreePositioningStrategies.kt index 2ec29f3966d..adb0332fa00 100644 --- a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/LightTreePositioningStrategies.kt +++ b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/LightTreePositioningStrategies.kt @@ -473,6 +473,9 @@ object LightTreePositioningStrategies { val OPERATOR_MODIFIER: LightTreePositioningStrategy = ModifierSetBasedLightTreePositioningStrategy(KtTokens.OPERATOR_KEYWORD) + val INFIX_MODIFIER: LightTreePositioningStrategy = + ModifierSetBasedLightTreePositioningStrategy(KtTokens.INFIX_KEYWORD) + val ENUM_MODIFIER: LightTreePositioningStrategy = ModifierSetBasedLightTreePositioningStrategy(KtTokens.ENUM_KEYWORD) diff --git a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index 9442cdf09af..669768c0f66 100644 --- a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -315,6 +315,10 @@ object PositioningStrategies { val OPERATOR_MODIFIER: PositioningStrategy = ModifierSetBasedPositioningStrategy(KtTokens.OPERATOR_KEYWORD) + @JvmField + val INFIX_MODIFIER: PositioningStrategy = + ModifierSetBasedPositioningStrategy(KtTokens.INFIX_KEYWORD) + @JvmField val ENUM_MODIFIER: PositioningStrategy = ModifierSetBasedPositioningStrategy(KtTokens.ENUM_KEYWORD) diff --git a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/SourceElementPositioningStrategies.kt b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/SourceElementPositioningStrategies.kt index ca48e9ce437..b40008998b7 100644 --- a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/SourceElementPositioningStrategies.kt +++ b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/SourceElementPositioningStrategies.kt @@ -340,6 +340,11 @@ object SourceElementPositioningStrategies { PositioningStrategies.OPERATOR_MODIFIER ) + val INFIX_MODIFIER = SourceElementPositioningStrategy( + LightTreePositioningStrategies.INFIX_MODIFIER, + PositioningStrategies.INFIX_MODIFIER + ) + val NON_FINAL_MODIFIER_OR_NAME = SourceElementPositioningStrategy( LightTreePositioningStrategies.NON_FINAL_MODIFIER_OR_NAME, PositioningStrategies.NON_FINAL_MODIFIER_OR_NAME diff --git a/compiler/testData/diagnostics/tests/Infix.fir.kt b/compiler/testData/diagnostics/tests/Infix.fir.kt deleted file mode 100644 index 152301dc0ad..00000000000 --- a/compiler/testData/diagnostics/tests/Infix.fir.kt +++ /dev/null @@ -1,38 +0,0 @@ -class Pair(val first: A, val second: B) - -class Example { - infix fun to(other: Example) = Pair(this, other) - fun toNonInfix(other: Example) = Pair(this, other) -} - -infix fun Example.toExt(other: Example) = Pair(this, other) -fun Example.toExtNonInfix(other: Example) = Pair(this, other) - -infix fun Example.toExtWithExtraParams(other: Example, blah: Int = 0) = Pair(this, other) -fun Example.toExtNonInfixWithExtraParams(other: Example, blah: Int = 0) = Pair(this, other) - -infix fun Example.toExtDefaultValues(other: Example? = null, blah: Int = 0) = Pair(this, other) -fun Example.toExtNonInfixDefaultValues(other: Example? = null, blah: Int = 0) = Pair(this, other) - -fun Example.withLambda(f: () -> Unit) = Pair(this, f) - -fun test() { - Example() to Example() - Example() toNonInfix Example() - Example().toNonInfix(Example()) - - val a = Example() - val b = Example() - - a toExt b - a toExtNonInfix b - a.toExtNonInfix(b) - - a toExtWithExtraParams b - a toExtNonInfixWithExtraParams b - - a toExtDefaultValues b - a toExtNonInfixDefaultValues b - - a withLambda { } -} diff --git a/compiler/testData/diagnostics/tests/Infix.kt b/compiler/testData/diagnostics/tests/Infix.kt index b703f762427..c35f4355fdb 100644 --- a/compiler/testData/diagnostics/tests/Infix.kt +++ b/compiler/testData/diagnostics/tests/Infix.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL class Pair(val first: A, val second: B) class Example { diff --git a/compiler/testData/diagnostics/tests/InfixModifierApplicability.fir.kt b/compiler/testData/diagnostics/tests/InfixModifierApplicability.fir.kt index 914bf5b0c45..afb8fc59fec 100644 --- a/compiler/testData/diagnostics/tests/InfixModifierApplicability.fir.kt +++ b/compiler/testData/diagnostics/tests/InfixModifierApplicability.fir.kt @@ -11,17 +11,17 @@ class OkTest { } // Errors -infix fun String.e1(o: String, o2: String? = null) = o -infix fun String.e2(o: String = "", o2: String? = null) = o +infix fun String.e1(o: String, o2: String? = null) = o +infix fun String.e2(o: String = "", o2: String? = null) = o -infix fun e3() {} -infix fun e4(s: String) {} -infix fun String.e5() {} -infix fun String.e6(a: Int, b: Int) {} -infix fun e7(a: Int, b: Int) {} +infix fun e3() {} +infix fun e4(s: String) {} +infix fun String.e5() {} +infix fun String.e6(a: Int, b: Int) {} +infix fun e7(a: Int, b: Int) {} class Example { - infix fun e8(s: String, a: Int = 0) {} - infix fun e9(s: String, a: Int) {} - infix fun e10() {} + infix fun e8(s: String, a: Int = 0) {} + infix fun e9(s: String, a: Int) {} + infix fun e10() {} } diff --git a/compiler/testData/diagnostics/tests/OperatorChecks.fir.kt b/compiler/testData/diagnostics/tests/OperatorChecks.fir.kt deleted file mode 100644 index c344e2be272..00000000000 --- a/compiler/testData/diagnostics/tests/OperatorChecks.fir.kt +++ /dev/null @@ -1,219 +0,0 @@ -// !DIAGNOSTICS: -EXTENSION_SHADOWED_BY_MEMBER - -import kotlin.reflect.KProperty - -interface Example { - operator fun plus(o: Example): Example - operator fun div(o: Example): Example - operator fun plus(o: Example, s: String = ""): Example - operator fun minus(vararg o: Example): Example - operator fun plus(): Example - operator fun minus(): Example - - operator fun unaryPlus(): Example - operator fun unaryMinus(): Example - - operator fun unaryPlus(s: String = ""): Example - operator fun unaryMinus(o: Example) - - operator fun inc(): Example - operator fun dec(): Example? - - operator fun plusAssign(n: Int) - operator fun minusAssign(n: Int): String - operator fun divAssign(n: Int, a: String = "") - operator fun modAssign(vararg n: Int) - - operator fun compareTo(other: Example): Int - - override operator fun equals(other: Any?): Boolean - operator fun equals(a: String): Boolean - - operator fun contains(n: Int): Boolean - operator fun contains(n: Int, s: String = ""): Boolean - - operator fun invoke() - - operator fun get(n: Int) - operator fun get(n: Int, n2: Int) - operator fun get() - - operator fun set(n: Int, v: Int) - operator fun set(n: Int, n2: Int, v: Int) - operator fun set(v: Int) - - operator fun rangeTo(o: Int) - operator fun rangeTo(o: Int, o2: Int) - operator fun rangeTo(vararg o: String) - - operator fun component1(): Int - operator fun component1(n: Int): Int - operator fun componentN(): Int - - operator fun iterator(): String - operator fun iterator(n: Int): String - - operator fun next(): String - operator fun next(n: Int): String - - operator fun hasNext(): Boolean - operator fun hasNext(n: Int): String - - infix fun i1(n: Int) - infix fun i1(n: Int, n2: Int) - infix fun i1(vararg n: Int) -} - -class OkDelegates { - operator fun getValue(thisRef: Any?, prop: KProperty<*>): String = "" - operator fun setValue(thisRef: Any?, prop: KProperty<*>, s: String): String = "" - operator fun setValue(thisRef: Any?, prop: Any, n: Int) {} - operator fun setValue(thisRef: Any?, prop: Any?, s: String) {} -} - -class DelegatesWithErrors { - operator fun getValue(thisRef: Any?, prop: String): String = "" - operator fun setValue(thisRef: Any?, prop: String, value: String) {} - - operator fun setValue(thisRef: Any?, prop: KProperty<*>, vararg n: Int) {} - operator fun setValue(thisRef: Any?, prop: KProperty<*>, f: Float = 0.0f) {} - - operator fun getValue(prop: KProperty<*>): String = "" - operator fun setValue(prop: KProperty<*>, value: String) {} -} - -interface Example2 { - operator fun inc(s: String): Example - operator fun dec() - operator fun compareTo(vararg other: Example): Int - operator fun contains(vararg n: Int): Boolean - operator fun hasNext(): Int -} - -interface Example3 { - operator fun compareTo(other: Example, s: String = ""): Int - operator fun contains(n: Int) -} - - - - -operator fun Example.plus(o: Any): Example {} -operator fun Example.div(o: Example): Example {} -operator fun Example.plus(o: Example, s: String = ""): Example {} -operator fun Example.minus(vararg o: Example): Example {} -operator fun Example.plus(): Example {} -operator fun Example.minus(): Example {} - -operator fun Example.unaryPlus(): Example {} -operator fun Example.unaryMinus(): Example {} - -operator fun Example.unaryPlus(s: String = ""): Example {} -operator fun Example.unaryMinus(o: Example) {} - -operator fun Example.inc(): Example {} -operator fun Example.dec(): Example? {} - -operator fun Example.plusAssign(n: Int) {} -operator fun Example.minusAssign(n: Int): String {} -operator fun Example.divAssign(n: Int, a: String = "") {} -operator fun Example.modAssign(vararg n: Int) {} - -operator fun Example.compareTo(other: Example): Int {} - -operator fun Example.equals(a: String): Boolean {} - -operator fun Example.contains(n: Int): Boolean {} -operator fun Example.contains(n: Int, s: String = ""): Boolean {} - -operator fun Example.invoke() {} - -operator fun Example.get(n: Int) {} -operator fun Example.get(n: Int, n2: Int) {} -operator fun Example.get() {} - -operator fun Example.set(n: Int, v: Int) {} -operator fun Example.set(n: Int, n2: Int, v: Int) {} -operator fun Example.set(v: Int) {} - -operator fun Example.rangeTo(o: Int) {} -operator fun Example.rangeTo(o: Int, o2: Int) {} -operator fun Example.rangeTo(vararg o: String) {} - -operator fun Example.component1(): Int {} -operator fun Example.component1(n: Int): Int {} -operator fun Example.componentN(): Int {} - -operator fun Example.iterator(): String {} -operator fun Example.iterator(n: Int): String {} - -operator fun Example.next(): String {} -operator fun Example.next(n: Int): String {} - -operator fun Example.hasNext(): Boolean {} -operator fun Example.hasNext(n: Int): String {} - -infix fun Example.i1(n: Int) {} -infix fun Example.i1(n: Int, n2: Int) {} -infix fun Example.i1(vararg n: Int) {} - - - - - -operator fun plus(o: String): Example {} -operator fun div(o: Example): Example {} -operator fun plus(o: Example, s: String = ""): Example {} -operator fun minus(vararg o: Example): Example {} - -operator fun unaryPlus(): Example {} -operator fun unaryMinus(): Example {} - -operator fun unaryPlus(s: String = ""): Example {} -operator fun unaryMinus(o: Example) {} - -operator fun inc(): Example {} -operator fun dec(): Example? {} - -operator fun plusAssign(n: Int) {} -operator fun minusAssign(n: Int): String {} -operator fun divAssign(n: Int, a: String = "") {} -operator fun modAssign(vararg n: Int) {} - -operator fun compareTo(other: Example): Int {} - -operator fun equals(a: String): Boolean {} - -operator fun contains(n: Int): Boolean {} -operator fun contains(n: Int, s: String = ""): Boolean {} - -operator fun invoke() {} - -operator fun get(n: Int) {} -operator fun get(n: Int, n2: Int) {} -operator fun get() {} - -operator fun set(n: Int, v: Int) {} -operator fun set(n: Int, n2: Int, v: Int) {} -operator fun set(v: Int) {} - -operator fun rangeTo(o: Int) {} -operator fun rangeTo(o: Int, o2: Int) {} -operator fun rangeTo(vararg o: String) {} - -operator fun component1(): Int {} -operator fun component1(n: Int): Int {} -operator fun componentN(): Int {} - -operator fun iterator(): String {} -operator fun iterator(n: Int): String {} - -operator fun next(): String {} -operator fun next(n: Int): String {} - -operator fun hasNext(): Boolean {} -operator fun hasNext(n: Int): String {} - -infix fun i1(n: Int) {} -infix fun i1(n: Int, n2: Int) {} -infix fun i1(vararg n: Int) {} diff --git a/compiler/testData/diagnostics/tests/OperatorChecks.kt b/compiler/testData/diagnostics/tests/OperatorChecks.kt index b3b8f45bd69..41e96239a9d 100644 --- a/compiler/testData/diagnostics/tests/OperatorChecks.kt +++ b/compiler/testData/diagnostics/tests/OperatorChecks.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -EXTENSION_SHADOWED_BY_MEMBER import kotlin.reflect.KProperty