2
* Sun Public License Notice
4
* The contents of this file are subject to the Sun Public License
5
* Version 1.0 (the "License"). You may not use this file except in
6
* compliance with the License. A copy of the License is available at
9
* The Original Code is NetBeans. The Initial Developer of the Original
10
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2005 Sun
11
* Microsystems, Inc. All Rights Reserved.
13
If you wish your version of this file to be governed by only the CDDL
14
or only the GPL Version 2, indicate your decision by adding
15
"[Contributor] elects to include this software in this distribution
16
under the [CDDL or GPL Version 2] license." If you do not indicate a
17
single choice of license, a recipient has the option to distribute
18
your version of this file under either the CDDL, the GPL Version 2 or
19
to extend the choice of license to its licensees as provided above.
20
However, if you add GPL Version 2 code and therefore, elected the GPL
21
Version 2 license, then the option applies only if the new code is
22
made subject to such option by the copyright holder.
25
package org.netbeans.modules.refactoring.java.plugins;
27
import org.netbeans.modules.refactoring.java.api.*;
28
import com.sun.source.tree.AssignmentTree;
29
import com.sun.source.tree.ExpressionTree;
30
import com.sun.source.tree.MemberSelectTree;
31
import com.sun.source.tree.Tree;
32
import com.sun.source.tree.VariableTree;
33
import com.sun.source.util.TreePath;
34
import com.sun.source.util.Trees;
35
import java.util.List;
37
import javax.lang.model.element.Element;
38
import javax.lang.model.element.ElementKind;
39
import javax.lang.model.element.ExecutableElement;
40
import javax.lang.model.element.Modifier;
41
import javax.lang.model.element.TypeElement;
42
import javax.lang.model.element.VariableElement;
43
import javax.lang.model.type.DeclaredType;
44
import javax.lang.model.type.TypeKind;
45
import javax.lang.model.type.TypeMirror;
46
import javax.lang.model.util.Elements;
47
import javax.lang.model.util.Types;
48
import org.netbeans.api.java.source.WorkingCopy;
49
import org.netbeans.modules.refactoring.java.spi.RefactoringVisitor;
50
import org.netbeans.modules.refactoring.java.spi.ToPhaseException;
51
import org.openide.util.Exceptions;
54
* @author Jan Becicka, Bharath Ravi Kumar
56
class VarUsageVisitor extends RefactoringVisitor {
58
private final TypeElement superTypeElement;
59
private final TypeElement subTypeElement;
60
private boolean isReplCandidate = true;
62
VarUsageVisitor(TypeElement subTypeElement, WorkingCopy workingCopy,
63
TypeElement superTypeElem) {
65
setWorkingCopy(workingCopy);
66
} catch (ToPhaseException ex) {
67
Exceptions.printStackTrace(ex);
69
this.superTypeElement = superTypeElem;
70
this.subTypeElement = subTypeElement;
74
public Tree visitMemberSelect(MemberSelectTree memSelectTree, Element refVarElem) {
76
Element methodElement = this.asElement(memSelectTree);
77
Element varElement = asElement(memSelectTree.getExpression());
78
if (!refVarElem.equals(varElement)) {
79
return super.visitMemberSelect(memSelectTree, refVarElem);
82
boolean isAssgCmptble = isMemberAvailable(subTypeElement, methodElement,
85
isReplCandidate = false;
87
return super.visitMemberSelect(memSelectTree, refVarElem);
91
public Tree visitAssignment(AssignmentTree assgnTree, Element refVarElem) {
93
ExpressionTree exprnTree = assgnTree.getExpression();
94
Element exprElement = asElement(exprnTree);
95
if (!refVarElem.equals(exprElement)) {
96
return super.visitAssignment(assgnTree, refVarElem);
98
ExpressionTree varExprTree = assgnTree.getVariable();
100
VariableElement varElement = (VariableElement) asElement(varExprTree);
101
isReplCandidate = isReplacableAssgnmt(varElement) && isReplCandidate;
102
return super.visitAssignment(assgnTree, refVarElem);
106
public Tree visitVariable(VariableTree varTree, Element refVarElem) {
107
ExpressionTree initTree = varTree.getInitializer();
108
if (null == initTree) {
109
return super.visitVariable(varTree, refVarElem);
111
Element exprElement = asElement(initTree);
112
if (!refVarElem.equals(exprElement)) {
113
return super.visitVariable(varTree, refVarElem);
115
VariableElement varElement = (VariableElement) asElement(varTree);
116
isReplCandidate = isReplacableAssgnmt(varElement) && isReplCandidate;
117
return super.visitVariable(varTree, refVarElem);
120
private boolean isMemberAvailable(TypeElement subTypeElement, Element methodElement,
121
TypeElement superTypeElement) {
122
ElementKind memberKind = methodElement.getKind();
123
if(ElementKind.METHOD.equals(memberKind)){
124
return isMethodAvailable(subTypeElement, (ExecutableElement)methodElement,
127
return isHidingMember(subTypeElement, methodElement, superTypeElement);
131
private boolean isMethodAvailable(TypeElement subTypeElement,
132
ExecutableElement execElem, TypeElement superTypeElement) {
133
Elements elements = workingCopy.getElements();
134
List<? extends Element> memberElements = elements.getAllMembers(superTypeElement);
135
for (Element elem : memberElements) {
136
if(ElementKind.METHOD.equals(elem.getKind())){
137
if(isStatic(execElem) && elements.hides(execElem, elem)){
140
if(execElem.equals(elem) || elements.overrides(execElem, (ExecutableElement)elem,
151
private boolean isHidingMember(TypeElement subTypeElement, Element variableElement,
152
TypeElement superTypeElement) {
153
//TODO: We do not handle nested types yet (includes enums)
154
Elements elements = workingCopy.getElements();
155
List<? extends Element> memberElements = elements.getAllMembers(superTypeElement);
156
for (Element elem : memberElements) {
157
if(variableElement.equals(elem) || elements.hides(variableElement, elem)){
164
private boolean isReplacableAssgnmt(VariableElement varElement) {
165
if (isDeclaredType(varElement.asType())) {
166
DeclaredType declType = (DeclaredType) varElement.asType();
167
TypeElement varType = (TypeElement) declType.asElement();
168
if (isAssignable(superTypeElement, varType)) {
175
boolean isReplaceCandidate() {
176
return isReplCandidate;
179
private boolean isAssignable(TypeElement typeFrom, TypeElement typeTo) {
180
Types types = workingCopy.getTypes();
181
return types.isAssignable(typeFrom.asType(), typeTo.asType());
184
private Element asElement(Tree tree) {
185
Trees treeUtil = workingCopy.getTrees();
186
TreePath treePath = treeUtil.getPath(workingCopy.getCompilationUnit(), tree);
187
Element element = treeUtil.getElement(treePath);
191
private boolean isDeclaredType(TypeMirror type) {
192
return TypeKind.DECLARED.equals(type.getKind());
194
//TODO: This method can be shared. Copied from UseSuperTypeRefactoringPlugin.
195
private boolean isStatic(Element element) {
196
Set<Modifier> modifiers = element.getModifiers();
197
return modifiers.contains(Modifier.STATIC);