KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > dom > LinkedNodeFinder


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.corext.dom;
12
13 import java.util.ArrayList JavaDoc;
14
15 import org.eclipse.jdt.core.compiler.IProblem;
16 import org.eclipse.jdt.core.dom.ASTNode;
17 import org.eclipse.jdt.core.dom.ASTVisitor;
18 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
19 import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
20 import org.eclipse.jdt.core.dom.BreakStatement;
21 import org.eclipse.jdt.core.dom.CompilationUnit;
22 import org.eclipse.jdt.core.dom.ContinueStatement;
23 import org.eclipse.jdt.core.dom.EnumDeclaration;
24 import org.eclipse.jdt.core.dom.IBinding;
25 import org.eclipse.jdt.core.dom.IMethodBinding;
26 import org.eclipse.jdt.core.dom.ITypeBinding;
27 import org.eclipse.jdt.core.dom.IVariableBinding;
28 import org.eclipse.jdt.core.dom.LabeledStatement;
29 import org.eclipse.jdt.core.dom.MethodDeclaration;
30 import org.eclipse.jdt.core.dom.SimpleName;
31 import org.eclipse.jdt.core.dom.TypeDeclaration;
32
33
34 /**
35  * Find all nodes connected to a given binding or node. e.g. Declaration of a field and all references.
36  * For types this includes also the constructor declaration, for methods also overridden methods
37  * or methods overriding (if existing in the same AST)
38   */

39
40 public class LinkedNodeFinder {
41     
42     private LinkedNodeFinder() {
43     }
44     
45     
46     /**
47      * Find all nodes connected to the given binding. e.g. Declaration of a field and all references.
48      * For types this includes also the constructor declaration, for methods also overridden methods
49      * or methods overriding (if existing in the same AST)
50      * @param root The root of the AST tree to search
51      * @param binding The binding of the searched nodes
52      * @return Return
53      */

54     public static SimpleName[] findByBinding(ASTNode root, IBinding binding) {
55         ArrayList JavaDoc res= new ArrayList JavaDoc();
56         BindingFinder nodeFinder= new BindingFinder(binding, res);
57         root.accept(nodeFinder);
58         return (SimpleName[]) res.toArray(new SimpleName[res.size()]);
59     }
60     
61     /**
62      * Find all nodes connected to the given name node. If the node has a binding then all nodes connected
63      * to this binding are returned. If the node has no binding, then all nodes that also miss a binding and have
64      * the same name are returned.
65      * @param root The root of the AST tree to search
66      * @param name The node to find linked nodes for
67      * @return Return
68      */

69     public static SimpleName[] findByNode(ASTNode root, SimpleName name) {
70         IBinding binding = name.resolveBinding();
71         if (binding != null) {
72             return findByBinding(root, binding);
73         }
74         SimpleName[] names= findByProblems(root, name);
75         if (names != null) {
76             return names;
77         }
78         int parentKind= name.getParent().getNodeType();
79         if (parentKind == ASTNode.LABELED_STATEMENT || parentKind == ASTNode.BREAK_STATEMENT || parentKind == ASTNode.CONTINUE_STATEMENT) {
80             ArrayList JavaDoc res= new ArrayList JavaDoc();
81             LabelFinder nodeFinder= new LabelFinder(name, res);
82             root.accept(nodeFinder);
83             return (SimpleName[]) res.toArray(new SimpleName[res.size()]);
84         }
85         return new SimpleName[] { name };
86     }
87     
88     
89     
90     private static final int FIELD= 1;
91     private static final int METHOD= 2;
92     private static final int TYPE= 4;
93     private static final int LABEL= 8;
94     private static final int NAME= FIELD | TYPE;
95     
96     private static int getProblemKind(IProblem problem) {
97         switch (problem.getID()) {
98             case IProblem.UndefinedField:
99                 return FIELD;
100             case IProblem.UndefinedMethod:
101                 return METHOD;
102             case IProblem.UndefinedLabel:
103                 return LABEL;
104             case IProblem.UndefinedName:
105                 return NAME;
106             case IProblem.UndefinedType:
107                 return TYPE;
108         }
109         return 0;
110     }
111     
112     private static int getNameNodeProblemKind(IProblem[] problems, SimpleName nameNode) {
113         int nameOffset= nameNode.getStartPosition();
114         int nameInclEnd= nameOffset + nameNode.getLength() - 1;
115         
116         for (int i= 0; i < problems.length; i++) {
117             IProblem curr= problems[i];
118             if (curr.getSourceStart() == nameOffset && curr.getSourceEnd() == nameInclEnd) {
119                 int kind= getProblemKind(curr);
120                 if (kind != 0) {
121                     return kind;
122                 }
123             }
124         }
125         return 0;
126     }
127     
128     
129     public static SimpleName[] findByProblems(ASTNode parent, SimpleName nameNode) {
130         ArrayList JavaDoc res= new ArrayList JavaDoc();
131         
132         ASTNode astRoot = parent.getRoot();
133         if (!(astRoot instanceof CompilationUnit)) {
134             return null;
135         }
136             
137         IProblem[] problems= ((CompilationUnit) astRoot).getProblems();
138         int nameNodeKind= getNameNodeProblemKind(problems, nameNode);
139         if (nameNodeKind == 0) { // no problem on node
140
return null;
141         }
142             
143         int bodyStart= parent.getStartPosition();
144         int bodyEnd= bodyStart + parent.getLength();
145         
146         String JavaDoc name= nameNode.getIdentifier();
147
148         for (int i= 0; i < problems.length; i++) {
149             IProblem curr= problems[i];
150             int probStart= curr.getSourceStart();
151             int probEnd= curr.getSourceEnd() + 1;
152             
153             if (probStart > bodyStart && probEnd < bodyEnd) {
154                 int currKind= getProblemKind(curr);
155                 if ((nameNodeKind & currKind) != 0) {
156                     ASTNode node= NodeFinder.perform(parent, probStart, probEnd - probStart);
157                     if (node instanceof SimpleName && name.equals(((SimpleName) node).getIdentifier())) {
158                         res.add(node);
159                     }
160                 }
161             }
162         }
163         return (SimpleName[]) res.toArray(new SimpleName[res.size()]);
164     }
165     
166     private static class LabelFinder extends ASTVisitor {
167         
168         private SimpleName fLabel;
169         private ASTNode fDefiningLabel;
170         private ArrayList JavaDoc fResult;
171         
172         public LabelFinder(SimpleName label, ArrayList JavaDoc result) {
173             super(true);
174             fLabel= label;
175             fResult= result;
176             fDefiningLabel= null;
177         }
178         
179         private boolean isSameLabel(SimpleName label) {
180             return label != null && fLabel.getIdentifier().equals(label.getIdentifier());
181         }
182         
183         public boolean visit(BreakStatement node) {
184             SimpleName label= node.getLabel();
185             if (fDefiningLabel != null && isSameLabel(label) && ASTNodes.isParent(label, fDefiningLabel)) {
186                 fResult.add(label);
187             }
188             return false;
189         }
190                 
191         public boolean visit(ContinueStatement node) {
192             SimpleName label= node.getLabel();
193             if (fDefiningLabel != null && isSameLabel(label) && ASTNodes.isParent(label, fDefiningLabel)) {
194                 fResult.add(label);
195             }
196             return false;
197         }
198
199         public boolean visit(LabeledStatement node) {
200             if (fDefiningLabel == null) {
201                 SimpleName label= node.getLabel();
202                 if (fLabel == label || isSameLabel(label) && ASTNodes.isParent(fLabel, node)) {
203                     fDefiningLabel= node;
204                     fResult.add(label);
205                 }
206             }
207             node.getBody().accept(this);
208             return false;
209         }
210     }
211     
212     private static class BindingFinder extends ASTVisitor {
213     
214         private IBinding fBinding;
215         private ArrayList JavaDoc fResult;
216         
217         public BindingFinder(IBinding binding, ArrayList JavaDoc result) {
218             super(true);
219             fBinding= getDeclaration(binding);
220             fResult= result;
221         }
222         
223         public boolean visit(MethodDeclaration node) {
224             if (node.isConstructor() && fBinding.getKind() == IBinding.TYPE) {
225                 ASTNode typeNode= node.getParent();
226                 if (typeNode instanceof AbstractTypeDeclaration) {
227                     if (fBinding == ((AbstractTypeDeclaration) typeNode).resolveBinding()) {
228                         fResult.add(node.getName());
229                     }
230                 }
231             }
232             return true;
233         }
234         
235         public boolean visit(TypeDeclaration node) {
236             if (fBinding.getKind() == IBinding.METHOD) {
237                 IMethodBinding binding= (IMethodBinding) fBinding;
238                 if (binding.isConstructor() && binding.getDeclaringClass() == node.resolveBinding()) {
239                     fResult.add(node.getName());
240                 }
241             }
242             return true;
243         }
244
245         public boolean visit(EnumDeclaration node) {
246             if (fBinding.getKind() == IBinding.METHOD) {
247                 IMethodBinding binding= (IMethodBinding) fBinding;
248                 if (binding.isConstructor() && binding.getDeclaringClass() == node.resolveBinding()) {
249                     fResult.add(node.getName());
250                 }
251             }
252             return true;
253         }
254
255         public boolean visit(AnnotationTypeDeclaration node) {
256             // annotation types can not have a constructor
257
return true;
258         }
259
260         public boolean visit(SimpleName node) {
261             IBinding binding= node.resolveBinding();
262             if (binding == null || binding.getKind() != fBinding.getKind()) {
263                 return false;
264             }
265             binding= getDeclaration(binding);
266             
267             if (fBinding == binding) {
268                 fResult.add(node);
269             } else if (binding.getKind() == IBinding.METHOD) {
270                 IMethodBinding curr= (IMethodBinding) binding;
271                 IMethodBinding methodBinding= (IMethodBinding) fBinding;
272                 if (methodBinding.overrides(curr) || curr.overrides(methodBinding)) {
273                     fResult.add(node);
274                 }
275             }
276             return false;
277         }
278         
279         private static IBinding getDeclaration(IBinding binding) {
280             if (binding instanceof ITypeBinding) {
281                 return ((ITypeBinding) binding).getTypeDeclaration();
282             } else if (binding instanceof IMethodBinding) {
283                 return ((IMethodBinding) binding).getMethodDeclaration();
284             } else if (binding instanceof IVariableBinding) {
285                 return ((IVariableBinding) binding).getVariableDeclaration();
286             }
287             return binding;
288         }
289     }
290 }
291
Popular Tags