<s> package org . eclipse . jdt . internal . compiler . ast ; import org . eclipse . jdt . internal . compiler . ASTVisitor ; import org . eclipse . jdt . internal . compiler . codegen . CodeStream ; import org . eclipse . jdt . internal . compiler . flow . FlowContext ; import org . eclipse . jdt . internal . compiler . flow . FlowInfo ; import org . eclipse . jdt . internal . compiler . impl . CompilerOptions ; import org . eclipse . jdt . internal . compiler . impl . Constant ; import org . eclipse . jdt . internal . compiler . lookup . ArrayBinding ; import org . eclipse . jdt . internal . compiler . lookup . Binding ; import org . eclipse . jdt . internal . compiler . lookup . BlockScope ; import org . eclipse . jdt . internal . compiler . lookup . InvocationSite ; import org . eclipse . jdt . internal . compiler . lookup . LocalVariableBinding ; import org . eclipse . jdt . internal . compiler . lookup . LookupEnvironment ; import org . eclipse . jdt . internal . compiler . lookup . MethodBinding ; import org . eclipse . jdt . internal . compiler . lookup . ParameterizedGenericMethodBinding ; import org . eclipse . jdt . internal . compiler . lookup . ParameterizedTypeBinding ; import org . eclipse . jdt . internal . compiler . lookup . PolymorphicMethodBinding ; import org . eclipse . jdt . internal . compiler . lookup . ReferenceBinding ; import org . eclipse . jdt . internal . compiler . lookup . Scope ; import org . eclipse . jdt . internal . compiler . lookup . TagBits ; import org . eclipse . jdt . internal . compiler . lookup . TypeBinding ; import org . eclipse . jdt . internal . compiler . lookup . TypeIds ; import org . eclipse . jdt . internal . compiler . problem . ProblemSeverities ; public class CastExpression extends Expression { public Expression expression ; public TypeReference type ; public TypeBinding expectedType ; public CastExpression ( Expression expression , TypeReference type ) { this . expression = expression ; this . type = type ; type . bits |= ASTNode . IgnoreRawTypeCheck ; } public FlowInfo analyseCode ( BlockScope currentScope , FlowContext flowContext , FlowInfo flowInfo ) { FlowInfo result = this . expression . analyseCode ( currentScope , flowContext , flowInfo ) . unconditionalInits ( ) ; if ( ( this . expression . implicitConversion & TypeIds . UNBOXING ) != 0 ) { this . expression . checkNPE ( currentScope , flowContext , flowInfo ) ; } return result ; } public static void checkNeedForAssignedCast ( BlockScope scope , TypeBinding expectedType , CastExpression rhs ) { if ( scope . compilerOptions ( ) . getSeverity ( CompilerOptions . UnnecessaryTypeCheck ) == ProblemSeverities . Ignore ) return ; TypeBinding castedExpressionType = rhs . expression . resolvedType ; if ( castedExpressionType == null || rhs . resolvedType . isBaseType ( ) ) return ; if ( castedExpressionType . isCompatibleWith ( expectedType ) ) { scope . problemReporter ( ) . unnecessaryCast ( rhs ) ; } } public static void checkNeedForCastCast ( BlockScope scope , CastExpression enclosingCast ) { if ( scope . compilerOptions ( ) . getSeverity ( CompilerOptions . UnnecessaryTypeCheck ) == ProblemSeverities . Ignore ) return ; CastExpression nestedCast = ( CastExpression ) enclosingCast . expression ; if ( ( nestedCast . bits & ASTNode . UnnecessaryCast ) == 0 ) return ; CastExpression alternateCast = new CastExpression ( null , enclosingCast . type ) ; alternateCast . resolvedType = enclosingCast . resolvedType ; if ( ! alternateCast . checkCastTypesCompatibility ( scope , enclosingCast . resolvedType , nestedCast . expression . resolvedType , null ) ) return ; scope . problemReporter ( ) . unnecessaryCast ( nestedCast ) ; } public static void checkNeedForEnclosingInstanceCast ( BlockScope scope , Expression enclosingInstance , TypeBinding enclosingInstanceType , TypeBinding memberType ) { if ( scope . compilerOptions ( ) . getSeverity ( CompilerOptions . UnnecessaryTypeCheck ) == ProblemSeverities . Ignore ) return ; TypeBinding castedExpressionType = ( ( CastExpression ) enclosingInstance ) . expression . resolvedType ; if ( castedExpressionType == null ) return ; if ( castedExpressionType == enclosingInstanceType ) { scope . problemReporter ( ) . unnecessaryCast ( ( CastExpression ) enclosingInstance ) ; } else if ( castedExpressionType == TypeBinding . NULL ) { return ; } else { TypeBinding alternateEnclosingInstanceType = castedExpressionType ; if ( castedExpressionType . isBaseType ( ) || castedExpressionType . isArrayType ( ) ) return ; if ( memberType == scope . getMemberType ( memberType . sourceName ( ) , ( ReferenceBinding ) alternateEnclosingInstanceType ) ) { scope . problemReporter ( ) . unnecessaryCast ( ( CastExpression ) enclosingInstance ) ; } } } public static void checkNeedForArgumentCast ( BlockScope scope , int operator , int operatorSignature , Expression expression , int expressionTypeId ) { if ( scope . compilerOptions ( ) . getSeverity ( CompilerOptions . UnnecessaryTypeCheck ) == ProblemSeverities . Ignore ) return ; if ( ( expression . bits & ASTNode . UnnecessaryCast ) == 0 && expression . resolvedType . isBaseType ( ) ) { return ; } else { TypeBinding alternateLeftType = ( ( CastExpression ) expression ) . expression . resolvedType ; if ( alternateLeftType == null ) return ; if ( alternateLeftType . id == expressionTypeId ) { scope . problemReporter ( ) . unnecessaryCast ( ( CastExpression ) expression ) ; return ; } } } public static void checkNeedForArgumentCasts ( BlockScope scope , Expression receiver , TypeBinding receiverType , MethodBinding binding , Expression [ ] arguments , TypeBinding [ ] argumentTypes , final InvocationSite invocationSite ) { if ( scope . compilerOptions ( ) . getSeverity ( CompilerOptions . UnnecessaryTypeCheck ) == ProblemSeverities . Ignore ) return ; int length = argumentTypes . length ; TypeBinding [ ] rawArgumentTypes = argumentTypes ; for ( int i = 0 ; i < length ; i ++ ) { Expression argument = arguments [ i ] ; if ( argument instanceof CastExpression ) { if ( ( argument . bits & ASTNode . UnnecessaryCast ) == 0 && argument . resolvedType . isBaseType ( ) ) { continue ; } TypeBinding castedExpressionType = ( ( CastExpression ) argument ) . expression . resolvedType ; if ( castedExpressionType == null ) return ; if ( castedExpressionType == argumentTypes [ i ] ) { scope . problemReporter ( ) . unnecessaryCast ( ( CastExpression ) argument ) ; } else if ( castedExpressionType == TypeBinding . NULL ) { continue ; } else if ( ( argument . implicitConversion & TypeIds . BOXING ) != 0 ) { continue ; } else { if ( rawArgumentTypes == argumentTypes ) { System . arraycopy ( rawArgumentTypes , 0 , rawArgumentTypes = new TypeBinding [ length ] , 0 , length ) ; } rawArgumentTypes [ i ] = castedExpressionType ; } } } if ( rawArgumentTypes != argumentTypes ) { checkAlternateBinding ( scope , receiver , receiverType , binding , arguments , argumentTypes , rawArgumentTypes , invocationSite ) ; } } public static void checkNeedForArgumentCasts ( BlockScope scope , int operator , int operatorSignature , Expression left , int leftTypeId , boolean leftIsCast , Expression right , int rightTypeId , boolean rightIsCast ) { if ( scope . compilerOptions ( ) . getSeverity ( CompilerOptions . UnnecessaryTypeCheck ) == ProblemSeverities . Ignore ) return ; int alternateLeftTypeId = leftTypeId ; if ( leftIsCast ) { if ( ( left . bits & ASTNode . UnnecessaryCast ) == 0 && left . resolvedType . isBaseType ( ) ) { leftIsCast = false ; } else { TypeBinding alternateLeftType = ( ( CastExpression ) left ) . expression . resolvedType ; if ( alternateLeftType == null ) return ; if ( ( alternateLeftTypeId = alternateLeftType . id ) == leftTypeId || scope . environment ( ) . computeBoxingType ( alternateLeftType ) . id == leftTypeId ) { scope . problemReporter ( ) . unnecessaryCast ( ( CastExpression ) left ) ; leftIsCast = false ; } else if ( alternateLeftTypeId == TypeIds . T_null ) { alternateLeftTypeId = leftTypeId ; leftIsCast = false ; } } } int alternateRightTypeId = rightTypeId ; if ( rightIsCast ) { if ( ( right . bits & ASTNode . UnnecessaryCast ) == 0 && right . resolvedType . isBaseType ( ) ) { rightIsCast = false ; } else { TypeBinding alternateRightType = ( ( CastExpression ) right ) . expression . resolvedType ; if ( alternateRightType == null ) return ; if ( ( alternateRightTypeId = alternateRightType . id ) == rightTypeId || scope . environment ( ) . computeBoxingType ( alternateRightType ) . id == rightTypeId ) { scope . problemReporter ( ) . unnecessaryCast ( ( CastExpression ) right ) ; rightIsCast = false ; } else if ( alternateRightTypeId == TypeIds . T_null ) { alternateRightTypeId = rightTypeId ; rightIsCast = false ; } } } if ( leftIsCast || rightIsCast ) { if ( alternateLeftTypeId > 15 || alternateRightTypeId > 15 ) { if ( alternateLeftTypeId == TypeIds . T_JavaLangString ) { alternateRightTypeId = TypeIds . T_JavaLangObject ; } else if ( alternateRightTypeId == TypeIds . T_JavaLangString ) { alternateLeftTypeId = TypeIds . T_JavaLangObject ; } else { return ; } } int alternateOperatorSignature = OperatorExpression . OperatorSignatures [ operator ] [ ( alternateLeftTypeId << 4 ) + alternateRightTypeId ] ; final int CompareMASK = ( 0xF << 16 ) + ( 0xF << 8 ) + 0xF ; if ( ( operatorSignature & CompareMASK ) == ( alternateOperatorSignature & CompareMASK ) ) { if ( leftIsCast ) scope . problemReporter ( ) . unnecessaryCast ( ( CastExpression ) left ) ; if ( rightIsCast ) scope . problemReporter ( ) . unnecessaryCast ( ( CastExpression ) right ) ; } } } private static void checkAlternateBinding ( BlockScope scope , Expression receiver , TypeBinding receiverType , MethodBinding binding , Expression [ ] arguments , TypeBinding [ ] originalArgumentTypes , TypeBinding [ ] alternateArgumentTypes , final InvocationSite invocationSite ) { InvocationSite fakeInvocationSite = new InvocationSite ( ) { public TypeBinding [ ] genericTypeArguments ( ) { return null ; } public boolean isSuperAccess ( ) { return invocationSite . isSuperAccess ( ) ; } public boolean isTypeAccess ( ) { return invocationSite . isTypeAccess ( ) ; } public void setActualReceiverType ( ReferenceBinding actualReceiverType ) { } public void setDepth ( int depth ) { } public void setFieldIndex ( int depth ) { } public int sourceStart ( ) { return 0 ; } public int sourceEnd ( ) { return 0 ; } public TypeBinding expectedType ( ) { return invocationSite . expectedType ( ) ; } } ; MethodBinding bindingIfNoCast ; if ( binding . isConstructor ( ) ) { bindingIfNoCast = scope . getConstructor ( ( ReferenceBinding ) receiverType , alternateArgumentTypes , fakeInvocationSite ) ; } else { bindingIfNoCast = receiver . isImplicitThis ( ) ? scope . getImplicitMethod ( binding . selector , alternateArgumentTypes , fakeInvocationSite ) : scope . getMethod ( receiverType , binding . selector , alternateArgumentTypes , fakeInvocationSite ) ; } if ( bindingIfNoCast == binding ) { int argumentLength = originalArgumentTypes . length ; if ( binding . isVarargs ( ) ) { int paramLength = binding . parameters . length ; if ( paramLength == argumentLength ) { int varargsIndex = paramLength - 1 ; ArrayBinding varargsType = ( ArrayBinding ) binding . parameters [ varargsIndex ] ; TypeBinding lastArgType = alternateArgumentTypes [ varargsIndex ] ; if ( varargsType . dimensions != lastArgType . dimensions ( ) ) { return ; } if ( lastArgType . isCompatibleWith ( varargsType . elementsType ( ) ) && lastArgType . isCompatibleWith ( varargsType ) ) { return ; } } } for ( int i = 0 ; i < argumentLength ; i ++ ) { if ( originalArgumentTypes [ i ] != alternateArgumentTypes [ i ] ) { scope . problemReporter ( ) . unnecessaryCast ( ( CastExpression ) arguments [ i ] ) ; } } } } public boolean checkUnsafeCast ( Scope scope , TypeBinding castType , TypeBinding expressionType , TypeBinding match , boolean isNarrowing ) { if ( match == castType ) { if ( ! isNarrowing && match == this . resolvedType . leafComponentType ( ) ) { tagAsUnnecessaryCast ( scope , castType ) ; } return true ; } if ( match != null ) { if ( isNarrowing ? match . isProvablyDistinct ( expressionType ) : castType . isProvablyDistinct ( match ) ) { return false ; } } switch ( castType . kind ( ) ) { case Binding . PARAMETERIZED_TYPE : if ( ! castType . isReifiable ( ) ) { if ( match == null ) { this . bits |= ASTNode . UnsafeCast ; return true ; } switch ( match . kind ( ) ) { case Binding . PARAMETERIZED_TYPE : if ( isNarrowing ) { if ( expressionType . isRawType ( ) || ! expressionType . isEquivalentTo ( match ) ) { this . bits |= ASTNode . UnsafeCast ; return true ; } ParameterizedTypeBinding paramCastType = ( ParameterizedTypeBinding ) castType ; ParameterizedTypeBinding paramMatch = ( ParameterizedTypeBinding ) match ; TypeBinding [ ] castArguments = paramCastType . arguments ; int length = castArguments == null ? 0 : castArguments . length ; if ( paramMatch . arguments == null || length > paramMatch . arguments . length ) { this . bits |= ASTNode . UnsafeCast ; } else if ( ( paramCastType . tagBits & ( TagBits . HasDirectWildcard | TagBits . HasTypeVariable ) ) != 0 ) { nextAlternateArgument : for ( int i = 0 ; i < length ; i ++ ) { switch ( castArguments [ i ] . kind ( ) ) { case Binding . WILDCARD_TYPE : case Binding . TYPE_PARAMETER : break ; default : continue nextAlternateArgument ; } TypeBinding [ ] alternateArguments ; System . arraycopy ( paramCastType . arguments , 0 , alternateArguments = new TypeBinding [ length ] , 0 , length ) ; alternateArguments [ i ] = scope . getJavaLangObject ( ) ; LookupEnvironment environment = scope . environment ( ) ; ParameterizedTypeBinding alternateCastType = environment . createParameterizedType ( ( ReferenceBinding ) castType . erasure ( ) , alternateArguments , castType . enclosingType ( ) ) ; if ( alternateCastType . findSuperTypeOriginatingFrom ( expressionType ) == match ) { this . bits |= ASTNode . UnsafeCast ; break ; } } } return true ; } else { if ( ! match . isEquivalentTo ( castType ) ) { this . bits |= ASTNode . UnsafeCast ; return true ; } } break ; case Binding . RAW_TYPE : this . bits |= ASTNode . UnsafeCast ; return true ; default : if ( isNarrowing ) { this . bits |= ASTNode . UnsafeCast ; return true ; } break ; } } break ; case Binding . ARRAY_TYPE : TypeBinding leafType = castType . leafComponentType ( ) ; if ( isNarrowing && ( ! leafType . isReifiable ( ) || leafType . isTypeVariable ( ) ) ) { this . bits |= ASTNode . UnsafeCast ; return true ; } break ; case Binding . TYPE_PARAMETER : this . bits |= ASTNode . UnsafeCast ; return true ; } if ( ! isNarrowing && match == this . resolvedType . leafComponentType ( ) ) { tagAsUnnecessaryCast ( scope , castType ) ; } return true ; } public void generateCode ( BlockScope currentScope , CodeStream codeStream , boolean valueRequired ) { int pc = codeStream . position ; boolean needRuntimeCheckcast = ( this . bits & ASTNode . GenerateCheckcast ) != 0 ; if ( this . constant != Constant . NotAConstant ) { if ( valueRequired || needRuntimeCheckcast ) { codeStream . generateConstant ( this . constant , this . implicitConversion ) ; if ( needRuntimeCheckcast ) { codeStream . checkcast ( this . resolvedType ) ; } if ( ! valueRequired ) { codeStream . pop ( ) ; } } codeStream . recordPositionsFrom ( pc , this . sourceStart ) ; return ; } this . expression . generateCode ( currentScope , codeStream , valueRequired || needRuntimeCheckcast ) ; if ( needRuntimeCheckcast && this . expression . postConversionType ( currentScope ) != this . resolvedType . erasure ( ) ) { codeStream . checkcast ( this . resolvedType ) ; } if ( valueRequired ) { codeStream . generateImplicitConversion ( this . implicitConversion ) ; } else if ( needRuntimeCheckcast ) { codeStream . pop ( ) ; } codeStream . recordPositionsFrom ( pc , this . sourceStart ) ; } public Expression innermostCastedExpression ( ) { Expression current = this . expression ; while ( current instanceof CastExpression ) { current = ( ( CastExpression ) current ) . expression ; } return current ; } public LocalVariableBinding localVariableBinding ( ) { return this . expression . localVariableBinding ( ) ; } public int nullStatus ( FlowInfo flowInfo ) { return this . expression . nullStatus ( flowInfo ) ; } public Constant optimizedBooleanConstant ( ) { switch ( this . resolvedType . id ) { case T_boolean : case T_JavaLangBoolean : return this . expression . optimizedBooleanConstant ( ) ; } return Constant . NotAConstant ; } public StringBuffer printExpression ( int indent , StringBuffer output ) { output . append ( '(' ) ; this . type . print ( 0 , output ) . append ( ") " ) ; return this . expression . printExpression ( 0 , output ) ; } public TypeBinding resolveType ( BlockScope scope ) { this . constant = Constant . NotAConstant ; this . implicitConversion = TypeIds . T_undefined ; boolean exprContainCast = false ; TypeBinding castType = this . resolvedType = this . type . resolveType ( scope ) ; if ( this . expression instanceof CastExpression ) { this . expression . bits |= ASTNode . DisableUnnecessaryCastCheck ; exprContainCast = true ; } TypeBinding expressionType = this . expression . resolveType ( scope ) ; if ( this . expression instanceof MessageSend ) { MessageSend messageSend = ( MessageSend ) this . expression ; MethodBinding methodBinding = messageSend . binding ; if ( methodBinding != null && methodBinding . isPolymorphic ( ) ) { messageSend . binding = scope . environment ( ) . updatePolymorphicMethodReturnType ( ( PolymorphicMethodBinding ) methodBinding , castType ) ; expressionType = castType ; } } 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 ) { if ( scope . compilerOptions ( ) . reportUnavoidableGenericTypeProblems || ! this . expression . forcedToBeRaw ( scope . referenceContext ( ) ) ) { 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 ) { if ( ! isIndirectlyUsed ( ) ) scope . problemReporter ( ) . unnecessaryCast ( this ) ; } } } else { if ( ( castType . tagBits & TagBits . HasMissingType ) == 0 ) { scope . problemReporter ( ) . typeCastError ( this , castType , expressionType ) ; } this . bits |= ASTNode . DisableUnnecessaryCastCheck ; } } this . resolvedType = castType . capture ( scope , this . sourceEnd ) ; if ( exprContainCast ) { checkNeedForCastCast ( scope , this ) ; } } return this . resolvedType ; } public void setExpectedType ( TypeBinding expectedType ) { this . expectedType = expectedType ; } private boolean isIndirectlyUsed ( ) { if ( this . expression instanceof MessageSend ) { MethodBinding method = ( ( MessageSend ) this . expression ) . binding ; if ( method instanceof ParameterizedGenericMethodBinding && ( ( ParameterizedGenericMethodBinding ) method ) . inferredReturnType ) { if ( this . expectedType == null ) return true ; if ( this . resolvedType != this . expectedType ) return true ; } } if ( this . expectedType != null && this . resolvedType . isBaseType ( ) && ! this . resolvedType . isCompatibleWith ( this . expectedType ) ) { return true ; } return false ; } public void tagAsNeedCheckCast ( ) { this . bits |= ASTNode . GenerateCheckcast ; } public void tagAsUnnecessaryCast ( Scope scope , TypeBinding castType ) { this . bits |= ASTNode . UnnecessaryCast ; } public void traverse ( ASTVisitor visitor , BlockScope blockScope ) { if ( visitor . visit ( this , blockScope ) ) { this . type . traverse ( visitor , blockScope ) ; this . expression . traverse ( visitor , blockScope ) ; } visitor . endVisit ( this , blockScope ) ; } } </s>