From 0008e832d855f3394a2b56bccfceac8f319d1dfe Mon Sep 17 00:00:00 2001 From: Sergej Jaskiewicz Date: Thu, 29 Feb 2024 18:51:53 +0100 Subject: [PATCH] [PowerAssert] Improve the accuracy of locating infix operator tokens Use KotlinLexer to determine the correct offset of an infix operator token instead of skipping whitespaces after the operator's LHS. This fixes cases like this: ``` assert("Name"/*in*/in/*in*/listOf("Hello", "World")) | | | [Hello, World] false ``` --- .../power-assert.backend/build.gradle.kts | 2 ++ .../kotlin/powerassert/diagram/IrDiagram.kt | 18 +++++++++++------- .../codegen/cast/InstanceEquals.box.txt | 4 ++-- .../codegen/cast/InstanceNotEquals.box.txt | 4 ++-- .../codegen/operator/ContainsOperator.box.txt | 6 +++--- .../codegen/operator/ExcleqOperator.box.txt | 4 ++-- .../codegen/operator/ExcleqeqOperator.box.txt | 4 ++-- .../operator/NegativeContainsOperator.box.txt | 6 +++--- 8 files changed, 27 insertions(+), 21 deletions(-) diff --git a/plugins/power-assert/power-assert.backend/build.gradle.kts b/plugins/power-assert/power-assert.backend/build.gradle.kts index ba2d388cab3..7c0d1c8507a 100644 --- a/plugins/power-assert/power-assert.backend/build.gradle.kts +++ b/plugins/power-assert/power-assert.backend/build.gradle.kts @@ -10,6 +10,8 @@ dependencies { compileOnly(project(":compiler:ir.backend.common")) compileOnly(project(":compiler:ir.tree")) compileOnly(project(":compiler:cli")) + + compileOnly(intellijCore()) } optInToUnsafeDuringIrConstructionAPI() diff --git a/plugins/power-assert/power-assert.backend/src/org/jetbrains/kotlin/powerassert/diagram/IrDiagram.kt b/plugins/power-assert/power-assert.backend/src/org/jetbrains/kotlin/powerassert/diagram/IrDiagram.kt index 2aed37ccb35..cbf432ea25b 100644 --- a/plugins/power-assert/power-assert.backend/src/org/jetbrains/kotlin/powerassert/diagram/IrDiagram.kt +++ b/plugins/power-assert/power-assert.backend/src/org/jetbrains/kotlin/powerassert/diagram/IrDiagram.kt @@ -27,6 +27,8 @@ import org.jetbrains.kotlin.ir.builders.irGet import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.lexer.KotlinLexer +import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.powerassert.irString fun IrBuilderWithScope.irDiagramString( @@ -187,22 +189,24 @@ private fun typeOperatorOffset( } /** - * The offset of the infix operator/function itself. + * The offset of the infix operator/function token itself. * * @param lhs The left-hand side expression of the operator. * @param wholeOperatorSourceRangeInfo The source range of the whole operator expression. * @param wholeOperatorSource The source text of the whole operator expression. */ private fun binaryOperatorOffset(lhs: IrExpression, wholeOperatorSourceRangeInfo: SourceRangeInfo, wholeOperatorSource: String): Int { - var offset = lhs.endOffset - wholeOperatorSourceRangeInfo.startOffset + 1 + val offset = lhs.endOffset - wholeOperatorSourceRangeInfo.startOffset if (offset < 0 || offset >= wholeOperatorSource.length) return 0 // infix function called using non-infix syntax - // Continue until there is a non-whitespace character - while (wholeOperatorSource[offset].isWhitespace() || wholeOperatorSource[offset] == '.') { - offset++ - if (offset >= wholeOperatorSource.length) return 0 + KotlinLexer().run { + start(wholeOperatorSource, offset, wholeOperatorSource.length) + while (tokenType != null && tokenType != KtTokens.EOF && (tokenType == KtTokens.DOT || tokenType !in KtTokens.OPERATIONS)) { + advance() + } + if (tokenStart >= wholeOperatorSource.length) return 0 + return tokenStart } - return offset } /** diff --git a/plugins/power-assert/testData/codegen/cast/InstanceEquals.box.txt b/plugins/power-assert/testData/codegen/cast/InstanceEquals.box.txt index 5a3529dd233..ae0409607e9 100644 --- a/plugins/power-assert/testData/codegen/cast/InstanceEquals.box.txt +++ b/plugins/power-assert/testData/codegen/cast/InstanceEquals.box.txt @@ -24,8 +24,8 @@ assert(!( Assertion failed assert(null/*is*/is/*is*/String) - | - false + | + false Assertion failed assert(!((null is String) is Boolean)) diff --git a/plugins/power-assert/testData/codegen/cast/InstanceNotEquals.box.txt b/plugins/power-assert/testData/codegen/cast/InstanceNotEquals.box.txt index 0d7015930e8..a446c43daa3 100644 --- a/plugins/power-assert/testData/codegen/cast/InstanceNotEquals.box.txt +++ b/plugins/power-assert/testData/codegen/cast/InstanceNotEquals.box.txt @@ -21,8 +21,8 @@ assert( Assertion failed assert("Hello, world!"/*!is*/!is/*!is*/String) - | - false + | + false Assertion failed assert(("Hello, world!" !is String) !is Boolean) diff --git a/plugins/power-assert/testData/codegen/operator/ContainsOperator.box.txt b/plugins/power-assert/testData/codegen/operator/ContainsOperator.box.txt index 0d45e4f9bd5..5be2e6ee019 100644 --- a/plugins/power-assert/testData/codegen/operator/ContainsOperator.box.txt +++ b/plugins/power-assert/testData/codegen/operator/ContainsOperator.box.txt @@ -25,9 +25,9 @@ assert( Assertion failed assert("Name"/*in*/in/*in*/listOf("Hello", "World")) - | | - | [Hello, World] - false + | | + | [Hello, World] + false Assertion failed assert(("Name" in listOf("Hello", "World")) in listOf(true)) diff --git a/plugins/power-assert/testData/codegen/operator/ExcleqOperator.box.txt b/plugins/power-assert/testData/codegen/operator/ExcleqOperator.box.txt index 503c23379a1..fabced47d45 100644 --- a/plugins/power-assert/testData/codegen/operator/ExcleqOperator.box.txt +++ b/plugins/power-assert/testData/codegen/operator/ExcleqOperator.box.txt @@ -21,8 +21,8 @@ assert( Assertion failed assert(1/*!=*/!=/*!=*/1) - | - false + | + false Assertion failed assert((1 != 1) != false) diff --git a/plugins/power-assert/testData/codegen/operator/ExcleqeqOperator.box.txt b/plugins/power-assert/testData/codegen/operator/ExcleqeqOperator.box.txt index 9ed3fa9c48b..551ff34cabe 100644 --- a/plugins/power-assert/testData/codegen/operator/ExcleqeqOperator.box.txt +++ b/plugins/power-assert/testData/codegen/operator/ExcleqeqOperator.box.txt @@ -21,8 +21,8 @@ assert( Assertion failed assert(1/*!==*/!==/*!==*/1) - | - false + | + false Assertion failed assert((1 !== 1) !== false) diff --git a/plugins/power-assert/testData/codegen/operator/NegativeContainsOperator.box.txt b/plugins/power-assert/testData/codegen/operator/NegativeContainsOperator.box.txt index af414cbfe50..2cb3b75e856 100644 --- a/plugins/power-assert/testData/codegen/operator/NegativeContainsOperator.box.txt +++ b/plugins/power-assert/testData/codegen/operator/NegativeContainsOperator.box.txt @@ -25,9 +25,9 @@ assert( Assertion failed assert("Hello"/*!in*/!in/*!in*/listOf("Hello", "World")) - | | - | [Hello, World] - false + | | + | [Hello, World] + false Assertion failed assert(("Hello" !in listOf("Hello", "World")) !in listOf(false))