<s> package org . eclipse . jdt . internal . compiler . lookup ; import org . eclipse . jdt . core . compiler . CharOperation ; import org . eclipse . jdt . internal . compiler . ast . Wildcard ; import org . eclipse . jdt . internal . compiler . classfmt . ClassFileConstants ; public class TypeVariableBinding extends ReferenceBinding { public Binding declaringElement ; public int rank ; public TypeBinding firstBound ; public ReferenceBinding superclass ; public ReferenceBinding [ ] superInterfaces ; public char [ ] genericTypeSignature ; LookupEnvironment environment ; public TypeVariableBinding ( char [ ] sourceName , Binding declaringElement , int rank , LookupEnvironment environment ) { this . sourceName = sourceName ; this . declaringElement = declaringElement ; this . rank = rank ; this . modifiers = ClassFileConstants . AccPublic | ExtraCompilerModifiers . AccGenericSignature ; this . tagBits |= TagBits . HasTypeVariable ; this . environment = environment ; this . typeBits = TypeIds . BitUninitialized ; } public int boundCheck ( Substitution substitution , TypeBinding argumentType ) { if ( argumentType == TypeBinding . NULL || argumentType == this ) { return TypeConstants . OK ; } boolean hasSubstitution = substitution != null ; if ( ! ( argumentType instanceof ReferenceBinding || argumentType . isArrayType ( ) ) ) return TypeConstants . MISMATCH ; if ( this . superclass == null ) return TypeConstants . OK ; if ( argumentType . kind ( ) == Binding . WILDCARD_TYPE ) { WildcardBinding wildcard = ( WildcardBinding ) argumentType ; switch ( wildcard . boundKind ) { case Wildcard . EXTENDS : TypeBinding wildcardBound = wildcard . bound ; if ( wildcardBound == this ) return TypeConstants . OK ; boolean isArrayBound = wildcardBound . isArrayType ( ) ; if ( ! wildcardBound . isInterface ( ) ) { TypeBinding substitutedSuperType = hasSubstitution ? Scope . substitute ( substitution , this . superclass ) : this . superclass ; if ( substitutedSuperType . id != TypeIds . T_JavaLangObject ) { if ( isArrayBound ) { if ( ! wildcardBound . isCompatibleWith ( substitutedSuperType ) ) return TypeConstants . MISMATCH ; } else { TypeBinding match = wildcardBound . findSuperTypeOriginatingFrom ( substitutedSuperType ) ; if ( match != null ) { if ( substitutedSuperType . isProvablyDistinct ( match ) ) { return TypeConstants . MISMATCH ; } } else { match = substitutedSuperType . findSuperTypeOriginatingFrom ( wildcardBound ) ; if ( match != null ) { if ( match . isProvablyDistinct ( wildcardBound ) ) { return TypeConstants . MISMATCH ; } } else { if ( ! wildcardBound . isTypeVariable ( ) && ! substitutedSuperType . isTypeVariable ( ) ) { return TypeConstants . MISMATCH ; } } } } } } boolean mustImplement = isArrayBound || ( ( ReferenceBinding ) wildcardBound ) . isFinal ( ) ; for ( int i = 0 , length = this . superInterfaces . length ; i < length ; i ++ ) { TypeBinding substitutedSuperType = hasSubstitution ? Scope . substitute ( substitution , this . superInterfaces [ i ] ) : this . superInterfaces [ i ] ; if ( isArrayBound ) { if ( ! wildcardBound . isCompatibleWith ( substitutedSuperType ) ) return TypeConstants . MISMATCH ; } else { TypeBinding match = wildcardBound . findSuperTypeOriginatingFrom ( substitutedSuperType ) ; if ( match != null ) { if ( substitutedSuperType . isProvablyDistinct ( match ) ) { return TypeConstants . MISMATCH ; } } else if ( mustImplement ) { return TypeConstants . MISMATCH ; } } } break ; case Wildcard . SUPER : if ( wildcard . bound . isTypeVariable ( ) && ( ( TypeVariableBinding ) wildcard . bound ) . superclass . id == TypeIds . T_JavaLangObject ) break ; return boundCheck ( substitution , wildcard . bound ) ; case Wildcard . UNBOUND : break ; } return TypeConstants . OK ; } boolean unchecked = false ; if ( this . superclass . id != TypeIds . T_JavaLangObject ) { TypeBinding substitutedSuperType = hasSubstitution ? Scope . substitute ( substitution , this . superclass ) : this . superclass ; if ( substitutedSuperType != argumentType ) { if ( ! argumentType . isCompatibleWith ( substitutedSuperType ) ) { return TypeConstants . MISMATCH ; } TypeBinding match = argumentType . findSuperTypeOriginatingFrom ( substitutedSuperType ) ; if ( match != null ) { if ( match . isRawType ( ) && substitutedSuperType . isBoundParameterizedType ( ) ) unchecked = true ; } } } for ( int i = 0 , length = this . superInterfaces . length ; i < length ; i ++ ) { TypeBinding substitutedSuperType = hasSubstitution ? Scope . substitute ( substitution , this . superInterfaces [ i ] ) : this . superInterfaces [ i ] ; if ( substitutedSuperType != argumentType ) { if ( ! argumentType . isCompatibleWith ( substitutedSuperType ) ) { return TypeConstants . MISMATCH ; } TypeBinding match = argumentType . findSuperTypeOriginatingFrom ( substitutedSuperType ) ; if ( match != null ) { if ( match . isRawType ( ) && substitutedSuperType . isBoundParameterizedType ( ) ) unchecked = true ; } } } return unchecked ? TypeConstants . UNCHECKED : TypeConstants . OK ; } public int boundsCount ( ) { if ( this . firstBound == null ) { return 0 ; } else if ( this . firstBound == this . superclass ) { return this . superInterfaces . length + 1 ; } else { return this . superInterfaces . length ; } } public boolean canBeInstantiated ( ) { return false ; } public void collectSubstitutes ( Scope scope , TypeBinding actualType , InferenceContext inferenceContext , int constraint ) { if ( this . declaringElement != inferenceContext . genericMethod ) return ; switch ( actualType . kind ( ) ) { case Binding . BASE_TYPE : if ( actualType == TypeBinding . NULL ) return ; TypeBinding boxedType = scope . environment ( ) . computeBoxingType ( actualType ) ; if ( boxedType == actualType ) return ; actualType = boxedType ; break ; case Binding . WILDCARD_TYPE : return ; } int variableConstraint ; switch ( constraint ) { case TypeConstants . CONSTRAINT_EQUAL : variableConstraint = TypeConstants . CONSTRAINT_EQUAL ; break ; case TypeConstants . CONSTRAINT_EXTENDS : variableConstraint = TypeConstants . CONSTRAINT_SUPER ; break ; default : variableConstraint = TypeConstants . CONSTRAINT_EXTENDS ; break ; } inferenceContext . recordSubstitute ( this , actualType , variableConstraint ) ; } public char [ ] computeUniqueKey ( boolean isLeaf ) { StringBuffer buffer = new StringBuffer ( ) ; Binding declaring = this . declaringElement ; if ( ! isLeaf && declaring . kind ( ) == Binding . METHOD ) { MethodBinding methodBinding = ( MethodBinding ) declaring ; ReferenceBinding declaringClass = methodBinding . declaringClass ; buffer . append ( declaringClass . computeUniqueKey ( false ) ) ; buffer . append ( ':' ) ; MethodBinding [ ] methods = declaringClass . methods ( ) ; if ( methods != null ) for ( int i = 0 , length = methods . length ; i < length ; i ++ ) { MethodBinding binding = methods [ i ] ; if ( binding == methodBinding ) { buffer . append ( i ) ; break ; } } } else { buffer . append ( declaring . computeUniqueKey ( false ) ) ; buffer . append ( ':' ) ; } buffer . append ( genericTypeSignature ( ) ) ; int length = buffer . length ( ) ; char [ ] uniqueKey = new char [ length ] ; buffer . getChars ( 0 , length , uniqueKey , 0 ) ; return uniqueKey ; } public char [ ] constantPoolName ( ) { if ( this . firstBound != null ) { return this . firstBound . constantPoolName ( ) ; } return this . superclass . constantPoolName ( ) ; } public String debugName ( ) { return new String ( this . sourceName ) ; } public TypeBinding erasure ( ) { if ( this . firstBound != null ) { return this . firstBound . erasure ( ) ; } return this . superclass ; } public char [ ] genericSignature ( ) { StringBuffer sig = new StringBuffer ( 10 ) ; sig . append ( this . sourceName ) . append ( ':' ) ; int interfaceLength = this . superInterfaces == null ? 0 : this . superInterfaces . length ; if ( interfaceLength == 0 || this . firstBound == this . superclass ) { if ( this . superclass != null ) sig . append ( this . superclass . genericTypeSignature ( ) ) ; } for ( int i = 0 ; i < interfaceLength ; i ++ ) { sig . append ( ':' ) . append ( this . superInterfaces [ i ] . genericTypeSignature ( ) ) ; } int sigLength = sig . length ( ) ; char [ ] genericSignature = new char [ sigLength ] ; sig . getChars ( 0 , sigLength , genericSignature , 0 ) ; return genericSignature ; } public char [ ] genericTypeSignature ( ) { if ( this . genericTypeSignature != null ) return this . genericTypeSignature ; return this . genericTypeSignature = CharOperation . concat ( 'T' , this . sourceName , ';' ) ; } boolean hasOnlyRawBounds ( ) { if ( this . superclass != null && this . firstBound == this . superclass ) if ( ! this . superclass . isRawType ( ) ) return false ; if ( this . superInterfaces != null ) for ( int i = 0 , l = this . superInterfaces . length ; i < l ; i ++ ) if ( ! this . superInterfaces [ i ] . isRawType ( ) ) return false ; return true ; } public boolean hasTypeBit ( int bit ) { if ( this . typeBits == TypeIds . BitUninitialized ) { this . typeBits = 0 ; if ( this . superclass != null && this . superclass . hasTypeBit ( ~ TypeIds . BitUninitialized ) ) this . typeBits |= ( this . superclass . typeBits & TypeIds . InheritableBits ) ; if ( this . superInterfaces != null ) for ( int i = 0 , l = this . superInterfaces . length ; i < l ; i ++ ) if ( this . superInterfaces [ i ] . hasTypeBit ( ~ TypeIds . BitUninitialized ) ) this . typeBits |= ( this . superInterfaces [ i ] . typeBits & TypeIds . InheritableBits ) ; } return ( this . typeBits & bit ) != 0 ; } public boolean isErasureBoundTo ( TypeBinding type ) { if ( this . superclass . erasure ( ) == type ) return true ; for ( int i = 0 , length = this . superInterfaces . length ; i < length ; i ++ ) { if ( this . superInterfaces [ i ] . erasure ( ) == type ) return true ; } return false ; } public boolean isHierarchyConnected ( ) { return ( this . modifiers & ExtraCompilerModifiers . AccUnresolved ) == 0 ; } public boolean isInterchangeableWith ( TypeVariableBinding otherVariable , Substitution substitute ) { if ( this == otherVariable ) return true ; int length = this . superInterfaces . length ; if ( length != otherVariable . superInterfaces . length ) return false ; if ( this . superclass != Scope . substitute ( substitute , otherVariable . superclass ) ) return false ; next : for ( int i = 0 ; i < length ; i ++ ) { TypeBinding superType = Scope . substitute ( substitute , otherVariable . superInterfaces [ i ] ) ; for ( int j = 0 ; j < length ; j ++ ) if ( superType == this . superInterfaces [ j ] ) continue next ; return false ; } return true ; } public boolean isTypeVariable ( ) { return true ; } public int kind ( ) { return Binding . TYPE_PARAMETER ; } public TypeBinding [ ] otherUpperBounds ( ) { if ( this . firstBound == null ) return Binding . NO_TYPES ; if ( this . firstBound == this . superclass ) return this . superInterfaces ; int otherLength = this . superInterfaces . length - 1 ; if ( otherLength > 0 ) { TypeBinding [ ] otherBounds ; System . arraycopy ( this . superInterfaces , 1 , otherBounds = new TypeBinding [ otherLength ] , 0 , otherLength ) ; return otherBounds ; } return Binding . NO_TYPES ; } public char [ ] readableName ( ) { return this . sourceName ; } ReferenceBinding resolve ( ) { if ( ( this . modifiers & ExtraCompilerModifiers . AccUnresolved ) == 0 ) return this ; TypeBinding oldSuperclass = this . superclass , oldFirstInterface = null ; if ( this . superclass != null ) { ReferenceBinding resolveType = ( ReferenceBinding ) BinaryTypeBinding . resolveType ( this . superclass , this . environment , true ) ; this . tagBits |= resolveType . tagBits & TagBits . ContainsNestedTypeReferences ; this . superclass = resolveType ; } ReferenceBinding [ ] interfaces = this . superInterfaces ; int length ; if ( ( length = interfaces . length ) != 0 ) { oldFirstInterface = interfaces [ 0 ] ; for ( int i = length ; -- i >= 0 ; ) { ReferenceBinding resolveType = ( ReferenceBinding ) BinaryTypeBinding . resolveType ( interfaces [ i ] , this . environment , true ) ; this . tagBits |= resolveType . tagBits & TagBits . ContainsNestedTypeReferences ; interfaces [ i ] = resolveType ; } } if ( this . firstBound != null ) { if ( this . firstBound == oldSuperclass ) { this . firstBound = this . superclass ; } else if ( this . firstBound == oldFirstInterface ) { this . firstBound = interfaces [ 0 ] ; } } this . modifiers &= ~ ExtraCompilerModifiers . AccUnresolved ; return this ; } public char [ ] shortReadableName ( ) { return readableName ( ) ; } public ReferenceBinding superclass ( ) { return this . superclass ; } public ReferenceBinding [ ] superInterfaces ( ) { return this . superInterfaces ; } public String toString ( ) { StringBuffer buffer = new StringBuffer ( 10 ) ; buffer . append ( '<' ) . append ( this . sourceName ) ; if ( this . superclass != null && this . firstBound == this . superclass ) { buffer . append ( " extends " ) . append ( this . superclass . debugName ( ) ) ; } if ( this . superInterfaces != null && this . superInterfaces != Binding . NO_SUPERINTERFACES ) { if ( this . firstBound != this . superclass ) { buffer . append ( " extends " ) ; } for ( int i = 0 , length = this . superInterfaces . length ; i < length ; i ++ ) { if ( i > 0 || this . firstBound == this . superclass ) { buffer . append ( " & " ) ; } buffer . append ( this . superInterfaces [ i ] . debugName ( ) ) ; } } buffer . append ( '>' ) ; return buffer . toString ( ) ; } public TypeBinding upperBound ( ) { if ( this . firstBound != null ) { return this . firstBound ; } return this . superclass ; } } </s>