2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com
.intellij
.refactoring
.rename
;
18 import com
.intellij
.openapi
.diagnostic
.Logger
;
19 import com
.intellij
.psi
.*;
20 import com
.intellij
.psi
.util
.PsiTreeUtil
;
21 import com
.intellij
.refactoring
.util
.RefactoringUtil
;
22 import com
.intellij
.usageView
.UsageInfo
;
24 import java
.util
.List
;
26 public class JavaUnresolvableLocalCollisionDetector
{
27 private static final Logger LOG
= Logger
.getInstance("#com.intellij.refactoring.rename.JavaUnresolvableLocalCollisionDetector");
29 private JavaUnresolvableLocalCollisionDetector() {
32 public static void findCollisions(final PsiElement element
, final String newName
, final List
<UsageInfo
> result
) {
33 if (!(element
instanceof PsiLocalVariable
|| element
instanceof PsiParameter
)) {
39 PsiElement anchor
= null;
40 if (element
instanceof PsiLocalVariable
) {
41 scope
= RefactoringUtil
.getVariableScope((PsiLocalVariable
)element
);
42 if (!(element
instanceof ImplicitVariable
)) {
43 anchor
= element
.getParent();
47 // element is a PsiParameter
48 scope
= ((PsiParameter
)element
).getDeclarationScope();
50 LOG
.assertTrue(scope
!= null);
52 final CollidingVariableVisitor collidingNameVisitor
= new CollidingVariableVisitor() {
53 public void visitCollidingElement(PsiVariable collidingVariable
) {
54 if (collidingVariable
.equals(element
) || collidingVariable
instanceof PsiField
) return;
55 LocalHidesRenamedLocalUsageInfo collision
= new LocalHidesRenamedLocalUsageInfo(element
, collidingVariable
);
56 result
.add(collision
);
60 visitLocalsCollisions(element
, newName
, scope
, anchor
, collidingNameVisitor
);
63 /*PsiElement place = scope.getLastChild();
64 PsiResolveHelper helper = place.getManager().getResolveHelper();
65 PsiVariable refVar = helper.resolveReferencedVariable(newName, place, null);
68 LocalHidesRenamedLocalUsageInfo collision = new LocalHidesRenamedLocalUsageInfo(element, refVar);
69 result.add(collision);
73 public static void visitLocalsCollisions(PsiElement element
, final String newName
,
76 final CollidingVariableVisitor collidingNameVisitor
) {
77 if (scope
== null) return;
78 visitDownstreamCollisions(scope
, place
, newName
, collidingNameVisitor
);
79 visitUpstreamLocalCollisions(element
, scope
, newName
, collidingNameVisitor
);
82 private static void visitDownstreamCollisions(PsiElement scope
, PsiElement place
, final String newName
,
83 final CollidingVariableVisitor collidingNameVisitor
85 ConflictingLocalVariablesVisitor collector
=
86 new ConflictingLocalVariablesVisitor(newName
, collidingNameVisitor
);
88 scope
.accept(collector
);
91 LOG
.assertTrue(place
.getParent() == scope
);
92 for (PsiElement sibling
= place
; sibling
!= null; sibling
= sibling
.getNextSibling()) {
93 sibling
.accept(collector
);
99 public interface CollidingVariableVisitor
{
100 void visitCollidingElement(PsiVariable collidingVariable
);
103 private static void visitUpstreamLocalCollisions(PsiElement element
, PsiElement scope
,
105 final CollidingVariableVisitor collidingNameVisitor
) {
106 final PsiVariable collidingVariable
=
107 JavaPsiFacade
.getInstance(scope
.getProject()).getResolveHelper().resolveReferencedVariable(newName
, scope
);
108 if (collidingVariable
instanceof PsiLocalVariable
|| collidingVariable
instanceof PsiParameter
) {
109 final PsiElement commonParent
= PsiTreeUtil
.findCommonParent(element
, collidingVariable
);
110 if (commonParent
!= null) {
111 PsiElement current
= element
;
112 while (current
!= null && current
!= commonParent
) {
113 if (current
instanceof PsiMethod
|| current
instanceof PsiClass
) {
116 current
= current
.getParent();
121 if (collidingVariable
!= null) {
122 collidingNameVisitor
.visitCollidingElement(collidingVariable
);
126 public static class ConflictingLocalVariablesVisitor
extends JavaRecursiveElementWalkingVisitor
{
127 protected final String myName
;
128 protected CollidingVariableVisitor myCollidingNameVisitor
;
130 public ConflictingLocalVariablesVisitor(String newName
, CollidingVariableVisitor collidingNameVisitor
) {
132 myCollidingNameVisitor
= collidingNameVisitor
;
135 @Override public void visitReferenceExpression(PsiReferenceExpression expression
) {
136 visitElement(expression
);
139 @Override public void visitClass(PsiClass aClass
) {
142 @Override public void visitVariable(PsiVariable variable
) {
143 if (myName
.equals(variable
.getName())) {
144 myCollidingNameVisitor
.visitCollidingElement(variable
);