public TypeBinding resolveType(BlockScope scope) {
    // field and/or local are done before type lookups
    // the only available value for the restrictiveFlag BEFORE
    // the TC is Flag_Type Flag_LocalField and Flag_TypeLocalField
    this.actualReceiverType = scope.enclosingReceiverType();
    this.constant = Constant.NotAConstant;
    if ((
        /*this.codegenBinding =*/ this.binding =
            scope.getBinding(
                this.tokens, this.bits & ASTNode.RestrictiveFlagMASK, this, true /*resolve*/))
        .isValidBinding()) {
      switch (this.bits & ASTNode.RestrictiveFlagMASK) {
        case Binding.VARIABLE: // ============only variable===========
        case Binding.TYPE | Binding.VARIABLE:
          if (this.binding instanceof LocalVariableBinding) {
            this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits
            this.bits |= Binding.LOCAL;
            return this.resolvedType = getOtherFieldBindings(scope);
          }
          if (this.binding instanceof FieldBinding) {
            FieldBinding fieldBinding = (FieldBinding) this.binding;
            MethodScope methodScope = scope.methodScope();
            // check for forward references
            if (this.indexOfFirstFieldBinding == 1
                && methodScope.enclosingSourceType() == fieldBinding.original().declaringClass
                && methodScope.lastVisibleFieldID >= 0
                && fieldBinding.id >= methodScope.lastVisibleFieldID
                && (!fieldBinding.isStatic() || methodScope.isStatic)) {
              scope.problemReporter().forwardReference(this, 0, methodScope.enclosingSourceType());
            }
            this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits
            this.bits |= Binding.FIELD;

            //						// check for deprecated receiver type
            //						// deprecation check for receiver type if not first token
            //						if (indexOfFirstFieldBinding > 1) {
            //							if (isTypeUseDeprecated(this.actualReceiverType, scope))
            //								scope.problemReporter().deprecatedType(this.actualReceiverType, this);
            //						}

            return this.resolvedType = getOtherFieldBindings(scope);
          }
          // thus it was a type
          this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits
          this.bits |= Binding.TYPE;
        case Binding.TYPE: // =============only type ==============
          TypeBinding type = (TypeBinding) this.binding;
          //					if (isTypeUseDeprecated(type, scope))
          //						scope.problemReporter().deprecatedType(type, this);
          return this.resolvedType = type;
      }
    }
    // ========error cases===============
    return this.resolvedType = this.reportError(scope);
  }
 /** Check and/or redirect the field access to the delegate receiver if any */
 public TypeBinding checkFieldAccess(BlockScope scope) {
   FieldBinding fieldBinding = (FieldBinding) this.binding;
   MethodScope methodScope = scope.methodScope();
   // check for forward references
   if (this.indexOfFirstFieldBinding == 1
       && methodScope.enclosingSourceType() == fieldBinding.original().declaringClass
       && methodScope.lastVisibleFieldID >= 0
       && fieldBinding.id >= methodScope.lastVisibleFieldID
       && (!fieldBinding.isStatic() || methodScope.isStatic)) {
     scope.problemReporter().forwardReference(this, 0, methodScope.enclosingSourceType());
   }
   this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits
   this.bits |= Binding.FIELD;
   return getOtherFieldBindings(scope);
 }
  public void resolve(MethodScope initializationScope) {
    // the two <constant = Constant.NotAConstant> could be regrouped into
    // a single line but it is clearer to have two lines while the reason of their
    // existence is not at all the same. See comment for the second one.

    // --------------------------------------------------------
    if ((this.bits & ASTNode.HasBeenResolved) != 0) return;
    if (this.binding == null || !this.binding.isValidBinding()) return;

    this.bits |= ASTNode.HasBeenResolved;

    // check if field is hiding some variable - issue is that field binding already got inserted in
    // scope
    // thus must lookup separately in super type and outer context
    ClassScope classScope = initializationScope.enclosingClassScope();

    if (classScope != null) {
      checkHiding:
      {
        SourceTypeBinding declaringType = classScope.enclosingSourceType();
        checkHidingSuperField:
        {
          if (declaringType.superclass == null) break checkHidingSuperField;
          Binding existingVariable =
              classScope.findField(
                  declaringType.superclass, this.name, this, false /*do not resolve hidden field*/);
          if (existingVariable == null) break checkHidingSuperField; // keep checking outer scenario
          if (!existingVariable.isValidBinding())
            break checkHidingSuperField; // keep checking outer scenario
          if (existingVariable instanceof FieldBinding) {
            FieldBinding existingField = (FieldBinding) existingVariable;
            if (existingField.original() == this.binding)
              break checkHidingSuperField; // keep checking outer scenario
          }
          // collision with supertype field
          initializationScope.problemReporter().fieldHiding(this, existingVariable);
          break checkHiding; // already found a matching field
        }
        // only corner case is: lookup of outer field through static declaringType, which isn't
        // detected by #getBinding as lookup starts
        // from outer scope. Subsequent static contexts are detected for free.
        Scope outerScope = classScope.parent;
        if (outerScope.kind == Scope.COMPILATION_UNIT_SCOPE) break checkHiding;
        Binding existingVariable =
            outerScope.getBinding(
                this.name, Binding.VARIABLE, this, false /*do not resolve hidden field*/);
        if (existingVariable == null) break checkHiding;
        if (!existingVariable.isValidBinding()) break checkHiding;
        if (existingVariable == this.binding) break checkHiding;
        if (existingVariable instanceof FieldBinding) {
          FieldBinding existingField = (FieldBinding) existingVariable;
          if (existingField.original() == this.binding) break checkHiding;
          if (!existingField.isStatic() && declaringType.isStatic()) break checkHiding;
        }
        // collision with outer field or local variable
        initializationScope.problemReporter().fieldHiding(this, existingVariable);
      }
    }

    if (this.type != null) { // enum constants have no declared type
      this.type.resolvedType = this.binding.type; // update binding for type reference
    }

    FieldBinding previousField = initializationScope.initializedField;
    int previousFieldID = initializationScope.lastVisibleFieldID;
    try {
      initializationScope.initializedField = this.binding;
      initializationScope.lastVisibleFieldID = this.binding.id;

      //		resolveAnnotations(initializationScope, this.annotations, this.binding);
      // the resolution of the initialization hasn't been done
      if (this.initialization != null) {

        TypeBinding fieldType = this.binding.type;
        TypeBinding initializationType;
        this.initialization.setExpectedType(
            fieldType); // needed in case of generic method invocation
        if (this.initialization instanceof ArrayInitializer) {

          if ((initializationType =
                  this.initialization.resolveTypeExpecting(initializationScope, fieldType))
              != null) {
            ((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationType;
          }
        } else if ((initializationType = this.initialization.resolveType(initializationScope))
            != null) {

          if (fieldType
              != initializationType) // must call before computeConversion() and typeMismatchError()
          initializationScope
                .compilationUnitScope()
                .recordTypeConversion(fieldType, initializationType);
          if (this.initialization.isConstantValueOfTypeAssignableToType(
                  initializationType, fieldType)
              || (fieldType.isBaseType()
                  && BaseTypeBinding.isWidening(fieldType.id, initializationType.id))
              || initializationType.isCompatibleWith(fieldType)) {
          } else if (initializationScope.isBoxingCompatibleWith(initializationType, fieldType)
              || (initializationType.isBaseType() // narrowing then boxing ?
                  && initializationScope.compilerOptions().sourceLevel
                      >= ClassFileConstants.JDK1_5 // autoboxing
                  && !fieldType.isBaseType()
                  && initialization.isConstantValueOfTypeAssignableToType(
                      initializationType,
                      initializationScope.environment().computeBoxingType(fieldType)))) {
          } else {
            initializationScope
                .problemReporter()
                .typeMismatchError(initializationType, fieldType, this);
          }
        }
        // check for assignment with no effect
        if (this.binding == Assignment.getDirectBinding(this.initialization)) {
          initializationScope.problemReporter().assignmentHasNoEffect(this, this.name);
        }
      }
      // Resolve Javadoc comment if one is present
      if (this.javadoc != null) {
        /*
        if (classScope != null) {
        	this.javadoc.resolve(classScope);
        }
        */
        this.javadoc.resolve(initializationScope);
      } else if (this.binding.declaringClass != null
          && !this.binding.declaringClass.isLocalType()) {
        initializationScope
            .problemReporter()
            .javadocMissing(this.sourceStart, this.sourceEnd, this.binding.modifiers);
      }
    } finally {
      initializationScope.initializedField = previousField;
      initializationScope.lastVisibleFieldID = previousFieldID;
    }
  }
  public TypeBinding getOtherFieldBindings(BlockScope scope) {
    // At this point restrictiveFlag may ONLY have two potential value : FIELD LOCAL (i.e cast
    // <<(VariableBinding) binding>> is valid)
    int length = this.tokens.length;
    FieldBinding field;
    if ((this.bits & Binding.FIELD) != 0) {
      field = (FieldBinding) this.binding;
      if (!field.isStatic()) {
        // must check for the static status....
        if (this.indexOfFirstFieldBinding
                > 1 // accessing to a field using a type as "receiver" is allowed only with static
                    // field
            || scope.methodScope()
                .isStatic) { // the field is the first token of the qualified reference....
          scope.problemReporter().staticFieldAccessToNonStaticVariable(this, field);
          return null;
        }
      } else {
        // indirect static reference ?
        if (this.indexOfFirstFieldBinding > 1
            && field.declaringClass != this.actualReceiverType
            && field.declaringClass.canBeSeenBy(scope)) {
          scope.problemReporter().indirectAccessToStaticField(this, field);
        }
      }
      // only last field is actually a write access if any
      if (isFieldUseDeprecated(
          field,
          scope,
          (this.bits & ASTNode.IsStrictlyAssigned) != 0 && this.indexOfFirstFieldBinding == length))
        scope.problemReporter().deprecatedField(field, this);
    } else {
      field = null;
    }
    TypeBinding type = ((VariableBinding) this.binding).type;
    int index = this.indexOfFirstFieldBinding;
    if (index == length) { // 	restrictiveFlag == FIELD
      // perform capture conversion if read access
      return type;
    }
    // allocation of the fieldBindings array	and its respective constants
    int otherBindingsLength = length - index;
    this.otherCodegenBindings = this.otherBindings = new FieldBinding[otherBindingsLength];
    this.otherDepths = new int[otherBindingsLength];

    // save first depth, since will be updated by visibility checks of other bindings
    int firstDepth = (this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT;
    // iteration on each field
    while (index < length) {
      char[] token = this.tokens[index];
      if (type == null) return null; // could not resolve type prior to this point

      this.bits &= ~ASTNode.DepthMASK; // flush previous depth if any
      FieldBinding previousField = field;
      field = scope.getField(type, token, this);
      int place = index - this.indexOfFirstFieldBinding;
      this.otherBindings[place] = field;
      this.otherDepths[place] = (this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT;
      if (field.isValidBinding()) {
        // set generic cast of for previous field (if any)
        if (previousField != null) {
          TypeBinding fieldReceiverType = type;
          TypeBinding receiverErasure = type;
          if (receiverErasure instanceof ReferenceBinding) {
            if (receiverErasure.findSuperTypeWithSameErasure(field.declaringClass) == null) {
              fieldReceiverType =
                  field.declaringClass; // handle indirect inheritance thru variable secondary bound
            }
          }
          FieldBinding originalBinding = previousField.original();
        }
        // only last field is actually a write access if any
        if (isFieldUseDeprecated(
            field, scope, (this.bits & ASTNode.IsStrictlyAssigned) != 0 && index + 1 == length)) {
          scope.problemReporter().deprecatedField(field, this);
        }

        if (field.isStatic()) {
          // static field accessed through receiver? legal but unoptimal (optional warning)
          scope.problemReporter().nonStaticAccessToStaticField(this, field);
          // indirect static reference ?
          if (field.declaringClass != type) {
            scope.problemReporter().indirectAccessToStaticField(this, field);
          }
        }
        type = field.type;
        index++;
      } else {
        this.constant = Constant.NotAConstant; // don't fill other constants slots...
        scope.problemReporter().invalidField(this, field, index, type);
        setDepth(firstDepth);
        return null;
      }
    }
    setDepth(firstDepth);
    type = (this.otherBindings[otherBindingsLength - 1]).type;
    // perform capture conversion if read access
    return type;
  }