Implement 'when' transformations (flatten, introduce subject, eliminate subject)
This commit is contained in:
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright 2010-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.lang.psi;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class JetPsiMatcher {
|
||||
private JetPsiMatcher() {
|
||||
}
|
||||
|
||||
private static boolean checkTypeReferenceMatch(JetTypeReference t1, JetTypeReference t2) {
|
||||
return (t1 == t2) || (t1 != null && t2 != null && t1.getText().equals(t2.getText()));
|
||||
}
|
||||
|
||||
private static boolean checkStringTemplateEntryMatch(JetStringTemplateEntry e1, JetStringTemplateEntry e2) {
|
||||
if (e1 == e2) return true;
|
||||
if (e1 == null || e2 == null) return false;
|
||||
|
||||
return e1.getClass() == e2.getClass() && checkExpressionMatch(e1.getExpression(), e2.getExpression());
|
||||
}
|
||||
|
||||
private static boolean checkWhenConditionMatch(JetWhenCondition cond1, JetWhenCondition cond2) {
|
||||
if (cond1 == cond2) return true;
|
||||
if (cond1 == null || cond2 == null) return false;
|
||||
|
||||
if (cond1.getClass() != cond2.getClass()) return false;
|
||||
|
||||
if (cond1 instanceof JetWhenConditionInRange) {
|
||||
JetWhenConditionInRange inRange1 = (JetWhenConditionInRange) cond1;
|
||||
JetWhenConditionInRange inRange2 = (JetWhenConditionInRange) cond2;
|
||||
|
||||
return inRange1.isNegated() == inRange2.isNegated() &&
|
||||
checkExpressionMatch(inRange1.getRangeExpression(), inRange2.getRangeExpression()) &&
|
||||
checkExpressionMatch(inRange1.getOperationReference(), inRange2.getOperationReference());
|
||||
}
|
||||
|
||||
if (cond1 instanceof JetWhenConditionIsPattern) {
|
||||
JetWhenConditionIsPattern pattern1 = (JetWhenConditionIsPattern) cond1;
|
||||
JetWhenConditionIsPattern pattern2 = (JetWhenConditionIsPattern) cond2;
|
||||
|
||||
return pattern1.isNegated() == pattern2.isNegated() &&
|
||||
checkTypeReferenceMatch(pattern1.getTypeRef(), pattern2.getTypeRef());
|
||||
}
|
||||
|
||||
if (cond1 instanceof JetWhenConditionWithExpression) {
|
||||
return checkExpressionMatch(((JetWhenConditionWithExpression) cond1).getExpression(), ((JetWhenConditionWithExpression) cond2).getExpression());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean checkWhenEntryMatch(JetWhenEntry e1, JetWhenEntry e2) {
|
||||
if (e1 == e2) return true;
|
||||
if (e1 == null || e2 == null) return false;
|
||||
|
||||
if (!(e1.isElse() == e2.isElse() && checkExpressionMatch(e1.getExpression(), e2.getExpression()))) return false;
|
||||
|
||||
JetWhenCondition[] conditions1 = e1.getConditions();
|
||||
JetWhenCondition[] conditions2 = e2.getConditions();
|
||||
|
||||
int n = conditions1.length;
|
||||
if (conditions2.length != n) return false;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (!checkWhenConditionMatch(conditions1[i], conditions2[i])) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean checkExpressionMatch(JetExpression e1, JetExpression e2) {
|
||||
if (e1 == e2) return true;
|
||||
if (e1 == null || e2 == null) return false;
|
||||
|
||||
e1 = JetPsiUtil.deparenthesizeWithNoTypeResolution(e1);
|
||||
e2 = JetPsiUtil.deparenthesizeWithNoTypeResolution(e2);
|
||||
|
||||
assert e1 != null && e2 != null;
|
||||
|
||||
if (e1.getClass() != e2.getClass()) return false;
|
||||
|
||||
if (e1 instanceof JetArrayAccessExpression) {
|
||||
JetArrayAccessExpression aae1 = (JetArrayAccessExpression) e1;
|
||||
JetArrayAccessExpression aae2 = (JetArrayAccessExpression) e2;
|
||||
|
||||
if (!checkExpressionMatch(aae1.getArrayExpression(), aae2.getArrayExpression())) return false;
|
||||
|
||||
List<JetExpression> indexes1 = aae1.getIndexExpressions();
|
||||
List<JetExpression> indexes2 = aae2.getIndexExpressions();
|
||||
|
||||
int n = indexes1.size();
|
||||
if (indexes2.size() != n) return false;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (!checkExpressionMatch(indexes1.get(i), indexes2.get(i))) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (e1 instanceof JetBinaryExpression) {
|
||||
JetBinaryExpression be1 = (JetBinaryExpression) e1;
|
||||
JetBinaryExpression be2 = (JetBinaryExpression) e2;
|
||||
|
||||
return be1.getOperationToken() == be2.getOperationToken() &&
|
||||
checkExpressionMatch(be1.getLeft(), be2.getLeft()) &&
|
||||
checkExpressionMatch(be1.getRight(), be2.getRight());
|
||||
}
|
||||
|
||||
if (e1 instanceof JetBinaryExpressionWithTypeRHS) {
|
||||
JetBinaryExpressionWithTypeRHS bet1 = (JetBinaryExpressionWithTypeRHS) e1;
|
||||
JetBinaryExpressionWithTypeRHS bet2 = (JetBinaryExpressionWithTypeRHS) e2;
|
||||
|
||||
return checkExpressionMatch(bet1.getLeft(), bet2.getLeft()) &&
|
||||
checkTypeReferenceMatch(bet1.getRight(), bet2.getRight());
|
||||
}
|
||||
|
||||
if (e1 instanceof JetCallExpression) {
|
||||
JetCallExpression call1 = (JetCallExpression) e1;
|
||||
JetCallExpression call2 = (JetCallExpression) e2;
|
||||
|
||||
if (!checkExpressionMatch(call1.getCalleeExpression(), call2.getCalleeExpression())) return false;
|
||||
|
||||
List<? extends ValueArgument> args1 = call1.getValueArguments();
|
||||
List<? extends ValueArgument> args2 = call2.getValueArguments();
|
||||
|
||||
int argCount = args1.size();
|
||||
if (args2.size() != argCount) return false;
|
||||
|
||||
for (int i = 0; i < argCount; i++) {
|
||||
if (!checkExpressionMatch(args1.get(i).getArgumentExpression(), args2.get(i).getArgumentExpression())) return false;
|
||||
}
|
||||
|
||||
List<JetExpression> funLiterals1 = call1.getFunctionLiteralArguments();
|
||||
List<JetExpression> funLiterals2 = call2.getFunctionLiteralArguments();
|
||||
|
||||
int funLiteralCount = funLiterals1.size();
|
||||
if (funLiterals2.size() != funLiteralCount) return false;
|
||||
|
||||
for (int i = 0; i < argCount; i++) {
|
||||
if (!checkExpressionMatch(funLiterals1.get(i), funLiterals2.get(i))) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (e1 instanceof JetConstantExpression || e1 instanceof JetSimpleNameExpression) {
|
||||
return e1.getText().equals(e2.getText());
|
||||
}
|
||||
|
||||
if (e1 instanceof JetConstructorCalleeExpression) {
|
||||
return checkTypeReferenceMatch(((JetConstructorCalleeExpression) e1).getTypeReference(), ((JetConstructorCalleeExpression) e2).getTypeReference());
|
||||
}
|
||||
|
||||
if (e1 instanceof JetQualifiedExpression) {
|
||||
return ((JetQualifiedExpression) e1).getOperationSign() == ((JetQualifiedExpression) e2).getOperationSign() &&
|
||||
checkExpressionMatch(((JetQualifiedExpression) e1).getReceiverExpression(), ((JetQualifiedExpression) e2).getReceiverExpression()) &&
|
||||
checkExpressionMatch(((JetQualifiedExpression) e1).getSelectorExpression(), ((JetQualifiedExpression) e2).getSelectorExpression());
|
||||
}
|
||||
|
||||
if (e1 instanceof JetIfExpression) {
|
||||
return checkExpressionMatch(((JetIfExpression) e1).getCondition(), ((JetIfExpression) e2).getCondition()) &&
|
||||
checkExpressionMatch(((JetIfExpression) e1).getThen(), ((JetIfExpression) e2).getThen()) &&
|
||||
checkExpressionMatch(((JetIfExpression) e1).getElse(), ((JetIfExpression) e2).getElse());
|
||||
}
|
||||
|
||||
if (e1 instanceof JetIsExpression) {
|
||||
return checkExpressionMatch(((JetIsExpression) e1).getLeftHandSide(), ((JetIsExpression) e2).getLeftHandSide()) &&
|
||||
checkTypeReferenceMatch(((JetIsExpression) e1).getTypeRef(), ((JetIsExpression) e2).getTypeRef()) &&
|
||||
((JetIsExpression) e1).isNegated() == ((JetIsExpression) e2).isNegated();
|
||||
}
|
||||
|
||||
if (e1 instanceof JetStringTemplateExpression) {
|
||||
JetStringTemplateExpression str1 = (JetStringTemplateExpression) e1;
|
||||
JetStringTemplateExpression str2 = (JetStringTemplateExpression) e2;
|
||||
|
||||
JetStringTemplateEntry[] entries1 = str1.getEntries();
|
||||
JetStringTemplateEntry[] entries2 = str2.getEntries();
|
||||
|
||||
int n = entries1.length;
|
||||
if (entries2.length != n) return false;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (!checkStringTemplateEntryMatch(entries1[i], entries2[i])) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (e1 instanceof JetThrowExpression) {
|
||||
return checkExpressionMatch(((JetThrowExpression) e1).getThrownExpression(), ((JetThrowExpression) e2).getThrownExpression());
|
||||
}
|
||||
|
||||
if (e1 instanceof JetUnaryExpression) {
|
||||
JetUnaryExpression ue1 = (JetUnaryExpression) e1;
|
||||
JetUnaryExpression ue2 = (JetUnaryExpression) e2;
|
||||
|
||||
return checkExpressionMatch(ue1.getBaseExpression(), ue2.getBaseExpression()) &&
|
||||
checkExpressionMatch(ue1.getOperationReference(), ue2.getOperationReference());
|
||||
}
|
||||
|
||||
if (e1 instanceof JetWhenExpression) {
|
||||
JetWhenExpression when1 = (JetWhenExpression) e1;
|
||||
JetWhenExpression when2 = (JetWhenExpression) e2;
|
||||
|
||||
if (checkExpressionMatch(when1.getSubjectExpression(), when2.getSubjectExpression())) return false;
|
||||
|
||||
List<JetWhenEntry> entries1 = when1.getEntries();
|
||||
List<JetWhenEntry> entries2 = when2.getEntries();
|
||||
|
||||
int n = entries1.size();
|
||||
if (entries2.size() != n) return false;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (!checkWhenEntryMatch(entries1.get(i), entries2.get(i))) return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (e1 instanceof JetThisExpression) return true;
|
||||
|
||||
if (e1 instanceof JetSuperExpression) {
|
||||
JetSuperExpression super1 = (JetSuperExpression) e1;
|
||||
JetSuperExpression super2 = (JetSuperExpression) e2;
|
||||
|
||||
return checkTypeReferenceMatch(super1.getSuperTypeQualifier(), super2.getSuperTypeQualifier()) &&
|
||||
checkExpressionMatch(super1.getInstanceReference(), super2.getInstanceReference()) &&
|
||||
checkExpressionMatch(super1.getTargetLabel(), super2.getTargetLabel());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
when {
|
||||
n == 1 -> {
|
||||
res = "one"
|
||||
}
|
||||
n == 2 -> {
|
||||
res = "two"
|
||||
}
|
||||
else -> {
|
||||
res = "???"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
when (n) {
|
||||
1 -> {
|
||||
res = "one"
|
||||
}
|
||||
2 -> {
|
||||
res = "two"
|
||||
}
|
||||
else -> {
|
||||
res = "???"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention eliminates argument of 'when' expression transforming its pattern-matching conditions into boolean expressions
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,17 @@
|
||||
when (n) {
|
||||
1 -> {
|
||||
res = "one"
|
||||
}
|
||||
2 -> {
|
||||
res = "two"
|
||||
}
|
||||
3 -> {
|
||||
res = "three"
|
||||
}
|
||||
4 -> {
|
||||
res = "four"
|
||||
}
|
||||
else -> {
|
||||
res = "???"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
when (n) {
|
||||
1 -> {
|
||||
res = "one"
|
||||
}
|
||||
2 -> {
|
||||
res = "two"
|
||||
}
|
||||
else -> when (n) {
|
||||
3 -> {
|
||||
res = "thress"
|
||||
}
|
||||
4 -> {
|
||||
res = "four"
|
||||
}
|
||||
else -> {
|
||||
res = "???"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention merges branches of nested 'when' expression into enclosing one
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,11 @@
|
||||
when (n) {
|
||||
1 -> {
|
||||
res = "one"
|
||||
}
|
||||
2 -> {
|
||||
res = "two"
|
||||
}
|
||||
else -> {
|
||||
res = "???"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
when {
|
||||
n == 1 -> {
|
||||
res = "one"
|
||||
}
|
||||
n == 2 -> {
|
||||
res = "two"
|
||||
}
|
||||
else -> {
|
||||
res = "???"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention introduces argument into 'when' expression simplifying conditions of its branches
|
||||
</body>
|
||||
</html>
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
|
||||
public class GuardedExpression {
|
||||
@NotNull
|
||||
private final JetExpression condition;
|
||||
|
||||
@NotNull
|
||||
private final JetExpression baseExpression;
|
||||
|
||||
public GuardedExpression(@NotNull JetExpression condition, @NotNull JetExpression baseExpression) {
|
||||
this.condition = condition;
|
||||
this.baseExpression = baseExpression;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetExpression getCondition() {
|
||||
return condition;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetExpression getBaseExpression() {
|
||||
return baseExpression;
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MultiGuardedExpression {
|
||||
@NotNull
|
||||
private final List<JetExpression> conditions;
|
||||
|
||||
@NotNull
|
||||
private final JetExpression baseExpression;
|
||||
|
||||
public MultiGuardedExpression(@NotNull List<JetExpression> conditions, @NotNull JetExpression baseExpression) {
|
||||
this.conditions = conditions;
|
||||
this.baseExpression = baseExpression;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<JetExpression> getConditions() {
|
||||
return conditions;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetExpression getBaseExpression() {
|
||||
return baseExpression;
|
||||
}
|
||||
}
|
||||
+320
@@ -0,0 +1,320 @@
|
||||
package org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class WhenUtils {
|
||||
private WhenUtils() {
|
||||
}
|
||||
|
||||
public static final String TRANSFORM_WITHOUT_CHECK =
|
||||
"Expression must be checked before applying transformation";
|
||||
|
||||
private static JetExpression getWhenConditionSubjectCandidate(JetExpression condition) {
|
||||
if (condition instanceof JetIsExpression) {
|
||||
return ((JetIsExpression) condition).getLeftHandSide();
|
||||
}
|
||||
|
||||
if (condition instanceof JetBinaryExpression) {
|
||||
JetBinaryExpression binaryExpression = (JetBinaryExpression) condition;
|
||||
IElementType op = binaryExpression.getOperationToken();
|
||||
if (op == JetTokens.EQEQ || op == JetTokens.IN_KEYWORD || op == JetTokens.NOT_IN) {
|
||||
return ((JetBinaryExpression) condition).getLeft();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static JetExpression getWhenSubjectCandidate(@NotNull JetWhenExpression whenExpression) {
|
||||
if (whenExpression.getSubjectExpression() != null) return null;
|
||||
|
||||
JetExpression lastCandidate = null;
|
||||
for (JetWhenEntry entry : whenExpression.getEntries()) {
|
||||
JetWhenCondition[] conditions = entry.getConditions();
|
||||
|
||||
if (!entry.isElse() && conditions.length == 0) return null;
|
||||
|
||||
for (JetWhenCondition condition : conditions) {
|
||||
if (!(condition instanceof JetWhenConditionWithExpression)) return null;
|
||||
|
||||
JetExpression currCandidate = getWhenConditionSubjectCandidate(((JetWhenConditionWithExpression) condition).getExpression());
|
||||
|
||||
if (!(currCandidate instanceof JetSimpleNameExpression)) return null;
|
||||
|
||||
if (lastCandidate == null) {
|
||||
lastCandidate = currCandidate;
|
||||
}
|
||||
else if (!JetPsiMatcher.checkExpressionMatch(lastCandidate, currCandidate)) return null;
|
||||
}
|
||||
}
|
||||
|
||||
return lastCandidate;
|
||||
}
|
||||
|
||||
public static boolean checkFlattenWhen(@NotNull JetWhenExpression whenExpression) {
|
||||
JetExpression subject = whenExpression.getSubjectExpression();
|
||||
|
||||
if (subject != null && !(subject instanceof JetSimpleNameExpression)) return false;
|
||||
|
||||
if (!JetPsiUtil.checkWhenExpressionHasSingleElse(whenExpression)) return false;
|
||||
|
||||
JetExpression elseBranch = JetPsiUtil.getWhenElseBranch(whenExpression);
|
||||
if (!(elseBranch instanceof JetWhenExpression)) return false;
|
||||
|
||||
JetWhenExpression nestedWhenExpression = (JetWhenExpression) elseBranch;
|
||||
|
||||
return JetPsiUtil.checkWhenExpressionHasSingleElse(nestedWhenExpression) &&
|
||||
JetPsiMatcher.checkExpressionMatch(subject, nestedWhenExpression.getSubjectExpression());
|
||||
}
|
||||
|
||||
public static boolean checkIntroduceWhenSubject(@NotNull JetWhenExpression whenExpression) {
|
||||
return getWhenSubjectCandidate(whenExpression) != null;
|
||||
}
|
||||
|
||||
public static boolean checkEliminateWhenSubject(@NotNull JetWhenExpression whenExpression) {
|
||||
return whenExpression.getSubjectExpression() instanceof JetSimpleNameExpression;
|
||||
}
|
||||
|
||||
public static void flattenWhen(@NotNull JetWhenExpression whenExpression) {
|
||||
JetExpression subjectExpression = whenExpression.getSubjectExpression();
|
||||
boolean hasSubject = subjectExpression != null;
|
||||
|
||||
JetExpression elseBranch = JetPsiUtil.getWhenElseBranch(whenExpression);
|
||||
assert elseBranch instanceof JetWhenExpression : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
JetWhenExpression nestedWhenExpression = (JetWhenExpression) elseBranch;
|
||||
|
||||
List<JetWhenEntry> outerEntries = whenExpression.getEntries();
|
||||
List<JetWhenEntry> innerEntries = nestedWhenExpression.getEntries();
|
||||
|
||||
JetWhenExpression newWhenExpression = new JetPsiFactory.WhenTemplateBuilder(hasSubject)
|
||||
.addBranchesWithSingleCondition(outerEntries.size() + innerEntries.size() - 2)
|
||||
.toExpression(whenExpression.getProject());
|
||||
|
||||
if (hasSubject) {
|
||||
JetExpression dummySubjectExpression = newWhenExpression.getSubjectExpression();
|
||||
assert dummySubjectExpression != null : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
dummySubjectExpression.replace(subjectExpression);
|
||||
}
|
||||
|
||||
List<JetWhenEntry> newEntries = newWhenExpression.getEntries();
|
||||
|
||||
int i = 0;
|
||||
for (JetWhenEntry entry : outerEntries) {
|
||||
if (!entry.isElse()) {
|
||||
newEntries.get(i++).replace(entry);
|
||||
}
|
||||
}
|
||||
for (JetWhenEntry entry : innerEntries) {
|
||||
newEntries.get(i++).replace(entry);
|
||||
}
|
||||
|
||||
whenExpression.replace(newWhenExpression);
|
||||
}
|
||||
|
||||
private static JetWhenExpression createWhenTemplateWithSubject(@NotNull JetWhenExpression whenExpression) {
|
||||
JetPsiFactory.WhenTemplateBuilder builder = new JetPsiFactory.WhenTemplateBuilder(true);
|
||||
|
||||
for (JetWhenEntry entry : whenExpression.getEntries()) {
|
||||
if (entry.isElse()) continue;
|
||||
|
||||
for (JetWhenCondition condition : entry.getConditions()) {
|
||||
assert condition instanceof JetWhenConditionWithExpression : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
JetExpression conditionExpression = ((JetWhenConditionWithExpression) condition).getExpression();
|
||||
|
||||
if (conditionExpression instanceof JetIsExpression) {
|
||||
builder.addIsCondition(((JetIsExpression) conditionExpression).isNegated());
|
||||
}
|
||||
else if (conditionExpression instanceof JetBinaryExpression) {
|
||||
JetBinaryExpression binaryExpression = (JetBinaryExpression) conditionExpression;
|
||||
|
||||
IElementType op = binaryExpression.getOperationToken();
|
||||
if (op == JetTokens.IN_KEYWORD) {
|
||||
builder.addInCondition(false);
|
||||
}
|
||||
else if (op == JetTokens.NOT_IN) {
|
||||
builder.addInCondition(true);
|
||||
}
|
||||
else if (op == JetTokens.EQEQ) {
|
||||
builder.addExpressionCondition();
|
||||
}
|
||||
else assert false : TRANSFORM_WITHOUT_CHECK;
|
||||
}
|
||||
else assert false : TRANSFORM_WITHOUT_CHECK;
|
||||
}
|
||||
|
||||
builder.finishBranch();
|
||||
}
|
||||
|
||||
return builder.toExpression(whenExpression.getProject());
|
||||
}
|
||||
|
||||
public static void introduceWhenSubject(@NotNull JetWhenExpression whenExpression) {
|
||||
JetExpression subject = getWhenSubjectCandidate(whenExpression);
|
||||
assert subject != null : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
JetWhenExpression newWhenExpression = createWhenTemplateWithSubject(whenExpression);
|
||||
|
||||
JetExpression newSubject = newWhenExpression.getSubjectExpression();
|
||||
assert newSubject != null : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
newSubject.replace(subject);
|
||||
|
||||
int i = 0;
|
||||
List<JetWhenEntry> entries = whenExpression.getEntries();
|
||||
List<JetWhenEntry> newEntries = newWhenExpression.getEntries();
|
||||
for (JetWhenEntry newEntry : newEntries) {
|
||||
JetWhenEntry entry = entries.get(i++);
|
||||
|
||||
JetExpression branchExpression = entry.getExpression();
|
||||
assert branchExpression != null : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
JetExpression newBranchExpression = newEntry.getExpression();
|
||||
assert newBranchExpression != null : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
newBranchExpression.replace(branchExpression);
|
||||
|
||||
int j = 0;
|
||||
JetWhenCondition[] conditions = entry.getConditions();
|
||||
JetWhenCondition[] newConditions = newEntry.getConditions();
|
||||
|
||||
for (JetWhenCondition newCondition : newConditions) {
|
||||
JetWhenCondition condition = conditions[j++];
|
||||
|
||||
assert condition instanceof JetWhenConditionWithExpression : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
JetExpression conditionExpression = ((JetWhenConditionWithExpression) condition).getExpression();
|
||||
|
||||
if (conditionExpression instanceof JetIsExpression) {
|
||||
assert newCondition instanceof JetWhenConditionIsPattern : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
JetTypeReference typeReference = ((JetIsExpression) conditionExpression).getTypeRef();
|
||||
assert typeReference != null : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
JetTypeReference newTypeReference = ((JetWhenConditionIsPattern) newCondition).getTypeRef();
|
||||
assert newTypeReference != null : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
newTypeReference.replace(typeReference);
|
||||
}
|
||||
else if (conditionExpression instanceof JetBinaryExpression) {
|
||||
JetBinaryExpression binaryExpression = (JetBinaryExpression) conditionExpression;
|
||||
|
||||
JetExpression rhs = binaryExpression.getRight();
|
||||
assert rhs != null : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
IElementType op = binaryExpression.getOperationToken();
|
||||
if (op == JetTokens.IN_KEYWORD || op == JetTokens.NOT_IN) {
|
||||
assert newCondition instanceof JetWhenConditionInRange : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
JetExpression newRangeExpression = ((JetWhenConditionInRange) newCondition).getRangeExpression();
|
||||
assert newRangeExpression != null : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
newRangeExpression.replace(rhs);
|
||||
}
|
||||
else if (op == JetTokens.EQEQ) {
|
||||
assert newCondition instanceof JetWhenConditionWithExpression : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
JetExpression newConditionExpression = ((JetWhenConditionWithExpression) newCondition).getExpression();
|
||||
assert newConditionExpression != null : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
newConditionExpression.replace(rhs);
|
||||
}
|
||||
else assert false : TRANSFORM_WITHOUT_CHECK;
|
||||
}
|
||||
else assert false : TRANSFORM_WITHOUT_CHECK;
|
||||
}
|
||||
}
|
||||
|
||||
whenExpression.replace(newWhenExpression);
|
||||
}
|
||||
|
||||
private static JetWhenExpression createWhenTemplateWithoutSubject(@NotNull JetWhenExpression whenExpression) {
|
||||
JetPsiFactory.WhenTemplateBuilder builder = new JetPsiFactory.WhenTemplateBuilder(false);
|
||||
|
||||
for (JetWhenEntry entry : whenExpression.getEntries()) {
|
||||
if (!entry.isElse()) {
|
||||
builder.addBranchWithMultiCondition(entry.getConditions().length);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.toExpression(whenExpression.getProject());
|
||||
}
|
||||
|
||||
static JetExpression whenConditionToExpression(@NotNull JetWhenCondition condition, JetExpression subject) {
|
||||
Project project = condition.getProject();
|
||||
|
||||
if (condition instanceof JetWhenConditionIsPattern) {
|
||||
JetWhenConditionIsPattern patternCondition = (JetWhenConditionIsPattern) condition;
|
||||
|
||||
JetTypeReference typeReference = patternCondition.getTypeRef();
|
||||
assert typeReference != null : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
assert subject != null : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
return JetPsiFactory.createIsExpression(project, subject, typeReference, patternCondition.isNegated());
|
||||
}
|
||||
|
||||
if (condition instanceof JetWhenConditionInRange) {
|
||||
JetWhenConditionInRange rangeCondition = (JetWhenConditionInRange) condition;
|
||||
|
||||
JetExpression rangeExpression = rangeCondition.getRangeExpression();
|
||||
assert rangeExpression != null : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
assert subject != null : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
return JetPsiFactory.createBinaryExpression(project, subject, rangeCondition.getOperationReference().getText(), rangeExpression);
|
||||
}
|
||||
|
||||
assert condition instanceof JetWhenConditionWithExpression : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
JetExpression conditionExpression = ((JetWhenConditionWithExpression) condition).getExpression();
|
||||
assert conditionExpression != null : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
return subject != null ? JetPsiFactory.createBinaryExpression(project, subject, "==", conditionExpression) : conditionExpression;
|
||||
}
|
||||
|
||||
public static void eliminateWhenSubject(@NotNull JetWhenExpression whenExpression) {
|
||||
JetExpression subject = whenExpression.getSubjectExpression();
|
||||
assert subject != null : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
JetWhenExpression newWhenExpression = createWhenTemplateWithoutSubject(whenExpression);
|
||||
|
||||
int i = 0;
|
||||
List<JetWhenEntry> entries = whenExpression.getEntries();
|
||||
List<JetWhenEntry> newEntries = newWhenExpression.getEntries();
|
||||
for (JetWhenEntry newEntry : newEntries) {
|
||||
JetWhenEntry entry = entries.get(i++);
|
||||
|
||||
JetExpression branchExpression = entry.getExpression();
|
||||
assert branchExpression != null : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
JetExpression newBranchExpression = newEntry.getExpression();
|
||||
assert newBranchExpression != null : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
newBranchExpression.replace(branchExpression);
|
||||
|
||||
int j = 0;
|
||||
JetWhenCondition[] conditions = entry.getConditions();
|
||||
JetWhenCondition[] newConditions = newEntry.getConditions();
|
||||
|
||||
for (JetWhenCondition newCondition : newConditions) {
|
||||
JetWhenCondition condition = conditions[j++];
|
||||
|
||||
JetExpression newConditionExpression = ((JetWhenConditionWithExpression) newCondition).getExpression();
|
||||
assert newConditionExpression != null : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
newConditionExpression.replace(whenConditionToExpression(condition, subject));
|
||||
}
|
||||
}
|
||||
|
||||
whenExpression.replace(newWhenExpression);
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetWhenExpression;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.AbstractCodeTransformationIntention;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.WhenUtils;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.core.Transformer;
|
||||
|
||||
public class EliminateWhenSubjectIntention extends AbstractCodeTransformationIntention<Transformer> {
|
||||
private static final Transformer TRANSFORMER = new Transformer() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getKey() {
|
||||
return "eliminate.when.subject";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(@NotNull PsiElement element) {
|
||||
WhenUtils.eliminateWhenSubject((JetWhenExpression) element);
|
||||
}
|
||||
};
|
||||
|
||||
private static final Predicate<PsiElement> IS_APPLICABLE = new Predicate<PsiElement>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable PsiElement input) {
|
||||
return input instanceof JetWhenExpression && WhenUtils.checkEliminateWhenSubject((JetWhenExpression) input);
|
||||
}
|
||||
};
|
||||
|
||||
public EliminateWhenSubjectIntention() {
|
||||
super(TRANSFORMER, IS_APPLICABLE);
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetWhenExpression;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.AbstractCodeTransformationIntention;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.WhenUtils;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.core.Transformer;
|
||||
|
||||
public class FlattenWhenIntention extends AbstractCodeTransformationIntention<Transformer> {
|
||||
private static final Transformer TRANSFORMER = new Transformer() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getKey() {
|
||||
return "flatten.when";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(@NotNull PsiElement element) {
|
||||
WhenUtils.flattenWhen((JetWhenExpression) element);
|
||||
}
|
||||
};
|
||||
|
||||
private static final Predicate<PsiElement> IS_APPLICABLE = new Predicate<PsiElement>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable PsiElement input) {
|
||||
return input instanceof JetWhenExpression && WhenUtils.checkFlattenWhen((JetWhenExpression) input);
|
||||
}
|
||||
};
|
||||
|
||||
public FlattenWhenIntention() {
|
||||
super(TRANSFORMER, IS_APPLICABLE);
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetWhenExpression;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.AbstractCodeTransformationIntention;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.WhenUtils;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.core.Transformer;
|
||||
|
||||
public class IntroduceWhenSubjectIntention extends AbstractCodeTransformationIntention<Transformer> {
|
||||
private static final Transformer TRANSFORMER = new Transformer() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getKey() {
|
||||
return "introduce.when.subject";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(@NotNull PsiElement element) {
|
||||
WhenUtils.introduceWhenSubject((JetWhenExpression) element);
|
||||
}
|
||||
};
|
||||
|
||||
private static final Predicate<PsiElement> IS_APPLICABLE = new Predicate<PsiElement>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable PsiElement input) {
|
||||
return input instanceof JetWhenExpression && WhenUtils.checkIntroduceWhenSubject((JetWhenExpression) input);
|
||||
}
|
||||
};
|
||||
|
||||
public IntroduceWhenSubjectIntention() {
|
||||
super(TRANSFORMER, IS_APPLICABLE);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user