class FactoryBot::Linter

def calculate_invalid_factories

def calculate_invalid_factories
  factories_to_lint.each_with_object(Hash.new([])) do |factory, result|
    errors = lint(factory)
    result[factory] |= errors unless errors.empty?
  end
end

def error_message

def error_message
  lines = invalid_factories.map { |_factory, exceptions|
    exceptions.map(&error_message_type)
  }.flatten
  <<~ERROR_MESSAGE.strip
    The following factories are invalid:
    #{lines.join("\n")}
  ERROR_MESSAGE
end

def error_message_type

def error_message_type
  if @verbose
    :verbose_message
  else
    :message
  end
end

def initialize(factories, strategy: :create, traits: false, verbose: false)

def initialize(factories, strategy: :create, traits: false, verbose: false)
  @factories_to_lint = factories
  @factory_strategy = strategy
  @traits = traits
  @verbose = verbose
  @invalid_factories = calculate_invalid_factories
end

def lint(factory)

def lint(factory)
  if @traits
    lint_factory(factory) + lint_traits(factory)
  else
    lint_factory(factory)
  end
end

def lint!

def lint!
  if invalid_factories.any?
    raise InvalidFactoryError, error_message
  end
end

def lint_factory(factory)

def lint_factory(factory)
  result = []
  begin
    FactoryBot.public_send(factory_strategy, factory.name)
  rescue => e
    result |= [FactoryError.new(e, factory)]
  end
  result
end

def lint_traits(factory)

def lint_traits(factory)
  result = []
  factory.definition.defined_traits.map(&:name).each do |trait_name|
    FactoryBot.public_send(factory_strategy, factory.name, trait_name)
  rescue => e
    result |= [FactoryTraitError.new(e, factory, trait_name)]
  end
  result
end