<s> package org . eclipse . jdt . internal . compiler . lookup ; public class ParameterizedGenericMethodBinding extends ParameterizedMethodBinding implements Substitution { public TypeBinding [ ] typeArguments ; private LookupEnvironment environment ; public boolean inferredReturnType ; public boolean wasInferred ; public boolean isRaw ; private MethodBinding tiebreakMethod ; public static MethodBinding computeCompatibleMethod ( MethodBinding originalMethod , TypeBinding [ ] arguments , Scope scope , InvocationSite invocationSite ) { ParameterizedGenericMethodBinding methodSubstitute ; TypeVariableBinding [ ] typeVariables = originalMethod . typeVariables ; TypeBinding [ ] substitutes = invocationSite . genericTypeArguments ( ) ; TypeBinding [ ] uncheckedArguments = null ; computeSubstitutes : { if ( substitutes != null ) { if ( substitutes . length != typeVariables . length ) { return new ProblemMethodBinding ( originalMethod , originalMethod . selector , substitutes , ProblemReasons . TypeParameterArityMismatch ) ; } methodSubstitute = scope . environment ( ) . createParameterizedGenericMethod ( originalMethod , substitutes ) ; break computeSubstitutes ; } TypeBinding [ ] parameters = originalMethod . parameters ; InferenceContext inferenceContext = new InferenceContext ( originalMethod ) ; methodSubstitute = inferFromArgumentTypes ( scope , originalMethod , arguments , parameters , inferenceContext ) ; if ( methodSubstitute == null ) return null ; if ( inferenceContext . hasUnresolvedTypeArgument ( ) ) { if ( inferenceContext . isUnchecked ) { int length = inferenceContext . substitutes . length ; System . arraycopy ( inferenceContext . substitutes , 0 , uncheckedArguments = new TypeBinding [ length ] , 0 , length ) ; } if ( methodSubstitute . returnType != TypeBinding . VOID ) { TypeBinding expectedType = invocationSite . expectedType ( ) ; if ( expectedType != null ) { inferenceContext . hasExplicitExpectedType = true ; } else { expectedType = scope . getJavaLangObject ( ) ; } inferenceContext . expectedType = expectedType ; } methodSubstitute = methodSubstitute . inferFromExpectedType ( scope , inferenceContext ) ; if ( methodSubstitute == null ) return null ; } } for ( int i = 0 , length = typeVariables . length ; i < length ; i ++ ) { TypeVariableBinding typeVariable = typeVariables [ i ] ; TypeBinding substitute = methodSubstitute . typeArguments [ i ] ; if ( uncheckedArguments != null && uncheckedArguments [ i ] == null ) continue ; switch ( typeVariable . boundCheck ( methodSubstitute , substitute ) ) { case TypeConstants . MISMATCH : int argLength = arguments . length ; TypeBinding [ ] augmentedArguments = new TypeBinding [ argLength + 2 ] ; System . arraycopy ( arguments , 0 , augmentedArguments , 0 , argLength ) ; augmentedArguments [ argLength ] = substitute ; augmentedArguments [ argLength + 1 ] = typeVariable ; return new ProblemMethodBinding ( methodSubstitute , originalMethod . selector , augmentedArguments , ProblemReasons . ParameterBoundMismatch ) ; case TypeConstants . UNCHECKED : methodSubstitute . tagBits |= TagBits . HasUncheckedTypeArgumentForBoundCheck ; break ; } } return methodSubstitute ; } private static ParameterizedGenericMethodBinding inferFromArgumentTypes ( Scope scope , MethodBinding originalMethod , TypeBinding [ ] arguments , TypeBinding [ ] parameters , InferenceContext inferenceContext ) { if ( originalMethod . isVarargs ( ) ) { int paramLength = parameters . length ; int minArgLength = paramLength - 1 ; int argLength = arguments . length ; for ( int i = 0 ; i < minArgLength ; i ++ ) { parameters [ i ] . collectSubstitutes ( scope , arguments [ i ] , inferenceContext , TypeConstants . CONSTRAINT_EXTENDS ) ; if ( inferenceContext . status == InferenceContext . FAILED ) return null ; } if ( minArgLength < argLength ) { TypeBinding varargType = parameters [ minArgLength ] ; TypeBinding lastArgument = arguments [ minArgLength ] ; checkVarargDimension : { if ( paramLength == argLength ) { if ( lastArgument == TypeBinding . NULL ) break checkVarargDimension ; switch ( lastArgument . dimensions ( ) ) { case 0 : break ; case 1 : if ( ! lastArgument . leafComponentType ( ) . isBaseType ( ) ) break checkVarargDimension ; break ; default : break checkVarargDimension ; } } varargType = ( ( ArrayBinding ) varargType ) . elementsType ( ) ; } for ( int i = minArgLength ; i < argLength ; i ++ ) { varargType . collectSubstitutes ( scope , arguments [ i ] , inferenceContext , TypeConstants . CONSTRAINT_EXTENDS ) ; if ( inferenceContext . status == InferenceContext . FAILED ) return null ; } } } else { int paramLength = parameters . length ; for ( int i = 0 ; i < paramLength ; i ++ ) { parameters [ i ] . collectSubstitutes ( scope , arguments [ i ] , inferenceContext , TypeConstants . CONSTRAINT_EXTENDS ) ; if ( inferenceContext . status == InferenceContext . FAILED ) return null ; } } TypeVariableBinding [ ] originalVariables = originalMethod . typeVariables ; if ( ! resolveSubstituteConstraints ( scope , originalVariables , inferenceContext , false ) ) return null ; TypeBinding [ ] inferredSustitutes = inferenceContext . substitutes ; TypeBinding [ ] actualSubstitutes = inferredSustitutes ; for ( int i = 0 , varLength = originalVariables . length ; i < varLength ; i ++ ) { if ( inferredSustitutes [ i ] == null ) { if ( actualSubstitutes == inferredSustitutes ) { System . arraycopy ( inferredSustitutes , 0 , actualSubstitutes = new TypeBinding [ varLength ] , 0 , i ) ; } actualSubstitutes [ i ] = originalVariables [ i ] ; } else if ( actualSubstitutes != inferredSustitutes ) { actualSubstitutes [ i ] = inferredSustitutes [ i ] ; } } ParameterizedGenericMethodBinding paramMethod = scope . environment ( ) . createParameterizedGenericMethod ( originalMethod , actualSubstitutes ) ; return paramMethod ; } private static boolean resolveSubstituteConstraints ( Scope scope , TypeVariableBinding [ ] typeVariables , InferenceContext inferenceContext , boolean considerEXTENDSConstraints ) { TypeBinding [ ] substitutes = inferenceContext . substitutes ; int varLength = typeVariables . length ; nextTypeParameter : for ( int i = 0 ; i < varLength ; i ++ ) { TypeVariableBinding current = typeVariables [ i ] ; TypeBinding substitute = substitutes [ i ] ; if ( substitute != null ) continue nextTypeParameter ; TypeBinding [ ] equalSubstitutes = inferenceContext . getSubstitutes ( current , TypeConstants . CONSTRAINT_EQUAL ) ; if ( equalSubstitutes != null ) { nextConstraint : for ( int j = 0 , equalLength = equalSubstitutes . length ; j < equalLength ; j ++ ) { TypeBinding equalSubstitute = equalSubstitutes [ j ] ; if ( equalSubstitute == null ) continue nextConstraint ; if ( equalSubstitute == current ) { for ( int k = j + 1 ; k < equalLength ; k ++ ) { equalSubstitute = equalSubstitutes [ k ] ; if ( equalSubstitute != current && equalSubstitute != null ) { substitutes [ i ] = equalSubstitute ; continue nextTypeParameter ; } } substitutes [ i ] = current ; continue nextTypeParameter ; } substitutes [ i ] = equalSubstitute ; continue nextTypeParameter ; } } } if ( inferenceContext . hasUnresolvedTypeArgument ( ) ) { nextTypeParameter : for ( int i = 0 ; i < varLength ; i ++ ) { TypeVariableBinding current = typeVariables [ i ] ; TypeBinding substitute = substitutes [ i ] ; if ( substitute != null ) continue nextTypeParameter ; TypeBinding [ ] bounds = inferenceContext . getSubstitutes ( current , TypeConstants . CONSTRAINT_SUPER ) ; if ( bounds == null ) continue nextTypeParameter ; TypeBinding mostSpecificSubstitute = scope . lowerUpperBound ( bounds ) ; if ( mostSpecificSubstitute == null ) { return false ; } if ( mostSpecificSubstitute != TypeBinding . VOID ) { substitutes [ i ] = mostSpecificSubstitute ; } } } if ( considerEXTENDSConstraints && inferenceContext . hasUnresolvedTypeArgument ( ) ) { nextTypeParameter : for ( int i = 0 ; i < varLength ; i ++ ) { TypeVariableBinding current = typeVariables [ i ] ; TypeBinding substitute = substitutes [ i ] ; if ( substitute != null ) continue nextTypeParameter ; TypeBinding [ ] bounds = inferenceContext . getSubstitutes ( current , TypeConstants . CONSTRAINT_EXTENDS ) ; if ( bounds == null ) continue nextTypeParameter ; TypeBinding [ ] glb = Scope . greaterLowerBound ( bounds ) ; TypeBinding mostSpecificSubstitute = null ; if ( glb != null ) mostSpecificSubstitute = glb [ 0 ] ; if ( mostSpecificSubstitute != null ) { substitutes [ i ] = mostSpecificSubstitute ; } } } return true ; } public ParameterizedGenericMethodBinding ( MethodBinding originalMethod , RawTypeBinding rawType , LookupEnvironment environment ) { TypeVariableBinding [ ] originalVariables = originalMethod . typeVariables ; int length = originalVariables . length ; TypeBinding [ ] rawArguments = new TypeBinding [ length ] ; for ( int i = 0 ; i < length ; i ++ ) { rawArguments [ i ] = environment . convertToRawType ( originalVariables [ i ] . erasure ( ) , false ) ; } this . isRaw = true ; this . tagBits = originalMethod . tagBits ; this . environment = environment ; this . modifiers = originalMethod . modifiers ; this . selector = originalMethod . selector ; this . declaringClass = rawType == null ? originalMethod . declaringClass : rawType ; this . typeVariables = Binding . NO_TYPE_VARIABLES ; this . typeArguments = rawArguments ; this . originalMethod = originalMethod ; boolean ignoreRawTypeSubstitution = rawType == null || originalMethod . isStatic ( ) ; this . parameters = Scope . substitute ( this , ignoreRawTypeSubstitution ? originalMethod . parameters : Scope . substitute ( rawType , originalMethod . parameters ) ) ; this . thrownExceptions = Scope . substitute ( this , ignoreRawTypeSubstitution ? originalMethod . thrownExceptions : Scope . substitute ( rawType , originalMethod . thrownExceptions ) ) ; if ( this . thrownExceptions == null ) this . thrownExceptions = Binding . NO_EXCEPTIONS ; this . returnType = Scope . substitute ( this , ignoreRawTypeSubstitution ? originalMethod . returnType : Scope . substitute ( rawType , originalMethod . returnType ) ) ; this . wasInferred = false ; } public ParameterizedGenericMethodBinding ( MethodBinding originalMethod , TypeBinding [ ] typeArguments , LookupEnvironment environment ) { this . environment = environment ; this . modifiers = originalMethod . modifiers ; this . selector = originalMethod . selector ; this . declaringClass = originalMethod . declaringClass ; this . typeVariables = Binding . NO_TYPE_VARIABLES ; this . typeArguments = typeArguments ; this . isRaw = false ; this . tagBits = originalMethod . tagBits ; this . originalMethod = originalMethod ; this . parameters = Scope . substitute ( this , originalMethod . parameters ) ; this . returnType = Scope . substitute ( this , originalMethod . returnType ) ; this . thrownExceptions = Scope . substitute ( this , originalMethod . thrownExceptions ) ; if ( this . thrownExceptions == null ) this . thrownExceptions = Binding . NO_EXCEPTIONS ; checkMissingType : { if ( ( this . tagBits & TagBits . HasMissingType ) != 0 ) break checkMissingType ; if ( ( this . returnType . tagBits & TagBits . HasMissingType ) != 0 ) { this . tagBits |= TagBits . HasMissingType ; break checkMissingType ; } for ( int i = 0 , max = this . parameters . length ; i < max ; i ++ ) { if ( ( this . parameters [ i ] . tagBits & TagBits . HasMissingType ) != 0 ) { this . tagBits |= TagBits . HasMissingType ; break checkMissingType ; } } for ( int i = 0 , max = this . thrownExceptions . length ; i < max ; i ++ ) { if ( ( this . thrownExceptions [ i ] . tagBits & TagBits . HasMissingType ) != 0 ) { this . tagBits |= TagBits . HasMissingType ; break checkMissingType ; } } } this . wasInferred = true ; } public char [ ] computeUniqueKey ( boolean isLeaf ) { StringBuffer buffer = new StringBuffer ( ) ; buffer . append ( this . originalMethod . computeUniqueKey ( false ) ) ; buffer . append ( '%' ) ; buffer . append ( '<' ) ; if ( ! this . isRaw ) { int length = this . typeArguments . length ; for ( int i = 0 ; i < length ; i ++ ) { TypeBinding typeArgument = this . typeArguments [ i ] ; buffer . append ( typeArgument . computeUniqueKey ( false ) ) ; } } buffer . append ( '>' ) ; int resultLength = buffer . length ( ) ; char [ ] result = new char [ resultLength ] ; buffer . getChars ( 0 , resultLength , result , 0 ) ; return result ; } public LookupEnvironment environment ( ) { return this . environment ; } public boolean hasSubstitutedParameters ( ) { if ( this . wasInferred ) return this . originalMethod . hasSubstitutedParameters ( ) ; return super . hasSubstitutedParameters ( ) ; } public boolean hasSubstitutedReturnType ( ) { if ( this . inferredReturnType ) return this . originalMethod . hasSubstitutedReturnType ( ) ; return super . hasSubstitutedReturnType ( ) ; } private ParameterizedGenericMethodBinding inferFromExpectedType ( Scope scope , InferenceContext inferenceContext ) { TypeVariableBinding [ ] originalVariables = this . originalMethod . typeVariables ; int varLength = originalVariables . length ; if ( inferenceContext . expectedType != null ) { this . returnType . collectSubstitutes ( scope , inferenceContext . expectedType , inferenceContext , TypeConstants . CONSTRAINT_SUPER ) ; if ( inferenceContext . status == InferenceContext . FAILED ) return null ; } for ( int i = 0 ; i < varLength ; i ++ ) { TypeVariableBinding originalVariable = originalVariables [ i ] ; TypeBinding argument = this . typeArguments [ i ] ; boolean argAlreadyInferred = argument != originalVariable ; if ( originalVariable . firstBound == originalVariable . superclass ) { TypeBinding substitutedBound = Scope . substitute ( this , originalVariable . superclass ) ; argument . collectSubstitutes ( scope , substitutedBound , inferenceContext , TypeConstants . CONSTRAINT_SUPER ) ; if ( inferenceContext . status == InferenceContext . FAILED ) return null ; if ( argAlreadyInferred ) { substitutedBound . collectSubstitutes ( scope , argument , inferenceContext , TypeConstants . CONSTRAINT_EXTENDS ) ; if ( inferenceContext . status == InferenceContext . FAILED ) return null ; } } for ( int j = 0 , max = originalVariable . superInterfaces . length ; j < max ; j ++ ) { TypeBinding substitutedBound = Scope . substitute ( this , originalVariable . superInterfaces [ j ] ) ; argument . collectSubstitutes ( scope , substitutedBound , inferenceContext , TypeConstants . CONSTRAINT_SUPER ) ; if ( inferenceContext . status == InferenceContext . FAILED ) return null ; if ( argAlreadyInferred ) { substitutedBound . collectSubstitutes ( scope , argument , inferenceContext , TypeConstants . CONSTRAINT_EXTENDS ) ; if ( inferenceContext . status == InferenceContext . FAILED ) return null ; } } } if ( ! resolveSubstituteConstraints ( scope , originalVariables , inferenceContext , true ) ) return null ; for ( int i = 0 ; i < varLength ; i ++ ) { TypeBinding substitute = inferenceContext . substitutes [ i ] ; if ( substitute != null ) { this . typeArguments [ i ] = inferenceContext . substitutes [ i ] ; } else { this . typeArguments [ i ] = originalVariables [ i ] . upperBound ( ) ; } } this . typeArguments = Scope . substitute ( this , this . typeArguments ) ; TypeBinding oldReturnType = this . returnType ; this . returnType = Scope . substitute ( this , this . returnType ) ; this . inferredReturnType = inferenceContext . hasExplicitExpectedType && this . returnType != oldReturnType ; this . parameters = Scope . substitute ( this , this . parameters ) ; this . thrownExceptions = Scope . substitute ( this , this . thrownExceptions ) ; if ( this . thrownExceptions == null ) this . thrownExceptions = Binding . NO_EXCEPTIONS ; checkMissingType : { if ( ( this . tagBits & TagBits . HasMissingType ) != 0 ) break checkMissingType ; if ( ( this . returnType . tagBits & TagBits . HasMissingType ) != 0 ) { this . tagBits |= TagBits . HasMissingType ; break checkMissingType ; } for ( int i = 0 , max = this . parameters . length ; i < max ; i ++ ) { if ( ( this . parameters [ i ] . tagBits & TagBits . HasMissingType ) != 0 ) { this . tagBits |= TagBits . HasMissingType ; break checkMissingType ; } } for ( int i = 0 , max = this . thrownExceptions . length ; i < max ; i ++ ) { if ( ( this . thrownExceptions [ i ] . tagBits & TagBits . HasMissingType ) != 0 ) { this . tagBits |= TagBits . HasMissingType ; break checkMissingType ; } } } return this ; } public boolean isRawSubstitution ( ) { return this . isRaw ; } public TypeBinding substitute ( TypeVariableBinding originalVariable ) { TypeVariableBinding [ ] variables = this . originalMethod . typeVariables ; int length = variables . length ; if ( originalVariable . rank < length && variables [ originalVariable . rank ] == originalVariable ) { return this . typeArguments [ originalVariable . rank ] ; } return originalVariable ; } public MethodBinding tiebreakMethod ( ) { if ( this . tiebreakMethod == null ) this . tiebreakMethod = this . originalMethod . asRawMethod ( this . environment ) ; return this . tiebreakMethod ; } } </s>