1 11 package org.eclipse.jdt.internal.eval; 12 13 import org.eclipse.jdt.internal.compiler.ast.Assignment; 14 import org.eclipse.jdt.internal.compiler.ast.CompoundAssignment; 15 import org.eclipse.jdt.internal.compiler.ast.Expression; 16 import org.eclipse.jdt.internal.compiler.ast.FieldReference; 17 import org.eclipse.jdt.internal.compiler.ast.IntLiteral; 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.BlockScope; 24 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; 25 import org.eclipse.jdt.internal.compiler.lookup.ParameterizedFieldBinding; 26 import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding; 27 import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons; 28 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; 29 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; 30 import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; 31 32 public class CodeSnippetFieldReference extends FieldReference implements ProblemReasons, EvaluationConstants { 33 34 EvaluationContext evaluationContext; 35 FieldBinding delegateThis; 36 41 public CodeSnippetFieldReference(char[] source, long pos, EvaluationContext evaluationContext) { 42 super(source, pos); 43 this.evaluationContext = evaluationContext; 44 } 45 public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) { 46 47 if (this.codegenBinding.canBeSeenBy(this.receiverType, this, currentScope)) { 48 this.receiver.generateCode(currentScope, codeStream, !this.codegenBinding.isStatic()); 49 assignment.expression.generateCode(currentScope, codeStream, true); 50 fieldStore(codeStream, this.codegenBinding, null, valueRequired); 51 } else { 52 codeStream.generateEmulationForField(this.codegenBinding); 53 this.receiver.generateCode(currentScope, codeStream, !this.codegenBinding.isStatic()); 54 if (this.codegenBinding.isStatic()) { codeStream.aconst_null(); 56 } 57 assignment.expression.generateCode(currentScope, codeStream, true); 58 if (valueRequired) { 59 if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) { 60 codeStream.dup2_x2(); 61 } else { 62 codeStream.dup_x2(); 63 } 64 } 65 codeStream.generateEmulatedWriteAccessForField(this.codegenBinding); 66 } 67 if (valueRequired){ 68 codeStream.generateImplicitConversion(assignment.implicitConversion); 69 } 70 } 71 78 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { 79 80 int pc = codeStream.position; 81 if (this.constant != Constant.NotAConstant) { 82 if (valueRequired) { 83 codeStream.generateConstant(this.constant, this.implicitConversion); 84 } 85 } else { 86 boolean isStatic = this.codegenBinding.isStatic(); 87 this.receiver.generateCode(currentScope, codeStream, !isStatic); 88 if (valueRequired) { 89 Constant fieldConstant = this.codegenBinding.constant(); 90 if (fieldConstant == Constant.NotAConstant) { 91 if (this.codegenBinding.declaringClass == null) { codeStream.arraylength(); 93 } else { 94 if (this.codegenBinding.canBeSeenBy(this.receiverType, this, currentScope)) { 95 if (isStatic) { 96 codeStream.getstatic(this.codegenBinding); 97 } else { 98 codeStream.getfield(this.codegenBinding); 99 } 100 } else { 101 if (isStatic) { 102 codeStream.aconst_null(); 104 } 105 codeStream.generateEmulatedReadAccessForField(this.codegenBinding); 106 } 107 } 108 codeStream.generateImplicitConversion(this.implicitConversion); 109 } else { 110 if (!isStatic) { 111 codeStream.invokeObjectGetClass(); codeStream.pop(); 113 } 114 codeStream.generateConstant(fieldConstant, this.implicitConversion); 115 } 116 } else { 117 if (!isStatic){ 118 codeStream.invokeObjectGetClass(); codeStream.pop(); 120 } 121 } 122 } 123 codeStream.recordPositionsFrom(pc, this.sourceStart); 124 } 125 126 public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { 127 128 boolean isStatic; 129 if (this.codegenBinding.canBeSeenBy(this.receiverType, this, currentScope)) { 130 this.receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic())); 131 if (isStatic) { 132 codeStream.getstatic(this.codegenBinding); 133 } else { 134 codeStream.dup(); 135 codeStream.getfield(this.codegenBinding); 136 } 137 int operationTypeID; 138 switch(operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) { 139 case T_JavaLangString : 140 case T_JavaLangObject : 141 case T_undefined : 142 codeStream.generateStringConcatenationAppend(currentScope, null, expression); 143 break; 144 default : 145 codeStream.generateImplicitConversion(this.implicitConversion); 147 if (expression == IntLiteral.One){ codeStream.generateConstant(expression.constant, this.implicitConversion); 150 } else { 151 expression.generateCode(currentScope, codeStream, true); 152 } 153 codeStream.sendOperator(operator, operationTypeID); 155 codeStream.generateImplicitConversion(assignmentImplicitConversion); 157 } 158 fieldStore(codeStream, this.codegenBinding, null, valueRequired); 159 } else { 160 this.receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic())); 161 if (isStatic) { 162 codeStream.generateEmulationForField(this.codegenBinding); 164 codeStream.aconst_null(); 165 166 codeStream.aconst_null(); 168 codeStream.generateEmulatedReadAccessForField(this.codegenBinding); 169 } else { 170 codeStream.generateEmulationForField(this.binding); 172 this.receiver.generateCode(currentScope, codeStream, !isStatic); 173 174 codeStream.dup(); 176 codeStream.generateEmulatedReadAccessForField(this.codegenBinding); 177 } 178 int operationTypeID; 179 if ((operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_JavaLangString) { 180 codeStream.generateStringConcatenationAppend(currentScope, null, expression); 181 } else { 182 codeStream.generateImplicitConversion(this.implicitConversion); 184 if (expression == IntLiteral.One){ codeStream.generateConstant(expression.constant, this.implicitConversion); 187 } else { 188 expression.generateCode(currentScope, codeStream, true); 189 } 190 codeStream.sendOperator(operator, operationTypeID); 192 codeStream.generateImplicitConversion(assignmentImplicitConversion); 194 } 195 if (valueRequired) { 198 if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) { 199 codeStream.dup2_x2(); 200 } else { 201 codeStream.dup_x2(); 202 } 203 } 204 codeStream.generateEmulatedWriteAccessForField(this.codegenBinding); 207 } 208 } 209 public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) { 210 boolean isStatic; 211 if (this.codegenBinding.canBeSeenBy(this.receiverType, this, currentScope)) { 212 this.receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic())); 213 if (isStatic) { 214 codeStream.getstatic(this.codegenBinding); 215 } else { 216 codeStream.dup(); 217 codeStream.getfield(this.codegenBinding); 218 } 219 if (valueRequired) { 220 if (isStatic) { 221 if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) { 222 codeStream.dup2(); 223 } else { 224 codeStream.dup(); 225 } 226 } else { if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) { 228 codeStream.dup2_x1(); 229 } else { 230 codeStream.dup_x1(); 231 } 232 } 233 } 234 codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion); 235 codeStream.sendOperator(postIncrement.operator, this.codegenBinding.type.id); 236 codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion); 237 fieldStore(codeStream, this.codegenBinding, null, false); 238 } else { 239 this.receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic())); 240 if (isStatic) { 241 codeStream.aconst_null(); 242 } 243 codeStream.dup(); 245 codeStream.generateEmulatedReadAccessForField(this.codegenBinding); 247 if (valueRequired) { 259 if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) { 260 codeStream.dup2_x1(); 261 } else { 262 codeStream.dup_x1(); 263 } 264 } 265 if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) { 266 codeStream.dup2_x1(); 267 codeStream.pop2(); 268 } else { 269 codeStream.dup_x1(); 270 codeStream.pop(); 271 } 272 codeStream.generateEmulationForField(this.codegenBinding); 273 codeStream.swap(); 274 275 if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) { 276 codeStream.dup2_x2(); 277 } else { 278 codeStream.dup2_x1(); 279 } 280 codeStream.pop2(); 281 282 codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion); 283 codeStream.sendOperator(postIncrement.operator, this.codegenBinding.type.id); 284 codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion); 285 codeStream.generateEmulatedWriteAccessForField(this.codegenBinding); 286 } 287 } 288 291 public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo, boolean isReadAccess){ 292 294 if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return; 295 296 if (this.binding instanceof ParameterizedFieldBinding) { 298 ParameterizedFieldBinding parameterizedField = (ParameterizedFieldBinding) this.binding; 299 this.codegenBinding = parameterizedField.originalField; 300 if (this.codegenBinding.type.isTypeVariable()) { 302 TypeVariableBinding variableReturnType = (TypeVariableBinding) this.codegenBinding.type; 303 if (variableReturnType.firstBound != parameterizedField.type) { this.genericCast = parameterizedField.type.erasure(); 305 } 306 } 307 } else { 308 this.codegenBinding = this.binding; 309 } 310 311 TypeBinding someReceiverType = this.delegateThis != null ? this.delegateThis.type : this.receiverType; 315 if (this.binding.declaringClass != someReceiverType 316 && !someReceiverType.isArrayType() 317 && this.binding.declaringClass != null && this.binding.constant() == Constant.NotAConstant) { 319 320 CompilerOptions options = currentScope.compilerOptions(); 321 if ((options.targetJDK >= ClassFileConstants.JDK1_2 322 && (options.complianceLevel >= ClassFileConstants.JDK1_4 || !receiver.isImplicitThis() || !this.codegenBinding.isStatic()) 323 && this.binding.declaringClass.id != T_JavaLangObject) || !this.binding.declaringClass.canBeSeenBy(currentScope)) { 325 326 this.codegenBinding = 327 currentScope.enclosingSourceType().getUpdatedFieldBinding( 328 this.codegenBinding, 329 (ReferenceBinding) someReceiverType.erasure()); 330 } 331 } 332 } 333 public TypeBinding resolveType(BlockScope scope) { 334 338 this.receiverType = this.receiver.resolveType(scope); 340 if (this.receiverType == null){ 341 this.constant = Constant.NotAConstant; 342 return null; 343 } 344 this.codegenBinding = this.binding = scope.getField(this.receiverType, this.token, this); 346 FieldBinding firstAttempt = this.binding; 347 boolean isNotVisible = false; 348 if (!this.binding.isValidBinding()) { 349 if (this.binding instanceof ProblemFieldBinding 350 && ((ProblemFieldBinding) this.binding).problemId() == NotVisible) { 351 isNotVisible = true; 352 if (this.evaluationContext.declaringTypeName != null) { 353 this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this); 354 if (this.delegateThis == null){ this.constant = Constant.NotAConstant; 356 scope.problemReporter().invalidField(this, this.receiverType); 357 return null; 358 } 359 } else { 360 this.constant = Constant.NotAConstant; 361 scope.problemReporter().invalidField(this, this.receiverType); 362 return null; 363 } 364 CodeSnippetScope localScope = new CodeSnippetScope(scope); 365 this.codegenBinding = this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.token, this); 366 } 367 } 368 369 if (!this.binding.isValidBinding()) { 370 this.constant = Constant.NotAConstant; 371 if (isNotVisible) { 372 this.codegenBinding = this.binding = firstAttempt; 373 } 374 scope.problemReporter().invalidField(this, this.receiverType); 375 return null; 376 } 377 378 if (isFieldUseDeprecated(this.binding, scope, (this.bits & IsStrictlyAssigned) !=0)) { 379 scope.problemReporter().deprecatedField(this.binding, this); 380 } 381 this.constant = this.receiver.isImplicitThis() ? this.binding.constant() : Constant.NotAConstant; 383 if (!this.receiver.isThis()) { this.constant = Constant.NotAConstant; 385 } 386 return this.resolvedType = this.binding.type; 387 } 388 } 389 | Popular Tags |