blob: 2068ae96757d9a3df906ef420a66c4b651c47b1f [file] [log] [blame]
/*
* Copyright 2000-2009 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.refactoring.rename;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.usageView.UsageInfo;
import java.util.List;
public class JavaUnresolvableLocalCollisionDetector {
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.rename.JavaUnresolvableLocalCollisionDetector");
private JavaUnresolvableLocalCollisionDetector() {
}
public static void findCollisions(final PsiElement element, final String newName, final List<UsageInfo> result) {
if (!(element instanceof PsiLocalVariable || element instanceof PsiParameter)) {
return;
}
PsiElement scope;
PsiElement anchor = null;
if (element instanceof PsiLocalVariable) {
scope = RefactoringUtil.getVariableScope((PsiLocalVariable)element);
if (!(element instanceof ImplicitVariable)) {
anchor = element.getParent();
}
}
else {
// element is a PsiParameter
scope = ((PsiParameter)element).getDeclarationScope();
}
LOG.assertTrue(scope != null, element.getClass().getName());
final CollidingVariableVisitor collidingNameVisitor = new CollidingVariableVisitor() {
public void visitCollidingElement(PsiVariable collidingVariable) {
if (collidingVariable.equals(element)) return;
LocalHidesRenamedLocalUsageInfo collision = new LocalHidesRenamedLocalUsageInfo(element, collidingVariable);
result.add(collision);
}
};
visitLocalsCollisions(element, newName, scope, anchor, collidingNameVisitor);
/*PsiElement place = scope.getLastChild();
PsiResolveHelper helper = place.getManager().getResolveHelper();
PsiVariable refVar = helper.resolveReferencedVariable(newName, place, null);
if (refVar != null) {
LocalHidesRenamedLocalUsageInfo collision = new LocalHidesRenamedLocalUsageInfo(element, refVar);
result.add(collision);
}*/
}
public static void visitLocalsCollisions(PsiElement element, final String newName,
PsiElement scope,
PsiElement place,
final CollidingVariableVisitor collidingNameVisitor) {
if (scope == null) return;
visitDownstreamCollisions(scope, place, newName, collidingNameVisitor);
visitUpstreamLocalCollisions(element, scope, newName, collidingNameVisitor);
}
private static void visitDownstreamCollisions(PsiElement scope, PsiElement place, final String newName,
final CollidingVariableVisitor collidingNameVisitor
) {
ConflictingLocalVariablesVisitor collector =
new ConflictingLocalVariablesVisitor(newName, collidingNameVisitor);
if (place == null) {
scope.accept(collector);
}
else {
LOG.assertTrue(place.getParent() == scope);
for (PsiElement sibling = place; sibling != null; sibling = sibling.getNextSibling()) {
sibling.accept(collector);
}
}
}
public interface CollidingVariableVisitor {
void visitCollidingElement(PsiVariable collidingVariable);
}
private static void visitUpstreamLocalCollisions(PsiElement element, PsiElement scope,
String newName,
final CollidingVariableVisitor collidingNameVisitor) {
final PsiVariable collidingVariable =
JavaPsiFacade.getInstance(scope.getProject()).getResolveHelper().resolveAccessibleReferencedVariable(newName, scope);
if (collidingVariable instanceof PsiLocalVariable || collidingVariable instanceof PsiParameter) {
final PsiElement commonParent = PsiTreeUtil.findCommonParent(element, collidingVariable);
if (commonParent != null) {
PsiElement current = element;
while (current != null && current != commonParent) {
if (current instanceof PsiMethod || current instanceof PsiClass) {
return;
}
current = current.getParent();
}
}
collidingNameVisitor.visitCollidingElement(collidingVariable);
}
}
public static class ConflictingLocalVariablesVisitor extends JavaRecursiveElementWalkingVisitor {
protected final String myName;
protected CollidingVariableVisitor myCollidingNameVisitor;
public ConflictingLocalVariablesVisitor(String newName, CollidingVariableVisitor collidingNameVisitor) {
myName = newName;
myCollidingNameVisitor = collidingNameVisitor;
}
@Override public void visitReferenceExpression(PsiReferenceExpression expression) {
visitElement(expression);
}
@Override
public void visitField(PsiField field) {
if (myName.equals(field.getName())) {
myCollidingNameVisitor.visitCollidingElement(field);
}
}
@Override public void visitVariable(PsiVariable variable) {
if (myName.equals(variable.getName())) {
myCollidingNameVisitor.visitCollidingElement(variable);
}
}
}
}