From e91bcbde30ff87e4137f865a039ae24bd4aa9be4 Mon Sep 17 00:00:00 2001 From: aleksandrina-streltsova Date: Fri, 2 Feb 2024 16:14:15 +0100 Subject: [PATCH] [kotlin] Fix inconsistent highlighting for loop exit points ^KTIJ-28726 Fixed GitOrigin-RevId: 758c52107bddc73cfebab48a1d0c4928c7468d4e --- .../K2HighlightExitPointsTestGenerated.java | 5 ++++ ...KotlinHighlightExitPointsHandlerFactory.kt | 30 +++++++++++++------ .../HighlightExitPointsTestGenerated.java | 5 ++++ .../exitPoints/forLoopNestedLabeledBreak2.kt | 13 ++++++++ 4 files changed, 44 insertions(+), 9 deletions(-) create mode 100644 plugins/kotlin/idea/tests/testData/exitPoints/forLoopNestedLabeledBreak2.kt diff --git a/plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java b/plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java index 76a34faf21b2..7ecf1eb0a656 100644 --- a/plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java +++ b/plugins/kotlin/highlighting/highlighting-k2/test/org/jetbrains/kotlin/idea/k2/highlighting/K2HighlightExitPointsTestGenerated.java @@ -63,6 +63,11 @@ public class K2HighlightExitPointsTestGenerated extends AbstractK2HighlightExitP runTest("../../idea/tests/testData/exitPoints/forLoopNestedLabeledBreak.kt"); } + @TestMetadata("forLoopNestedLabeledBreak2.kt") + public void testForLoopNestedLabeledBreak2() throws Exception { + runTest("../../idea/tests/testData/exitPoints/forLoopNestedLabeledBreak2.kt"); + } + @TestMetadata("forLoopNestedLabeledBreakOnLoop.kt") public void testForLoopNestedLabeledBreakOnLoop() throws Exception { runTest("../../idea/tests/testData/exitPoints/forLoopNestedLabeledBreakOnLoop.kt"); diff --git a/plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/AbstractKotlinHighlightExitPointsHandlerFactory.kt b/plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/AbstractKotlinHighlightExitPointsHandlerFactory.kt index 8a3a093ead33..6723c8810d9f 100644 --- a/plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/AbstractKotlinHighlightExitPointsHandlerFactory.kt +++ b/plugins/kotlin/highlighting/highlighting-shared/src/org/jetbrains/kotlin/idea/base/highlighting/AbstractKotlinHighlightExitPointsHandlerFactory.kt @@ -36,6 +36,7 @@ abstract class AbstractKotlinHighlightExitPointsHandlerFactory : HighlightUsages )?.takeUnless { it is KtFunction } + else -> null } as? KtExpression ?: return null return OnExitUsagesHandler(editor, file, null, expression, false) @@ -117,10 +118,12 @@ abstract class AbstractKotlinHighlightExitPointsHandlerFactory : HighlightUsages targetOccurrenceAdded = true addOccurrence(it) } + is KtPropertyAccessor -> relevantFunction.namePlaceholder.let { targetOccurrenceAdded = true addOccurrence(it) } + is KtFunctionLiteral -> { targetOccurrenceAdded = true addOccurrence(relevantFunction.lBrace) @@ -141,7 +144,7 @@ abstract class AbstractKotlinHighlightExitPointsHandlerFactory : HighlightUsages } override fun visitExpression(expression: KtExpression) { - when(expression) { + when (expression) { is KtBinaryExpression -> { expression.left?.let { lastStatements.addIfNotNullAndNotBlock(it) @@ -152,34 +155,39 @@ abstract class AbstractKotlinHighlightExitPointsHandlerFactory : HighlightUsages visitExpression(it) } } + is KtCallExpression -> { expression.calleeExpression?.let { lastStatements.addIfNotNullAndNotBlock(it) visitExpression(it) } } + is KtBlockExpression -> { expression.lastStatementOrNull()?.let { lastStatements.addIfNotNullAndNotBlock(it) visitExpression(it) } } + is KtIfExpression -> { expression.then?.let { lastStatements.addIfNotNullAndNotBlock(it) visitExpression(it) } - expression.`else`?.let{ + expression.`else`?.let { lastStatements.addIfNotNullAndNotBlock(it) visitExpression(it) } } + is KtWhenExpression -> { expression.entries.mapNotNull { it.expression }.forEach { lastStatements.addIfNotNullAndNotBlock(it) visitExpression(it) } } + else -> super.visitExpression(expression) } } @@ -321,7 +329,7 @@ abstract class AbstractKotlinHighlightExitPointsHandlerFactory : HighlightUsages } override fun computeUsages(targets: MutableList) { - val labelName = when (target) { + val targetLabelName = when (target) { is KtExpressionWithLabel -> target.getLabelName() is KtLoopExpression -> (target.parent as? KtLabeledExpression)?.getLabelName() else -> null @@ -333,7 +341,10 @@ abstract class AbstractKotlinHighlightExitPointsHandlerFactory : HighlightUsages var targetLoop: KtLoopExpression? = null while (element != null) { val parent = element.parent - if (element is KtLoopExpression && (labelName == null || (parent as? KtLabeledExpression)?.getLabelName() == labelName)) { + if ( + element is KtLoopExpression && + (targetLabelName == null || (parent as? KtLabeledExpression)?.getLabelName() == targetLabelName) + ) { targetLoop = element break } @@ -342,8 +353,9 @@ abstract class AbstractKotlinHighlightExitPointsHandlerFactory : HighlightUsages targetLoop } } ?: return + val loopLabelName = (relevantLoop.parent as? KtLabeledExpression)?.getLabelName() - when(relevantLoop) { + when (relevantLoop) { is KtForExpression -> addOccurrence(relevantLoop.forKeyword) is KtDoWhileExpression -> relevantLoop.node.findChildByType(KtTokens.DO_KEYWORD)?.psi?.let(::addOccurrence) is KtWhileExpression -> relevantLoop.node.findChildByType(KtTokens.WHILE_KEYWORD)?.psi?.let(::addOccurrence) @@ -361,9 +373,9 @@ abstract class AbstractKotlinHighlightExitPointsHandlerFactory : HighlightUsages override fun visitExpression(expression: KtExpression) { val nestedLoopFound = if (expression != relevantLoop && expression is KtLoopExpression) { - val loopLabelName = (expression.parent as? KtLabeledExpression)?.getLabelName() + val nestedLoopLabelName = (expression.parent as? KtLabeledExpression)?.getLabelName() // no reasons to step into another loop with the same label name or no label name - if (labelName == null || labelName == loopLabelName) return + if (loopLabelName == null || loopLabelName == nestedLoopLabelName) return nestedLoopExpressions.push(expression) true @@ -374,10 +386,10 @@ abstract class AbstractKotlinHighlightExitPointsHandlerFactory : HighlightUsages if (expression is KtBreakExpression || expression is KtContinueExpression) { val expressionLabelName = (expression as? KtExpressionWithLabel)?.getLabelName() if (nestedLoopExpressions.isEmpty()) { - if (expressionLabelName == null || expressionLabelName == labelName) { + if (expressionLabelName == null || expressionLabelName == loopLabelName) { addOccurrence(expression) } - } else if (expressionLabelName == labelName) { + } else if (expressionLabelName == loopLabelName) { addOccurrence(expression) } } diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/HighlightExitPointsTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/HighlightExitPointsTestGenerated.java index b5838d5c9416..a8d13cc84b82 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/HighlightExitPointsTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/highlighter/HighlightExitPointsTestGenerated.java @@ -63,6 +63,11 @@ public class HighlightExitPointsTestGenerated extends AbstractCustomHighlightUsa runTest("testData/exitPoints/forLoopNestedLabeledBreak.kt"); } + @TestMetadata("forLoopNestedLabeledBreak2.kt") + public void testForLoopNestedLabeledBreak2() throws Exception { + runTest("testData/exitPoints/forLoopNestedLabeledBreak2.kt"); + } + @TestMetadata("forLoopNestedLabeledBreakOnLoop.kt") public void testForLoopNestedLabeledBreakOnLoop() throws Exception { runTest("testData/exitPoints/forLoopNestedLabeledBreakOnLoop.kt"); diff --git a/plugins/kotlin/idea/tests/testData/exitPoints/forLoopNestedLabeledBreak2.kt b/plugins/kotlin/idea/tests/testData/exitPoints/forLoopNestedLabeledBreak2.kt new file mode 100644 index 000000000000..4ead6c8731fc --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/exitPoints/forLoopNestedLabeledBreak2.kt @@ -0,0 +1,13 @@ +fun some(list: List) { + a@ for (j in 0..5) { + for (i in 0..5) { + break@a + } + if (j == 0) continue + if (j == 2) brea~k + b@ for (i in 0..5) { + break@b + break@a + } + } +}