Пример #1
0
  public TypeBinding resolveType(BlockScope scope) {
    // due to syntax lhs may be only a NameReference, a FieldReference or an ArrayReference
    this.constant = Constant.NotAConstant;
    if (!(this.lhs instanceof Reference) || this.lhs.isThis()) {
      scope.problemReporter().expressionShouldBeAVariable(this.lhs);
      return null;
    }
    TypeBinding lhsType = lhs.resolveType(scope);
    this.expression.setExpectedType(lhsType); // needed in case of generic method invocation
    if (lhsType != null) {
      this.resolvedType = lhsType.capture(scope, this.sourceEnd);
    }
    TypeBinding rhsType = this.expression.resolveType(scope);
    if (lhsType == null || rhsType == null) {
      return null;
    }
    // check for assignment with no effect
    Binding left = getDirectBinding(this.lhs);
    if (left != null && left == getDirectBinding(this.expression)) {
      scope.problemReporter().assignmentHasNoEffect(this, left.shortReadableName());
    }

    // Compile-time conversion of base-types : implicit narrowing integer into byte/short/character
    // may require to widen the rhs expression at runtime
    if (lhsType != rhsType) { // must call before computeConversion() and typeMismatchError()
      scope.compilationUnitScope().recordTypeConversion(lhsType, rhsType);
    }
    if ((this.expression.isConstantValueOfTypeAssignableToType(rhsType, lhsType)
            || (lhsType.isBaseType() && BaseTypeBinding.isWidening(lhsType.id, rhsType.id)))
        || rhsType.isCompatibleWith(lhsType)) {
      this.expression.computeConversion(scope, lhsType, rhsType);
      checkAssignment(scope, lhsType, rhsType);
      if (this.expression instanceof CastExpression
          && (this.expression.bits & ASTNode.UnnecessaryCast) == 0) {
        CastExpression.checkNeedForAssignedCast(scope, lhsType, (CastExpression) this.expression);
      }
      return this.resolvedType;
    } else if (scope.isBoxingCompatibleWith(rhsType, lhsType)
        || (rhsType.isBaseType() // narrowing then boxing ?
            && scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5 // autoboxing
            && !lhsType.isBaseType()
            && this.expression.isConstantValueOfTypeAssignableToType(
                rhsType, scope.environment().computeBoxingType(lhsType)))) {
      this.expression.computeConversion(scope, lhsType, rhsType);
      if (this.expression instanceof CastExpression
          && (this.expression.bits & ASTNode.UnnecessaryCast) == 0) {
        CastExpression.checkNeedForAssignedCast(scope, lhsType, (CastExpression) this.expression);
      }
      return this.resolvedType;
    }
    scope.problemReporter().typeMismatchError(rhsType, lhsType, this.expression, this.lhs);
    return lhsType;
  }
Пример #2
0
  public TypeBinding resolveType(BlockScope scope) {
    // compute a new constant if the cast is effective

    // due to the fact an expression may start with ( and that a cast can also start with (
    // the field is an expression....it can be a TypeReference OR a NameReference Or
    // any kind of Expression <-- this last one is invalid.......

    this.constant = Constant.NotAConstant;
    this.implicitConversion = TypeIds.T_undefined;

    if ((this.type instanceof TypeReference)
        || (this.type instanceof NameReference)
            && ((this.type.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT)
                == 0) { // no extra parenthesis around type: ((A))exp

      boolean exprContainCast = false;

      TypeBinding castType = this.resolvedType = this.type.resolveType(scope);
      // expression.setExpectedType(this.resolvedType); // needed in case of generic method
      // invocation
      if (this.expression instanceof CastExpression) {
        this.expression.bits |= ASTNode.DisableUnnecessaryCastCheck;
        exprContainCast = true;
      }
      TypeBinding expressionType = this.expression.resolveType(scope);
      if (castType != null) {
        if (expressionType != null) {
          boolean isLegal =
              checkCastTypesCompatibility(scope, castType, expressionType, this.expression);
          if (isLegal) {
            this.expression.computeConversion(scope, castType, expressionType);
            if ((this.bits & ASTNode.UnsafeCast) != 0) { // unsafe cast
              scope.problemReporter().unsafeCast(this, scope);
            } else {
              if (castType.isRawType()
                  && scope.compilerOptions().getSeverity(CompilerOptions.RawTypeReference)
                      != ProblemSeverities.Ignore) {
                scope.problemReporter().rawTypeReference(this.type, castType);
              }
              if ((this.bits & (ASTNode.UnnecessaryCast | ASTNode.DisableUnnecessaryCastCheck))
                  == ASTNode.UnnecessaryCast) { // unnecessary cast
                if (!isIndirectlyUsed()) // used for generic type inference or boxing ?
                scope.problemReporter().unnecessaryCast(this);
              }
            }
          } else { // illegal cast
            if ((castType.tagBits & TagBits.HasMissingType)
                == 0) { // no complaint if secondary error
              scope.problemReporter().typeCastError(this, castType, expressionType);
            }
            this.bits |= ASTNode.DisableUnnecessaryCastCheck; // disable further secondary diagnosis
          }
        }
        this.resolvedType = castType.capture(scope, this.sourceEnd);
        if (exprContainCast) {
          checkNeedForCastCast(scope, this);
        }
      }
      return this.resolvedType;
    } else { // expression as a cast
      TypeBinding expressionType = this.expression.resolveType(scope);
      if (expressionType == null) return null;
      scope.problemReporter().invalidTypeReference(this.type);
      return null;
    }
  }