Пример #1
0
  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);
    }
  }
Пример #2
0
  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);
          }
        }
      }
    }
  }
Пример #3
0
  /* 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;
  }