@Override
  public boolean processAddedMethods(DifferentiateContext context, Difference.Change<JvmClass, JvmClass.Diff> change, Iterable<JvmMethod> added, Utils future, Utils present) {
    JvmClass changedClass = change.getPast();
    if (changedClass.isAnnotation()) {
      debug("Class is annotation, skipping method analysis for added methods");
      return true;
    }

    debug("Processing added methods: ");
    for (JvmMethod addedMethod : added) {
      if (!addedMethod.isPrivate() && (changedClass.isInterface() || changedClass.isAbstract() || addedMethod.isAbstract())) {
        debug("Method: " + addedMethod.getName());
        debug("Class is abstract, or is interface, or added non-private method is abstract => affecting all subclasses");
        affectSubclasses(context, future, changedClass.getReferenceID(), false);
        break;
      }
    }

    for (JvmMethod addedMethod : added) {
      debug("Method: ", addedMethod.getName());

      if (addedMethod.isPrivate()) {
        continue;
      }

      Iterable<JvmNodeReferenceID> propagated = lazy(() -> {
        return future.collectSubclassesWithoutMethod(changedClass.getReferenceID(), addedMethod);
      });

      if (!isEmpty(addedMethod.getArgTypes()) && !present.hasOverriddenMethods(changedClass, addedMethod)) {
        debug("Conservative case on overriding methods, affecting method usages");
        context.affectUsage(asIterable(changedClass.getReferenceID()), addedMethod.createUsageQuery(changedClass.getReferenceID()));
        if (!addedMethod.isConstructor()) { // do not propagate constructors access, since constructors are always concrete and not accessible via references to subclasses
          for (JvmNodeReferenceID id : propagated) {
            context.affectUsage(asIterable(id), addedMethod.createUsageQuery(id));
          }
        }
      }

      if (addedMethod.isStatic() && !addedMethod.isStaticInitializer()) {
        affectStaticMemberOnDemandUsages(context, changedClass.getReferenceID(), propagated);
      }

      Predicate<JvmMethod> lessSpecificCond = future.lessSpecific(addedMethod);
      for (JvmMethod lessSpecific : filter(changedClass.getMethods(), lessSpecificCond::test)) {
        debug("Found less specific method, affecting method usages; ", lessSpecific.getName(), lessSpecific.getDescriptor());
        affectMemberUsages(context, changedClass.getReferenceID(), lessSpecific, present.collectSubclassesWithoutMethod(changedClass.getReferenceID(), lessSpecific));
      }

      debug("Processing affected by specificity methods");

      for (Pair<JvmClass, JvmMethod> pair : future.getOverriddenMethods(changedClass, lessSpecificCond)) {
        JvmClass cls = pair.getFirst();
        JvmMethod overriddenMethod = pair.getSecond();
        // isInheritor(cls, changedClass) == false

        debug("Method: ", overriddenMethod.getName());
        debug("Class : ", cls.getName());
        debug("Affecting method usages for that found");
        affectMemberUsages(context, changedClass.getReferenceID(), overriddenMethod, present.collectSubclassesWithoutMethod(changedClass.getReferenceID(), overriddenMethod));
      }

      for (Pair<JvmClass, JvmMethod> pair : future.getOverridingMethods(changedClass, addedMethod, lessSpecificCond)) {
        JvmClass cls = pair.getFirst();
        JvmMethod overridingMethod = pair.getSecond();
        // isInheritor(cls, changedClass) == true

        debug("Method: ", overridingMethod.getName());
        debug("Class : ", cls.getName());

        if (overridingMethod.isSameByJavaRules(addedMethod)) {
          debug("Current method overrides the added method");
          affectNodeSources(context, cls.getReferenceID(), "Affecting source ", future);
        }
        else {
          debug("Current method does not override the added method");
          debug("Affecting method usages for the method");
          affectMemberUsages(context, cls.getReferenceID(), overridingMethod, present.collectSubclassesWithoutMethod(cls.getReferenceID(), overridingMethod));
        }
      }

      for (ReferenceID subClassId : future.allSubclasses(changedClass.getReferenceID())) {
        Iterable<NodeSource> sources = context.getGraph().getSources(subClassId);
        if (!isEmpty(filter(sources, s -> !context.isCompiled(s)))) { // has non-compiled sources
          for (JvmClass outerClass : flat(map(future.getNodes(subClassId, JvmClass.class), cl -> {
            return future.getNodes(new JvmNodeReferenceID(cl.getOuterFqName()), JvmClass.class);
          }))) {
            if (future.isMethodVisible(outerClass, addedMethod)  || future.inheritsFromLibraryClass(outerClass)) {
              for (NodeSource source : filter(sources, context.getParams().affectionFilter()::test)) {
                debug("Affecting file due to local overriding: ", source);
                context.affectNodeSource(source);
              }
            }
          }
        }
      }

    }
    debug("End of added methods processing");
    return true;
  }
@Override
  public boolean processAddedMethods(DifferentiateContext context, Difference.Change<JvmClass, JvmClass.Diff> change, Iterable<JvmMethod> added, Utils future, Utils present)