1 11 package org.eclipse.jdt.internal.core.util; 12 13 import java.util.ArrayList ; 14 15 import org.eclipse.jdt.core.compiler.CharOperation; 16 import org.eclipse.jdt.internal.compiler.ASTVisitor; 17 import org.eclipse.jdt.internal.compiler.Compiler; 18 import org.eclipse.jdt.internal.compiler.ast.ArrayReference; 19 import org.eclipse.jdt.internal.compiler.ast.Assignment; 20 import org.eclipse.jdt.internal.compiler.ast.CastExpression; 21 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; 22 import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression; 23 import org.eclipse.jdt.internal.compiler.ast.FieldReference; 24 import org.eclipse.jdt.internal.compiler.ast.MessageSend; 25 import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; 26 import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; 27 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; 28 import org.eclipse.jdt.internal.compiler.ast.Wildcard; 29 import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding; 30 import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding; 31 import org.eclipse.jdt.internal.compiler.lookup.Binding; 32 import org.eclipse.jdt.internal.compiler.lookup.BlockScope; 33 import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding; 34 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; 35 import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding; 36 import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; 37 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; 38 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; 39 import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; 40 import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding; 41 import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding; 42 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; 43 import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; 44 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; 45 import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; 46 import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding; 47 48 public class BindingKeyResolver extends BindingKeyParser { 49 Compiler compiler; 50 Binding compilerBinding; 51 52 char[][] compoundName; 53 int dimension; 54 LookupEnvironment environment; 55 ReferenceBinding genericType; 56 MethodBinding methodBinding; 57 58 char[] secondarySimpleName; 59 CompilationUnitDeclaration parsedUnit; 60 BlockScope scope; 61 TypeBinding typeBinding; 62 TypeDeclaration typeDeclaration; 63 ArrayList types = new ArrayList (); 64 int rank = 0; 65 66 int wildcardRank; 67 68 CompilationUnitDeclaration outerMostParsedUnit; 69 70 private BindingKeyResolver(BindingKeyParser parser, Compiler compiler, LookupEnvironment environment, int wildcardRank, CompilationUnitDeclaration outerMostParsedUnit) { 71 super(parser); 72 this.compiler = compiler; 73 this.environment = environment; 74 this.wildcardRank = wildcardRank; 75 this.outerMostParsedUnit = outerMostParsedUnit; 76 } 77 78 public BindingKeyResolver(String key) { 79 this(key, null, null); 80 } 81 82 public BindingKeyResolver(String key, Compiler compiler, LookupEnvironment environment) { 83 super(key); 84 this.compiler = compiler; 85 this.environment = environment; 86 } 87 88 94 public char[][] compoundName() { 95 return this.compoundName; 96 } 97 98 public void consumeArrayDimension(char[] brakets) { 99 this.dimension = brakets.length; 100 } 101 102 public void consumeBaseType(char[] baseTypeSig) { 103 this.compoundName = new char[][] {getKey().toCharArray()}; 104 TypeBinding baseTypeBinding = getBaseTypeBinding(baseTypeSig); 105 if (baseTypeBinding != null) { 106 this.typeBinding = baseTypeBinding; 107 } 108 } 109 110 public void consumeCapture(final int position) { 111 CompilationUnitDeclaration outerParsedUnit = this.outerMostParsedUnit == null ? this.parsedUnit : this.outerMostParsedUnit; 112 if (outerParsedUnit == null) return; 113 final Binding wildcardBinding = ((BindingKeyResolver) this.types.get(0)).compilerBinding; 114 class CaptureFinder extends ASTVisitor { 115 CaptureBinding capture; 116 boolean checkType(TypeBinding binding) { 117 if (binding == null) 118 return false; 119 switch (binding.kind()) { 120 case Binding.PARAMETERIZED_TYPE: 121 TypeBinding[] arguments = ((ParameterizedTypeBinding) binding).arguments; 122 if (arguments == null) return false; 123 for (int i = 0, length = arguments.length; i < length; i++) { 124 if (checkType(arguments[i])) 125 return true; 126 } 127 break; 128 case Binding.WILDCARD_TYPE: 129 return checkType(((WildcardBinding) binding).bound); 130 case Binding.ARRAY_TYPE: 131 return checkType(((ArrayBinding) binding).leafComponentType); 132 case Binding.TYPE_PARAMETER: 133 if (binding.isCapture()) { 134 CaptureBinding captureBinding = (CaptureBinding) binding; 135 if (captureBinding.position == position && captureBinding.wildcard == wildcardBinding) { 136 this.capture = captureBinding; 137 return true; 138 } 139 } 140 break; 141 } 142 return false; 143 } 144 public boolean visit(SingleNameReference singleNameReference, BlockScope blockScope) { 145 if (checkType(singleNameReference.resolvedType)) 146 return false; 147 return super.visit(singleNameReference, blockScope); 148 } 149 public boolean visit(QualifiedNameReference qualifiedNameReference, BlockScope blockScope) { 150 if (checkType(qualifiedNameReference.resolvedType)) 151 return false; 152 return super.visit(qualifiedNameReference, blockScope); 153 } 154 public boolean visit(MessageSend messageSend, BlockScope blockScope) { 155 if (checkType(messageSend.resolvedType)) 156 return false; 157 return super.visit(messageSend, blockScope); 158 } 159 public boolean visit(FieldReference fieldReference, BlockScope blockScope) { 160 if (checkType(fieldReference.resolvedType)) 161 return false; 162 return super.visit(fieldReference, blockScope); 163 } 164 public boolean visit(ConditionalExpression conditionalExpression, BlockScope blockScope) { 165 if (checkType(conditionalExpression.resolvedType)) 166 return false; 167 return super.visit(conditionalExpression, blockScope); 168 } 169 public boolean visit(CastExpression castExpression, BlockScope blockScope) { 170 if (checkType(castExpression.resolvedType)) 171 return false; 172 return super.visit(castExpression, blockScope); 173 } 174 public boolean visit(Assignment assignment, BlockScope blockScope) { 175 if (checkType(assignment.resolvedType)) 176 return false; 177 return super.visit(assignment, blockScope); 178 } 179 public boolean visit(ArrayReference arrayReference, BlockScope blockScope) { 180 if (checkType(arrayReference.resolvedType)) 181 return false; 182 return super.visit(arrayReference, blockScope); 183 } 184 } 185 CaptureFinder captureFinder = new CaptureFinder(); 186 outerParsedUnit.traverse(captureFinder, outerParsedUnit.scope); 187 this.typeBinding = captureFinder.capture; 188 } 189 190 public void consumeException() { 191 this.types = new ArrayList (); 192 } 193 194 public void consumeField(char[] fieldName) { 195 FieldBinding[] fields = ((ReferenceBinding) this.typeBinding).availableFields(); for (int i = 0, length = fields.length; i < length; i++) { 197 FieldBinding field = fields[i]; 198 if (CharOperation.equals(fieldName, field.name)) { 199 this.typeBinding = null; 200 this.compilerBinding = field; 201 return; 202 } 203 } 204 } 205 206 public void consumeParameterizedGenericMethod() { 207 if (this.methodBinding == null) 208 return; 209 TypeBinding[] arguments = getTypeBindingArguments(); 210 if (arguments.length != this.methodBinding.typeVariables().length) 211 this.methodBinding = this.environment.createParameterizedGenericMethod(this.methodBinding, (RawTypeBinding) null); 212 else 213 this.methodBinding = this.environment.createParameterizedGenericMethod(this.methodBinding, arguments); 214 this.compilerBinding = this.methodBinding; 215 } 216 217 public void consumeLocalType(char[] uniqueKey) { 218 LocalTypeBinding[] localTypeBindings = this.parsedUnit.localTypes; 219 for (int i = 0; i < this.parsedUnit.localTypeCount; i++) 220 if (CharOperation.equals(uniqueKey, localTypeBindings[i].computeUniqueKey(false))) { 221 this.typeBinding = localTypeBindings[i]; 222 return; 223 } 224 } 225 226 public void consumeLocalVar(char[] varName) { 227 if (this.scope == null) { 228 this.scope = this.methodBinding.sourceMethod().scope; 229 } 230 for (int i = 0; i < this.scope.localIndex; i++) { 231 LocalVariableBinding local = this.scope.locals[i]; 232 if (CharOperation.equals(varName, local.name)) { 233 this.methodBinding = null; 234 this.compilerBinding = local; 235 return; 236 } 237 } 238 } 239 240 public void consumeMethod(char[] selector, char[] signature) { 241 MethodBinding[] methods = ((ReferenceBinding) this.typeBinding).availableMethods(); for (int i = 0, methodLength = methods.length; i < methodLength; i++) { 243 MethodBinding method = methods[i]; 244 if (CharOperation.equals(selector, method.selector) || (selector.length == 0 && method.isConstructor())) { 245 char[] methodSignature = method.genericSignature(); 246 if (methodSignature == null) 247 methodSignature = method.signature(); 248 if (CharOperation.equals(signature, methodSignature)) { 249 this.typeBinding = null; 250 this.methodBinding = method; 251 this.compilerBinding = this.methodBinding; 252 return; 253 } 254 } 255 } 256 } 257 258 public void consumeMemberType(char[] simpleTypeName) { 259 this.typeBinding = getTypeBinding(simpleTypeName); 260 } 261 262 public void consumePackage(char[] pkgName) { 263 this.compoundName = CharOperation.splitOn('/', pkgName); 264 this.compilerBinding = new PackageBinding(this.compoundName, null, this.environment); 265 } 266 267 public void consumeParameterizedType(char[] simpleTypeName, boolean isRaw) { 268 TypeBinding[] arguments = getTypeBindingArguments(); 269 if (simpleTypeName != null) { 270 if (this.genericType == null) { 271 this.genericType = ((ReferenceBinding) this.typeBinding).getMemberType(simpleTypeName); 273 } else { 274 this.genericType = this.genericType.getMemberType(simpleTypeName); 276 } 277 if (!isRaw) 278 this.typeBinding = this.environment.createParameterizedType(this.genericType, arguments, (ReferenceBinding) this.typeBinding); 279 else 280 this.typeBinding = this.environment.createRawType(this.genericType, (ReferenceBinding) this.typeBinding); 282 } else { 283 this.genericType = (ReferenceBinding) this.typeBinding; 285 ReferenceBinding enclosing = this.genericType.enclosingType(); 286 if (enclosing != null) enclosing = (ReferenceBinding) this.environment.convertToRawType(enclosing); 287 this.typeBinding = this.environment.createParameterizedType(this.genericType, arguments, enclosing); 288 } 289 } 290 291 292 public void consumeParser(BindingKeyParser parser) { 293 this.types.add(parser); 294 if (((BindingKeyResolver) parser).compilerBinding instanceof WildcardBinding) 295 this.rank++; 296 } 297 298 public void consumeScope(int scopeNumber) { 299 if (this.scope == null) { 300 this.scope = this.methodBinding.sourceMethod().scope; 301 } 302 if (scopeNumber >= this.scope.subscopeCount) 303 return; this.scope = (BlockScope) this.scope.subscopes[scopeNumber]; 305 } 306 307 public void consumeRawType() { 308 if (this.typeBinding == null) return; 309 this.typeBinding = this.environment.convertToRawType(this.typeBinding); 310 } 311 public void consumeSecondaryType(char[] simpleTypeName) { 312 this.secondarySimpleName = simpleTypeName; 313 } 314 315 public void consumeFullyQualifiedName(char[] fullyQualifiedName) { 316 this.compoundName = CharOperation.splitOn('/', fullyQualifiedName); 317 } 318 319 public void consumeTopLevelType() { 320 this.parsedUnit = getCompilationUnitDeclaration(); 321 if (this.parsedUnit != null && this.compiler != null) { 322 this.compiler.process(this.parsedUnit, this.compiler.totalUnits+1); } 324 if (this.parsedUnit == null) { 325 this.typeBinding = getBinaryBinding(); 326 } else { 327 char[] typeName = this.secondarySimpleName == null ? this.compoundName[this.compoundName.length-1] : this.secondarySimpleName; 328 this.typeBinding = getTypeBinding(typeName); 329 } 330 } 331 332 public void consumeKey() { 333 if (this.typeBinding != null) { 334 this.typeBinding = getArrayBinding(this.dimension, this.typeBinding); 335 this.compilerBinding = this.typeBinding; 336 } 337 } 338 339 public void consumeTypeVariable(char[] position, char[] typeVariableName) { 340 if (position.length > 0) { 341 int pos = Integer.parseInt(new String (position)); 342 MethodBinding[] methods = ((ReferenceBinding) this.typeBinding).availableMethods(); if (methods != null && pos < methods.length) { 344 this.methodBinding = methods[pos]; 345 } 346 } 347 TypeVariableBinding[] typeVariableBindings = this.methodBinding != null ? this.methodBinding.typeVariables() : this.typeBinding.typeVariables(); 348 for (int i = 0, length = typeVariableBindings.length; i < length; i++) { 349 TypeVariableBinding typeVariableBinding = typeVariableBindings[i]; 350 if (CharOperation.equals(typeVariableName, typeVariableBinding.sourceName())) { 351 this.typeBinding = typeVariableBinding; 352 return; 353 } 354 } 355 } 356 357 public void consumeTypeWithCapture() { 358 BindingKeyResolver resolver = (BindingKeyResolver) this.types.get(0); 359 this.typeBinding =(TypeBinding) resolver.compilerBinding; 360 } 361 362 public void consumeWildCard(int kind) { 363 switch (kind) { 364 case Wildcard.EXTENDS: 365 case Wildcard.SUPER: 366 BindingKeyResolver boundResolver = (BindingKeyResolver) this.types.get(0); 367 this.typeBinding = this.environment.createWildcard((ReferenceBinding) this.typeBinding, this.wildcardRank, (TypeBinding) boundResolver.compilerBinding, null , kind); 368 break; 369 case Wildcard.UNBOUND: 370 this.typeBinding = this.environment.createWildcard((ReferenceBinding) this.typeBinding, rank++, null, null , kind); 371 break; 372 } 373 } 374 375 380 private TypeBinding getArrayBinding(int dim, TypeBinding binding) { 381 if (binding == null) return null; 382 if (dim == 0) return binding; 383 return this.environment.createArrayType(binding, dim); 384 } 385 386 private TypeBinding getBaseTypeBinding(char[] signature) { 387 switch (signature[0]) { 388 case 'I' : 389 return TypeBinding.INT; 390 case 'Z' : 391 return TypeBinding.BOOLEAN; 392 case 'V' : 393 return TypeBinding.VOID; 394 case 'C' : 395 return TypeBinding.CHAR; 396 case 'D' : 397 return TypeBinding.DOUBLE; 398 case 'B' : 399 return TypeBinding.BYTE; 400 case 'F' : 401 return TypeBinding.FLOAT; 402 case 'J' : 403 return TypeBinding.LONG; 404 case 'S' : 405 return TypeBinding.SHORT; 406 case 'N': 407 return TypeBinding.NULL; 408 default : 409 return null; 410 } 411 } 412 413 417 private TypeBinding getBinaryBinding() { 418 if (this.compoundName.length == 0) return null; 419 return this.environment.getType(this.compoundName); 420 } 421 422 427 public CompilationUnitDeclaration getCompilationUnitDeclaration() { 428 char[][] name = this.compoundName; 429 if (name.length == 0) return null; 430 if (this.environment == null) return null; 431 ReferenceBinding binding = this.environment.getType(name); 432 if (!(binding instanceof SourceTypeBinding)) { 433 if (this.secondarySimpleName == null) 434 return null; 435 int length = name.length; 437 System.arraycopy(name, 0, name = new char[length][], 0, length-1); 438 name[length-1] = this.secondarySimpleName; 439 binding = this.environment.getType(name); 440 if (!(binding instanceof SourceTypeBinding)) 441 return null; 442 } 443 SourceTypeBinding sourceTypeBinding = (SourceTypeBinding) binding; 444 if (sourceTypeBinding.scope == null) 445 return null; 446 return sourceTypeBinding.scope.compilationUnitScope().referenceContext; 447 } 448 449 454 public Binding getCompilerBinding() { 455 try { 456 parse(); 457 return this.compilerBinding; 458 } catch (RuntimeException e) { 459 Util.log(e, "Could not create binding from binding key: " + getKey()); return null; 461 } 462 } 463 464 private TypeBinding getTypeBinding(char[] simpleTypeName) { 465 if (this.typeBinding instanceof BinaryTypeBinding) { 466 return ((BinaryTypeBinding) this.typeBinding).getMemberType(simpleTypeName); 467 } else { 468 TypeDeclaration[] typeDeclarations = 469 this.typeDeclaration == null ? 470 (this.parsedUnit == null ? null : this.parsedUnit.types) : 471 this.typeDeclaration.memberTypes; 472 if (typeDeclarations == null) return null; 473 for (int i = 0, length = typeDeclarations.length; i < length; i++) { 474 TypeDeclaration declaration = typeDeclarations[i]; 475 if (CharOperation.equals(simpleTypeName, declaration.name)) { 476 this.typeDeclaration = declaration; 477 return declaration.binding; 478 } 479 } 480 } 481 return null; 482 } 483 484 private TypeBinding[] getTypeBindingArguments() { 485 int size = this.types.size(); 486 TypeBinding[] arguments = new TypeBinding[size]; 487 for (int i = 0; i < size; i++) { 488 BindingKeyResolver resolver = (BindingKeyResolver) this.types.get(i); 489 TypeBinding compilerBinding2 = (TypeBinding) resolver.compilerBinding; 490 if (compilerBinding2 == null) { 491 throw new IllegalArgumentException (); 492 } 493 arguments[i] = compilerBinding2; 494 } 495 this.types = new ArrayList (); 496 return arguments; 497 } 498 499 public void malformedKey() { 500 this.compoundName = CharOperation.NO_CHAR_CHAR; 501 } 502 503 public BindingKeyParser newParser() { 504 return new BindingKeyResolver(this, this.compiler, this.environment, this.rank, this.outerMostParsedUnit == null ? this.parsedUnit : this.outerMostParsedUnit); 505 } 506 507 public String toString() { 508 return getKey(); 509 } 510 511 } 512 | Popular Tags |