leftovers 0.5.4 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -1
  3. data/README.md +21 -1
  4. data/docs/Configuration.md +188 -20
  5. data/leftovers.gemspec +8 -5
  6. data/lib/config/actionmailer.yml +11 -11
  7. data/lib/config/actionpack.yml +11 -0
  8. data/lib/config/activesupport.yml +1 -1
  9. data/lib/config/rails.yml +1 -1
  10. data/lib/config/railties.yml +11 -0
  11. data/lib/config/ruby.yml +79 -0
  12. data/lib/leftovers/ast/node.rb +16 -11
  13. data/lib/leftovers/collector.rb +3 -1
  14. data/lib/leftovers/config.rb +9 -28
  15. data/lib/leftovers/config_loader/argument_position_schema.rb +11 -0
  16. data/lib/leftovers/config_loader/argumentless_transform_schema.rb +21 -0
  17. data/lib/leftovers/config_loader/attribute.rb +30 -0
  18. data/lib/leftovers/config_loader/document_schema.rb +21 -0
  19. data/lib/leftovers/config_loader/dynamic_schema.rb +17 -0
  20. data/lib/leftovers/config_loader/has_argument_schema.rb +13 -0
  21. data/lib/leftovers/config_loader/has_value_schema.rb +18 -0
  22. data/lib/leftovers/config_loader/keep_test_only_schema.rb +13 -0
  23. data/lib/leftovers/config_loader/node.rb +106 -0
  24. data/lib/leftovers/config_loader/object_schema.rb +189 -0
  25. data/lib/leftovers/config_loader/privacy_processor_schema.rb +12 -0
  26. data/lib/leftovers/config_loader/privacy_schema.rb +15 -0
  27. data/lib/leftovers/config_loader/require_schema.rb +11 -0
  28. data/lib/leftovers/config_loader/rule_pattern_schema.rb +18 -0
  29. data/lib/leftovers/config_loader/scalar_argument_schema.rb +14 -0
  30. data/lib/leftovers/config_loader/scalar_value_schema.rb +14 -0
  31. data/lib/leftovers/config_loader/schema.rb +21 -0
  32. data/lib/leftovers/config_loader/string_enum_schema.rb +62 -0
  33. data/lib/leftovers/config_loader/string_pattern_schema.rb +14 -0
  34. data/lib/leftovers/config_loader/string_schema.rb +14 -0
  35. data/lib/leftovers/config_loader/string_value_processor_schema.rb +11 -0
  36. data/lib/leftovers/config_loader/suggester.rb +22 -0
  37. data/lib/leftovers/config_loader/transform_schema.rb +28 -0
  38. data/lib/leftovers/config_loader/true_schema.rb +18 -0
  39. data/lib/leftovers/config_loader/value_matcher_schema.rb +18 -0
  40. data/lib/leftovers/config_loader/value_or_array_schema.rb +64 -0
  41. data/lib/leftovers/config_loader/value_processor_schema.rb +14 -0
  42. data/lib/leftovers/config_loader/value_type_schema.rb +17 -0
  43. data/lib/leftovers/config_loader.rb +82 -0
  44. data/lib/leftovers/definition.rb +1 -1
  45. data/lib/leftovers/definition_node.rb +6 -17
  46. data/lib/leftovers/definition_node_set.rb +11 -0
  47. data/lib/leftovers/definition_to_add.rb +31 -0
  48. data/lib/leftovers/dynamic_processors/call.rb +4 -7
  49. data/lib/leftovers/dynamic_processors/call_definition.rb +14 -11
  50. data/lib/leftovers/dynamic_processors/definition.rb +8 -7
  51. data/lib/leftovers/dynamic_processors/set_default_privacy.rb +18 -0
  52. data/lib/leftovers/dynamic_processors/set_privacy.rb +23 -0
  53. data/lib/leftovers/dynamic_processors.rb +2 -0
  54. data/lib/leftovers/file.rb +57 -11
  55. data/lib/leftovers/file_collector.rb +77 -19
  56. data/lib/leftovers/json.rb +28 -0
  57. data/lib/leftovers/matcher_builders/document.rb +13 -0
  58. data/lib/leftovers/matcher_builders/node.rb +7 -1
  59. data/lib/leftovers/matcher_builders/node_has_argument.rb +3 -4
  60. data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +1 -1
  61. data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +1 -1
  62. data/lib/leftovers/matcher_builders/node_privacy.rb +13 -0
  63. data/lib/leftovers/matcher_builders/node_type.rb +4 -4
  64. data/lib/leftovers/matcher_builders/node_value.rb +1 -1
  65. data/lib/leftovers/matcher_builders/string_pattern.rb +14 -5
  66. data/lib/leftovers/matcher_builders.rb +2 -0
  67. data/lib/leftovers/matchers/all.rb +0 -4
  68. data/lib/leftovers/matchers/and.rb +0 -4
  69. data/lib/leftovers/matchers/any.rb +0 -4
  70. data/lib/leftovers/matchers/node_has_any_keyword_argument.rb +1 -7
  71. data/lib/leftovers/matchers/node_has_any_positional_argument_with_value.rb +1 -7
  72. data/lib/leftovers/matchers/node_has_positional_argument_with_value.rb +0 -4
  73. data/lib/leftovers/matchers/node_name.rb +0 -4
  74. data/lib/leftovers/matchers/node_pair_value.rb +0 -4
  75. data/lib/leftovers/matchers/node_path.rb +0 -4
  76. data/lib/leftovers/matchers/node_privacy.rb +19 -0
  77. data/lib/leftovers/matchers/node_scalar_value.rb +0 -4
  78. data/lib/leftovers/matchers/node_type.rb +0 -4
  79. data/lib/leftovers/matchers/not.rb +0 -4
  80. data/lib/leftovers/matchers/or.rb +0 -4
  81. data/lib/leftovers/matchers.rb +1 -0
  82. data/lib/leftovers/merged_config.rb +25 -23
  83. data/lib/leftovers/processor_builders/add_prefix.rb +1 -1
  84. data/lib/leftovers/processor_builders/add_suffix.rb +1 -1
  85. data/lib/leftovers/processor_builders/dynamic.rb +51 -16
  86. data/lib/leftovers/processor_builders/transform.rb +2 -2
  87. data/lib/leftovers/processor_builders/transform_set.rb +8 -8
  88. data/lib/leftovers/todo_reporter.rb +10 -35
  89. data/lib/leftovers/value_processors/delete_prefix.rb +0 -6
  90. data/lib/leftovers/value_processors/delete_suffix.rb +0 -6
  91. data/lib/leftovers/value_processors/each_for_definition_set.rb +2 -5
  92. data/lib/leftovers/value_processors/each_positional_argument.rb +1 -1
  93. data/lib/leftovers/value_processors/keyword.rb +0 -4
  94. data/lib/leftovers/value_processors/keyword_argument.rb +0 -4
  95. data/lib/leftovers/value_processors/return_definition_node.rb +14 -0
  96. data/lib/leftovers/value_processors/{return_string.rb → return_sym.rb} +1 -1
  97. data/lib/leftovers/value_processors.rb +2 -2
  98. data/lib/leftovers/version.rb +1 -1
  99. data/lib/leftovers/yaml.rb +73 -0
  100. data/lib/leftovers.rb +29 -21
  101. metadata +85 -36
  102. data/lib/config/actioncable.yml +0 -4
  103. data/lib/leftovers/backports.rb +0 -40
  104. data/lib/leftovers/config_validator/error_processor.rb +0 -196
  105. data/lib/leftovers/config_validator/schema_hash.rb +0 -530
  106. data/lib/leftovers/config_validator.rb +0 -60
  107. data/lib/leftovers/value_processors/return_definition.rb +0 -26
@@ -5,7 +5,11 @@ require 'pathname'
5
5
  module Leftovers
6
6
  class File < Pathname
7
7
  def relative_path
8
- @relative_path ||= relative_path_from(Leftovers.pwd)
8
+ @relative_path ||= begin
9
+ relative_path_from(Leftovers.pwd)
10
+ rescue ArgumentError
11
+ self
12
+ end
9
13
  end
10
14
 
11
15
  def test?
@@ -14,20 +18,62 @@ module Leftovers
14
18
  @test = Leftovers.config.test_paths.allowed?(relative_path)
15
19
  end
16
20
 
17
- def ruby
18
- precompiler&.precompile(read, self) || read
21
+ def ruby # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
22
+ precompiled = []
23
+ precompile = false
24
+
25
+ if haml?
26
+ precompiled << ::Leftovers::Haml.precompile(read, self)
27
+ precompile = true
28
+ end
29
+
30
+ if json?
31
+ precompiled << ::Leftovers::JSON.precompile(read, self)
32
+ precompile = true
33
+ end
34
+
35
+ if erb?
36
+ precompiled << ::Leftovers::ERB.precompile(read, self)
37
+ precompile = true
38
+ end
39
+
40
+ if slim?
41
+ precompiled << ::Leftovers::Slim.precompile(read, self)
42
+ precompile = true
43
+ end
44
+
45
+ if yaml?
46
+ precompiled << ::Leftovers::YAML.precompile(read, self)
47
+ precompile = true
48
+ end
49
+
50
+ if precompile
51
+ precompiled.join("\n")
52
+ else
53
+ read
54
+ end
19
55
  end
20
56
 
21
57
  private
22
58
 
23
- def precompiler
24
- if Leftovers.config.haml_paths.allowed?(relative_path)
25
- ::Leftovers::Haml
26
- elsif Leftovers.config.slim_paths.allowed?(relative_path)
27
- ::Leftovers::Slim
28
- elsif Leftovers.config.erb_paths.allowed?(relative_path)
29
- ::Leftovers::ERB
30
- end
59
+ def erb?
60
+ Leftovers.config.erb_paths.allowed?(relative_path)
61
+ end
62
+
63
+ def haml?
64
+ Leftovers.config.haml_paths.allowed?(relative_path)
65
+ end
66
+
67
+ def yaml?
68
+ Leftovers.config.yaml_paths.allowed?(relative_path)
69
+ end
70
+
71
+ def json?
72
+ Leftovers.config.json_paths.allowed?(relative_path)
73
+ end
74
+
75
+ def slim?
76
+ Leftovers.config.slim_paths.allowed?(relative_path)
31
77
  end
32
78
  end
33
79
  end
@@ -5,15 +5,19 @@ require 'parser'
5
5
 
6
6
  module Leftovers
7
7
  class FileCollector < ::Parser::AST::Processor # rubocop:disable Metrics/ClassLength
8
- attr_reader :calls, :definitions
8
+ attr_reader :calls
9
+ attr_accessor :default_method_privacy
9
10
 
10
11
  def initialize(ruby, file) # rubocop:disable Lint/MissingSuper
11
12
  @calls = []
12
- @definitions = []
13
+ @definitions_to_add = {}
13
14
  @allow_lines = Set.new.compare_by_identity
14
15
  @test_lines = Set.new.compare_by_identity
16
+ @dynamic_lines = {}
15
17
  @ruby = ruby
16
18
  @file = file
19
+ @default_method_privacy = :public
20
+ @definition_sets_to_add = []
17
21
  end
18
22
 
19
23
  def filename
@@ -37,7 +41,6 @@ module Leftovers
37
41
  definitions.flatten!
38
42
  definitions.compact!
39
43
  definitions.uniq!
40
- definitions.reject! { |v| v == :keep }
41
44
  end
42
45
 
43
46
  def collect
@@ -58,19 +61,29 @@ module Leftovers
58
61
  LEFTOVERS_CALL_RE = /\bleftovers:call(?:s|ed|er|ers|) (#{NAME_RE}(?:[, :]+#{NAME_RE})*)/.freeze
59
62
  LEFTOVERS_ALLOW_RE = /\bleftovers:(?:keeps?|skip(?:s|ped|)|allow(?:s|ed|))\b/.freeze
60
63
  LEFTOVERS_TEST_RE = /\bleftovers:(?:for_tests?|tests?|testing|test_only)\b/.freeze
64
+ LEFTOVERS_DYNAMIC_RE = /\bleftovers:dynamic:(#{NAME_RE})\b/.freeze
65
+
61
66
  def process_comments(comments) # rubocop:disable Metrics/AbcSize
62
67
  comments.each do |comment|
63
68
  @allow_lines << comment.loc.line if comment.text.match?(LEFTOVERS_ALLOW_RE)
64
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
65
72
 
66
- next unless (match = comment.text.match(LEFTOVERS_CALL_RE))
73
+ next unless (call_match = comment.text.match(LEFTOVERS_CALL_RE))
67
74
 
68
- match[1].scan(NAME_RE).each { |s| add_call(s.to_sym) }
75
+ call_match[1].scan(NAME_RE).each { |s| add_call(s.to_sym) }
69
76
  end
70
77
  end
71
78
 
72
79
  # grab method definitions
73
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)
74
87
  add_definition(node)
75
88
  super
76
89
  end
@@ -136,6 +149,16 @@ module Leftovers
136
149
  add_call(node.name)
137
150
  end
138
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
+
139
162
  # grab e.g. :to_s in each(&:to_s)
140
163
  def on_block_pass(node)
141
164
  super
@@ -169,24 +192,41 @@ module Leftovers
169
192
  add_call(original_method.children.first)
170
193
  end
171
194
 
172
- private
195
+ 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)
198
+ end
173
199
 
174
- def test_line?(loc)
175
- @file.test? ||
176
- @test_lines.include?(loc.line)
200
+ def add_definition_set(definition_node_set)
201
+ @definition_sets_to_add << definition_node_set.definitions.map do |definition_node|
202
+ ::Leftovers::DefinitionToAdd.new(definition_node, location: definition_node.loc)
203
+ end
177
204
  end
178
205
 
179
- def test_node?(node, loc)
180
- test_line?(loc) || ::Leftovers.config.test_only === node
206
+ def set_privacy(name, to)
207
+ @definitions_to_add[name]&.privacy = to
181
208
  end
182
209
 
183
- def add_definition(node, name: node.name, loc: node.loc.name)
184
- return if @allow_lines.include?(loc.line)
185
- return if Leftovers.config.keep === node
210
+ def definitions
211
+ @definitions ||= @definitions_to_add.each_value.map { |d| d.to_definition(self) }.compact +
212
+ @definition_sets_to_add.map do |definition_set|
213
+ next nil if definition_set.any? { |d| d.keep?(self) }
214
+
215
+ ::Leftovers::DefinitionSet.new(definition_set.map { |d| d.to_definition(self) })
216
+ end.compact
217
+ end
218
+
219
+ def test_line?(line)
220
+ @file.test? ||
221
+ @test_lines.include?(line)
222
+ end
186
223
 
187
- definitions << Leftovers::Definition.new(name, location: loc, test: test_node?(node, loc))
224
+ def keep_line?(line)
225
+ @allow_lines.include?(line)
188
226
  end
189
227
 
228
+ private
229
+
190
230
  def add_call(name)
191
231
  calls << name
192
232
  end
@@ -217,17 +257,35 @@ module Leftovers
217
257
 
218
258
  def collect_op_asgn(node)
219
259
  node = node.children.first
220
- # :nocov: # don't need else, it's exhaustive for callers
221
260
  case node.type
222
- # :nocov:
223
261
  when :send then collect_send_op_asgn(node)
224
262
  when :ivasgn, :gvasgn, :cvasgn then collect_var_op_asgn(node)
263
+ when :lvasgn then nil # we don't care about lvasgn
264
+ # :nocov:
265
+ else
266
+ raise "Unrecognized op_asgn node type #{node.type}"
267
+ # :nocov:
225
268
  end
226
269
  end
227
270
 
228
- def collect_dynamic(node) # rubocop:disable Metrics/AbcSize
271
+ 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
+ )
285
+ end
286
+
287
+ def collect_dynamic(node)
229
288
  node.keep_line = @allow_lines.include?(node.loc.line)
230
- node.test_line = test_line?(node.loc) unless node.keep_line?
231
289
 
232
290
  Leftovers.config.dynamic.process(node, self)
233
291
  rescue StandardError => e
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Leftovers
6
+ module JSON
7
+ class << self
8
+ def precompile(json, name)
9
+ "__leftovers_document(#{to_ruby_argument(::JSON.parse(json))})"
10
+ rescue ::JSON::ParserError => e
11
+ Leftovers.warn "#{e.class}: (#{name.relative_path}): #{e.message}"
12
+ ''
13
+ end
14
+
15
+ private
16
+
17
+ def to_ruby_argument(value)
18
+ ruby = value.inspect
19
+ return ruby unless value.is_a?(Array)
20
+
21
+ ruby.delete_prefix!('[')
22
+ ruby.delete_suffix!(']')
23
+
24
+ ruby
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ module MatcherBuilders
5
+ module Document
6
+ def self.build(true_arg)
7
+ return unless true_arg
8
+
9
+ ::Leftovers::Matchers::NodeName.new(:__leftovers_document)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -10,7 +10,7 @@ module Leftovers
10
10
  ::Leftovers::MatcherBuilders::NodeName.build(pat)
11
11
  when ::Hash
12
12
  build_from_hash(**pat)
13
- # :nocov:
13
+ # :nocov:
14
14
  else raise
15
15
  # :nocov:
16
16
  end
@@ -19,9 +19,12 @@ module Leftovers
19
19
 
20
20
  def self.build_from_hash( # rubocop:disable Metrics/ParameterLists, Metrics/MethodLength
21
21
  names: nil, match: nil, has_prefix: nil, has_suffix: nil,
22
+ document: false,
22
23
  paths: nil,
23
24
  has_arguments: nil,
24
25
  has_receiver: nil,
26
+ type: nil,
27
+ privacy: nil,
25
28
  unless_arg: nil
26
29
  )
27
30
  ::Leftovers::MatcherBuilders::And.build([
@@ -29,9 +32,12 @@ module Leftovers
29
32
  names,
30
33
  { match: match, has_prefix: has_prefix, has_suffix: has_suffix }.compact
31
34
  ]),
35
+ ::Leftovers::MatcherBuilders::Document.build(document),
32
36
  ::Leftovers::MatcherBuilders::NodePath.build(paths),
33
37
  ::Leftovers::MatcherBuilders::NodeHasArgument.build(has_arguments),
34
38
  ::Leftovers::MatcherBuilders::NodeHasReceiver.build(has_receiver),
39
+ ::Leftovers::MatcherBuilders::NodePrivacy.build(privacy),
40
+ ::Leftovers::MatcherBuilders::NodeType.build(type),
35
41
  ::Leftovers::MatcherBuilders::Unless.build(
36
42
  (::Leftovers::MatcherBuilders::Node.build(unless_arg) if unless_arg)
37
43
  )
@@ -26,12 +26,10 @@ module Leftovers
26
26
 
27
27
  ::Leftovers.each_or_self(at) do |k|
28
28
  case k
29
- when '*'
29
+ when '*', ::Integer
30
30
  positions << k
31
31
  when ::String, ::Hash
32
32
  keys << k
33
- when ::Integer
34
- positions << k
35
33
  # :nocov:
36
34
  else raise
37
35
  # :nocov:
@@ -62,7 +60,8 @@ module Leftovers
62
60
  elsif positions
63
61
  ::Leftovers::MatcherBuilders::NodeHasPositionalArgument.build(positions, value_matcher)
64
62
  # :nocov:
65
- else raise
63
+ else
64
+ raise
66
65
  # :nocov:
67
66
  end
68
67
 
@@ -6,7 +6,7 @@ module Leftovers
6
6
  class << self
7
7
  def build(keywords, value_matcher) # rubocop:disable Metrics/MethodLength
8
8
  value_matcher = ::Leftovers::MatcherBuilders::NodePairValue.build(value_matcher)
9
- keyword_matcher = if ::Leftovers.each_or_self(keywords).any? { |x| x == '**' }
9
+ keyword_matcher = if ::Leftovers.each_or_self(keywords).include?('**')
10
10
  ::Leftovers::Matchers::NodeType.new(:pair)
11
11
  else
12
12
  ::Leftovers::MatcherBuilders::NodePairName.build(keywords)
@@ -14,7 +14,7 @@ module Leftovers
14
14
  end
15
15
  end
16
16
  elsif positions
17
- pos = 0 if ::Leftovers.each_or_self(positions).any? { |x| x == '*' }
17
+ pos = 0 if ::Leftovers.each_or_self(positions).include?('*')
18
18
  pos ||= ::Leftovers.each_or_self(positions).min
19
19
 
20
20
  ::Leftovers::Matchers::NodeHasPositionalArgument.new(pos)
@@ -0,0 +1,13 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Leftovers
4
+ module MatcherBuilders
5
+ module NodePrivacy
6
+ def self.build(privacy_settings)
7
+ ::Leftovers::MatcherBuilders::Or.each_or_self(privacy_settings) do |privacy|
8
+ ::Leftovers::Matchers::NodePrivacy.new(privacy)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -14,12 +14,12 @@ module Leftovers
14
14
  when 'Float' then ::Leftovers::Matchers::NodeType.new(:float)
15
15
  when 'Array' then ::Leftovers::Matchers::NodeType.new(:array)
16
16
  when 'Hash' then ::Leftovers::Matchers::NodeType.new(:hash)
17
-
18
17
  when 'Proc' then ::Leftovers::Matchers::Predicate.new(:proc?)
19
- # when 'Method' then ::Leftovers::Matchers::NodeType.new(Set[:send, :csend, :def])
20
- # when 'Constant' then ::Leftovers::Matchers::NodeType.new(Set[:const, :class, :module])
18
+ when 'Method' then ::Leftovers::Matchers::NodeType.new(Set[:send, :csend, :def, :defs])
19
+ when 'Constant'
20
+ ::Leftovers::Matchers::NodeType.new(Set[:const, :class, :module, :casgn])
21
21
  # :nocov:
22
- else raise
22
+ else raise "Unknown type #{type}"
23
23
  # :nocov:
24
24
  end
25
25
  end
@@ -7,7 +7,7 @@ module Leftovers
7
7
  def build(pattern) # rubocop:disable Metrics/MethodLength
8
8
  ::Leftovers::MatcherBuilders::Or.each_or_self(pattern) do |pat|
9
9
  case pat
10
- when ::Integer, true, false, nil
10
+ when ::Integer, ::Float, true, false, nil
11
11
  ::Leftovers::Matchers::NodeScalarValue.new(pat)
12
12
  when ::String
13
13
  ::Leftovers::MatcherBuilders::NodeName.build(pat)
@@ -3,15 +3,24 @@
3
3
  module Leftovers
4
4
  module MatcherBuilders
5
5
  module StringPattern
6
- def self.build(match: nil, has_prefix: nil, has_suffix: nil)
7
- if match
6
+ def self.build(match: nil, has_prefix: nil, has_suffix: nil) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
7
+ has_prefix = ::Regexp.escape(has_prefix) if has_prefix
8
+ has_suffix = ::Regexp.escape(has_suffix) if has_suffix
9
+
10
+ if match && has_prefix && has_suffix
11
+ /\A(?=#{match}\z)(?=#{has_prefix}).*#{has_suffix}\z/
12
+ elsif match && has_prefix
13
+ /\A(?=#{match}\z)#{has_prefix}/
14
+ elsif match && has_suffix
15
+ /\A(?=#{match}\z).*#{has_suffix}\z/
16
+ elsif match
8
17
  /\A#{match}\z/
9
18
  elsif has_prefix && has_suffix
10
- /\A#{::Regexp.escape(has_prefix)}.*#{::Regexp.escape(has_suffix)}\z/
19
+ /\A(?=#{has_prefix}).*#{has_suffix}\z/
11
20
  elsif has_prefix
12
- /\A#{::Regexp.escape(has_prefix)}/
21
+ /\A#{has_prefix}/
13
22
  elsif has_suffix
14
- /#{::Regexp.escape(has_suffix)}\z/
23
+ /#{has_suffix}\z/
15
24
  end
16
25
  end
17
26
  end
@@ -4,6 +4,7 @@ module Leftovers
4
4
  module MatcherBuilders
5
5
  autoload(:AndNot, "#{__dir__}/matcher_builders/and_not")
6
6
  autoload(:And, "#{__dir__}/matcher_builders/and")
7
+ autoload(:Document, "#{__dir__}/matcher_builders/document")
7
8
  autoload(:Name, "#{__dir__}/matcher_builders/name")
8
9
  autoload(:Node, "#{__dir__}/matcher_builders/node")
9
10
  autoload(:NodeHasArgument, "#{__dir__}/matcher_builders/node_has_argument")
@@ -14,6 +15,7 @@ module Leftovers
14
15
  autoload(:NodePairName, "#{__dir__}/matcher_builders/node_pair_name")
15
16
  autoload(:NodePairValue, "#{__dir__}/matcher_builders/node_pair_value")
16
17
  autoload(:NodePath, "#{__dir__}/matcher_builders/node_path")
18
+ autoload(:NodePrivacy, "#{__dir__}/matcher_builders/node_privacy")
17
19
  autoload(:NodeType, "#{__dir__}/matcher_builders/node_type")
18
20
  autoload(:NodeValue, "#{__dir__}/matcher_builders/node_value")
19
21
  autoload(:Or, "#{__dir__}/matcher_builders/or")
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class All
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(matchers)
11
7
  @matchers = matchers
12
8
 
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class And
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(lhs, rhs)
11
7
  @lhs = lhs
12
8
  @rhs = rhs
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class Any
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  attr_reader :matchers
11
7
 
12
8
  def initialize(matchers)
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class NodeHasAnyKeywordArgument
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(pair_matcher)
11
7
  @pair_matcher = pair_matcher
12
8
 
@@ -17,9 +13,7 @@ module Leftovers
17
13
  kwargs = node.kwargs
18
14
  return false unless kwargs
19
15
 
20
- kwargs.children.any? do |pair|
21
- @pair_matcher === pair
22
- end
16
+ kwargs.children.any?(@pair_matcher)
23
17
  end
24
18
 
25
19
  freeze
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class NodeHasAnyPositionalArgumentWithValue
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(matcher)
11
7
  @matcher = matcher
12
8
 
@@ -17,9 +13,7 @@ module Leftovers
17
13
  args = node.positional_arguments
18
14
  return false unless args
19
15
 
20
- args.any? do |value|
21
- @matcher === value
22
- end
16
+ args.any?(@matcher)
23
17
  end
24
18
 
25
19
  freeze
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class NodeHasPositionalArgumentWithValue
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(position, matcher)
11
7
  @position = position
12
8
  @matcher = matcher
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class NodeName
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(name_matcher)
11
7
  @name_matcher = name_matcher
12
8
 
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class NodePairValue
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(value_matcher)
11
7
  @value_matcher = value_matcher
12
8
 
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class NodePath
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(path_matcher)
11
7
  @path_matcher = path_matcher
12
8
 
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ module Matchers
5
+ class NodePrivacy
6
+ def initialize(privacy_matcher)
7
+ @privacy_matcher = privacy_matcher
8
+
9
+ freeze
10
+ end
11
+
12
+ def ===(node)
13
+ @privacy_matcher === node.privacy
14
+ end
15
+
16
+ freeze
17
+ end
18
+ end
19
+ end
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class NodeScalarValue
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(matcher)
11
7
  @matcher = matcher
12
8
 
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class NodeType
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(type_matcher)
11
7
  @type_matcher = type_matcher
12
8
 
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class Not
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(matcher)
11
7
  @matcher = matcher
12
8
 
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class Or
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  attr_reader :lhs, :rhs
11
7
 
12
8
  def initialize(lhs, rhs)
@@ -19,6 +19,7 @@ module Leftovers
19
19
  autoload(:NodeName, "#{__dir__}/matchers/node_name")
20
20
  autoload(:NodePairValue, "#{__dir__}/matchers/node_pair_value")
21
21
  autoload(:NodePath, "#{__dir__}/matchers/node_path")
22
+ autoload(:NodePrivacy, "#{__dir__}/matchers/node_privacy")
22
23
  autoload(:NodeScalarValue, "#{__dir__}/matchers/node_scalar_value")
23
24
  autoload(:NodeType, "#{__dir__}/matchers/node_type")
24
25
  autoload(:Not, "#{__dir__}/matchers/not")