KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > api > java > source > query > ReferenceFinder


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.api.java.source.query;
21
22 import org.netbeans.modules.java.source.engine.EngineEnvironment;
23 import org.netbeans.api.java.source.ElementUtilities;
24 import org.netbeans.api.java.source.query.ElementReferenceList;
25 import com.sun.source.tree.AssignmentTree;
26 import com.sun.source.tree.CompoundAssignmentTree;
27 import com.sun.source.tree.ExpressionTree;
28 import com.sun.source.tree.IdentifierTree;
29 import com.sun.source.tree.ImportTree;
30 import com.sun.source.tree.MemberSelectTree;
31 import com.sun.source.tree.MethodInvocationTree;
32 import com.sun.source.tree.MethodTree;
33 import com.sun.source.tree.NewArrayTree;
34 import com.sun.source.tree.NewClassTree;
35 import com.sun.source.tree.Tree;
36 import com.sun.source.tree.UnaryTree;
37 import com.sun.source.tree.VariableTree;
38 import com.sun.source.util.TreeScanner;
39 import java.util.HashMap JavaDoc;
40 import java.util.Map JavaDoc;
41 import java.util.Set JavaDoc;
42 import javax.lang.model.element.Element;
43 import javax.lang.model.element.ExecutableElement;
44 import javax.lang.model.element.PackageElement;
45 import javax.lang.model.element.TypeElement;
46 import org.netbeans.modules.java.source.engine.EngineEnvironment;
47 import org.netbeans.modules.java.source.engine.ASTModel;
48
49 import static org.netbeans.api.java.source.query.UseFinder.*;
50
51 /**
52  * Version of UseFinder which finds multiple references in a single pass.
53  *
54  * @author Tom Ball
55  */

56 public class ReferenceFinder extends TreeScanner<Void JavaDoc,Object JavaDoc> {
57     private ASTModel model;
58     private ElementUtilities elements;
59     private Element currentSym;
60     Map JavaDoc<Element, ElementReferenceList<Element>> elementReferences;
61     
62     /**
63      * Create a ReferenceFinder for a given set of elements over a specified
64      * root tree node.
65      *
66      *
67      * @param env the QueryEnvironment associated with the elements.
68      * @param elementSet the set of elements for which references are to be found.
69      * @param root the tree node to search for references.
70      */

71     public static ReferenceFinder findReferences(QueryEnvironment env, Set JavaDoc<Element> elementSet, Tree root) {
72         ReferenceFinder finder = new ReferenceFinder(env, elementSet);
73         finder.scan(root, null);
74         return finder;
75     }
76
77     /**
78      * Create a ReferenceFinder for a given set of elements.
79      *
80      *
81      * @param env the QueryEnvironment associated with the elements.
82      * @param elementSet the set of elements for which references are to be found.
83      */

84     protected ReferenceFinder(QueryEnvironment env, Set JavaDoc<Element> elementSet) {
85         this.model = ((EngineEnvironment)env).getModel();
86         elements = env.getElementUtilities();
87         elementReferences = new HashMap JavaDoc<Element,ElementReferenceList<Element>>();
88         for (Element e : elementSet)
89             elementReferences.put(e, new ElementReferenceList<Element>(e));
90     }
91
92     /**
93      * Returns the reference list for a specified element.
94      * <p>
95      * Note: a reference list for an element always contains at least
96      * that element, as a declaration is a form of reference.
97      *
98      * @param var the element for which references are requested.
99      * @return the list of references for the specified element, or null if
100      * var is not a member of the set of elements this ReferenceFinder
101      * was to search for.
102      */

103     public ElementReferenceList<Element> get(Element var) {
104         return elementReferences.get(var);
105     }
106     
107     /**
108      * Returns true if element is a member of the set which this ReferenceFinder
109      * was initialized with.
110      * @see #findReferences
111      */

112     public boolean hasReferences(Element var) {
113         return elementReferences.containsKey(var);
114     }
115     
116     /**
117      * TreeScanner.scan() implementation. This method is not normally called
118      * directly, but may be overridden by a subclass.
119      */

120     @Override JavaDoc
121     public Void JavaDoc scan(Tree tree, Object JavaDoc p) {
122         if(tree != null) {
123             Tree.Kind kind = tree.getKind();
124             boolean saveSymbol =
125                     kind == Tree.Kind.CLASS ||
126                     kind == Tree.Kind.METHOD ||
127                     kind == Tree.Kind.VARIABLE;
128             Element sym = model.getElement(tree);
129             if (sym != null && saveSymbol) {
130                 Element oldSym = currentSym;
131                 currentSym = sym;
132                 tree.accept(this, p);
133                 currentSym = oldSym;
134             }
135             else
136                 tree.accept(this, p);
137         }
138         return null;
139     }
140
141
142     private void add(Tree var, int usage) {
143         Element sym = model.getElement(var);
144         ElementReferenceList<Element> varRef = elementReferences.get(sym);
145         if (varRef == null) // true if element is not "interesting"
146
return;
147         if (currentSym == null)
148
149             throw new AssertionError JavaDoc("no currentSym");
150         TypeElement here = elements.enclosingTypeElement(currentSym);
151         PackageElement phere = elements.packageElement(here);
152         int flags = usage <<
153                     (here == varRef.varClass ? CLASSSHIFT
154                    : phere == varRef.varPackage ? PACKAGESHIFT
155                                                 : WORLDSHIFT);
156         varRef.addReference(currentSym, flags);
157     }
158
159     /**
160      * TreeScanner visitor method. This method should not be called
161      * directly, but may be overridden by a subclass.
162      */

163     @Override JavaDoc
164     public Void JavaDoc visitAssignment(AssignmentTree tree, Object JavaDoc p) {
165         if (tree.getVariable() instanceof MemberSelectTree) {
166             MemberSelectTree t = (MemberSelectTree)tree.getVariable();
167             add(t, SETUSE);
168             scan(t.getExpression(), p);
169         } else if (tree.getVariable() instanceof IdentifierTree) {
170             add(tree, SETUSE);
171         } else
172             scan(tree.getVariable(), p);
173         scan(tree.getExpression(), p);
174         return null;
175     }
176
177     /**
178      * TreeScanner visitor method. This method should not be called
179      * directly, but may be overridden by a subclass.
180      */

181     @Override JavaDoc
182     public Void JavaDoc visitCompoundAssignment(CompoundAssignmentTree tree, Object JavaDoc p) {
183         if (tree.getVariable() instanceof MemberSelectTree) {
184             MemberSelectTree t = (MemberSelectTree)tree.getVariable();
185             scan(t.getExpression(), p);
186             add(t, SETUSE | GETUSE);
187         } else if (tree.getVariable() instanceof IdentifierTree) {
188             add(tree, SETUSE | GETUSE);
189         } else
190             scan(tree.getVariable(), p);
191         scan(tree.getExpression(), p);
192         return null;
193     }
194
195     /**
196      * TreeScanner visitor method. This method should not be called
197      * directly, but may be overridden by a subclass.
198      */

199     @Override JavaDoc
200     public Void JavaDoc visitUnary(UnaryTree tree, Object JavaDoc p) {
201         switch (tree.getKind()) {
202           case PREFIX_INCREMENT:
203           case PREFIX_DECREMENT:
204           case POSTFIX_INCREMENT:
205           case POSTFIX_DECREMENT: {
206             ExpressionTree expr = tree.getExpression();
207             if (expr instanceof MemberSelectTree) {
208                 scan(((MemberSelectTree)expr).getExpression(), p);
209                 add(expr, SETUSE | GETUSE);
210             } else if (tree.getExpression() instanceof IdentifierTree) {
211                 add(expr, SETUSE | GETUSE);
212             } else
213                 scan(tree.getExpression(), p);
214             break;
215           }
216           default:
217             scan(tree.getExpression(), p);
218         }
219         return null;
220     }
221
222     /**
223      * TreeScanner visitor method. This method should not be called
224      * directly, but may be overridden by a subclass.
225      */

226     @Override JavaDoc
227     public Void JavaDoc visitIdentifier(IdentifierTree tree, Object JavaDoc p) {
228         add(tree, GETUSE);
229         return super.visitIdentifier(tree, p);
230     }
231
232     /**
233      * TreeScanner visitor method. This method should not be called
234      * directly, but may be overridden by a subclass.
235      */

236     @Override JavaDoc
237     public Void JavaDoc visitVariable(VariableTree tree, Object JavaDoc p) {
238         ElementReferenceList<Element> varRef = elementReferences.get(model.getElement(tree));
239         if (varRef != null) {
240             int flags = DECLARATION;
241             if (tree.getInitializer() != null)
242                 flags |= SETUSE << CLASSSHIFT;
243             varRef.addReference(currentSym, flags);
244         }
245         return super.visitVariable(tree, p);
246     }
247
248     /**
249      * TreeScanner visitor method. This method should not be called
250      * directly, but may be overridden by a subclass.
251      */

252     @Override JavaDoc
253     public Void JavaDoc visitMethod(MethodTree tree, Object JavaDoc p) {
254         ExecutableElement e = (ExecutableElement)model.getElement(tree);
255         ElementReferenceList<Element> methodRefs = elementReferences.get(e);
256         if (methodRefs != null)
257             methodRefs.addReference(e, DECLARATION);
258         ExecutableElement superMethod = elements.getOverriddenMethod(e);
259         if (superMethod != null) {
260             methodRefs = elementReferences.get(superMethod);
261             if (methodRefs != null)
262                 methodRefs.addReference(superMethod, GETUSE);
263         }
264         return super.visitMethod(tree, p);
265     }
266
267     /**
268      * TreeScanner visitor method. This method should not be called
269      * directly, but may be overridden by a subclass.
270      */

271     @Override JavaDoc
272     public Void JavaDoc visitMethodInvocation(MethodInvocationTree tree, Object JavaDoc p) {
273         Tree method = tree.getMethodSelect();
274         ElementReferenceList<Element> methodRef = elementReferences.get(model.getElement(method));
275         if (methodRef != null)
276             methodRef.addReference(currentSym, GETUSE);
277         return super.visitMethodInvocation(tree, p);
278     }
279
280     /**
281      * TreeScanner visitor method. This method should not be called
282      * directly, but may be overridden by a subclass.
283      */

284     @Override JavaDoc
285     public Void JavaDoc visitNewClass(NewClassTree tree, Object JavaDoc p) {
286         ElementReferenceList<Element> constructorRef = elementReferences.get(model.getElement(tree));
287         if (constructorRef != null)
288             constructorRef.addReference(currentSym, GETUSE);
289         return super.visitNewClass(tree, p);
290     }
291
292     /**
293      * TreeScanner visitor method. This method should not be called
294      * directly, but may be overridden by a subclass.
295      */

296     @Override JavaDoc
297     public Void JavaDoc visitNewArray(NewArrayTree tree, Object JavaDoc p) {
298         Tree type = tree.getType();
299         if (type != null) { // true for array variable declarations
300
ElementReferenceList<Element> typeRef = elementReferences.get(model.getElement(type));
301             if (typeRef != null)
302                 typeRef.addReference(currentSym, GETUSE);
303         }
304         return super.visitNewArray(tree, p);
305     }
306
307     /**
308      * TreeScanner visitor method. This method should not be called
309      * directly, but may be overridden by a subclass.
310      */

311     @Override JavaDoc
312     public Void JavaDoc visitMemberSelect(MemberSelectTree tree, Object JavaDoc p) {
313         add(tree, GETUSE);
314         return super.visitMemberSelect(tree, p);
315     }
316
317     /**
318      * TreeScanner visitor method. This method should not be called
319      * directly, but may be overridden by a subclass.
320      */

321     @Override JavaDoc
322     public Void JavaDoc visitImport(ImportTree tree, Object JavaDoc p) {
323         return null; // skip imports
324
}
325 }
326
Popular Tags