diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/defUse/DefUseInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/defUse/DefUseInspectionBase.java index 9e3c2a9b6246..fa0a0e3f8bf9 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/defUse/DefUseInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/defUse/DefUseInspectionBase.java @@ -101,7 +101,8 @@ public class DefUseInspectionBase extends BaseJavaBatchLocalInspectionTool { final PsiAssignmentExpression assignment = (PsiAssignmentExpression)context; holder.registerProblem(assignment.getLExpression(), InspectionsBundle.message("inspection.unused.assignment.problem.descriptor3", - assignment.getRExpression().getText(), "#ref" + " #loc"), ProblemHighlightType.LIKE_UNUSED_SYMBOL); + assignment.getRExpression().getText(), "#ref" + " #loc"), + ProblemHighlightType.LIKE_UNUSED_SYMBOL, createRemoveAssignmentFix()); } else { if (context instanceof PsiPrefixExpression && REPORT_PREFIX_EXPRESSIONS || @@ -153,6 +154,10 @@ public class DefUseInspectionBase extends BaseJavaBatchLocalInspectionTool { return null; } + protected LocalQuickFix createRemoveAssignmentFix() { + return null; + } + @Override public JComponent createOptionsPanel() { return new OptionsPanel(); diff --git a/java/java-impl/src/com/intellij/codeInspection/defUse/DefUseInspection.java b/java/java-impl/src/com/intellij/codeInspection/defUse/DefUseInspection.java index 8b19def82111..1c4b8a7a8012 100644 --- a/java/java-impl/src/com/intellij/codeInspection/defUse/DefUseInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/defUse/DefUseInspection.java @@ -50,6 +50,30 @@ public class DefUseInspection extends DefUseInspectionBase { return new RemoveInitializerFix(); } + @Override + protected LocalQuickFix createRemoveAssignmentFix() { + return new RemoveAssignmentFix(); + } + + private static class RemoveAssignmentFix extends RemoveInitializerFix { + @NotNull + @Override + public String getName() { + return InspectionsBundle.message("inspection.unused.assignment.remove.assignment.quickfix"); + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + final PsiElement left = descriptor.getPsiElement(); + if (!(left instanceof PsiReferenceExpression)) return; + final PsiElement parent = left.getParent(); + if (!(parent instanceof PsiAssignmentExpression)) return; + + final PsiElement resolve = ((PsiReferenceExpression)left).resolve(); + if (!(resolve instanceof PsiVariable)) return; + sideEffectAwareRemove(project, ((PsiAssignmentExpression)parent).getRExpression(), parent, (PsiVariable)resolve); + } + } private static class RemoveInitializerFix implements LocalQuickFix { @Override @NotNull @@ -62,9 +86,14 @@ public class DefUseInspection extends DefUseInspectionBase { final PsiElement psiInitializer = descriptor.getPsiElement(); if (!(psiInitializer instanceof PsiExpression)) return; if (!(psiInitializer.getParent() instanceof PsiVariable)) return; - if (!FileModificationService.getInstance().prepareFileForWrite(psiInitializer.getContainingFile())) return; final PsiVariable variable = (PsiVariable)psiInitializer.getParent(); + sideEffectAwareRemove(project, psiInitializer, psiInitializer, variable); + } + + protected void sideEffectAwareRemove(Project project, PsiElement psiInitializer, PsiElement elementToDelete, PsiVariable variable) { + if (!FileModificationService.getInstance().prepareFileForWrite(psiInitializer.getContainingFile())) return; + final PsiDeclarationStatement declaration = (PsiDeclarationStatement)variable.getParent(); final List sideEffects = new ArrayList(); boolean hasSideEffects = RemoveUnusedVariableUtil.checkSideEffects(psiInitializer, variable, sideEffects); @@ -74,25 +103,30 @@ public class DefUseInspection extends DefUseInspectionBase { res = RemoveUnusedVariableFix.showSideEffectsWarning(sideEffects, variable, FileEditorManager.getInstance(project).getSelectedTextEditor(), hasSideEffects, sideEffects.get(0).getText(), - variable.getTypeElement().getText() + " " + variable.getName() + ";
" + PsiExpressionTrimRenderer - .render((PsiExpression)psiInitializer)); + variable.getTypeElement().getText() + + " " + + variable.getName() + + ";
" + + PsiExpressionTrimRenderer + .render((PsiExpression)psiInitializer) + ); } try { if (res == RemoveUnusedVariableUtil.DELETE_ALL) { - psiInitializer.delete(); + elementToDelete.delete(); } else if (res == RemoveUnusedVariableUtil.MAKE_STATEMENT) { - final PsiElementFactory factory = JavaPsiFacade.getInstance(variable.getProject()).getElementFactory(); + final PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory(); final PsiStatement statementFromText = factory.createStatementFromText(psiInitializer.getText() + ";", null); declaration.getParent().addAfter(statementFromText, declaration); - psiInitializer.delete(); + elementToDelete.delete(); } } catch (IncorrectOperationException e) { LOG.error(e); } } - + @Override @NotNull public String getFamilyName() { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/unusedAssignment/afterNoSideEffect.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/unusedAssignment/afterNoSideEffect.java new file mode 100644 index 000000000000..6819587b3329 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/unusedAssignment/afterNoSideEffect.java @@ -0,0 +1,8 @@ +// "Remove redundant assignment" "true" +class A { + void m() { + int i; + i = 0; + System.out.println(i); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/unusedAssignment/beforeNoSideEffect.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/unusedAssignment/beforeNoSideEffect.java new file mode 100644 index 000000000000..1c8b767bdad5 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/unusedAssignment/beforeNoSideEffect.java @@ -0,0 +1,9 @@ +// "Remove redundant assignment" "true" +class A { + void m() { + int i; + i = 9; + i = 0; + System.out.println(i); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/EmptyIntentionInspectionQuickFixTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/EmptyIntentionInspectionQuickFixTest.java index 579081a99cc5..50258fd8f302 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/EmptyIntentionInspectionQuickFixTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/EmptyIntentionInspectionQuickFixTest.java @@ -5,6 +5,7 @@ import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.LocalInspectionTool; import com.intellij.codeInspection.ProblemsHolder; import com.intellij.codeInspection.defUse.DefUseInspection; +import com.intellij.codeInspection.ex.EditInspectionToolsSettingsAction; import com.intellij.psi.JavaElementVisitor; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiLiteralExpression; @@ -88,7 +89,7 @@ public class EmptyIntentionInspectionQuickFixTest extends LightQuickFixTestCase } assertTrue(i < emptyActions.size()); for (; i < emptyActions.size(); i++) { - if (emptyActions.get(i) instanceof EmptyIntentionAction) { + if (emptyActions.get(i) instanceof EditInspectionToolsSettingsAction) { return; } } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveUnusedAssignmentTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveUnusedAssignmentTest.java new file mode 100644 index 000000000000..a8816f832323 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveUnusedAssignmentTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2000-2014 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.codeInsight.daemon.quickFix; + +import com.intellij.codeInspection.LocalInspectionTool; +import com.intellij.codeInspection.defUse.DefUseInspection; +import com.intellij.pom.java.LanguageLevel; +import org.jetbrains.annotations.NotNull; + +public class RemoveUnusedAssignmentTest extends LightQuickFixTestCase { + public void test() throws Exception { doAllTests(); } + + @NotNull + @Override + protected LocalInspectionTool[] configureLocalInspectionTools() { + return new LocalInspectionTool[] {new DefUseInspection()}; + } + + @Override + protected String getBasePath() { + return "/codeInsight/daemonCodeAnalyzer/quickFix/unusedAssignment"; + } + + @Override + protected LanguageLevel getLanguageLevel() { + return LanguageLevel.JDK_1_5; + } +} diff --git a/platform/platform-resources-en/src/messages/InspectionsBundle.properties b/platform/platform-resources-en/src/messages/InspectionsBundle.properties index 4f7d14ae7e76..eff9ee33d6f8 100644 --- a/platform/platform-resources-en/src/messages/InspectionsBundle.properties +++ b/platform/platform-resources-en/src/messages/InspectionsBundle.properties @@ -185,6 +185,7 @@ inspection.unused.assignment.option=Report ++i when may be replaced with (i + 1) inspection.unused.assignment.option1=Report i++ when changed value is not used afterwards inspection.unused.assignment.option2=Report redundant initializers inspection.unused.assignment.remove.quickfix=Remove Redundant Initializer +inspection.unused.assignment.remove.assignment.quickfix=Remove redundant assignment inspection.unused.assignment.problem.descriptor1=Variable {0} is never used inspection.unused.assignment.problem.descriptor2=Variable {0} initializer {1} is redundant inspection.unused.assignment.problem.descriptor3=The value {0} assigned to {1} is never used