| Home >> All >> com >> port80 >> eclipse >> jdt >> [ graph Javadoc ] |
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 }