From accc2bf2842beb2b567b1098eaef295f2115449c Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Tue, 3 Apr 2012 22:08:01 +0400 Subject: [PATCH] IDEA-84036 Redundant thrown exception not detected if the method calls itself --- .../reference/RefMethodImpl.java | 2 +- .../intellij/codeInsight/ExceptionUtil.java | 30 +++++++++++++++---- .../redundantThrow/SelfCall/expected.xml | 9 ++++++ .../redundantThrow/SelfCall/src/Foo.java | 9 ++++++ .../codeInspection/RedundantThrowTest.java | 5 ++++ 5 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 java/java-tests/testData/inspection/redundantThrow/SelfCall/expected.xml create mode 100644 java/java-tests/testData/inspection/redundantThrow/SelfCall/src/Foo.java diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java index f5aa2c90b0a7..d6498510aa35 100644 --- a/java/java-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java +++ b/java/java-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java @@ -305,7 +305,7 @@ public class RefMethodImpl extends RefJavaElementImpl implements RefMethod { final PsiCodeBlock body = method.getBody(); if (body == null) return; - final Collection exceptionTypes = ExceptionUtil.collectUnhandledExceptions(body, method); + final Collection exceptionTypes = ExceptionUtil.collectUnhandledExceptions(body, method, false); for (final PsiClassType exceptionType : exceptionTypes) { updateThrowsList(exceptionType); } diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java index c9f49dbf0d19..624a987920dc 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java @@ -192,19 +192,26 @@ public class ExceptionUtil { } @NotNull - public static Collection collectUnhandledExceptions(@NotNull PsiElement element, @Nullable PsiElement topElement) { - final Set set = collectUnhandledExceptions(element, topElement, null); + public static Collection collectUnhandledExceptions(@NotNull PsiElement element, + @Nullable PsiElement topElement) { + return collectUnhandledExceptions(element, topElement, true); + } + + @NotNull + public static Collection collectUnhandledExceptions(@NotNull PsiElement element, + @Nullable PsiElement topElement, boolean includeSelfCalls) { + final Set set = collectUnhandledExceptions(element, topElement, null, includeSelfCalls); return set == null ? Collections.emptyList() : set; } @Nullable private static Set collectUnhandledExceptions(@NotNull PsiElement element, PsiElement topElement, - @Nullable Set foundExceptions) { + @Nullable Set foundExceptions, boolean includeSelfCalls) { Collection unhandledExceptions = null; if (element instanceof PsiCallExpression) { PsiCallExpression expression = (PsiCallExpression)element; - unhandledExceptions = getUnhandledExceptions(expression, topElement); + unhandledExceptions = getUnhandledExceptions(expression, topElement, includeSelfCalls); } else if (element instanceof PsiThrowStatement) { PsiThrowStatement statement = (PsiThrowStatement)element; @@ -239,7 +246,7 @@ public class ExceptionUtil { for (PsiClassInitializer initializer : initializers) { if (initializer.hasModifierProperty(PsiModifier.STATIC)) continue; thrownByInitializer.clear(); - collectUnhandledExceptions(initializer.getBody(), initializer, thrownByInitializer); + collectUnhandledExceptions(initializer.getBody(), initializer, thrownByInitializer, includeSelfCalls); for (PsiClassType thrown : thrownByInitializer) { if (!isHandled(constructor.getBody(), thrown, topElement)) { unhandled.add(thrown); @@ -268,7 +275,7 @@ public class ExceptionUtil { } for (PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()) { - foundExceptions = collectUnhandledExceptions(child, topElement, foundExceptions); + foundExceptions = collectUnhandledExceptions(child, topElement, foundExceptions, includeSelfCalls); } return foundExceptions; @@ -334,8 +341,19 @@ public class ExceptionUtil { @NotNull public static List getUnhandledExceptions(final PsiCallExpression methodCall, @Nullable final PsiElement topElement) { + return getUnhandledExceptions(methodCall, topElement, true); + } + + @NotNull + public static List getUnhandledExceptions(final PsiCallExpression methodCall, + @Nullable final PsiElement topElement, + boolean includeSelfCalls) { final JavaResolveResult result = methodCall.resolveMethodGenerics(); final PsiMethod method = (PsiMethod)result.getElement(); + if (!includeSelfCalls && method == PsiTreeUtil.getParentOfType(methodCall, PsiMethod.class)) { + return Collections.emptyList(); + } + final PsiSubstitutor substitutor = ApplicationManager.getApplication().runReadAction(new Computable() { @Override public PsiSubstitutor compute() { diff --git a/java/java-tests/testData/inspection/redundantThrow/SelfCall/expected.xml b/java/java-tests/testData/inspection/redundantThrow/SelfCall/expected.xml new file mode 100644 index 000000000000..67e5336cd5c8 --- /dev/null +++ b/java/java-tests/testData/inspection/redundantThrow/SelfCall/expected.xml @@ -0,0 +1,9 @@ + + + + Foo.java + 4 + IOException + + + diff --git a/java/java-tests/testData/inspection/redundantThrow/SelfCall/src/Foo.java b/java/java-tests/testData/inspection/redundantThrow/SelfCall/src/Foo.java new file mode 100644 index 000000000000..3602d5d26356 --- /dev/null +++ b/java/java-tests/testData/inspection/redundantThrow/SelfCall/src/Foo.java @@ -0,0 +1,9 @@ +import java.io.*; + +public class Foo { + public void foo() throws IOException { + if (4 > 3) { + foo(); + } + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/RedundantThrowTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/RedundantThrowTest.java index 823295110b93..75de7baffc0c 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/RedundantThrowTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/RedundantThrowTest.java @@ -41,4 +41,9 @@ public class RedundantThrowTest extends InspectionTestCase { public void testimplicitSuper() throws Exception { doTest(); } + + public void testselfCall() throws Exception { + doTest(); + } + }