safe delete: enable on local variables; treat side effects as conflicts ( IDEA-17366 )

This commit is contained in:
anna
2010-05-21 13:53:13 +04:00
parent 7cdc82b8bc
commit abfb0af852
7 changed files with 65 additions and 11 deletions

View File

@@ -40,7 +40,7 @@ public class JavaRefactoringSupportProvider extends DefaultRefactoringSupportPro
public boolean isSafeDeleteAvailable(PsiElement element) {
return element instanceof PsiClass || element instanceof PsiMethod || element instanceof PsiField ||
(element instanceof PsiParameter && ((PsiParameter)element).getDeclarationScope() instanceof PsiMethod) ||
element instanceof PsiPackage;
element instanceof PsiPackage || element instanceof PsiLocalVariable;
}
public RefactoringActionHandler getIntroduceConstantHandler() {

View File

@@ -15,6 +15,7 @@
*/
package com.intellij.refactoring.safeDelete;
import com.intellij.codeInsight.daemon.impl.quickfix.RemoveUnusedVariableFix;
import com.intellij.ide.util.SuperMethodWarningUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -30,10 +31,7 @@ import com.intellij.psi.javadoc.PsiDocTag;
import com.intellij.psi.search.searches.OverridingMethodsSearch;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.search.searches.SuperMethodsSearch;
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
import com.intellij.psi.util.MethodSignatureUtil;
import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.*;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.safeDelete.usageInfo.*;
import com.intellij.refactoring.util.RefactoringMessageUtil;
@@ -53,7 +51,7 @@ public class JavaSafeDeleteProcessor implements SafeDeleteProcessorDelegate {
public boolean handlesElement(final PsiElement element) {
return element instanceof PsiClass || element instanceof PsiMethod ||
element instanceof PsiField || element instanceof PsiParameter;
element instanceof PsiField || element instanceof PsiParameter || element instanceof PsiLocalVariable;
}
@Nullable
@@ -75,6 +73,20 @@ public class JavaSafeDeleteProcessor implements SafeDeleteProcessorDelegate {
LOG.assertTrue(((PsiParameter) element).getDeclarationScope() instanceof PsiMethod);
findParameterUsages((PsiParameter)element, usages);
}
else if (element instanceof PsiLocalVariable) {
for (PsiReference reference : ReferencesSearch.search(element)) {
PsiReferenceExpression referencedElement = (PsiReferenceExpression)reference.getElement();
final PsiStatement statement = PsiTreeUtil.getParentOfType(referencedElement, PsiStatement.class);
boolean isSafeToDelete = PsiUtil.isAccessedForWriting(referencedElement);
boolean hasSideEffects = false;
if (PsiUtil.isOnAssignmentLeftHand(referencedElement)) {
hasSideEffects =
RemoveUnusedVariableFix.checkSideEffects(((PsiAssignmentExpression)referencedElement.getParent()).getRExpression(), ((PsiLocalVariable)element), new ArrayList<PsiElement>());
}
usages.add(new SafeDeleteReferenceJavaDeleteUsageInfo(statement, element, isSafeToDelete && !hasSideEffects));
}
}
return new NonCodeUsageSearchInfo(insideDeletedCondition, element);
}
@@ -468,7 +480,6 @@ public class JavaSafeDeleteProcessor implements SafeDeleteProcessorDelegate {
@Nullable
private static PsiMethod getOverridingConstructorOfSuperCall(final PsiElement element) {
PsiMethod overridingConstructor = null;
if(element instanceof PsiReferenceExpression && "super".equals(element.getText())) {
PsiElement parent = element.getParent();
if(parent instanceof PsiMethodCallExpression) {
@@ -478,13 +489,13 @@ public class JavaSafeDeleteProcessor implements SafeDeleteProcessorDelegate {
if(parent instanceof PsiCodeBlock) {
parent = parent.getParent();
if(parent instanceof PsiMethod && ((PsiMethod) parent).isConstructor()) {
overridingConstructor = (PsiMethod) parent;
return (PsiMethod) parent;
}
}
}
}
}
return overridingConstructor;
return null;
}
private static boolean canBePrivate(PsiMethod method, Collection<PsiReference> references, Collection<? extends PsiElement> deleted,

View File

@@ -0,0 +1,5 @@
class Super {
void foo() {
}
}

View File

@@ -0,0 +1,8 @@
class Super {
void foo() {
int var<caret>Name = 0;
varName++;
varName = 10;
}
}

View File

@@ -0,0 +1,5 @@
class Super {
void foo() {
}
}

View File

@@ -0,0 +1,9 @@
class Super {
void foo() {
int var<caret>Name = 0;
varName++;
varName = bar();
}
int bar() {return 0;}
}

View File

@@ -2,7 +2,6 @@ package com.intellij.refactoring;
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.idea.Bombed;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
@@ -13,7 +12,6 @@ import com.intellij.testFramework.IdeaTestUtil;
import org.jetbrains.annotations.NonNls;
import java.io.File;
import java.util.Calendar;
public class SafeDeleteTest extends MultiFileTestCase {
private VirtualFile myRootBefore;
@@ -79,6 +77,24 @@ public class SafeDeleteTest extends MultiFileTestCase {
}
}
public void testLocalVariable() throws Exception {
myDoCompare = false;
doTest("Super");
}
public void testLocalVariableSideEffect() throws Exception {
myDoCompare = false;
try {
doTest("Super");
fail("Side effect was ignored");
}
catch (BaseRefactoringProcessor.ConflictsInTestsException e) {
String message = e.getMessage();
assertTrue(message, message.startsWith("local variable <b><code>varName</code></b> has 1 usage that is not safe to delete.\n" +
"Of those 0 usages are in strings, comments, or non-Java files."));
}
}
private void doTest(@NonNls final String qClassName) throws Exception {
doTest(new PerformAction() {
public void performAction(VirtualFile rootDir, VirtualFile rootAfter) throws Exception {