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
This commit is contained in:
@@ -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<JetTypeReference, Void> 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<JetTypeReference, Void> 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<JetTypeReference, Void> 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;
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
+1
-1
@@ -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<JetTypeReference, Void>() {
|
||||
JetExpression left = deparenthesizeWithResolutionStrategy(leftOperand, new Function<JetTypeReference, Void>() {
|
||||
@Override
|
||||
public Void apply(JetTypeReference reference) {
|
||||
components.typeResolver.resolveType(context.scope, reference, context.trace, true);
|
||||
|
||||
@@ -82,4 +82,15 @@ class C {
|
||||
}
|
||||
a<!UNSAFE_CALL!>.<!>compareTo("2")
|
||||
}
|
||||
|
||||
fun twoLabelsOnLoop() {
|
||||
label1@ label2@ for (i in 1..100) {
|
||||
if (i > 0) {
|
||||
break@label1
|
||||
}
|
||||
else {
|
||||
break@label2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.Int>): kotlin.Unit
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// ERROR: The label '@OuterLoop1' does not denote a loop
|
||||
public object TestClass {
|
||||
public fun main(args: Array<String>) {
|
||||
var i = 1
|
||||
|
||||
Reference in New Issue
Block a user