functional expressions: push down conflicts

This commit is contained in:
Anna Kozlova
2014-04-08 12:18:33 +02:00
parent d8ed05dbfa
commit 05fb5ed27b
7 changed files with 90 additions and 4 deletions
@@ -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<UsageInfo> usages = new ArrayList<UsageInfo>(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<PsiFunctionalExpression>() {
@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<UsageInfo[]> 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);
}
@@ -0,0 +1,12 @@
interface Base {
default void foo() {
System.out.println("Hi there.");
}
void ba<caret>r();
}
class Test {
{
Base base = () -> {};
}
}
@@ -0,0 +1,14 @@
interface Base {
default void foo<caret>() {
System.out.println("Hi there.");
}
void bar();
}
class Test {
{
Base base = () -> {};
}
}
class Child implements Base {}
@@ -0,0 +1,15 @@
interface Base {
void bar();
}
class Test {
{
Base base = () -> {};
}
}
class Child implements Base {
public void foo() {
System.out.println("Hi there.");
}
}
@@ -0,0 +1,11 @@
interface Base {
default void foo() {
System.out.println("Hi there.");
}
}
class Test {
{
Base base = () -> {};
}
}
@@ -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);
}
@@ -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