Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/port80/eclipse/jdt/graph/TypeReferenceASTVisitor.java


1   package com.port80.eclipse.jdt.graph;
2   
3   import java.util.HashMap;
4   import java.util.Iterator;
5   import java.util.List;
6   import java.util.Map;
7   
8   import org.eclipse.jdt.core.dom.ASTNode;
9   import org.eclipse.jdt.core.dom.ASTVisitor;
10  import org.eclipse.jdt.core.dom.ArrayType;
11  import org.eclipse.jdt.core.dom.ClassInstanceCreation;
12  import org.eclipse.jdt.core.dom.Expression;
13  import org.eclipse.jdt.core.dom.FieldAccess;
14  import org.eclipse.jdt.core.dom.IBinding;
15  import org.eclipse.jdt.core.dom.ITypeBinding;
16  import org.eclipse.jdt.core.dom.MethodDeclaration;
17  import org.eclipse.jdt.core.dom.MethodInvocation;
18  import org.eclipse.jdt.core.dom.Name;
19  import org.eclipse.jdt.core.dom.PackageDeclaration;
20  import org.eclipse.jdt.core.dom.QualifiedName;
21  import org.eclipse.jdt.core.dom.SimpleName;
22  import org.eclipse.jdt.core.dom.SimpleType;
23  import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
24  import org.eclipse.jdt.core.dom.ThisExpression;
25  import org.eclipse.jdt.core.dom.TypeDeclaration;
26  
27  import com.port80.util.Msg;
28  
29  /**
30   * Find type referenced in a given CompilationUnit.
31   * 
32   * @author chrisl
33   * @see org.eclipse.jdt.internal.corext.codemanipulation
34   */
35  public class TypeReferenceASTVisitor extends ASTVisitor {
36  
37    ////////////////////////////////////////////////////////////////////////
38  
39    private static final String NAME = "TypeReferenceASTVisitor";
40    private static final boolean DEBUG = false;
41  
42    public static class Result {
43      public static final int NONE = 0;
44      public static final int CLASS = 1;
45      public static final int INTERFACE = 2;
46      public int fKind;
47      /** Super classes.  Fully qualified typename -> ITypeBinding.*/
48      public Map fSuperClasses;
49      /** FullQualifiedName->ITypeBinding mapping.*/
50      public Map fSuperInterfaces;
51      /** Referenced types. FullyQualifiedName->ITypeBinding mapping.*/
52      public Map fReferences;
53      /** Declared types. FullyQualifiedName->ITypeBinding mapping.*/
54      public Map fDeclares;
55  
56      public Result() {
57        fKind = 0;
58        fReferences = new HashMap();
59        fSuperClasses = new HashMap();
60        fSuperInterfaces = new HashMap();
61        fDeclares = new HashMap();
62      }
63      public int getKind() {
64        return fKind;
65      }
66      public Map getDeclares() {
67        return fDeclares;
68      }
69      public Map getSuperClasses() {
70        return fSuperClasses;
71      }
72      public Map getReferences() {
73        return fReferences;
74      }
75      public Map getSuperInterfaces() {
76        return fSuperInterfaces;
77      }
78    }
79    private Result fResult;
80    
81    ////////////////////////////////////////////////////////////////////////
82  
83    /**
84     * @return Type references in a (String fullTypeName) -> (ITypeBinding type) hash.
85     */
86    public static TypeReferenceASTVisitor startAt(ASTNode root) {
87      TypeReferenceASTVisitor visitor = new TypeReferenceASTVisitor();
88      root.accept(visitor);
89      return visitor;
90    }
91  
92    ////////////////////////////////////////////////////////////////////////
93  
94    public Result getResult() {
95      return fResult;
96    }
97  
98    public TypeReferenceASTVisitor() {
99      fResult = new Result();
100   }
101 
102   private ITypeBinding addDeclaredType(Name node) {
103     ITypeBinding type = resolveType(node);
104     if (type != null)
105       fResult.fDeclares.put(type.getPackage().getName() + "." + type.getName(), type);
106     return type;
107   }
108 
109   private ITypeBinding addReference(ITypeBinding type) {
110     return addType(fResult.fReferences, type);
111   }
112 
113   private ITypeBinding addSuperClass(ITypeBinding type) {
114     if (type.isInterface())
115       return addSuperInterface(type);
116     return addType(fResult.fSuperClasses, type);
117   }
118 
119   private ITypeBinding addSuperInterface(ITypeBinding type) {
120     return addType(fResult.fSuperInterfaces, type);
121   }
122 
123   private ITypeBinding addType(Map table, ITypeBinding type) {
124     if (type == null)
125       return null;
126     //    StringBuffer buf = new StringBuffer();
127     //    buf.append(type.qualifiedPackageName());
128     //    buf.append(".");
129     //    buf.append(type.qualifiedSourceName());
130     //    String typename = buf.toString();
131     String typename = type.getPackage().getName();
132     typename += "." + type.getName();
133     if (DEBUG)
134       System.err.println(NAME + ".addReference(): " + typename);
135     if (!table.containsKey(typename)) {
136       table.put(typename, type);
137     }
138     return type;
139   }
140 
141   private ITypeBinding resolveType(Name node) {
142     if (node != null) {
143       while (node.isQualifiedName()) {
144         node = ((QualifiedName) node).getQualifier();
145       }
146       if (DEBUG)
147         System.err.println(NAME + ".resolveType(): " + node);
148       IBinding binding = node.resolveBinding();
149       if (binding != null && binding.getKind() == IBinding.TYPE) {
150         return (ITypeBinding) binding;
151       }
152     }
153     return null;
154   }
155 
156   private ITypeBinding typeRefFound(Name node) {
157     if (node != null) {
158       while (node.isQualifiedName()) {
159         node = ((QualifiedName) node).getQualifier();
160       }
161       if (DEBUG)
162         System.err.println(NAME + ".typeRefFound(): " + node);
163       IBinding binding = node.resolveBinding();
164       if (binding != null && binding.getKind() == IBinding.TYPE) {
165         addReference((ITypeBinding) binding);
166         return (ITypeBinding) binding;
167       }
168     }
169     return null;
170   }
171 
172   private void possibleTypeRefFound(Name node) {
173     while (node.isQualifiedName()) {
174       node = ((QualifiedName) node).getQualifier();
175     }
176     if (DEBUG)
177       System.err.println(NAME + ".possibleTypeRefFound(): " + node);
178     IBinding binding = node.resolveBinding();
179     if (binding != null && binding.getKind() == IBinding.TYPE)
180       addReference((ITypeBinding) binding);
181     //    if (binding == null || binding.getKind() == IBinding.TYPE) {
182     //      // if the binding is null, we cannot determine if 
183     //      // we have a type binding or not, so we will assume
184     //      // we do.
185     //      addReference((SimpleName) node);
186     //    }
187   }
188 
189   private void visitChildren(List elements) {
190     int nElements = elements.size();
191     for (int i = 0; i < nElements; i++) {
192       ((ASTNode) elements.get(i)).accept(this);
193     }
194   }
195 
196   ////////////////////////////////////////////////////////////////////////
197 
198   /*
199    * @see ASTVisitor#visit(ArrayType)
200    */
201   public boolean visit(ArrayType node) {
202     node.getElementType().accept(this);
203     return false;
204   }
205 
206   /*
207    * @see ASTVisitor#visit(SimpleType)
208    */
209   public boolean visit(SimpleType node) {
210     typeRefFound(node.getName());
211     return false;
212   }
213 
214   /*
215    * @see ASTVisitor#visit(QualifiedName)
216    */
217   public boolean visit(QualifiedName node) {
218     possibleTypeRefFound(node); // possible ref
219     return false;
220   }
221 
222   /*
223    * @see ASTVisitor#visit(PackageDeclaration)
224    */
225   public boolean visit(PackageDeclaration node) {
226     return false;
227   }
228 
229   /*
230    * @see ASTVisitor#visit(ThisExpression)
231    */
232   public boolean visit(ThisExpression node) {
233     typeRefFound(node.getQualifier());
234     return false;
235   }
236 
237   private void evalQualifyingExpression(Expression expr) {
238     if (expr != null) {
239       if (expr instanceof Name) {
240         possibleTypeRefFound((Name) expr);
241       } else {
242         expr.accept(this);
243       }
244     }
245   }
246 
247   /*
248    * @see ASTVisitor#visit(ClassInstanceCreation)
249    */
250   public boolean visit(ClassInstanceCreation node) {
251     typeRefFound(node.getName());
252     evalQualifyingExpression(node.getExpression());
253     if (node.getAnonymousClassDeclaration() != null) {
254       node.getAnonymousClassDeclaration().accept(this);
255     }
256     visitChildren(node.arguments());
257     return false;
258   }
259 
260   /*
261    * @see ASTVisitor#endVisit(MethodInvocation)
262    */
263   public boolean visit(MethodInvocation node) {
264     evalQualifyingExpression(node.getExpression());
265     visitChildren(node.arguments());
266     return false;
267   }
268 
269   /*
270    * @see ASTVisitor#visit(SuperConstructorInvocation)
271    */
272   public boolean visit(SuperConstructorInvocation node) {
273     evalQualifyingExpression(node.getExpression());
274     visitChildren(node.arguments());
275     return false;
276   }
277 
278   /*
279    * @see ASTVisitor#visit(FieldAccess)
280    */
281   public boolean visit(FieldAccess node) {
282     evalQualifyingExpression(node.getExpression());
283     return false;
284   }
285 
286   /*
287    * @see ASTVisitor#visit(SimpleName)
288    */
289   public boolean visit(SimpleName node) {
290     // if the call gets here, it can only be a variable reference
291     return false;
292   }
293 
294   /*
295    * @see ASTVisitor#visit(TypeDeclaration)
296    */
297   public boolean visit(TypeDeclaration node) {
298     ITypeBinding type = typeRefFound(node.getSuperclass());
299     if (type != null)
300       addSuperClass(type);
301     Iterator iter = node.superInterfaces().iterator();
302     while (iter.hasNext()) {
303       type = typeRefFound((Name) iter.next());
304       if (type != null)
305         addSuperInterface(type);
306     }
307     visitChildren(node.bodyDeclarations());
308     type = addDeclaredType(node.getName());
309     if (type != null) {
310       if (type.isInterface())
311         fResult.fKind |= Result.INTERFACE;
312       if (type.isClass())
313         fResult.fKind |= Result.CLASS;
314     } else {
315       Msg.err(NAME+".visit(TypeDeclaration): declared type==null: node="+node.getName());
316     }
317     return false;
318   }
319 
320   /*
321    * @see ASTVisitor#visit(MethodDeclaration)
322    */
323   public boolean visit(MethodDeclaration node) {
324     if (!node.isConstructor()) {
325       node.getReturnType().accept(this);
326     }
327     visitChildren(node.parameters());
328     Iterator iter = node.thrownExceptions().iterator();
329     while (iter.hasNext()) {
330       typeRefFound((Name) iter.next());
331     }
332     if (node.getBody() != null) {
333       node.getBody().accept(this);
334     }
335     return false;
336   }
337 
338   /*
339    * @see ASTVisitor#preVisit(ASTNode)
340    */
341   public void preVisit(ASTNode node) {
342     if ((node.getFlags() & ASTNode.MALFORMED) != 0) {
343       throw new ASTError(node);
344     }
345   }
346 
347   ////////////////////////////////////////////////////////////////////////
348 
349 }