KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > eval > CodeSnippetSingleNameReference


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

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.BinaryExpression;
15 import org.eclipse.jdt.internal.compiler.ast.CompoundAssignment;
16 import org.eclipse.jdt.internal.compiler.ast.Expression;
17 import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
18 import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
19 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
20 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
21 import org.eclipse.jdt.internal.compiler.flow.FlowContext;
22 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
23 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
24 import org.eclipse.jdt.internal.compiler.impl.Constant;
25 import org.eclipse.jdt.internal.compiler.lookup.*;
26 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
27 import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
28 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
29 import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
30 import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
31 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
32 import org.eclipse.jdt.internal.compiler.lookup.ProblemBinding;
33 import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
34 import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
35 import org.eclipse.jdt.internal.compiler.lookup.Scope;
36 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
37 import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
38
39 /**
40  * A single name reference inside a code snippet can denote a field of a remote
41  * receiver object (that is, the receiver of the context in the stack frame).
42  */

43 public class CodeSnippetSingleNameReference extends SingleNameReference implements EvaluationConstants, InvocationSite, ProblemReasons {
44
45     EvaluationContext evaluationContext;
46     FieldBinding delegateThis;
47     
48 public CodeSnippetSingleNameReference(char[] source, long pos, EvaluationContext evaluationContext) {
49     super(source, pos);
50     this.evaluationContext = evaluationContext;
51 }
52 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) {
53
54     switch (this.bits & RestrictiveFlagMASK) {
55         case Binding.FIELD : // reading a field
56
// check if reading a final blank field
57
FieldBinding fieldBinding;
58             if ((fieldBinding = (FieldBinding) this.binding).isBlankFinal()
59                     && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
60                 if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
61                     currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
62                 }
63             }
64             break;
65         case Binding.LOCAL : // reading a local variable
66
LocalVariableBinding localBinding;
67             if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) {
68                 currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
69             }
70             if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
71                 localBinding.useFlag = LocalVariableBinding.USED;
72             } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) {
73                 localBinding.useFlag = LocalVariableBinding.FAKE_USED;
74             }
75     }
76     return flowInfo;
77 }
78 /**
79  * Check and/or redirect the field access to the delegate receiver if any
80  */

81 public TypeBinding checkFieldAccess(BlockScope scope) {
82
83     if (this.delegateThis == null) {
84         return super.checkFieldAccess(scope);
85     }
86     FieldBinding fieldBinding = (FieldBinding) this.binding;
87     this.bits &= ~RestrictiveFlagMASK; // clear bits
88
this.bits |= Binding.FIELD;
89     if (!fieldBinding.isStatic()) {
90         // must check for the static status....
91
if (this.evaluationContext.isStatic) {
92             scope.problemReporter().staticFieldAccessToNonStaticVariable(
93                 this,
94                 fieldBinding);
95             this.constant = Constant.NotAConstant;
96             return null;
97         }
98     }
99     this.constant = fieldBinding.constant();
100
101     if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & IsStrictlyAssigned) !=0)) {
102         scope.problemReporter().deprecatedField(fieldBinding, this);
103     }
104     return fieldBinding.type;
105
106 }
107 public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
108
109     // optimizing assignment like: i = i + 1 or i = 1 + i
110
if (assignment.expression.isCompactableOperation()) {
111         BinaryExpression operation = (BinaryExpression) assignment.expression;
112         int operator = (operation.bits & OperatorMASK) >> OperatorSHIFT;
113         SingleNameReference variableReference;
114         if ((operation.left instanceof SingleNameReference) && ((variableReference = (SingleNameReference) operation.left).binding == this.binding)) {
115             // i = i + value, then use the variable on the right hand side, since it has the correct implicit conversion
116
variableReference.generateCompoundAssignment(currentScope, codeStream, this.syntheticAccessors == null ? null : this.syntheticAccessors[WRITE], operation.right, operator, operation.implicitConversion, valueRequired);
117             if (valueRequired) {
118                 codeStream.generateImplicitConversion(assignment.implicitConversion);
119             }
120             return;
121         }
122         if ((operation.right instanceof SingleNameReference)
123             && ((operator == PLUS) || (operator == MULTIPLY)) // only commutative operations
124
&& ((variableReference = (SingleNameReference) operation.right).binding == this.binding)
125             && (operation.left.constant != Constant.NotAConstant) // exclude non constant expressions, since could have side-effect
126
&& (((operation.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_JavaLangString) // exclude string concatenation which would occur backwards
127
&& (((operation.right.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_JavaLangString)) { // exclude string concatenation which would occur backwards
128
// i = value + i, then use the variable on the right hand side, since it has the correct implicit conversion
129
variableReference.generateCompoundAssignment(currentScope, codeStream, this.syntheticAccessors == null ? null : this.syntheticAccessors[WRITE], operation.left, operator, operation.implicitConversion, valueRequired);
130             if (valueRequired) {
131                 codeStream.generateImplicitConversion(assignment.implicitConversion);
132             }
133             return;
134         }
135     }
136     switch (this.bits & RestrictiveFlagMASK) {
137         case Binding.FIELD : // assigning to a field
138
FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
139             if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
140                 if (!fieldBinding.isStatic()) { // need a receiver?
141
if ((this.bits & DepthMASK) != 0) {
142                         ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
143                         Object JavaDoc[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
144                         codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
145                     } else {
146                         this.generateReceiver(codeStream);
147                     }
148                 }
149                 assignment.expression.generateCode(currentScope, codeStream, true);
150                 fieldStore(codeStream, fieldBinding, null, valueRequired);
151                 if (valueRequired) {
152                     codeStream.generateImplicitConversion(assignment.implicitConversion);
153                 }
154             } else {
155                 codeStream.generateEmulationForField(fieldBinding);
156                 if (!fieldBinding.isStatic()) { // need a receiver?
157
if ((this.bits & DepthMASK) != 0) {
158                         // internal error, per construction we should have found it
159
// not yet supported
160
currentScope.problemReporter().needImplementation();
161                     } else {
162                         this.generateReceiver(codeStream);
163                     }
164                 } else {
165                     codeStream.aconst_null();
166                 }
167                 assignment.expression.generateCode(currentScope, codeStream, true);
168                 if (valueRequired) {
169                     if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) {
170                         codeStream.dup2_x2();
171                     } else {
172                         codeStream.dup_x2();
173                     }
174                 }
175                 codeStream.generateEmulatedWriteAccessForField(fieldBinding);
176                 if (valueRequired) {
177                     codeStream.generateImplicitConversion(assignment.implicitConversion);
178                 }
179             }
180             return;
181         case Binding.LOCAL : // assigning to a local variable
182
LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
183             if (localBinding.resolvedPosition != -1) {
184                 assignment.expression.generateCode(currentScope, codeStream, true);
185             } else {
186                 if (assignment.expression.constant != Constant.NotAConstant) {
187                     // assigning an unused local to a constant value = no actual assignment is necessary
188
if (valueRequired) {
189                         codeStream.generateConstant(assignment.expression.constant, assignment.implicitConversion);
190                     }
191                 } else {
192                     assignment.expression.generateCode(currentScope, codeStream, true);
193                     /* Even though the value may not be required, we force it to be produced, and discard it later
194                     on if it was actually not necessary, so as to provide the same behavior as JDK1.2beta3. */

195                     if (valueRequired) {
196                         codeStream.generateImplicitConversion(assignment.implicitConversion); // implicit conversion
197
} else {
198                         if ((localBinding.type == TypeBinding.LONG) || (localBinding.type == TypeBinding.DOUBLE)) {
199                             codeStream.pop2();
200                         } else {
201                             codeStream.pop();
202                         }
203                     }
204                 }
205                 return;
206             }
207             // normal local assignment (since cannot store in outer local which are final locations)
208
codeStream.store(localBinding, valueRequired);
209             if ((this.bits & FirstAssignmentToLocal) != 0) { // for local variable debug attributes
210
localBinding.recordInitializationStartPC(codeStream.position);
211             }
212             // implicit conversion
213
if (valueRequired) {
214                 codeStream.generateImplicitConversion(assignment.implicitConversion);
215             }
216     }
217 }
218 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
219     int pc = codeStream.position;
220     if (this.constant != Constant.NotAConstant) {
221         if (valueRequired) {
222             codeStream.generateConstant(this.constant, this.implicitConversion);
223         }
224     } else {
225         switch (this.bits & RestrictiveFlagMASK) {
226             case Binding.FIELD : // reading a field
227
if (!valueRequired)
228                     break;
229                 FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
230                 Constant fieldConstant = fieldBinding.constant();
231                 if (fieldConstant == Constant.NotAConstant) { // directly use inlined value for constant fields
232
if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
233                          // directly use inlined value for constant fields
234
boolean isStatic;
235                         if (!(isStatic = fieldBinding.isStatic())) {
236                             if ((this.bits & DepthMASK) != 0) {
237                                 ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
238                                 Object JavaDoc[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
239                                 codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
240                             } else {
241                                 generateReceiver(codeStream);
242                             }
243                         }
244                         // managing private access
245
if (isStatic) {
246                             codeStream.getstatic(fieldBinding);
247                         } else {
248                             codeStream.getfield(fieldBinding);
249                         }
250                     } else {
251                         // managing private access
252
if (!fieldBinding.isStatic()) {
253                             if ((this.bits & DepthMASK) != 0) {
254                                 // internal error, per construction we should have found it
255
// not yet supported
256
currentScope.problemReporter().needImplementation();
257                             } else {
258                                 generateReceiver(codeStream);
259                             }
260                         } else {
261                             codeStream.aconst_null();
262                         }
263                         codeStream.generateEmulatedReadAccessForField(fieldBinding);
264                     }
265                     if (this.genericCast != null) codeStream.checkcast(this.genericCast);
266                     codeStream.generateImplicitConversion(this.implicitConversion);
267                 } else { // directly use the inlined value
268
codeStream.generateConstant(fieldConstant, this.implicitConversion);
269                 }
270                 break;
271             case Binding.LOCAL : // reading a local
272
LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
273                 if (!valueRequired)
274                     break;
275                 // outer local?
276
if ((this.bits & DepthMASK) != 0) {
277                     // outer local can be reached either through a synthetic arg or a synthetic field
278
VariableBinding[] path = currentScope.getEmulationPath(localBinding);
279                     codeStream.generateOuterAccess(path, this, localBinding, currentScope);
280                 } else {
281                     // regular local variable read
282
codeStream.load(localBinding);
283                 }
284                 codeStream.generateImplicitConversion(this.implicitConversion);
285                 break;
286         }
287     }
288     codeStream.recordPositionsFrom(pc, this.sourceStart);
289 }
290 /*
291  * The APIs with an extra argument is used whenever there are two references to the same variable which
292  * are optimized in one access: e.g "a = a + 1" optimized into "a++".
293  */

294 public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, MethodBinding writeAccessor, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
295     switch (this.bits & RestrictiveFlagMASK) {
296         case Binding.FIELD : // assigning to a field
297
FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
298             if (fieldBinding.isStatic()) {
299                 if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
300                     codeStream.getstatic(fieldBinding);
301                 } else {
302                     // used to store the value
303
codeStream.generateEmulationForField(fieldBinding);
304                     codeStream.aconst_null();
305
306                     // used to retrieve the actual value
307
codeStream.aconst_null();
308                     codeStream.generateEmulatedReadAccessForField(fieldBinding);
309                 }
310             } else {
311                 if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
312                     if ((this.bits & DepthMASK) != 0) {
313                         ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
314                         Object JavaDoc[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
315                         codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
316                     } else {
317                         generateReceiver(codeStream);
318                     }
319                     codeStream.dup();
320                     codeStream.getfield(fieldBinding);
321                 } else {
322                     if ((this.bits & DepthMASK) != 0) {
323                         // internal error, per construction we should have found it
324
// not yet supported
325
currentScope.problemReporter().needImplementation();
326                     }
327                     // used to store the value
328
codeStream.generateEmulationForField(fieldBinding);
329                     generateReceiver(codeStream);
330
331                     // used to retrieve the actual value
332
codeStream.dup();
333                     codeStream.generateEmulatedReadAccessForField(fieldBinding);
334                 }
335             }
336             break;
337         case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local)
338
LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
339             Constant assignConstant;
340             int increment;
341             // using incr bytecode if possible
342
switch (localBinding.type.id) {
343                 case T_JavaLangString :
344                     codeStream.generateStringConcatenationAppend(currentScope, this, expression);
345                     if (valueRequired) {
346                         codeStream.dup();
347                     }
348                     codeStream.store(localBinding, false);
349                     return;
350                 case T_int :
351                     if (((assignConstant = expression.constant) != Constant.NotAConstant)
352                         && (assignConstant.typeID() != T_float) // only for integral types
353
&& (assignConstant.typeID() != T_double)
354                         && ((increment = assignConstant.intValue()) == (short) increment)) { // 16 bits value
355
switch (operator) {
356                             case PLUS :
357                                 codeStream.iinc(localBinding.resolvedPosition, increment);
358                                 if (valueRequired) {
359                                     codeStream.load(localBinding);
360                                 }
361                                 return;
362                             case MINUS :
363                                 codeStream.iinc(localBinding.resolvedPosition, -increment);
364                                 if (valueRequired) {
365                                     codeStream.load(localBinding);
366                                 }
367                                 return;
368                         }
369                     }
370                 default :
371                     codeStream.load(localBinding);
372             }
373     }
374     // perform the actual compound operation
375
int operationTypeID;
376     switch(operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
377         case T_JavaLangString :
378         case T_JavaLangObject :
379         case T_undefined :
380             codeStream.generateStringConcatenationAppend(currentScope, null, expression);
381             break;
382         default :
383             // promote the array reference to the suitable operation type
384
codeStream.generateImplicitConversion(this.implicitConversion);
385             // generate the increment value (will by itself be promoted to the operation value)
386
if (expression == IntLiteral.One){ // prefix operation
387
codeStream.generateConstant(expression.constant, this.implicitConversion);
388             } else {
389                 expression.generateCode(currentScope, codeStream, true);
390             }
391             // perform the operation
392
codeStream.sendOperator(operator, operationTypeID);
393             // cast the value back to the array reference type
394
codeStream.generateImplicitConversion(assignmentImplicitConversion);
395     }
396     // store the result back into the variable
397
switch (this.bits & RestrictiveFlagMASK) {
398         case Binding.FIELD : // assigning to a field
399
FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
400             if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
401                 fieldStore(codeStream, fieldBinding, writeAccessor, valueRequired);
402             } else {
403                 // current stack is:
404
// field receiver value
405
if (valueRequired) {
406                     if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) {
407                         codeStream.dup2_x2();
408                     } else {
409                         codeStream.dup_x2();
410                     }
411                 }
412                 // current stack is:
413
// value field receiver value
414
codeStream.generateEmulatedWriteAccessForField(fieldBinding);
415             }
416             return;
417         case Binding.LOCAL : // assigning to a local variable
418
LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
419             if (valueRequired) {
420                 if ((localBinding.type == TypeBinding.LONG) || (localBinding.type == TypeBinding.DOUBLE)) {
421                     codeStream.dup2();
422                 } else {
423                     codeStream.dup();
424                 }
425             }
426             codeStream.store(localBinding, false);
427     }
428 }
429 public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
430     switch (this.bits & RestrictiveFlagMASK) {
431         case Binding.FIELD : // assigning to a field
432
FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
433             if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
434                 if (fieldBinding.isStatic()) {
435                     codeStream.getstatic(fieldBinding);
436                 } else {
437                     if ((this.bits & DepthMASK) != 0) {
438                         ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
439                         Object JavaDoc[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
440                         codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
441                     } else {
442                         generateReceiver(codeStream);
443                     }
444                     codeStream.dup();
445                     codeStream.getfield(fieldBinding);
446                 }
447                 if (valueRequired) {
448                     if (fieldBinding.isStatic()) {
449                         if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) {
450                             codeStream.dup2();
451                         } else {
452                             codeStream.dup();
453                         }
454                     } else { // Stack: [owner][old field value] ---> [old field value][owner][old field value]
455
if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) {
456                             codeStream.dup2_x1();
457                         } else {
458                             codeStream.dup_x1();
459                         }
460                     }
461                 }
462                 codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
463                 codeStream.sendOperator(postIncrement.operator, fieldBinding.type.id);
464                 codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
465                 fieldStore(codeStream, fieldBinding, null, false);
466             } else {
467                 if (fieldBinding.isStatic()) {
468                     codeStream.aconst_null();
469                 } else {
470                     if ((this.bits & DepthMASK) != 0) {
471                         // internal error, per construction we should have found it
472
// not yet supported
473
currentScope.problemReporter().needImplementation();
474                     } else {
475                         generateReceiver(codeStream);
476                     }
477                 }
478                 codeStream.generateEmulatedReadAccessForField(fieldBinding);
479                 if (valueRequired) {
480                     if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) {
481                         codeStream.dup2();
482                     } else {
483                         codeStream.dup();
484                     }
485                 }
486                 codeStream.generateEmulationForField(fieldBinding);
487                 if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) {
488                     codeStream.dup_x2();
489                     codeStream.pop();
490                     if (fieldBinding.isStatic()) {
491                         codeStream.aconst_null();
492                     } else {
493                         generateReceiver(codeStream);
494                     }
495                     codeStream.dup_x2();
496                     codeStream.pop();
497                 } else {
498                     codeStream.dup_x1();
499                     codeStream.pop();
500                     if (fieldBinding.isStatic()) {
501                         codeStream.aconst_null();
502                     } else {
503                         generateReceiver(codeStream);
504                     }
505                     codeStream.dup_x1();
506                     codeStream.pop();
507                 }
508                 codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
509                 codeStream.sendOperator(postIncrement.operator, fieldBinding.type.id);
510                 codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
511                 codeStream.generateEmulatedWriteAccessForField(fieldBinding);
512             }
513             return;
514         case Binding.LOCAL : // assigning to a local variable
515
LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
516             // using incr bytecode if possible
517
if (localBinding.type == TypeBinding.INT) {
518                 if (valueRequired) {
519                     codeStream.load(localBinding);
520                 }
521                 if (postIncrement.operator == PLUS) {
522                     codeStream.iinc(localBinding.resolvedPosition, 1);
523                 } else {
524                     codeStream.iinc(localBinding.resolvedPosition, -1);
525                 }
526             } else {
527                 codeStream.load(localBinding);
528                 if (valueRequired){
529                     if ((localBinding.type == TypeBinding.LONG) || (localBinding.type == TypeBinding.DOUBLE)) {
530                         codeStream.dup2();
531                     } else {
532                         codeStream.dup();
533                     }
534                 }
535                 codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
536                 codeStream.sendOperator(postIncrement.operator, localBinding.type.id);
537                 codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
538
539                 codeStream.store(localBinding, false);
540             }
541     }
542 }
543 public void generateReceiver(CodeStream codeStream) {
544     codeStream.aload_0();
545     if (this.delegateThis != null) {
546         codeStream.getfield(this.delegateThis); // delegated field access
547
}
548 }
549 /**
550  * Check and/or redirect the field access to the delegate receiver if any
551  */

552 public TypeBinding getReceiverType(BlockScope currentScope) {
553     Scope scope = currentScope.parent;
554     while (true) {
555             switch (scope.kind) {
556                 case Scope.CLASS_SCOPE :
557                     return ((ClassScope) scope).referenceContext.binding;
558                 default:
559                     scope = scope.parent;
560             }
561     }
562 }
563 public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo, boolean isReadAccess) {
564
565     if (this.delegateThis == null) {
566         super.manageSyntheticAccessIfNecessary(currentScope, flowInfo, isReadAccess);
567         return;
568     }
569
570     if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return;
571     //If inlinable field, forget the access emulation, the code gen will directly target it
572
if (this.constant != Constant.NotAConstant)
573         return;
574     // if field from parameterized type got found, use the original field at codegen time
575
if (this.binding instanceof ParameterizedFieldBinding) {
576         ParameterizedFieldBinding parameterizedField = (ParameterizedFieldBinding) this.binding;
577         this.codegenBinding = parameterizedField.originalField;
578         FieldBinding fieldCodegenBinding = (FieldBinding)this.codegenBinding;
579         // extra cast needed if field type was type variable
580
if ((fieldCodegenBinding.type.tagBits & TagBits.HasTypeVariable) != 0) {
581             this.genericCast = fieldCodegenBinding.type.genericCast(currentScope.boxing(parameterizedField.type)); // runtimeType could be base type in boxing case
582
}
583     }
584     if ((this.bits & Binding.FIELD) != 0) {
585         FieldBinding fieldBinding = (FieldBinding) this.binding;
586         
587         // if the binding declaring class is not visible, need special action
588
// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
589
// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
590
// and not from Object or implicit static field access.
591
if (fieldBinding.declaringClass != this.delegateThis.type
592                 && fieldBinding.declaringClass != null // array.length
593
&& fieldBinding.constant() == Constant.NotAConstant) {
594             CompilerOptions options = currentScope.compilerOptions();
595             if ((options.targetJDK >= ClassFileConstants.JDK1_2
596                     && (options.complianceLevel >= ClassFileConstants.JDK1_4 || !fieldBinding.isStatic())
597                     && fieldBinding.declaringClass.id != T_JavaLangObject) // no change for Object fields
598
|| !fieldBinding.declaringClass.canBeSeenBy(currentScope)) {
599     
600                 this.codegenBinding =
601                     currentScope.enclosingSourceType().getUpdatedFieldBinding(
602                            (FieldBinding)this.codegenBinding,
603                             (ReferenceBinding)this.delegateThis.type.erasure());
604             }
605         }
606     }
607 }
608 /**
609  * Normal field binding did not work, try to bind to a field of the delegate receiver.
610  */

611 public TypeBinding reportError(BlockScope scope) {
612
613     this.constant = Constant.NotAConstant;
614     if (this.binding instanceof ProblemFieldBinding && ((ProblemFieldBinding) this.binding).problemId() == NotFound){
615         if (this.evaluationContext.declaringTypeName != null) {
616             this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
617             if (this.delegateThis != null){ // if not found then internal error, field should have been found
618
// will not support innerclass emulation inside delegate
619
this.codegenBinding = this.binding = scope.getField(this.delegateThis.type, this.token, this);
620                 if (!this.binding.isValidBinding()) {
621                     return super.reportError(scope);
622                 }
623                 return checkFieldAccess(scope);
624             }
625         }
626     }
627     if (this.binding instanceof ProblemBinding && ((ProblemBinding) this.binding).problemId() == NotFound){
628         if (this.evaluationContext.declaringTypeName != null) {
629             this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
630             if (this.delegateThis != null){ // if not found then internal error, field should have been found
631
// will not support innerclass emulation inside delegate
632
FieldBinding fieldBinding = scope.getField(this.delegateThis.type, this.token, this);
633                 if (!fieldBinding.isValidBinding()) {
634                     if (((ProblemFieldBinding) fieldBinding).problemId() == NotVisible) {
635                         // manage the access to a private field of the enclosing type
636
CodeSnippetScope localScope = new CodeSnippetScope(scope);
637                         this.codegenBinding = this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.token, this);
638                         return checkFieldAccess(scope);
639                     } else {
640                         return super.reportError(scope);
641                     }
642                 }
643                 this.codegenBinding = this.binding = fieldBinding;
644                 return checkFieldAccess(scope);
645             }
646         }
647     }
648     return super.reportError(scope);
649 }
650 }
651
Popular Tags