KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > ast > QualifiedNameReference


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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.compiler.ast;
12
13 import org.eclipse.jdt.internal.compiler.ASTVisitor;
14 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
15 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
16 import org.eclipse.jdt.internal.compiler.flow.FlowContext;
17 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
18 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
19 import org.eclipse.jdt.internal.compiler.impl.Constant;
20 import org.eclipse.jdt.internal.compiler.lookup.Binding;
21 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
22 import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
23 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
24 import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
25 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
26 import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
27 import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
28 import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
29 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
30 import org.eclipse.jdt.internal.compiler.lookup.Scope;
31 import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
32 import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
33 import org.eclipse.jdt.internal.compiler.lookup.TagBits;
34 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
35 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
36 import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
37 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
38
39 public class QualifiedNameReference extends NameReference {
40     
41     public char[][] tokens;
42     public long[] sourcePositions;
43     public FieldBinding[] otherBindings, otherCodegenBindings;
44     int[] otherDepths;
45     public int indexOfFirstFieldBinding;//points (into tokens) for the first token that corresponds to first FieldBinding
46
SyntheticMethodBinding syntheticWriteAccessor;
47     SyntheticMethodBinding[] syntheticReadAccessors;
48     public TypeBinding genericCast;
49     public TypeBinding[] otherGenericCasts;
50     
51 public QualifiedNameReference( char[][] tokens, long[] positions, int sourceStart, int sourceEnd) {
52     this.tokens = tokens;
53     this.sourcePositions = positions;
54     this.sourceStart = sourceStart;
55     this.sourceEnd = sourceEnd;
56 }
57
58 public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound) {
59     // determine the rank until which we now we do not need any actual value for the field access
60
int otherBindingsCount = this.otherBindings == null ? 0 : this.otherBindings.length;
61     boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic();
62     boolean complyTo14 = currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4;
63     FieldBinding lastFieldBinding = null;
64     switch (this.bits & ASTNode.RestrictiveFlagMASK) {
65         case Binding.FIELD : // reading a field
66
lastFieldBinding = (FieldBinding) this.binding;
67             if (needValue || complyTo14) {
68                 manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, this.actualReceiverType, 0, flowInfo);
69             }
70             if (this.indexOfFirstFieldBinding == 1) { // was an implicit reference to the first field binding
71
ReferenceBinding declaringClass = lastFieldBinding.declaringClass;
72                 // check if accessing enum static field in initializer
73
if (declaringClass.isEnum()) {
74                     MethodScope methodScope = currentScope.methodScope();
75                     SourceTypeBinding sourceType = methodScope.enclosingSourceType();
76                     if (lastFieldBinding.isStatic()
77                             && (sourceType == declaringClass || sourceType.superclass == declaringClass) // enum constant body
78
&& lastFieldBinding.constant() == Constant.NotAConstant
79                             && !methodScope.isStatic
80                             && methodScope.isInsideInitializerOrConstructor()) {
81                         currentScope.problemReporter().enumStaticFieldUsedDuringInitialization(lastFieldBinding, this);
82                     }
83                 }
84             }
85             // check if final blank field
86
if (lastFieldBinding.isBlankFinal()
87                     && this.otherBindings != null // the last field binding is only assigned
88
&& currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)) {
89                 if (!flowInfo.isDefinitelyAssigned(lastFieldBinding)) {
90                     currentScope.problemReporter().uninitializedBlankFinalField(
91                         lastFieldBinding,
92                         this);
93                 }
94             }
95             break;
96         case Binding.LOCAL :
97             // first binding is a local variable
98
LocalVariableBinding localBinding;
99             if (!flowInfo
100                 .isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) {
101                 currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
102             }
103             if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
104                 localBinding.useFlag = LocalVariableBinding.USED;
105             } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) {
106                 localBinding.useFlag = LocalVariableBinding.FAKE_USED;
107             }
108             checkNPE(currentScope, flowContext, flowInfo, true);
109     }
110     
111     if (needValue) {
112         manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
113         // only for first binding
114
}
115     // all intermediate field accesses are read accesses
116
if (this.otherBindings != null) {
117         for (int i = 0; i < otherBindingsCount-1; i++) {
118             lastFieldBinding = this.otherBindings[i];
119             needValue = !this.otherBindings[i+1].isStatic();
120             if (needValue || complyTo14) {
121                 manageSyntheticAccessIfNecessary(
122                     currentScope,
123                     lastFieldBinding,
124                     i == 0
125                         ? ((VariableBinding)this.binding).type
126                         : this.otherBindings[i-1].type,
127                     i + 1,
128                     flowInfo);
129             }
130         }
131         lastFieldBinding = this.otherBindings[otherBindingsCount-1];
132     }
133
134     if (isCompound) {
135         if (otherBindingsCount == 0
136                 && lastFieldBinding.isBlankFinal()
137                 && currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)
138                 && (!flowInfo.isDefinitelyAssigned(lastFieldBinding))) {
139             currentScope.problemReporter().uninitializedBlankFinalField(lastFieldBinding, this);
140         }
141         TypeBinding lastReceiverType;
142         switch (otherBindingsCount) {
143             case 0 :
144                 lastReceiverType = this.actualReceiverType;
145                 break;
146             case 1 :
147                 lastReceiverType = ((VariableBinding)this.binding).type;
148                 break;
149             default:
150                 lastReceiverType = this.otherBindings[otherBindingsCount-2].type;
151                 break;
152         }
153         manageSyntheticAccessIfNecessary(
154             currentScope,
155             lastFieldBinding,
156             lastReceiverType,
157             otherBindingsCount,
158             flowInfo);
159     }
160     
161     if (assignment.expression != null) {
162         flowInfo =
163             assignment
164                 .expression
165                 .analyseCode(currentScope, flowContext, flowInfo)
166                 .unconditionalInits();
167     }
168     
169     // the last field access is a write access
170
if (lastFieldBinding.isFinal()) {
171         // in a context where it can be assigned?
172
if (otherBindingsCount == 0
173                 && this.indexOfFirstFieldBinding == 1
174                 && lastFieldBinding.isBlankFinal()
175                 && !isCompound
176                 && currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)) {
177             if (flowInfo.isPotentiallyAssigned(lastFieldBinding)) {
178                 currentScope.problemReporter().duplicateInitializationOfBlankFinalField(lastFieldBinding, this);
179             } else {
180                 flowContext.recordSettingFinal(lastFieldBinding, this, flowInfo);
181             }
182             flowInfo.markAsDefinitelyAssigned(lastFieldBinding);
183         } else {
184             currentScope.problemReporter().cannotAssignToFinalField(lastFieldBinding, this);
185             if (otherBindingsCount == 0 && currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)) { // pretend it got assigned
186
flowInfo.markAsDefinitelyAssigned(lastFieldBinding);
187             }
188         }
189     }
190     // equivalent to valuesRequired[maxOtherBindings]
191
TypeBinding lastReceiverType;
192     switch (otherBindingsCount) {
193         case 0 :
194             lastReceiverType = this.actualReceiverType;
195             break;
196         case 1 :
197             lastReceiverType = ((VariableBinding)this.binding).type;
198             break;
199         default :
200             lastReceiverType = this.otherBindings[otherBindingsCount-2].type;
201             break;
202     }
203     manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, lastReceiverType, -1 /*write-access*/, flowInfo);
204
205     return flowInfo;
206 }
207
208 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
209     return analyseCode(currentScope, flowContext, flowInfo, true);
210 }
211
212 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) {
213     // determine the rank until which we now we do not need any actual value for the field access
214
int otherBindingsCount = this.otherBindings == null ? 0 : this.otherBindings.length;
215
216     boolean needValue = otherBindingsCount == 0 ? valueRequired : !this.otherBindings[0].isStatic();
217     boolean complyTo14 = currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4;
218     switch (this.bits & ASTNode.RestrictiveFlagMASK) {
219         case Binding.FIELD : // reading a field
220
if (needValue || complyTo14) {
221                 manageSyntheticAccessIfNecessary(currentScope, (FieldBinding) this.binding, this.actualReceiverType, 0, flowInfo);
222             }
223             if (this.indexOfFirstFieldBinding == 1) { // was an implicit reference to the first field binding
224
FieldBinding fieldBinding = (FieldBinding) this.binding;
225                 ReferenceBinding declaringClass = fieldBinding.declaringClass;
226                 // check if accessing enum static field in initializer
227
if (declaringClass.isEnum()) {
228                     MethodScope methodScope = currentScope.methodScope();
229                     SourceTypeBinding sourceType = methodScope.enclosingSourceType();
230                     if (fieldBinding.isStatic()
231                             && (sourceType == declaringClass || sourceType.superclass == declaringClass) // enum constant body
232
&& fieldBinding.constant() == Constant.NotAConstant
233                             && !methodScope.isStatic
234                             && methodScope.isInsideInitializerOrConstructor()) {
235                         currentScope.problemReporter().enumStaticFieldUsedDuringInitialization(fieldBinding, this);
236                     }
237                 }
238                 // check if reading a final blank field
239
if (fieldBinding.isBlankFinal()
240                         && currentScope.allowBlankFinalFieldAssignment(fieldBinding)
241                         && !flowInfo.isDefinitelyAssigned(fieldBinding)) {
242                     currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
243                 }
244             }
245             break;
246         case Binding.LOCAL : // reading a local variable
247
LocalVariableBinding localBinding;
248             if (!flowInfo
249                 .isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) {
250                 currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
251             }
252             if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
253                 localBinding.useFlag = LocalVariableBinding.USED;
254             } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) {
255                 localBinding.useFlag = LocalVariableBinding.FAKE_USED;
256             }
257             checkNPE(currentScope, flowContext, flowInfo, true);
258     }
259     if (needValue) {
260         manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
261         // only for first binding (if value needed only)
262
}
263     if (this.otherBindings != null) {
264         for (int i = 0; i < otherBindingsCount; i++) {
265             needValue = i < otherBindingsCount-1 ? !this.otherBindings[i+1].isStatic() : valueRequired;
266             if (needValue || complyTo14) {
267                 TypeBinding lastReceiverType = getGenericCast(i);
268                 if (lastReceiverType == null) {
269                     if (i == 0) {
270                          lastReceiverType = ((VariableBinding)this.binding).type;
271                     } else {
272                         lastReceiverType = this.otherBindings[i-1].type;
273                     }
274                 }
275                 manageSyntheticAccessIfNecessary(
276                     currentScope,
277                     this.otherBindings[i],
278                     lastReceiverType,
279                     i + 1,
280                     flowInfo);
281             }
282         }
283     }
284     return flowInfo;
285 }
286
287 /**
288  * Check and/or redirect the field access to the delegate receiver if any
289  */

290 public TypeBinding checkFieldAccess(BlockScope scope) {
291     FieldBinding fieldBinding = (FieldBinding) this.binding;
292     MethodScope methodScope = scope.methodScope();
293     // check for forward references
294
if (this.indexOfFirstFieldBinding == 1
295             && methodScope.enclosingSourceType() == fieldBinding.original().declaringClass
296             && methodScope.lastVisibleFieldID >= 0
297             && fieldBinding.id >= methodScope.lastVisibleFieldID
298             && (!fieldBinding.isStatic() || methodScope.isStatic)) {
299         scope.problemReporter().forwardReference(this, 0, methodScope.enclosingSourceType());
300     }
301     this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits
302
this.bits |= Binding.FIELD;
303     return getOtherFieldBindings(scope);
304 }
305
306 public void checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, boolean checkString) {
307     // cannot override localVariableBinding because this would project o.m onto o when
308
// analysing assignments
309
if ((this.bits & ASTNode.RestrictiveFlagMASK) == Binding.LOCAL) {
310         LocalVariableBinding local = (LocalVariableBinding) this.binding;
311         if (local != null &&
312             (local.type.tagBits & TagBits.IsBaseType) == 0 &&
313             (checkString || local.type.id != TypeIds.T_JavaLangString)) {
314             if ((this.bits & ASTNode.IsNonNull) == 0) {
315                 flowContext.recordUsingNullReference(scope, local, this,
316                     FlowContext.MAY_NULL, flowInfo);
317             }
318             flowInfo.markAsComparedEqualToNonNull(local);
319                 // from thereon it is set
320
if (flowContext.initsOnFinally != null) {
321                 flowContext.initsOnFinally.markAsComparedEqualToNonNull(local);
322             }
323         }
324     }
325 }
326
327 /**
328  * @see org.eclipse.jdt.internal.compiler.ast.Expression#computeConversion(org.eclipse.jdt.internal.compiler.lookup.Scope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
329  */

330 public void computeConversion(Scope scope, TypeBinding runtimeTimeType, TypeBinding compileTimeType) {
331     if (runtimeTimeType == null || compileTimeType == null)
332         return;
333     // set the generic cast after the fact, once the type expectation is fully known (no need for strict cast)
334
FieldBinding field = null;
335     int length = this.otherBindings == null ? 0 : this.otherBindings.length;
336     if (length == 0) {
337         if ((this.bits & Binding.FIELD) != 0 && this.binding != null && this.binding.isValidBinding()) {
338             field = (FieldBinding) this.binding;
339         }
340     } else {
341         field = this.otherBindings[length-1];
342     }
343     if (field != null) {
344         FieldBinding originalBinding = field.original();
345         TypeBinding originalType = originalBinding.type;
346         // extra cast needed if method return type has type variable
347
if (originalBinding != field
348                 && originalType != field.type
349                 && runtimeTimeType.id != TypeIds.T_JavaLangObject
350                 && (originalType.tagBits & TagBits.HasTypeVariable) != 0) {
351             TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType())
352                 ? compileTimeType // unboxing: checkcast before conversion
353
: runtimeTimeType;
354             setGenericCast(length, originalType.genericCast(targetType));
355         }
356     }
357     super.computeConversion(scope, runtimeTimeType, compileTimeType);
358 }
359
360 public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
361     int pc = codeStream.position;
362     FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
363     codeStream.recordPositionsFrom(pc , this.sourceStart);
364     assignment.expression.generateCode(currentScope, codeStream, true);
365     fieldStore(codeStream, lastFieldBinding, this.syntheticWriteAccessor, valueRequired);
366     // equivalent to valuesRequired[maxOtherBindings]
367
if (valueRequired) {
368         codeStream.generateImplicitConversion(assignment.implicitConversion);
369     }
370 }
371
372 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
373     int pc = codeStream.position;
374     if (this.constant != Constant.NotAConstant) {
375         if (valueRequired) {
376             codeStream.generateConstant(this.constant, this.implicitConversion);
377         }
378     } else {
379         FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
380         if (lastFieldBinding != null) {
381             boolean isStatic = lastFieldBinding.isStatic();
382             Constant fieldConstant = lastFieldBinding.constant();
383             if (fieldConstant != Constant.NotAConstant) {
384                 if (!isStatic){
385                     codeStream.invokeObjectGetClass();
386                     codeStream.pop();
387                 }
388                 if (valueRequired) { // inline the last field constant
389
codeStream.generateConstant(fieldConstant, this.implicitConversion);
390                 }
391             } else {
392                 boolean isFirst = lastFieldBinding == this.binding
393                                                 && (this.indexOfFirstFieldBinding == 1 || lastFieldBinding.declaringClass == currentScope.enclosingReceiverType())
394                                                 && this.otherBindings == null; // could be dup: next.next.next
395
TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length);
396                 if (valueRequired
397                         || (!isFirst && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)
398                         || ((this.implicitConversion & TypeIds.UNBOXING) != 0)
399                         || requiredGenericCast != null) {
400                     int lastFieldPc = codeStream.position;
401                     if (lastFieldBinding.declaringClass == null) { // array length
402
codeStream.arraylength();
403                         if (valueRequired) {
404                             codeStream.generateImplicitConversion(this.implicitConversion);
405                         } else {
406                             // could occur if !valueRequired but compliance >= 1.4
407
codeStream.pop();
408                         }
409                     } else {
410                         SyntheticMethodBinding accessor =
411                             this.syntheticReadAccessors == null
412                                 ? null
413                                 : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1];
414                         if (accessor == null) {
415                             if (isStatic) {
416                                 codeStream.getstatic(lastFieldBinding);
417                             } else {
418                                 codeStream.getfield(lastFieldBinding);
419                             }
420                         } else {
421                             codeStream.invokestatic(accessor);
422                         }
423                         if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast);
424                         if (valueRequired) {
425                             codeStream.generateImplicitConversion(this.implicitConversion);
426                         } else {
427                             boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0;
428                             // conversion only generated if unboxing
429
if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion);
430                             switch (isUnboxing ? postConversionType(currentScope).id : lastFieldBinding.type.id) {
431                                 case T_long :
432                                 case T_double :
433                                     codeStream.pop2();
434                                     break;
435                                 default :
436                                     codeStream.pop();
437                             }
438                         }
439                     }
440                     
441                     int fieldPosition = (int) (this.sourcePositions[this.sourcePositions.length - 1] >>> 32);
442                     codeStream.recordPositionsFrom(lastFieldPc, fieldPosition);
443                 } else {
444                     if (!isStatic){
445                         codeStream.invokeObjectGetClass(); // perform null check
446
codeStream.pop();
447                     }
448                 }
449             }
450         }
451     }
452     codeStream.recordPositionsFrom(pc, this.sourceStart);
453 }
454
455 public void generateCompoundAssignment(
456     BlockScope currentScope,
457     CodeStream codeStream,
458     Expression expression,
459     int operator,
460     int assignmentImplicitConversion,
461     boolean valueRequired) {
462         
463     FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
464     SyntheticMethodBinding accessor =
465         this.syntheticReadAccessors == null
466             ? null
467             : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1];
468     if (lastFieldBinding.isStatic()) {
469         if (accessor == null) {
470             codeStream.getstatic(lastFieldBinding);
471         } else {
472             codeStream.invokestatic(accessor);
473         }
474     } else {
475         codeStream.dup();
476         if (accessor == null) {
477             codeStream.getfield(lastFieldBinding);
478         } else {
479             codeStream.invokestatic(accessor);
480         }
481     }
482     // the last field access is a write access
483
// perform the actual compound operation
484
int operationTypeID;
485     switch(operationTypeID = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4) {
486         case T_JavaLangString :
487         case T_JavaLangObject :
488         case T_undefined :
489             codeStream.generateStringConcatenationAppend(currentScope, null, expression);
490             break;
491         default :
492             TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length);
493             if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast);
494             // promote the array reference to the suitable operation type
495
codeStream.generateImplicitConversion(this.implicitConversion);
496             // generate the increment value (will by itself be promoted to the operation value)
497
if (expression == IntLiteral.One) { // prefix operation
498
codeStream.generateConstant(expression.constant, this.implicitConversion);
499             } else {
500                 expression.generateCode(currentScope, codeStream, true);
501             }
502             // perform the operation
503
codeStream.sendOperator(operator, operationTypeID);
504             // cast the value back to the array reference type
505
codeStream.generateImplicitConversion(assignmentImplicitConversion);
506     }
507     // actual assignment
508
fieldStore(codeStream, lastFieldBinding, this.syntheticWriteAccessor, valueRequired);
509     // equivalent to valuesRequired[maxOtherBindings]
510
}
511
512 public void generatePostIncrement(
513     BlockScope currentScope,
514     CodeStream codeStream,
515     CompoundAssignment postIncrement,
516     boolean valueRequired) {
517     
518     FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
519     SyntheticMethodBinding accessor =
520         this.syntheticReadAccessors == null
521             ? null
522             : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1];
523     if (lastFieldBinding.isStatic()) {
524         if (accessor == null) {
525             codeStream.getstatic(lastFieldBinding);
526         } else {
527             codeStream.invokestatic(accessor);
528         }
529     } else {
530         codeStream.dup();
531         if (accessor == null) {
532             codeStream.getfield(lastFieldBinding);
533         } else {
534             codeStream.invokestatic(accessor);
535         }
536     }
537     // duplicate the old field value
538
if (valueRequired) {
539         if (lastFieldBinding.isStatic()) {
540             if ((lastFieldBinding.type == TypeBinding.LONG)
541                 || (lastFieldBinding.type == TypeBinding.DOUBLE)) {
542                 codeStream.dup2();
543             } else {
544                 codeStream.dup();
545             }
546         } else { // Stack: [owner][old field value] ---> [old field value][owner][old field value]
547
if ((lastFieldBinding.type == TypeBinding.LONG)
548                 || (lastFieldBinding.type == TypeBinding.DOUBLE)) {
549                 codeStream.dup2_x1();
550             } else {
551                 codeStream.dup_x1();
552             }
553         }
554     }
555     TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length);
556     if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast);
557     
558     codeStream.generateImplicitConversion(this.implicitConversion);
559     codeStream.generateConstant(
560         postIncrement.expression.constant,
561         this.implicitConversion);
562     codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK);
563     codeStream.generateImplicitConversion(
564         postIncrement.preAssignImplicitConversion);
565     fieldStore(codeStream, lastFieldBinding, this.syntheticWriteAccessor, false);
566 }
567
568 /*
569  * Generate code for all bindings (local and fields) excluding the last one, which may then be generated code
570  * for a read or write access.
571  */

572 public FieldBinding generateReadSequence(BlockScope currentScope, CodeStream codeStream) {
573     // determine the rank until which we now we do not need any actual value for the field access
574
int otherBindingsCount = this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length;
575     boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic();
576     FieldBinding lastFieldBinding = null;
577     TypeBinding lastGenericCast = null;
578     boolean complyTo14 = currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4;
579
580     switch (this.bits & ASTNode.RestrictiveFlagMASK) {
581         case Binding.FIELD :
582             lastFieldBinding = (FieldBinding) this.codegenBinding;
583             lastGenericCast = this.genericCast;
584             // if first field is actually constant, we can inline it
585
if (lastFieldBinding.constant() != Constant.NotAConstant) {
586                 break;
587             }
588             if ((needValue && !lastFieldBinding.isStatic()) || lastGenericCast != null) {
589                 int pc = codeStream.position;
590                 if ((this.bits & ASTNode.DepthMASK) != 0) {
591                     ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);
592                     Object JavaDoc[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
593                     codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
594                 } else {
595                     generateReceiver(codeStream);
596                 }
597                 codeStream.recordPositionsFrom(pc, this.sourceStart);
598             }
599             break;
600         case Binding.LOCAL : // reading the first local variable
601
if (!needValue) break; // no value needed
602
LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
603             // regular local variable read
604
Constant localConstant = localBinding.constant();
605             if (localConstant != Constant.NotAConstant) {
606                 codeStream.generateConstant(localConstant, 0);
607                 // no implicit conversion
608
} else {
609                 // outer local?
610
if ((this.bits & ASTNode.DepthMASK) != 0) {
611                     // outer local can be reached either through a synthetic arg or a synthetic field
612
VariableBinding[] path = currentScope.getEmulationPath(localBinding);
613                     codeStream.generateOuterAccess(path, this, localBinding, currentScope);
614                 } else {
615                     codeStream.load(localBinding);
616                 }
617             }
618     }
619                     
620     // all intermediate field accesses are read accesses
621
// only the last field binding is a write access
622
int positionsLength = this.sourcePositions.length;
623     if (this.otherCodegenBindings != null) {
624         for (int i = 0; i < otherBindingsCount; i++) {
625             int pc = codeStream.position;
626             FieldBinding nextField = this.otherCodegenBindings[i];
627             TypeBinding nextGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[i];
628             if (lastFieldBinding != null) {
629                 needValue = !nextField.isStatic();
630                 Constant fieldConstant = lastFieldBinding.constant();
631                 if (fieldConstant != Constant.NotAConstant) {
632                     if (i > 0 && !lastFieldBinding.isStatic()) {
633                         codeStream.invokeObjectGetClass(); // perform null check
634
codeStream.pop();
635                     }
636                     if (needValue) {
637                         codeStream.generateConstant(fieldConstant, 0);
638                     }
639                 } else {
640                     if (needValue || (i > 0 && complyTo14) || lastGenericCast != null) {
641                         MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i];
642                         if (accessor == null) {
643                             if (lastFieldBinding.isStatic()) {
644                                 codeStream.getstatic(lastFieldBinding);
645                             } else {
646                                 codeStream.getfield(lastFieldBinding);
647                             }
648                         } else {
649                             codeStream.invokestatic(accessor);
650                         }
651                         if (lastGenericCast != null) codeStream.checkcast(lastGenericCast);
652                         if (!needValue) codeStream.pop();
653                     } else {
654                         if (this.codegenBinding == lastFieldBinding) {
655                             if (lastFieldBinding.isStatic()){
656                                 // if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class
657
if (((FieldBinding)this.binding).original().declaringClass != this.actualReceiverType.erasure()) {
658                                     MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i];
659                                     if (accessor == null) {
660                                         codeStream.getstatic(lastFieldBinding);
661                                     } else {
662                                         codeStream.invokestatic(accessor);
663                                     }
664                                     codeStream.pop();
665                                 }
666                             }
667                         } else if (!lastFieldBinding.isStatic()){
668                             codeStream.invokeObjectGetClass(); // perform null check
669
codeStream.pop();
670                         }
671                     }
672                     if ((positionsLength - otherBindingsCount + i - 1) >= 0) {
673                         int fieldPosition = (int) (this.sourcePositions[positionsLength - otherBindingsCount + i - 1] >>>32);
674                         codeStream.recordPositionsFrom(pc, fieldPosition);
675                     }
676                 }
677             }
678             lastFieldBinding = nextField;
679             lastGenericCast = nextGenericCast;
680         }
681     }
682     return lastFieldBinding;
683 }
684
685 public void generateReceiver(CodeStream codeStream) {
686     codeStream.aload_0();
687 }
688
689 /**
690  * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
691  */

692 public TypeBinding[] genericTypeArguments() {
693     return null;
694 }
695
696 // get the matching codegenBinding
697
protected FieldBinding getCodegenBinding(int index) {
698   if (index == 0){
699         return (FieldBinding)this.codegenBinding;
700     } else {
701         return this.otherCodegenBindings[index-1];
702     }
703 }
704
705 // get the matching generic cast
706
protected TypeBinding getGenericCast(int index) {
707    if (index == 0){
708         return this.genericCast;
709     } else {
710         if (this.otherGenericCasts == null) return null;
711         return this.otherGenericCasts[index-1];
712     }
713 }
714
715 public TypeBinding getOtherFieldBindings(BlockScope scope) {
716     // At this point restrictiveFlag may ONLY have two potential value : FIELD LOCAL (i.e cast <<(VariableBinding) binding>> is valid)
717
int length = this.tokens.length;
718     FieldBinding field;
719     if ((this.bits & Binding.FIELD) != 0) {
720         field = (FieldBinding) this.binding;
721         if (!field.isStatic()) {
722             //must check for the static status....
723
if (this.indexOfFirstFieldBinding > 1 //accessing to a field using a type as "receiver" is allowed only with static field
724
|| scope.methodScope().isStatic) { // the field is the first token of the qualified reference....
725
scope.problemReporter().staticFieldAccessToNonStaticVariable(this, field);
726                 return null;
727              }
728         } else {
729             // indirect static reference ?
730
if (this.indexOfFirstFieldBinding > 1
731                     && field.declaringClass != this.actualReceiverType
732                     && field.declaringClass.canBeSeenBy(scope)) {
733                 scope.problemReporter().indirectAccessToStaticField(this, field);
734             }
735         }
736         // only last field is actually a write access if any
737
if (isFieldUseDeprecated(field, scope, (this.bits & ASTNode.IsStrictlyAssigned) != 0 && this.indexOfFirstFieldBinding == length))
738             scope.problemReporter().deprecatedField(field, this);
739     } else {
740         field = null;
741     }
742     TypeBinding type = ((VariableBinding) this.binding).type;
743     int index = this.indexOfFirstFieldBinding;
744     if (index == length) { // restrictiveFlag == FIELD
745
this.constant = ((FieldBinding) this.binding).constant();
746         // perform capture conversion if read access
747
return (type != null && (this.bits & ASTNode.IsStrictlyAssigned) == 0)
748                 ? type.capture(scope, this.sourceEnd)
749                 : type;
750     }
751     // allocation of the fieldBindings array and its respective constants
752
int otherBindingsLength = length - index;
753     this.otherCodegenBindings = this.otherBindings = new FieldBinding[otherBindingsLength];
754     this.otherDepths = new int[otherBindingsLength];
755     
756     // fill the first constant (the one of the binding)
757
this.constant = ((VariableBinding) this.binding).constant();
758     // save first depth, since will be updated by visibility checks of other bindings
759
int firstDepth = (this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT;
760     // iteration on each field
761
while (index < length) {
762         char[] token = this.tokens[index];
763         if (type == null)
764             return null; // could not resolve type prior to this point
765

766         this.bits &= ~ASTNode.DepthMASK; // flush previous depth if any
767
FieldBinding previousField = field;
768         field = scope.getField(type.capture(scope, (int)this.sourcePositions[index]), token, this);
769         int place = index - this.indexOfFirstFieldBinding;
770         this.otherBindings[place] = field;
771         this.otherDepths[place] = (this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT;
772         if (field.isValidBinding()) {
773             // set generic cast of for previous field (if any)
774
if (previousField != null) {
775                 TypeBinding fieldReceiverType = type;
776                 TypeBinding receiverErasure = type.erasure();
777                 if (receiverErasure instanceof ReferenceBinding) {
778                     if (receiverErasure.findSuperTypeWithSameErasure(field.declaringClass) == null) {
779                         fieldReceiverType = field.declaringClass; // handle indirect inheritance thru variable secondary bound
780
}
781                 }
782                 FieldBinding originalBinding = previousField.original();
783                 if ((originalBinding.type.tagBits & TagBits.HasTypeVariable) != 0 && fieldReceiverType.id != TypeIds.T_JavaLangObject) {
784                     setGenericCast(index-1,originalBinding.type.genericCast(fieldReceiverType)); // type cannot be base-type even in boxing case
785
}
786             }
787             // only last field is actually a write access if any
788
if (isFieldUseDeprecated(field, scope, (this.bits & ASTNode.IsStrictlyAssigned) !=0 && index+1 == length)) {
789                 scope.problemReporter().deprecatedField(field, this);
790             }
791             // constant propagation can only be performed as long as the previous one is a constant too.
792
if (this.constant != Constant.NotAConstant) {
793                 this.constant = field.constant();
794             }
795
796             if (field.isStatic()) {
797                 // static field accessed through receiver? legal but unoptimal (optional warning)
798
scope.problemReporter().nonStaticAccessToStaticField(this, field);
799                 // indirect static reference ?
800
if (field.declaringClass != type) {
801                     scope.problemReporter().indirectAccessToStaticField(this, field);
802                 }
803             }
804             type = field.type;
805             index++;
806         } else {
807             this.constant = Constant.NotAConstant; //don't fill other constants slots...
808
scope.problemReporter().invalidField(this, field, index, type);
809             setDepth(firstDepth);
810             return null;
811         }
812     }
813     setDepth(firstDepth);
814     type = (this.otherBindings[otherBindingsLength - 1]).type;
815     // perform capture conversion if read access
816
return (type != null && (this.bits & ASTNode.IsStrictlyAssigned) == 0)
817             ? type.capture(scope, this.sourceEnd)
818             : type;
819 }
820
821 public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
822     if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
823     //If inlinable field, forget the access emulation, the code gen will directly target it
824
if (((this.bits & ASTNode.DepthMASK) == 0) || (this.constant != Constant.NotAConstant)) {
825         return;
826     }
827     if ((this.bits & ASTNode.RestrictiveFlagMASK) == Binding.LOCAL) {
828         currentScope.emulateOuterAccess((LocalVariableBinding) this.binding);
829     }
830     }
831 }
832
833 /**
834  * index is <0 to denote write access emulation
835  */

836 public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FieldBinding fieldBinding, TypeBinding lastReceiverType, int index, FlowInfo flowInfo) {
837     if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return;
838     // index == 0 denotes the first fieldBinding, index > 0 denotes one of the 'otherBindings', index < 0 denotes a write access (to last binding)
839
if (fieldBinding.constant() != Constant.NotAConstant)
840         return;
841
842     // if field from parameterized type got found, use the original field at codegen time
843
FieldBinding originalField = fieldBinding.original();
844     if (originalField != fieldBinding) {
845         setCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index, originalField);
846     }
847     
848     if (fieldBinding.isPrivate()) { // private access
849
FieldBinding someCodegenBinding = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index);
850         if (someCodegenBinding.declaringClass != currentScope.enclosingSourceType()) {
851             setSyntheticAccessor(fieldBinding, index,
852                     ((SourceTypeBinding) someCodegenBinding.declaringClass).addSyntheticMethod(someCodegenBinding, index >= 0 /*read-access?*/));
853             currentScope.problemReporter().needToEmulateFieldAccess(someCodegenBinding, this, index >= 0 /*read-access?*/);
854             return;
855         }
856     } else if (fieldBinding.isProtected()){
857         int depth = (index == 0 || (index < 0 && this.otherDepths == null))
858                 ? (this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT
859                  : this.otherDepths[index < 0 ? this.otherDepths.length-1 : index-1];
860         
861         // implicit protected access
862
if (depth > 0 && (fieldBinding.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage())) {
863             FieldBinding someCodegenBinding = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index);
864             setSyntheticAccessor(fieldBinding, index,
865                     ((SourceTypeBinding) currentScope.enclosingSourceType().enclosingTypeAt(depth)).addSyntheticMethod(someCodegenBinding, index >= 0 /*read-access?*/));
866             currentScope.problemReporter().needToEmulateFieldAccess(someCodegenBinding, this, index >= 0 /*read-access?*/);
867             return;
868         }
869     }
870     // if the binding declaring class is not visible, need special action
871
// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
872
// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
873
// and not from Object or implicit static field access.
874
if (fieldBinding.declaringClass != lastReceiverType
875             && !lastReceiverType.isArrayType()
876             && fieldBinding.declaringClass != null // array.length
877
&& fieldBinding.constant() == Constant.NotAConstant) {
878         CompilerOptions options = currentScope.compilerOptions();
879         if ((options.targetJDK >= ClassFileConstants.JDK1_2
880                 && (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(index <= 1 && this.indexOfFirstFieldBinding == 1 && fieldBinding.isStatic()))
881                 && fieldBinding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object fields
882
|| !fieldBinding.declaringClass.canBeSeenBy(currentScope)) {
883     
884             setCodegenBinding(
885                     index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index,
886                     currentScope.enclosingSourceType().getUpdatedFieldBinding(
887                             getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index),
888                             (ReferenceBinding)lastReceiverType.erasure()));
889         }
890     }
891 }
892
893 public int nullStatus(FlowInfo flowInfo) {
894     return FlowInfo.UNKNOWN;
895 }
896
897 public Constant optimizedBooleanConstant() {
898     switch (this.resolvedType.id) {
899         case T_boolean :
900         case T_JavaLangBoolean :
901             if (this.constant != Constant.NotAConstant) return this.constant;
902             switch (this.bits & ASTNode.RestrictiveFlagMASK) {
903                 case Binding.FIELD : // reading a field
904
if (this.otherBindings == null)
905                     return ((FieldBinding)this.binding).constant();
906                 // fall thru
907
case Binding.LOCAL : // reading a local variable
908
return this.otherBindings[this.otherBindings.length-1].constant();
909         }
910     }
911     return Constant.NotAConstant;
912 }
913
914 /**
915  * @see org.eclipse.jdt.internal.compiler.ast.Expression#postConversionType(Scope)
916  */

917 public TypeBinding postConversionType(Scope scope) {
918     TypeBinding convertedType = this.resolvedType;
919     TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length);
920     if (requiredGenericCast != null)
921         convertedType = requiredGenericCast;
922     int runtimeType = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4;
923     switch (runtimeType) {
924         case T_boolean :
925             convertedType = TypeBinding.BOOLEAN;
926             break;
927         case T_byte :
928             convertedType = TypeBinding.BYTE;
929             break;
930         case T_short :
931             convertedType = TypeBinding.SHORT;
932             break;
933         case T_char :
934             convertedType = TypeBinding.CHAR;
935             break;
936         case T_int :
937             convertedType = TypeBinding.INT;
938             break;
939         case T_float :
940             convertedType = TypeBinding.FLOAT;
941             break;
942         case T_long :
943             convertedType = TypeBinding.LONG;
944             break;
945         case T_double :
946             convertedType = TypeBinding.DOUBLE;
947             break;
948         default :
949     }
950     if ((this.implicitConversion & TypeIds.BOXING) != 0) {
951         convertedType = scope.environment().computeBoxingType(convertedType);
952     }
953     return convertedType;
954 }
955
956 public StringBuffer JavaDoc printExpression(int indent, StringBuffer JavaDoc output) {
957     for (int i = 0; i < this.tokens.length; i++) {
958         if (i > 0) output.append('.');
959         output.append(this.tokens[i]);
960     }
961     return output;
962 }
963     
964 /**
965  * Normal field binding did not work, try to bind to a field of the delegate receiver.
966  */

967 public TypeBinding reportError(BlockScope scope) {
968     if (this.binding instanceof ProblemFieldBinding) {
969         scope.problemReporter().invalidField(this, (FieldBinding) this.binding);
970     } else if (this.binding instanceof ProblemReferenceBinding) {
971         scope.problemReporter().invalidType(this, (TypeBinding) this.binding);
972     } else {
973         scope.problemReporter().unresolvableReference(this, this.binding);
974     }
975     return null;
976 }
977
978 public TypeBinding resolveType(BlockScope scope) {
979     // field and/or local are done before type lookups
980
// the only available value for the restrictiveFlag BEFORE
981
// the TC is Flag_Type Flag_LocalField and Flag_TypeLocalField
982
this.actualReceiverType = scope.enclosingReceiverType();
983     this.constant = Constant.NotAConstant;
984     if ((this.codegenBinding = this.binding = scope.getBinding(this.tokens, this.bits & ASTNode.RestrictiveFlagMASK, this, true /*resolve*/)).isValidBinding()) {
985         switch (this.bits & ASTNode.RestrictiveFlagMASK) {
986             case Binding.VARIABLE : //============only variable===========
987
case Binding.TYPE | Binding.VARIABLE :
988                 if (this.binding instanceof LocalVariableBinding) {
989                     if (!((LocalVariableBinding) this.binding).isFinal() && ((this.bits & ASTNode.DepthMASK) != 0))
990                         scope.problemReporter().cannotReferToNonFinalOuterLocal(
991                             (LocalVariableBinding) this.binding,
992                             this);
993                     this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits
994
this.bits |= Binding.LOCAL;
995                     return this.resolvedType = getOtherFieldBindings(scope);
996                 }
997                 if (this.binding instanceof FieldBinding) {
998                     FieldBinding fieldBinding = (FieldBinding) this.binding;
999                     MethodScope methodScope = scope.methodScope();
1000                    // check for forward references
1001
if (this.indexOfFirstFieldBinding == 1
1002                            && methodScope.enclosingSourceType() == fieldBinding.original().declaringClass
1003                            && methodScope.lastVisibleFieldID >= 0
1004                            && fieldBinding.id >= methodScope.lastVisibleFieldID
1005                            && (!fieldBinding.isStatic() || methodScope.isStatic)) {
1006                        scope.problemReporter().forwardReference(this, 0, methodScope.enclosingSourceType());
1007                    }
1008                    if (!fieldBinding.isStatic()
1009                            && this.indexOfFirstFieldBinding == 1
1010                            && scope.compilerOptions().getSeverity(CompilerOptions.UnqualifiedFieldAccess) != ProblemSeverities.Ignore) {
1011                        scope.problemReporter().unqualifiedFieldAccess(this, fieldBinding);
1012                    }
1013                    this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits
1014
this.bits |= Binding.FIELD;
1015                    
1016// // check for deprecated receiver type
1017
// // deprecation check for receiver type if not first token
1018
// if (indexOfFirstFieldBinding > 1) {
1019
// if (isTypeUseDeprecated(this.actualReceiverType, scope))
1020
// scope.problemReporter().deprecatedType(this.actualReceiverType, this);
1021
// }
1022

1023                    return this.resolvedType = getOtherFieldBindings(scope);
1024                }
1025                // thus it was a type
1026
this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits
1027
this.bits |= Binding.TYPE;
1028            case Binding.TYPE : //=============only type ==============
1029
TypeBinding type = (TypeBinding) this.binding;
1030// if (isTypeUseDeprecated(type, scope))
1031
// scope.problemReporter().deprecatedType(type, this);
1032
type = scope.environment().convertToRawType(type);
1033                return this.resolvedType = type;
1034        }
1035    }
1036    //========error cases===============
1037
return this.resolvedType = this.reportError(scope);
1038}
1039
1040// set the matching codegenBinding and generic cast
1041
protected void setCodegenBinding(int index, FieldBinding someCodegenBinding) {
1042    if (index == 0){
1043        this.codegenBinding = someCodegenBinding;
1044    } else {
1045        int length = this.otherBindings.length;
1046        if (this.otherCodegenBindings == this.otherBindings){
1047            System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[length], 0, length);
1048        }
1049        this.otherCodegenBindings[index-1] = someCodegenBinding;
1050    }
1051}
1052
1053public void setFieldIndex(int index) {
1054    this.indexOfFirstFieldBinding = index;
1055}
1056
1057// set the matching codegenBinding and generic cast
1058
protected void setGenericCast(int index, TypeBinding someGenericCast) {
1059    if (index == 0){
1060        this.genericCast = someGenericCast;
1061    } else {
1062        if (this.otherGenericCasts == null) {
1063            this.otherGenericCasts = new TypeBinding[this.otherBindings.length];
1064        }
1065        this.otherGenericCasts[index-1] = someGenericCast;
1066    }
1067}
1068
1069// set the matching synthetic accessor
1070
protected void setSyntheticAccessor(FieldBinding fieldBinding, int index, SyntheticMethodBinding syntheticAccessor) {
1071    if (index < 0) { // write-access ?
1072
this.syntheticWriteAccessor = syntheticAccessor;
1073    } else {
1074        if (this.syntheticReadAccessors == null) {
1075            this.syntheticReadAccessors = new SyntheticMethodBinding[this.otherBindings == null ? 1 : this.otherBindings.length + 1];
1076        }
1077        this.syntheticReadAccessors[index] = syntheticAccessor;
1078    }
1079}
1080
1081public void traverse(ASTVisitor visitor, BlockScope scope) {
1082    visitor.visit(this, scope);
1083    visitor.endVisit(this, scope);
1084}
1085
1086public void traverse(ASTVisitor visitor, ClassScope scope) {
1087    visitor.visit(this, scope);
1088    visitor.endVisit(this, scope);
1089}
1090
1091public String JavaDoc unboundReferenceErrorName() {
1092    return new String JavaDoc(this.tokens[0]);
1093}
1094}
1095
Popular Tags