diff --git a/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodProcessor.java index 91c900926e6f..633a955f4809 100644 --- a/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodProcessor.java @@ -16,10 +16,9 @@ package com.intellij.refactoring.convertToInstanceMethod; import com.intellij.codeInsight.ChangeContextUtil; -import com.intellij.history.LocalHistory; -import com.intellij.history.LocalHistoryAction; import com.intellij.ide.util.EditorHelper; import com.intellij.java.refactoring.JavaRefactoringBundle; +import com.intellij.model.ModelBranch; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; @@ -41,6 +40,7 @@ import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; import com.intellij.util.IncorrectOperationException; import com.intellij.util.VisibilityUtil; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -50,7 +50,7 @@ import java.util.*; /** * @author dsl */ -public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor { +public final class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor { private static final Logger LOG = Logger.getInstance(ConvertToInstanceMethodProcessor.class); private PsiMethod myMethod; @@ -220,21 +220,55 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor { return showConflicts(conflicts, usagesIn); } + @Override - protected void performRefactoring(UsageInfo @NotNull [] usages) { - LocalHistoryAction a = LocalHistory.getInstance().startAction(getCommandName()); - try { - doRefactoring(usages); - } - catch (IncorrectOperationException e) { - LOG.error(e); - } - finally { - a.finish(); - } + protected boolean canPerformRefactoringInBranch() { + return true; } - private void doRefactoring(UsageInfo[] usages) throws IncorrectOperationException { + @Override + protected void performRefactoringInBranch(UsageInfo @NotNull [] usages, ModelBranch branch) { + ConvertToInstanceMethodProcessor processor = new ConvertToInstanceMethodProcessor( + myProject, branch.obtainPsiCopy(myMethod), + myTargetParameter == null ? null : branch.obtainPsiCopy(myTargetParameter), + myNewVisibility); + UsageInfo[] convertedUsages = ContainerUtil.mapNotNull(usages, usage -> obtainBranchCopy(branch, usage)).toArray(UsageInfo.EMPTY_ARRAY); + PsiMethod result = processor.doRefactoring(convertedUsages); + branch.runAfterMerge(() -> { + PsiDocumentManager.getInstance(myProject).commitAllDocuments(); + PsiMethod toOpen = branch.findOriginalPsi(result); + if (toOpen != null) { + EditorHelper.openInEditor(toOpen); + } + }); + } + + @Nullable + private static UsageInfo obtainBranchCopy(ModelBranch branch, UsageInfo usage) { + if (usage instanceof MethodCallUsageInfo) { + return new MethodCallUsageInfo(branch.obtainPsiCopy(((MethodCallUsageInfo)usage).getMethodCall())); + } + if (usage instanceof ParameterUsageInfo) { + PsiElement element = ((ParameterUsageInfo)usage).getReferenceExpression().getElement(); + return new ParameterUsageInfo(branch.obtainPsiCopy(element).getReference()); + } + if (usage instanceof ImplementingClassUsageInfo) { + return new ImplementingClassUsageInfo(branch.obtainPsiCopy(((ImplementingClassUsageInfo)usage).getPsiClass())); + } + if (usage instanceof MethodReferenceUsageInfo) { + return new MethodReferenceUsageInfo(branch.obtainPsiCopy(((MethodReferenceUsageInfo)usage).getExpression()), + ((MethodReferenceUsageInfo)usage).isApplicableBySecondSearch()); + } + return null; + } + + @Override + protected void performRefactoring(UsageInfo @NotNull [] usages) { + EditorHelper.openInEditor(doRefactoring(usages)); + } + + @NotNull + private PsiMethod doRefactoring(UsageInfo[] usages) throws IncorrectOperationException { myTypeParameterReplacements = buildTypeParameterReplacements(); List inheritors = new ArrayList<>(); @@ -259,21 +293,22 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor { prepareTypeParameterReplacement(); if (myTargetParameter != null) myTargetParameter.delete(); ChangeContextUtil.encodeContextInfo(myMethod, true); + PsiMethod result; if (!myTargetClass.isInterface()) { - PsiMethod method = addMethodToClass(myTargetClass); - fixVisibility(method, usages); - EditorHelper.openInEditor(method); + result = addMethodToClass(myTargetClass); + fixVisibility(result, usages); + EditorHelper.openInEditor(result); } else { - final PsiMethod interfaceMethod = addMethodToClass(myTargetClass); - final PsiModifierList modifierList = interfaceMethod.getModifierList(); + result = addMethodToClass(myTargetClass); + final PsiModifierList modifierList = result.getModifierList(); final boolean markAsDefault = PsiUtil.isLanguageLevel8OrHigher(myTargetClass); if (markAsDefault) { modifierList.setModifierProperty(PsiModifier.DEFAULT, true); } - RefactoringUtil.makeMethodAbstract(myTargetClass, interfaceMethod); + RefactoringUtil.makeMethodAbstract(myTargetClass, result); - EditorHelper.openInEditor(interfaceMethod); + EditorHelper.openInEditor(result); if (!markAsDefault) { for (final PsiClass psiClass : inheritors) { @@ -284,6 +319,7 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor { } } myMethod.delete(); + return result; } private void processMethodReference(MethodReferenceUsageInfo usage) { diff --git a/java/java-tests/testSrc/com/intellij/java/refactoring/convertToInstanceMethod/ConvertToInstance8MethodTest.java b/java/java-tests/testSrc/com/intellij/java/refactoring/convertToInstanceMethod/ConvertToInstance8MethodTest.java index 915b30a92ff0..6f0d6d4504e3 100644 --- a/java/java-tests/testSrc/com/intellij/java/refactoring/convertToInstanceMethod/ConvertToInstance8MethodTest.java +++ b/java/java-tests/testSrc/com/intellij/java/refactoring/convertToInstanceMethod/ConvertToInstance8MethodTest.java @@ -15,11 +15,12 @@ */ package com.intellij.java.refactoring.convertToInstanceMethod; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.pom.java.LanguageLevel; import com.intellij.refactoring.BaseRefactoringProcessor; -public class ConvertToInstance8MethodTest extends ConvertToInstanceMethodTest { +public abstract class ConvertToInstance8MethodTest extends ConvertToInstanceMethodTest { @Override protected String getBasePath() { return "/refactoring/convertToInstance8Method/"; @@ -58,4 +59,14 @@ public class ConvertToInstance8MethodTest extends ConvertToInstanceMethodTest { protected LanguageLevel getLanguageLevel() { return LanguageLevel.JDK_1_8; } + + public static class SyncTest extends ConvertToInstance8MethodTest { } + + public static class BranchTest extends ConvertToInstance8MethodTest { + @Override + protected void setUp() throws Exception { + super.setUp(); + Registry.get("run.refactorings.in.model.branch").setValue(true, getTestRootDisposable()); + } + } } diff --git a/java/java-tests/testSrc/com/intellij/java/refactoring/convertToInstanceMethod/ConvertToInstanceMethodTest.java b/java/java-tests/testSrc/com/intellij/java/refactoring/convertToInstanceMethod/ConvertToInstanceMethodTest.java index da193f6c94e9..73eced4c09d9 100644 --- a/java/java-tests/testSrc/com/intellij/java/refactoring/convertToInstanceMethod/ConvertToInstanceMethodTest.java +++ b/java/java-tests/testSrc/com/intellij/java/refactoring/convertToInstanceMethod/ConvertToInstanceMethodTest.java @@ -18,6 +18,7 @@ package com.intellij.java.refactoring.convertToInstanceMethod; import com.intellij.JavaTestUtil; import com.intellij.codeInsight.TargetElementUtil; import com.intellij.java.refactoring.LightRefactoringTestCase; +import com.intellij.openapi.util.registry.Registry; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; @@ -92,4 +93,15 @@ public class ConvertToInstanceMethodTest extends LightRefactoringTestCase { protected LanguageLevel getLanguageLevel() { return LanguageLevel.JDK_1_6; } + + public static class SyncTest extends ConvertToInstanceMethodTest { } + + public static class BranchTest extends ConvertToInstanceMethodTest { + @Override + protected void setUp() throws Exception { + super.setUp(); + Registry.get("run.refactorings.in.model.branch").setValue(true, getTestRootDisposable()); + } + } + }