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; }
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; } }