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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +1 -0
- data/docs/Configuration.md +20 -57
- data/docs/Custom-Precompilers.md +38 -0
- data/lib/config/actionpack.yml +5 -3
- data/lib/config/haml.yml +4 -2
- data/lib/config/ruby.yml +4 -15
- data/lib/config/slim.yml +4 -2
- data/lib/leftovers/cli.rb +5 -0
- data/lib/leftovers/collector.rb +2 -1
- data/lib/leftovers/config.rb +2 -18
- data/lib/leftovers/config_loader/argument_position_schema.rb +2 -2
- data/lib/leftovers/config_loader/attribute.rb +36 -10
- data/lib/leftovers/config_loader/built_in_precompiler_schema.rb +13 -0
- data/lib/leftovers/config_loader/document_schema.rb +32 -5
- data/lib/leftovers/config_loader/has_argument_schema.rb +2 -2
- data/lib/leftovers/config_loader/has_value_schema.rb +2 -2
- data/lib/leftovers/config_loader/inherit_schema_attributes.rb +22 -0
- data/lib/leftovers/config_loader/keep_test_only_schema.rb +2 -2
- data/lib/leftovers/config_loader/object_schema.rb +33 -105
- data/lib/leftovers/config_loader/precompile_schema.rb +12 -0
- data/lib/leftovers/config_loader/precompiler_schema.rb +11 -0
- data/lib/leftovers/config_loader/privacy_processor_schema.rb +0 -2
- data/lib/leftovers/config_loader/require_schema.rb +3 -3
- data/lib/leftovers/config_loader/schema.rb +2 -0
- data/lib/leftovers/config_loader/string_pattern_schema.rb +2 -2
- data/lib/leftovers/config_loader/string_value_processor_schema.rb +2 -2
- data/lib/leftovers/config_loader/transform_schema.rb +4 -6
- data/lib/leftovers/config_loader/value_matcher_schema.rb +2 -2
- data/lib/leftovers/config_loader/value_or_array_schema.rb +5 -3
- data/lib/leftovers/config_loader/value_or_object_schema.rb +40 -0
- data/lib/leftovers/config_loader/value_processor_schema.rb +2 -2
- data/lib/leftovers/config_loader.rb +5 -1
- data/lib/leftovers/file.rb +7 -53
- data/lib/leftovers/file_collector/comments_processor.rb +57 -0
- data/lib/leftovers/file_collector/node_processor.rb +131 -0
- data/lib/leftovers/file_collector.rb +42 -203
- data/lib/leftovers/matcher_builders/and_not.rb +7 -5
- data/lib/leftovers/matcher_builders/name.rb +18 -17
- data/lib/leftovers/matcher_builders/node.rb +48 -34
- data/lib/leftovers/matcher_builders/node_has_argument.rb +48 -52
- data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +13 -10
- data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +29 -15
- data/lib/leftovers/matcher_builders/node_type.rb +1 -1
- data/lib/leftovers/matcher_builders/node_value.rb +27 -22
- data/lib/leftovers/matcher_builders/or.rb +50 -50
- data/lib/leftovers/matcher_builders/string_pattern.rb +1 -1
- data/lib/leftovers/merged_config.rb +3 -23
- data/lib/leftovers/precompilers/erb.rb +22 -0
- data/lib/leftovers/precompilers/haml.rb +15 -0
- data/lib/leftovers/precompilers/json.rb +27 -0
- data/lib/leftovers/precompilers/precompiler.rb +28 -0
- data/lib/leftovers/precompilers/slim.rb +15 -0
- data/lib/leftovers/precompilers/yaml.rb +75 -0
- data/lib/leftovers/precompilers.rb +50 -0
- data/lib/leftovers/processor_builders/action.rb +48 -39
- data/lib/leftovers/processor_builders/add_prefix.rb +1 -1
- data/lib/leftovers/processor_builders/add_suffix.rb +1 -1
- data/lib/leftovers/processor_builders/argument.rb +8 -11
- data/lib/leftovers/processor_builders/dynamic.rb +5 -5
- data/lib/leftovers/processor_builders/each.rb +2 -2
- data/lib/leftovers/processor_builders/each_action.rb +33 -33
- data/lib/leftovers/processor_builders/each_dynamic.rb +4 -8
- data/lib/leftovers/processor_builders/each_for_definition_set.rb +25 -21
- data/lib/leftovers/processor_builders/keyword.rb +3 -4
- data/lib/leftovers/processor_builders/transform.rb +2 -2
- data/lib/leftovers/processor_builders/transform_chain.rb +16 -8
- data/lib/leftovers/processor_builders/transform_set.rb +32 -28
- data/lib/leftovers/rake_task.rb +1 -1
- data/lib/leftovers/value_processors/add_dynamic_prefix.rb +3 -10
- data/lib/leftovers/value_processors/add_dynamic_suffix.rb +3 -10
- data/lib/leftovers/value_processors/each.rb +1 -1
- data/lib/leftovers/value_processors/each_for_definition_set.rb +2 -5
- data/lib/leftovers/value_processors/each_keyword.rb +1 -1
- data/lib/leftovers/value_processors/each_keyword_argument.rb +1 -1
- data/lib/leftovers/value_processors/each_positional_argument.rb +2 -1
- data/lib/leftovers/value_processors/keyword.rb +3 -7
- data/lib/leftovers/value_processors/keyword_argument.rb +2 -6
- data/lib/leftovers/value_processors/split.rb +2 -2
- data/lib/leftovers/version.rb +1 -1
- data/lib/leftovers.rb +41 -6
- metadata +17 -7
- data/lib/leftovers/erb.rb +0 -20
- data/lib/leftovers/haml.rb +0 -21
- data/lib/leftovers/json.rb +0 -28
- data/lib/leftovers/slim.rb +0 -21
- 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
|
8
|
-
|
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)
|
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
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
-
|
49
|
-
process(ast)
|
42
|
+
CommentsProcessor.process(comments, self)
|
43
|
+
NodeProcessor.new(self).process(ast)
|
50
44
|
rescue ::Parser::SyntaxError => e
|
51
|
-
Leftovers.warn
|
52
|
-
|
53
|
-
|
54
|
-
|
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) }
|
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
|
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
|
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.
|
98
|
+
node = node.first
|
260
99
|
case node.type
|
261
|
-
|
262
|
-
when :
|
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
|
-
|
273
|
-
|
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}\
|
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
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
::
|
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
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
::Leftovers::MatcherBuilders::NodeName.build(
|
11
|
-
|
12
|
-
|
13
|
-
#
|
14
|
-
|
15
|
-
|
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
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
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
|