diff --git a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt index 51d0f76be68..de9a917f311 100644 --- a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt +++ b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt @@ -160,8 +160,6 @@ internal fun IElementType.toFirOperation(): FirOperation = KtTokens.EXCLEQ -> FirOperation.NOT_EQ KtTokens.EQEQEQ -> FirOperation.IDENTITY KtTokens.EXCLEQEQEQ -> FirOperation.NOT_IDENTITY - KtTokens.IN_KEYWORD -> FirOperation.IN - KtTokens.NOT_IN -> FirOperation.NOT_IN KtTokens.EQ -> FirOperation.ASSIGN KtTokens.PLUSEQ -> FirOperation.PLUS_ASSIGN @@ -237,14 +235,8 @@ internal fun KtWhenCondition.toFirWhenCondition( } } is KtWhenConditionInRange -> { - FirOperatorCallImpl( - session, - rangeExpression, - if (isNegated) FirOperation.NOT_IN else FirOperation.IN - ).apply { - arguments += firSubjectExpression - arguments += rangeExpression.convert("No range in condition with range") - } + val firRange = rangeExpression.convert("No range in condition with range") + firRange.generateContainsOperation(session, firSubjectExpression, isNegated, rangeExpression, operationReference) } is KtWhenConditionIsPattern -> { FirTypeOperatorCallImpl( @@ -321,6 +313,25 @@ internal fun Array.toInterpolatingCall( return if (hasExpressions) result!! else FirConstExpressionImpl(session, base, IrConstKind.String, sb.toString()) } +internal fun FirExpression.generateContainsOperation( + session: FirSession, + argument: FirExpression, + inverted: Boolean, + base: KtExpression?, + operationReference: KtOperationReferenceExpression +): FirFunctionCall { + val containsCall = FirFunctionCallImpl(session, base).apply { + calleeReference = FirSimpleNamedReference(session, operationReference, OperatorNameConventions.CONTAINS) + explicitReceiver = this@generateContainsOperation + arguments += argument + } + if (!inverted) return containsCall + return FirFunctionCallImpl(session, base).apply { + calleeReference = FirSimpleNamedReference(session, operationReference, OperatorNameConventions.NOT) + explicitReceiver = containsCall + } +} + internal fun generateIncrementOrDecrementBlock( session: FirSession, baseExpression: KtUnaryExpression, diff --git a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index 98e2294d122..f3bc6ef6ae2 100644 --- a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -22,7 +22,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.FirTypeProjection import org.jetbrains.kotlin.fir.types.impl.* -import org.jetbrains.kotlin.ir.expressions.IrConstKind import org.jetbrains.kotlin.lexer.KtTokens.* import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName @@ -1137,6 +1136,10 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) { return leftArgument.generateNotNullOrOther(session, rightArgument, "elvis", expression) ANDAND, OROR -> return leftArgument.generateLazyLogicalOperation(session, rightArgument, operationToken == ANDAND, expression) + in OperatorConventions.IN_OPERATIONS -> + return rightArgument.generateContainsOperation( + session, leftArgument, operationToken == NOT_IN, expression, expression.operationReference + ) } val conventionCallName = operationToken.toBinaryName() return if (conventionCallName != null || operationToken == IDENTIFIER) { diff --git a/compiler/fir/psi2fir/testData/rawBuilder/expressions/branches.txt b/compiler/fir/psi2fir/testData/rawBuilder/expressions/branches.txt index 921ae97dc20..b116b138e84 100644 --- a/compiler/fir/psi2fir/testData/rawBuilder/expressions/branches.txt +++ b/compiler/fir/psi2fir/testData/rawBuilder/expressions/branches.txt @@ -57,7 +57,7 @@ FILE: branches.kt ==($subj$, Int(3)) -> { String(Mediocre) } - in($subj$, Int(1).rangeTo#(Int(2))) -> { + Int(1).rangeTo#(Int(2)).contains#($subj$) -> { String(Fail) } ($subj$ is Number) -> { diff --git a/compiler/fir/psi2fir/testData/rawBuilder/expressions/in.kt b/compiler/fir/psi2fir/testData/rawBuilder/expressions/in.kt new file mode 100644 index 00000000000..f159e5073b9 --- /dev/null +++ b/compiler/fir/psi2fir/testData/rawBuilder/expressions/in.kt @@ -0,0 +1,2 @@ +fun foo(x: Int, y: Int, c: Collection) = + x in c && y !in c \ No newline at end of file diff --git a/compiler/fir/psi2fir/testData/rawBuilder/expressions/in.txt b/compiler/fir/psi2fir/testData/rawBuilder/expressions/in.txt new file mode 100644 index 00000000000..5778d2fc772 --- /dev/null +++ b/compiler/fir/psi2fir/testData/rawBuilder/expressions/in.txt @@ -0,0 +1,12 @@ +FILE: in.kt + public? final? fun foo(x: Int, y: Int, c: Collection): { + ^foo when () { + c#.contains#(x#) -> { + c#.contains#(y#).not#() + } + else -> { + Boolean(false) + } + } + + } diff --git a/compiler/fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTestCaseGenerated.java b/compiler/fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTestCaseGenerated.java index a5d89e18f23..cf55127bfcf 100644 --- a/compiler/fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTestCaseGenerated.java +++ b/compiler/fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTestCaseGenerated.java @@ -204,6 +204,11 @@ public class RawFirBuilderTestCaseGenerated extends AbstractRawFirBuilderTestCas runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/genericCalls.kt"); } + @TestMetadata("in.kt") + public void testIn() throws Exception { + runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/in.kt"); + } + @TestMetadata("init.kt") public void testInit() throws Exception { runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/init.kt"); diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirOperation.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirOperation.kt index 325236d88f3..025208be7c0 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirOperation.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirOperation.kt @@ -17,8 +17,6 @@ enum class FirOperation(val operator: String = "???") { GT(">"), LT_EQ("<="), GT_EQ(">="), - IN("in"), - NOT_IN("!in"), ASSIGN("="), PLUS_ASSIGN("+="), @@ -41,7 +39,7 @@ enum class FirOperation(val operator: String = "???") { val ASSIGNMENTS: Set = EnumSet.of(ASSIGN, PLUS_ASSIGN, MINUS_ASSIGN, TIMES_ASSIGN, DIV_ASSIGN, REM_ASSIGN) val BOOLEANS: Set = EnumSet.of( - EQ, NOT_EQ, IDENTITY, NOT_IDENTITY, LT, GT, LT_EQ, GT_EQ, IN, NOT_IN, IS, NOT_IS + EQ, NOT_EQ, IDENTITY, NOT_IDENTITY, LT, GT, LT_EQ, GT_EQ, IS, NOT_IS ) } } \ No newline at end of file