<s> package org . eclipse . jdt . internal . compiler . lookup ; import org . eclipse . jdt . internal . compiler . ast . * ; import org . eclipse . jdt . internal . compiler . classfmt . ClassFileConstants ; import org . eclipse . jdt . internal . compiler . impl . CompilerOptions ; import org . eclipse . jdt . internal . compiler . problem . ProblemReporter ; import org . eclipse . jdt . internal . compiler . util . HashtableOfObject ; import org . eclipse . jdt . internal . compiler . util . SimpleSet ; public class MethodVerifier { SourceTypeBinding type ; HashtableOfObject inheritedMethods ; HashtableOfObject currentMethods ; LookupEnvironment environment ; private boolean allowCompatibleReturnTypes ; MethodVerifier ( LookupEnvironment environment ) { this . type = null ; this . inheritedMethods = null ; this . currentMethods = null ; this . environment = environment ; this . allowCompatibleReturnTypes = environment . globalOptions . complianceLevel >= ClassFileConstants . JDK1_5 && environment . globalOptions . sourceLevel < ClassFileConstants . JDK1_5 ; } boolean areMethodsCompatible ( MethodBinding one , MethodBinding two ) { return isParameterSubsignature ( one , two ) && areReturnTypesCompatible ( 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 ; for ( int i = 0 ; i < length ; i ++ ) if ( ! areTypesEqual ( oneArgs [ i ] , twoArgs [ i ] ) ) return false ; return true ; } boolean areReturnTypesCompatible ( MethodBinding one , MethodBinding two ) { if ( one . returnType == two . returnType ) return true ; if ( areTypesEqual ( one . returnType , two . returnType ) ) return true ; if ( this . allowCompatibleReturnTypes && one . declaringClass instanceof BinaryTypeBinding && two . declaringClass instanceof BinaryTypeBinding ) { return areReturnTypesCompatible0 ( one , two ) ; } return false ; } boolean areReturnTypesCompatible0 ( MethodBinding one , MethodBinding two ) { if ( one . returnType . isBaseType ( ) ) return false ; if ( ! one . declaringClass . isInterface ( ) && one . declaringClass . id == TypeIds . T_JavaLangObject ) return two . returnType . isCompatibleWith ( one . returnType ) ; return one . returnType . isCompatibleWith ( two . returnType ) ; } boolean areTypesEqual ( TypeBinding one , TypeBinding two ) { if ( one == two ) return true ; if ( one instanceof UnresolvedReferenceBinding ) return ( ( UnresolvedReferenceBinding ) one ) . resolvedType == two ; if ( two instanceof UnresolvedReferenceBinding ) return ( ( UnresolvedReferenceBinding ) two ) . resolvedType == one ; return false ; } boolean canSkipInheritedMethods ( ) { if ( this . type . superclass ( ) != null && this . type . superclass ( ) . isAbstract ( ) ) return false ; return this . type . superInterfaces ( ) == Binding . NO_SUPERINTERFACES ; } boolean canSkipInheritedMethods ( MethodBinding one , MethodBinding two ) { return two == null || one . declaringClass == two . declaringClass ; } void checkAbstractMethod ( MethodBinding abstractMethod ) { if ( mustImplementAbstractMethod ( abstractMethod . declaringClass ) ) { TypeDeclaration typeDeclaration = this . type . scope . referenceContext ; if ( typeDeclaration != null ) { MethodDeclaration missingAbstractMethod = typeDeclaration . addMissingAbstractMethodFor ( abstractMethod ) ; missingAbstractMethod . scope . problemReporter ( ) . abstractMethodMustBeImplemented ( this . type , abstractMethod ) ; } else { problemReporter ( ) . abstractMethodMustBeImplemented ( this . type , abstractMethod ) ; } } } void checkAgainstInheritedMethods ( MethodBinding currentMethod , MethodBinding [ ] methods , int length , MethodBinding [ ] allInheritedMethods ) { if ( this . type . isAnnotationType ( ) ) { problemReporter ( ) . annotationCannotOverrideMethod ( currentMethod , methods [ length - 1 ] ) ; return ; } CompilerOptions options = this . type . scope . compilerOptions ( ) ; int [ ] overriddenInheritedMethods = length > 1 ? findOverriddenInheritedMethods ( methods , length ) : null ; nextMethod : for ( int i = length ; -- i >= 0 ; ) { MethodBinding inheritedMethod = methods [ i ] ; if ( overriddenInheritedMethods == null || overriddenInheritedMethods [ i ] == 0 ) { if ( currentMethod . isStatic ( ) != inheritedMethod . isStatic ( ) ) { problemReporter ( currentMethod ) . staticAndInstanceConflict ( currentMethod , inheritedMethod ) ; continue nextMethod ; } if ( inheritedMethod . isAbstract ( ) ) { if ( inheritedMethod . declaringClass . isInterface ( ) ) { currentMethod . modifiers |= ExtraCompilerModifiers . AccImplementing ; } else { currentMethod . modifiers |= ExtraCompilerModifiers . AccImplementing | ExtraCompilerModifiers . AccOverriding ; } } else if ( inheritedMethod . isPublic ( ) || ! this . type . isInterface ( ) ) { currentMethod . modifiers |= ExtraCompilerModifiers . AccOverriding ; } if ( ! areReturnTypesCompatible ( currentMethod , inheritedMethod ) && ( currentMethod . returnType . tagBits & TagBits . HasMissingType ) == 0 ) { if ( reportIncompatibleReturnTypeError ( currentMethod , inheritedMethod ) ) continue nextMethod ; } if ( currentMethod . thrownExceptions != Binding . NO_EXCEPTIONS ) checkExceptions ( currentMethod , inheritedMethod ) ; if ( inheritedMethod . isFinal ( ) ) problemReporter ( currentMethod ) . finalMethodCannotBeOverridden ( currentMethod , inheritedMethod ) ; if ( ! isAsVisible ( currentMethod , inheritedMethod ) ) problemReporter ( currentMethod ) . visibilityConflict ( currentMethod , inheritedMethod ) ; if ( inheritedMethod . isSynchronized ( ) && ! currentMethod . isSynchronized ( ) ) { problemReporter ( currentMethod ) . missingSynchronizedOnInheritedMethod ( currentMethod , inheritedMethod ) ; } if ( options . reportDeprecationWhenOverridingDeprecatedMethod && inheritedMethod . isViewedAsDeprecated ( ) ) { if ( ! currentMethod . isViewedAsDeprecated ( ) || options . reportDeprecationInsideDeprecatedCode ) { ReferenceBinding declaringClass = inheritedMethod . declaringClass ; if ( declaringClass . isInterface ( ) ) for ( int j = length ; -- j >= 0 ; ) if ( i != j && methods [ j ] . declaringClass . implementsInterface ( declaringClass , false ) ) continue nextMethod ; problemReporter ( currentMethod ) . overridesDeprecatedMethod ( currentMethod , inheritedMethod ) ; } } } checkForBridgeMethod ( currentMethod , inheritedMethod , allInheritedMethods ) ; } } void checkConcreteInheritedMethod ( MethodBinding concreteMethod , MethodBinding [ ] abstractMethods ) { if ( concreteMethod . isStatic ( ) ) problemReporter ( ) . staticInheritedMethodConflicts ( this . type , concreteMethod , abstractMethods ) ; if ( ! concreteMethod . isPublic ( ) ) { int index = 0 , length = abstractMethods . length ; if ( concreteMethod . isProtected ( ) ) { for ( ; index < length ; index ++ ) if ( abstractMethods [ index ] . isPublic ( ) ) break ; } else if ( concreteMethod . isDefault ( ) ) { for ( ; index < length ; index ++ ) if ( ! abstractMethods [ index ] . isDefault ( ) ) break ; } if ( index < length ) problemReporter ( ) . inheritedMethodReducesVisibility ( this . type , concreteMethod , abstractMethods ) ; } if ( concreteMethod . thrownExceptions != Binding . NO_EXCEPTIONS ) for ( int i = abstractMethods . length ; -- i >= 0 ; ) checkExceptions ( concreteMethod , abstractMethods [ i ] ) ; if ( concreteMethod . isOrEnclosedByPrivateType ( ) ) concreteMethod . original ( ) . modifiers |= ExtraCompilerModifiers . AccLocallyUsed ; } void checkExceptions ( MethodBinding newMethod , MethodBinding inheritedMethod ) { ReferenceBinding [ ] newExceptions = resolvedExceptionTypesFor ( newMethod ) ; ReferenceBinding [ ] inheritedExceptions = resolvedExceptionTypesFor ( inheritedMethod ) ; for ( int i = newExceptions . length ; -- i >= 0 ; ) { ReferenceBinding newException = newExceptions [ i ] ; int j = inheritedExceptions . length ; while ( -- j > - 1 && ! isSameClassOrSubclassOf ( newException , inheritedExceptions [ j ] ) ) { } if ( j == - 1 ) if ( ! newException . isUncheckedException ( false ) && ( newException . tagBits & TagBits . HasMissingType ) == 0 ) { problemReporter ( newMethod ) . incompatibleExceptionInThrowsClause ( this . type , newMethod , inheritedMethod , newException ) ; } } } void checkForBridgeMethod ( MethodBinding currentMethod , MethodBinding inheritedMethod , MethodBinding [ ] allInheritedMethods ) { } void checkForMissingHashCodeMethod ( ) { MethodBinding [ ] choices = this . type . getMethods ( TypeConstants . EQUALS ) ; boolean overridesEquals = false ; for ( int i = choices . length ; ! overridesEquals && -- i >= 0 ; ) overridesEquals = choices [ i ] . parameters . length == 1 && choices [ i ] . parameters [ 0 ] . id == TypeIds . T_JavaLangObject ; if ( overridesEquals ) { MethodBinding hashCodeMethod = this . type . getExactMethod ( TypeConstants . HASHCODE , Binding . NO_PARAMETERS , null ) ; if ( hashCodeMethod != null && hashCodeMethod . declaringClass . id == TypeIds . T_JavaLangObject ) this . problemReporter ( ) . shouldImplementHashcode ( this . type ) ; } } void checkForRedundantSuperinterfaces ( ReferenceBinding superclass , ReferenceBinding [ ] superInterfaces ) { if ( superInterfaces == Binding . NO_SUPERINTERFACES ) return ; SimpleSet interfacesToCheck = new SimpleSet ( superInterfaces . length ) ; next : for ( int i = 0 , l = superInterfaces . length ; i < l ; i ++ ) { ReferenceBinding toCheck = superInterfaces [ i ] ; for ( int j = 0 ; j < l ; j ++ ) { if ( i != j && toCheck . implementsInterface ( superInterfaces [ j ] , true ) ) { TypeReference [ ] refs = this . type . scope . referenceContext . superInterfaces ; for ( int r = 0 , rl = refs . length ; r < rl ; r ++ ) { if ( refs [ r ] . resolvedType == toCheck ) { problemReporter ( ) . redundantSuperInterface ( this . type , refs [ j ] , superInterfaces [ j ] , toCheck ) ; continue next ; } } } } interfacesToCheck . add ( toCheck ) ; } ReferenceBinding [ ] itsInterfaces = null ; SimpleSet inheritedInterfaces = new SimpleSet ( 5 ) ; ReferenceBinding superType = superclass ; while ( superType != null && superType . isValidBinding ( ) ) { if ( ( itsInterfaces = superType . superInterfaces ( ) ) != Binding . NO_SUPERINTERFACES ) { for ( int i = 0 , l = itsInterfaces . length ; i < l ; i ++ ) { ReferenceBinding inheritedInterface = itsInterfaces [ i ] ; if ( ! inheritedInterfaces . includes ( inheritedInterface ) && inheritedInterface . isValidBinding ( ) ) { if ( interfacesToCheck . includes ( inheritedInterface ) ) { TypeReference [ ] refs = this . type . scope . referenceContext . superInterfaces ; for ( int r = 0 , rl = refs . length ; r < rl ; r ++ ) { if ( refs [ r ] . resolvedType == inheritedInterface ) { problemReporter ( ) . redundantSuperInterface ( this . type , refs [ r ] , inheritedInterface , superType ) ; break ; } } } else { inheritedInterfaces . add ( inheritedInterface ) ; } } } } superType = superType . superclass ( ) ; } int nextPosition = inheritedInterfaces . elementSize ; if ( nextPosition == 0 ) return ; ReferenceBinding [ ] interfacesToVisit = new ReferenceBinding [ nextPosition ] ; inheritedInterfaces . asArray ( interfacesToVisit ) ; for ( int i = 0 ; i < nextPosition ; i ++ ) { superType = interfacesToVisit [ i ] ; 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 ) ; for ( int a = 0 ; a < itsLength ; a ++ ) { ReferenceBinding inheritedInterface = itsInterfaces [ a ] ; if ( ! inheritedInterfaces . includes ( inheritedInterface ) && inheritedInterface . isValidBinding ( ) ) { if ( interfacesToCheck . includes ( inheritedInterface ) ) { TypeReference [ ] refs = this . type . scope . referenceContext . superInterfaces ; for ( int r = 0 , rl = refs . length ; r < rl ; r ++ ) { if ( refs [ r ] . resolvedType == inheritedInterface ) { problemReporter ( ) . redundantSuperInterface ( this . type , refs [ r ] , inheritedInterface , superType ) ; break ; } } } else { inheritedInterfaces . add ( inheritedInterface ) ; interfacesToVisit [ nextPosition ++ ] = inheritedInterface ; } } } } } } void checkInheritedMethods ( MethodBinding [ ] methods , int length ) { MethodBinding concreteMethod = this . type . isInterface ( ) || methods [ 0 ] . isAbstract ( ) ? null : methods [ 0 ] ; if ( concreteMethod == null ) { MethodBinding bestAbstractMethod = length == 1 ? methods [ 0 ] : findBestInheritedAbstractMethod ( methods , length ) ; boolean noMatch = bestAbstractMethod == null ; if ( noMatch ) bestAbstractMethod = methods [ 0 ] ; if ( mustImplementAbstractMethod ( bestAbstractMethod . declaringClass ) ) { TypeDeclaration typeDeclaration = this . type . scope . referenceContext ; MethodBinding superclassAbstractMethod = methods [ 0 ] ; if ( superclassAbstractMethod == bestAbstractMethod || superclassAbstractMethod . declaringClass . isInterface ( ) ) { if ( typeDeclaration != null ) { MethodDeclaration missingAbstractMethod = typeDeclaration . addMissingAbstractMethodFor ( bestAbstractMethod ) ; missingAbstractMethod . scope . problemReporter ( ) . abstractMethodMustBeImplemented ( this . type , bestAbstractMethod ) ; } else { problemReporter ( ) . abstractMethodMustBeImplemented ( this . type , bestAbstractMethod ) ; } } else { if ( typeDeclaration != null ) { MethodDeclaration missingAbstractMethod = typeDeclaration . addMissingAbstractMethodFor ( bestAbstractMethod ) ; missingAbstractMethod . scope . problemReporter ( ) . abstractMethodMustBeImplemented ( this . type , bestAbstractMethod , superclassAbstractMethod ) ; } else { problemReporter ( ) . abstractMethodMustBeImplemented ( this . type , bestAbstractMethod , superclassAbstractMethod ) ; } } } else if ( noMatch ) { problemReporter ( ) . inheritedMethodsHaveIncompatibleReturnTypes ( this . type , methods , length ) ; } return ; } if ( length < 2 ) return ; int index = length ; while ( -- index > 0 && checkInheritedReturnTypes ( concreteMethod , methods [ index ] ) ) { } if ( index > 0 ) { MethodBinding bestAbstractMethod = findBestInheritedAbstractMethod ( methods , length ) ; if ( bestAbstractMethod == null ) problemReporter ( ) . inheritedMethodsHaveIncompatibleReturnTypes ( this . type , methods , length ) ; else problemReporter ( ) . abstractMethodMustBeImplemented ( this . type , bestAbstractMethod , concreteMethod ) ; return ; } MethodBinding [ ] abstractMethods = new MethodBinding [ length - 1 ] ; index = 0 ; for ( int i = 0 ; i < length ; i ++ ) if ( methods [ i ] . isAbstract ( ) ) abstractMethods [ index ++ ] = methods [ i ] ; if ( index == 0 ) return ; if ( index < abstractMethods . length ) System . arraycopy ( abstractMethods , 0 , abstractMethods = new MethodBinding [ index ] , 0 , index ) ; checkConcreteInheritedMethod ( concreteMethod , abstractMethods ) ; } boolean checkInheritedReturnTypes ( MethodBinding method , MethodBinding otherMethod ) { if ( areReturnTypesCompatible ( method , otherMethod ) ) return true ; if ( ! this . type . isInterface ( ) ) if ( method . declaringClass . isClass ( ) || ! this . type . implementsInterface ( method . declaringClass , false ) ) if ( otherMethod . declaringClass . isClass ( ) || ! this . type . implementsInterface ( otherMethod . declaringClass , false ) ) return true ; return false ; } 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 && skipInheritedMethods ) continue nextSelector ; if ( inherited . length == 1 && current == null ) { if ( mustImplementAbstractMethods && inherited [ 0 ] . isAbstract ( ) ) checkAbstractMethod ( inherited [ 0 ] ) ; continue nextSelector ; } int index = - 1 ; MethodBinding [ ] matchingInherited = new MethodBinding [ inherited . length ] ; if ( current != null ) { for ( int i = 0 , length1 = current . length ; i < length1 ; i ++ ) { MethodBinding currentMethod = current [ i ] ; for ( int j = 0 , length2 = inherited . length ; j < length2 ; j ++ ) { MethodBinding inheritedMethod = computeSubstituteMethod ( inherited [ j ] , currentMethod ) ; if ( inheritedMethod != null ) { if ( isParameterSubsignature ( currentMethod , inheritedMethod ) ) { matchingInherited [ ++ index ] = inheritedMethod ; inherited [ j ] = null ; } } } if ( index >= 0 ) { checkAgainstInheritedMethods ( currentMethod , matchingInherited , index + 1 , inherited ) ; while ( index >= 0 ) matchingInherited [ index -- ] = null ; } } } for ( int i = 0 , length = inherited . length ; i < length ; i ++ ) { MethodBinding inheritedMethod = inherited [ i ] ; if ( inheritedMethod == null ) continue ; if ( ! isOrEnclosedByPrivateType && current != null ) { inheritedMethod . original ( ) . modifiers |= ExtraCompilerModifiers . AccLocallyUsed ; } 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 ) { if ( isParameterSubsignature ( inheritedMethod , otherInheritedMethod ) ) { matchingInherited [ ++ index ] = otherInheritedMethod ; inherited [ j ] = null ; } } } if ( index == - 1 ) continue ; if ( index > 0 ) checkInheritedMethods ( matchingInherited , index + 1 ) ; else if ( mustImplementAbstractMethods && matchingInherited [ 0 ] . isAbstract ( ) ) checkAbstractMethod ( matchingInherited [ 0 ] ) ; while ( index >= 0 ) matchingInherited [ index -- ] = null ; } } } void checkPackagePrivateAbstractMethod ( MethodBinding abstractMethod ) { PackageBinding necessaryPackage = abstractMethod . declaringClass . fPackage ; if ( necessaryPackage == this . type . fPackage ) return ; ReferenceBinding superType = this . type . superclass ( ) ; char [ ] selector = abstractMethod . selector ; do { if ( ! superType . isValidBinding ( ) ) return ; if ( ! superType . isAbstract ( ) ) return ; if ( necessaryPackage == superType . fPackage ) { MethodBinding [ ] methods = superType . getMethods ( selector ) ; nextMethod : for ( int m = methods . length ; -- m >= 0 ; ) { MethodBinding method = methods [ m ] ; if ( method . isPrivate ( ) || method . isConstructor ( ) || method . isDefaultAbstract ( ) ) continue nextMethod ; if ( areMethodsCompatible ( method , abstractMethod ) ) return ; } } } while ( ( superType = superType . superclass ( ) ) != abstractMethod . declaringClass ) ; problemReporter ( ) . abstractMethodCannotBeOverridden ( this . type , abstractMethod ) ; } void computeInheritedMethods ( ) { ReferenceBinding superclass = this . type . isInterface ( ) ? this . type . scope . getJavaLangObject ( ) : this . type . superclass ( ) ; computeInheritedMethods ( superclass , this . type . superInterfaces ( ) ) ; checkForRedundantSuperinterfaces ( superclass , this . type . superInterfaces ( ) ) ; } void computeInheritedMethods ( ReferenceBinding superclass , ReferenceBinding [ ] superInterfaces ) { this . inheritedMethods = new HashtableOfObject ( 51 ) ; ReferenceBinding [ ] interfacesToVisit = null ; int nextPosition = 0 ; ReferenceBinding [ ] itsInterfaces = superInterfaces ; if ( itsInterfaces != Binding . NO_SUPERINTERFACES ) { nextPosition = itsInterfaces . length ; interfacesToVisit = itsInterfaces ; } ReferenceBinding superType = superclass ; HashtableOfObject nonVisibleDefaultMethods = new HashtableOfObject ( 3 ) ; while ( superType != null && superType . isValidBinding ( ) ) { 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 ; } } } MethodBinding [ ] methods = superType . unResolvedMethods ( ) ; nextMethod : for ( int m = methods . length ; -- m >= 0 ; ) { MethodBinding inheritedMethod = methods [ m ] ; if ( inheritedMethod . isPrivate ( ) || inheritedMethod . isConstructor ( ) || inheritedMethod . isDefaultAbstract ( ) ) continue nextMethod ; MethodBinding [ ] existingMethods = ( MethodBinding [ ] ) this . inheritedMethods . get ( inheritedMethod . selector ) ; if ( existingMethods != null ) { existing : for ( int i = 0 , length = existingMethods . length ; i < length ; i ++ ) { MethodBinding existingMethod = existingMethods [ i ] ; if ( existingMethod . declaringClass != inheritedMethod . declaringClass && areMethodsCompatible ( existingMethod , inheritedMethod ) && ! canOverridingMethodDifferInErasure ( existingMethod , inheritedMethod ) ) { if ( inheritedMethod . isDefault ( ) ) { if ( inheritedMethod . isAbstract ( ) ) { checkPackagePrivateAbstractMethod ( inheritedMethod ) ; } else if ( existingMethod . declaringClass . fPackage != inheritedMethod . declaringClass . fPackage ) { if ( this . type . fPackage == inheritedMethod . declaringClass . fPackage && ! areReturnTypesCompatible ( inheritedMethod , existingMethod ) ) continue existing ; } } continue nextMethod ; } } } if ( ! inheritedMethod . isDefault ( ) || inheritedMethod . declaringClass . fPackage == this . type . fPackage ) { if ( existingMethods == null ) { existingMethods = new MethodBinding [ ] { inheritedMethod } ; } else { int length = existingMethods . length ; System . arraycopy ( existingMethods , 0 , existingMethods = new MethodBinding [ length + 1 ] , 0 , length ) ; existingMethods [ length ] = inheritedMethod ; } this . inheritedMethods . put ( inheritedMethod . selector , existingMethods ) ; } else { MethodBinding [ ] nonVisible = ( MethodBinding [ ] ) nonVisibleDefaultMethods . get ( inheritedMethod . selector ) ; if ( nonVisible != null ) for ( int i = 0 , l = nonVisible . length ; i < l ; i ++ ) if ( areMethodsCompatible ( nonVisible [ i ] , inheritedMethod ) ) continue nextMethod ; if ( nonVisible == null ) { nonVisible = new MethodBinding [ ] { inheritedMethod } ; } else { int length = nonVisible . length ; System . arraycopy ( nonVisible , 0 , nonVisible = new MethodBinding [ length + 1 ] , 0 , length ) ; nonVisible [ length ] = inheritedMethod ; } nonVisibleDefaultMethods . put ( inheritedMethod . selector , nonVisible ) ; if ( inheritedMethod . isAbstract ( ) && ! this . type . isAbstract ( ) ) problemReporter ( ) . abstractMethodCannotBeOverridden ( this . type , inheritedMethod ) ; MethodBinding [ ] current = ( MethodBinding [ ] ) this . currentMethods . get ( inheritedMethod . selector ) ; if ( current != null && ! inheritedMethod . isStatic ( ) ) { foundMatch : for ( int i = 0 , length = current . length ; i < length ; i ++ ) { if ( ! current [ i ] . isStatic ( ) && areMethodsCompatible ( current [ i ] , inheritedMethod ) ) { problemReporter ( ) . overridesPackageDefaultMethod ( current [ i ] , inheritedMethod ) ; break foundMatch ; } } } } } superType = superType . superclass ( ) ; } if ( nextPosition == 0 ) return ; SimpleSet skip = findSuperinterfaceCollisions ( superclass , superInterfaces ) ; for ( int i = 0 ; i < nextPosition ; i ++ ) { superType = interfacesToVisit [ i ] ; if ( superType . isValidBinding ( ) ) { if ( skip != null && skip . includes ( superType ) ) continue ; 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 ; } } MethodBinding [ ] methods = superType . unResolvedMethods ( ) ; nextMethod : for ( int m = methods . length ; -- m >= 0 ; ) { MethodBinding inheritedMethod = methods [ m ] ; MethodBinding [ ] existingMethods = ( MethodBinding [ ] ) this . inheritedMethods . get ( inheritedMethod . selector ) ; if ( existingMethods == null ) { existingMethods = new MethodBinding [ ] { inheritedMethod } ; } else { int length = existingMethods . length ; for ( int e = 0 ; e < length ; e ++ ) if ( isInterfaceMethodImplemented ( inheritedMethod , existingMethods [ e ] , superType ) && ! canOverridingMethodDifferInErasure ( existingMethods [ e ] , inheritedMethod ) ) continue nextMethod ; System . arraycopy ( existingMethods , 0 , existingMethods = new MethodBinding [ length + 1 ] , 0 , length ) ; existingMethods [ length ] = inheritedMethod ; } this . inheritedMethods . put ( inheritedMethod . selector , existingMethods ) ; } } } } protected boolean canOverridingMethodDifferInErasure ( MethodBinding overridingMethod , MethodBinding inheritedMethod ) { return false ; } void computeMethods ( ) { MethodBinding [ ] methods = this . type . methods ( ) ; int size = methods . length ; this . currentMethods = new HashtableOfObject ( size == 0 ? 1 : size ) ; for ( int m = size ; -- m >= 0 ; ) { MethodBinding method = methods [ m ] ; if ( ! ( method . isConstructor ( ) || method . isDefaultAbstract ( ) ) ) { MethodBinding [ ] existingMethods = ( MethodBinding [ ] ) this . currentMethods . get ( method . selector ) ; if ( existingMethods == null ) existingMethods = new MethodBinding [ 1 ] ; else System . arraycopy ( existingMethods , 0 , ( existingMethods = new MethodBinding [ existingMethods . length + 1 ] ) , 0 , existingMethods . length - 1 ) ; existingMethods [ existingMethods . length - 1 ] = method ; this . currentMethods . put ( method . selector , existingMethods ) ; } } } MethodBinding computeSubstituteMethod ( MethodBinding inheritedMethod , MethodBinding currentMethod ) { if ( inheritedMethod == null ) return null ; if ( currentMethod . parameters . length != inheritedMethod . parameters . length ) return null ; return inheritedMethod ; } boolean couldMethodOverride ( MethodBinding method , MethodBinding inheritedMethod ) { if ( ! org . eclipse . jdt . core . compiler . CharOperation . equals ( method . selector , inheritedMethod . selector ) ) return false ; if ( method == inheritedMethod || method . isStatic ( ) || inheritedMethod . isStatic ( ) ) return false ; if ( inheritedMethod . isPrivate ( ) ) return false ; if ( inheritedMethod . isDefault ( ) && method . declaringClass . getPackage ( ) != inheritedMethod . declaringClass . getPackage ( ) ) return false ; if ( ! method . isPublic ( ) ) { if ( inheritedMethod . isPublic ( ) ) return false ; if ( inheritedMethod . isProtected ( ) && ! method . isProtected ( ) ) return false ; } return true ; } public boolean doesMethodOverride ( MethodBinding method , MethodBinding inheritedMethod ) { if ( ! couldMethodOverride ( method , inheritedMethod ) ) return false ; inheritedMethod = inheritedMethod . original ( ) ; TypeBinding match = method . declaringClass . findSuperTypeOriginatingFrom ( inheritedMethod . declaringClass ) ; if ( ! ( match instanceof ReferenceBinding ) ) return false ; return isParameterSubsignature ( method , inheritedMethod ) ; } SimpleSet findSuperinterfaceCollisions ( ReferenceBinding superclass , ReferenceBinding [ ] superInterfaces ) { return null ; } MethodBinding findBestInheritedAbstractMethod ( MethodBinding [ ] methods , int length ) { findMethod : for ( int i = 0 ; i < length ; i ++ ) { MethodBinding method = methods [ i ] ; if ( ! method . isAbstract ( ) ) continue findMethod ; for ( int j = 0 ; j < length ; j ++ ) { if ( i == j ) continue ; if ( ! checkInheritedReturnTypes ( method , methods [ j ] ) ) { if ( this . type . isInterface ( ) && methods [ j ] . declaringClass . id == TypeIds . T_JavaLangObject ) return method ; continue findMethod ; } } return method ; } return null ; } int [ ] findOverriddenInheritedMethods ( MethodBinding [ ] methods , int length ) { int [ ] toSkip = null ; int i = 0 ; ReferenceBinding declaringClass = methods [ i ] . declaringClass ; if ( ! declaringClass . isInterface ( ) ) { ReferenceBinding declaringClass2 = methods [ ++ i ] . declaringClass ; while ( declaringClass == declaringClass2 ) { if ( ++ i == length ) return null ; declaringClass2 = methods [ i ] . declaringClass ; } if ( ! declaringClass2 . isInterface ( ) ) { if ( declaringClass . fPackage != declaringClass2 . fPackage && methods [ i ] . isDefault ( ) ) return null ; toSkip = new int [ length ] ; do { toSkip [ i ] = - 1 ; if ( ++ i == length ) return toSkip ; declaringClass2 = methods [ i ] . declaringClass ; } while ( ! declaringClass2 . isInterface ( ) ) ; } } nextMethod : for ( ; i < length ; i ++ ) { if ( toSkip != null && toSkip [ i ] == - 1 ) continue nextMethod ; declaringClass = methods [ i ] . declaringClass ; for ( int j = i + 1 ; j < length ; j ++ ) { if ( toSkip != null && toSkip [ j ] == - 1 ) continue ; ReferenceBinding declaringClass2 = methods [ j ] . declaringClass ; if ( declaringClass == declaringClass2 ) continue ; if ( declaringClass . implementsInterface ( declaringClass2 , true ) ) { if ( toSkip == null ) toSkip = new int [ length ] ; toSkip [ j ] = - 1 ; } else if ( declaringClass2 . implementsInterface ( declaringClass , true ) ) { if ( toSkip == null ) toSkip = new int [ length ] ; toSkip [ i ] = - 1 ; continue nextMethod ; } } } return toSkip ; } boolean isAsVisible ( MethodBinding newMethod , MethodBinding inheritedMethod ) { if ( inheritedMethod . modifiers == newMethod . modifiers ) return true ; if ( newMethod . isPublic ( ) ) return true ; if ( inheritedMethod . isPublic ( ) ) return false ; if ( newMethod . isProtected ( ) ) return true ; if ( inheritedMethod . isProtected ( ) ) return false ; return ! newMethod . isPrivate ( ) ; } boolean isInterfaceMethodImplemented ( MethodBinding inheritedMethod , MethodBinding existingMethod , ReferenceBinding superType ) { return areParametersEqual ( existingMethod , inheritedMethod ) && existingMethod . declaringClass . implementsInterface ( superType , true ) ; } public boolean isMethodSubsignature ( MethodBinding method , MethodBinding inheritedMethod ) { return org . eclipse . jdt . core . compiler . CharOperation . equals ( method . selector , inheritedMethod . selector ) && isParameterSubsignature ( method , inheritedMethod ) ; } boolean isParameterSubsignature ( MethodBinding method , MethodBinding inheritedMethod ) { return areParametersEqual ( method , inheritedMethod ) ; } boolean isSameClassOrSubclassOf ( ReferenceBinding testClass , ReferenceBinding superclass ) { do { if ( testClass == superclass ) return true ; } while ( ( testClass = testClass . superclass ( ) ) != null ) ; return false ; } boolean mustImplementAbstractMethod ( ReferenceBinding declaringClass ) { if ( ! mustImplementAbstractMethods ( ) ) return false ; ReferenceBinding superclass = this . type . superclass ( ) ; if ( declaringClass . isClass ( ) ) { while ( superclass . isAbstract ( ) && superclass != declaringClass ) superclass = superclass . superclass ( ) ; } else { if ( this . type . implementsInterface ( declaringClass , false ) ) if ( ! superclass . implementsInterface ( declaringClass , true ) ) return true ; while ( superclass . isAbstract ( ) && ! superclass . implementsInterface ( declaringClass , false ) ) superclass = superclass . superclass ( ) ; } return superclass . isAbstract ( ) ; } boolean mustImplementAbstractMethods ( ) { return ! this . type . isInterface ( ) && ! this . type . isAbstract ( ) ; } ProblemReporter problemReporter ( ) { return this . type . scope . problemReporter ( ) ; } ProblemReporter problemReporter ( MethodBinding currentMethod ) { ProblemReporter reporter = problemReporter ( ) ; if ( currentMethod . declaringClass == this . type && currentMethod . sourceMethod ( ) != null ) reporter . referenceContext = currentMethod . sourceMethod ( ) ; return reporter ; } boolean reportIncompatibleReturnTypeError ( MethodBinding currentMethod , MethodBinding inheritedMethod ) { problemReporter ( currentMethod ) . incompatibleReturnType ( currentMethod , inheritedMethod ) ; return true ; } ReferenceBinding [ ] resolvedExceptionTypesFor ( MethodBinding method ) { ReferenceBinding [ ] exceptions = method . thrownExceptions ; if ( ( method . modifiers & ExtraCompilerModifiers . AccUnresolved ) == 0 ) return exceptions ; if ( ! ( method . declaringClass instanceof BinaryTypeBinding ) ) return Binding . NO_EXCEPTIONS ; for ( int i = exceptions . length ; -- i >= 0 ; ) exceptions [ i ] = ( ReferenceBinding ) BinaryTypeBinding . resolveType ( exceptions [ i ] , this . environment , true ) ; return exceptions ; } void verify ( ) { computeMethods ( ) ; computeInheritedMethods ( ) ; checkMethods ( ) ; if ( this . type . isClass ( ) ) checkForMissingHashCodeMethod ( ) ; } void verify ( SourceTypeBinding someType ) { if ( this . type == null ) { try { this . type = someType ; verify ( ) ; } finally { this . type = null ; } } else { this . environment . newMethodVerifier ( ) . verify ( someType ) ; } } public String toString ( ) { StringBuffer buffer = new StringBuffer ( 10 ) ; buffer . append ( "" ) ; buffer . append ( this . type . readableName ( ) ) ; buffer . append ( '\n' ) ; buffer . append ( "" ) ; buffer . append ( this . inheritedMethods ) ; return buffer . toString ( ) ; } } </s>