leftovers 0.2.2 → 0.4.2

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 (146) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +41 -0
  3. data/README.md +35 -49
  4. data/docs/Configuration.md +627 -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 -4
  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 +160 -97
  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 -49
  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 +61 -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 +66 -107
  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 +38 -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 +496 -0
  33. data/lib/leftovers/definition.rb +16 -41
  34. data/lib/leftovers/definition_node.rb +36 -0
  35. data/lib/leftovers/definition_set.rb +17 -24
  36. data/lib/leftovers/dynamic_processors.rb +11 -0
  37. data/lib/leftovers/dynamic_processors/call.rb +25 -0
  38. data/lib/leftovers/dynamic_processors/call_definition.rb +31 -0
  39. data/lib/leftovers/dynamic_processors/definition.rb +26 -0
  40. data/lib/leftovers/dynamic_processors/each.rb +19 -0
  41. data/lib/leftovers/dynamic_processors/null.rb +9 -0
  42. data/lib/leftovers/erb.rb +2 -2
  43. data/lib/leftovers/file.rb +3 -5
  44. data/lib/leftovers/file_collector.rb +82 -62
  45. data/lib/leftovers/file_list.rb +9 -15
  46. data/lib/leftovers/haml.rb +9 -12
  47. data/lib/leftovers/matcher_builders.rb +24 -0
  48. data/lib/leftovers/matcher_builders/and.rb +19 -0
  49. data/lib/leftovers/matcher_builders/and_not.rb +14 -0
  50. data/lib/leftovers/matcher_builders/argument_node_value.rb +21 -0
  51. data/lib/leftovers/matcher_builders/name.rb +29 -0
  52. data/lib/leftovers/matcher_builders/node.rb +40 -0
  53. data/lib/leftovers/matcher_builders/node_has_argument.rb +71 -0
  54. data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +22 -0
  55. data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +24 -0
  56. data/lib/leftovers/matcher_builders/node_name.rb +15 -0
  57. data/lib/leftovers/matcher_builders/node_pair_name.rb +18 -0
  58. data/lib/leftovers/matcher_builders/node_pair_value.rb +16 -0
  59. data/lib/leftovers/matcher_builders/node_path.rb +14 -0
  60. data/lib/leftovers/matcher_builders/node_type.rb +28 -0
  61. data/lib/leftovers/matcher_builders/or.rb +73 -0
  62. data/lib/leftovers/matcher_builders/path.rb +15 -0
  63. data/lib/leftovers/matcher_builders/string.rb +11 -0
  64. data/lib/leftovers/matcher_builders/string_pattern.rb +19 -0
  65. data/lib/leftovers/matcher_builders/unless.rb +13 -0
  66. data/lib/leftovers/matchers.rb +26 -0
  67. data/lib/leftovers/matchers/all.rb +25 -0
  68. data/lib/leftovers/matchers/and.rb +24 -0
  69. data/lib/leftovers/matchers/any.rb +27 -0
  70. data/lib/leftovers/matchers/node_has_any_keyword_argument.rb +28 -0
  71. data/lib/leftovers/matchers/node_has_any_positional_argument_with_value.rb +25 -0
  72. data/lib/leftovers/matchers/node_has_positional_argument.rb +23 -0
  73. data/lib/leftovers/matchers/node_has_positional_argument_with_value.rb +25 -0
  74. data/lib/leftovers/matchers/node_name.rb +23 -0
  75. data/lib/leftovers/matchers/node_pair_value.rb +23 -0
  76. data/lib/leftovers/matchers/node_path.rb +23 -0
  77. data/lib/leftovers/matchers/node_scalar_value.rb +25 -0
  78. data/lib/leftovers/matchers/node_type.rb +23 -0
  79. data/lib/leftovers/matchers/not.rb +23 -0
  80. data/lib/leftovers/matchers/or.rb +26 -0
  81. data/lib/leftovers/merged_config.rb +24 -14
  82. data/lib/leftovers/parser.rb +2 -5
  83. data/lib/leftovers/processor_builders.rb +22 -0
  84. data/lib/leftovers/processor_builders/action.rb +63 -0
  85. data/lib/leftovers/processor_builders/add_prefix.rb +20 -0
  86. data/lib/leftovers/processor_builders/add_suffix.rb +20 -0
  87. data/lib/leftovers/processor_builders/argument.rb +25 -0
  88. data/lib/leftovers/processor_builders/dynamic.rb +27 -0
  89. data/lib/leftovers/processor_builders/each.rb +36 -0
  90. data/lib/leftovers/processor_builders/each_action.rb +51 -0
  91. data/lib/leftovers/processor_builders/each_dynamic.rb +54 -0
  92. data/lib/leftovers/processor_builders/each_for_definition_set.rb +36 -0
  93. data/lib/leftovers/processor_builders/itself.rb +13 -0
  94. data/lib/leftovers/processor_builders/keyword.rb +24 -0
  95. data/lib/leftovers/processor_builders/keyword_argument.rb +14 -0
  96. data/lib/leftovers/processor_builders/transform.rb +55 -0
  97. data/lib/leftovers/processor_builders/transform_chain.rb +24 -0
  98. data/lib/leftovers/processor_builders/transform_set.rb +47 -0
  99. data/lib/leftovers/processor_builders/value.rb +13 -0
  100. data/lib/leftovers/rake_task.rb +4 -4
  101. data/lib/leftovers/reporter.rb +1 -1
  102. data/lib/leftovers/value_processors.rb +40 -0
  103. data/lib/leftovers/value_processors/add_dynamic_prefix.rb +31 -0
  104. data/lib/leftovers/value_processors/add_dynamic_suffix.rb +31 -0
  105. data/lib/leftovers/value_processors/add_prefix.rb +20 -0
  106. data/lib/leftovers/value_processors/add_suffix.rb +20 -0
  107. data/lib/leftovers/value_processors/camelize.rb +24 -0
  108. data/lib/leftovers/value_processors/capitalize.rb +19 -0
  109. data/lib/leftovers/value_processors/deconstantize.rb +24 -0
  110. data/lib/leftovers/value_processors/delete_after.rb +22 -0
  111. data/lib/leftovers/value_processors/delete_before.rb +22 -0
  112. data/lib/leftovers/value_processors/delete_prefix.rb +26 -0
  113. data/lib/leftovers/value_processors/delete_suffix.rb +26 -0
  114. data/lib/leftovers/value_processors/demodulize.rb +24 -0
  115. data/lib/leftovers/value_processors/downcase.rb +19 -0
  116. data/lib/leftovers/value_processors/each.rb +21 -0
  117. data/lib/leftovers/value_processors/each_for_definition_set.rb +29 -0
  118. data/lib/leftovers/value_processors/each_keyword.rb +27 -0
  119. data/lib/leftovers/value_processors/each_keyword_argument.rb +27 -0
  120. data/lib/leftovers/value_processors/each_positional_argument.rb +24 -0
  121. data/lib/leftovers/value_processors/itself.rb +17 -0
  122. data/lib/leftovers/value_processors/keyword.rb +36 -0
  123. data/lib/leftovers/value_processors/keyword_argument.rb +36 -0
  124. data/lib/leftovers/value_processors/parameterize.rb +24 -0
  125. data/lib/leftovers/value_processors/placeholder.rb +18 -0
  126. data/lib/leftovers/value_processors/pluralize.rb +24 -0
  127. data/lib/leftovers/value_processors/positional_argument.rb +26 -0
  128. data/lib/leftovers/value_processors/replace_value.rb +18 -0
  129. data/lib/leftovers/value_processors/return_definition.rb +26 -0
  130. data/lib/leftovers/value_processors/return_string.rb +14 -0
  131. data/lib/leftovers/value_processors/singularize.rb +24 -0
  132. data/lib/leftovers/value_processors/split.rb +22 -0
  133. data/lib/leftovers/value_processors/swapcase.rb +19 -0
  134. data/lib/leftovers/value_processors/titleize.rb +24 -0
  135. data/lib/leftovers/value_processors/underscore.rb +24 -0
  136. data/lib/leftovers/value_processors/upcase.rb +19 -0
  137. data/lib/leftovers/version.rb +1 -1
  138. metadata +190 -28
  139. data/lib/config/selenium.yml +0 -21
  140. data/lib/leftovers/argument_rule.rb +0 -219
  141. data/lib/leftovers/core_ext.rb +0 -13
  142. data/lib/leftovers/hash_rule.rb +0 -40
  143. data/lib/leftovers/name_rule.rb +0 -53
  144. data/lib/leftovers/rule.rb +0 -74
  145. data/lib/leftovers/transform_rule.rb +0 -171
  146. 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,30 @@ 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))
61
+ end
62
+
63
+ def keep
64
+ @keep ||= ::Leftovers::MatcherBuilders::Or.build(@configs.map(&:keep))
54
65
  end
55
66
 
56
- def rules
57
- @rules ||= @configs.flat_map(&:rules)
67
+ def test_only
68
+ @test_only ||= ::Leftovers::MatcherBuilders::Or.build(@configs.map(&:test_only))
58
69
  end
59
70
 
60
71
  private
61
72
 
62
73
  def load_bundled_gem_config
63
- Leftovers.try_require('bundler')
64
- return unless defined?(Bundler)
74
+ return unless Leftovers.try_require('bundler')
65
75
 
66
76
  Bundler.locked_gems.specs.each do |spec|
67
- self.<< Leftovers::Config.new(spec.name.to_sym)
77
+ self << spec.name
68
78
  end
69
79
  end
70
80
  end
@@ -3,9 +3,6 @@
3
3
  require 'parser'
4
4
  require 'parser/current'
5
5
 
6
- require_relative 'ast/builder'
7
- require_relative 'ast/node'
8
-
9
6
  module Leftovers
10
7
  module Parser
11
8
  class << self
@@ -23,13 +20,13 @@ module Leftovers
23
20
 
24
21
  # mostly copied from https://github.com/whitequark/parser/blob/master/lib/parser/base.rb
25
22
  # but with our builder
26
- def parser # rubocop:disable Metrics/MethodLength
23
+ def parser
27
24
  p = ::Parser::CurrentRuby.new(Leftovers::AST::Builder.new)
28
25
  p.diagnostics.all_errors_are_fatal = true
29
26
  p.diagnostics.ignore_warnings = true
30
27
 
31
28
  p.diagnostics.consumer = lambda do |diagnostic|
32
- warn(diagnostic.render)
29
+ diagnostic
33
30
  end
34
31
 
35
32
  p
@@ -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
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ module ProcessorBuilders
5
+ module EachForDefinitionSet
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::EachForDefinitionSet.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