From 9101505ecad824daebfc6d264e46953b8630b1c7 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Tue, 5 May 2015 12:20:26 +0300 Subject: [PATCH] Rework `deparenthesize`-like methods - Extract private `deparenthesizeOnce` and repeat it until get the same expression - Drop redundant parameter `deparenthesizeRecursively` - Drop some usages of `safeDeparenthesize` in `deparenthesize` because even if `deparenthesize` returns null (i.e. something was not parsed) there is no sense in working with such expressions Note, that `deparenthesize` now unwraps nested labels' declaration (see changes in testData), but it seems to be reasonable --- .../org/jetbrains/kotlin/psi/JetPsiUtil.java | 40 +++++++++++-------- .../kotlin/resolve/calls/util/callUtil.kt | 2 +- .../ExpressionTypingVisitorForStatements.java | 2 +- .../diagnostics/tests/BreakContinue.kt | 11 +++++ .../diagnostics/tests/BreakContinue.txt | 1 + .../for/withContinueAndLabels.kt | 1 - 6 files changed, 38 insertions(+), 19 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiUtil.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiUtil.java index 9f7926029b0..317a3617090 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiUtil.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiUtil.java @@ -90,7 +90,7 @@ public class JetPsiUtil { boolean deparenthesizeBinaryExpressionWithTypeRHS ) { return deparenthesizeWithResolutionStrategy( - expression, deparenthesizeBinaryExpressionWithTypeRHS, /* deparenthesizeRecursively = */ true, null); + expression, deparenthesizeBinaryExpressionWithTypeRHS, /* deparenthesizeRecursively = */ null); } @Nullable @@ -98,50 +98,58 @@ public class JetPsiUtil { @Nullable JetExpression expression, boolean deparenthesizeBinaryExpressionWithTypeRHS ) { - return deparenthesizeWithResolutionStrategy( - expression, deparenthesizeBinaryExpressionWithTypeRHS, /* deparenthesizeRecursively = */ false, null); + return deparenthesizeOnce(expression, deparenthesizeBinaryExpressionWithTypeRHS, null); } @Nullable public static JetExpression deparenthesizeWithResolutionStrategy( @Nullable JetExpression expression, - boolean deparenthesizeBinaryExpressionWithTypeRHS, @Nullable Function typeResolutionStrategy ) { - return deparenthesizeWithResolutionStrategy(expression, true, true, typeResolutionStrategy); + return deparenthesizeWithResolutionStrategy(expression, true, typeResolutionStrategy); } @Nullable private static JetExpression deparenthesizeWithResolutionStrategy( @Nullable JetExpression expression, boolean deparenthesizeBinaryExpressionWithTypeRHS, - boolean deparenthesizeRecursively, + @Nullable Function typeResolutionStrategy + ) { + while (true) { + JetExpression baseExpression = + deparenthesizeOnce(expression, deparenthesizeBinaryExpressionWithTypeRHS, typeResolutionStrategy); + + if (baseExpression == expression) return baseExpression; + expression = baseExpression; + } + } + + @Nullable + private static JetExpression deparenthesizeOnce( + @Nullable JetExpression expression, + boolean deparenthesizeBinaryExpressionWithTypeRHS, @Nullable Function typeResolutionStrategy ) { if (deparenthesizeBinaryExpressionWithTypeRHS && expression instanceof JetBinaryExpressionWithTypeRHS) { JetBinaryExpressionWithTypeRHS binaryExpression = (JetBinaryExpressionWithTypeRHS) expression; JetSimpleNameExpression operationSign = binaryExpression.getOperationReference(); if (JetTokens.COLON.equals(operationSign.getReferencedNameElementType())) { - expression = binaryExpression.getLeft(); JetTypeReference typeReference = binaryExpression.getRight(); if (typeResolutionStrategy != null && typeReference != null) { typeResolutionStrategy.apply(typeReference); } + return binaryExpression.getLeft(); } + return expression; } else if (expression instanceof JetLabeledExpression) { - JetExpression baseExpression = ((JetLabeledExpression) expression).getBaseExpression(); - if (baseExpression != null) { - expression = baseExpression; - } + return ((JetLabeledExpression) expression).getBaseExpression(); } else if (expression instanceof JetExpressionWrapper) { - expression = ((JetExpressionWrapper) expression).getBaseExpression(); + return ((JetExpressionWrapper) expression).getBaseExpression(); } - if (expression instanceof JetParenthesizedExpression) { - JetExpression innerExpression = ((JetParenthesizedExpression) expression).getExpression(); - return innerExpression != null && deparenthesizeRecursively ? deparenthesizeWithResolutionStrategy( - innerExpression, deparenthesizeBinaryExpressionWithTypeRHS, true, typeResolutionStrategy) : innerExpression; + else if (expression instanceof JetParenthesizedExpression) { + return ((JetParenthesizedExpression) expression).getExpression(); } return expression; } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/callUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/callUtil.kt index 3f2d9a4ad17..94e5cf2acf2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/callUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/callUtil.kt @@ -101,7 +101,7 @@ public fun Call.getValueArgumentForExpression(expression: JetExpression): ValueA // Get call / resolved call from binding context public fun JetElement?.getCalleeExpressionIfAny(): JetExpression? { - val element = if (this is JetExpression) JetPsiUtil.safeDeparenthesize(this, false) else this + val element = if (this is JetExpression) JetPsiUtil.deparenthesize(this, false) else this return when (element) { is JetSimpleNameExpression -> element is JetCallElement -> element.getCalleeExpression() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java index 51969c4eaa3..6dece3bb9b1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java @@ -337,7 +337,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito final ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceScope(scope).replaceContextDependency(INDEPENDENT); JetExpression leftOperand = expression.getLeft(); - JetExpression left = deparenthesizeWithResolutionStrategy(leftOperand, true, new Function() { + JetExpression left = deparenthesizeWithResolutionStrategy(leftOperand, new Function() { @Override public Void apply(JetTypeReference reference) { components.typeResolver.resolveType(context.scope, reference, context.trace, true); diff --git a/compiler/testData/diagnostics/tests/BreakContinue.kt b/compiler/testData/diagnostics/tests/BreakContinue.kt index db3eb8c36a2..333f9ea024b 100644 --- a/compiler/testData/diagnostics/tests/BreakContinue.kt +++ b/compiler/testData/diagnostics/tests/BreakContinue.kt @@ -82,4 +82,15 @@ class C { } a.compareTo("2") } + + fun twoLabelsOnLoop() { + label1@ label2@ for (i in 1..100) { + if (i > 0) { + break@label1 + } + else { + break@label2 + } + } + } } diff --git a/compiler/testData/diagnostics/tests/BreakContinue.txt b/compiler/testData/diagnostics/tests/BreakContinue.txt index b91551ece9a..53a12c0c89b 100644 --- a/compiler/testData/diagnostics/tests/BreakContinue.txt +++ b/compiler/testData/diagnostics/tests/BreakContinue.txt @@ -12,5 +12,6 @@ internal final class C { public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int internal final fun notContainsBreak(/*0*/ a: kotlin.String?, /*1*/ b: kotlin.String?): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + internal final fun twoLabelsOnLoop(): kotlin.Unit internal final fun unresolvedBreak(/*0*/ a: kotlin.String?, /*1*/ array: kotlin.Array): kotlin.Unit } diff --git a/j2k/testData/fileOrElement/for/withContinueAndLabels.kt b/j2k/testData/fileOrElement/for/withContinueAndLabels.kt index 73e9653632e..838494f0e36 100644 --- a/j2k/testData/fileOrElement/for/withContinueAndLabels.kt +++ b/j2k/testData/fileOrElement/for/withContinueAndLabels.kt @@ -1,4 +1,3 @@ -// ERROR: The label '@OuterLoop1' does not denote a loop public object TestClass { public fun main(args: Array) { var i = 1