1 11 package org.eclipse.jdt.internal.compiler.lookup; 12 13 import org.eclipse.jdt.core.compiler.CharOperation; 14 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; 15 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; 16 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 17 18 public class SyntheticMethodBinding extends MethodBinding { 19 20 public FieldBinding targetReadField; public FieldBinding targetWriteField; public MethodBinding targetMethod; public TypeBinding targetEnumType; 25 public int kind; 26 27 public final static int FieldReadAccess = 1; public final static int FieldWriteAccess = 2; public final static int MethodAccess = 3; public final static int ConstructorAccess = 4; public final static int SuperMethodAccess = 5; public final static int BridgeMethod = 6; public final static int EnumValues = 7; public final static int EnumValueOf = 8; public final static int SwitchTable = 9; 37 public int sourceStart = 0; public int index; 40 public SyntheticMethodBinding(FieldBinding targetField, boolean isReadAccess, ReferenceBinding declaringClass) { 41 42 this.modifiers = ClassFileConstants.AccDefault | ClassFileConstants.AccStatic | ClassFileConstants.AccSynthetic; 43 this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); 44 SourceTypeBinding declaringSourceType = (SourceTypeBinding) declaringClass; 45 SyntheticMethodBinding[] knownAccessMethods = declaringSourceType.syntheticMethods(); 46 int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length; 47 this.index = methodId; 48 this.selector = CharOperation.concat(TypeConstants.SYNTHETIC_ACCESS_METHOD_PREFIX, String.valueOf(methodId).toCharArray()); 49 if (isReadAccess) { 50 this.returnType = targetField.type; 51 if (targetField.isStatic()) { 52 this.parameters = Binding.NO_PARAMETERS; 53 } else { 54 this.parameters = new TypeBinding[1]; 55 this.parameters[0] = declaringSourceType; 56 } 57 this.targetReadField = targetField; 58 this.kind = FieldReadAccess; 59 } else { 60 this.returnType = TypeBinding.VOID; 61 if (targetField.isStatic()) { 62 this.parameters = new TypeBinding[1]; 63 this.parameters[0] = targetField.type; 64 } else { 65 this.parameters = new TypeBinding[2]; 66 this.parameters[0] = declaringSourceType; 67 this.parameters[1] = targetField.type; 68 } 69 this.targetWriteField = targetField; 70 this.kind = FieldWriteAccess; 71 } 72 this.thrownExceptions = Binding.NO_EXCEPTIONS; 73 this.declaringClass = declaringSourceType; 74 75 boolean needRename; 77 do { 78 check : { 79 needRename = false; 80 long range; 82 MethodBinding[] methods = declaringSourceType.methods(); 83 if ((range = ReferenceBinding.binarySearch(this.selector, methods)) >= 0) { 84 int paramCount = this.parameters.length; 85 nextMethod: for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) { 86 MethodBinding method = methods[imethod]; 87 if (method.parameters.length == paramCount) { 88 TypeBinding[] toMatch = method.parameters; 89 for (int i = 0; i < paramCount; i++) { 90 if (toMatch[i] != this.parameters[i]) { 91 continue nextMethod; 92 } 93 } 94 needRename = true; 95 break check; 96 } 97 } 98 } 99 if (knownAccessMethods != null) { 101 for (int i = 0, length = knownAccessMethods.length; i < length; i++) { 102 if (knownAccessMethods[i] == null) continue; 103 if (CharOperation.equals(this.selector, knownAccessMethods[i].selector) && this.areParametersEqual(methods[i])) { 104 needRename = true; 105 break check; 106 } 107 } 108 } 109 } 110 if (needRename) { this.setSelector(CharOperation.concat(TypeConstants.SYNTHETIC_ACCESS_METHOD_PREFIX, String.valueOf(++methodId).toCharArray())); 112 } 113 } while (needRename); 114 115 FieldDeclaration[] fieldDecls = declaringSourceType.scope.referenceContext.fields; 117 if (fieldDecls != null) { 118 for (int i = 0, max = fieldDecls.length; i < max; i++) { 119 if (fieldDecls[i].binding == targetField) { 120 this.sourceStart = fieldDecls[i].sourceStart; 121 return; 122 } 123 } 124 } 125 126 140 this.sourceStart = declaringSourceType.scope.referenceContext.sourceStart; } 144 145 public SyntheticMethodBinding(FieldBinding targetField, ReferenceBinding declaringClass, TypeBinding enumBinding, char[] selector) { 146 this.modifiers = ClassFileConstants.AccDefault | ClassFileConstants.AccStatic | ClassFileConstants.AccSynthetic; 147 this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); 148 SourceTypeBinding declaringSourceType = (SourceTypeBinding) declaringClass; 149 SyntheticMethodBinding[] knownAccessMethods = declaringSourceType.syntheticMethods(); 150 int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length; 151 this.index = methodId; 152 this.selector = selector; 153 this.returnType = declaringSourceType.scope.createArrayType(TypeBinding.INT, 1); 154 this.parameters = Binding.NO_PARAMETERS; 155 this.targetReadField = targetField; 156 this.targetEnumType = enumBinding; 157 this.kind = SwitchTable; 158 this.thrownExceptions = Binding.NO_EXCEPTIONS; 159 this.declaringClass = declaringSourceType; 160 161 if (declaringSourceType.isStrictfp()) { 162 this.modifiers |= ClassFileConstants.AccStrictfp; 163 } 164 boolean needRename; 166 do { 167 check : { 168 needRename = false; 169 long range; 171 MethodBinding[] methods = declaringSourceType.methods(); 172 if ((range = ReferenceBinding.binarySearch(this.selector, methods)) >= 0) { 173 int paramCount = this.parameters.length; 174 nextMethod: for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) { 175 MethodBinding method = methods[imethod]; 176 if (method.parameters.length == paramCount) { 177 TypeBinding[] toMatch = method.parameters; 178 for (int i = 0; i < paramCount; i++) { 179 if (toMatch[i] != this.parameters[i]) { 180 continue nextMethod; 181 } 182 } 183 needRename = true; 184 break check; 185 } 186 } 187 } 188 if (knownAccessMethods != null) { 190 for (int i = 0, length = knownAccessMethods.length; i < length; i++) { 191 if (knownAccessMethods[i] == null) continue; 192 if (CharOperation.equals(this.selector, knownAccessMethods[i].selector) && this.areParametersEqual(methods[i])) { 193 needRename = true; 194 break check; 195 } 196 } 197 } 198 } 199 if (needRename) { this.setSelector(CharOperation.concat(selector, String.valueOf(++methodId).toCharArray())); 201 } 202 } while (needRename); 203 204 this.sourceStart = declaringSourceType.scope.referenceContext.sourceStart; } 208 209 public SyntheticMethodBinding(MethodBinding targetMethod, boolean isSuperAccess, ReferenceBinding receiverType) { 210 211 if (targetMethod.isConstructor()) { 212 this.initializeConstructorAccessor(targetMethod); 213 } else { 214 this.initializeMethodAccessor(targetMethod, isSuperAccess, receiverType); 215 } 216 } 217 218 221 public SyntheticMethodBinding(MethodBinding overridenMethodToBridge, MethodBinding targetMethod, SourceTypeBinding declaringClass) { 222 223 this.declaringClass = declaringClass; 224 this.selector = overridenMethodToBridge.selector; 225 this.modifiers = (targetMethod.modifiers | ClassFileConstants.AccBridge | ClassFileConstants.AccSynthetic) & ~(ClassFileConstants.AccAbstract | ClassFileConstants.AccNative | ClassFileConstants.AccFinal | ExtraCompilerModifiers.AccGenericSignature); 228 this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); 229 this.returnType = overridenMethodToBridge.returnType; 230 this.parameters = overridenMethodToBridge.parameters; 231 this.thrownExceptions = overridenMethodToBridge.thrownExceptions; 232 this.targetMethod = targetMethod; 233 this.kind = BridgeMethod; 234 SyntheticMethodBinding[] knownAccessMethods = declaringClass.syntheticMethods(); 235 int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length; 236 this.index = methodId; 237 } 238 239 242 public SyntheticMethodBinding(SourceTypeBinding declaringEnum, char[] selector) { 243 this.declaringClass = declaringEnum; 244 this.selector = selector; 245 this.modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccStatic; 246 this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); 247 this.thrownExceptions = Binding.NO_EXCEPTIONS; 248 if (selector == TypeConstants.VALUES) { 249 this.returnType = declaringEnum.scope.createArrayType(declaringEnum, 1); 250 this.parameters = Binding.NO_PARAMETERS; 251 this.kind = EnumValues; 252 } else if (selector == TypeConstants.VALUEOF) { 253 this.returnType = declaringEnum; 254 this.parameters = new TypeBinding[]{ declaringEnum.scope.getJavaLangString() }; 255 this.kind = EnumValueOf; 256 } 257 SyntheticMethodBinding[] knownAccessMethods = ((SourceTypeBinding)this.declaringClass).syntheticMethods(); 258 int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length; 259 this.index = methodId; 260 if (declaringEnum.isStrictfp()) { 261 this.modifiers |= ClassFileConstants.AccStrictfp; 262 } 263 } 264 265 269 public void initializeConstructorAccessor(MethodBinding accessedConstructor) { 270 271 this.targetMethod = accessedConstructor; 272 this.modifiers = ClassFileConstants.AccDefault | ClassFileConstants.AccSynthetic; 273 this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); 274 SourceTypeBinding sourceType = (SourceTypeBinding) accessedConstructor.declaringClass; 275 SyntheticMethodBinding[] knownSyntheticMethods = 276 sourceType.syntheticMethods(); 277 this.index = knownSyntheticMethods == null ? 0 : knownSyntheticMethods.length; 278 279 this.selector = accessedConstructor.selector; 280 this.returnType = accessedConstructor.returnType; 281 this.kind = ConstructorAccess; 282 this.parameters = new TypeBinding[accessedConstructor.parameters.length + 1]; 283 System.arraycopy( 284 accessedConstructor.parameters, 285 0, 286 this.parameters, 287 0, 288 accessedConstructor.parameters.length); 289 parameters[accessedConstructor.parameters.length] = 290 accessedConstructor.declaringClass; 291 this.thrownExceptions = accessedConstructor.thrownExceptions; 292 this.declaringClass = sourceType; 293 294 boolean needRename; 296 do { 297 check : { 298 needRename = false; 299 MethodBinding[] methods = sourceType.methods(); 301 for (int i = 0, length = methods.length; i < length; i++) { 302 if (CharOperation.equals(this.selector, methods[i].selector) 303 && this.areParametersEqual(methods[i])) { 304 needRename = true; 305 break check; 306 } 307 } 308 if (knownSyntheticMethods != null) { 310 for (int i = 0, length = knownSyntheticMethods.length; i < length; i++) { 311 if (knownSyntheticMethods[i] == null) 312 continue; 313 if (CharOperation.equals(this.selector, knownSyntheticMethods[i].selector) 314 && this.areParametersEqual(knownSyntheticMethods[i])) { 315 needRename = true; 316 break check; 317 } 318 } 319 } 320 } 321 if (needRename) { int length = this.parameters.length; 323 System.arraycopy( 324 this.parameters, 325 0, 326 this.parameters = new TypeBinding[length + 1], 327 0, 328 length); 329 this.parameters[length] = this.declaringClass; 330 } 331 } while (needRename); 332 333 AbstractMethodDeclaration[] methodDecls = 335 sourceType.scope.referenceContext.methods; 336 if (methodDecls != null) { 337 for (int i = 0, length = methodDecls.length; i < length; i++) { 338 if (methodDecls[i].binding == accessedConstructor) { 339 this.sourceStart = methodDecls[i].sourceStart; 340 return; 341 } 342 } 343 } 344 } 345 346 349 public void initializeMethodAccessor(MethodBinding accessedMethod, boolean isSuperAccess, ReferenceBinding receiverType) { 350 351 this.targetMethod = accessedMethod; 352 this.modifiers = ClassFileConstants.AccDefault | ClassFileConstants.AccStatic | ClassFileConstants.AccSynthetic; 353 this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); 354 SourceTypeBinding declaringSourceType = (SourceTypeBinding) receiverType; 355 SyntheticMethodBinding[] knownAccessMethods = declaringSourceType.syntheticMethods(); 356 int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length; 357 this.index = methodId; 358 359 this.selector = CharOperation.concat(TypeConstants.SYNTHETIC_ACCESS_METHOD_PREFIX, String.valueOf(methodId).toCharArray()); 360 this.returnType = accessedMethod.returnType; 361 this.kind = isSuperAccess ? SuperMethodAccess : MethodAccess; 362 363 if (accessedMethod.isStatic()) { 364 this.parameters = accessedMethod.parameters; 365 } else { 366 this.parameters = new TypeBinding[accessedMethod.parameters.length + 1]; 367 this.parameters[0] = declaringSourceType; 368 System.arraycopy(accessedMethod.parameters, 0, this.parameters, 1, accessedMethod.parameters.length); 369 } 370 this.thrownExceptions = accessedMethod.thrownExceptions; 371 this.declaringClass = declaringSourceType; 372 373 boolean needRename; 375 do { 376 check : { 377 needRename = false; 378 MethodBinding[] methods = declaringSourceType.methods(); 380 for (int i = 0, length = methods.length; i < length; i++) { 381 if (CharOperation.equals(this.selector, methods[i].selector) && this.areParametersEqual(methods[i])) { 382 needRename = true; 383 break check; 384 } 385 } 386 if (knownAccessMethods != null) { 388 for (int i = 0, length = knownAccessMethods.length; i < length; i++) { 389 if (knownAccessMethods[i] == null) continue; 390 if (CharOperation.equals(this.selector, knownAccessMethods[i].selector) && this.areParametersEqual(knownAccessMethods[i])) { 391 needRename = true; 392 break check; 393 } 394 } 395 } 396 } 397 if (needRename) { this.setSelector(CharOperation.concat(TypeConstants.SYNTHETIC_ACCESS_METHOD_PREFIX, String.valueOf(++methodId).toCharArray())); 399 } 400 } while (needRename); 401 402 AbstractMethodDeclaration[] methodDecls = declaringSourceType.scope.referenceContext.methods; 404 if (methodDecls != null) { 405 for (int i = 0, length = methodDecls.length; i < length; i++) { 406 if (methodDecls[i].binding == accessedMethod) { 407 this.sourceStart = methodDecls[i].sourceStart; 408 return; 409 } 410 } 411 } 412 } 413 414 protected boolean isConstructorRelated() { 415 return kind == ConstructorAccess; 416 } 417 } 418 | Popular Tags |