<s> package org . eclipse . jdt . internal . compiler . lookup ; import org . eclipse . jdt . internal . compiler . ast . ASTNode ; import org . eclipse . jdt . internal . compiler . ast . AbstractMethodDeclaration ; import org . eclipse . jdt . internal . compiler . ast . Argument ; import org . eclipse . jdt . internal . compiler . ast . MethodDeclaration ; import org . eclipse . jdt . internal . compiler . ast . TypeParameter ; import org . eclipse . jdt . internal . compiler . ast . TypeReference ; import org . eclipse . jdt . internal . compiler . classfmt . ClassFileConstants ; import org . eclipse . jdt . internal . compiler . impl . CompilerOptions ; import org . eclipse . jdt . internal . compiler . problem . ProblemSeverities ; import org . eclipse . jdt . internal . compiler . util . HashtableOfObject ; import org . eclipse . jdt . internal . compiler . util . SimpleSet ; class MethodVerifier15 extends MethodVerifier { MethodVerifier15 ( LookupEnvironment environment ) { super ( environment ) ; } boolean areMethodsCompatible ( MethodBinding one , MethodBinding two ) { one = one . original ( ) ; two = one . findOriginalInheritedMethod ( two ) ; if ( two == null ) return false ; return isParameterSubsignature ( one , two ) ; } boolean areParametersEqual ( MethodBinding one , MethodBinding two ) { TypeBinding [ ] oneArgs = one . parameters ; TypeBinding [ ] twoArgs = two . parameters ; if ( oneArgs == twoArgs ) return true ; int length = oneArgs . length ; if ( length != twoArgs . length ) return false ; int i ; foundRAW : for ( i = 0 ; i < length ; i ++ ) { if ( ! areTypesEqual ( oneArgs [ i ] , twoArgs [ i ] ) ) { if ( oneArgs [ i ] . leafComponentType ( ) . isRawType ( ) ) { if ( oneArgs [ i ] . dimensions ( ) == twoArgs [ i ] . dimensions ( ) && oneArgs [ i ] . leafComponentType ( ) . isEquivalentTo ( twoArgs [ i ] . leafComponentType ( ) ) ) { if ( one . typeVariables != Binding . NO_TYPE_VARIABLES ) return false ; for ( int j = 0 ; j < i ; j ++ ) if ( oneArgs [ j ] . leafComponentType ( ) . isParameterizedTypeWithActualArguments ( ) ) return false ; break foundRAW ; } } return false ; } } for ( i ++ ; i < length ; i ++ ) { if ( ! areTypesEqual ( oneArgs [ i ] , twoArgs [ i ] ) ) { if ( oneArgs [ i ] . leafComponentType ( ) . isRawType ( ) ) if ( oneArgs [ i ] . dimensions ( ) == twoArgs [ i ] . dimensions ( ) && oneArgs [ i ] . leafComponentType ( ) . isEquivalentTo ( twoArgs [ i ] . leafComponentType ( ) ) ) continue ; return false ; } else if ( oneArgs [ i ] . leafComponentType ( ) . isParameterizedTypeWithActualArguments ( ) ) { return false ; } } return true ; } boolean areReturnTypesCompatible ( MethodBinding one , MethodBinding two ) { if ( one . returnType == two . returnType ) return true ; if ( this . type . scope . compilerOptions ( ) . sourceLevel >= ClassFileConstants . JDK1_5 ) { return areReturnTypesCompatible0 ( one , two ) ; } else { return areTypesEqual ( one . returnType . erasure ( ) , two . returnType . erasure ( ) ) ; } } boolean areTypesEqual ( TypeBinding one , TypeBinding two ) { if ( one == two ) return true ; switch ( one . kind ( ) ) { case Binding . TYPE : switch ( two . kind ( ) ) { case Binding . PARAMETERIZED_TYPE : case Binding . RAW_TYPE : if ( one == two . erasure ( ) ) return true ; } break ; case Binding . RAW_TYPE : case Binding . PARAMETERIZED_TYPE : switch ( two . kind ( ) ) { case Binding . TYPE : if ( one . erasure ( ) == two ) return true ; } } if ( one . isParameterizedType ( ) && two . isParameterizedType ( ) ) return one . isEquivalentTo ( two ) && two . isEquivalentTo ( one ) ; return false ; } protected boolean canOverridingMethodDifferInErasure ( MethodBinding overridingMethod , MethodBinding inheritedMethod ) { if ( overridingMethod . areParameterErasuresEqual ( inheritedMethod ) ) return false ; if ( overridingMethod . declaringClass . isRawType ( ) ) return false ; return true ; } boolean canSkipInheritedMethods ( ) { if ( this . type . superclass ( ) != null ) if ( this . type . superclass ( ) . isAbstract ( ) || this . type . superclass ( ) . isParameterizedType ( ) ) return false ; return this . type . superInterfaces ( ) == Binding . NO_SUPERINTERFACES ; } boolean canSkipInheritedMethods ( MethodBinding one , MethodBinding two ) { return two == null || ( one . declaringClass == two . declaringClass && ! one . declaringClass . isParameterizedType ( ) ) ; } void checkConcreteInheritedMethod ( MethodBinding concreteMethod , MethodBinding [ ] abstractMethods ) { super . checkConcreteInheritedMethod ( concreteMethod , abstractMethods ) ; boolean analyseNullAnnotations = this . environment . globalOptions . isAnnotationBasedNullAnalysisEnabled ; for ( int i = 0 , l = abstractMethods . length ; i < l ; i ++ ) { MethodBinding abstractMethod = abstractMethods [ i ] ; if ( concreteMethod . isVarargs ( ) != abstractMethod . isVarargs ( ) ) problemReporter ( ) . varargsConflict ( concreteMethod , abstractMethod , this . type ) ; MethodBinding originalInherited = abstractMethod . original ( ) ; if ( originalInherited . returnType != concreteMethod . returnType ) if ( ! isAcceptableReturnTypeOverride ( concreteMethod , abstractMethod ) ) problemReporter ( ) . unsafeReturnTypeOverride ( concreteMethod , originalInherited , this . type ) ; if ( originalInherited . declaringClass . isInterface ( ) ) { if ( ( concreteMethod . declaringClass == this . type . superclass && this . type . superclass . isParameterizedType ( ) && ! areMethodsCompatible ( concreteMethod , originalInherited ) ) || this . type . superclass . erasure ( ) . findSuperTypeOriginatingFrom ( originalInherited . declaringClass ) == null ) this . type . addSyntheticBridgeMethod ( originalInherited , concreteMethod . original ( ) ) ; } if ( analyseNullAnnotations && ! concreteMethod . isStatic ( ) && ! abstractMethod . isStatic ( ) ) checkNullSpecInheritance ( concreteMethod , abstractMethod ) ; } } void checkForBridgeMethod ( MethodBinding currentMethod , MethodBinding inheritedMethod , MethodBinding [ ] allInheritedMethods ) { if ( currentMethod . isVarargs ( ) != inheritedMethod . isVarargs ( ) ) problemReporter ( currentMethod ) . varargsConflict ( currentMethod , inheritedMethod , this . type ) ; MethodBinding originalInherited = inheritedMethod . original ( ) ; if ( originalInherited . returnType != currentMethod . returnType ) if ( ! isAcceptableReturnTypeOverride ( currentMethod , inheritedMethod ) ) problemReporter ( currentMethod ) . unsafeReturnTypeOverride ( currentMethod , originalInherited , this . type ) ; MethodBinding bridge = this . type . addSyntheticBridgeMethod ( originalInherited , currentMethod . original ( ) ) ; if ( bridge != null ) { for ( int i = 0 , l = allInheritedMethods == null ? 0 : allInheritedMethods . length ; i < l ; i ++ ) { if ( allInheritedMethods [ i ] != null && detectInheritedNameClash ( originalInherited , allInheritedMethods [ i ] . original ( ) ) ) return ; } MethodBinding [ ] current = ( MethodBinding [ ] ) this . currentMethods . get ( bridge . selector ) ; for ( int i = current . length - 1 ; i >= 0 ; -- i ) { final MethodBinding thisMethod = current [ i ] ; if ( thisMethod . areParameterErasuresEqual ( bridge ) && thisMethod . returnType . erasure ( ) == bridge . returnType . erasure ( ) ) { problemReporter ( thisMethod ) . methodNameClash ( thisMethod , inheritedMethod . declaringClass . isRawType ( ) ? inheritedMethod : inheritedMethod . original ( ) , ProblemSeverities . Error ) ; return ; } } } } void checkForNameClash ( MethodBinding currentMethod , MethodBinding inheritedMethod ) { if ( inheritedMethod . isStatic ( ) || currentMethod . isStatic ( ) ) { MethodBinding original = inheritedMethod . original ( ) ; if ( this . type . scope . compilerOptions ( ) . complianceLevel >= ClassFileConstants . JDK1_7 && currentMethod . areParameterErasuresEqual ( original ) ) { problemReporter ( currentMethod ) . methodNameClashHidden ( currentMethod , inheritedMethod . declaringClass . isRawType ( ) ? inheritedMethod : original ) ; } return ; } if ( ! detectNameClash ( currentMethod , inheritedMethod , false ) ) { TypeBinding [ ] currentParams = currentMethod . parameters ; TypeBinding [ ] inheritedParams = inheritedMethod . parameters ; int length = currentParams . length ; if ( length != inheritedParams . length ) return ; for ( int i = 0 ; i < length ; i ++ ) if ( currentParams [ i ] != inheritedParams [ i ] ) if ( currentParams [ i ] . isBaseType ( ) != inheritedParams [ i ] . isBaseType ( ) || ! inheritedParams [ i ] . isCompatibleWith ( currentParams [ i ] ) ) return ; ReferenceBinding [ ] interfacesToVisit = null ; int nextPosition = 0 ; ReferenceBinding superType = inheritedMethod . declaringClass ; ReferenceBinding [ ] itsInterfaces = superType . superInterfaces ( ) ; if ( itsInterfaces != Binding . NO_SUPERINTERFACES ) { nextPosition = itsInterfaces . length ; interfacesToVisit = itsInterfaces ; } superType = superType . superclass ( ) ; while ( superType != null && superType . isValidBinding ( ) ) { MethodBinding [ ] methods = superType . getMethods ( currentMethod . selector ) ; for ( int m = 0 , n = methods . length ; m < n ; m ++ ) { MethodBinding substitute = computeSubstituteMethod ( methods [ m ] , currentMethod ) ; if ( substitute != null && ! isSubstituteParameterSubsignature ( currentMethod , substitute ) && detectNameClash ( currentMethod , substitute , true ) ) return ; } if ( ( itsInterfaces = superType . superInterfaces ( ) ) != Binding . NO_SUPERINTERFACES ) { if ( interfacesToVisit == null ) { interfacesToVisit = itsInterfaces ; nextPosition = interfacesToVisit . length ; } else { int itsLength = itsInterfaces . length ; if ( nextPosition + itsLength >= interfacesToVisit . length ) System . arraycopy ( interfacesToVisit , 0 , interfacesToVisit = new ReferenceBinding [ nextPosition + itsLength + 5 ] , 0 , nextPosition ) ; nextInterface : for ( int a = 0 ; a < itsLength ; a ++ ) { ReferenceBinding next = itsInterfaces [ a ] ; for ( int b = 0 ; b < nextPosition ; b ++ ) if ( next == interfacesToVisit [ b ] ) continue nextInterface ; interfacesToVisit [ nextPosition ++ ] = next ; } } } superType = superType . superclass ( ) ; } for ( int i = 0 ; i < nextPosition ; i ++ ) { superType = interfacesToVisit [ i ] ; if ( superType . isValidBinding ( ) ) { MethodBinding [ ] methods = superType . getMethods ( currentMethod . selector ) ; for ( int m = 0 , n = methods . length ; m < n ; m ++ ) { MethodBinding substitute = computeSubstituteMethod ( methods [ m ] , currentMethod ) ; if ( substitute != null && ! isSubstituteParameterSubsignature ( currentMethod , substitute ) && detectNameClash ( currentMethod , substitute , true ) ) return ; } if ( ( itsInterfaces = superType . superInterfaces ( ) ) != Binding . NO_SUPERINTERFACES ) { int itsLength = itsInterfaces . length ; if ( nextPosition + itsLength >= interfacesToVisit . length ) System . arraycopy ( interfacesToVisit , 0 , interfacesToVisit = new ReferenceBinding [ nextPosition + itsLength + 5 ] , 0 , nextPosition ) ; nextInterface : for ( int a = 0 ; a < itsLength ; a ++ ) { ReferenceBinding next = itsInterfaces [ a ] ; for ( int b = 0 ; b < nextPosition ; b ++ ) if ( next == interfacesToVisit [ b ] ) continue nextInterface ; interfacesToVisit [ nextPosition ++ ] = next ; } } } } } } void checkInheritedMethods ( MethodBinding inheritedMethod , MethodBinding otherInheritedMethod ) { if ( inheritedMethod . isStatic ( ) ) return ; if ( this . environment . globalOptions . complianceLevel < ClassFileConstants . JDK1_7 && inheritedMethod . declaringClass . isInterface ( ) ) return ; detectInheritedNameClash ( inheritedMethod . original ( ) , otherInheritedMethod . original ( ) ) ; } void checkInheritedMethods ( MethodBinding [ ] methods , int length ) { boolean continueInvestigation = true ; MethodBinding concreteMethod = null ; for ( int i = 0 ; i < length ; i ++ ) { if ( ! methods [ i ] . isAbstract ( ) ) { if ( concreteMethod != null ) { problemReporter ( ) . duplicateInheritedMethods ( this . type , concreteMethod , methods [ i ] ) ; continueInvestigation = false ; } concreteMethod = methods [ i ] ; } } if ( continueInvestigation ) { super . checkInheritedMethods ( methods , length ) ; } } boolean checkInheritedReturnTypes ( MethodBinding method , MethodBinding otherMethod ) { if ( areReturnTypesCompatible ( method , otherMethod ) ) return true ; if ( isUnsafeReturnTypeOverride ( method , otherMethod ) ) { if ( ! method . declaringClass . implementsInterface ( otherMethod . declaringClass , false ) ) problemReporter ( method ) . unsafeReturnTypeOverride ( method , otherMethod , this . type ) ; return true ; } return false ; } void checkAgainstInheritedMethods ( MethodBinding currentMethod , MethodBinding [ ] methods , int length , MethodBinding [ ] allInheritedMethods ) { super . checkAgainstInheritedMethods ( currentMethod , methods , length , allInheritedMethods ) ; if ( this . environment . globalOptions . isAnnotationBasedNullAnalysisEnabled ) { for ( int i = length ; -- i >= 0 ; ) if ( ! currentMethod . isStatic ( ) && ! methods [ i ] . isStatic ( ) ) checkNullSpecInheritance ( currentMethod , methods [ i ] ) ; } } void checkNullSpecInheritance ( MethodBinding currentMethod , MethodBinding inheritedMethod ) { long inheritedBits = inheritedMethod . tagBits ; long currentBits = currentMethod . tagBits ; AbstractMethodDeclaration srcMethod = null ; if ( this . type . equals ( currentMethod . declaringClass ) ) srcMethod = currentMethod . sourceMethod ( ) ; if ( ( inheritedBits & TagBits . AnnotationNonNull ) != 0 ) { long currentNullBits = currentBits & ( TagBits . AnnotationNonNull | TagBits . AnnotationNullable ) ; if ( currentNullBits != TagBits . AnnotationNonNull ) { if ( srcMethod != null ) { this . type . scope . problemReporter ( ) . illegalReturnRedefinition ( srcMethod , inheritedMethod , this . environment . getNonNullAnnotationName ( ) ) ; } else { this . type . scope . problemReporter ( ) . cannotImplementIncompatibleNullness ( currentMethod , inheritedMethod ) ; return ; } } } Argument [ ] currentArguments = srcMethod == null ? null : srcMethod . arguments ; if ( inheritedMethod . parameterNonNullness != null ) { int length = inheritedMethod . parameterNonNullness . length ; for ( int i = 0 ; i < length ; i ++ ) { Argument currentArgument = currentArguments == null ? null : currentArguments [ i ] ; Boolean inheritedNonNullNess = inheritedMethod . parameterNonNullness [ i ] ; Boolean currentNonNullNess = ( currentMethod . parameterNonNullness == null ) ? null : currentMethod . parameterNonNullness [ i ] ; if ( inheritedNonNullNess != null ) { if ( currentNonNullNess == null ) { boolean needNonNull = false ; char [ ] [ ] annotationName ; if ( inheritedNonNullNess == Boolean . TRUE ) { needNonNull = true ; annotationName = this . environment . getNonNullAnnotationName ( ) ; } else { annotationName = this . environment . getNullableAnnotationName ( ) ; } if ( currentArgument != null ) { this . type . scope . problemReporter ( ) . parameterLackingNullAnnotation ( currentArgument , inheritedMethod . declaringClass , needNonNull , annotationName ) ; continue ; } else { this . type . scope . problemReporter ( ) . cannotImplementIncompatibleNullness ( currentMethod , inheritedMethod ) ; break ; } } } if ( inheritedNonNullNess != Boolean . TRUE ) { if ( currentNonNullNess == Boolean . TRUE ) { if ( currentArgument != null ) this . type . scope . problemReporter ( ) . illegalRedefinitionToNonNullParameter ( currentArgument , inheritedMethod . declaringClass , inheritedNonNullNess == null ? null : this . environment . getNullableAnnotationName ( ) ) ; else this . type . scope . problemReporter ( ) . cannotImplementIncompatibleNullness ( currentMethod , inheritedMethod ) ; } } } } else if ( currentMethod . parameterNonNullness != null ) { for ( int i = 0 ; i < currentMethod . parameterNonNullness . length ; i ++ ) { if ( currentMethod . parameterNonNullness [ i ] == Boolean . TRUE ) { if ( currentArguments != null ) { this . type . scope . problemReporter ( ) . illegalRedefinitionToNonNullParameter ( currentArguments [ i ] , inheritedMethod . declaringClass , null ) ; } else { this . type . scope . problemReporter ( ) . cannotImplementIncompatibleNullness ( currentMethod , inheritedMethod ) ; break ; } } } } } void reportRawReferences ( ) { CompilerOptions compilerOptions = this . type . scope . compilerOptions ( ) ; if ( compilerOptions . sourceLevel < ClassFileConstants . JDK1_5 || compilerOptions . reportUnavoidableGenericTypeProblems ) { return ; } Object [ ] methodArray = this . currentMethods . valueTable ; for ( int s = methodArray . length ; -- s >= 0 ; ) { if ( methodArray [ s ] == null ) continue ; MethodBinding [ ] current = ( MethodBinding [ ] ) methodArray [ s ] ; for ( int i = 0 , length = current . length ; i < length ; i ++ ) { MethodBinding currentMethod = current [ i ] ; if ( ( currentMethod . modifiers & ( ExtraCompilerModifiers . AccImplementing | ExtraCompilerModifiers . AccOverriding ) ) == 0 ) { AbstractMethodDeclaration methodDecl = currentMethod . sourceMethod ( ) ; if ( methodDecl == null ) return ; TypeBinding [ ] parameterTypes = currentMethod . parameters ; Argument [ ] arguments = methodDecl . arguments ; for ( int j = 0 , size = currentMethod . parameters . length ; j < size ; j ++ ) { TypeBinding parameterType = parameterTypes [ j ] ; Argument arg = arguments [ j ] ; if ( parameterType . leafComponentType ( ) . isRawType ( ) && compilerOptions . getSeverity ( CompilerOptions . RawTypeReference ) != ProblemSeverities . Ignore && ( arg . type . bits & ASTNode . IgnoreRawTypeCheck ) == 0 ) { methodDecl . scope . problemReporter ( ) . rawTypeReference ( arg . type , parameterType ) ; } } if ( ! methodDecl . isConstructor ( ) && methodDecl instanceof MethodDeclaration ) { TypeReference returnType = ( ( MethodDeclaration ) methodDecl ) . returnType ; TypeBinding methodType = currentMethod . returnType ; if ( returnType != null ) { if ( methodType . leafComponentType ( ) . isRawType ( ) && compilerOptions . getSeverity ( CompilerOptions . RawTypeReference ) != ProblemSeverities . Ignore && ( returnType . bits & ASTNode . IgnoreRawTypeCheck ) == 0 ) { methodDecl . scope . problemReporter ( ) . rawTypeReference ( returnType , methodType ) ; } } } } } } } public void reportRawReferences ( MethodBinding currentMethod , MethodBinding inheritedMethod ) { CompilerOptions compilerOptions = this . type . scope . compilerOptions ( ) ; if ( compilerOptions . sourceLevel < ClassFileConstants . JDK1_5 || compilerOptions . reportUnavoidableGenericTypeProblems ) { return ; } AbstractMethodDeclaration methodDecl = currentMethod . sourceMethod ( ) ; if ( methodDecl == null ) return ; TypeBinding [ ] parameterTypes = currentMethod . parameters ; TypeBinding [ ] inheritedParameterTypes = inheritedMethod . parameters ; Argument [ ] arguments = methodDecl . arguments ; for ( int j = 0 , size = currentMethod . parameters . length ; j < size ; j ++ ) { TypeBinding parameterType = parameterTypes [ j ] ; TypeBinding inheritedParameterType = inheritedParameterTypes [ j ] ; Argument arg = arguments [ j ] ; if ( parameterType . leafComponentType ( ) . isRawType ( ) ) { if ( inheritedParameterType . leafComponentType ( ) . isRawType ( ) ) { arg . binding . tagBits |= TagBits . ForcedToBeRawType ; } else { if ( compilerOptions . getSeverity ( CompilerOptions . RawTypeReference ) != ProblemSeverities . Ignore && ( arg . type . bits & ASTNode . IgnoreRawTypeCheck ) == 0 ) { methodDecl . scope . problemReporter ( ) . rawTypeReference ( arg . type , parameterType ) ; } } } } TypeReference returnType = null ; if ( ! methodDecl . isConstructor ( ) && methodDecl instanceof MethodDeclaration && ( returnType = ( ( MethodDeclaration ) methodDecl ) . returnType ) != null ) { final TypeBinding inheritedMethodType = inheritedMethod . returnType ; final TypeBinding methodType = currentMethod . returnType ; if ( methodType . leafComponentType ( ) . isRawType ( ) ) { if ( inheritedMethodType . leafComponentType ( ) . isRawType ( ) ) { } else { if ( ( returnType . bits & ASTNode . IgnoreRawTypeCheck ) == 0 && compilerOptions . getSeverity ( CompilerOptions . RawTypeReference ) != ProblemSeverities . Ignore ) { methodDecl . scope . problemReporter ( ) . rawTypeReference ( returnType , methodType ) ; } } } } } void checkMethods ( ) { boolean mustImplementAbstractMethods = mustImplementAbstractMethods ( ) ; boolean skipInheritedMethods = mustImplementAbstractMethods && canSkipInheritedMethods ( ) ; boolean isOrEnclosedByPrivateType = this . type . isOrEnclosedByPrivateType ( ) ; char [ ] [ ] methodSelectors = this . inheritedMethods . keyTable ; nextSelector : for ( int s = methodSelectors . length ; -- s >= 0 ; ) { if ( methodSelectors [ s ] == null ) continue nextSelector ; MethodBinding [ ] current = ( MethodBinding [ ] ) this . currentMethods . get ( methodSelectors [ s ] ) ; MethodBinding [ ] inherited = ( MethodBinding [ ] ) this . inheritedMethods . valueTable [ s ] ; if ( current == null && ! isOrEnclosedByPrivateType ) { int length = inherited . length ; for ( int i = 0 ; i < length ; i ++ ) { inherited [ i ] . original ( ) . modifiers |= ExtraCompilerModifiers . AccLocallyUsed ; } } if ( current == null && this . type . isPublic ( ) ) { int length = inherited . length ; for ( int i = 0 ; i < length ; i ++ ) { MethodBinding inheritedMethod = inherited [ i ] ; if ( inheritedMethod . isPublic ( ) && ! inheritedMethod . declaringClass . isPublic ( ) ) this . type . addSyntheticBridgeMethod ( inheritedMethod . original ( ) ) ; } } if ( current == null && skipInheritedMethods ) continue nextSelector ; if ( inherited . length == 1 && current == null ) { if ( mustImplementAbstractMethods && inherited [ 0 ] . isAbstract ( ) ) checkAbstractMethod ( inherited [ 0 ] ) ; continue nextSelector ; } int index = - 1 ; int inheritedLength = inherited . length ; MethodBinding [ ] matchingInherited = new MethodBinding [ inheritedLength ] ; MethodBinding [ ] foundMatch = new MethodBinding [ inheritedLength ] ; if ( current != null ) { for ( int i = 0 , length1 = current . length ; i < length1 ; i ++ ) { MethodBinding currentMethod = current [ i ] ; MethodBinding [ ] nonMatchingInherited = null ; for ( int j = 0 ; j < inheritedLength ; j ++ ) { MethodBinding inheritedMethod = computeSubstituteMethod ( inherited [ j ] , currentMethod ) ; if ( inheritedMethod != null ) { if ( foundMatch [ j ] == null && isSubstituteParameterSubsignature ( currentMethod , inheritedMethod ) ) { matchingInherited [ ++ index ] = inheritedMethod ; foundMatch [ j ] = currentMethod ; } else { checkForNameClash ( currentMethod , inheritedMethod ) ; if ( inheritedLength > 1 ) { if ( nonMatchingInherited == null ) nonMatchingInherited = new MethodBinding [ inheritedLength ] ; nonMatchingInherited [ j ] = inheritedMethod ; } } } } if ( index >= 0 ) { checkAgainstInheritedMethods ( currentMethod , matchingInherited , index + 1 , nonMatchingInherited ) ; while ( index >= 0 ) matchingInherited [ index -- ] = null ; } } } boolean [ ] skip = new boolean [ inheritedLength ] ; for ( int i = 0 ; i < inheritedLength ; i ++ ) { MethodBinding matchMethod = foundMatch [ i ] ; if ( matchMethod == null && current != null && this . type . isPublic ( ) ) { MethodBinding inheritedMethod = inherited [ i ] ; if ( inheritedMethod . isPublic ( ) && ! inheritedMethod . declaringClass . isPublic ( ) ) { this . type . addSyntheticBridgeMethod ( inheritedMethod . original ( ) ) ; } } if ( ! isOrEnclosedByPrivateType && matchMethod == null && current != null ) { inherited [ i ] . original ( ) . modifiers |= ExtraCompilerModifiers . AccLocallyUsed ; } if ( skip [ i ] ) continue ; MethodBinding inheritedMethod = inherited [ i ] ; if ( matchMethod == null ) matchingInherited [ ++ index ] = inheritedMethod ; for ( int j = i + 1 ; j < inheritedLength ; j ++ ) { MethodBinding otherInheritedMethod = inherited [ j ] ; if ( matchMethod == foundMatch [ j ] && matchMethod != null ) continue ; if ( canSkipInheritedMethods ( inheritedMethod , otherInheritedMethod ) ) continue ; if ( inheritedMethod . declaringClass != otherInheritedMethod . declaringClass ) { if ( otherInheritedMethod . declaringClass . isInterface ( ) ) { if ( isInterfaceMethodImplemented ( otherInheritedMethod , inheritedMethod , otherInheritedMethod . declaringClass ) ) { skip [ j ] = true ; continue ; } } else if ( areMethodsCompatible ( inheritedMethod , otherInheritedMethod ) ) { skip [ j ] = true ; continue ; } } otherInheritedMethod = computeSubstituteMethod ( otherInheritedMethod , inheritedMethod ) ; if ( otherInheritedMethod != null ) { if ( isSubstituteParameterSubsignature ( inheritedMethod , otherInheritedMethod ) ) { if ( index == - 1 ) matchingInherited [ ++ index ] = inheritedMethod ; if ( foundMatch [ j ] == null ) matchingInherited [ ++ index ] = otherInheritedMethod ; skip [ j ] = true ; } else if ( matchMethod == null && foundMatch [ j ] == null ) { checkInheritedMethods ( inheritedMethod , otherInheritedMethod ) ; } } } if ( index == - 1 ) continue ; if ( index > 0 ) checkInheritedMethods ( matchingInherited , index + 1 ) ; else if ( mustImplementAbstractMethods && matchingInherited [ 0 ] . isAbstract ( ) && matchMethod == null ) checkAbstractMethod ( matchingInherited [ 0 ] ) ; while ( index >= 0 ) matchingInherited [ index -- ] = null ; } } } void checkTypeVariableMethods ( TypeParameter typeParameter ) { char [ ] [ ] methodSelectors = this . inheritedMethods . keyTable ; nextSelector : for ( int s = methodSelectors . length ; -- s >= 0 ; ) { if ( methodSelectors [ s ] == null ) continue nextSelector ; MethodBinding [ ] inherited = ( MethodBinding [ ] ) this . inheritedMethods . valueTable [ s ] ; if ( inherited . length == 1 ) continue nextSelector ; int index = - 1 ; MethodBinding [ ] matchingInherited = new MethodBinding [ inherited . length ] ; for ( int i = 0 , length = inherited . length ; i < length ; i ++ ) { while ( index >= 0 ) matchingInherited [ index -- ] = null ; MethodBinding inheritedMethod = inherited [ i ] ; if ( inheritedMethod != null ) { matchingInherited [ ++ index ] = inheritedMethod ; for ( int j = i + 1 ; j < length ; j ++ ) { MethodBinding otherInheritedMethod = inherited [ j ] ; if ( canSkipInheritedMethods ( inheritedMethod , otherInheritedMethod ) ) continue ; otherInheritedMethod = computeSubstituteMethod ( otherInheritedMethod , inheritedMethod ) ; if ( otherInheritedMethod != null && isSubstituteParameterSubsignature ( inheritedMethod , otherInheritedMethod ) ) { matchingInherited [ ++ index ] = otherInheritedMethod ; inherited [ j ] = null ; } } } if ( index > 0 ) { MethodBinding first = matchingInherited [ 0 ] ; int count = index + 1 ; while ( -- count > 0 ) { MethodBinding match = matchingInherited [ count ] ; MethodBinding interfaceMethod = null , implementation = null ; if ( first . declaringClass . isInterface ( ) ) { interfaceMethod = first ; } else if ( first . declaringClass . isClass ( ) ) { implementation = first ; } if ( match . declaringClass . isInterface ( ) ) { interfaceMethod = match ; } else if ( match . declaringClass . isClass ( ) ) { implementation = match ; } if ( interfaceMethod != null && implementation != null && ! isAsVisible ( implementation , interfaceMethod ) ) problemReporter ( ) . inheritedMethodReducesVisibility ( typeParameter , implementation , new MethodBinding [ ] { interfaceMethod } ) ; if ( areReturnTypesCompatible ( first , match ) ) continue ; if ( first . declaringClass . isInterface ( ) && match . declaringClass . isInterface ( ) && areReturnTypesCompatible ( match , first ) ) continue ; break ; } if ( count > 0 ) { problemReporter ( ) . inheritedMethodsHaveIncompatibleReturnTypes ( typeParameter , matchingInherited , index + 1 ) ; continue nextSelector ; } } } } } MethodBinding computeSubstituteMethod ( MethodBinding inheritedMethod , MethodBinding currentMethod ) { if ( inheritedMethod == null ) return null ; if ( currentMethod . parameters . length != inheritedMethod . parameters . length ) return null ; if ( currentMethod . declaringClass instanceof BinaryTypeBinding ) ( ( BinaryTypeBinding ) currentMethod . declaringClass ) . resolveTypesFor ( currentMethod ) ; if ( inheritedMethod . declaringClass instanceof BinaryTypeBinding ) ( ( BinaryTypeBinding ) inheritedMethod . declaringClass ) . resolveTypesFor ( inheritedMethod ) ; TypeVariableBinding [ ] inheritedTypeVariables = inheritedMethod . typeVariables ; int inheritedLength = inheritedTypeVariables . length ; if ( inheritedLength == 0 ) return inheritedMethod ; TypeVariableBinding [ ] typeVariables = currentMethod . typeVariables ; int length = typeVariables . length ; if ( length == 0 ) return inheritedMethod . asRawMethod ( this . environment ) ; if ( length != inheritedLength ) return inheritedMethod ; TypeBinding [ ] arguments = new TypeBinding [ length ] ; System . arraycopy ( typeVariables , 0 , arguments , 0 , length ) ; ParameterizedGenericMethodBinding substitute = this . environment . createParameterizedGenericMethod ( inheritedMethod , arguments ) ; for ( int i = 0 ; i < inheritedLength ; i ++ ) { TypeVariableBinding inheritedTypeVariable = inheritedTypeVariables [ i ] ; TypeBinding argument = arguments [ i ] ; if ( argument instanceof TypeVariableBinding ) { TypeVariableBinding typeVariable = ( TypeVariableBinding ) argument ; if ( typeVariable . firstBound == inheritedTypeVariable . firstBound ) { if ( typeVariable . firstBound == null ) continue ; } else if ( typeVariable . firstBound != null && inheritedTypeVariable . firstBound != null ) { if ( typeVariable . firstBound . isClass ( ) != inheritedTypeVariable . firstBound . isClass ( ) ) return inheritedMethod ; } if ( Scope . substitute ( substitute , inheritedTypeVariable . superclass ) != typeVariable . superclass ) return inheritedMethod ; int interfaceLength = inheritedTypeVariable . superInterfaces . length ; ReferenceBinding [ ] interfaces = typeVariable . superInterfaces ; if ( interfaceLength != interfaces . length ) return inheritedMethod ; next : for ( int j = 0 ; j < interfaceLength ; j ++ ) { TypeBinding superType = Scope . substitute ( substitute , inheritedTypeVariable . superInterfaces [ j ] ) ; for ( int k = 0 ; k < interfaceLength ; k ++ ) if ( superType == interfaces [ k ] ) continue next ; return inheritedMethod ; } } else if ( inheritedTypeVariable . boundCheck ( substitute , argument ) != TypeConstants . OK ) { return inheritedMethod ; } } return substitute ; } boolean detectInheritedNameClash ( MethodBinding inherited , MethodBinding otherInherited ) { if ( ! inherited . areParameterErasuresEqual ( otherInherited ) ) return false ; if ( inherited . returnType . erasure ( ) != otherInherited . returnType . erasure ( ) ) return false ; if ( inherited . declaringClass . erasure ( ) != otherInherited . declaringClass . erasure ( ) ) { if ( inherited . declaringClass . findSuperTypeOriginatingFrom ( otherInherited . declaringClass ) != null ) return false ; if ( otherInherited . declaringClass . findSuperTypeOriginatingFrom ( inherited . declaringClass ) != null ) return false ; } problemReporter ( ) . inheritedMethodsHaveNameClash ( this . type , inherited , otherInherited ) ; return true ; } boolean detectNameClash ( MethodBinding current , MethodBinding inherited , boolean treatAsSynthetic ) { MethodBinding methodToCheck = inherited ; MethodBinding original = methodToCheck . original ( ) ; if ( ! current . areParameterErasuresEqual ( original ) ) return false ; int severity = ProblemSeverities . Error ; if ( this . environment . globalOptions . complianceLevel == ClassFileConstants . JDK1_6 ) { if ( current . returnType . erasure ( ) != original . returnType . erasure ( ) ) severity = ProblemSeverities . Warning ; } if ( ! treatAsSynthetic ) { MethodBinding [ ] currentNamesakes = ( MethodBinding [ ] ) this . currentMethods . get ( inherited . selector ) ; if ( currentNamesakes . length > 1 ) { for ( int i = 0 , length = currentNamesakes . length ; i < length ; i ++ ) { MethodBinding currentMethod = currentNamesakes [ i ] ; if ( currentMethod != current && doesMethodOverride ( currentMethod , inherited ) ) { methodToCheck = currentMethod ; break ; } } } } original = methodToCheck . original ( ) ; if ( ! current . areParameterErasuresEqual ( original ) ) return false ; original = inherited . original ( ) ; problemReporter ( current ) . methodNameClash ( current , inherited . declaringClass . isRawType ( ) ? inherited : original , severity ) ; if ( severity == ProblemSeverities . Warning ) return false ; return true ; } public boolean doesMethodOverride ( MethodBinding method , MethodBinding inheritedMethod ) { return couldMethodOverride ( method , inheritedMethod ) && areMethodsCompatible ( method , inheritedMethod ) ; } boolean doTypeVariablesClash ( MethodBinding one , MethodBinding substituteTwo ) { return one . typeVariables != Binding . NO_TYPE_VARIABLES && ! ( substituteTwo instanceof ParameterizedGenericMethodBinding ) ; } SimpleSet findSuperinterfaceCollisions ( ReferenceBinding superclass , ReferenceBinding [ ] superInterfaces ) { ReferenceBinding [ ] interfacesToVisit = null ; int nextPosition = 0 ; ReferenceBinding [ ] itsInterfaces = superInterfaces ; if ( itsInterfaces != Binding . NO_SUPERINTERFACES ) { nextPosition = itsInterfaces . length ; interfacesToVisit = itsInterfaces ; } boolean isInconsistent = this . type . isHierarchyInconsistent ( ) ; ReferenceBinding superType = superclass ; while ( superType != null && superType . isValidBinding ( ) ) { isInconsistent |= superType . isHierarchyInconsistent ( ) ; if ( ( itsInterfaces = superType . superInterfaces ( ) ) != Binding . NO_SUPERINTERFACES ) { if ( interfacesToVisit == null ) { interfacesToVisit = itsInterfaces ; nextPosition = interfacesToVisit . length ; } else { int itsLength = itsInterfaces . length ; if ( nextPosition + itsLength >= interfacesToVisit . length ) System . arraycopy ( interfacesToVisit , 0 , interfacesToVisit = new ReferenceBinding [ nextPosition + itsLength + 5 ] , 0 , nextPosition ) ; nextInterface : for ( int a = 0 ; a < itsLength ; a ++ ) { ReferenceBinding next = itsInterfaces [ a ] ; for ( int b = 0 ; b < nextPosition ; b ++ ) if ( next == interfacesToVisit [ b ] ) continue nextInterface ; interfacesToVisit [ nextPosition ++ ] = next ; } } } superType = superType . superclass ( ) ; } for ( int i = 0 ; i < nextPosition ; i ++ ) { superType = interfacesToVisit [ i ] ; if ( superType . isValidBinding ( ) ) { isInconsistent |= superType . isHierarchyInconsistent ( ) ; if ( ( itsInterfaces = superType . superInterfaces ( ) ) != Binding . NO_SUPERINTERFACES ) { int itsLength = itsInterfaces . length ; if ( nextPosition + itsLength >= interfacesToVisit . length ) System . arraycopy ( interfacesToVisit , 0 , interfacesToVisit = new ReferenceBinding [ nextPosition + itsLength + 5 ] , 0 , nextPosition ) ; nextInterface : for ( int a = 0 ; a < itsLength ; a ++ ) { ReferenceBinding next = itsInterfaces [ a ] ; for ( int b = 0 ; b < nextPosition ; b ++ ) if ( next == interfacesToVisit [ b ] ) continue nextInterface ; interfacesToVisit [ nextPosition ++ ] = next ; } } } } if ( ! isInconsistent ) return null ; SimpleSet copy = null ; for ( int i = 0 ; i < nextPosition ; i ++ ) { ReferenceBinding current = interfacesToVisit [ i ] ; if ( current . isValidBinding ( ) ) { TypeBinding erasure = current . erasure ( ) ; for ( int j = i + 1 ; j < nextPosition ; j ++ ) { ReferenceBinding next = interfacesToVisit [ j ] ; if ( next . isValidBinding ( ) && next . erasure ( ) == erasure ) { if ( copy == null ) copy = new SimpleSet ( nextPosition ) ; copy . add ( interfacesToVisit [ i ] ) ; copy . add ( interfacesToVisit [ j ] ) ; } } } } return copy ; } boolean hasGenericParameter ( MethodBinding method ) { if ( method . genericSignature ( ) == null ) return false ; TypeBinding [ ] params = method . parameters ; for ( int i = 0 , l = params . length ; i < l ; i ++ ) { TypeBinding param = params [ i ] . leafComponentType ( ) ; if ( param instanceof ReferenceBinding ) { int modifiers = ( ( ReferenceBinding ) param ) . modifiers ; if ( ( modifiers & ExtraCompilerModifiers . AccGenericSignature ) != 0 ) return true ; } } return false ; } boolean isAcceptableReturnTypeOverride ( MethodBinding currentMethod , MethodBinding inheritedMethod ) { if ( inheritedMethod . declaringClass . isRawType ( ) ) return true ; MethodBinding originalInherited = inheritedMethod . original ( ) ; TypeBinding originalInheritedReturnType = originalInherited . returnType . leafComponentType ( ) ; if ( originalInheritedReturnType . isParameterizedTypeWithActualArguments ( ) ) return ! currentMethod . returnType . leafComponentType ( ) . isRawType ( ) ; TypeBinding currentReturnType = currentMethod . returnType . leafComponentType ( ) ; switch ( currentReturnType . kind ( ) ) { case Binding . TYPE_PARAMETER : if ( currentReturnType == inheritedMethod . returnType . leafComponentType ( ) ) return true ; default : if ( originalInheritedReturnType . isTypeVariable ( ) ) if ( ( ( TypeVariableBinding ) originalInheritedReturnType ) . declaringElement == originalInherited ) return false ; return true ; } } boolean isInterfaceMethodImplemented ( MethodBinding inheritedMethod , MethodBinding existingMethod , ReferenceBinding superType ) { if ( inheritedMethod . original ( ) != inheritedMethod && existingMethod . declaringClass . isInterface ( ) ) return false ; inheritedMethod = computeSubstituteMethod ( inheritedMethod , existingMethod ) ; return inheritedMethod != null && inheritedMethod . returnType == existingMethod . returnType && doesMethodOverride ( existingMethod , inheritedMethod ) ; } public boolean isMethodSubsignature ( MethodBinding method , MethodBinding inheritedMethod ) { if ( ! org . eclipse . jdt . core . compiler . CharOperation . equals ( method . selector , inheritedMethod . selector ) ) return false ; if ( method . declaringClass . isParameterizedType ( ) ) method = method . original ( ) ; MethodBinding inheritedOriginal = method . findOriginalInheritedMethod ( inheritedMethod ) ; return isParameterSubsignature ( method , inheritedOriginal == null ? inheritedMethod : inheritedOriginal ) ; } boolean isParameterSubsignature ( MethodBinding method , MethodBinding inheritedMethod ) { MethodBinding substitute = computeSubstituteMethod ( inheritedMethod , method ) ; return substitute != null && isSubstituteParameterSubsignature ( method , substitute ) ; } boolean isSubstituteParameterSubsignature ( MethodBinding method , MethodBinding substituteMethod ) { if ( ! areParametersEqual ( method , substituteMethod ) ) { if ( substituteMethod . hasSubstitutedParameters ( ) && method . areParameterErasuresEqual ( substituteMethod ) ) return method . typeVariables == Binding . NO_TYPE_VARIABLES && ! hasGenericParameter ( method ) ; if ( method . declaringClass . isRawType ( ) && substituteMethod . declaringClass . isRawType ( ) ) if ( method . hasSubstitutedParameters ( ) && substituteMethod . hasSubstitutedParameters ( ) ) return areMethodsCompatible ( method , substituteMethod ) ; return false ; } if ( substituteMethod instanceof ParameterizedGenericMethodBinding ) { if ( method . typeVariables != Binding . NO_TYPE_VARIABLES ) return ! ( ( ParameterizedGenericMethodBinding ) substituteMethod ) . isRaw ; return ! hasGenericParameter ( method ) ; } return method . typeVariables == Binding . NO_TYPE_VARIABLES ; } boolean isUnsafeReturnTypeOverride ( MethodBinding currentMethod , MethodBinding inheritedMethod ) { if ( currentMethod . returnType == inheritedMethod . returnType . erasure ( ) ) { TypeBinding [ ] currentParams = currentMethod . parameters ; TypeBinding [ ] inheritedParams = inheritedMethod . parameters ; for ( int i = 0 , l = currentParams . length ; i < l ; i ++ ) if ( ! areTypesEqual ( currentParams [ i ] , inheritedParams [ i ] ) ) return true ; } if ( currentMethod . typeVariables == Binding . NO_TYPE_VARIABLES && inheritedMethod . original ( ) . typeVariables != Binding . NO_TYPE_VARIABLES && currentMethod . returnType . erasure ( ) . findSuperTypeOriginatingFrom ( inheritedMethod . returnType . erasure ( ) ) != null ) { return true ; } return false ; } boolean reportIncompatibleReturnTypeError ( MethodBinding currentMethod , MethodBinding inheritedMethod ) { if ( isUnsafeReturnTypeOverride ( currentMethod , inheritedMethod ) ) { problemReporter ( currentMethod ) . unsafeReturnTypeOverride ( currentMethod , inheritedMethod , this . type ) ; return false ; } return super . reportIncompatibleReturnTypeError ( currentMethod , inheritedMethod ) ; } void verify ( ) { if ( this . type . isAnnotationType ( ) ) this . type . detectAnnotationCycle ( ) ; super . verify ( ) ; reportRawReferences ( ) ; for ( int i = this . type . typeVariables . length ; -- i >= 0 ; ) { TypeVariableBinding var = this . type . typeVariables [ i ] ; if ( var . superInterfaces == Binding . NO_SUPERINTERFACES ) continue ; if ( var . superInterfaces . length == 1 && var . superclass . id == TypeIds . T_JavaLangObject ) continue ; this . currentMethods = new HashtableOfObject ( 0 ) ; ReferenceBinding superclass = var . superclass ( ) ; if ( superclass . kind ( ) == Binding . TYPE_PARAMETER ) superclass = ( ReferenceBinding ) superclass . erasure ( ) ; ReferenceBinding [ ] itsInterfaces = var . superInterfaces ( ) ; ReferenceBinding [ ] superInterfaces = new ReferenceBinding [ itsInterfaces . length ] ; for ( int j = itsInterfaces . length ; -- j >= 0 ; ) { superInterfaces [ j ] = itsInterfaces [ j ] . kind ( ) == Binding . TYPE_PARAMETER ? ( ReferenceBinding ) itsInterfaces [ j ] . erasure ( ) : itsInterfaces [ j ] ; } computeInheritedMethods ( superclass , superInterfaces ) ; checkTypeVariableMethods ( this . type . scope . referenceContext . typeParameters [ i ] ) ; } } } </s>