Fixed "Variable assigned to itself" quickfix (IDEA-148688)

This commit is contained in:
Bas Leijdekkers
2016-08-01 16:51:43 +02:00
parent 7c44378da1
commit 46e4268b8f
16 changed files with 187 additions and 24 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 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.
@@ -27,12 +27,6 @@ import org.jetbrains.annotations.Nullable;
public class SillyAssignmentInspectionBase extends BaseJavaBatchLocalInspectionTool {
@Override
@NotNull
public String getGroupDisplayName() {
return "";
}
@Override
@NotNull
public String getDisplayName() {
@@ -84,8 +78,10 @@ public class SillyAssignmentInspectionBase extends BaseJavaBatchLocalInspectionT
if (qualifier == null || qualifier instanceof PsiThisExpression || qualifier instanceof PsiSuperExpression ||
variable.hasModifierProperty(PsiModifier.STATIC)) {
if (refExpr.isReferenceTo(variable)) {
holder.registerProblem(expression, InspectionsBundle.message("assignment.to.declared.variable.problem.descriptor",
variable.getName()), ProblemHighlightType.LIKE_UNUSED_SYMBOL);
holder.registerProblem(refExpr,
InspectionsBundle.message("assignment.to.declared.variable.problem.descriptor", variable.getName()),
ProblemHighlightType.LIKE_UNUSED_SYMBOL,
createRemoveAssignmentFix(refExpr));
}
}
}
@@ -119,8 +115,8 @@ public class SillyAssignmentInspectionBase extends BaseJavaBatchLocalInspectionT
}
PsiManager manager = assignment.getManager();
if (!sameInstanceReferences(lRef, rRef, manager)) return;
holder.registerProblem(assignment, InspectionsBundle.message("assignment.to.itself.problem.descriptor", variable.getName()),
ProblemHighlightType.LIKE_UNUSED_SYMBOL, createRemoveAssignmentFix());
holder.registerProblem(rRef, InspectionsBundle.message("assignment.to.itself.problem.descriptor", variable.getName()),
ProblemHighlightType.LIKE_UNUSED_SYMBOL, createRemoveAssignmentFix(rRef));
}
private static PsiExpression deparenthesizeRExpr(PsiExpression rExpression, PsiVariable variable) {
@@ -144,7 +140,7 @@ public class SillyAssignmentInspectionBase extends BaseJavaBatchLocalInspectionT
return rExpression;
}
protected LocalQuickFix createRemoveAssignmentFix() {
protected LocalQuickFix createRemoveAssignmentFix(PsiReferenceExpression expression) {
return null;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2016 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.
@@ -15,8 +15,15 @@
*/
package com.intellij.codeInspection.sillyAssignment;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.RemoveAssignmentFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
/**
* User: anna
@@ -25,7 +32,66 @@ import com.intellij.codeInspection.RemoveAssignmentFix;
public class SillyAssignmentInspection extends SillyAssignmentInspectionBase {
@Override
protected LocalQuickFix createRemoveAssignmentFix() {
return new RemoveAssignmentFix();
protected LocalQuickFix createRemoveAssignmentFix(PsiReferenceExpression expression) {
final PsiElement parent = expression.getParent();
if (parent instanceof PsiVariable) {
final PsiVariable variable = (PsiVariable)parent;
if (variable.hasModifierProperty(PsiModifier.FINAL)) {
return null;
}
}
return new RemoveSillyAssignmentFix();
}
private static class RemoveSillyAssignmentFix implements LocalQuickFix {
@Nls
@NotNull
@Override
public String getName() {
return InspectionsBundle.message("assignment.to.itself.quickfix.name");
}
@Nls
@NotNull
@Override
public String getFamilyName() {
return getName();
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
if (!(element instanceof PsiReferenceExpression)) {
return;
}
final PsiElement parent = PsiUtil.skipParenthesizedExprUp(element.getParent());
if (parent instanceof PsiVariable) {
element.delete();
}
if (!(parent instanceof PsiAssignmentExpression)) {
return;
}
final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)parent;
final PsiExpression lhs = assignmentExpression.getLExpression();
final PsiExpression rhs = assignmentExpression.getRExpression();
if (PsiTreeUtil.isAncestor(lhs, element, false)) {
if (rhs != null) {
assignmentExpression.replace(rhs);
}
else {
assignmentExpression.delete();
}
}
else {
final PsiElement grandParent = assignmentExpression.getParent();
if (grandParent instanceof PsiExpressionStatement) {
grandParent.delete();
}
else {
assignmentExpression.replace(element);
}
}
}
}
}

View File

@@ -10,21 +10,21 @@ class a {
void f(int i) {
<warning descr="Variable 'i' is assigned to itself">i = i</warning>;
i = <warning descr="Variable 'i' is assigned to itself">i</warning>;
}
void f2() {
<warning descr="Variable 'f' is assigned to itself">this.f = f</warning>;
<warning descr="Variable 'f' is assigned to itself">a.this.f = f</warning>;
<warning descr="Variable 'f' is assigned to itself">f = this.f</warning>;
this.f = <warning descr="Variable 'f' is assigned to itself">f</warning>;
a.this.f = <warning descr="Variable 'f' is assigned to itself">f</warning>;
f = <warning descr="Variable 'f' is assigned to itself">this.f</warning>;
}
void f3(Object o) {
int i = 0;
<warning descr="Variable 'i' is assigned to itself">i = i</warning>;
<warning descr="Variable 'i' is assigned to itself">i = (int)i</warning>;
<warning descr="Variable 'o' is assigned to itself">o = ((Object)(o))</warning>;
Object o1 = <warning descr="Variable 'o' is assigned to itself">o = ((Object)(o))</warning>;
i = <warning descr="Variable 'i' is assigned to itself">i</warning>;
i = (int)<warning descr="Variable 'i' is assigned to itself">i</warning>;
o = ((Object)(<warning descr="Variable 'o' is assigned to itself">o</warning>));
Object o1 = o = ((Object)(<warning descr="Variable 'o' is assigned to itself">o</warning>));
System.out.println(o1);
o = (double)o;
}

View File

@@ -0,0 +1,3 @@
class C {
private String s;
}

View File

@@ -0,0 +1,3 @@
class C {
private String s = this.s<caret>;
}

View File

@@ -0,0 +1,3 @@
class C {
private String s = "initializer";
}

View File

@@ -0,0 +1,3 @@
class C {
private String s = this.s<caret> = "initializer";
}

View File

@@ -0,0 +1,3 @@
class X {
private final String s = this.<caret>s;
}

View File

@@ -0,0 +1,5 @@
class C {
void a(int i) {
System.out.println(i);
}
}

View File

@@ -0,0 +1,5 @@
class C {
void a(int i) {
System.out.println(i = <caret>i);
}
}

View File

@@ -0,0 +1,4 @@
class X {
void a(int i) {
}
}

View File

@@ -0,0 +1,5 @@
class X {
void a(int i) {
i = <caret>i;
}
}

View File

@@ -0,0 +1,5 @@
class C {
void a(int i) {
i =
}
}

View File

@@ -0,0 +1,5 @@
class C {
void a(int i) {
i = i<caret> =
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2000-2016 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.intellij.codeInspection;
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.sillyAssignment.SillyAssignmentInspection;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
/**
* @author Bas Leijdekkers
*/
public class RemoveSillyAssignmentFixTest extends LightCodeInsightFixtureTestCase {
public void testRemoveCompleteAssignment() { doTest(); }
public void testKeepReference() { doTest(); }
public void testFieldAssignsItself() { doTest(); }
public void testFieldKeepInitializer() { doTest(); }
public void testSillyButIncomplete() { doTest(); }
public void testFinalField() { assertQuickfixNotAvailable(); }
public void doTest() {
myFixture.enableInspections(SillyAssignmentInspection.class);
myFixture.configureByFile(getTestName(false) + ".java");
final IntentionAction intention = myFixture.findSingleIntention(InspectionsBundle.message("assignment.to.itself.quickfix.name"));
assertNotNull(intention);
myFixture.launchAction(intention);
myFixture.checkResultByFile(getTestName(false) + ".after.java");
}
protected void assertQuickfixNotAvailable() {
myFixture.enableInspections(SillyAssignmentInspection.class);
final String quickfixName = InspectionsBundle.message("assignment.to.itself.quickfix.name");
myFixture.configureByFile(getTestName(false) + ".java");
assertEmpty("Quickfix \'" + quickfixName + "\' is available unexpectedly", myFixture.filterAvailableIntentions(quickfixName));
}
@Override
protected String getTestDataPath() {
return JavaTestUtil.getJavaTestDataPath() + "/codeInspection/removeSillyAssignmentFix";
}
}

View File

@@ -703,6 +703,7 @@ special.annotations.list.annotation.pattern=Add Annotations Pattern
inspection.variable.assigned.to.itself.display.name=Variable is assigned to itself
assignment.to.itself.problem.descriptor=Variable ''{0}'' is assigned to itself
assignment.to.declared.variable.problem.descriptor=Variable ''{0}'' is initialized with self assignment
assignment.to.itself.quickfix.name=Remove self assignment
problematic.whitespace.display.name=Problematic whitespace
problematic.whitespace.tabs.problem.descriptor=File ''{0}'' uses tabs for indentation