diff --git a/java/java-impl/src/com/intellij/codeInsight/FunctionalInterfaceSuggester.java b/java/java-impl/src/com/intellij/codeInsight/FunctionalInterfaceSuggester.java index e2fd08ac64a1..b869379d111a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/FunctionalInterfaceSuggester.java +++ b/java/java-impl/src/com/intellij/codeInsight/FunctionalInterfaceSuggester.java @@ -20,6 +20,7 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.searches.AnnotatedMembersSearch; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.NullableFunction; @@ -87,6 +88,21 @@ public class FunctionalInterfaceSuggester { return null; } + final PsiClassType[] interfaceThrownTypes = interfaceMethod.getThrowsList().getReferencedTypes(); + final PsiClassType[] thrownTypes = method.getThrowsList().getReferencedTypes(); + for (PsiClassType thrownType : thrownTypes) { + if (!ExceptionUtil.isHandledBy(thrownType, interfaceThrownTypes, substitutor)) { + return null; + } + } + + for (PsiClassType thrownType : interfaceThrownTypes) { + final PsiCodeBlock codeBlock = PsiTreeUtil.getContextOfType(method, PsiCodeBlock.class); + if (codeBlock == null || !ExceptionUtil.isHandled(thrownType, codeBlock)) { + return null; + } + } + final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(aClass.getProject()); final PsiType type = elementFactory.createType(aClass, substitutor); return type; diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java index fe04b0211b7f..e7b391c7894c 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java @@ -541,7 +541,9 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase { if (!processor.prepare()) return false; processor.showDialog(); - final PsiMethod emptyMethod = processor.generateEmptyMethod("name"); + //provide context for generated method to check exceptions compatibility + final PsiMethod emptyMethod = JavaPsiFacade.getElementFactory(project) + .createMethodFromText(processor.generateEmptyMethod("name").getText(), elements[0]); final Collection types = FunctionalInterfaceSuggester.suggestFunctionalInterfaces(emptyMethod); if (types.isEmpty()) { return false; diff --git a/java/java-tests/testData/refactoring/introduceFunctionalParameter/afterExceptionPreventFromCompatibility.java b/java/java-tests/testData/refactoring/introduceFunctionalParameter/afterExceptionPreventFromCompatibility.java new file mode 100644 index 000000000000..b5cee16b01e9 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceFunctionalParameter/afterExceptionPreventFromCompatibility.java @@ -0,0 +1,19 @@ +class Test { + @FunctionalInterface + interface I { + void f() throws Exception; + } + + void bar() { + foo(new Runnable() { + public void run() { + System.out.println(""); + System.out.println(""); + } + }); + } + + void foo(Runnable anObject) { + anObject.run(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceFunctionalParameter/afterThrownExceptionsAgree.java b/java/java-tests/testData/refactoring/introduceFunctionalParameter/afterThrownExceptionsAgree.java new file mode 100644 index 000000000000..16d090f09aec --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceFunctionalParameter/afterThrownExceptionsAgree.java @@ -0,0 +1,19 @@ +class Test { + @FunctionalInterface + interface I { + void f() throws Exception; + } + + void bar() throws Exception { + foo(new I() { + public void f() { + System.out.println(""); + System.out.println(""); + } + }); + } + + void foo(I anObject) throws Exception { + anObject.f(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceFunctionalParameter/beforeExceptionPreventFromCompatibility.java b/java/java-tests/testData/refactoring/introduceFunctionalParameter/beforeExceptionPreventFromCompatibility.java new file mode 100644 index 000000000000..864989ae86fa --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceFunctionalParameter/beforeExceptionPreventFromCompatibility.java @@ -0,0 +1,15 @@ +class Test { + @FunctionalInterface + interface I { + void f() throws Exception; + } + + void bar() { + foo(); + } + + void foo() { + System.out.println(""); + System.out.println(""); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceFunctionalParameter/beforeThrownExceptionsAgree.java b/java/java-tests/testData/refactoring/introduceFunctionalParameter/beforeThrownExceptionsAgree.java new file mode 100644 index 000000000000..9a9175c8c695 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceFunctionalParameter/beforeThrownExceptionsAgree.java @@ -0,0 +1,15 @@ +class Test { + @FunctionalInterface + interface I { + void f() throws Exception; + } + + void bar() throws Exception { + foo(); + } + + void foo() throws Exception { + System.out.println(""); + System.out.println(""); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceFunctionalParameterTest.java b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceFunctionalParameterTest.java index 6da97834656b..1bd71cfb4196 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceFunctionalParameterTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceFunctionalParameterTest.java @@ -41,6 +41,14 @@ public class IntroduceFunctionalParameterTest extends LightRefactoringTestCase doTest(); } + public void testExceptionPreventFromCompatibility() throws Exception { + doTest(); + } + + public void testThrownExceptionsAgree() throws Exception { + doTest(); + } + @NotNull @Override protected String getTestDataPath() {