leftovers 0.8.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (196) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -0
  3. data/README.md +7 -7
  4. data/docs/Configuration.md +169 -38
  5. data/docs/Custom-Precompilers.md +6 -0
  6. data/leftovers.gemspec +2 -1
  7. data/lib/config/actioncable.yml +36 -0
  8. data/lib/config/actionmailbox.yml +31 -0
  9. data/lib/config/actionmailer.yml +91 -12
  10. data/lib/config/actionpack.yml +139 -35
  11. data/lib/config/actiontext.yml +56 -0
  12. data/lib/config/actionview.yml +194 -44
  13. data/lib/config/activejob.yml +16 -10
  14. data/lib/config/activemodel.yml +195 -27
  15. data/lib/config/activerecord.yml +436 -88
  16. data/lib/config/activestorage.yml +26 -0
  17. data/lib/config/activesupport.yml +177 -24
  18. data/lib/config/leftovers.yml +48 -0
  19. data/lib/config/rails.yml +7 -3
  20. data/lib/config/railties.yml +7 -0
  21. data/lib/config/ruby.yml +438 -83
  22. data/lib/config/test-unit.yml +8 -0
  23. data/lib/leftovers/ast/array_node.rb +12 -0
  24. data/lib/leftovers/ast/block_node.rb +12 -0
  25. data/lib/leftovers/ast/builder.rb +24 -5
  26. data/lib/leftovers/ast/casgn_node.rb +20 -0
  27. data/lib/leftovers/ast/const_node.rb +15 -0
  28. data/lib/leftovers/ast/def_node.rb +15 -0
  29. data/lib/leftovers/ast/defs_node.rb +15 -0
  30. data/lib/leftovers/ast/false_node.rb +24 -0
  31. data/lib/leftovers/ast/has_arguments.rb +31 -0
  32. data/lib/leftovers/ast/hash_node.rb +17 -0
  33. data/lib/leftovers/ast/module_node.rb +16 -0
  34. data/lib/leftovers/ast/nil_node.rb +23 -0
  35. data/lib/leftovers/ast/node.rb +33 -90
  36. data/lib/leftovers/ast/numeric_node.rb +22 -0
  37. data/lib/leftovers/ast/send_node.rb +25 -0
  38. data/lib/leftovers/ast/str_node.rb +24 -0
  39. data/lib/leftovers/ast/sym_node.rb +25 -0
  40. data/lib/leftovers/ast/true_node.rb +24 -0
  41. data/lib/leftovers/ast/var_node.rb +14 -0
  42. data/lib/leftovers/ast/vasgn_node.rb +20 -0
  43. data/lib/leftovers/ast.rb +18 -0
  44. data/lib/leftovers/cli.rb +7 -1
  45. data/lib/leftovers/comparable_instance.rb +18 -0
  46. data/lib/leftovers/config_loader/argument_position_schema.rb +3 -1
  47. data/lib/leftovers/config_loader/array_schema.rb +53 -0
  48. data/lib/leftovers/config_loader/document_schema.rb +3 -2
  49. data/lib/leftovers/config_loader/dynamic_schema.rb +1 -0
  50. data/lib/leftovers/config_loader/has_receiver_schema.rb +15 -0
  51. data/lib/leftovers/config_loader/has_value_schema.rb +5 -1
  52. data/lib/leftovers/config_loader/keyword_argument_schema.rb +13 -0
  53. data/lib/leftovers/config_loader/regexp_schema.rb +27 -0
  54. data/lib/leftovers/config_loader/rule_pattern_schema.rb +3 -1
  55. data/lib/leftovers/config_loader/scalar_value_schema.rb +8 -0
  56. data/lib/leftovers/config_loader/schema.rb +10 -0
  57. data/lib/leftovers/config_loader/string_enum_schema.rb +1 -1
  58. data/lib/leftovers/config_loader/string_pattern_schema.rb +1 -1
  59. data/lib/leftovers/config_loader/transform_schema.rb +12 -6
  60. data/lib/leftovers/config_loader/value_matcher_condition_schema.rb +13 -0
  61. data/lib/leftovers/config_loader/value_matcher_schema.rb +4 -1
  62. data/lib/leftovers/config_loader/value_or_array_schema.rb +2 -34
  63. data/lib/leftovers/config_loader/value_processor_schema.rb +2 -2
  64. data/lib/leftovers/config_loader.rb +12 -4
  65. data/lib/leftovers/definition_collection.rb +37 -0
  66. data/lib/leftovers/definition_node.rb +8 -14
  67. data/lib/leftovers/definition_node_set.rb +10 -2
  68. data/lib/leftovers/file.rb +1 -1
  69. data/lib/leftovers/file_collector/comments_processor.rb +1 -1
  70. data/lib/leftovers/file_collector/node_processor.rb +7 -7
  71. data/lib/leftovers/file_collector.rb +26 -32
  72. data/lib/leftovers/file_list.rb +3 -2
  73. data/lib/leftovers/matcher_builders/and.rb +26 -9
  74. data/lib/leftovers/matcher_builders/node.rb +32 -20
  75. data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +3 -1
  76. data/lib/leftovers/matcher_builders/node_has_receiver.rb +12 -3
  77. data/lib/leftovers/matcher_builders/node_pair_key.rb +16 -0
  78. data/lib/leftovers/matcher_builders/node_type.rb +9 -9
  79. data/lib/leftovers/matcher_builders/node_value.rb +25 -9
  80. data/lib/leftovers/matcher_builders/or.rb +22 -7
  81. data/lib/leftovers/matcher_builders/path.rb +3 -1
  82. data/lib/leftovers/matcher_builders.rb +1 -1
  83. data/lib/leftovers/matchers/all.rb +4 -0
  84. data/lib/leftovers/matchers/and.rb +4 -0
  85. data/lib/leftovers/matchers/any.rb +2 -0
  86. data/lib/leftovers/matchers/node_has_any_keyword_argument.rb +7 -4
  87. data/lib/leftovers/matchers/node_has_any_positional_argument_with_value.rb +5 -4
  88. data/lib/leftovers/matchers/node_has_any_receiver.rb +13 -0
  89. data/lib/leftovers/matchers/node_has_positional_argument.rb +5 -1
  90. data/lib/leftovers/matchers/node_has_positional_argument_with_value.rb +6 -1
  91. data/lib/leftovers/matchers/node_has_receiver.rb +4 -0
  92. data/lib/leftovers/matchers/node_is_proc.rb +13 -0
  93. data/lib/leftovers/matchers/node_name.rb +9 -3
  94. data/lib/leftovers/matchers/node_pair_key.rb +23 -0
  95. data/lib/leftovers/matchers/node_pair_value.rb +7 -3
  96. data/lib/leftovers/matchers/node_path.rb +7 -3
  97. data/lib/leftovers/matchers/node_privacy.rb +7 -3
  98. data/lib/leftovers/matchers/node_scalar_value.rb +6 -1
  99. data/lib/leftovers/matchers/node_type.rb +7 -3
  100. data/lib/leftovers/matchers/not.rb +2 -0
  101. data/lib/leftovers/matchers/or.rb +2 -0
  102. data/lib/leftovers/matchers/path.rb +21 -0
  103. data/lib/leftovers/matchers.rb +4 -1
  104. data/lib/leftovers/merged_config.rb +26 -25
  105. data/lib/leftovers/parser.rb +7 -4
  106. data/lib/leftovers/precompilers.rb +5 -5
  107. data/lib/leftovers/processor_builders/action.rb +55 -37
  108. data/lib/leftovers/processor_builders/add_prefix.rb +18 -10
  109. data/lib/leftovers/processor_builders/add_suffix.rb +18 -10
  110. data/lib/leftovers/processor_builders/argument.rb +28 -11
  111. data/lib/leftovers/processor_builders/dynamic.rb +37 -31
  112. data/lib/leftovers/processor_builders/each.rb +82 -10
  113. data/lib/leftovers/processor_builders/itself.rb +2 -2
  114. data/lib/leftovers/processor_builders/keyword.rb +7 -6
  115. data/lib/leftovers/processor_builders/keyword_argument.rb +4 -2
  116. data/lib/leftovers/processor_builders/receiver.rb +13 -0
  117. data/lib/leftovers/processor_builders/transform.rb +55 -44
  118. data/lib/leftovers/processor_builders/transform_chain.rb +1 -1
  119. data/lib/leftovers/processor_builders/transform_set.rb +9 -29
  120. data/lib/leftovers/processor_builders/value.rb +4 -4
  121. data/lib/leftovers/processor_builders.rb +1 -3
  122. data/lib/leftovers/processors/add_call.rb +14 -0
  123. data/lib/leftovers/processors/add_definition_node.rb +16 -0
  124. data/lib/leftovers/processors/add_dynamic_prefix.rb +29 -0
  125. data/lib/leftovers/processors/add_dynamic_suffix.rb +29 -0
  126. data/lib/leftovers/{value_processors → processors}/add_prefix.rb +7 -3
  127. data/lib/leftovers/{value_processors → processors}/add_suffix.rb +7 -3
  128. data/lib/leftovers/processors/append_sym.rb +13 -0
  129. data/lib/leftovers/{value_processors → processors}/camelize.rb +7 -3
  130. data/lib/leftovers/{value_processors → processors}/capitalize.rb +7 -3
  131. data/lib/leftovers/{value_processors → processors}/deconstantize.rb +7 -3
  132. data/lib/leftovers/{value_processors → processors}/delete_after.rb +9 -5
  133. data/lib/leftovers/processors/delete_after_last.rb +26 -0
  134. data/lib/leftovers/processors/delete_before.rb +27 -0
  135. data/lib/leftovers/processors/delete_before_last.rb +27 -0
  136. data/lib/leftovers/{value_processors → processors}/delete_prefix.rb +7 -3
  137. data/lib/leftovers/{value_processors → processors}/delete_suffix.rb +7 -3
  138. data/lib/leftovers/{value_processors → processors}/demodulize.rb +7 -3
  139. data/lib/leftovers/{value_processors → processors}/downcase.rb +7 -3
  140. data/lib/leftovers/processors/each.rb +25 -0
  141. data/lib/leftovers/processors/each_for_definition_set.rb +33 -0
  142. data/lib/leftovers/processors/each_keyword.rb +29 -0
  143. data/lib/leftovers/processors/each_keyword_argument.rb +29 -0
  144. data/lib/leftovers/processors/each_positional_argument.rb +27 -0
  145. data/lib/leftovers/processors/each_positional_argument_from.rb +30 -0
  146. data/lib/leftovers/processors/eval.rb +16 -0
  147. data/lib/leftovers/processors/itself.rb +21 -0
  148. data/lib/leftovers/processors/keyword_argument.rb +30 -0
  149. data/lib/leftovers/processors/match_current_node.rb +26 -0
  150. data/lib/leftovers/processors/match_matched_node.rb +26 -0
  151. data/lib/leftovers/{value_processors → processors}/parameterize.rb +7 -3
  152. data/lib/leftovers/{value_processors → processors}/placeholder.rb +5 -4
  153. data/lib/leftovers/{value_processors → processors}/pluralize.rb +7 -3
  154. data/lib/leftovers/{value_processors → processors}/positional_argument.rb +8 -6
  155. data/lib/leftovers/processors/receiver.rb +24 -0
  156. data/lib/leftovers/{value_processors → processors}/replace_value.rb +7 -3
  157. data/lib/leftovers/processors/set_default_privacy.rb +21 -0
  158. data/lib/leftovers/processors/set_privacy.rb +23 -0
  159. data/lib/leftovers/{value_processors → processors}/singularize.rb +7 -3
  160. data/lib/leftovers/{value_processors → processors}/split.rb +8 -4
  161. data/lib/leftovers/{value_processors → processors}/swapcase.rb +7 -3
  162. data/lib/leftovers/{value_processors → processors}/titleize.rb +7 -3
  163. data/lib/leftovers/{value_processors → processors}/underscore.rb +7 -3
  164. data/lib/leftovers/{value_processors → processors}/upcase.rb +7 -3
  165. data/lib/leftovers/processors.rb +49 -0
  166. data/lib/leftovers/reporter.rb +2 -2
  167. data/lib/leftovers/version.rb +1 -1
  168. data/lib/leftovers.rb +3 -12
  169. metadata +99 -52
  170. data/lib/leftovers/dynamic_processors/call.rb +0 -22
  171. data/lib/leftovers/dynamic_processors/call_definition.rb +0 -34
  172. data/lib/leftovers/dynamic_processors/definition.rb +0 -27
  173. data/lib/leftovers/dynamic_processors/each.rb +0 -19
  174. data/lib/leftovers/dynamic_processors/null.rb +0 -9
  175. data/lib/leftovers/dynamic_processors/set_default_privacy.rb +0 -18
  176. data/lib/leftovers/dynamic_processors/set_privacy.rb +0 -23
  177. data/lib/leftovers/dynamic_processors.rb +0 -13
  178. data/lib/leftovers/matcher_builders/node_pair_name.rb +0 -18
  179. data/lib/leftovers/matchers/predicate.rb +0 -19
  180. data/lib/leftovers/processor_builders/each_action.rb +0 -51
  181. data/lib/leftovers/processor_builders/each_dynamic.rb +0 -50
  182. data/lib/leftovers/processor_builders/each_for_definition_set.rb +0 -40
  183. data/lib/leftovers/value_processors/add_dynamic_prefix.rb +0 -24
  184. data/lib/leftovers/value_processors/add_dynamic_suffix.rb +0 -24
  185. data/lib/leftovers/value_processors/delete_before.rb +0 -22
  186. data/lib/leftovers/value_processors/each.rb +0 -21
  187. data/lib/leftovers/value_processors/each_for_definition_set.rb +0 -23
  188. data/lib/leftovers/value_processors/each_keyword.rb +0 -27
  189. data/lib/leftovers/value_processors/each_keyword_argument.rb +0 -27
  190. data/lib/leftovers/value_processors/each_positional_argument.rb +0 -25
  191. data/lib/leftovers/value_processors/itself.rb +0 -17
  192. data/lib/leftovers/value_processors/keyword.rb +0 -28
  193. data/lib/leftovers/value_processors/keyword_argument.rb +0 -28
  194. data/lib/leftovers/value_processors/return_definition_node.rb +0 -14
  195. data/lib/leftovers/value_processors/return_sym.rb +0 -14
  196. data/lib/leftovers/value_processors.rb +0 -40
@@ -10,13 +10,16 @@ module Leftovers
10
10
  :NodeHasAnyPositionalArgumentWithValue,
11
11
  "#{__dir__}/matchers/node_has_any_positional_argument_with_value"
12
12
  )
13
+ autoload(:NodeHasAnyReceiver, "#{__dir__}/matchers/node_has_any_receiver")
13
14
  autoload(
14
15
  :NodeHasPositionalArgumentWithValue,
15
16
  "#{__dir__}/matchers/node_has_positional_argument_with_value"
16
17
  )
17
18
  autoload(:NodeHasPositionalArgument, "#{__dir__}/matchers/node_has_positional_argument")
18
19
  autoload(:NodeHasReceiver, "#{__dir__}/matchers/node_has_receiver")
20
+ autoload(:NodeIsProc, "#{__dir__}/matchers/node_is_proc")
19
21
  autoload(:NodeName, "#{__dir__}/matchers/node_name")
22
+ autoload(:NodePairKey, "#{__dir__}/matchers/node_pair_key")
20
23
  autoload(:NodePairValue, "#{__dir__}/matchers/node_pair_value")
21
24
  autoload(:NodePath, "#{__dir__}/matchers/node_path")
22
25
  autoload(:NodePrivacy, "#{__dir__}/matchers/node_privacy")
@@ -24,6 +27,6 @@ module Leftovers
24
27
  autoload(:NodeType, "#{__dir__}/matchers/node_type")
25
28
  autoload(:Not, "#{__dir__}/matchers/not")
26
29
  autoload(:Or, "#{__dir__}/matchers/or")
27
- autoload(:Predicate, "#{__dir__}/matchers/predicate")
30
+ autoload(:Path, "#{__dir__}/matchers/path")
28
31
  end
29
32
  end
@@ -5,12 +5,23 @@ require 'fast_ignore'
5
5
 
6
6
  module Leftovers
7
7
  class MergedConfig
8
+ MEMOIZED_IVARS = %i{
9
+ @exclude_paths
10
+ @include_paths
11
+ @test_paths
12
+ @precompilers
13
+ @dynamic
14
+ @keep
15
+ @test_only
16
+ }.freeze
17
+
8
18
  def initialize(load_defaults: false)
9
19
  @configs = []
10
20
  @loaded_configs = Set.new
11
21
  return unless load_defaults
12
22
 
13
23
  self << :ruby
24
+ self << :leftovers
14
25
  self << project_config
15
26
  self << project_todo
16
27
  load_bundled_gem_config
@@ -27,30 +38,6 @@ module Leftovers
27
38
  require_requires(config)
28
39
  end
29
40
 
30
- def project_config
31
- Leftovers::Config.new(:'.leftovers.yml', path: Leftovers.pwd + '.leftovers.yml')
32
- end
33
-
34
- def project_todo
35
- Leftovers::Config.new(:'.leftovers_todo.yml', path: Leftovers.pwd + '.leftovers_todo.yml')
36
- end
37
-
38
- MEMOIZED_IVARS = %i{
39
- @exclude_paths
40
- @include_paths
41
- @test_paths
42
- @precompilers
43
- @dynamic
44
- @keep
45
- @test_only
46
- }.freeze
47
-
48
- def unmemoize
49
- MEMOIZED_IVARS.each do |ivar|
50
- remove_instance_variable(ivar) if instance_variable_get(ivar)
51
- end
52
- end
53
-
54
41
  def exclude_paths
55
42
  @exclude_paths ||= @configs.flat_map(&:exclude_paths)
56
43
  end
@@ -68,7 +55,7 @@ module Leftovers
68
55
  end
69
56
 
70
57
  def dynamic
71
- @dynamic ||= ::Leftovers::ProcessorBuilders::EachDynamic.build(@configs.map(&:dynamic))
58
+ @dynamic ||= ::Leftovers::ProcessorBuilders::Each.build(@configs.map(&:dynamic))
72
59
  end
73
60
 
74
61
  def keep
@@ -81,6 +68,20 @@ module Leftovers
81
68
 
82
69
  private
83
70
 
71
+ def project_config
72
+ Leftovers::Config.new(:'.leftovers.yml', path: Leftovers.pwd + '.leftovers.yml')
73
+ end
74
+
75
+ def project_todo
76
+ Leftovers::Config.new(:'.leftovers_todo.yml', path: Leftovers.pwd + '.leftovers_todo.yml')
77
+ end
78
+
79
+ def unmemoize
80
+ MEMOIZED_IVARS.each do |ivar|
81
+ remove_instance_variable(ivar) if instance_variable_get(ivar)
82
+ end
83
+ end
84
+
84
85
  def require_requires(config)
85
86
  config.requires.each do |req|
86
87
  if req.is_a?(Hash) && req[:quiet]
@@ -10,14 +10,17 @@ module Leftovers
10
10
  # but with our parser
11
11
  def parse_with_comments(string, file = '(string)', line = 1)
12
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)
13
+ PARSER.parse_with_comments(new_source_buffer(string, file, line))
17
14
  end
18
15
 
19
16
  private
20
17
 
18
+ def new_source_buffer(string, file, line)
19
+ ::Parser::CurrentRuby.send(
20
+ :setup_source_buffer, file, line, string, PARSER.default_encoding
21
+ )
22
+ end
23
+
21
24
  # mostly copied from https://github.com/whitequark/parser/blob/master/lib/parser/base.rb
22
25
  # but with our builder
23
26
  def parser
@@ -23,11 +23,11 @@ module Leftovers
23
23
 
24
24
  def build_precompiler(format)
25
25
  case format
26
- when 'erb' then ::Leftovers::Precompilers::ERB
27
- when 'haml' then ::Leftovers::Precompilers::Haml
28
- when 'json' then ::Leftovers::Precompilers::JSON
29
- when 'slim' then ::Leftovers::Precompilers::Slim
30
- when 'yaml' then ::Leftovers::Precompilers::YAML
26
+ when :erb then ::Leftovers::Precompilers::ERB
27
+ when :haml then ::Leftovers::Precompilers::Haml
28
+ when :json then ::Leftovers::Precompilers::JSON
29
+ when :slim then ::Leftovers::Precompilers::Slim
30
+ when :yaml then ::Leftovers::Precompilers::YAML
31
31
  when Hash then constantize_precompiler(format[:custom])
32
32
  # :nocov:
33
33
  else raise Leftovers::UnexpectedCase, "Unhandled value #{format}"
@@ -4,12 +4,12 @@ module Leftovers
4
4
  module ProcessorBuilders
5
5
  module Action
6
6
  class << self
7
- def build(patterns, action)
8
- ::Leftovers::ProcessorBuilders::EachAction.each_or_self(patterns) do |pattern|
7
+ def build(patterns, final_processor)
8
+ ::Leftovers::ProcessorBuilders::Each.each_or_self(patterns) do |pattern|
9
9
  case pattern
10
10
  when ::String, ::Integer
11
- ::Leftovers::ProcessorBuilders::Argument.build(pattern, final_transformer(action))
12
- when ::Hash then build_from_hash_value(action, **pattern)
11
+ ::Leftovers::ProcessorBuilders::Argument.build(pattern, final_processor)
12
+ when ::Hash then build_from_hash_value(**pattern, final_processor: final_processor)
13
13
  # :nocov:
14
14
  else raise Leftovers::UnexpectedCase, "Unhandled value #{pattern.inspect}"
15
15
  # :nocov:
@@ -17,54 +17,72 @@ module Leftovers
17
17
  end
18
18
  end
19
19
 
20
- private
20
+ def build_from_hash_value( # rubocop:disable Metrics/ParameterLists
21
+ final_processor:,
22
+ arguments: nil,
23
+ keywords: nil,
24
+ itself: nil,
25
+ receiver: nil,
26
+ value: nil,
27
+ nested: nil,
28
+ recursive: nil,
29
+
30
+ has_arguments: nil,
31
+ has_receiver: nil,
32
+ unless_arg: nil, all: nil, any: nil,
33
+ **transform_args
34
+ )
35
+ processor = ::Leftovers::ProcessorBuilders::TransformSet.build(
36
+ transform_args, final_processor
37
+ )
38
+ processor = build_nested(nested, processor) if nested
39
+ recursive_placeholder, processor = build_recursive(processor) if recursive
40
+ processor = build_sources(arguments, keywords, itself, receiver, value, processor)
41
+ processor = build_matcher(has_arguments, has_receiver, unless_arg, all, any, processor)
42
+ return processor unless recursive
21
43
 
22
- def final_transformer(action)
23
- ::Leftovers::ProcessorBuilders::TransformSet.build_final(action)
44
+ recursive_placeholder.processor = processor
45
+ recursive_placeholder
24
46
  end
25
47
 
26
- def build_nested(nested, transformer, action)
48
+ private
49
+
50
+ def build_nested(nested, processor)
27
51
  ::Leftovers::ProcessorBuilders::Each.build([
28
- ::Leftovers::ProcessorBuilders::Action.build(nested, action),
29
- transformer
52
+ ::Leftovers::ProcessorBuilders::Action.build(nested, processor),
53
+ processor
30
54
  ])
31
55
  end
32
56
 
33
- def build_processor(arguments, keywords, itself, value, transformer)
34
- ::Leftovers::ProcessorBuilders::EachAction.build([
35
- ::Leftovers::ProcessorBuilders::Argument.build(arguments, transformer),
36
- ::Leftovers::ProcessorBuilders::Keyword.build(keywords, transformer),
37
- ::Leftovers::ProcessorBuilders::Itself.build(itself, transformer),
38
- ::Leftovers::ProcessorBuilders::Value.build(value, transformer)
57
+ def build_sources(arguments, keywords, itself, receiver, value, processor) # rubocop:disable Metrics/ParameterLists
58
+ ::Leftovers::ProcessorBuilders::Each.build([
59
+ ::Leftovers::ProcessorBuilders::Argument.build(arguments, processor),
60
+ ::Leftovers::ProcessorBuilders::Keyword.build(keywords, processor),
61
+ ::Leftovers::ProcessorBuilders::Itself.build(itself, processor),
62
+ ::Leftovers::ProcessorBuilders::Receiver.build(receiver, processor),
63
+ ::Leftovers::ProcessorBuilders::Value.build(value, processor)
39
64
  ])
40
65
  end
41
66
 
42
- def build_recursive(transformer)
43
- placeholder = ::Leftovers::ValueProcessors::Placeholder.new
44
- transformer = ::Leftovers::ProcessorBuilders::Each.build([placeholder, transformer])
67
+ def build_recursive(processor)
68
+ recursive_placeholder = ::Leftovers::Processors::Placeholder.new
69
+ processor = ::Leftovers::ProcessorBuilders::Each.build([recursive_placeholder, processor])
45
70
 
46
- [placeholder, transformer]
71
+ [recursive_placeholder, processor]
47
72
  end
48
73
 
49
- def build_from_hash_value( # rubocop:disable Metrics/ParameterLists
50
- action,
51
- arguments: nil,
52
- keywords: nil,
53
- itself: nil,
54
- value: nil,
55
- nested: nil,
56
- recursive: nil,
57
- **transform_args
58
- )
59
- transformer = ::Leftovers::ProcessorBuilders::TransformSet.build(transform_args, action)
60
- transformer = build_nested(nested, transformer, action) if nested
61
- placeholder, transformer = build_recursive(transformer) if recursive
62
- processor = build_processor(arguments, keywords, itself, value, transformer)
74
+ def build_matcher(has_arguments, has_receiver, unless_arg, all, any, processor) # rubocop:disable Metrics/ParameterLists
75
+ matcher = Leftovers::MatcherBuilders::Node.build_from_hash(
76
+ has_arguments: has_arguments,
77
+ has_receiver: has_receiver,
78
+ unless_arg: unless_arg,
79
+ all: all,
80
+ any: any
81
+ )
63
82
 
64
- return processor unless recursive
83
+ return processor unless matcher
65
84
 
66
- placeholder.processor = processor
67
- placeholder
85
+ ::Leftovers::Processors::MatchMatchedNode.new(matcher, processor)
68
86
  end
69
87
  end
70
88
  end
@@ -3,16 +3,24 @@
3
3
  module Leftovers
4
4
  module ProcessorBuilders
5
5
  module AddPrefix
6
- def self.build(argument, then_processor)
7
- case argument
8
- when ::Hash
9
- dynamic_prefix = ::Leftovers::ProcessorBuilders::Action.build(argument, :sym)
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 Leftovers::UnexpectedCase, "Unhandled value #{argument.inspect}"
15
- # :nocov:
6
+ class << self
7
+ def build(argument, then_processor)
8
+ case argument
9
+ when ::Hash then build_hash(argument, then_processor)
10
+ when ::String then ::Leftovers::Processors::AddPrefix.new(argument, then_processor)
11
+ # :nocov:
12
+ else raise Leftovers::UnexpectedCase, "Unhandled value #{argument.inspect}"
13
+ # :nocov:
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def build_hash(argument, then_processor)
20
+ dynamic_prefix = ::Leftovers::ProcessorBuilders::Action.build(
21
+ argument, ::Leftovers::Processors::AppendSym
22
+ )
23
+ ::Leftovers::Processors::AddDynamicPrefix.new(dynamic_prefix, then_processor)
16
24
  end
17
25
  end
18
26
  end
@@ -3,16 +3,24 @@
3
3
  module Leftovers
4
4
  module ProcessorBuilders
5
5
  module AddSuffix
6
- def self.build(argument, then_processor)
7
- case argument
8
- when ::Hash
9
- dynamic_suffix = ::Leftovers::ProcessorBuilders::Action.build(argument, :sym)
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 Leftovers::UnexpectedCase, "Unhandled value #{argument.inspect}"
15
- # :nocov:
6
+ class << self
7
+ def build(argument, then_processor)
8
+ case argument
9
+ when ::Hash then build_hash(argument, then_processor)
10
+ when ::String then ::Leftovers::Processors::AddSuffix.new(argument, then_processor)
11
+ # :nocov:
12
+ else raise Leftovers::UnexpectedCase, "Unhandled value #{argument.inspect}"
13
+ # :nocov:
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def build_hash(argument, then_processor)
20
+ dynamic_suffix = ::Leftovers::ProcessorBuilders::Action.build(
21
+ argument, ::Leftovers::Processors::AppendSym
22
+ )
23
+ ::Leftovers::Processors::AddDynamicSuffix.new(dynamic_suffix, then_processor)
16
24
  end
17
25
  end
18
26
  end
@@ -3,19 +3,36 @@
3
3
  module Leftovers
4
4
  module ProcessorBuilders
5
5
  module Argument
6
- def self.build(patterns, processor)
7
- ::Leftovers::ProcessorBuilders::EachAction.each_or_self(patterns) do |pat|
8
- case pat
9
- when ::Integer then ::Leftovers::ValueProcessors::PositionalArgument.new(pat, processor)
10
- when '*' then ::Leftovers::ValueProcessors::EachPositionalArgument.new(processor)
11
- when '**' then ::Leftovers::ValueProcessors::EachKeywordArgument.new(processor)
12
- when ::String, ::Hash
13
- ::Leftovers::ProcessorBuilders::KeywordArgument.build(pat, processor)
14
- # :nocov:
15
- else raise Leftovers::UnexpectedCase, "Unhandled value #{pat.inspect}"
16
- # :nocov:
6
+ class << self
7
+ def build(patterns, processor) # rubocop:disable Metrics/MethodLength
8
+ ::Leftovers::ProcessorBuilders::Each.each_or_self(patterns) do |pat|
9
+ case pat
10
+ when ::Integer then ::Leftovers::Processors::PositionalArgument.new(pat, processor)
11
+ when '*' then ::Leftovers::Processors::EachPositionalArgument.new(processor)
12
+ when '**' then ::Leftovers::Processors::EachKeywordArgument.new(processor)
13
+ when /\A(\d+)\+\z/
14
+ ::Leftovers::Processors::EachPositionalArgumentFrom.new(pat.to_i, processor)
15
+ when ::String
16
+ ::Leftovers::ProcessorBuilders::KeywordArgument.build(pat, processor)
17
+ when ::Hash
18
+ build_hash(processor, pat)
19
+ # :nocov:
20
+ else raise Leftovers::UnexpectedCase, "Unhandled value #{pat.inspect}"
21
+ # :nocov:
22
+ end
17
23
  end
18
24
  end
25
+
26
+ private
27
+
28
+ def build_hash(then_processor, pat)
29
+ ::Leftovers::Processors::KeywordArgument.new(
30
+ ::Leftovers::MatcherBuilders::NodePairKey.build(
31
+ ::Leftovers::MatcherBuilders::Node.build_from_hash(**pat)
32
+ ),
33
+ then_processor
34
+ )
35
+ end
19
36
  end
20
37
  end
21
38
  end
@@ -5,57 +5,63 @@ module Leftovers
5
5
  module Dynamic
6
6
  class << self
7
7
  def build(dynamic_rules)
8
- ::Leftovers::ProcessorBuilders::EachDynamic.each_or_self(dynamic_rules) do |dynamic|
8
+ ::Leftovers::ProcessorBuilders::Each.each_or_self(dynamic_rules) do |dynamic|
9
9
  build_processors(**dynamic)
10
10
  end
11
11
  end
12
12
 
13
13
  private
14
14
 
15
- def build_processors(
16
- call: nil, define: nil, set_privacy: nil, set_default_privacy: nil, **matcher_rules
15
+ def build_processors( # rubocop:disable Metrics/ParameterLists
16
+ call: nil, define: nil,
17
+ set_privacy: nil, set_default_privacy: nil,
18
+ eval: nil, **matcher_rules
17
19
  )
18
20
  matcher = ::Leftovers::MatcherBuilders::Node.build(**matcher_rules)
19
21
 
20
- call_action = build_action(call, return_type: :sym)
21
- define_action = build_action(define, return_type: :definition_node)
22
-
23
- ::Leftovers::ProcessorBuilders::EachDynamic.build([
24
- build_call_define_processor(matcher, call_action, define_action),
25
- build_set_privacy_processor(matcher, set_privacy),
26
- build_set_default_privacy_processor(matcher, set_default_privacy)
22
+ processor = ::Leftovers::ProcessorBuilders::Each.build([
23
+ build_call_action(call),
24
+ build_define_action(define),
25
+ build_set_privacy_action(set_privacy),
26
+ build_set_default_privacy_action(set_default_privacy),
27
+ build_eval_action(eval)
27
28
  ])
28
- end
29
29
 
30
- def build_action(processor_rules, return_type:)
31
- ::Leftovers::ProcessorBuilders::Action.build(processor_rules, return_type)
30
+ ::Leftovers::Processors::MatchMatchedNode.new(matcher, processor)
32
31
  end
33
32
 
34
- def build_set_privacy_processor(matcher, set_privacy)
35
- ::Leftovers::ProcessorBuilders::EachDynamic.each_or_self(set_privacy) do |action_values|
36
- to = action_values.delete(:to)
37
- action = build_action(action_values, return_type: :sym)
33
+ def build_call_action(call)
34
+ ::Leftovers::ProcessorBuilders::Action.build(
35
+ call, ::Leftovers::Processors::AddCall
36
+ )
37
+ end
38
38
 
39
- ::Leftovers::DynamicProcessors::SetPrivacy.new(matcher, action, to)
40
- end
39
+ def build_define_action(define)
40
+ ::Leftovers::ProcessorBuilders::Action.build(
41
+ define, ::Leftovers::Processors::AddDefinitionNode
42
+ )
41
43
  end
42
44
 
43
- def build_set_default_privacy_processor(matcher, set_default_privacy)
44
- ::Leftovers::DynamicProcessors::SetDefaultPrivacy.new(matcher, set_default_privacy)
45
+ def build_eval_action(eval)
46
+ ::Leftovers::ProcessorBuilders::Action.build(
47
+ eval, ::Leftovers::Processors::Eval
48
+ )
45
49
  end
46
50
 
47
- def build_call_define_processor(matcher, call_action, define_action)
48
- if call_action && define_action
49
- # this nonsense saves a method call and array instantiation per method
50
- ::Leftovers::DynamicProcessors::CallDefinition.new(matcher, call_action, define_action)
51
- elsif define_action
52
- ::Leftovers::DynamicProcessors::Definition.new(matcher, define_action)
53
- elsif call_action
54
- ::Leftovers::DynamicProcessors::Call.new(matcher, call_action)
55
- else
56
- ::Leftovers::DynamicProcessors::Null
51
+ def build_set_privacy_action(set_privacies)
52
+ ::Leftovers::ProcessorBuilders::Each.each_or_self(set_privacies) do |set_privacy|
53
+ processor = ::Leftovers::Processors::SetPrivacy.new(set_privacy.delete(:to))
54
+ ::Leftovers::ProcessorBuilders::Action.build_from_hash_value(
55
+ **set_privacy, final_processor: processor
56
+ )
57
57
  end
58
58
  end
59
+
60
+ def build_set_default_privacy_action(set_default_privacy)
61
+ return unless set_default_privacy
62
+
63
+ ::Leftovers::Processors::SetDefaultPrivacy.new(set_default_privacy)
64
+ end
59
65
  end
60
66
  end
61
67
  end
@@ -2,18 +2,37 @@
2
2
 
3
3
  module Leftovers
4
4
  module ProcessorBuilders
5
- module Each
5
+ class Each
6
+ def self.build(processors)
7
+ self[:each].build(processors)
8
+ end
9
+
6
10
  def self.each_or_self(value, &block)
11
+ self[:each].each_or_self(value, &block)
12
+ end
13
+
14
+ def self.[](processor_name)
15
+ @each ||= {
16
+ each: new(::Leftovers::Processors::Each),
17
+ each_for_definition_set: new(::Leftovers::Processors::EachForDefinitionSet)
18
+ }
19
+
20
+ @each.fetch(processor_name)
21
+ end
22
+
23
+ def initialize(processor_class = ::Leftovers::Processors::Each)
24
+ @processor_class = processor_class
25
+ end
26
+
27
+ def each_or_self(value, &block)
7
28
  case value
8
- # :nocov:
9
- when nil then raise Leftovers::UnexpectedCase, "Unhandled value #{value.inspect}"
10
- # :nocov:
29
+ when nil then nil
11
30
  when Array then build(value.map(&block))
12
31
  else build([yield(value)])
13
32
  end
14
33
  end
15
34
 
16
- def self.build(processors)
35
+ def build(processors)
17
36
  processors = compact(processors)
18
37
 
19
38
  case processors.length
@@ -21,15 +40,68 @@ module Leftovers
21
40
  when 0 then raise Leftovers::UnexpectedCase, "Unhandled value #{processors.inspect}"
22
41
  # :nocov:
23
42
  when 1 then processors.first
24
- else ::Leftovers::ValueProcessors::Each.new(processors)
43
+ else @processor_class.new(processors)
25
44
  end
26
45
  end
27
46
 
28
- def self.compact(processors)
29
- processors.flatten!
30
- processors.compact!
47
+ def flatten(processors)
48
+ case processors
49
+ when ::Leftovers::Processors::Each, @processor_class
50
+ flatten(processors.processors)
51
+ when Array
52
+ processors.flat_map { |v| flatten(v) }
53
+ when ::Leftovers::Processors::MatchCurrentNode, ::Leftovers::Processors::MatchMatchedNode
54
+ flatten_matchers(processors)
55
+ else
56
+ [processors]
57
+ end
58
+ end
59
+
60
+ def flatten_matchers(processor)
61
+ then_processors = flatten(processor.then_processor)
62
+ return [processor] if then_processors.length <= 1
63
+
64
+ then_processors.map do |then_processor|
65
+ processor.class.new(processor.matcher, then_processor)
66
+ end
67
+ end
68
+
69
+ def compact_matchers_with_same_processor(matchers)
70
+ matchers.group_by(&:then_processor).map do |then_processor, group|
71
+ next group.first unless group.length > 1
72
+
73
+ group.first.class.new(
74
+ ::Leftovers::MatcherBuilders::Or.build(group.map(&:matcher)),
75
+ then_processor
76
+ )
77
+ end
78
+ end
79
+
80
+ def compact_matchers_with_same_matcher(matchers)
81
+ matchers.group_by(&:matcher).map do |matcher, group|
82
+ next group.first unless group.length > 1
83
+
84
+ group.first.class.new(matcher, build(group.map(&:then_processor)))
85
+ end
86
+ end
87
+
88
+ def compact_matchers(matchers)
89
+ return [] unless matchers
90
+
91
+ matchers = compact_matchers_with_same_processor(matchers)
92
+ compact_matchers_with_same_matcher(matchers)
93
+ end
94
+
95
+ def compact(processors)
96
+ processors = flatten(processors).compact
97
+
98
+ return processors if processors.length <= 1
99
+
100
+ group = processors.group_by(&:class)
31
101
 
32
- processors
102
+ compact_matchers(group.delete(::Leftovers::Processors::MatchCurrentNode)) +
103
+ compact_matchers(group.delete(::Leftovers::Processors::MatchMatchedNode)) +
104
+ group.values.flatten(1)
33
105
  end
34
106
  end
35
107
  end
@@ -4,9 +4,9 @@ module Leftovers
4
4
  module ProcessorBuilders
5
5
  module Itself
6
6
  def self.build(value, then_processor)
7
- return unless value && then_processor
7
+ return unless value
8
8
 
9
- ::Leftovers::ValueProcessors::Itself.new(then_processor)
9
+ ::Leftovers::Processors::Itself.new(then_processor)
10
10
  end
11
11
  end
12
12
  end
@@ -4,19 +4,20 @@ module Leftovers
4
4
  module ProcessorBuilders
5
5
  module Keyword
6
6
  def self.build(value, then_processor)
7
- return unless value && then_processor
7
+ return unless value
8
8
 
9
- case value
10
- when true, '**' then ::Leftovers::ValueProcessors::EachKeyword.new(then_processor)
9
+ then_processor = case value
10
+ when true, '**' then then_processor
11
11
  when ::String, ::Hash, ::Array
12
- ::Leftovers::ValueProcessors::Keyword.new(
13
- ::Leftovers::MatcherBuilders::NodePairName.build(value),
14
- then_processor
12
+ ::Leftovers::Processors::MatchCurrentNode.new(
13
+ ::Leftovers::MatcherBuilders::NodeName.build(value), then_processor
15
14
  )
16
15
  # :nocov:
17
16
  else raise Leftovers::UnexpectedCase, "Unhandled value #{value.inspect}"
18
17
  # :nocov:
19
18
  end
19
+
20
+ ::Leftovers::Processors::EachKeyword.new(then_processor)
20
21
  end
21
22
  end
22
23
  end
@@ -4,8 +4,10 @@ module Leftovers
4
4
  module ProcessorBuilders
5
5
  module KeywordArgument
6
6
  def self.build(pattern, then_processor)
7
- ::Leftovers::ValueProcessors::KeywordArgument.new(
8
- ::Leftovers::MatcherBuilders::NodePairName.build(pattern),
7
+ ::Leftovers::Processors::KeywordArgument.new(
8
+ ::Leftovers::MatcherBuilders::NodePairKey.build(
9
+ ::Leftovers::MatcherBuilders::NodeName.build(pattern)
10
+ ),
9
11
  then_processor
10
12
  )
11
13
  end