Minimize update operations on active PSI and move them to the last phase

This commit is contained in:
Alexey Sedunov
2013-04-17 16:35:50 +04:00
parent 2ba806bee8
commit fe3d749257
2 changed files with 72 additions and 64 deletions
@@ -61,11 +61,11 @@ public class BranchedFoldingUtils {
} }
}; };
private static JetBinaryExpression checkAndGetFoldableBranchedAssignment(JetExpression branch) { private static JetBinaryExpression getFoldableBranchedAssignment(JetExpression branch) {
return (JetBinaryExpression)JetPsiUtil.getOutermostLastBlockElement(branch, CHECK_ASSIGNMENT); return (JetBinaryExpression)JetPsiUtil.getOutermostLastBlockElement(branch, CHECK_ASSIGNMENT);
} }
private static JetReturnExpression checkAndGetFoldableBranchedReturn(JetExpression branch) { private static JetReturnExpression getFoldableBranchedReturn(JetExpression branch) {
return (JetReturnExpression)JetPsiUtil.getOutermostLastBlockElement(branch, CHECK_RETURN); return (JetReturnExpression)JetPsiUtil.getOutermostLastBlockElement(branch, CHECK_RETURN);
} }
@@ -77,8 +77,8 @@ public class BranchedFoldingUtils {
JetExpression thenBranch = ifExpression.getThen(); JetExpression thenBranch = ifExpression.getThen();
JetExpression elseBranch = ifExpression.getElse(); JetExpression elseBranch = ifExpression.getElse();
JetBinaryExpression thenAssignment = checkAndGetFoldableBranchedAssignment(thenBranch); JetBinaryExpression thenAssignment = getFoldableBranchedAssignment(thenBranch);
JetBinaryExpression elseAssignment = checkAndGetFoldableBranchedAssignment(elseBranch); JetBinaryExpression elseAssignment = getFoldableBranchedAssignment(elseBranch);
if (thenAssignment == null || elseAssignment == null) return false; if (thenAssignment == null || elseAssignment == null) return false;
@@ -94,7 +94,7 @@ public class BranchedFoldingUtils {
List<JetBinaryExpression> assignments = new ArrayList<JetBinaryExpression>(); List<JetBinaryExpression> assignments = new ArrayList<JetBinaryExpression>();
for (JetWhenEntry entry : entries) { for (JetWhenEntry entry : entries) {
JetBinaryExpression assignment = checkAndGetFoldableBranchedAssignment(entry.getExpression()); JetBinaryExpression assignment = getFoldableBranchedAssignment(entry.getExpression());
if (assignment == null) return false; if (assignment == null) return false;
assignments.add(assignment); assignments.add(assignment);
} }
@@ -110,8 +110,8 @@ public class BranchedFoldingUtils {
} }
private static boolean checkFoldableIfExpressionWithReturns(JetIfExpression ifExpression) { private static boolean checkFoldableIfExpressionWithReturns(JetIfExpression ifExpression) {
return checkAndGetFoldableBranchedReturn(ifExpression.getThen()) != null && return getFoldableBranchedReturn(ifExpression.getThen()) != null &&
checkAndGetFoldableBranchedReturn(ifExpression.getElse()) != null; getFoldableBranchedReturn(ifExpression.getElse()) != null;
} }
private static boolean checkFoldableWhenExpressionWithReturns(JetWhenExpression whenExpression) { private static boolean checkFoldableWhenExpressionWithReturns(JetWhenExpression whenExpression) {
@@ -122,20 +122,20 @@ public class BranchedFoldingUtils {
if (entries.isEmpty()) return false; if (entries.isEmpty()) return false;
for (JetWhenEntry entry : entries) { for (JetWhenEntry entry : entries) {
if (checkAndGetFoldableBranchedReturn(entry.getExpression()) == null) return false; if (getFoldableBranchedReturn(entry.getExpression()) == null) return false;
} }
return true; return true;
} }
private static boolean checkFoldableIfExpressionWithAsymmetricReturns(JetIfExpression ifExpression) { private static boolean checkFoldableIfExpressionWithAsymmetricReturns(JetIfExpression ifExpression) {
if (checkAndGetFoldableBranchedReturn(ifExpression.getThen()) == null || if (getFoldableBranchedReturn(ifExpression.getThen()) == null ||
ifExpression.getElse() != null) { ifExpression.getElse() != null) {
return false; return false;
} }
PsiElement nextElement = JetPsiUtil.skipTrailingWhitespacesAndComments(ifExpression); PsiElement nextElement = JetPsiUtil.skipTrailingWhitespacesAndComments(ifExpression);
return (nextElement instanceof JetExpression) && checkAndGetFoldableBranchedReturn((JetExpression)nextElement) != null; return (nextElement instanceof JetExpression) && getFoldableBranchedReturn((JetExpression) nextElement) != null;
} }
@Nullable @Nullable
@@ -161,21 +161,20 @@ public class BranchedFoldingUtils {
public static void foldIfExpressionWithAssignments(JetIfExpression ifExpression) { public static void foldIfExpressionWithAssignments(JetIfExpression ifExpression) {
Project project = ifExpression.getProject(); Project project = ifExpression.getProject();
JetBinaryExpression thenAssignment = checkAndGetFoldableBranchedAssignment(ifExpression.getThen()); JetBinaryExpression thenAssignment = getFoldableBranchedAssignment(ifExpression.getThen());
assert thenAssignment != null : FOLD_WITHOUT_CHECK; assert thenAssignment != null : FOLD_WITHOUT_CHECK;
String op = thenAssignment.getOperationReference().getText(); String op = thenAssignment.getOperationReference().getText();
JetSimpleNameExpression lhs = (JetSimpleNameExpression) thenAssignment.getLeft(); JetSimpleNameExpression lhs = (JetSimpleNameExpression) thenAssignment.getLeft();
JetBinaryExpression assignment = JetBinaryExpression assignment = JetPsiFactory.createBinaryExpression(project, lhs, op, ifExpression);
(JetBinaryExpression)ifExpression.replace(JetPsiFactory.createBinaryExpression(project, lhs, op, ifExpression)); JetIfExpression newIfExpression = (JetIfExpression)assignment.getRight();
ifExpression = (JetIfExpression)assignment.getRight();
assert ifExpression != null : FOLD_WITHOUT_CHECK; assert newIfExpression != null : FOLD_WITHOUT_CHECK;
thenAssignment = checkAndGetFoldableBranchedAssignment(ifExpression.getThen()); thenAssignment = getFoldableBranchedAssignment(newIfExpression.getThen());
JetBinaryExpression elseAssignment = checkAndGetFoldableBranchedAssignment(ifExpression.getElse()); JetBinaryExpression elseAssignment = getFoldableBranchedAssignment(newIfExpression.getElse());
assert thenAssignment != null : FOLD_WITHOUT_CHECK; assert thenAssignment != null : FOLD_WITHOUT_CHECK;
assert elseAssignment != null : FOLD_WITHOUT_CHECK; assert elseAssignment != null : FOLD_WITHOUT_CHECK;
@@ -188,18 +187,20 @@ public class BranchedFoldingUtils {
thenAssignment.replace(thenRhs); thenAssignment.replace(thenRhs);
elseAssignment.replace(elseRhs); elseAssignment.replace(elseRhs);
ifExpression.replace(assignment);
} }
public static void foldIfExpressionWithReturns(JetIfExpression ifExpression) { public static void foldIfExpressionWithReturns(JetIfExpression ifExpression) {
Project project = ifExpression.getProject(); Project project = ifExpression.getProject();
JetReturnExpression returnExpr = (JetReturnExpression)ifExpression.replace(JetPsiFactory.createReturn(project, ifExpression)); JetReturnExpression newReturnExpression = JetPsiFactory.createReturn(project, ifExpression);
ifExpression = (JetIfExpression)returnExpr.getReturnedExpression(); JetIfExpression newIfExpression = (JetIfExpression)newReturnExpression.getReturnedExpression();
assert ifExpression != null : FOLD_WITHOUT_CHECK; assert newIfExpression != null;
JetReturnExpression thenReturn = checkAndGetFoldableBranchedReturn(ifExpression.getThen()); JetReturnExpression thenReturn = getFoldableBranchedReturn(newIfExpression.getThen());
JetReturnExpression elseReturn = checkAndGetFoldableBranchedReturn(ifExpression.getElse()); JetReturnExpression elseReturn = getFoldableBranchedReturn(newIfExpression.getElse());
assert thenReturn != null : FOLD_WITHOUT_CHECK; assert thenReturn != null : FOLD_WITHOUT_CHECK;
assert elseReturn != null : FOLD_WITHOUT_CHECK; assert elseReturn != null : FOLD_WITHOUT_CHECK;
@@ -212,6 +213,8 @@ public class BranchedFoldingUtils {
thenReturn.replace(thenExpr); thenReturn.replace(thenExpr);
elseReturn.replace(elseExpr); elseReturn.replace(elseExpr);
ifExpression.replace(newReturnExpression);
} }
public static void foldIfExpressionWithAsymmetricReturns(JetIfExpression ifExpression) { public static void foldIfExpressionWithAsymmetricReturns(JetIfExpression ifExpression) {
@@ -225,22 +228,15 @@ public class BranchedFoldingUtils {
assert thenRoot != null : FOLD_WITHOUT_CHECK; assert thenRoot != null : FOLD_WITHOUT_CHECK;
assert elseRoot != null : FOLD_WITHOUT_CHECK; assert elseRoot != null : FOLD_WITHOUT_CHECK;
JetIfExpression newIfExpr = JetPsiFactory.createIf(project, condition, thenRoot, elseRoot); JetIfExpression newIfExpression = JetPsiFactory.createIf(project, condition, thenRoot, elseRoot);
JetReturnExpression newReturnExpr = JetPsiFactory.createReturn(project, newIfExpr); JetReturnExpression newReturnExpression = JetPsiFactory.createReturn(project, newIfExpression);
newReturnExpr = (JetReturnExpression) ifExpression.replace(newReturnExpr);
JetReturnExpression oldReturn = (JetReturnExpression)JetPsiUtil.skipTrailingWhitespacesAndComments(newReturnExpr); newIfExpression = (JetIfExpression)newReturnExpression.getReturnedExpression();
assert oldReturn != null : FOLD_WITHOUT_CHECK; assert newIfExpression != null : FOLD_WITHOUT_CHECK;
oldReturn.delete(); JetReturnExpression thenReturn = getFoldableBranchedReturn(newIfExpression.getThen());
JetReturnExpression elseReturn = getFoldableBranchedReturn(newIfExpression.getElse());
newIfExpr = (JetIfExpression)newReturnExpr.getReturnedExpression();
assert newIfExpr != null : FOLD_WITHOUT_CHECK;
JetReturnExpression thenReturn = checkAndGetFoldableBranchedReturn(newIfExpr.getThen());
JetReturnExpression elseReturn = checkAndGetFoldableBranchedReturn(newIfExpr.getElse());
assert thenReturn != null : FOLD_WITHOUT_CHECK; assert thenReturn != null : FOLD_WITHOUT_CHECK;
assert elseReturn != null : FOLD_WITHOUT_CHECK; assert elseReturn != null : FOLD_WITHOUT_CHECK;
@@ -253,6 +249,9 @@ public class BranchedFoldingUtils {
thenReturn.replace(thenExpr); thenReturn.replace(thenExpr);
elseReturn.replace(elseExpr); elseReturn.replace(elseExpr);
elseRoot.delete();
ifExpression.replace(newReturnExpression);
} }
public static void foldWhenExpressionWithAssignments(JetWhenExpression whenExpression) { public static void foldWhenExpressionWithAssignments(JetWhenExpression whenExpression) {
@@ -260,21 +259,20 @@ public class BranchedFoldingUtils {
assert !whenExpression.getEntries().isEmpty() : FOLD_WITHOUT_CHECK; assert !whenExpression.getEntries().isEmpty() : FOLD_WITHOUT_CHECK;
JetBinaryExpression firstAssignment = checkAndGetFoldableBranchedAssignment(whenExpression.getEntries().get(0).getExpression()); JetBinaryExpression firstAssignment = getFoldableBranchedAssignment(whenExpression.getEntries().get(0).getExpression());
assert firstAssignment != null : FOLD_WITHOUT_CHECK; assert firstAssignment != null : FOLD_WITHOUT_CHECK;
String op = firstAssignment.getOperationReference().getText(); String op = firstAssignment.getOperationReference().getText();
JetSimpleNameExpression lhs = (JetSimpleNameExpression) firstAssignment.getLeft(); JetSimpleNameExpression lhs = (JetSimpleNameExpression) firstAssignment.getLeft();
JetBinaryExpression assignment = JetBinaryExpression assignment = JetPsiFactory.createBinaryExpression(project, lhs, op, whenExpression);
(JetBinaryExpression)whenExpression.replace(JetPsiFactory.createBinaryExpression(project, lhs, op, whenExpression)); JetWhenExpression newWhenExpression = (JetWhenExpression)assignment.getRight();
whenExpression = (JetWhenExpression)assignment.getRight();
assert whenExpression != null : FOLD_WITHOUT_CHECK; assert newWhenExpression != null : FOLD_WITHOUT_CHECK;
for (JetWhenEntry entry : whenExpression.getEntries()) { for (JetWhenEntry entry : newWhenExpression.getEntries()) {
JetBinaryExpression currAssignment = checkAndGetFoldableBranchedAssignment(entry.getExpression()); JetBinaryExpression currAssignment = getFoldableBranchedAssignment(entry.getExpression());
assert currAssignment != null : FOLD_WITHOUT_CHECK; assert currAssignment != null : FOLD_WITHOUT_CHECK;
@@ -284,6 +282,8 @@ public class BranchedFoldingUtils {
currAssignment.replace(currRhs); currAssignment.replace(currRhs);
} }
whenExpression.replace(assignment);
} }
public static void foldWhenExpressionWithReturns(JetWhenExpression whenExpression) { public static void foldWhenExpressionWithReturns(JetWhenExpression whenExpression) {
@@ -291,13 +291,13 @@ public class BranchedFoldingUtils {
assert !whenExpression.getEntries().isEmpty() : FOLD_WITHOUT_CHECK; assert !whenExpression.getEntries().isEmpty() : FOLD_WITHOUT_CHECK;
JetReturnExpression returnExpr = (JetReturnExpression)whenExpression.replace(JetPsiFactory.createReturn(project, whenExpression)); JetReturnExpression newReturnExpression = JetPsiFactory.createReturn(project, whenExpression);
whenExpression = (JetWhenExpression)returnExpr.getReturnedExpression(); JetWhenExpression newWhenExpression = (JetWhenExpression)newReturnExpression.getReturnedExpression();
assert whenExpression != null : FOLD_WITHOUT_CHECK; assert newWhenExpression != null : FOLD_WITHOUT_CHECK;
for (JetWhenEntry entry : whenExpression.getEntries()) { for (JetWhenEntry entry : newWhenExpression.getEntries()) {
JetReturnExpression currReturn = checkAndGetFoldableBranchedReturn(entry.getExpression()); JetReturnExpression currReturn = getFoldableBranchedReturn(entry.getExpression());
assert currReturn != null : FOLD_WITHOUT_CHECK; assert currReturn != null : FOLD_WITHOUT_CHECK;
@@ -307,5 +307,7 @@ public class BranchedFoldingUtils {
currReturn.replace(currExpr); currReturn.replace(currExpr);
} }
whenExpression.replace(newReturnExpression);
} }
} }
@@ -16,9 +16,7 @@
package org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations; package org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations;
import com.google.common.base.Predicate;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
@@ -59,40 +57,44 @@ public class BranchedUnfoldingUtils {
public static void unfoldAssignmentToIf(@NotNull JetBinaryExpression assignment) { public static void unfoldAssignmentToIf(@NotNull JetBinaryExpression assignment) {
Project project = assignment.getProject(); Project project = assignment.getProject();
String op = assignment.getOperationReference().getText(); String op = assignment.getOperationReference().getText();
String lhsText = assignment.getLeft().getText(); JetExpression lhs = assignment.getLeft();
JetIfExpression ifExpression = (JetIfExpression)assignment.getRight(); JetIfExpression ifExpression = (JetIfExpression)assignment.getRight();
assert ifExpression != null : UNFOLD_WITHOUT_CHECK; assert ifExpression != null : UNFOLD_WITHOUT_CHECK;
ifExpression = (JetIfExpression)assignment.replace(ifExpression); JetIfExpression newIfExpression = (JetIfExpression) ifExpression.copy();
JetExpression thenExpr = getOutermostLastBlockElement(ifExpression.getThen()); JetExpression thenExpr = getOutermostLastBlockElement(newIfExpression.getThen());
JetExpression elseExpr = getOutermostLastBlockElement(ifExpression.getElse()); JetExpression elseExpr = getOutermostLastBlockElement(newIfExpression.getElse());
assert thenExpr != null : UNFOLD_WITHOUT_CHECK; assert thenExpr != null : UNFOLD_WITHOUT_CHECK;
assert elseExpr != null : UNFOLD_WITHOUT_CHECK; assert elseExpr != null : UNFOLD_WITHOUT_CHECK;
thenExpr.replace(JetPsiFactory.createBinaryExpression(project, JetPsiFactory.createExpression(project, lhsText), op, thenExpr)); thenExpr.replace(JetPsiFactory.createBinaryExpression(project, lhs, op, thenExpr));
elseExpr.replace(JetPsiFactory.createBinaryExpression(project, JetPsiFactory.createExpression(project, lhsText), op, elseExpr)); elseExpr.replace(JetPsiFactory.createBinaryExpression(project, lhs, op, elseExpr));
assignment.replace(newIfExpression);
} }
public static void unfoldAssignmentToWhen(@NotNull JetBinaryExpression assignment) { public static void unfoldAssignmentToWhen(@NotNull JetBinaryExpression assignment) {
Project project = assignment.getProject(); Project project = assignment.getProject();
String op = assignment.getOperationReference().getText(); String op = assignment.getOperationReference().getText();
String lhsText = assignment.getLeft().getText(); JetExpression lhs = assignment.getLeft();
JetWhenExpression whenExpression = (JetWhenExpression)assignment.getRight(); JetWhenExpression whenExpression = (JetWhenExpression)assignment.getRight();
assert whenExpression != null : UNFOLD_WITHOUT_CHECK; assert whenExpression != null : UNFOLD_WITHOUT_CHECK;
whenExpression = (JetWhenExpression)assignment.replace(whenExpression); JetWhenExpression newWhenExpression = (JetWhenExpression) whenExpression.copy();
for (JetWhenEntry entry : whenExpression.getEntries()) { for (JetWhenEntry entry : newWhenExpression.getEntries()) {
JetExpression currExpr = getOutermostLastBlockElement(entry.getExpression()); JetExpression currExpr = getOutermostLastBlockElement(entry.getExpression());
assert currExpr != null : UNFOLD_WITHOUT_CHECK; assert currExpr != null : UNFOLD_WITHOUT_CHECK;
currExpr.replace(JetPsiFactory.createBinaryExpression(project, JetPsiFactory.createExpression(project, lhsText), op, currExpr)); currExpr.replace(JetPsiFactory.createBinaryExpression(project, lhs, op, currExpr));
} }
assignment.replace(newWhenExpression);
} }
public static void unfoldReturnToIf(@NotNull JetReturnExpression returnExpression) { public static void unfoldReturnToIf(@NotNull JetReturnExpression returnExpression) {
@@ -101,16 +103,18 @@ public class BranchedUnfoldingUtils {
assert ifExpression != null : UNFOLD_WITHOUT_CHECK; assert ifExpression != null : UNFOLD_WITHOUT_CHECK;
ifExpression = (JetIfExpression)returnExpression.replace(ifExpression); JetIfExpression newIfExpression = (JetIfExpression) ifExpression.copy();
JetExpression thenExpr = getOutermostLastBlockElement(ifExpression.getThen()); JetExpression thenExpr = getOutermostLastBlockElement(newIfExpression.getThen());
JetExpression elseExpr = getOutermostLastBlockElement(ifExpression.getElse()); JetExpression elseExpr = getOutermostLastBlockElement(newIfExpression.getElse());
assert thenExpr != null : UNFOLD_WITHOUT_CHECK; assert thenExpr != null : UNFOLD_WITHOUT_CHECK;
assert elseExpr != null : UNFOLD_WITHOUT_CHECK; assert elseExpr != null : UNFOLD_WITHOUT_CHECK;
thenExpr.replace(JetPsiFactory.createReturn(project, thenExpr)); thenExpr.replace(JetPsiFactory.createReturn(project, thenExpr));
elseExpr.replace(JetPsiFactory.createReturn(project, elseExpr)); elseExpr.replace(JetPsiFactory.createReturn(project, elseExpr));
returnExpression.replace(newIfExpression);
} }
public static void unfoldReturnToWhen(@NotNull JetReturnExpression returnExpression) { public static void unfoldReturnToWhen(@NotNull JetReturnExpression returnExpression) {
@@ -119,14 +123,16 @@ public class BranchedUnfoldingUtils {
assert whenExpression != null : UNFOLD_WITHOUT_CHECK; assert whenExpression != null : UNFOLD_WITHOUT_CHECK;
whenExpression = (JetWhenExpression)returnExpression.replace(whenExpression); JetWhenExpression newWhenExpression = (JetWhenExpression) whenExpression.copy();
for (JetWhenEntry entry : whenExpression.getEntries()) { for (JetWhenEntry entry : newWhenExpression.getEntries()) {
JetExpression currExpr = getOutermostLastBlockElement(entry.getExpression()); JetExpression currExpr = getOutermostLastBlockElement(entry.getExpression());
assert currExpr != null : UNFOLD_WITHOUT_CHECK; assert currExpr != null : UNFOLD_WITHOUT_CHECK;
currExpr.replace(JetPsiFactory.createReturn(project, currExpr)); currExpr.replace(JetPsiFactory.createReturn(project, currExpr));
} }
returnExpression.replace(newWhenExpression);
} }
} }