leftovers 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +49 -0
  3. data/README.md +28 -45
  4. data/docs/Configuration.md +598 -0
  5. data/exe/leftovers +2 -2
  6. data/leftovers.gemspec +13 -7
  7. data/lib/config/attr_encrypted.yml +3 -4
  8. data/lib/config/audited.yml +9 -0
  9. data/lib/config/datagrid.yml +1 -1
  10. data/lib/config/flipper.yml +1 -3
  11. data/lib/config/graphql.yml +15 -13
  12. data/lib/config/okcomputer.yml +1 -3
  13. data/lib/config/parser.yml +89 -91
  14. data/lib/config/rails.yml +162 -92
  15. data/lib/config/redcarpet.yml +35 -38
  16. data/lib/config/rollbar.yml +1 -3
  17. data/lib/config/rspec.yml +18 -10
  18. data/lib/config/ruby.yml +42 -39
  19. data/lib/config/selenium-webdriver.yml +19 -0
  20. data/lib/config/sidekiq.yml +9 -0
  21. data/lib/config/will_paginate.yml +12 -14
  22. data/lib/leftovers.rb +60 -43
  23. data/lib/leftovers/ast.rb +8 -0
  24. data/lib/leftovers/ast/builder.rb +6 -3
  25. data/lib/leftovers/ast/node.rb +63 -104
  26. data/lib/leftovers/backports.rb +24 -40
  27. data/lib/leftovers/cli.rb +17 -14
  28. data/lib/leftovers/collector.rb +7 -11
  29. data/lib/leftovers/config.rb +34 -13
  30. data/lib/leftovers/config_validator.rb +60 -0
  31. data/lib/leftovers/config_validator/error_processor.rb +196 -0
  32. data/lib/leftovers/config_validator/schema_hash.rb +495 -0
  33. data/lib/leftovers/definition.rb +14 -39
  34. data/lib/leftovers/definition_set.rb +7 -17
  35. data/lib/leftovers/dynamic_processors.rb +11 -0
  36. data/lib/leftovers/dynamic_processors/call.rb +25 -0
  37. data/lib/leftovers/dynamic_processors/call_definition.rb +31 -0
  38. data/lib/leftovers/dynamic_processors/definition.rb +26 -0
  39. data/lib/leftovers/dynamic_processors/each.rb +19 -0
  40. data/lib/leftovers/dynamic_processors/null.rb +9 -0
  41. data/lib/leftovers/erb.rb +2 -2
  42. data/lib/leftovers/file.rb +3 -5
  43. data/lib/leftovers/file_collector.rb +72 -85
  44. data/lib/leftovers/file_list.rb +9 -12
  45. data/lib/leftovers/haml.rb +9 -12
  46. data/lib/leftovers/matcher_builders.rb +24 -0
  47. data/lib/leftovers/matcher_builders/and.rb +19 -0
  48. data/lib/leftovers/matcher_builders/and_not.rb +14 -0
  49. data/lib/leftovers/matcher_builders/argument_node_value.rb +21 -0
  50. data/lib/leftovers/matcher_builders/name.rb +29 -0
  51. data/lib/leftovers/matcher_builders/node.rb +40 -0
  52. data/lib/leftovers/matcher_builders/node_has_argument.rb +71 -0
  53. data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +22 -0
  54. data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +24 -0
  55. data/lib/leftovers/matcher_builders/node_name.rb +15 -0
  56. data/lib/leftovers/matcher_builders/node_pair_name.rb +18 -0
  57. data/lib/leftovers/matcher_builders/node_pair_value.rb +16 -0
  58. data/lib/leftovers/matcher_builders/node_path.rb +14 -0
  59. data/lib/leftovers/matcher_builders/node_type.rb +28 -0
  60. data/lib/leftovers/matcher_builders/or.rb +73 -0
  61. data/lib/leftovers/matcher_builders/path.rb +15 -0
  62. data/lib/leftovers/matcher_builders/string.rb +11 -0
  63. data/lib/leftovers/matcher_builders/string_pattern.rb +19 -0
  64. data/lib/leftovers/matcher_builders/unless.rb +13 -0
  65. data/lib/leftovers/matchers.rb +26 -0
  66. data/lib/leftovers/matchers/all.rb +25 -0
  67. data/lib/leftovers/matchers/and.rb +24 -0
  68. data/lib/leftovers/matchers/any.rb +27 -0
  69. data/lib/leftovers/matchers/node_has_any_keyword_argument.rb +28 -0
  70. data/lib/leftovers/matchers/node_has_any_positional_argument_with_value.rb +25 -0
  71. data/lib/leftovers/matchers/node_has_positional_argument.rb +23 -0
  72. data/lib/leftovers/matchers/node_has_positional_argument_with_value.rb +25 -0
  73. data/lib/leftovers/matchers/node_name.rb +23 -0
  74. data/lib/leftovers/matchers/node_pair_value.rb +23 -0
  75. data/lib/leftovers/matchers/node_path.rb +23 -0
  76. data/lib/leftovers/matchers/node_scalar_value.rb +25 -0
  77. data/lib/leftovers/matchers/node_type.rb +23 -0
  78. data/lib/leftovers/matchers/not.rb +23 -0
  79. data/lib/leftovers/matchers/or.rb +26 -0
  80. data/lib/leftovers/merged_config.rb +20 -14
  81. data/lib/leftovers/parser.rb +37 -0
  82. data/lib/leftovers/processor_builders.rb +22 -0
  83. data/lib/leftovers/processor_builders/action.rb +63 -0
  84. data/lib/leftovers/processor_builders/add_prefix.rb +20 -0
  85. data/lib/leftovers/processor_builders/add_suffix.rb +20 -0
  86. data/lib/leftovers/processor_builders/argument.rb +25 -0
  87. data/lib/leftovers/processor_builders/dynamic.rb +27 -0
  88. data/lib/leftovers/processor_builders/each.rb +36 -0
  89. data/lib/leftovers/processor_builders/each_action.rb +51 -0
  90. data/lib/leftovers/processor_builders/each_dynamic.rb +54 -0
  91. data/lib/leftovers/processor_builders/each_for_definition_set.rb +36 -0
  92. data/lib/leftovers/processor_builders/itself.rb +13 -0
  93. data/lib/leftovers/processor_builders/keyword.rb +24 -0
  94. data/lib/leftovers/processor_builders/keyword_argument.rb +14 -0
  95. data/lib/leftovers/processor_builders/transform.rb +55 -0
  96. data/lib/leftovers/processor_builders/transform_chain.rb +24 -0
  97. data/lib/leftovers/processor_builders/transform_set.rb +47 -0
  98. data/lib/leftovers/processor_builders/value.rb +13 -0
  99. data/lib/leftovers/rake_task.rb +4 -4
  100. data/lib/leftovers/reporter.rb +1 -1
  101. data/lib/leftovers/value_processors.rb +40 -0
  102. data/lib/leftovers/value_processors/add_dynamic_prefix.rb +31 -0
  103. data/lib/leftovers/value_processors/add_dynamic_suffix.rb +31 -0
  104. data/lib/leftovers/value_processors/add_prefix.rb +20 -0
  105. data/lib/leftovers/value_processors/add_suffix.rb +20 -0
  106. data/lib/leftovers/value_processors/camelize.rb +24 -0
  107. data/lib/leftovers/value_processors/capitalize.rb +19 -0
  108. data/lib/leftovers/value_processors/deconstantize.rb +24 -0
  109. data/lib/leftovers/value_processors/delete_after.rb +22 -0
  110. data/lib/leftovers/value_processors/delete_before.rb +22 -0
  111. data/lib/leftovers/value_processors/delete_prefix.rb +26 -0
  112. data/lib/leftovers/value_processors/delete_suffix.rb +26 -0
  113. data/lib/leftovers/value_processors/demodulize.rb +24 -0
  114. data/lib/leftovers/value_processors/downcase.rb +19 -0
  115. data/lib/leftovers/value_processors/each.rb +21 -0
  116. data/lib/leftovers/value_processors/each_for_definition_set.rb +33 -0
  117. data/lib/leftovers/value_processors/each_keyword.rb +27 -0
  118. data/lib/leftovers/value_processors/each_keyword_argument.rb +27 -0
  119. data/lib/leftovers/value_processors/each_positional_argument.rb +24 -0
  120. data/lib/leftovers/value_processors/itself.rb +17 -0
  121. data/lib/leftovers/value_processors/keyword.rb +36 -0
  122. data/lib/leftovers/value_processors/keyword_argument.rb +36 -0
  123. data/lib/leftovers/value_processors/parameterize.rb +24 -0
  124. data/lib/leftovers/value_processors/placeholder.rb +18 -0
  125. data/lib/leftovers/value_processors/pluralize.rb +24 -0
  126. data/lib/leftovers/value_processors/positional_argument.rb +26 -0
  127. data/lib/leftovers/value_processors/replace_value.rb +18 -0
  128. data/lib/leftovers/value_processors/return_definition.rb +24 -0
  129. data/lib/leftovers/value_processors/return_string.rb +14 -0
  130. data/lib/leftovers/value_processors/singularize.rb +24 -0
  131. data/lib/leftovers/value_processors/split.rb +22 -0
  132. data/lib/leftovers/value_processors/swapcase.rb +19 -0
  133. data/lib/leftovers/value_processors/titleize.rb +24 -0
  134. data/lib/leftovers/value_processors/underscore.rb +24 -0
  135. data/lib/leftovers/value_processors/upcase.rb +19 -0
  136. data/lib/leftovers/version.rb +1 -1
  137. metadata +193 -29
  138. data/lib/config/selenium.yml +0 -21
  139. data/lib/leftovers/argument_rule.rb +0 -218
  140. data/lib/leftovers/core_ext.rb +0 -13
  141. data/lib/leftovers/hash_rule.rb +0 -40
  142. data/lib/leftovers/name_rule.rb +0 -53
  143. data/lib/leftovers/rule.rb +0 -74
  144. data/lib/leftovers/transform_rule.rb +0 -171
  145. data/lib/leftovers/value_rule.rb +0 -56
@@ -1,26 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'set'
4
- require_relative 'config'
5
4
  require 'fast_ignore'
6
5
 
7
6
  module Leftovers
8
7
  class MergedConfig
9
- def initialize
8
+ def initialize(load_defaults: false)
10
9
  @configs = []
11
10
  @loaded_configs = Set.new
12
- self.<< Leftovers::Config.new(:ruby)
13
- self.<< project_config
11
+ return unless load_defaults
12
+
13
+ self << :ruby
14
+ self << project_config
14
15
  load_bundled_gem_config
15
16
  end
16
17
 
17
18
  def <<(config)
19
+ config = Leftovers::Config.new(config) unless config.is_a?(Leftovers::Config)
18
20
  return if @loaded_configs.include?(config.name)
19
21
 
20
22
  unmemoize
21
23
  @configs << config
22
24
  @loaded_configs << config.name
23
- config.gems.each { |gem| self.<< Leftovers::Config.new(gem) }
25
+ config.gems.each { |gem| self << gem }
26
+ config.requires.each do |req|
27
+ Leftovers.try_require(req, message: "cannot require '#{req}' from #{config.name}.yml")
28
+ end
24
29
  end
25
30
 
26
31
  def project_config
@@ -31,7 +36,8 @@ module Leftovers
31
36
  remove_instance_variable(:@exclude_paths) if defined?(@exclude_paths)
32
37
  remove_instance_variable(:@include_paths) if defined?(@include_paths)
33
38
  remove_instance_variable(:@test_paths) if defined?(@test_paths)
34
- remove_instance_variable(:@rules) if defined?(@rules)
39
+ remove_instance_variable(:@dynamic) if defined?(@dynamic)
40
+ remove_instance_variable(:@keep) if defined?(@keep)
35
41
  end
36
42
 
37
43
  def exclude_paths
@@ -45,26 +51,26 @@ module Leftovers
45
51
  def test_paths
46
52
  @test_paths ||= FastIgnore.new(
47
53
  include_rules: @configs.flat_map(&:test_paths),
48
- gitignore: false
54
+ gitignore: false,
55
+ root: Leftovers.pwd
49
56
  )
50
57
  end
51
58
 
52
- def skip_rules
53
- @skip_rules ||= rules.select(&:skip?)
59
+ def dynamic
60
+ @dynamic ||= ::Leftovers::ProcessorBuilders::EachDynamic.build(@configs.map(&:dynamic))
54
61
  end
55
62
 
56
- def rules
57
- @rules ||= @configs.flat_map(&:rules)
63
+ def keep
64
+ @keep ||= ::Leftovers::MatcherBuilders::Or.build(@configs.map(&:keep))
58
65
  end
59
66
 
60
67
  private
61
68
 
62
69
  def load_bundled_gem_config
63
- Leftovers.try_require('bundler')
64
- return unless defined?(Bundler)
70
+ return unless Leftovers.try_require('bundler')
65
71
 
66
72
  Bundler.locked_gems.specs.each do |spec|
67
- self.<< Leftovers::Config.new(spec.name.to_sym)
73
+ self << spec.name
68
74
  end
69
75
  end
70
76
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'parser'
4
+ require 'parser/current'
5
+
6
+ module Leftovers
7
+ module Parser
8
+ class << self
9
+ # mostly copied from https://github.com/whitequark/parser/blob/master/lib/parser/base.rb
10
+ # but with our parser
11
+ def parse_with_comments(string, file = '(string)', line = 1)
12
+ PARSER.reset
13
+ source_buffer = ::Parser::CurrentRuby.send(
14
+ :setup_source_buffer, file, line, string, PARSER.default_encoding
15
+ )
16
+ PARSER.parse_with_comments(source_buffer)
17
+ end
18
+
19
+ private
20
+
21
+ # mostly copied from https://github.com/whitequark/parser/blob/master/lib/parser/base.rb
22
+ # but with our builder
23
+ def parser
24
+ p = ::Parser::CurrentRuby.new(Leftovers::AST::Builder.new)
25
+ p.diagnostics.all_errors_are_fatal = true
26
+ p.diagnostics.ignore_warnings = true
27
+
28
+ p.diagnostics.consumer = lambda do |diagnostic|
29
+ diagnostic
30
+ end
31
+
32
+ p
33
+ end
34
+ end
35
+ PARSER = parser
36
+ end
37
+ end
@@ -0,0 +1,22 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Leftovers
4
+ module ProcessorBuilders
5
+ autoload(:Action, "#{__dir__}/processor_builders/action")
6
+ autoload(:AddPrefix, "#{__dir__}/processor_builders/add_prefix")
7
+ autoload(:AddSuffix, "#{__dir__}/processor_builders/add_suffix")
8
+ autoload(:Argument, "#{__dir__}/processor_builders/argument")
9
+ autoload(:Dynamic, "#{__dir__}/processor_builders/dynamic")
10
+ autoload(:EachAction, "#{__dir__}/processor_builders/each_action")
11
+ autoload(:EachDynamic, "#{__dir__}/processor_builders/each_dynamic")
12
+ autoload(:EachForDefinitionSet, "#{__dir__}/processor_builders/each_for_definition_set")
13
+ autoload(:Each, "#{__dir__}/processor_builders/each")
14
+ autoload(:Itself, "#{__dir__}/processor_builders/itself")
15
+ autoload(:Keyword, "#{__dir__}/processor_builders/keyword")
16
+ autoload(:KeywordArgument, "#{__dir__}/processor_builders/keyword_argument")
17
+ autoload(:TransformChain, "#{__dir__}/processor_builders/transform_chain")
18
+ autoload(:TransformSet, "#{__dir__}/processor_builders/transform_set")
19
+ autoload(:Transform, "#{__dir__}/processor_builders/transform")
20
+ autoload(:Value, "#{__dir__}/processor_builders/value")
21
+ end
22
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ module ProcessorBuilders
5
+ module Action
6
+ def self.build(patterns, action)
7
+ ::Leftovers::ProcessorBuilders::EachAction.each_or_self(patterns) do |pattern|
8
+ case pattern
9
+ when ::String, ::Integer
10
+ ::Leftovers::ProcessorBuilders::Argument.build(pattern, final_transformer(action))
11
+ when ::Hash
12
+ build_from_hash_value(action, **pattern)
13
+ # :nocov:
14
+ else raise
15
+ # :nocov:
16
+ end
17
+ end
18
+ end
19
+
20
+ def self.final_transformer(action)
21
+ ::Leftovers::ProcessorBuilders::TransformSet.build_final(action)
22
+ end
23
+
24
+ def self.build_from_hash_value( # rubocop:disable Metrics/MethodLength, Metrics/ParameterLists
25
+ action,
26
+ arguments: nil,
27
+ keywords: nil,
28
+ itself: nil,
29
+ value: nil,
30
+ nested: nil,
31
+ recursive: nil,
32
+ **transform_args
33
+ )
34
+ transformer = ::Leftovers::ProcessorBuilders::TransformSet.build(transform_args, action)
35
+ if nested
36
+ transformer = ::Leftovers::ProcessorBuilders::Each.build([
37
+ ::Leftovers::ProcessorBuilders::Action.build(nested, action),
38
+ transformer
39
+ ])
40
+ end
41
+
42
+ if recursive
43
+ placeholder = ::Leftovers::ValueProcessors::Placeholder.new
44
+ transformer = ::Leftovers::ProcessorBuilders::Each.build(
45
+ [placeholder, transformer]
46
+ )
47
+ end
48
+
49
+ processor = ::Leftovers::ProcessorBuilders::EachAction.build([
50
+ ::Leftovers::ProcessorBuilders::Argument.build(arguments, transformer),
51
+ ::Leftovers::ProcessorBuilders::Keyword.build(keywords, transformer),
52
+ ::Leftovers::ProcessorBuilders::Itself.build(itself, transformer),
53
+ ::Leftovers::ProcessorBuilders::Value.build(value, transformer)
54
+ ])
55
+
56
+ return processor unless recursive
57
+
58
+ placeholder.processor = processor
59
+ placeholder
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ module ProcessorBuilders
5
+ module AddPrefix
6
+ def self.build(argument, then_processor)
7
+ case argument
8
+ when ::Hash
9
+ dynamic_prefix = ::Leftovers::ProcessorBuilders::Action.build(argument, :call)
10
+ ::Leftovers::ValueProcessors::AddDynamicPrefix.new(dynamic_prefix, then_processor)
11
+ when ::String
12
+ ::Leftovers::ValueProcessors::AddPrefix.new(argument, then_processor)
13
+ # :nocov:
14
+ else raise
15
+ # :nocov:
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ module ProcessorBuilders
5
+ module AddSuffix
6
+ def self.build(argument, then_processor)
7
+ case argument
8
+ when ::Hash
9
+ dynamic_suffix = ::Leftovers::ProcessorBuilders::Action.build(argument, :call)
10
+ ::Leftovers::ValueProcessors::AddDynamicSuffix.new(dynamic_suffix, then_processor)
11
+ when ::String
12
+ ::Leftovers::ValueProcessors::AddSuffix.new(argument, then_processor)
13
+ # :nocov:
14
+ else raise
15
+ # :nocov:
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ module ProcessorBuilders
5
+ module Argument
6
+ def self.build(patterns, then_processor) # rubocop:disable Metrics/MethodLength
7
+ ::Leftovers::ProcessorBuilders::EachAction.each_or_self(patterns) do |pattern|
8
+ case pattern
9
+ when ::Integer
10
+ ::Leftovers::ValueProcessors::PositionalArgument.new(pattern, then_processor)
11
+ when '*'
12
+ ::Leftovers::ValueProcessors::EachPositionalArgument.new(then_processor)
13
+ when '**'
14
+ ::Leftovers::ValueProcessors::EachKeywordArgument.new(then_processor)
15
+ when ::String, ::Hash
16
+ ::Leftovers::ProcessorBuilders::KeywordArgument.build(pattern, then_processor)
17
+ # :nocov:
18
+ else raise
19
+ # :nocov:
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,27 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Leftovers
4
+ module ProcessorBuilders
5
+ module Dynamic
6
+ def self.build(dynamic_rules) # rubocop:disable Metrics/MethodLength
7
+ ::Leftovers::ProcessorBuilders::EachDynamic.each_or_self(dynamic_rules) do |dynamic|
8
+ call = ::Leftovers::ProcessorBuilders::Action.build(dynamic.delete(:call), :call)
9
+ define = ::Leftovers::ProcessorBuilders::Action.build(dynamic.delete(:define), :define)
10
+ matcher = ::Leftovers::MatcherBuilders::Node.build(**dynamic)
11
+
12
+ # this nonsense saves a method call and array instantiation per method
13
+ if call && define
14
+ ::Leftovers::DynamicProcessors::CallDefinition.new(matcher, call, define)
15
+ elsif define
16
+ ::Leftovers::DynamicProcessors::Definition.new(matcher, define)
17
+ elsif call
18
+ ::Leftovers::DynamicProcessors::Call.new(matcher, call)
19
+ # :nocov:
20
+ else raise
21
+ # :nocov:
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ module ProcessorBuilders
5
+ module Each
6
+ def self.each_or_self(value, &block)
7
+ case value
8
+ # :nocov:
9
+ when nil then raise
10
+ # :nocov:
11
+ when Array then build(value.map(&block))
12
+ else build([yield(value)])
13
+ end
14
+ end
15
+
16
+ def self.build(processors)
17
+ processors = compact(processors)
18
+
19
+ case processors.length
20
+ # :nocov:
21
+ when 0 then raise
22
+ # :nocov:
23
+ when 1 then processors.first
24
+ else ::Leftovers::ValueProcessors::Each.new(processors)
25
+ end
26
+ end
27
+
28
+ def self.compact(processors)
29
+ processors.flatten!
30
+ processors.compact!
31
+
32
+ processors
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ module ProcessorBuilders
5
+ module EachAction
6
+ def self.each_or_self(value, &block)
7
+ case value
8
+ when nil then nil
9
+ when Array then build(value.map(&block))
10
+ else build([yield(value)])
11
+ end
12
+ end
13
+
14
+ def self.build(processors)
15
+ processors = compact(processors)
16
+
17
+ case processors.length
18
+ # :nocov:
19
+ when 0 then raise
20
+ # :nocov:
21
+ when 1 then processors.first
22
+ else ::Leftovers::ValueProcessors::Each.new(processors)
23
+ end
24
+ end
25
+
26
+ def self.flatten(value) # rubocop:disable Metrics/MethodLength
27
+ case value
28
+ when ::Leftovers::ValueProcessors::Each
29
+ ret = value.processors.map { |v| flatten(v) }
30
+ ret.flatten!(1)
31
+ ret
32
+ when Array
33
+ ret = value.map { |v| flatten(v) }
34
+ ret.flatten!(1)
35
+ ret
36
+ else
37
+ value
38
+ end
39
+ end
40
+
41
+ def self.compact(processors)
42
+ return processors if processors.length <= 1
43
+
44
+ processors = flatten(processors)
45
+ processors.compact!
46
+
47
+ processors
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ module ProcessorBuilders
5
+ module EachDynamic
6
+ def self.each_or_self(value, &block)
7
+ case value
8
+ when nil then ::Leftovers::DynamicProcessors::Null
9
+ when Array then build(value.map(&block))
10
+ else build([yield(value)])
11
+ end
12
+ end
13
+
14
+ def self.build(processors)
15
+ processors = compact(processors)
16
+
17
+ case processors.length
18
+ # :nocov:
19
+ when 0 then raise
20
+ # :nocov:
21
+ when 1 then processors.first
22
+ else ::Leftovers::DynamicProcessors::Each.new(processors)
23
+ end
24
+ end
25
+
26
+ def self.flatten(value) # rubocop:disable Metrics/MethodLength
27
+ case value
28
+ when ::Leftovers::DynamicProcessors::Each
29
+ ret = value.processors.map { |v| flatten(v) }
30
+ ret.flatten!(1)
31
+ ret
32
+ when Array
33
+ ret = value.map { |v| flatten(v) }
34
+ ret.flatten!(1)
35
+ ret
36
+ else
37
+ value
38
+ end
39
+ end
40
+
41
+ def self.compact(processors)
42
+ return processors if processors.length <= 1
43
+
44
+ processors = flatten(processors)
45
+
46
+ processors.reject! do |p|
47
+ p == ::Leftovers::DynamicProcessors::Null
48
+ end
49
+
50
+ processors
51
+ end
52
+ end
53
+ end
54
+ end