diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java index 031590492d9f..b626b08ef7ad 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java @@ -675,7 +675,7 @@ public class HighlightControlFlowUtil { return null; } - public static boolean isEffectivelyFinal(PsiVariable variable, PsiElement scope, PsiJavaCodeReferenceElement context) { + public static boolean isEffectivelyFinal(PsiVariable variable, PsiElement scope, @Nullable PsiJavaCodeReferenceElement context) { boolean effectivelyFinal; if (variable instanceof PsiParameter) { effectivelyFinal = notAccessedForWriting(variable, new LocalSearchScope(((PsiParameter)variable).getDeclarationScope())); diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/UnnecessaryLocalVariableInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/UnnecessaryLocalVariableInspectionBase.java index 4c82119a3483..ad4273156865 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/UnnecessaryLocalVariableInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/UnnecessaryLocalVariableInspectionBase.java @@ -15,16 +15,18 @@ */ package com.siyeh.ig.dataflow; +import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil; import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.DefaultJDOMExternalizer; -import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.WriteExternalException; import com.intellij.psi.*; +import com.intellij.psi.search.LocalSearchScope; +import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; -import com.intellij.util.xmlb.XmlSerializer; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; @@ -162,11 +164,17 @@ public class UnnecessaryLocalVariableInspectionBase extends BaseInspection { VariableAccessUtils.variableIsAssigned(initialization, containingScope, false)) { return false; } - if (!initialization.hasModifierProperty(PsiModifier.FINAL) && variable.hasModifierProperty(PsiModifier.FINAL)) { - if (VariableAccessUtils.variableIsUsedInInnerClass(variable, containingScope)) { - return false; + + if (!initialization.hasModifierProperty(PsiModifier.FINAL) && variable.hasModifierProperty(PsiModifier.FINAL) || + PsiUtil.isLanguageLevel8OrHigher(initialization) && !HighlightControlFlowUtil.isEffectivelyFinal(initialization, containingScope, null) && HighlightControlFlowUtil.isEffectivelyFinal(variable, containingScope, null)) { + for (PsiReference ref : ReferencesSearch.search(variable, new LocalSearchScope(containingScope))) { + final PsiElement element = PsiTreeUtil.getParentOfType(ref.getElement(), PsiClass.class, PsiLambdaExpression.class); + if (element != null && PsiTreeUtil.isAncestor(containingScope, element, true)) { + return false; + } } } + return !TypeConversionUtil.boxingConversionApplicable(variable.getType(), initialization.getType()); } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_vars/C.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_vars/C.java index da4b4b43181c..c316742bb3e9 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_vars/C.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_vars/C.java @@ -115,4 +115,15 @@ class C { System.out.println(k); } + void usedIn8Inner(int j) { + for (int i = 0; i < 7; i++) { + int k = i; + int n = j; + class F { + { + System.out.println(k + n); + } + } + } + } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_vars/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_vars/expected.xml index 70ce7071c30e..aa7bda34c4c4 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_vars/expected.xml +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_vars/expected.xml @@ -119,4 +119,10 @@ Local variable <code>k</code> is redundant #loc + + C.java + 121 + Redundant local variable + Local variable <code>n</code> is redundant #loc + \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/dataflow/UnnecessaryLocalVariableInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/dataflow/UnnecessaryLocalVariableInspectionTest.java index b7f1fb4ff67f..4efbf1a23d4b 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/dataflow/UnnecessaryLocalVariableInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/dataflow/UnnecessaryLocalVariableInspectionTest.java @@ -15,18 +15,17 @@ */ package com.siyeh.ig.dataflow; -import com.intellij.testFramework.IdeaTestUtil; -import com.siyeh.ig.IGInspectionTestCase; import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.pom.java.LanguageLevel; +import com.intellij.testFramework.IdeaTestUtil; +import com.siyeh.ig.IGInspectionTestCase; public class UnnecessaryLocalVariableInspectionTest extends IGInspectionTestCase { @Override protected Sdk getTestProjectSdk() { final Sdk sdk = IdeaTestUtil.getMockJdk17(); - LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_7); + LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.HIGHEST); return sdk; }