# frozen_string_literal: true module Leftovers # rubocop:disable Metrics/ModuleLength class Error < ::StandardError; end module_function autoload(:AST, "#{__dir__}/leftovers/ast") autoload(:Backports, "#{__dir__}/leftovers/backports") autoload(:CLI, "#{__dir__}/leftovers/cli") autoload(:Collector, "#{__dir__}/leftovers/collector") autoload(:ConfigValidator, "#{__dir__}/leftovers/config_validator") autoload(:Config, "#{__dir__}/leftovers/config") autoload(:DefinitionSet, "#{__dir__}/leftovers/definition_set") autoload(:Definition, "#{__dir__}/leftovers/definition") autoload(:ERB, "#{__dir__}/leftovers/erb") autoload(:FileCollector, "#{__dir__}/leftovers/file_collector") autoload(:FileList, "#{__dir__}/leftovers/file_list") autoload(:File, "#{__dir__}/leftovers/file") autoload(:Haml, "#{__dir__}/leftovers/haml") autoload(:MatcherBuilders, "#{__dir__}/leftovers/matcher_builders") autoload(:Matchers, "#{__dir__}/leftovers/matchers") autoload(:MergedConfig, "#{__dir__}/leftovers/merged_config") autoload(:Parser, "#{__dir__}/leftovers/parser") autoload(:ProcessorBuilders, "#{__dir__}/leftovers/processor_builders") autoload(:RakeTask, "#{__dir__}/leftovers/rake_task") autoload(:Reporter, "#{__dir__}/leftovers/reporter") autoload(:DynamicProcessors, "#{__dir__}/leftovers/dynamic_processors") autoload(:ValueProcessors, "#{__dir__}/leftovers/value_processors") autoload(:VERSION, "#{__dir__}/leftovers/version") class << self attr_accessor :parallel, :progress alias_method :parallel?, :parallel alias_method :progress?, :progress end def stdout @stdout ||= $stdout end def stderr @stderr ||= $stderr end def config @config ||= Leftovers::MergedConfig.new(load_defaults: true) end def collector @collector ||= Leftovers::Collector.new end def reporter @reporter ||= Leftovers::Reporter.new end def leftovers @leftovers ||= begin collector.collect collector.definitions.reject(&:in_collection?) end end def run(stdout: StringIO.new, stderr: StringIO.new) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity @stdout = stdout @stderr = stderr return 0 if leftovers.empty? only_test = [] none = [] leftovers.sort_by(&:location_s).each do |definition| if !definition.test? && definition.in_test_collection? only_test << definition else none << definition end end unless only_test.empty? puts "\e[31mOnly directly called in tests:\e[0m" only_test.each { |definition| reporter.call(definition) } end unless none.empty? puts "\e[31mNot directly called at all:\e[0m" none.each { |definition| reporter.call(definition) } end 1 end def reset # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity remove_instance_variable(:@config) if defined?(@config) remove_instance_variable(:@collector) if defined?(@collector) remove_instance_variable(:@reporter) if defined?(@reporter) remove_instance_variable(:@leftovers) if defined?(@leftovers) remove_instance_variable(:@try_require) if defined?(@try_require) remove_instance_variable(:@stdout) if defined?(@stdout) remove_instance_variable(:@stderr) if defined?(@stderr) remove_instance_variable(:@parallel) if defined?(@parallel) remove_instance_variable(:@pwd) if defined?(@pwd) end def warn(message) stderr.puts("\e[2K#{message}") end def error(message) warn(message) exit 1 end def puts(message) stdout.puts("\e[2K#{message}") end def print(message) stdout.print(message) end def newline stdout.puts('') end def pwd @pwd ||= Pathname.new(Dir.pwd + '/') end def exit(status = 0) throw :leftovers_exit, status end def try_require(requirable, message: nil) # rubocop:disable Metrics/MethodLength @try_require ||= {} @try_require[requirable] = begin if @try_require.key?(requirable) @try_require[requirable] else require requirable true end rescue LoadError false end warn message if !@try_require[requirable] && message @try_require[requirable] end def each_or_self(value, &block) case value when nil then nil when Array then value.each(&block) else yield(value) end end end