1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpeclipse.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
14 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
16 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
17 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
18 import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
19 import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
20 import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding;
21 import net.sourceforge.phpdt.internal.compiler.lookup.MethodScope;
22 import net.sourceforge.phpdt.internal.compiler.lookup.ProblemFieldBinding;
23 import net.sourceforge.phpdt.internal.compiler.lookup.ProblemReferenceBinding;
24 import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
25 import net.sourceforge.phpdt.internal.compiler.lookup.SourceTypeBinding;
26 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
27 import net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding;
29 public class SingleNameReference extends NameReference implements OperatorIds {
32 public MethodBinding[] syntheticAccessors; // [0]=read accessor [1]=write accessor
33 public static final int READ = 0;
34 public static final int WRITE = 1;
36 public SingleNameReference(char[] source, long pos) {
39 sourceStart = (int) (pos >>> 32);
40 sourceEnd = (int) pos;
42 public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound) {
44 // compound assignment extra work
45 if (isCompound) { // check the variable part is initialized if blank final
46 switch (bits & RestrictiveFlagMASK) {
47 case FIELD : // reading a field
48 FieldBinding fieldBinding;
49 if ((fieldBinding = (FieldBinding) binding).isBlankFinal()
50 && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
51 if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
52 currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
55 manageSyntheticReadAccessIfNecessary(currentScope);
57 case LOCAL : // reading a local variable
58 // check if assigning a final blank field
59 LocalVariableBinding localBinding;
60 if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) {
61 currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
62 // we could improve error msg here telling "cannot use compound assignment on final local variable"
64 if (flowInfo.isReachable()) {
65 localBinding.useFlag = LocalVariableBinding.USED;
66 } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) {
67 localBinding.useFlag = LocalVariableBinding.FAKE_USED;
71 if (assignment.expression != null) {
72 flowInfo = assignment.expression.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
74 switch (bits & RestrictiveFlagMASK) {
75 case FIELD : // assigning to a field
76 manageSyntheticWriteAccessIfNecessary(currentScope);
78 // check if assigning a final field
79 FieldBinding fieldBinding;
80 if ((fieldBinding = (FieldBinding) binding).isFinal()) {
81 // inside a context where allowed
82 if (!isCompound && fieldBinding.isBlankFinal() && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
83 if (flowInfo.isPotentiallyAssigned(fieldBinding)) {
84 currentScope.problemReporter().duplicateInitializationOfBlankFinalField(fieldBinding, this);
86 flowContext.recordSettingFinal(fieldBinding, this);
88 flowInfo.markAsDefinitelyAssigned(fieldBinding);
90 currentScope.problemReporter().cannotAssignToFinalField(fieldBinding, this);
94 case LOCAL : // assigning to a local variable
95 LocalVariableBinding localBinding = (LocalVariableBinding) binding;
96 if (!flowInfo.isDefinitelyAssigned(localBinding)){// for local variable debug attributes
97 bits |= FirstAssignmentToLocalMASK;
99 bits &= ~FirstAssignmentToLocalMASK;
101 if (localBinding.isFinal()) {
102 if ((bits & DepthMASK) == 0) {
103 if (isCompound || !localBinding.isBlankFinal()){
104 currentScope.problemReporter().cannotAssignToFinalLocal(localBinding, this);
105 } else if (flowInfo.isPotentiallyAssigned(localBinding)) {
106 currentScope.problemReporter().duplicateInitializationOfFinalLocal(localBinding, this);
108 flowContext.recordSettingFinal(localBinding, this);
111 currentScope.problemReporter().cannotAssignToFinalOuterLocal(localBinding, this);
114 flowInfo.markAsDefinitelyAssigned(localBinding);
116 manageEnclosingInstanceAccessIfNecessary(currentScope);
119 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
120 return analyseCode(currentScope, flowContext, flowInfo, true);
122 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) {
124 switch (bits & RestrictiveFlagMASK) {
125 case FIELD : // reading a field
127 manageSyntheticReadAccessIfNecessary(currentScope);
129 // check if reading a final blank field
130 FieldBinding fieldBinding;
131 if ((fieldBinding = (FieldBinding) binding).isBlankFinal()
132 && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
133 if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
134 currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
138 case LOCAL : // reading a local variable
139 LocalVariableBinding localBinding;
140 if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) {
141 currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
143 if (flowInfo.isReachable()) {
144 localBinding.useFlag = LocalVariableBinding.USED;
145 } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) {
146 localBinding.useFlag = LocalVariableBinding.FAKE_USED;
150 manageEnclosingInstanceAccessIfNecessary(currentScope);
154 public TypeBinding checkFieldAccess(BlockScope scope) {
156 FieldBinding fieldBinding = (FieldBinding) binding;
158 bits &= ~RestrictiveFlagMASK; // clear bits
160 if (!((FieldBinding) binding).isStatic()) {
161 // must check for the static status....
162 if (scope.methodScope().isStatic) {
163 scope.problemReporter().staticFieldAccessToNonStaticVariable(this, fieldBinding);
164 constant = NotAConstant;
165 return fieldBinding.type;
168 constant = FieldReference.getConstantFor(fieldBinding, this, true, scope);
170 if (isFieldUseDeprecated(fieldBinding, scope))
171 scope.problemReporter().deprecatedField(fieldBinding, this);
173 MethodScope ms = scope.methodScope();
174 if ((this.bits & IsStrictlyAssignedMASK) == 0
175 && ms.enclosingSourceType() == fieldBinding.declaringClass
176 && ms.fieldDeclarationIndex != MethodScope.NotInFieldDecl
177 && fieldBinding.id >= ms.fieldDeclarationIndex) {
178 //if the field is static and ms is not .... then it is valid
179 if (!fieldBinding.isStatic() || ms.isStatic)
180 scope.problemReporter().forwardReference(this, 0, scope.enclosingSourceType());
182 //====================================================
184 return fieldBinding.type;
187 //public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
189 // // optimizing assignment like: i = i + 1 or i = 1 + i
190 // if (assignment.expression.isCompactableOperation()) {
191 // BinaryExpression operation = (BinaryExpression) assignment.expression;
192 // SingleNameReference variableReference;
193 // if ((operation.left instanceof SingleNameReference) && ((variableReference = (SingleNameReference) operation.left).binding == binding)) {
194 // // i = i + value, then use the variable on the right hand side, since it has the correct implicit conversion
195 // variableReference.generateCompoundAssignment(currentScope, codeStream, syntheticAccessors == null ? null : syntheticAccessors[WRITE], operation.right, (operation.bits & OperatorMASK) >> OperatorSHIFT, operation.left.implicitConversion /*should be equivalent to no conversion*/, valueRequired);
198 // int operator = (operation.bits & OperatorMASK) >> OperatorSHIFT;
199 // if ((operation.right instanceof SingleNameReference)
200 // && ((operator == PLUS) || (operator == MULTIPLY)) // only commutative operations
201 // && ((variableReference = (SingleNameReference) operation.right).binding == binding)
202 // && (operation.left.constant != NotAConstant) // exclude non constant expressions, since could have side-effect
203 // && ((operation.left.implicitConversion >> 4) != T_String) // exclude string concatenation which would occur backwards
204 // && ((operation.right.implicitConversion >> 4) != T_String)) { // exclude string concatenation which would occur backwards
205 // // i = value + i, then use the variable on the right hand side, since it has the correct implicit conversion
206 // variableReference.generateCompoundAssignment(currentScope, codeStream, syntheticAccessors == null ? null : syntheticAccessors[WRITE], operation.left, operator, operation.right.implicitConversion /*should be equivalent to no conversion*/, valueRequired);
210 // switch (bits & RestrictiveFlagMASK) {
211 // case FIELD : // assigning to a field
212 // FieldBinding fieldBinding;
213 // if (!(fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) { // need a receiver?
214 // if ((bits & DepthMASK) != 0) {
215 // ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
216 // Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
217 // codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
219 // this.generateReceiver(codeStream);
222 // assignment.expression.generateCode(currentScope, codeStream, true);
223 // fieldStore(codeStream, fieldBinding, syntheticAccessors == null ? null : syntheticAccessors[WRITE], valueRequired);
224 // if (valueRequired) {
225 // codeStream.generateImplicitConversion(assignment.implicitConversion);
228 // case LOCAL : // assigning to a local variable
229 // LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
230 // if (localBinding.resolvedPosition != -1) {
231 // assignment.expression.generateCode(currentScope, codeStream, true);
233 // if (assignment.expression.constant != NotAConstant) {
234 // // assigning an unused local to a constant value = no actual assignment is necessary
235 // if (valueRequired) {
236 // codeStream.generateConstant(assignment.expression.constant, assignment.implicitConversion);
239 // assignment.expression.generateCode(currentScope, codeStream, true);
240 // /* Even though the value may not be required, we force it to be produced, and discard it later
241 // on if it was actually not necessary, so as to provide the same behavior as JDK1.2beta3. */
242 // if (valueRequired) {
243 // codeStream.generateImplicitConversion(assignment.implicitConversion); // implicit conversion
245 // if ((localBinding.type == LongBinding) || (localBinding.type == DoubleBinding)) {
246 // codeStream.pop2();
254 // // 26903, need extra cast to store null in array local var
255 // if (localBinding.type.isArrayType()
256 // && (assignment.expression.resolvedType == NullBinding // arrayLoc = null
257 // || ((assignment.expression instanceof CastExpression) // arrayLoc = (type[])null
258 // && (((CastExpression)assignment.expression).innermostCastedExpression().resolvedType == NullBinding)))){
259 // codeStream.checkcast(localBinding.type);
262 // // normal local assignment (since cannot store in outer local which are final locations)
263 // codeStream.store(localBinding, valueRequired);
264 // if ((bits & FirstAssignmentToLocalMASK) != 0) { // for local variable debug attributes
265 // localBinding.recordInitializationStartPC(codeStream.position);
267 // // implicit conversion
268 // if (valueRequired) {
269 // codeStream.generateImplicitConversion(assignment.implicitConversion);
273 //public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
274 // int pc = codeStream.position;
275 // if (constant != NotAConstant) {
276 // if (valueRequired) {
277 // codeStream.generateConstant(constant, implicitConversion);
280 // switch (bits & RestrictiveFlagMASK) {
281 // case FIELD : // reading a field
282 // FieldBinding fieldBinding;
283 // if (valueRequired) {
284 // if ((fieldBinding = (FieldBinding) this.codegenBinding).constant == NotAConstant) { // directly use inlined value for constant fields
286 // if (!(isStatic = fieldBinding.isStatic())) {
287 // if ((bits & DepthMASK) != 0) {
288 // ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
289 // Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
290 // codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
292 // generateReceiver(codeStream);
295 // // managing private access
296 // if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
298 // codeStream.getstatic(fieldBinding);
300 // codeStream.getfield(fieldBinding);
303 // codeStream.invokestatic(syntheticAccessors[READ]);
305 // codeStream.generateImplicitConversion(implicitConversion);
306 // } else { // directly use the inlined value
307 // codeStream.generateConstant(fieldBinding.constant, implicitConversion);
311 // case LOCAL : // reading a local
312 // LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
313 // if (valueRequired) {
315 // if ((bits & DepthMASK) != 0) {
316 // // outer local can be reached either through a synthetic arg or a synthetic field
317 // VariableBinding[] path = currentScope.getEmulationPath(localBinding);
318 // codeStream.generateOuterAccess(path, this, localBinding, currentScope);
320 // // regular local variable read
321 // codeStream.load(localBinding);
323 // codeStream.generateImplicitConversion(implicitConversion);
327 // codeStream.recordPositionsFrom(pc, this.sourceStart);
330 // * Regular API for compound assignment, relies on the fact that there is only one reference to the
331 // * variable, which carries both synthetic read/write accessors.
332 // * The APIs with an extra argument is used whenever there are two references to the same variable which
333 // * are optimized in one access: e.g "a = a + 1" optimized into "a++".
335 //public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
337 // this.generateCompoundAssignment(
340 // syntheticAccessors == null ? null : syntheticAccessors[WRITE],
343 // assignmentImplicitConversion,
347 // * The APIs with an extra argument is used whenever there are two references to the same variable which
348 // * are optimized in one access: e.g "a = a + 1" optimized into "a++".
350 //public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, MethodBinding writeAccessor, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
351 // switch (bits & RestrictiveFlagMASK) {
352 // case FIELD : // assigning to a field
353 // FieldBinding fieldBinding;
354 // if ((fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) {
355 // if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
356 // codeStream.getstatic(fieldBinding);
358 // codeStream.invokestatic(syntheticAccessors[READ]);
361 // if ((bits & DepthMASK) != 0) {
362 // ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
363 // Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
364 // codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
366 // codeStream.aload_0();
369 // if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
370 // codeStream.getfield(fieldBinding);
372 // codeStream.invokestatic(syntheticAccessors[READ]);
376 // case LOCAL : // assigning to a local variable (cannot assign to outer local)
377 // LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
378 // Constant assignConstant;
380 // // using incr bytecode if possible
381 // switch (localBinding.type.id) {
383 // codeStream.generateStringAppend(currentScope, this, expression);
384 // if (valueRequired) {
387 // codeStream.store(localBinding, false);
390 // if (((assignConstant = expression.constant) != NotAConstant)
391 // && (assignConstant.typeID() != T_float) // only for integral types
392 // && (assignConstant.typeID() != T_double)
393 // && ((increment = assignConstant.intValue()) == (short) increment)) { // 16 bits value
394 // switch (operator) {
396 // codeStream.iinc(localBinding.resolvedPosition, increment);
397 // if (valueRequired) {
398 // codeStream.load(localBinding);
402 // codeStream.iinc(localBinding.resolvedPosition, -increment);
403 // if (valueRequired) {
404 // codeStream.load(localBinding);
410 // codeStream.load(localBinding);
413 // // perform the actual compound operation
414 // int operationTypeID;
415 // if ((operationTypeID = implicitConversion >> 4) == T_String || operationTypeID == T_Object) {
416 // // we enter here if the single name reference is a field of type java.lang.String or if the type of the
417 // // operation is java.lang.Object
418 // // For example: o = o + ""; // where the compiled type of o is java.lang.Object.
419 // codeStream.generateStringAppend(currentScope, null, expression);
421 // // promote the array reference to the suitable operation type
422 // codeStream.generateImplicitConversion(implicitConversion);
423 // // generate the increment value (will by itself be promoted to the operation value)
424 // if (expression == IntLiteral.One){ // prefix operation
425 // codeStream.generateConstant(expression.constant, implicitConversion);
427 // expression.generateCode(currentScope, codeStream, true);
429 // // perform the operation
430 // codeStream.sendOperator(operator, operationTypeID);
431 // // cast the value back to the array reference type
432 // codeStream.generateImplicitConversion(assignmentImplicitConversion);
434 // // store the result back into the variable
435 // switch (bits & RestrictiveFlagMASK) {
436 // case FIELD : // assigning to a field
437 // fieldStore(codeStream, (FieldBinding) this.codegenBinding, writeAccessor, valueRequired);
439 // case LOCAL : // assigning to a local variable
440 // LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
441 // if (valueRequired) {
442 // if ((localBinding.type == LongBinding) || (localBinding.type == DoubleBinding)) {
443 // codeStream.dup2();
448 // codeStream.store(localBinding, false);
451 //public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
452 // switch (bits & RestrictiveFlagMASK) {
453 // case FIELD : // assigning to a field
454 // FieldBinding fieldBinding;
455 // if ((fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) {
456 // if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
457 // codeStream.getstatic(fieldBinding);
459 // codeStream.invokestatic(syntheticAccessors[READ]);
462 // if ((bits & DepthMASK) != 0) {
463 // ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
464 // Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
465 // codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
467 // codeStream.aload_0();
470 // if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
471 // codeStream.getfield(fieldBinding);
473 // codeStream.invokestatic(syntheticAccessors[READ]);
476 // if (valueRequired) {
477 // if (fieldBinding.isStatic()) {
478 // if ((fieldBinding.type == LongBinding) || (fieldBinding.type == DoubleBinding)) {
479 // codeStream.dup2();
483 // } else { // Stack: [owner][old field value] ---> [old field value][owner][old field value]
484 // if ((fieldBinding.type == LongBinding) || (fieldBinding.type == DoubleBinding)) {
485 // codeStream.dup2_x1();
487 // codeStream.dup_x1();
491 // codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
492 // codeStream.sendOperator(postIncrement.operator, fieldBinding.type.id);
493 // codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
494 // fieldStore(codeStream, fieldBinding, syntheticAccessors == null ? null : syntheticAccessors[WRITE], false);
496 // case LOCAL : // assigning to a local variable
497 // LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
498 // // using incr bytecode if possible
499 // if (localBinding.type == IntBinding) {
500 // if (valueRequired) {
501 // codeStream.load(localBinding);
503 // if (postIncrement.operator == PLUS) {
504 // codeStream.iinc(localBinding.resolvedPosition, 1);
506 // codeStream.iinc(localBinding.resolvedPosition, -1);
509 // codeStream.load(localBinding);
510 // if (valueRequired){
511 // if ((localBinding.type == LongBinding) || (localBinding.type == DoubleBinding)) {
512 // codeStream.dup2();
517 // codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
518 // codeStream.sendOperator(postIncrement.operator, localBinding.type.id);
519 // codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
521 // codeStream.store(localBinding, false);
525 //public void generateReceiver(CodeStream codeStream) {
526 // codeStream.aload_0();
528 public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
530 //If inlinable field, forget the access emulation, the code gen will directly target it
531 if (((bits & DepthMASK) == 0) || (constant != NotAConstant)) return;
533 if ((bits & RestrictiveFlagMASK) == LOCAL) {
534 currentScope.emulateOuterAccess((LocalVariableBinding) binding);
537 public void manageSyntheticReadAccessIfNecessary(BlockScope currentScope) {
539 //If inlinable field, forget the access emulation, the code gen will directly target it
540 if (constant != NotAConstant)
543 if ((bits & FIELD) != 0) {
544 FieldBinding fieldBinding = (FieldBinding) binding;
545 if (((bits & DepthMASK) != 0)
546 && (fieldBinding.isPrivate() // private access
547 || (fieldBinding.isProtected() // implicit protected access
548 && fieldBinding.declaringClass.getPackage()
549 != currentScope.enclosingSourceType().getPackage()))) {
550 if (syntheticAccessors == null)
551 syntheticAccessors = new MethodBinding[2];
552 syntheticAccessors[READ] =
553 ((SourceTypeBinding)currentScope.enclosingSourceType().
554 enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT)).
555 addSyntheticMethod(fieldBinding, true);
556 currentScope.problemReporter().needToEmulateFieldReadAccess(fieldBinding, this);
559 // if the binding declaring class is not visible, need special action
560 // for runtime compatibility on 1.2 VMs : change the declaring class of the binding
561 // NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
562 // and not from Object or implicit static field access.
563 // if (fieldBinding.declaringClass != this.actualReceiverType
564 // && !this.actualReceiverType.isArrayType()
565 // && fieldBinding.declaringClass != null
566 // && fieldBinding.constant == NotAConstant
567 // && ((currentScope.environment().options.targetJDK >= CompilerOptions.JDK1_2
568 // && !fieldBinding.isStatic()
569 // && fieldBinding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
570 // || !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
571 // this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)this.actualReceiverType);
575 public void manageSyntheticWriteAccessIfNecessary(BlockScope currentScope) {
577 if ((bits & FIELD) != 0) {
578 FieldBinding fieldBinding = (FieldBinding) binding;
579 if (((bits & DepthMASK) != 0)
580 && (fieldBinding.isPrivate() // private access
581 || (fieldBinding.isProtected() // implicit protected access
582 && fieldBinding.declaringClass.getPackage()
583 != currentScope.enclosingSourceType().getPackage()))) {
584 if (syntheticAccessors == null)
585 syntheticAccessors = new MethodBinding[2];
586 syntheticAccessors[WRITE] =
587 ((SourceTypeBinding)currentScope.enclosingSourceType().
588 enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT)).
589 addSyntheticMethod(fieldBinding, false);
590 currentScope.problemReporter().needToEmulateFieldWriteAccess(fieldBinding, this);
593 // if the binding declaring class is not visible, need special action
594 // for runtime compatibility on 1.2 VMs : change the declaring class of the binding
595 // NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
596 // and not from Object or implicit static field access.
597 // if (fieldBinding.declaringClass != this.actualReceiverType
598 // && !this.actualReceiverType.isArrayType()
599 // && fieldBinding.declaringClass != null
600 // && fieldBinding.constant == NotAConstant
601 // && ((currentScope.environment().options.targetJDK >= CompilerOptions.JDK1_2
602 // && !fieldBinding.isStatic()
603 // && fieldBinding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
604 // || !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
605 // this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)this.actualReceiverType);
609 public TypeBinding reportError(BlockScope scope) {
610 //=====error cases=======
611 constant = Constant.NotAConstant;
612 if (binding instanceof ProblemFieldBinding) {
613 scope.problemReporter().invalidField(this, (FieldBinding) binding);
614 } else if (binding instanceof ProblemReferenceBinding) {
615 scope.problemReporter().invalidType(this, (TypeBinding) binding);
617 scope.problemReporter().unresolvableReference(this, binding);
621 public TypeBinding resolveType(BlockScope scope) {
622 // for code gen, harm the restrictiveFlag
624 this.actualReceiverType = this.receiverType = scope.enclosingSourceType();
626 if ((this.codegenBinding = this.binding = scope.getBinding(token, bits & RestrictiveFlagMASK, this)).isValidBinding()) {
627 switch (bits & RestrictiveFlagMASK) {
628 case VARIABLE : // =========only variable============
629 case VARIABLE | TYPE : //====both variable and type============
630 if (binding instanceof VariableBinding) {
631 VariableBinding variable = (VariableBinding) binding;
632 if (binding instanceof LocalVariableBinding) {
633 bits &= ~RestrictiveFlagMASK; // clear bits
635 if ((this.bits & IsStrictlyAssignedMASK) == 0) {
636 constant = variable.constant;
638 constant = NotAConstant;
640 if ((!variable.isFinal()) && ((bits & DepthMASK) != 0)) {
641 scope.problemReporter().cannotReferToNonFinalOuterLocal((LocalVariableBinding)variable, this);
643 return this.resolvedType = variable.type;
646 return this.resolvedType = checkFieldAccess(scope);
649 // thus it was a type
650 bits &= ~RestrictiveFlagMASK; // clear bits
652 case TYPE : //========only type==============
653 constant = Constant.NotAConstant;
655 if (isTypeUseDeprecated((TypeBinding) binding, scope))
656 scope.problemReporter().deprecatedType((TypeBinding) binding, this);
657 return this.resolvedType = (TypeBinding) binding;
662 return this.resolvedType = this.reportError(scope);
664 public StringBuffer printExpression(int indent, StringBuffer output){
666 return output.append(token);
668 public String toStringExpression(){
670 return new String(token);}
671 public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
672 visitor.visit(this, scope);
673 visitor.endVisit(this, scope);
675 public String unboundReferenceErrorName(){
677 return new String(token);}