void checkAgainstInheritedMethods( MethodBinding currentMethod, MethodBinding[] methods, int length, MethodBinding[] allInheritedMethods) { CompilerOptions options = type.scope.compilerOptions(); // need to find the overridden methods to avoid blaming this type for issues which are already // reported against a supertype // but cannot ignore an overridden inherited method completely when it comes to checking for // bridge methods 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()) { // Cannot override a static method or hide an instance method problemReporter(currentMethod).staticAndInstanceConflict(currentMethod, inheritedMethod); continue nextMethod; } // want to tag currentMethod even if return types are not equal if (inheritedMethod.isAbstract()) { currentMethod.modifiers |= ExtraCompilerModifiers.AccImplementing | ExtraCompilerModifiers.AccOverriding; // with the above change an abstract method is tagged as implementing the inherited // abstract method // if (!currentMethod.isAbstract() && inheritedMethod.isAbstract()) { // if ((currentMethod.modifiers & CompilerModifiers.AccOverriding) == 0) // currentMethod.modifiers |= CompilerModifiers.AccImplementing; } else { currentMethod.modifiers |= ExtraCompilerModifiers.AccOverriding; } if (!areReturnTypesCompatible(currentMethod, inheritedMethod)) { if (!(currentMethod.returnType != null && currentMethod.returnType.isObjectLiteralType() && inheritedMethod.returnType != null && inheritedMethod.returnType.isObjectLiteralType())) if (reportIncompatibleReturnTypeError(currentMethod, inheritedMethod)) continue nextMethod; } if (!isAsVisible(currentMethod, inheritedMethod)) problemReporter(currentMethod).visibilityConflict(currentMethod, inheritedMethod); if (options.reportDeprecationWhenOverridingDeprecatedMethod && inheritedMethod.isViewedAsDeprecated()) { if (!currentMethod.isViewedAsDeprecated() || options.reportDeprecationInsideDeprecatedCode) { problemReporter(currentMethod) .overridesDeprecatedMethod(currentMethod, inheritedMethod); } } } checkForBridgeMethod(currentMethod, inheritedMethod, allInheritedMethods); } }
void checkAgainstInheritedMethods( MethodBinding currentMethod, MethodBinding[] methods, int length) { nextMethod: for (int i = length; --i >= 0; ) { MethodBinding inheritedMethod = methods[i]; if (currentMethod.isStatic() != inheritedMethod .isStatic()) { // Cannot override a static method or hide an instance method this.problemReporter(currentMethod) .staticAndInstanceConflict(currentMethod, inheritedMethod); continue nextMethod; } if (!currentMethod.isAbstract() && inheritedMethod.isAbstract()) { if ((currentMethod.modifiers & CompilerModifiers.AccOverriding) == 0) currentMethod.modifiers |= CompilerModifiers.AccImplementing; } else { currentMethod.modifiers |= CompilerModifiers.AccOverriding; } if (!areReturnTypesEqual(currentMethod, inheritedMethod)) { this.problemReporter(currentMethod).incompatibleReturnType(currentMethod, inheritedMethod); } else { if (currentMethod.thrownExceptions != NoExceptions) this.checkExceptions(currentMethod, inheritedMethod); if (inheritedMethod.isFinal()) this.problemReporter(currentMethod) .finalMethodCannotBeOverridden(currentMethod, inheritedMethod); if (!this.isAsVisible(currentMethod, inheritedMethod)) this.problemReporter(currentMethod).visibilityConflict(currentMethod, inheritedMethod); if (environment.options.reportDeprecationWhenOverridingDeprecatedMethod && inheritedMethod.isViewedAsDeprecated()) { if (!currentMethod.isViewedAsDeprecated() || environment.options.reportDeprecationInsideDeprecatedCode) { // check against the other inherited methods to see if they hide this inheritedMethod ReferenceBinding declaringClass = inheritedMethod.declaringClass; if (declaringClass.isInterface()) for (int j = length; --j >= 0; ) if (i != j && methods[j].declaringClass.implementsInterface(declaringClass, false)) continue nextMethod; this.problemReporter(currentMethod) .overridesDeprecatedMethod(currentMethod, inheritedMethod); } } } } }
/* Answer true if the method use is considered deprecated. * An access in the same compilation unit is allowed. */ public final boolean isMethodUseDeprecated( MethodBinding method, Scope scope, boolean isExplicitUse) { // ignore references insing Javadoc comments if ((this.bits & ASTNode.InsideJavadoc) == 0 && method.isOrEnclosedByPrivateType() && !scope.isDefinedInMethod(method)) { // ignore cases where method is used from inside itself (e.g. direct recursions) method.original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } // TODO (maxime) consider separating concerns between deprecation and access restriction. // Caveat: this was not the case when access restriction funtion was added. if (isExplicitUse && (method.modifiers & ExtraCompilerModifiers.AccRestrictedAccess) != 0) { // note: explicit constructors calls warnings are kept despite the 'new C1()' case (two // warnings, one on type, the other on constructor), because of the 'super()' case. AccessRestriction restriction = scope.environment().getAccessRestriction(method.declaringClass.erasure()); if (restriction != null) { scope .problemReporter() .forbiddenReference( method, this, restriction.classpathEntryType, restriction.classpathEntryName, restriction.getProblemId()); } } if (!method.isViewedAsDeprecated()) return false; // inside same unit - no report if (scope.isDefinedInSameUnit(method.declaringClass)) return false; // non explicit use and non explicitly deprecated - no report if (!isExplicitUse && (method.modifiers & ClassFileConstants.AccDeprecated) == 0) { return false; } // if context is deprecated, may avoid reporting if (!scope.compilerOptions().reportDeprecationInsideDeprecatedCode && scope.isInsideDeprecatedCode()) return false; return true; }