/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.plugin.ij.refactor;
import com.intellij.codeInsight.daemon.impl.quickfix.RemoveUnusedVariableFix;
import com.intellij.openapi.util.Condition;
import com.intellij.psi.*;
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.refactoring.safeDelete.JavaSafeDeleteProcessor;
import com.intellij.refactoring.safeDelete.NonCodeUsageSearchInfo;
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceJavaDeleteUsageInfo;
import com.intellij.usageView.UsageInfo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class GosuSafeDeleteProcessor extends JavaSafeDeleteProcessor {
@Nullable
public NonCodeUsageSearchInfo findUsages(final PsiElement element, final PsiElement[] allElementsToDelete, final List<UsageInfo> usages) {
if (element instanceof PsiLocalVariable) {
Condition<PsiElement> insideDeletedCondition = getUsageInsideDeletedFilter(allElementsToDelete);
for (PsiReference reference : ReferencesSearch.search(element)) {
PsiElement referencedElement = reference.getElement();
final PsiStatement statement = PsiTreeUtil.getParentOfType(referencedElement, PsiStatement.class);
boolean isSafeToDelete = isAccessedForWriting(referencedElement);
boolean hasSideEffects = false;
if (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);
}
return super.findUsages(element, allElementsToDelete, usages);
}
public static boolean isAccessedForWriting(@NotNull PsiElement expr) {
if (isOnAssignmentLeftHand(expr)) return true;
PsiElement parent = PsiTreeUtil.skipParentsOfType(expr, PsiParenthesizedExpression.class);
if (parent instanceof PsiPrefixExpression) {
IElementType tokenType = ((PsiPrefixExpression) parent).getOperationTokenType();
return tokenType == JavaTokenType.PLUSPLUS || tokenType == JavaTokenType.MINUSMINUS;
} else if (parent instanceof PsiPostfixExpression) {
IElementType tokenType = ((PsiPostfixExpression) parent).getOperationTokenType();
return tokenType == JavaTokenType.PLUSPLUS || tokenType == JavaTokenType.MINUSMINUS;
} else {
return false;
}
}
public static boolean isOnAssignmentLeftHand(@NotNull PsiElement expr) {
PsiElement parent = PsiTreeUtil.skipParentsOfType(expr, PsiParenthesizedExpression.class);
return parent instanceof PsiAssignmentExpression &&
PsiTreeUtil.isAncestor(((PsiAssignmentExpression) parent).getLExpression(), expr, false);
}
}