From 05fb5ed27b7781bcb0e3ff4b250da65011ed66e1 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 8 Apr 2014 11:19:27 +0200 Subject: [PATCH] functional expressions: push down conflicts --- .../memberPushDown/PushDownProcessor.java | 38 +++++++++++++++++-- .../pushDown/FunctionalExpression.java | 12 ++++++ .../FunctionalExpressionDefaultMethod.java | 14 +++++++ ...nctionalExpressionDefaultMethod_after.java | 15 ++++++++ .../pushDown/FunctionalExpression_after.java | 11 ++++++ .../intellij/refactoring/PushDownTest.java | 3 ++ .../src/messages/RefactoringBundle.properties | 1 + 7 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 java/java-tests/testData/refactoring/pushDown/FunctionalExpression.java create mode 100644 java/java-tests/testData/refactoring/pushDown/FunctionalExpressionDefaultMethod.java create mode 100644 java/java-tests/testData/refactoring/pushDown/FunctionalExpressionDefaultMethod_after.java create mode 100644 java/java-tests/testData/refactoring/pushDown/FunctionalExpression_after.java diff --git a/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java b/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java index d6f73676c7fd..e3deef7e153f 100644 --- a/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java @@ -29,6 +29,7 @@ import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.search.searches.ClassInheritorsSearch; +import com.intellij.psi.search.searches.FunctionalExpressionSearch; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.MethodSignatureUtil; import com.intellij.psi.util.PsiTreeUtil; @@ -46,6 +47,7 @@ import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.Processor; import com.intellij.util.containers.HashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -117,11 +119,32 @@ public class PushDownProcessor extends BaseRefactoringProcessor { @NotNull protected UsageInfo[] findUsages() { final PsiClass[] inheritors = ClassInheritorsSearch.search(myClass, false).toArray(PsiClass.EMPTY_ARRAY); - UsageInfo[] usages = new UsageInfo[inheritors.length]; - for (int i = 0; i < inheritors.length; i++) { - usages[i] = new UsageInfo(inheritors[i]); + final List usages = new ArrayList(inheritors.length); + for (PsiClass inheritor : inheritors) { + usages.add(new UsageInfo(inheritor)); } - return usages; + + final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(myClass); + if (interfaceMethod != null && isMoved(interfaceMethod)) { + FunctionalExpressionSearch.search(myClass).forEach(new Processor() { + @Override + public boolean process(PsiFunctionalExpression expression) { + usages.add(new UsageInfo(expression)); + return true; + } + }); + } + + return usages.toArray(new UsageInfo[usages.size()]); + } + + private boolean isMoved(PsiMember member) { + for (MemberInfo info : myMemberInfos) { + if (member == info.getMember()) { + return true; + } + } + return false; } protected boolean preprocessUsages(final Ref refUsages) { @@ -167,6 +190,13 @@ public class PushDownProcessor extends BaseRefactoringProcessor { if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(runnable, RefactoringBundle.message("detecting.possible.conflicts"), true, myProject)) { return false; } + + for (UsageInfo info : usagesIn) { + final PsiElement element = info.getElement(); + if (element instanceof PsiFunctionalExpression) { + pushDownConflicts.getConflicts().putValue(element, RefactoringBundle.message("functional.interface.broken")); + } + } return showConflicts(pushDownConflicts.getConflicts(), usagesIn); } diff --git a/java/java-tests/testData/refactoring/pushDown/FunctionalExpression.java b/java/java-tests/testData/refactoring/pushDown/FunctionalExpression.java new file mode 100644 index 000000000000..36975cff7e06 --- /dev/null +++ b/java/java-tests/testData/refactoring/pushDown/FunctionalExpression.java @@ -0,0 +1,12 @@ +interface Base { + default void foo() { + System.out.println("Hi there."); + } + void bar(); +} + +class Test { + { + Base base = () -> {}; + } +} diff --git a/java/java-tests/testData/refactoring/pushDown/FunctionalExpressionDefaultMethod.java b/java/java-tests/testData/refactoring/pushDown/FunctionalExpressionDefaultMethod.java new file mode 100644 index 000000000000..f3a6b82b7e92 --- /dev/null +++ b/java/java-tests/testData/refactoring/pushDown/FunctionalExpressionDefaultMethod.java @@ -0,0 +1,14 @@ +interface Base { + default void foo() { + System.out.println("Hi there."); + } + void bar(); +} + +class Test { + { + Base base = () -> {}; + } +} + +class Child implements Base {} diff --git a/java/java-tests/testData/refactoring/pushDown/FunctionalExpressionDefaultMethod_after.java b/java/java-tests/testData/refactoring/pushDown/FunctionalExpressionDefaultMethod_after.java new file mode 100644 index 000000000000..50fd08d85e97 --- /dev/null +++ b/java/java-tests/testData/refactoring/pushDown/FunctionalExpressionDefaultMethod_after.java @@ -0,0 +1,15 @@ +interface Base { + void bar(); +} + +class Test { + { + Base base = () -> {}; + } +} + +class Child implements Base { + public void foo() { + System.out.println("Hi there."); +} +} diff --git a/java/java-tests/testData/refactoring/pushDown/FunctionalExpression_after.java b/java/java-tests/testData/refactoring/pushDown/FunctionalExpression_after.java new file mode 100644 index 000000000000..1ddc1ab5e51a --- /dev/null +++ b/java/java-tests/testData/refactoring/pushDown/FunctionalExpression_after.java @@ -0,0 +1,11 @@ +interface Base { + default void foo() { + System.out.println("Hi there."); + } +} + +class Test { + { + Base base = () -> {}; + } +} diff --git a/java/java-tests/testSrc/com/intellij/refactoring/PushDownTest.java b/java/java-tests/testSrc/com/intellij/refactoring/PushDownTest.java index 5ea40f697a4d..72f82e2515ca 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/PushDownTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/PushDownTest.java @@ -54,6 +54,9 @@ public class PushDownTest extends LightRefactoringTestCase { public void testExtensionMethodToInterface() { doTest(); } public void testExtensionMethodToClass() { doTest(); } + public void testFunctionalExpression() { doTest(true);} + public void testFunctionalExpressionDefaultMethod() { doTest();} + private void doTest() { doTest(false); } diff --git a/platform/platform-resources-en/src/messages/RefactoringBundle.properties b/platform/platform-resources-en/src/messages/RefactoringBundle.properties index e4350745f34c..fef06603a84b 100644 --- a/platform/platform-resources-en/src/messages/RefactoringBundle.properties +++ b/platform/platform-resources-en/src/messages/RefactoringBundle.properties @@ -494,6 +494,7 @@ keep.abstract.column.header=Keep abstract push.down.javadoc.panel.title=JavaDoc for abstracts push.down.members.elements.header=Push down members from interface.0.does.not.have.inheritors=Interface {0} does not have inheritors +functional.interface.broken=Functional expression demands functional interface to have exact one method class.0.does.not.have.inheritors=Class {0} does not have inheritors push.down.will.delete.members=Pushing members down will result in them being deleted. Would you like to create a new subclass? edit.migration.map.title=Edit Migration Map