leftovers 0.7.0 → 0.8.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 (88) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/README.md +1 -0
  4. data/docs/Configuration.md +20 -57
  5. data/docs/Custom-Precompilers.md +38 -0
  6. data/lib/config/actionpack.yml +5 -3
  7. data/lib/config/haml.yml +4 -2
  8. data/lib/config/ruby.yml +4 -15
  9. data/lib/config/slim.yml +4 -2
  10. data/lib/leftovers/cli.rb +5 -0
  11. data/lib/leftovers/collector.rb +2 -1
  12. data/lib/leftovers/config.rb +2 -18
  13. data/lib/leftovers/config_loader/argument_position_schema.rb +2 -2
  14. data/lib/leftovers/config_loader/attribute.rb +36 -10
  15. data/lib/leftovers/config_loader/built_in_precompiler_schema.rb +13 -0
  16. data/lib/leftovers/config_loader/document_schema.rb +32 -5
  17. data/lib/leftovers/config_loader/has_argument_schema.rb +2 -2
  18. data/lib/leftovers/config_loader/has_value_schema.rb +2 -2
  19. data/lib/leftovers/config_loader/inherit_schema_attributes.rb +22 -0
  20. data/lib/leftovers/config_loader/keep_test_only_schema.rb +2 -2
  21. data/lib/leftovers/config_loader/object_schema.rb +33 -105
  22. data/lib/leftovers/config_loader/precompile_schema.rb +12 -0
  23. data/lib/leftovers/config_loader/precompiler_schema.rb +11 -0
  24. data/lib/leftovers/config_loader/privacy_processor_schema.rb +0 -2
  25. data/lib/leftovers/config_loader/require_schema.rb +3 -3
  26. data/lib/leftovers/config_loader/schema.rb +2 -0
  27. data/lib/leftovers/config_loader/string_pattern_schema.rb +2 -2
  28. data/lib/leftovers/config_loader/string_value_processor_schema.rb +2 -2
  29. data/lib/leftovers/config_loader/transform_schema.rb +4 -6
  30. data/lib/leftovers/config_loader/value_matcher_schema.rb +2 -2
  31. data/lib/leftovers/config_loader/value_or_array_schema.rb +5 -3
  32. data/lib/leftovers/config_loader/value_or_object_schema.rb +40 -0
  33. data/lib/leftovers/config_loader/value_processor_schema.rb +2 -2
  34. data/lib/leftovers/config_loader.rb +5 -1
  35. data/lib/leftovers/file.rb +7 -53
  36. data/lib/leftovers/file_collector/comments_processor.rb +57 -0
  37. data/lib/leftovers/file_collector/node_processor.rb +131 -0
  38. data/lib/leftovers/file_collector.rb +42 -203
  39. data/lib/leftovers/matcher_builders/and_not.rb +7 -5
  40. data/lib/leftovers/matcher_builders/name.rb +18 -17
  41. data/lib/leftovers/matcher_builders/node.rb +48 -34
  42. data/lib/leftovers/matcher_builders/node_has_argument.rb +48 -52
  43. data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +13 -10
  44. data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +29 -15
  45. data/lib/leftovers/matcher_builders/node_type.rb +1 -1
  46. data/lib/leftovers/matcher_builders/node_value.rb +27 -22
  47. data/lib/leftovers/matcher_builders/or.rb +50 -50
  48. data/lib/leftovers/matcher_builders/string_pattern.rb +1 -1
  49. data/lib/leftovers/merged_config.rb +3 -23
  50. data/lib/leftovers/precompilers/erb.rb +22 -0
  51. data/lib/leftovers/precompilers/haml.rb +15 -0
  52. data/lib/leftovers/precompilers/json.rb +27 -0
  53. data/lib/leftovers/precompilers/precompiler.rb +28 -0
  54. data/lib/leftovers/precompilers/slim.rb +15 -0
  55. data/lib/leftovers/precompilers/yaml.rb +75 -0
  56. data/lib/leftovers/precompilers.rb +50 -0
  57. data/lib/leftovers/processor_builders/action.rb +48 -39
  58. data/lib/leftovers/processor_builders/add_prefix.rb +1 -1
  59. data/lib/leftovers/processor_builders/add_suffix.rb +1 -1
  60. data/lib/leftovers/processor_builders/argument.rb +8 -11
  61. data/lib/leftovers/processor_builders/dynamic.rb +5 -5
  62. data/lib/leftovers/processor_builders/each.rb +2 -2
  63. data/lib/leftovers/processor_builders/each_action.rb +33 -33
  64. data/lib/leftovers/processor_builders/each_dynamic.rb +4 -8
  65. data/lib/leftovers/processor_builders/each_for_definition_set.rb +25 -21
  66. data/lib/leftovers/processor_builders/keyword.rb +3 -4
  67. data/lib/leftovers/processor_builders/transform.rb +2 -2
  68. data/lib/leftovers/processor_builders/transform_chain.rb +16 -8
  69. data/lib/leftovers/processor_builders/transform_set.rb +32 -28
  70. data/lib/leftovers/rake_task.rb +1 -1
  71. data/lib/leftovers/value_processors/add_dynamic_prefix.rb +3 -10
  72. data/lib/leftovers/value_processors/add_dynamic_suffix.rb +3 -10
  73. data/lib/leftovers/value_processors/each.rb +1 -1
  74. data/lib/leftovers/value_processors/each_for_definition_set.rb +2 -5
  75. data/lib/leftovers/value_processors/each_keyword.rb +1 -1
  76. data/lib/leftovers/value_processors/each_keyword_argument.rb +1 -1
  77. data/lib/leftovers/value_processors/each_positional_argument.rb +2 -1
  78. data/lib/leftovers/value_processors/keyword.rb +3 -7
  79. data/lib/leftovers/value_processors/keyword_argument.rb +2 -6
  80. data/lib/leftovers/value_processors/split.rb +2 -2
  81. data/lib/leftovers/version.rb +1 -1
  82. data/lib/leftovers.rb +41 -6
  83. metadata +17 -7
  84. data/lib/leftovers/erb.rb +0 -20
  85. data/lib/leftovers/haml.rb +0 -21
  86. data/lib/leftovers/json.rb +0 -28
  87. data/lib/leftovers/slim.rb +0 -21
  88. data/lib/leftovers/yaml.rb +0 -73
@@ -0,0 +1,131 @@
1
+ # frozen-string-literal: true
2
+
3
+ require 'parser'
4
+
5
+ module Leftovers
6
+ class FileCollector
7
+ class NodeProcessor < ::Parser::AST::Processor
8
+ def initialize(collector) # rubocop:disable Lint/MissingSuper # there isn't one to call
9
+ @collector = collector
10
+ end
11
+
12
+ def on_def(node)
13
+ node.privacy = @collector.default_method_privacy
14
+ @collector.add_definition(node)
15
+ super
16
+ end
17
+
18
+ def on_defs(node)
19
+ @collector.add_definition(node)
20
+ super
21
+ end
22
+
23
+ def on_ivasgn(node)
24
+ @collector.collect_variable_assign(node)
25
+ super
26
+ end
27
+
28
+ def on_gvasgn(node)
29
+ @collector.collect_variable_assign(node)
30
+ super
31
+ end
32
+
33
+ def on_cvasgn(node)
34
+ @collector.collect_variable_assign(node)
35
+ super
36
+ end
37
+
38
+ def on_ivar(node)
39
+ @collector.add_call(node.name)
40
+ super
41
+ end
42
+
43
+ def on_gvar(node)
44
+ @collector.add_call(node.name)
45
+ super
46
+ end
47
+
48
+ def on_cvar(node)
49
+ @collector.add_call(node.name)
50
+ super
51
+ end
52
+
53
+ def on_op_asgn(node)
54
+ @collector.collect_op_asgn(node)
55
+ super
56
+ end
57
+
58
+ def on_and_asgn(node)
59
+ @collector.collect_op_asgn(node)
60
+ super
61
+ end
62
+
63
+ def on_or_asgn(node)
64
+ @collector.collect_op_asgn(node)
65
+ super
66
+ end
67
+
68
+ def on_send(node)
69
+ super
70
+ @collector.collect_send(node)
71
+ end
72
+
73
+ def on_csend(node)
74
+ super
75
+ @collector.collect_send(node)
76
+ end
77
+
78
+ def on_const(node)
79
+ super
80
+ @collector.add_call(node.name)
81
+ end
82
+
83
+ def on_array(node)
84
+ super
85
+ @collector.collect_commented_dynamic(node)
86
+ end
87
+
88
+ def on_hash(node)
89
+ super
90
+ @collector.collect_commented_dynamic(node)
91
+ end
92
+
93
+ # grab e.g. :to_s in each(&:to_s)
94
+ def on_block_pass(node)
95
+ super
96
+ return unless node.first.string_or_symbol?
97
+
98
+ @collector.add_call(node.first.to_sym)
99
+ end
100
+
101
+ # grab class Constant or module Constant
102
+ def on_class(node)
103
+ # don't call super so we don't interpret the class name as being called by its definition
104
+ process_all(node.children.drop(1))
105
+
106
+ node = node.children.first
107
+
108
+ @collector.add_definition(node)
109
+ end
110
+ alias_method :on_module, :on_class
111
+
112
+ # grab Constant = Class.new or CONSTANT = 'string'.freeze
113
+ def on_casgn(node)
114
+ super
115
+
116
+ @collector.add_definition(node)
117
+ @collector.collect_dynamic(node)
118
+ end
119
+
120
+ # grab calls to `alias new_method original_method`
121
+ def on_alias(node)
122
+ super
123
+ new_method, original_method = node.children
124
+ @collector.add_definition(
125
+ new_method, name: new_method.children.first, loc: new_method.loc.expression
126
+ )
127
+ @collector.add_call(original_method.children.first)
128
+ end
129
+ end
130
+ end
131
+ end
@@ -1,14 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'set'
4
- require 'parser'
5
4
 
6
5
  module Leftovers
7
- class FileCollector < ::Parser::AST::Processor # rubocop:disable Metrics/ClassLength
8
- attr_reader :calls
6
+ class FileCollector
7
+ autoload(:CommentsProcessor, "#{__dir__}/file_collector/comments_processor.rb")
8
+ autoload(:NodeProcessor, "#{__dir__}/file_collector/node_processor.rb")
9
+
10
+ attr_reader :calls, :allow_lines, :test_lines, :dynamic_lines
9
11
  attr_accessor :default_method_privacy
10
12
 
11
- def initialize(ruby, file) # rubocop:disable Lint/MissingSuper
13
+ def initialize(ruby, file)
12
14
  @calls = []
13
15
  @definitions_to_add = {}
14
16
  @allow_lines = Set.new.compare_by_identity
@@ -25,176 +27,30 @@ module Leftovers
25
27
  end
26
28
 
27
29
  def to_h
28
- squash!
29
-
30
- {
31
- test?: @file.test?,
32
- calls: calls,
33
- definitions: definitions
34
- }
30
+ { test?: @file.test?, calls: squash!(calls), definitions: squash!(definitions) }
35
31
  end
36
32
 
37
- def squash!
38
- calls.flatten!
39
- calls.compact!
40
- calls.uniq!
41
- definitions.flatten!
42
- definitions.compact!
43
- definitions.uniq!
33
+ def squash!(list)
34
+ list.flatten!
35
+ list.compact!
36
+ list.uniq!
37
+ list
44
38
  end
45
39
 
46
40
  def collect
47
41
  ast, comments = Leftovers::Parser.parse_with_comments(@ruby, @file.relative_path)
48
- process_comments(comments)
49
- process(ast)
42
+ CommentsProcessor.process(comments, self)
43
+ NodeProcessor.new(self).process(ast)
50
44
  rescue ::Parser::SyntaxError => e
51
- Leftovers.warn "\e[31m#{filename}:#{e.diagnostic.location.line}:#{e.diagnostic.location.column} SyntaxError: #{e.message}\e[0m" # rubocop:disable Layout/LineLength
52
- end
53
-
54
- METHOD_NAME_RE = /[[:alpha:]_][[:alnum:]_]*\b[?!=]?/.freeze
55
- NON_ALNUM_METHOD_NAME_RE = Regexp.union(%w{
56
- []= [] ** ~ +@ -@ * / % + - >> << &
57
- ^ | <=> <= >= < > === == != =~ !~ !
58
- }.map { |op| /#{Regexp.escape(op)}/ })
59
- CONSTANT_NAME_RE = /[[:upper:]][[:alnum:]_]*\b/.freeze
60
- NAME_RE = Regexp.union(METHOD_NAME_RE, NON_ALNUM_METHOD_NAME_RE, CONSTANT_NAME_RE)
61
- LEFTOVERS_CALL_RE = /\bleftovers:call(?:s|ed|er|ers|) (#{NAME_RE}(?:[, :]+#{NAME_RE})*)/.freeze
62
- LEFTOVERS_ALLOW_RE = /\bleftovers:(?:keeps?|skip(?:s|ped|)|allow(?:s|ed|))\b/.freeze
63
- LEFTOVERS_TEST_RE = /\bleftovers:(?:for_tests?|tests?|testing|test_only)\b/.freeze
64
- LEFTOVERS_DYNAMIC_RE = /\bleftovers:dynamic:(#{NAME_RE})\b/.freeze
65
-
66
- def process_comments(comments) # rubocop:disable Metrics/AbcSize
67
- comments.each do |comment|
68
- @allow_lines << comment.loc.line if comment.text.match?(LEFTOVERS_ALLOW_RE)
69
- @test_lines << comment.loc.line if comment.text.match?(LEFTOVERS_TEST_RE)
70
- dynamic_match = comment.text.match(LEFTOVERS_DYNAMIC_RE)
71
- @dynamic_lines[comment.loc.line] = dynamic_match[1] if dynamic_match
72
-
73
- next unless (call_match = comment.text.match(LEFTOVERS_CALL_RE))
74
-
75
- call_match[1].scan(NAME_RE).each { |s| add_call(s.to_sym) }
76
- end
45
+ Leftovers.warn(
46
+ "\e[31m#{filename}:#{e.diagnostic.location.line}:#{e.diagnostic.location.column} " \
47
+ "SyntaxError: #{e.message}\e[0m"
48
+ )
77
49
  end
78
50
 
79
51
  # grab method definitions
80
- def on_def(node)
81
- node.privacy = default_method_privacy
82
- add_definition(node)
83
- super
84
- end
85
-
86
- def on_defs(node)
87
- add_definition(node)
88
- super
89
- end
90
-
91
- def on_ivasgn(node)
92
- collect_variable_assign(node)
93
- super
94
- end
95
-
96
- def on_gvasgn(node)
97
- collect_variable_assign(node)
98
- super
99
- end
100
-
101
- def on_cvasgn(node)
102
- collect_variable_assign(node)
103
- super
104
- end
105
-
106
- def on_ivar(node)
107
- add_call(node.name)
108
- super
109
- end
110
-
111
- def on_gvar(node)
112
- add_call(node.name)
113
- super
114
- end
115
-
116
- def on_cvar(node)
117
- add_call(node.name)
118
- super
119
- end
120
-
121
- def on_op_asgn(node)
122
- collect_op_asgn(node)
123
- super
124
- end
125
-
126
- def on_and_asgn(node)
127
- collect_op_asgn(node)
128
- super
129
- end
130
-
131
- def on_or_asgn(node)
132
- collect_op_asgn(node)
133
- super
134
- end
135
-
136
- # grab method calls
137
- def on_send(node)
138
- super
139
- collect_send(node)
140
- end
141
-
142
- def on_csend(node)
143
- super
144
- collect_send(node)
145
- end
146
-
147
- def on_const(node)
148
- super
149
- add_call(node.name)
150
- end
151
-
152
- def on_array(node)
153
- super
154
- collect_commented_dynamic(node)
155
- end
156
-
157
- def on_hash(node)
158
- super
159
- collect_commented_dynamic(node)
160
- end
161
-
162
- # grab e.g. :to_s in each(&:to_s)
163
- def on_block_pass(node)
164
- super
165
- add_call(node.children.first.to_sym) if node.children.first.string_or_symbol?
166
- end
167
-
168
- # grab class Constant or module Constant
169
- def on_class(node)
170
- # don't call super so we don't process the class name
171
- # !!! (# wtf does this mean dana? what would happen instead?)
172
- process_all(node.children.drop(1))
173
-
174
- node = node.children.first
175
-
176
- add_definition(node)
177
- end
178
- alias_method :on_module, :on_class
179
-
180
- # grab Constant = Class.new or CONSTANT = 'string'.freeze
181
- def on_casgn(node)
182
- super
183
- add_definition(node)
184
- collect_dynamic(node)
185
- end
186
-
187
- # grab calls to `alias new_method original_method`
188
- def on_alias(node)
189
- super
190
- new_method, original_method = node.children
191
- add_definition(new_method, name: new_method.children.first, loc: new_method.loc.expression)
192
- add_call(original_method.children.first)
193
- end
194
-
195
52
  def add_definition(node, name: node.name, loc: node.loc.name)
196
- @definitions_to_add[name] =
197
- ::Leftovers::DefinitionToAdd.new(node, name: name, location: loc)
53
+ @definitions_to_add[name] = ::Leftovers::DefinitionToAdd.new(node, name: name, location: loc)
198
54
  end
199
55
 
200
56
  def add_definition_set(definition_node_set)
@@ -208,25 +64,22 @@ module Leftovers
208
64
  end
209
65
 
210
66
  def definitions
211
- @definitions ||= @definitions_to_add.each_value.map { |d| d.to_definition(self) }.compact +
67
+ @definitions ||= @definitions_to_add.each_value.map { |d| d.to_definition(self) } +
212
68
  @definition_sets_to_add.map do |definition_set|
213
- next nil if definition_set.any? { |d| d.keep?(self) }
69
+ next if definition_set.any? { |d| d.keep?(self) }
214
70
 
215
71
  ::Leftovers::DefinitionSet.new(definition_set.map { |d| d.to_definition(self) })
216
- end.compact
72
+ end
217
73
  end
218
74
 
219
75
  def test_line?(line)
220
- @file.test? ||
221
- @test_lines.include?(line)
76
+ @file.test? || @test_lines.include?(line)
222
77
  end
223
78
 
224
79
  def keep_line?(line)
225
80
  @allow_lines.include?(line)
226
81
  end
227
82
 
228
- private
229
-
230
83
  def add_call(name)
231
84
  calls << name
232
85
  end
@@ -236,52 +89,29 @@ module Leftovers
236
89
  collect_dynamic(node)
237
90
  end
238
91
 
239
- # just collects the call, super will collect the definition
240
- def collect_var_op_asgn(node)
241
- name = node.children.first
242
-
243
- add_call(name)
244
- end
245
-
246
- def collect_send_op_asgn(node)
247
- name = node.children[1]
248
-
249
- add_call(:"#{name}=")
250
- end
251
-
252
92
  def collect_variable_assign(node)
253
93
  add_definition(node)
254
-
255
94
  collect_dynamic(node)
256
95
  end
257
96
 
258
97
  def collect_op_asgn(node)
259
- node = node.children.first
98
+ node = node.first
260
99
  case node.type
261
- when :send then collect_send_op_asgn(node)
262
- when :ivasgn, :gvasgn, :cvasgn then collect_var_op_asgn(node)
100
+ # just collects the :call=, super will collect the :call
101
+ when :send, :csend then add_call(:"#{node.name}=")
102
+ # just collects the call, super will collect the definition
103
+ when :ivasgn, :gvasgn, :cvasgn then add_call(node.name)
263
104
  when :lvasgn then nil # we don't care about lvasgn
264
105
  # :nocov:
265
- else
266
- raise "Unrecognized op_asgn node type #{node.type}"
106
+ else raise Leftovers::UnexpectedCase, "Unhandled value #{node.type.inspect}"
267
107
  # :nocov:
268
108
  end
269
109
  end
270
110
 
271
111
  def collect_commented_dynamic(node)
272
- fake_method_name = @dynamic_lines[node.loc.line]
273
- return unless fake_method_name
274
-
275
- node = build_send_wrapper_for(node, fake_method_name)
276
- collect_dynamic(node)
277
- end
278
-
279
- def build_send_wrapper_for(node, name)
280
- ::Leftovers::AST::Node.new(
281
- :send,
282
- [nil, name.to_sym, *node.arguments],
283
- location: node.location
284
- )
112
+ @dynamic_lines[node.loc.line]&.each do |fake_method_name|
113
+ collect_dynamic(build_send_wrapper_for(node, fake_method_name))
114
+ end
285
115
  end
286
116
 
287
117
  def collect_dynamic(node)
@@ -289,7 +119,16 @@ module Leftovers
289
119
 
290
120
  Leftovers.config.dynamic.process(node, self)
291
121
  rescue StandardError => e
292
- raise ::Leftovers::Error, "#{e.class}: #{e.message}\nwhen processing #{node} at #{filename}:#{node.loc.line}:#{node.loc.column}", e.backtrace # rubocop:disable Layout/LineLength
122
+ raise ::Leftovers::Error, "#{e.class}: #{e.message}\n" \
123
+ "when processing #{node} at #{filename}:#{node.loc.line}:#{node.loc.column}", e.backtrace
124
+ end
125
+
126
+ private
127
+
128
+ def build_send_wrapper_for(node, name)
129
+ ::Leftovers::AST::Node.new(
130
+ :send, [nil, name.to_sym, *node.arguments], location: node.location
131
+ )
293
132
  end
294
133
  end
295
134
  end
@@ -3,11 +3,13 @@
3
3
  module Leftovers
4
4
  module MatcherBuilders
5
5
  module AndNot
6
- def self.build(positive_matcher, negative_matcher)
7
- ::Leftovers::MatcherBuilders::And.build([
8
- positive_matcher,
9
- ::Leftovers::MatcherBuilders::Unless.build(negative_matcher)
10
- ])
6
+ class << self
7
+ def build(positive_matcher, negative_matcher)
8
+ ::Leftovers::MatcherBuilders::And.build([
9
+ positive_matcher,
10
+ ::Leftovers::MatcherBuilders::Unless.build(negative_matcher)
11
+ ])
12
+ end
11
13
  end
12
14
  end
13
15
  end
@@ -3,26 +3,27 @@
3
3
  module Leftovers
4
4
  module MatcherBuilders
5
5
  module Name
6
- def self.build(patterns) # rubocop:disable Metrics/MethodLength
7
- ::Leftovers::MatcherBuilders::Or.each_or_self(patterns) do |pat|
8
- case pat
9
- when nil
10
- when ::Array
11
- ::Leftovers::MatcherBuilders::Name.build(pat)
12
- when ::String
13
- ::Leftovers::MatcherBuilders::String.build(pat)
14
- when ::Hash
15
- unless_arg = pat.delete(:unless_arg)
16
-
17
- ::Leftovers::MatcherBuilders::AndNot.build(
18
- ::Leftovers::MatcherBuilders::StringPattern.build(**pat),
19
- ::Leftovers::MatcherBuilders::Name.build(unless_arg)
20
- )
21
- # :nocov:
22
- else raise
6
+ class << self
7
+ def build(patterns)
8
+ ::Leftovers::MatcherBuilders::Or.each_or_self(patterns) do |pat|
9
+ case pat
10
+ when ::String then ::Leftovers::MatcherBuilders::String.build(pat)
11
+ when ::Hash then build_from_hash(**pat)
23
12
  # :nocov:
13
+ else raise Leftovers::UnexpectedCase, "Unhandled value #{pat.inspect}"
14
+ # :nocov:
15
+ end
24
16
  end
25
17
  end
18
+
19
+ private
20
+
21
+ def build_from_hash(unless_arg: nil, **pattern)
22
+ ::Leftovers::MatcherBuilders::AndNot.build(
23
+ ::Leftovers::MatcherBuilders::StringPattern.build(**pattern),
24
+ ::Leftovers::MatcherBuilders::Name.build(unless_arg)
25
+ )
26
+ end
26
27
  end
27
28
  end
28
29
  end
@@ -3,45 +3,59 @@
3
3
  module Leftovers
4
4
  module MatcherBuilders
5
5
  module Node
6
- def self.build(pattern)
7
- ::Leftovers::MatcherBuilders::Or.each_or_self(pattern) do |pat|
8
- case pat
9
- when ::String
10
- ::Leftovers::MatcherBuilders::NodeName.build(pat)
11
- when ::Hash
12
- build_from_hash(**pat)
13
- # :nocov:
14
- else raise
15
- # :nocov:
6
+ class << self
7
+ def build(patterns)
8
+ ::Leftovers::MatcherBuilders::Or.each_or_self(patterns) do |pattern|
9
+ case pattern
10
+ when ::String then ::Leftovers::MatcherBuilders::NodeName.build(pattern)
11
+ when ::Hash then build_from_hash(**pattern)
12
+ # :nocov:
13
+ else raise Leftovers::UnexpectedCase, "Unhandled value #{pattern.inspect}"
14
+ # :nocov:
15
+ end
16
16
  end
17
17
  end
18
- end
19
18
 
20
- def self.build_from_hash( # rubocop:disable Metrics/ParameterLists, Metrics/MethodLength
21
- names: nil, match: nil, has_prefix: nil, has_suffix: nil,
22
- document: false,
23
- paths: nil,
24
- has_arguments: nil,
25
- has_receiver: nil,
26
- type: nil,
27
- privacy: nil,
28
- unless_arg: nil
29
- )
30
- ::Leftovers::MatcherBuilders::And.build([
31
- ::Leftovers::MatcherBuilders::NodeName.build([
32
- names,
33
- { match: match, has_prefix: has_prefix, has_suffix: has_suffix }.compact
34
- ]),
35
- ::Leftovers::MatcherBuilders::Document.build(document),
36
- ::Leftovers::MatcherBuilders::NodePath.build(paths),
37
- ::Leftovers::MatcherBuilders::NodeHasArgument.build(has_arguments),
38
- ::Leftovers::MatcherBuilders::NodeHasReceiver.build(has_receiver),
39
- ::Leftovers::MatcherBuilders::NodePrivacy.build(privacy),
40
- ::Leftovers::MatcherBuilders::NodeType.build(type),
19
+ private
20
+
21
+ def build_node_name_matcher(names, match, has_prefix, has_suffix)
22
+ ::Leftovers::MatcherBuilders::Or.build([
23
+ ::Leftovers::MatcherBuilders::NodeName.build(names),
24
+ ::Leftovers::MatcherBuilders::NodeName.build(
25
+ match: match, has_prefix: has_prefix, has_suffix: has_suffix
26
+ )
27
+ ])
28
+ end
29
+
30
+ def build_unless_matcher(unless_arg)
31
+ return unless unless_arg
32
+
41
33
  ::Leftovers::MatcherBuilders::Unless.build(
42
- (::Leftovers::MatcherBuilders::Node.build(unless_arg) if unless_arg)
34
+ ::Leftovers::MatcherBuilders::Node.build(unless_arg)
43
35
  )
44
- ])
36
+ end
37
+
38
+ def build_from_hash( # rubocop:disable Metrics/ParameterLists
39
+ names: nil, match: nil, has_prefix: nil, has_suffix: nil,
40
+ document: false,
41
+ paths: nil,
42
+ has_arguments: nil,
43
+ has_receiver: nil,
44
+ type: nil,
45
+ privacy: nil,
46
+ unless_arg: nil
47
+ )
48
+ ::Leftovers::MatcherBuilders::And.build([
49
+ build_node_name_matcher(names, match, has_prefix, has_suffix),
50
+ ::Leftovers::MatcherBuilders::Document.build(document),
51
+ ::Leftovers::MatcherBuilders::NodePath.build(paths),
52
+ ::Leftovers::MatcherBuilders::NodeHasArgument.build(has_arguments),
53
+ ::Leftovers::MatcherBuilders::NodeHasReceiver.build(has_receiver),
54
+ ::Leftovers::MatcherBuilders::NodePrivacy.build(privacy),
55
+ ::Leftovers::MatcherBuilders::NodeType.build(type),
56
+ build_unless_matcher(unless_arg)
57
+ ])
58
+ end
45
59
  end
46
60
  end
47
61
  end