<s> package org . eclipse . jdt . internal . compiler . ast ; import org . eclipse . jdt . internal . compiler . ASTVisitor ; import org . eclipse . jdt . internal . compiler . classfmt . ClassFileConstants ; import org . eclipse . jdt . internal . compiler . codegen . * ; import org . eclipse . jdt . internal . compiler . flow . * ; import org . eclipse . jdt . internal . compiler . impl . Constant ; import org . eclipse . jdt . internal . compiler . lookup . * ; public class CompoundAssignment extends Assignment implements OperatorIds { public int operator ; public int preAssignImplicitConversion ; public CompoundAssignment ( Expression lhs , Expression expression , int operator , int sourceEnd ) { super ( lhs , expression , sourceEnd ) ; lhs . bits &= ~ IsStrictlyAssigned ; lhs . bits |= IsCompoundAssigned ; this . operator = operator ; } public FlowInfo analyseCode ( BlockScope currentScope , FlowContext flowContext , FlowInfo flowInfo ) { if ( this . resolvedType . id != T_JavaLangString ) { this . lhs . checkNPE ( currentScope , flowContext , flowInfo ) ; } flowInfo = ( ( Reference ) this . lhs ) . analyseAssignment ( currentScope , flowContext , flowInfo , this , true ) . unconditionalInits ( ) ; if ( this . resolvedType . id == T_JavaLangString ) { LocalVariableBinding local = this . lhs . localVariableBinding ( ) ; if ( local != null ) { flowInfo . markAsDefinitelyNonNull ( local ) ; if ( flowContext . initsOnFinally != null ) flowContext . initsOnFinally . markAsDefinitelyNonNull ( local ) ; } } return flowInfo ; } public boolean checkCastCompatibility ( ) { return true ; } public void generateCode ( BlockScope currentScope , CodeStream codeStream , boolean valueRequired ) { int pc = codeStream . position ; ( ( Reference ) this . lhs ) . generateCompoundAssignment ( currentScope , codeStream , this . expression , this . operator , this . preAssignImplicitConversion , valueRequired ) ; if ( valueRequired ) { codeStream . generateImplicitConversion ( this . implicitConversion ) ; } codeStream . recordPositionsFrom ( pc , this . sourceStart ) ; } public int nullStatus ( FlowInfo flowInfo ) { return FlowInfo . NON_NULL ; } public String operatorToString ( ) { switch ( this . operator ) { case PLUS : return "+=" ; case MINUS : return "-=" ; case MULTIPLY : return "*=" ; case DIVIDE : return "/=" ; case AND : return "&=" ; case OR : return "|=" ; case XOR : return "^=" ; case REMAINDER : return "%=" ; case LEFT_SHIFT : return "<<=" ; case RIGHT_SHIFT : return ">>=" ; case UNSIGNED_RIGHT_SHIFT : return ">>>=" ; } return "" ; } public StringBuffer printExpressionNoParenthesis ( int indent , StringBuffer output ) { this . lhs . printExpression ( indent , output ) . append ( ' ' ) . append ( operatorToString ( ) ) . append ( ' ' ) ; return this . expression . printExpression ( 0 , output ) ; } public TypeBinding resolveType ( BlockScope scope ) { this . constant = Constant . NotAConstant ; if ( ! ( this . lhs instanceof Reference ) || this . lhs . isThis ( ) ) { scope . problemReporter ( ) . expressionShouldBeAVariable ( this . lhs ) ; return null ; } boolean expressionIsCast = this . expression instanceof CastExpression ; if ( expressionIsCast ) this . expression . bits |= ASTNode . DisableUnnecessaryCastCheck ; TypeBinding originalLhsType = this . lhs . resolveType ( scope ) ; TypeBinding originalExpressionType = this . expression . resolveType ( scope ) ; if ( originalLhsType == null || originalExpressionType == null ) return null ; LocalVariableBinding localVariableBinding = this . lhs . localVariableBinding ( ) ; if ( localVariableBinding != null ) { localVariableBinding . tagBits &= ~ TagBits . IsEffectivelyFinal ; } LookupEnvironment env = scope . environment ( ) ; TypeBinding lhsType = originalLhsType , expressionType = originalExpressionType ; boolean use15specifics = scope . compilerOptions ( ) . sourceLevel >= ClassFileConstants . JDK1_5 ; boolean unboxedLhs = false ; if ( use15specifics ) { if ( ! lhsType . isBaseType ( ) && expressionType . id != T_JavaLangString && expressionType . id != T_null ) { TypeBinding unboxedType = env . computeBoxingType ( lhsType ) ; if ( unboxedType != lhsType ) { lhsType = unboxedType ; unboxedLhs = true ; } } if ( ! expressionType . isBaseType ( ) && lhsType . id != T_JavaLangString && lhsType . id != T_null ) { expressionType = env . computeBoxingType ( expressionType ) ; } } if ( restrainUsageToNumericTypes ( ) && ! lhsType . isNumericType ( ) ) { scope . problemReporter ( ) . operatorOnlyValidOnNumericType ( this , lhsType , expressionType ) ; return null ; } int lhsID = lhsType . id ; int expressionID = expressionType . id ; if ( lhsID > 15 || expressionID > 15 ) { if ( lhsID != T_JavaLangString ) { scope . problemReporter ( ) . invalidOperator ( this , lhsType , expressionType ) ; return null ; } expressionID = T_JavaLangObject ; } int result = OperatorExpression . OperatorSignatures [ this . operator ] [ ( lhsID << 4 ) + expressionID ] ; if ( result == T_undefined ) { scope . problemReporter ( ) . invalidOperator ( this , lhsType , expressionType ) ; return null ; } if ( this . operator == PLUS ) { if ( lhsID == T_JavaLangObject && ( scope . compilerOptions ( ) . complianceLevel < ClassFileConstants . JDK1_7 ) ) { scope . problemReporter ( ) . invalidOperator ( this , lhsType , expressionType ) ; return null ; } else { if ( ( lhsType . isNumericType ( ) || lhsID == T_boolean ) && ! expressionType . isNumericType ( ) ) { scope . problemReporter ( ) . invalidOperator ( this , lhsType , expressionType ) ; return null ; } } } TypeBinding resultType = TypeBinding . wellKnownType ( scope , result & 0x0000F ) ; if ( checkCastCompatibility ( ) ) { if ( originalLhsType . id != T_JavaLangString && resultType . id != T_JavaLangString ) { if ( ! checkCastTypesCompatibility ( scope , originalLhsType , resultType , null ) ) { scope . problemReporter ( ) . invalidOperator ( this , originalLhsType , expressionType ) ; return null ; } } } this . lhs . computeConversion ( scope , TypeBinding . wellKnownType ( scope , ( result >>> 16 ) & 0x0000F ) , originalLhsType ) ; this . expression . computeConversion ( scope , TypeBinding . wellKnownType ( scope , ( result >>> 8 ) & 0x0000F ) , originalExpressionType ) ; this . preAssignImplicitConversion = ( unboxedLhs ? BOXING : 0 ) | ( lhsID << 4 ) | ( result & 0x0000F ) ; if ( unboxedLhs ) scope . problemReporter ( ) . autoboxing ( this , lhsType , originalLhsType ) ; if ( expressionIsCast ) CastExpression . checkNeedForArgumentCasts ( scope , this . operator , result , this . lhs , originalLhsType . id , false , this . expression , originalExpressionType . id , true ) ; return this . resolvedType = originalLhsType ; } public boolean restrainUsageToNumericTypes ( ) { return false ; } public void traverse ( ASTVisitor visitor , BlockScope scope ) { if ( visitor . visit ( this , scope ) ) { this . lhs . traverse ( visitor , scope ) ; this . expression . traverse ( visitor , scope ) ; } visitor . endVisit ( this , scope ) ; } } </s>