private void mergeInheritedOptions(
      SourceMethod method,
      MapperConfiguration mapperConfig,
      List<SourceMethod> availableMethods,
      List<SourceMethod> initializingMethods) {
    if (initializingMethods.contains(method)) {
      // cycle detected

      initializingMethods.add(method);

      messager.printMessage(
          method.getExecutable(),
          Message.INHERITCONFIGURATION_CYCLE,
          Strings.join(initializingMethods, " -> "));
      return;
    }

    initializingMethods.add(method);

    MappingOptions mappingOptions = method.getMappingOptions();
    List<SourceMethod> applicablePrototypeMethods = method.getApplicablePrototypeMethods();

    MappingOptions inverseMappingOptions =
        getInverseMappingOptions(availableMethods, method, initializingMethods, mapperConfig);

    MappingOptions templateMappingOptions =
        getTemplateMappingOptions(
            join(availableMethods, applicablePrototypeMethods),
            method,
            initializingMethods,
            mapperConfig);

    if (templateMappingOptions != null) {
      mappingOptions.applyInheritedOptions(
          templateMappingOptions, false, method, messager, typeFactory);
    } else if (inverseMappingOptions != null) {
      mappingOptions.applyInheritedOptions(
          inverseMappingOptions, true, method, messager, typeFactory);
    } else if (mapperConfig.getMappingInheritanceStrategy() == AUTO_INHERIT_FROM_CONFIG) {
      if (applicablePrototypeMethods.size() == 1) {
        mappingOptions.applyInheritedOptions(
            first(applicablePrototypeMethods).getMappingOptions(),
            false,
            method,
            messager,
            typeFactory);
      } else if (applicablePrototypeMethods.size() > 1) {
        messager.printMessage(
            method.getExecutable(),
            Message.INHERITCONFIGURATION_MULTIPLE_PROTOTYPE_METHODS_MATCH,
            Strings.join(applicablePrototypeMethods, ", "));
      }
    }

    mappingOptions.markAsFullyInitialized();
  }