diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/UnnecessaryInitCauseInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/UnnecessaryInitCauseInspectionBase.java index efcc1fcc270b..f2c5bb3e63c3 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/UnnecessaryInitCauseInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/UnnecessaryInitCauseInspectionBase.java @@ -15,6 +15,7 @@ */ package com.siyeh.ig.errorhandling; +import com.intellij.openapi.util.Ref; import com.intellij.psi.*; import com.intellij.psi.controlFlow.DefUseUtil; import com.intellij.psi.util.InheritanceUtil; @@ -76,12 +77,42 @@ public class UnnecessaryInitCauseInspectionBase extends BaseInspection { } final PsiExpression qualifier = ParenthesesUtils.stripParentheses(methodExpression.getQualifierExpression()); final PsiNewExpression newExpression = findNewExpression(qualifier); - if (!isCauseConstructorAvailable(newExpression)) { + if (!isCauseConstructorAvailable(newExpression) || !canExpressionBeMovedBackwards(argument, newExpression)) { return; } registerMethodCallError(expression); } + private static boolean canExpressionBeMovedBackwards(final PsiExpression cause, final PsiExpression newLocation) { + if (cause == null || newLocation == null) return false; + assert cause.getTextOffset() > newLocation.getTextOffset(); + final PsiCodeBlock block = PsiTreeUtil.getParentOfType(cause, PsiCodeBlock.class); + final PsiCodeBlock newBlock = PsiTreeUtil.getParentOfType(newLocation, PsiCodeBlock.class); + if (block == null || newBlock == null || !PsiTreeUtil.isAncestor(block, newBlock, false)) return false; + final int offset = newLocation.getTextOffset(); + final Ref result = new Ref(Boolean.TRUE); + cause.accept(new JavaRecursiveElementWalkingVisitor() { + @Override + public void visitReferenceExpression(PsiReferenceExpression expression) { + if (!result.get().booleanValue()) { + return; + } + super.visitReferenceExpression(expression); + final PsiElement target = expression.resolve(); + if (!(target instanceof PsiVariable)) { + return; + } + final PsiElement[] defs = DefUseUtil.getDefs(block, (PsiVariable)target, cause); + for (PsiElement def : defs) { + if (def.getTextOffset() > offset) { + result.set(Boolean.FALSE); + } + } + } + }); + return result.get().booleanValue(); + } + public static boolean isCauseConstructorAvailable(PsiNewExpression newExpression) { if (newExpression == null) { return false; diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/errorhandling/UnnecessaryInitCauseInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/errorhandling/UnnecessaryInitCauseInspectionTest.java index faf34b1c15fb..2e3a36d80ac4 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/errorhandling/UnnecessaryInitCauseInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/errorhandling/UnnecessaryInitCauseInspectionTest.java @@ -39,6 +39,19 @@ public class UnnecessaryInitCauseInspectionTest extends LightInspectionTestCase "}"); } + public void testReassigned() { + doMemberTest("void foo() {\n" + + " try {\n" + + " new java.io.FileInputStream(\"asdf\");\n" + + " } catch (java.io.FileNotFoundException e) {\n" + + " RuntimeException exception = new RuntimeException();\n" + + " e = null;\n" + + " exception.initCause(e);\n" + + " throw exception;\n" + + " }\n" + + "}"); + } + @Nullable @Override protected InspectionProfileEntry getInspection() {