public boolean matchesParams(String[] params, String[] dimensions, boolean varargs) {
    if (mParamStrings == null) {
      if (mParameters.size() != params.length) {
        return false;
      }
      int i = 0;
      for (ParameterInfo mine : mParameters) {
        if (!mine.matchesDimension(dimensions[i], varargs)) {
          return false;
        }
        TypeInfo myType = mine.type();
        String qualifiedName = myType.qualifiedTypeName();
        String realType = myType.isPrimitive() ? "" : myType.asClassInfo().qualifiedName();
        String s = params[i];
        int slen = s.length();
        int qnlen = qualifiedName.length();

        // Check for a matching generic name or best known type
        if (!matchesType(qualifiedName, s) && !matchesType(realType, s)) {
          return false;
        }
        i++;
      }
    }
    return true;
  }
  public boolean isConsistent(MethodInfo mInfo) {
    boolean consistent = true;
    if (this.mReturnType != mInfo.mReturnType && !this.mReturnType.equals(mInfo.mReturnType)) {
      if (!mReturnType.isPrimitive() && !mInfo.mReturnType.isPrimitive()) {
        // Check to see if our class extends the old class.
        ApiInfo infoApi = mInfo.containingClass().containingPackage().containingApi();
        ClassInfo infoReturnClass = infoApi.findClass(mInfo.mReturnType.qualifiedTypeName());
        // Find the classes.
        consistent =
            infoReturnClass != null
                && infoReturnClass.isAssignableTo(mReturnType.qualifiedTypeName());
      } else {
        consistent = false;
      }

      if (!consistent) {
        Errors.error(
            Errors.CHANGED_TYPE,
            mInfo.position(),
            "Method "
                + mInfo.qualifiedName()
                + " has changed return type from "
                + mReturnType
                + " to "
                + mInfo.mReturnType);
      }
    }

    if (mIsAbstract != mInfo.mIsAbstract) {
      consistent = false;
      Errors.error(
          Errors.CHANGED_ABSTRACT,
          mInfo.position(),
          "Method " + mInfo.qualifiedName() + " has changed 'abstract' qualifier");
    }

    if (mIsNative != mInfo.mIsNative) {
      consistent = false;
      Errors.error(
          Errors.CHANGED_NATIVE,
          mInfo.position(),
          "Method " + mInfo.qualifiedName() + " has changed 'native' qualifier");
    }

    if (!mIsStatic) {
      // Compiler-generated methods vary in their 'final' qualifier between versions of
      // the compiler, so this check needs to be quite narrow. A change in 'final'
      // status of a method is only relevant if (a) the method is not declared 'static'
      // and (b) the method is not already inferred to be 'final' by virtue of its class.
      if (!isEffectivelyFinal() && mInfo.isEffectivelyFinal()) {
        consistent = false;
        Errors.error(
            Errors.ADDED_FINAL,
            mInfo.position(),
            "Method " + mInfo.qualifiedName() + " has added 'final' qualifier");
      } else if (isEffectivelyFinal() && !mInfo.isEffectivelyFinal()) {
        consistent = false;
        Errors.error(
            Errors.REMOVED_FINAL,
            mInfo.position(),
            "Method " + mInfo.qualifiedName() + " has removed 'final' qualifier");
      }
    }

    if (mIsStatic != mInfo.mIsStatic) {
      consistent = false;
      Errors.error(
          Errors.CHANGED_STATIC,
          mInfo.position(),
          "Method " + mInfo.qualifiedName() + " has changed 'static' qualifier");
    }

    if (!scope().equals(mInfo.scope())) {
      consistent = false;
      Errors.error(
          Errors.CHANGED_SCOPE,
          mInfo.position(),
          "Method "
              + mInfo.qualifiedName()
              + " changed scope from "
              + scope()
              + " to "
              + mInfo.scope());
    }

    if (!isDeprecated() == mInfo.isDeprecated()) {
      Errors.error(
          Errors.CHANGED_DEPRECATED,
          mInfo.position(),
          "Method "
              + mInfo.qualifiedName()
              + " has changed deprecation state "
              + isDeprecated()
              + " --> "
              + mInfo.isDeprecated());
      consistent = false;
    }

    // see JLS 3 13.4.20 "Adding or deleting a synchronized modifier of a method does not break "
    // "compatibility with existing binaries."
    /*
    if (mIsSynchronized != mInfo.mIsSynchronized) {
      Errors.error(Errors.CHANGED_SYNCHRONIZED, mInfo.position(), "Method " + mInfo.qualifiedName()
          + " has changed 'synchronized' qualifier from " + mIsSynchronized + " to "
          + mInfo.mIsSynchronized);
      consistent = false;
    }
    */

    for (ClassInfo exception : thrownExceptions()) {
      if (!mInfo.throwsException(exception)) {
        // exclude 'throws' changes to finalize() overrides with no arguments
        if (!name().equals("finalize") || (!mParameters.isEmpty())) {
          Errors.error(
              Errors.CHANGED_THROWS,
              mInfo.position(),
              "Method "
                  + mInfo.qualifiedName()
                  + " no longer throws exception "
                  + exception.qualifiedName());
          consistent = false;
        }
      }
    }

    for (ClassInfo exec : mInfo.thrownExceptions()) {
      // exclude 'throws' changes to finalize() overrides with no arguments
      if (!throwsException(exec)) {
        if (!name().equals("finalize") || (!mParameters.isEmpty())) {
          Errors.error(
              Errors.CHANGED_THROWS,
              mInfo.position(),
              "Method "
                  + mInfo.qualifiedName()
                  + " added thrown exception "
                  + exec.qualifiedName());
          consistent = false;
        }
      }
    }

    return consistent;
  }