1 11 package org.eclipse.jdt.internal.eval; 12 13 import org.eclipse.jdt.core.compiler.CharOperation; 14 import org.eclipse.jdt.internal.compiler.ast.CastExpression; 15 import org.eclipse.jdt.internal.compiler.ast.Expression; 16 import org.eclipse.jdt.internal.compiler.ast.MessageSend; 17 import org.eclipse.jdt.internal.compiler.ast.NameReference; 18 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 19 import org.eclipse.jdt.internal.compiler.codegen.CodeStream; 20 import org.eclipse.jdt.internal.compiler.flow.FlowInfo; 21 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; 22 import org.eclipse.jdt.internal.compiler.impl.Constant; 23 import org.eclipse.jdt.internal.compiler.lookup.Binding; 24 import org.eclipse.jdt.internal.compiler.lookup.BlockScope; 25 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; 26 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; 27 import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding; 28 import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons; 29 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; 30 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; 31 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; 32 import org.eclipse.jdt.internal.compiler.lookup.TypeIds; 33 import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; 34 35 public class CodeSnippetMessageSend extends MessageSend implements ProblemReasons, EvaluationConstants { 36 EvaluationContext evaluationContext; 37 FieldBinding delegateThis; 38 41 public CodeSnippetMessageSend(EvaluationContext evaluationContext) { 42 this.evaluationContext = evaluationContext; 43 } 44 51 public void generateCode( 52 BlockScope currentScope, 53 CodeStream codeStream, 54 boolean valueRequired) { 55 56 int pc = codeStream.position; 57 58 if (this.codegenBinding.canBeSeenBy(this.actualReceiverType, this, currentScope)) { 59 boolean isStatic = this.codegenBinding.isStatic(); 61 if (!isStatic && ((this.bits & DepthMASK) != 0)) { 63 ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT); 65 Object [] path = currentScope.getEmulationPath(targetType, true , false); 66 if (path == null) { 67 currentScope.problemReporter().needImplementation(); 69 } else { 70 codeStream.generateOuterAccess(path, this, targetType, currentScope); 71 } 72 } else { 73 this.receiver.generateCode(currentScope, codeStream, !isStatic); 74 if (this.receiverGenericCast != null) 75 codeStream.checkcast(this.receiverGenericCast); 76 codeStream.recordPositionsFrom(pc, this.sourceStart); 77 } 78 generateArguments(binding, arguments, currentScope, codeStream); 80 if (isStatic) { 82 codeStream.invokestatic(this.codegenBinding); 83 } else { 84 if (this.receiver.isSuper()) { 85 codeStream.invokespecial(this.codegenBinding); 86 } else { 87 if (this.codegenBinding.declaringClass.isInterface()) { 88 codeStream.invokeinterface(this.codegenBinding); 89 } else { 90 codeStream.invokevirtual(this.codegenBinding); 91 } 92 } 93 } 94 } else { 95 codeStream.generateEmulationForMethod(currentScope, this.codegenBinding); 96 boolean isStatic = this.codegenBinding.isStatic(); 98 if (!isStatic && ((this.bits & DepthMASK) != 0)) { 100 currentScope.problemReporter().needImplementation(); 102 } else { 103 this.receiver.generateCode(currentScope, codeStream, !isStatic); 104 if (this.receiverGenericCast != null) 105 codeStream.checkcast(this.receiverGenericCast); 106 codeStream.recordPositionsFrom(pc, this.sourceStart); 107 } 108 if (isStatic) { 109 codeStream.aconst_null(); 111 } 112 if (this.arguments != null) { 114 int argsLength = this.arguments.length; 115 codeStream.generateInlinedValue(argsLength); 116 codeStream.newArray(currentScope.createArrayType(currentScope.getType(TypeConstants.JAVA_LANG_OBJECT, 3), 1)); 117 codeStream.dup(); 118 for (int i = 0; i < argsLength; i++) { 119 codeStream.generateInlinedValue(i); 120 this.arguments[i].generateCode(currentScope, codeStream, true); 121 TypeBinding parameterBinding = this.codegenBinding.parameters[i]; 122 if (parameterBinding.isBaseType() && parameterBinding != TypeBinding.NULL) { 123 codeStream.generateBoxingConversion(this.codegenBinding.parameters[i].id); 124 } 125 codeStream.aastore(); 126 if (i < argsLength - 1) { 127 codeStream.dup(); 128 } 129 } 130 } else { 131 codeStream.generateInlinedValue(0); 132 codeStream.newArray(currentScope.createArrayType(currentScope.getType(TypeConstants.JAVA_LANG_OBJECT, 3), 1)); 133 } 134 codeStream.invokeJavaLangReflectMethodInvoke(); 135 136 if (this.codegenBinding.returnType.isBaseType()) { 138 int typeID = this.codegenBinding.returnType.id; 139 if (typeID == T_void) { 140 codeStream.pop(); 142 } 143 codeStream.checkcast(typeID); 144 codeStream.getBaseTypeValue(typeID); 145 } else { 146 codeStream.checkcast(this.codegenBinding.returnType); 147 } 148 } 149 if (this.valueCast != null) codeStream.checkcast(this.valueCast); 151 if (valueRequired){ 152 codeStream.generateImplicitConversion(implicitConversion); 154 } else { 155 boolean isUnboxing = (implicitConversion & TypeIds.UNBOXING) != 0; 156 if (isUnboxing) codeStream.generateImplicitConversion(implicitConversion); 158 switch (isUnboxing ? postConversionType(currentScope).id : this.codegenBinding.returnType.id) { 159 case T_long : 160 case T_double : 161 codeStream.pop2(); 162 break; 163 case T_void : 164 break; 165 default : 166 codeStream.pop(); 167 } 168 } 169 codeStream.recordPositionsFrom(pc, (int)(this.nameSourcePosition >>> 32)); } 171 public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { 172 173 if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { 174 175 this.codegenBinding = this.binding.original(); 177 if (this.codegenBinding != this.binding) { 178 if (this.codegenBinding.returnType.isTypeVariable()) { 180 TypeVariableBinding variableReturnType = (TypeVariableBinding) this.codegenBinding.returnType; 181 if (variableReturnType.firstBound != this.binding.returnType) { this.valueCast = this.binding.returnType; 183 } 184 } 185 } 186 187 if (this.binding.declaringClass != this.actualReceiverType 192 && !this.actualReceiverType.isArrayType()) { 193 CompilerOptions options = currentScope.compilerOptions(); 194 if ((options.targetJDK >= ClassFileConstants.JDK1_2 195 && (options.complianceLevel >= ClassFileConstants.JDK1_4 || !receiver.isImplicitThis() || !this.codegenBinding.isStatic()) 196 && this.binding.declaringClass.id != T_JavaLangObject) || !this.binding.declaringClass.canBeSeenBy(currentScope)) { 198 199 this.codegenBinding = currentScope.enclosingSourceType().getUpdatedMethodBinding( 200 this.codegenBinding, (ReferenceBinding) this.actualReceiverType.erasure()); 201 } 202 } 205 } 206 } 207 public TypeBinding resolveType(BlockScope scope) { 208 211 this.constant = Constant.NotAConstant; 212 boolean receiverCast = false, argsContainCast = false; 213 if (this.receiver instanceof CastExpression) { 214 this.receiver.bits |= DisableUnnecessaryCastCheck; receiverCast = true; 216 } 217 this.actualReceiverType = receiver.resolveType(scope); 218 if (receiverCast && this.actualReceiverType != null) { 219 if (((CastExpression)this.receiver).expression.resolvedType == this.actualReceiverType) { 221 scope.problemReporter().unnecessaryCast((CastExpression)this.receiver); 222 } 223 } 224 if (this.typeArguments != null) { 226 int length = this.typeArguments.length; 227 boolean argHasError = false; this.genericTypeArguments = new TypeBinding[length]; 229 for (int i = 0; i < length; i++) { 230 if ((this.genericTypeArguments[i] = this.typeArguments[i].resolveType(scope, true )) == null) { 231 argHasError = true; 232 } 233 } 234 if (argHasError) { 235 return null; 236 } 237 } 238 TypeBinding[] argumentTypes = Binding.NO_PARAMETERS; 240 if (this.arguments != null) { 241 boolean argHasError = false; int length = this.arguments.length; 243 argumentTypes = new TypeBinding[length]; 244 for (int i = 0; i < length; i++) { 245 Expression argument = arguments[i]; 246 if (argument instanceof CastExpression) { 247 argument.bits |= DisableUnnecessaryCastCheck; argsContainCast = true; 249 } 250 if ((argumentTypes[i] = this.arguments[i].resolveType(scope)) == null) 251 argHasError = true; 252 } 253 if (argHasError) { 254 if(actualReceiverType instanceof ReferenceBinding) { 255 this.binding = scope.findMethod((ReferenceBinding)actualReceiverType, selector, new TypeBinding[]{}, this); 257 } 258 return null; 259 } 260 } 261 if (this.actualReceiverType == null) { 262 return null; 263 } 264 if (this.actualReceiverType.isBaseType()) { 266 scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes); 267 return null; 268 } 269 270 this.binding = 271 this.receiver.isImplicitThis() 272 ? scope.getImplicitMethod(this.selector, argumentTypes, this) 273 : scope.getMethod(this.actualReceiverType, this.selector, argumentTypes, this); 274 if (!this.binding.isValidBinding()) { 275 if (this.binding instanceof ProblemMethodBinding 276 && ((ProblemMethodBinding) this.binding).problemId() == NotVisible) { 277 if (this.evaluationContext.declaringTypeName != null) { 278 this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this); 279 if (this.delegateThis == null){ this.constant = Constant.NotAConstant; 281 scope.problemReporter().invalidMethod(this, this.binding); 282 return null; 283 } 284 } else { 285 this.constant = Constant.NotAConstant; 286 scope.problemReporter().invalidMethod(this, this.binding); 287 return null; 288 } 289 CodeSnippetScope localScope = new CodeSnippetScope(scope); 290 MethodBinding privateBinding = 291 this.receiver instanceof CodeSnippetThisReference && ((CodeSnippetThisReference) this.receiver).isImplicit 292 ? localScope.getImplicitMethod((ReferenceBinding)this.delegateThis.type, this.selector, argumentTypes, this) 293 : localScope.getMethod(this.delegateThis.type, this.selector, argumentTypes, this); 294 if (!privateBinding.isValidBinding()) { 295 if (this.binding.declaringClass == null) { 296 if (this.actualReceiverType instanceof ReferenceBinding) { 297 this.binding.declaringClass = (ReferenceBinding) this.actualReceiverType; 298 } else { scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes); 300 return null; 301 } 302 } 303 scope.problemReporter().invalidMethod(this, this.binding); 304 return null; 305 } else { 306 this.binding = privateBinding; 307 } 308 } else { 309 if (this.binding.declaringClass == null) { 310 if (this.actualReceiverType instanceof ReferenceBinding) { 311 this.binding.declaringClass = (ReferenceBinding) this.actualReceiverType; 312 } else { scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes); 314 return null; 315 } 316 } 317 scope.problemReporter().invalidMethod(this, this.binding); 318 return null; 319 } 320 } 321 if (!this.binding.isStatic()) { 322 if (receiver instanceof NameReference 324 && (((NameReference) receiver).bits & Binding.TYPE) != 0) { 325 scope.problemReporter().mustUseAStaticMethod(this, binding); 326 } else { 327 TypeBinding receiverErasure = this.actualReceiverType.erasure(); 329 if (receiverErasure instanceof ReferenceBinding) { 330 if (receiverErasure.findSuperTypeWithSameErasure(this.binding.declaringClass) == null) { 331 this.actualReceiverType = this.binding.declaringClass; } 333 } 334 receiver.computeConversion(scope, this.actualReceiverType, this.actualReceiverType); 335 } 336 } 337 checkInvocationArguments(scope, this.receiver, actualReceiverType, binding, this.arguments, argumentTypes, argsContainCast, this); 338 339 if (binding.isAbstract()) { 341 if (receiver.isSuper()) { 342 scope.problemReporter().cannotDireclyInvokeAbstractMethod(this, binding); 343 } 344 } 346 if (isMethodUseDeprecated(binding, scope, true)) 347 scope.problemReporter().deprecatedMethod(binding, this); 348 349 if (actualReceiverType.isArrayType() 351 && this.binding.parameters == Binding.NO_PARAMETERS 352 && scope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_5 353 && CharOperation.equals(this.binding.selector, CLONE)) { 354 this.resolvedType = actualReceiverType; 355 } else { 356 TypeBinding returnType = this.binding.returnType; 357 if (returnType != null) returnType = returnType.capture(scope, this.sourceEnd); 358 this.resolvedType = returnType; 359 } 360 return this.resolvedType; 361 } 362 } 363 | Popular Tags |