Unused local variable inspection made aware of try-with-resources

This commit is contained in:
Roman Shevchenko
2011-02-25 20:59:19 +01:00
parent 02bd2733a5
commit b2ec3c9263
5 changed files with 188 additions and 32 deletions
@@ -18,12 +18,6 @@ class C {
}
void m2() throws Exception {
// todo: test in IG
//MyResource < warning descr="Local variable 'r1' is redundant">r1</warning> = null;
//try (MyResource r = r1) {
// System.out.println(r);
//}
try (MyResource <warning descr="Variable 'r2' is never used">r2</warning> = new MyResource()) { }
MyResource <warning descr="Variable 'r3' is never assigned">r3</warning>;
@@ -15,6 +15,7 @@
*/
package com.siyeh.ig.dataflow;
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
@@ -24,10 +25,9 @@ import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.fixes.InlineVariableFix;
import com.siyeh.ig.psiutils.VariableAccessUtils;
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
import org.jetbrains.annotations.NotNull;
import javax.swing.JComponent;
import javax.swing.*;
public class UnnecessaryLocalVariableInspection extends BaseInspection {
@@ -85,23 +85,25 @@ public class UnnecessaryLocalVariableInspection extends BaseInspection {
private class UnnecessaryLocalVariableVisitor
extends BaseInspectionVisitor {
@Override public void visitLocalVariable(
@SuppressWarnings({"IfStatementWithIdenticalBranches"})
@Override
public void visitLocalVariable(
@NotNull PsiLocalVariable variable) {
super.visitLocalVariable(variable);
if (m_ignoreAnnotatedVariables) {
final PsiModifierList list = variable.getModifierList();
if (list != null && list.getAnnotations().length > 0) {
return;
final PsiModifierList list = variable.getModifierList();
if (list != null && list.getAnnotations().length > 0) {
return;
}
}
if (isCopyVariable(variable)) {
registerVariableError(variable);
} else if (!m_ignoreImmediatelyReturnedVariables &&
isImmediatelyReturned(variable)) {
isImmediatelyReturned(variable)) {
registerVariableError(variable);
} else if (!m_ignoreImmediatelyReturnedVariables &&
isImmediatelyThrown(variable)) {
isImmediatelyThrown(variable)) {
registerVariableError(variable);
} else if (isImmediatelyAssigned(variable)) {
registerVariableError(variable);
@@ -301,30 +303,73 @@ public class UnnecessaryLocalVariableInspection extends BaseInspection {
followingStatementNumber = i + 2;
}
}
if (!(nextStatement instanceof PsiDeclarationStatement)) {
return false;
if (nextStatement instanceof PsiDeclarationStatement) {
boolean referenceFound = false;
for (PsiElement declaration : ((PsiDeclarationStatement)nextStatement).getDeclaredElements()) {
if (!(declaration instanceof PsiVariable)) {
continue;
}
final PsiExpression initializer = ((PsiVariable)declaration).getInitializer();
if (!referenceFound) {
if (initializer instanceof PsiReferenceExpression) {
final PsiElement referent = ((PsiReference)initializer).resolve();
if (variable.equals(referent)) {
referenceFound = true;
continue;
}
}
}
if (VariableAccessUtils.variableIsUsed(variable, initializer)) {
return false;
}
}
if (!referenceFound) {
return false;
}
}
final PsiDeclarationStatement declaration =
(PsiDeclarationStatement) nextStatement;
final PsiElement[] declarations = declaration.getDeclaredElements();
if (declarations.length != 1) {
return false;
else if (nextStatement instanceof PsiTryStatement) {
final PsiTryStatement tryStatement = (PsiTryStatement)nextStatement;
final PsiResourceList resourceList = tryStatement.getResourceList();
if (resourceList == null) {
return false;
}
boolean referenceFound = false;
for (PsiResourceVariable resourceVariable : resourceList.getResourceVariables()) {
final PsiExpression initializer = resourceVariable.getInitializer();
if (!referenceFound) {
if (initializer instanceof PsiReferenceExpression) {
final PsiElement referent = ((PsiReferenceExpression)initializer).resolve();
if (variable.equals(referent)) {
referenceFound = true;
continue;
}
}
}
if (VariableAccessUtils.variableIsUsed(variable, initializer)) {
return false;
}
}
if (!referenceFound) {
return false;
}
if (VariableAccessUtils.variableIsUsed(variable, tryStatement.getTryBlock()) ||
VariableAccessUtils.variableIsUsed(variable, tryStatement.getFinallyBlock())) {
return false;
}
for (PsiCatchSection section : tryStatement.getCatchSections()) {
if (VariableAccessUtils.variableIsUsed(variable, section)) {
return false;
}
}
}
if (!(declarations[0] instanceof PsiVariable)) {
return false;
}
final PsiExpression rhs =
((PsiVariable) declarations[0]).getInitializer();
if (!(rhs instanceof PsiReferenceExpression)) {
return false;
}
final PsiElement referent = ((PsiReference) rhs).resolve();
if (referent == null || !referent.equals(variable)) {
else {
return false;
}
for (int i = followingStatementNumber; i < statements.length; i++) {
if (VariableAccessUtils.variableIsUsed(variable,
statements[i])) {
statements[i])) {
return false;
}
}
@@ -0,0 +1,23 @@
class C {
void m() throws Exception {
String s1 = null;
String s2 = s1, s3 = null;
System.out.println(s2 + s3);
AutoCloseable r1 = null;
try (AutoCloseable r2 = r1, AutoCloseable r3 = null) {
System.out.println(r2 + r3);
}
}
void n() throws Exception {
String s1 = null;
String s2 = s1, s3 = s1;
System.out.println(s2 + s3);
AutoCloseable r1 = null;
try (AutoCloseable r2 = r1; AutoCloseable r3 = r1) {
System.out.println(r2 + r3);
}
}
}
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
<problem>
<file>C.java</file>
<line>3</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Redundant local variable</problem_class>
<description>Local variable &lt;code&gt;s1&lt;/code&gt; is redundant #loc</description>
</problem>
<problem>
<file>C.java</file>
<line>4</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Redundant local variable</problem_class>
<description>Local variable &lt;code&gt;s2&lt;/code&gt; is redundant #loc</description>
</problem>
<problem>
<file>C.java</file>
<line>7</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Redundant local variable</problem_class>
<description>Local variable &lt;code&gt;r1&lt;/code&gt; is redundant #loc</description>
</problem>
<problem>
<file>C.java</file>
<line>8</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Redundant local variable</problem_class>
<description>Local variable &lt;code&gt;r2&lt;/code&gt; is redundant #loc</description>
</problem>
<problem>
<file>C.java</file>
<line>15</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Redundant local variable</problem_class>
<description>Local variable &lt;code&gt;s2&lt;/code&gt; is redundant #loc</description>
</problem>
<problem>
<file>C.java</file>
<line>15</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Redundant local variable</problem_class>
<description>Local variable &lt;code&gt;s3&lt;/code&gt; is redundant #loc</description>
</problem>
<problem>
<file>C.java</file>
<line>19</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Redundant local variable</problem_class>
<description>Local variable &lt;code&gt;r2&lt;/code&gt; is redundant #loc</description>
</problem>
<problem>
<file>C.java</file>
<line>19</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Redundant local variable</problem_class>
<description>Local variable &lt;code&gt;r3&lt;/code&gt; is redundant #loc</description>
</problem>
</problems>
@@ -0,0 +1,36 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ig.dataflow;
import com.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;
public class UnnecessaryLocalVariableInspectionTest extends IGInspectionTestCase {
@Override
protected Sdk getTestProjectSdk() {
final Sdk sdk = JavaSdkImpl.getMockJdk17();
LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_7);
return sdk;
}
public void test() throws Exception {
doTest("com/siyeh/igtest/dataflow/unnecessary_local_vars",
new UnnecessaryLocalVariableInspection());
}
}