extract functional: suggest incompatible SAM by throws list

when there is no applicable interfaces (IDEA-174045)
This commit is contained in:
Anna Kozlova
2017-06-09 12:28:27 +03:00
parent 23cc5b9cdb
commit e3aecbce9b
3 changed files with 34 additions and 9 deletions
@@ -70,6 +70,11 @@ public class FunctionalInterfaceSuggester {
}
public static Collection<? extends PsiType> suggestFunctionalInterfaces(final @NotNull PsiMethod method) {
return suggestFunctionalInterfaces(method, false);
}
public static Collection<? extends PsiType> suggestFunctionalInterfaces(final @NotNull PsiMethod method,
boolean suggestUnhandledThrowables) {
if (method.isConstructor()) {
return Collections.emptyList();
}
@@ -128,10 +133,14 @@ public class FunctionalInterfaceSuggester {
}
}
for (PsiClassType thrownType : interfaceThrownTypes) {
final PsiCodeBlock codeBlock = PsiTreeUtil.getContextOfType(method, PsiCodeBlock.class);
if (codeBlock == null || !ExceptionUtil.isHandled(thrownType, codeBlock)) {
return null;
if (!suggestUnhandledThrowables) {
for (PsiClassType thrownType : interfaceThrownTypes) {
final PsiCodeBlock codeBlock = PsiTreeUtil.getContextOfType(method, PsiCodeBlock.class);
PsiType substitutedThrowable = substitutor.substitute(thrownType);
if (codeBlock == null || !(substitutedThrowable instanceof PsiClassType) ||
!ExceptionUtil.isHandled((PsiClassType)substitutedThrowable, codeBlock)) {
return null;
}
}
}
@@ -83,7 +83,11 @@ public class IntroduceFunctionalVariableHandler extends IntroduceVariableHandler
final PsiMethod emptyMethod = JavaPsiFacade.getElementFactory(project)
.createMethodFromText(processor.generateEmptyMethod("name").getText(), elements[0]);
final Collection<? extends PsiType> types = FunctionalInterfaceSuggester.suggestFunctionalInterfaces(emptyMethod);
Collection<? extends PsiType> types = FunctionalInterfaceSuggester.suggestFunctionalInterfaces(emptyMethod);
if (types.isEmpty()) {
types = FunctionalInterfaceSuggester.suggestFunctionalInterfaces(emptyMethod, true);
}
if (types.isEmpty()) {
showErrorMessage(project, editor, "No applicable functional interfaces found");
return;
@@ -17,12 +17,14 @@ package com.intellij.java.refactoring;
import com.intellij.codeInsight.FunctionalInterfaceSuggester;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiType;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
import org.junit.Assert;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
@@ -39,8 +41,18 @@ public class FunctionalInterfaceSuggesterTest extends LightCodeInsightFixtureTes
.stream()
.map(type -> type.getCanonicalText())
.collect(Collectors.toList());
Assert.assertEquals(4, suggestedTypes.size());
Assert.assertTrue(suggestedTypes.containsAll(Arrays.asList("java.util.function.ToDoubleFunction<java.lang.Double>",
"java.util.function.DoubleUnaryOperator")));
assertEquals(4, suggestedTypes.size());
assertTrue(suggestedTypes.containsAll(Arrays.asList("java.util.function.ToDoubleFunction<java.lang.Double>",
"java.util.function.DoubleUnaryOperator")));
}
public void testSAMWithThrowable() throws Exception {
myFixture.addClass("@FunctionalInterface\n" +
"public interface MyThrowingConsumer<T> {\n" +
" void accept(T t) throws Throwable;\n" +
"}\n");
PsiMethod method = myFixture.addClass("class Foo { void foo(int i) {}}").getMethods()[0];
Collection<? extends PsiType> suggestedTypes = FunctionalInterfaceSuggester.suggestFunctionalInterfaces(method, true);
assertTrue(suggestedTypes.stream().anyMatch(type -> type.equalsToText("MyThrowingConsumer<Integer>")));
}
}