leftovers 0.11.1 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/README.md +1 -0
  4. data/docs/Configuration.md +7 -0
  5. data/exe/leftovers +3 -1
  6. data/leftovers.gemspec +3 -4
  7. data/lib/config/activesupport.yml +1 -1
  8. data/lib/config/rspec.yml +21 -0
  9. data/lib/leftovers/ast/array_node.rb +2 -2
  10. data/lib/leftovers/ast/block_node.rb +1 -1
  11. data/lib/leftovers/ast/builder.rb +19 -18
  12. data/lib/leftovers/ast/casgn_node.rb +2 -2
  13. data/lib/leftovers/ast/const_node.rb +1 -1
  14. data/lib/leftovers/ast/def_node.rb +1 -1
  15. data/lib/leftovers/ast/defs_node.rb +1 -1
  16. data/lib/leftovers/ast/false_node.rb +1 -1
  17. data/lib/leftovers/ast/hash_node.rb +2 -2
  18. data/lib/leftovers/ast/module_node.rb +1 -1
  19. data/lib/leftovers/ast/nil_node.rb +1 -1
  20. data/lib/leftovers/ast/node.rb +13 -1
  21. data/lib/leftovers/ast/numeric_node.rb +1 -1
  22. data/lib/leftovers/ast/send_node.rb +16 -3
  23. data/lib/leftovers/ast/str_node.rb +1 -1
  24. data/lib/leftovers/ast/sym_node.rb +1 -1
  25. data/lib/leftovers/ast/true_node.rb +1 -1
  26. data/lib/leftovers/ast/var_node.rb +1 -1
  27. data/lib/leftovers/ast/vasgn_node.rb +2 -2
  28. data/lib/leftovers/ast.rb +2 -21
  29. data/lib/leftovers/autoloader.rb +36 -0
  30. data/lib/leftovers/cli.rb +64 -45
  31. data/lib/leftovers/collection.rb +66 -0
  32. data/lib/leftovers/collector.rb +17 -27
  33. data/lib/leftovers/config.rb +17 -5
  34. data/lib/leftovers/config_loader/attribute.rb +2 -2
  35. data/lib/leftovers/config_loader/bool_schema.rb +21 -0
  36. data/lib/leftovers/config_loader/document_schema.rb +2 -2
  37. data/lib/leftovers/config_loader/inherit_schema_attributes.rb +1 -1
  38. data/lib/leftovers/config_loader/node.rb +8 -8
  39. data/lib/leftovers/config_loader/regexp_schema.rb +1 -1
  40. data/lib/leftovers/config_loader/rule_pattern_schema.rb +1 -0
  41. data/lib/leftovers/config_loader/schema.rb +1 -1
  42. data/lib/leftovers/config_loader/string_enum_schema.rb +1 -1
  43. data/lib/leftovers/config_loader/value_or_array_schema.rb +1 -1
  44. data/lib/leftovers/config_loader.rb +8 -48
  45. data/lib/leftovers/definition.rb +4 -4
  46. data/lib/leftovers/definition_collection.rb +3 -3
  47. data/lib/leftovers/definition_node.rb +2 -2
  48. data/lib/leftovers/definition_node_set.rb +1 -1
  49. data/lib/leftovers/definition_set.rb +4 -4
  50. data/lib/leftovers/definition_to_add.rb +2 -2
  51. data/lib/leftovers/error.rb +6 -0
  52. data/lib/leftovers/file.rb +4 -4
  53. data/lib/leftovers/file_collector/comments_processor.rb +23 -18
  54. data/lib/leftovers/file_collector/node_processor/error.rb +16 -0
  55. data/lib/leftovers/file_collector/node_processor.rb +19 -2
  56. data/lib/leftovers/file_collector.rb +28 -20
  57. data/lib/leftovers/file_list.rb +4 -6
  58. data/lib/leftovers/matcher_builders/and.rb +5 -5
  59. data/lib/leftovers/matcher_builders/document.rb +1 -3
  60. data/lib/leftovers/matcher_builders/name.rb +4 -7
  61. data/lib/leftovers/matcher_builders/node.rb +21 -35
  62. data/lib/leftovers/matcher_builders/node_has_argument.rb +17 -29
  63. data/lib/leftovers/matcher_builders/node_has_block.rb +17 -0
  64. data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +7 -9
  65. data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +10 -10
  66. data/lib/leftovers/matcher_builders/node_has_receiver.rb +6 -8
  67. data/lib/leftovers/matcher_builders/node_name.rb +3 -5
  68. data/lib/leftovers/matcher_builders/node_pair_key.rb +4 -4
  69. data/lib/leftovers/matcher_builders/node_pair_value.rb +4 -4
  70. data/lib/leftovers/matcher_builders/node_path.rb +3 -4
  71. data/lib/leftovers/matcher_builders/node_privacy.rb +3 -3
  72. data/lib/leftovers/matcher_builders/node_type.rb +18 -13
  73. data/lib/leftovers/matcher_builders/node_value.rb +18 -31
  74. data/lib/leftovers/matcher_builders/or.rb +10 -10
  75. data/lib/leftovers/matcher_builders/path.rb +3 -3
  76. data/lib/leftovers/matcher_builders/string_pattern.rb +2 -0
  77. data/lib/leftovers/matcher_builders/unless.rb +1 -3
  78. data/lib/leftovers/matcher_builders.rb +2 -22
  79. data/lib/leftovers/matchers/node_has_block.rb +13 -0
  80. data/lib/leftovers/matchers/node_scalar_value.rb +1 -1
  81. data/lib/leftovers/matchers.rb +2 -27
  82. data/lib/leftovers/merged_config.rb +16 -17
  83. data/lib/leftovers/parser.rb +1 -1
  84. data/lib/leftovers/precompile_error.rb +31 -0
  85. data/lib/leftovers/precompilers/haml.rb +23 -3
  86. data/lib/leftovers/precompilers/json.rb +1 -1
  87. data/lib/leftovers/precompilers/precompiler.rb +3 -3
  88. data/lib/leftovers/precompilers/slim.rb +1 -1
  89. data/lib/leftovers/precompilers/yaml/builder.rb +62 -0
  90. data/lib/leftovers/precompilers/yaml.rb +3 -56
  91. data/lib/leftovers/precompilers.rb +11 -16
  92. data/lib/leftovers/processor_builders/action.rb +15 -19
  93. data/lib/leftovers/processor_builders/add_prefix.rb +4 -6
  94. data/lib/leftovers/processor_builders/add_suffix.rb +4 -6
  95. data/lib/leftovers/processor_builders/argument.rb +10 -15
  96. data/lib/leftovers/processor_builders/dynamic.rb +12 -30
  97. data/lib/leftovers/processor_builders/each.rb +63 -76
  98. data/lib/leftovers/processor_builders/each_for_definition_set.rb +15 -0
  99. data/lib/leftovers/processor_builders/itself.rb +2 -4
  100. data/lib/leftovers/processor_builders/keyword.rb +4 -4
  101. data/lib/leftovers/processor_builders/keyword_argument.rb +4 -4
  102. data/lib/leftovers/processor_builders/receiver.rb +2 -4
  103. data/lib/leftovers/processor_builders/transform.rb +26 -49
  104. data/lib/leftovers/processor_builders/transform_chain.rb +4 -7
  105. data/lib/leftovers/processor_builders/transform_set.rb +6 -7
  106. data/lib/leftovers/processor_builders/value.rb +2 -2
  107. data/lib/leftovers/processor_builders.rb +2 -15
  108. data/lib/leftovers/processors/add_definition_node.rb +2 -2
  109. data/lib/leftovers/processors/camelize.rb +3 -3
  110. data/lib/leftovers/processors/deconstantize.rb +3 -3
  111. data/lib/leftovers/processors/demodulize.rb +3 -3
  112. data/lib/leftovers/processors/each_for_definition_set.rb +2 -2
  113. data/lib/leftovers/processors/eval.rb +1 -1
  114. data/lib/leftovers/processors/parameterize.rb +3 -3
  115. data/lib/leftovers/processors/placeholder.rb +1 -1
  116. data/lib/leftovers/processors/pluralize.rb +3 -3
  117. data/lib/leftovers/processors/set_default_privacy.rb +1 -1
  118. data/lib/leftovers/processors/set_privacy.rb +1 -1
  119. data/lib/leftovers/processors/singularize.rb +3 -3
  120. data/lib/leftovers/processors/titleize.rb +3 -3
  121. data/lib/leftovers/processors/underscore.rb +3 -3
  122. data/lib/leftovers/processors.rb +2 -44
  123. data/lib/leftovers/rake_task.rb +2 -2
  124. data/lib/leftovers/reporter.rb +44 -42
  125. data/lib/leftovers/runner.rb +40 -0
  126. data/lib/leftovers/todo_reporter.rb +96 -94
  127. data/lib/leftovers/unexpected_case.rb +8 -0
  128. data/lib/leftovers/version.rb +1 -1
  129. data/lib/leftovers.rb +23 -108
  130. metadata +15 -18
  131. data/lib/leftovers/matcher_builders/and_not.rb +0 -16
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class FileCollector
5
+ class NodeProcessor
6
+ class Error < ::Leftovers::FileCollector::Error
7
+ attr_reader :node
8
+
9
+ def initialize(message, node)
10
+ super(message)
11
+ @node = node
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,10 +1,20 @@
1
- # frozen-string-literal: true
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'parser'
4
4
 
5
5
  module Leftovers
6
6
  class FileCollector
7
- class NodeProcessor < ::Parser::AST::Processor
7
+ class NodeProcessor < ::Parser::AST::Processor # rubocop:disable Metrics/ClassLength
8
+ include Autoloader
9
+
10
+ def process(ast)
11
+ super
12
+ rescue FileCollector::Error
13
+ raise
14
+ rescue StandardError => e
15
+ raise Error.new(e.message, ast)
16
+ end
17
+
8
18
  def initialize(collector) # rubocop:disable Lint/MissingSuper # there isn't one to call
9
19
  @collector = collector
10
20
  end
@@ -90,6 +100,13 @@ module Leftovers
90
100
  @collector.collect_commented_dynamic(node)
91
101
  end
92
102
 
103
+ # why are block args the parent of send/csend
104
+ def on_block(node)
105
+ node.first.parent = node
106
+
107
+ super
108
+ end
109
+
93
110
  # grab e.g. :to_s in each(&:to_s)
94
111
  def on_block_pass(node)
95
112
  super
@@ -4,17 +4,18 @@ require 'set'
4
4
 
5
5
  module Leftovers
6
6
  class FileCollector
7
- autoload(:CommentsProcessor, "#{__dir__}/file_collector/comments_processor.rb")
8
- autoload(:NodeProcessor, "#{__dir__}/file_collector/node_processor.rb")
7
+ class Error < ::Leftovers::Error; end
8
+
9
+ include Autoloader
9
10
 
10
11
  attr_reader :calls, :allow_lines, :test_lines, :dynamic_lines
11
12
  attr_accessor :default_method_privacy
12
13
 
13
14
  def initialize(ruby, file)
14
15
  @calls = []
15
- @definition_collection = Leftovers::DefinitionCollection.new
16
- @allow_lines = Set.new.compare_by_identity
17
- @test_lines = Set.new.compare_by_identity
16
+ @definition_collection = DefinitionCollection.new
17
+ @allow_lines = ::Set.new.compare_by_identity
18
+ @test_lines = ::Set.new.compare_by_identity
18
19
  @dynamic_lines = {}
19
20
  @ruby = ruby
20
21
  @file = file
@@ -26,7 +27,7 @@ module Leftovers
26
27
  end
27
28
 
28
29
  def to_h
29
- { test?: @file.test?, calls: squash!(calls), definitions: squash!(definitions) }
30
+ { test: @file.test?, calls: squash!(calls), definitions: squash!(definitions) }
30
31
  end
31
32
 
32
33
  def squash!(list)
@@ -36,15 +37,27 @@ module Leftovers
36
37
  list
37
38
  end
38
39
 
39
- def collect(ruby = @ruby, line = 1)
40
- ast, comments = Leftovers::Parser.parse_with_comments(ruby, @file.relative_path, line)
40
+ def collect(ruby = @ruby, line = 1) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
41
+ ast, comments = Parser.parse_with_comments(ruby, @file.relative_path, line)
41
42
  CommentsProcessor.process(comments, self)
42
43
  NodeProcessor.new(self).process(ast)
43
44
  rescue ::Parser::SyntaxError => e
44
- Leftovers.warn(
45
- "\e[31m#{filename}:#{e.diagnostic.location.line}:#{e.diagnostic.location.column} " \
46
- "SyntaxError: #{e.message}\e[0m"
47
- )
45
+ raise Error, <<~MESSAGE.chomp, e.backtrace
46
+ SyntaxError: #{e.message}
47
+ when processing #{filename}:#{e.diagnostic.location.line}:#{e.diagnostic.location.column}
48
+ MESSAGE
49
+ rescue NodeProcessor::Error => e
50
+ raise Error, <<~MESSAGE.chomp, e.backtrace
51
+ #{e.cause.class}: #{e.message}
52
+ when processing #{e.node} at #{filename}:#{e.node.loc.line}:#{e.node.loc.column}
53
+ MESSAGE
54
+ rescue Error
55
+ raise
56
+ rescue ::StandardError => e
57
+ raise Error, <<~MESSAGE.chomp, e.backtrace
58
+ #{e.class}: #{e.message}
59
+ when processing #{filename}
60
+ MESSAGE
48
61
  end
49
62
 
50
63
  def collect_subfile(string, location)
@@ -100,7 +113,7 @@ module Leftovers
100
113
  when :lvasgn then nil # we don't check local variable use, rubocop already covers this
101
114
 
102
115
  # :nocov:
103
- else raise Leftovers::UnexpectedCase, "Unhandled value #{node.type.inspect}"
116
+ else raise UnexpectedCase, "Unhandled value #{node.type.inspect}"
104
117
  # :nocov:
105
118
  end
106
119
  end
@@ -112,18 +125,13 @@ module Leftovers
112
125
  end
113
126
 
114
127
  def collect_dynamic(node)
115
- Leftovers.config.dynamic.process(nil, node, node, self)
116
- rescue StandardError => e
117
- raise ::Leftovers::Error, "#{e.class}: #{e.message}\n" \
118
- "when processing #{node} at #{filename}:#{node.loc.line}:#{node.loc.column}", e.backtrace
128
+ ::Leftovers.config.dynamic.process(nil, node, node, self)
119
129
  end
120
130
 
121
131
  private
122
132
 
123
133
  def build_send_wrapper_for(node, name)
124
- ::Leftovers::AST::SendNode.new(
125
- :send, [nil, name.to_sym, *node.arguments], location: node.location
126
- )
134
+ AST::SendNode.new(:send, [nil, name.to_sym, *node.arguments], location: node.location)
127
135
  end
128
136
  end
129
137
  end
@@ -6,17 +6,15 @@ module Leftovers
6
6
  class FileList < ::FastIgnore
7
7
  def initialize(**arguments)
8
8
  super(
9
- ignore_rules: Leftovers.config.exclude_paths,
10
- include_rules: Leftovers.config.include_paths,
11
- root: Leftovers.pwd,
9
+ ignore_rules: ::Leftovers.config.exclude_paths,
10
+ include_rules: ::Leftovers.config.include_paths,
11
+ root: ::Leftovers.pwd,
12
12
  **arguments
13
13
  )
14
14
  end
15
15
 
16
16
  def each
17
- super do |file|
18
- yield(Leftovers::File.new(file))
19
- end
17
+ super { |file| yield(File.new(file)) }
20
18
  end
21
19
  end
22
20
  end
@@ -9,8 +9,8 @@ module Leftovers
9
9
  case matchers.length
10
10
  when 0 then nil
11
11
  when 1 then matchers.first
12
- when 2 then ::Leftovers::Matchers::And.new(matchers.first, matchers[1])
13
- else ::Leftovers::Matchers::All.new(matchers.dup)
12
+ when 2 then Matchers::And.new(matchers.first, matchers[1])
13
+ else Matchers::All.new(matchers.dup)
14
14
  end
15
15
  end
16
16
 
@@ -18,13 +18,13 @@ module Leftovers
18
18
 
19
19
  def flatten(value)
20
20
  case value
21
- when ::Leftovers::Matchers::And
21
+ when Matchers::And
22
22
  [*flatten(value.lhs), *flatten(value.rhs)]
23
23
  # :nocov: # not sure how to make this happen
24
- when ::Leftovers::Matchers::All
24
+ when Matchers::All
25
25
  flatten(value.matchers)
26
26
  # :nocov:
27
- when Array
27
+ when ::Array
28
28
  value.flat_map { |v| flatten(v) }
29
29
  else
30
30
  [value]
@@ -4,9 +4,7 @@ module Leftovers
4
4
  module MatcherBuilders
5
5
  module Document
6
6
  def self.build(true_arg)
7
- return unless true_arg
8
-
9
- ::Leftovers::Matchers::NodeName.new(:__leftovers_document)
7
+ Matchers::NodeName.new(:__leftovers_document) if true_arg
10
8
  end
11
9
  end
12
10
  end
@@ -5,12 +5,12 @@ module Leftovers
5
5
  module Name
6
6
  class << self
7
7
  def build(patterns)
8
- ::Leftovers::MatcherBuilders::Or.each_or_self(patterns) do |pat|
8
+ Or.each_or_self(patterns) do |pat|
9
9
  case pat
10
- when ::String then ::Leftovers::MatcherBuilders::String.build(pat)
10
+ when ::String then String.build(pat)
11
11
  when ::Hash then build_from_hash(**pat)
12
12
  # :nocov:
13
- else raise Leftovers::UnexpectedCase, "Unhandled value #{pat.inspect}"
13
+ else raise UnexpectedCase, "Unhandled value #{pat.inspect}"
14
14
  # :nocov:
15
15
  end
16
16
  end
@@ -19,10 +19,7 @@ module Leftovers
19
19
  private
20
20
 
21
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
- )
22
+ And.build([StringPattern.build(**pattern), Unless.build(build(unless_arg))])
26
23
  end
27
24
  end
28
25
  end
@@ -1,72 +1,58 @@
1
- # frozen-string-literal: true
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Leftovers
4
4
  module MatcherBuilders
5
5
  module Node
6
6
  class << self
7
7
  def build(patterns)
8
- ::Leftovers::MatcherBuilders::Or.each_or_self(patterns) do |pattern|
8
+ Or.each_or_self(patterns) do |pattern|
9
9
  case pattern
10
- when ::String then ::Leftovers::MatcherBuilders::NodeName.build(pattern)
10
+ when ::String then NodeName.build(pattern)
11
11
  when ::Hash then build_from_hash(**pattern)
12
12
  # :nocov:
13
- else raise Leftovers::UnexpectedCase, "Unhandled value #{pattern.inspect}"
13
+ else raise UnexpectedCase, "Unhandled value #{pattern.inspect}"
14
14
  # :nocov:
15
15
  end
16
16
  end
17
17
  end
18
18
 
19
- def build_from_hash( # rubocop:disable Metrics/ParameterLists
19
+ def build_from_hash( # rubocop:disable Metrics/ParameterLists, Metrics/MethodLength
20
20
  names: nil, match: nil, has_prefix: nil, has_suffix: nil,
21
21
  document: false,
22
22
  paths: nil,
23
23
  has_arguments: nil,
24
24
  has_receiver: nil,
25
+ has_block: nil,
25
26
  type: nil,
26
27
  privacy: nil,
27
28
  unless_arg: nil, all: nil, any: nil
28
29
  )
29
- ::Leftovers::MatcherBuilders::And.build([
30
+ And.build([
30
31
  build_node_name_matcher(names, match, has_prefix, has_suffix),
31
- ::Leftovers::MatcherBuilders::Document.build(document),
32
- ::Leftovers::MatcherBuilders::NodePath.build(paths),
33
- ::Leftovers::MatcherBuilders::NodeHasArgument.build(has_arguments),
34
- ::Leftovers::MatcherBuilders::NodeHasReceiver.build(has_receiver),
35
- ::Leftovers::MatcherBuilders::NodePrivacy.build(privacy),
36
- ::Leftovers::MatcherBuilders::NodeType.build(type),
37
- build_unless_matcher(unless_arg), build_all_matcher(all), build_any_matcher(any)
32
+ Document.build(document),
33
+ NodePath.build(paths),
34
+ NodeHasArgument.build(has_arguments),
35
+ NodeHasBlock.build(has_block),
36
+ NodeHasReceiver.build(has_receiver),
37
+ NodePrivacy.build(privacy),
38
+ NodeType.build(type),
39
+ Unless.build(build(unless_arg)),
40
+ build_all_matcher(all),
41
+ build(any)
38
42
  ])
39
43
  end
40
44
 
41
45
  private
42
46
 
43
47
  def build_node_name_matcher(names, match, has_prefix, has_suffix)
44
- ::Leftovers::MatcherBuilders::Or.build([
45
- ::Leftovers::MatcherBuilders::NodeName.build(names),
46
- ::Leftovers::MatcherBuilders::NodeName.build(
47
- match: match, has_prefix: has_prefix, has_suffix: has_suffix
48
- )
48
+ Or.build([
49
+ NodeName.build(names),
50
+ NodeName.build(match: match, has_prefix: has_prefix, has_suffix: has_suffix)
49
51
  ])
50
52
  end
51
53
 
52
- def build_unless_matcher(unless_arg)
53
- return unless unless_arg
54
-
55
- ::Leftovers::MatcherBuilders::Unless.build(
56
- ::Leftovers::MatcherBuilders::Node.build(unless_arg)
57
- )
58
- end
59
-
60
54
  def build_all_matcher(all)
61
- return unless all
62
-
63
- ::Leftovers::MatcherBuilders::And.build(
64
- all.map { |pattern| ::Leftovers::MatcherBuilders::Node.build(pattern) }
65
- )
66
- end
67
-
68
- def build_any_matcher(any)
69
- ::Leftovers::MatcherBuilders::Node.build(any)
55
+ And.build(all.map { |pattern| build(pattern) }) if all
70
56
  end
71
57
  end
72
58
  end
@@ -1,19 +1,17 @@
1
- # frozen-string-literal: true
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Leftovers
4
4
  module MatcherBuilders
5
5
  module NodeHasArgument
6
6
  class << self
7
7
  def build(patterns)
8
- ::Leftovers::MatcherBuilders::Or.each_or_self(patterns) do |pat|
8
+ Or.each_or_self(patterns) do |pat|
9
9
  case pat
10
- when ::String
11
- ::Leftovers::MatcherBuilders::NodeHasKeywordArgument.build(pat, nil)
12
- when ::Integer
13
- ::Leftovers::MatcherBuilders::NodeHasPositionalArgument.build(pat, nil)
10
+ when ::String then NodeHasKeywordArgument.build(pat, nil)
11
+ when ::Integer then NodeHasPositionalArgument.build(pat, nil)
14
12
  when ::Hash then build_from_hash(**pat)
15
13
  # :nocov:
16
- else raise Leftovers::UnexpectedCase, "Unhandled value #{pat.inspect}"
14
+ else raise UnexpectedCase, "Unhandled value #{pat.inspect}"
17
15
  # :nocov:
18
16
  end
19
17
  end
@@ -22,45 +20,35 @@ module Leftovers
22
20
  private
23
21
 
24
22
  def build_from_hash(at: nil, has_value: nil, unless_arg: nil)
25
- value_matcher = ::Leftovers::MatcherBuilders::NodeValue.build(has_value)
26
-
27
- ::Leftovers::MatcherBuilders::AndNot.build(
28
- build_argument_matcher(value_matcher, **separate_argument_types(at)),
29
- ::Leftovers::MatcherBuilders::NodeHasArgument.build(unless_arg)
30
- )
23
+ And.build([
24
+ build_argument_matcher(NodeValue.build(has_value), **separate_argument_types(at)),
25
+ Unless.build(build(unless_arg))
26
+ ])
31
27
  end
32
28
 
33
29
  def separate_argument_types(at)
34
- groups = ::Leftovers.each_or_self(at).group_by do |index|
30
+ groups = ::Leftovers.wrap_array(at).group_by do |index|
35
31
  case index
36
32
  when '*', ::Integer then :positions
37
33
  when ::String, ::Hash then :keys
38
34
  # :nocov:
39
- else raise Leftovers::UnexpectedCase, "Unhandled value #{index.inspect}"
35
+ else raise UnexpectedCase, "Unhandled value #{index.inspect}"
40
36
  # :nocov:
41
37
  end
42
38
  end
43
39
 
44
- groups.transform_values { |v| Leftovers.unwrap_array(v) }
45
- end
46
-
47
- def build_has_keyword_argument(keys, value_matcher)
48
- ::Leftovers::MatcherBuilders::NodeHasKeywordArgument.build(keys, value_matcher)
49
- end
50
-
51
- def build_has_positional_argument(positions, value_matcher)
52
- ::Leftovers::MatcherBuilders::NodeHasPositionalArgument.build(positions, value_matcher)
40
+ groups.transform_values { |v| ::Leftovers.unwrap_array(v) }
53
41
  end
54
42
 
55
43
  def build_argument_matcher(value_matcher, keys: nil, positions: nil)
56
44
  if keys && !positions
57
- build_has_keyword_argument(keys, value_matcher)
45
+ NodeHasKeywordArgument.build(keys, value_matcher)
58
46
  elsif positions && !keys
59
- build_has_positional_argument(positions, value_matcher)
47
+ NodeHasPositionalArgument.build(positions, value_matcher)
60
48
  else
61
- ::Leftovers::MatcherBuilders::Or.build([
62
- build_has_positional_argument(positions, value_matcher),
63
- build_has_keyword_argument(keys, value_matcher)
49
+ Or.build([
50
+ NodeHasPositionalArgument.build(positions, value_matcher),
51
+ NodeHasKeywordArgument.build(keys, value_matcher)
64
52
  ])
65
53
  end
66
54
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ module MatcherBuilders
5
+ module NodeHasBlock
6
+ class << self
7
+ def build(has_block)
8
+ if has_block
9
+ Matchers::NodeHasBlock
10
+ elsif has_block == false
11
+ Matchers::Not.new(Matchers::NodeHasBlock)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,28 +1,26 @@
1
- # frozen-string-literal: true
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Leftovers
4
4
  module MatcherBuilders
5
5
  module NodeHasKeywordArgument
6
6
  class << self
7
7
  def build(keywords, value_matcher)
8
- value_matcher = ::Leftovers::MatcherBuilders::NodePairValue.build(value_matcher)
8
+ value_matcher = NodePairValue.build(value_matcher)
9
9
  keyword_matcher = build_keyword_matcher(keywords)
10
- pair_matcher = ::Leftovers::MatcherBuilders::And.build([keyword_matcher, value_matcher])
10
+ pair_matcher = And.build([keyword_matcher, value_matcher])
11
11
 
12
12
  return unless pair_matcher
13
13
 
14
- ::Leftovers::Matchers::NodeHasAnyKeywordArgument.new(pair_matcher)
14
+ Matchers::NodeHasAnyKeywordArgument.new(pair_matcher)
15
15
  end
16
16
 
17
17
  private
18
18
 
19
19
  def build_keyword_matcher(keywords)
20
- if ::Leftovers.each_or_self(keywords).include?('**')
21
- ::Leftovers::Matchers::NodeType.new(:pair)
20
+ if ::Leftovers.wrap_array(keywords).include?('**')
21
+ Matchers::NodeType.new(:pair)
22
22
  else
23
- ::Leftovers::MatcherBuilders::NodePairKey.build(
24
- ::Leftovers::MatcherBuilders::Node.build(keywords)
25
- )
23
+ NodePairKey.build(Node.build(keywords))
26
24
  end
27
25
  end
28
26
  end
@@ -1,13 +1,14 @@
1
- # frozen-string-literal: true
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Leftovers
4
4
  module MatcherBuilders
5
5
  module NodeHasPositionalArgument
6
6
  class << self
7
7
  def build(positions, value_matcher)
8
- if positions && !all_positions?(positions) && value_matcher
8
+ positions = ::Leftovers.wrap_array(positions)
9
+ if !positions.empty? && !all_positions?(positions) && value_matcher
9
10
  build_has_positional_value_matcher(positions, value_matcher)
10
- elsif positions && !value_matcher
11
+ elsif !positions.empty? && !value_matcher
11
12
  build_has_position_matcher(positions)
12
13
  elsif value_matcher
13
14
  build_has_any_positional_value_matcher(value_matcher)
@@ -17,23 +18,22 @@ module Leftovers
17
18
  private
18
19
 
19
20
  def all_positions?(positions)
20
- ::Leftovers.each_or_self(positions).include?('*')
21
+ positions.include?('*')
21
22
  end
22
23
 
23
24
  def build_has_position_matcher(positions)
24
- position = 0 if all_positions?(positions)
25
- position ||= ::Leftovers.each_or_self(positions).min
25
+ last_position = all_positions?(positions) ? 0 : positions.min
26
26
 
27
- ::Leftovers::Matchers::NodeHasPositionalArgument.new(position)
27
+ Matchers::NodeHasPositionalArgument.new(last_position)
28
28
  end
29
29
 
30
30
  def build_has_any_positional_value_matcher(value_matcher)
31
- ::Leftovers::Matchers::NodeHasAnyPositionalArgumentWithValue.new(value_matcher)
31
+ Matchers::NodeHasAnyPositionalArgumentWithValue.new(value_matcher)
32
32
  end
33
33
 
34
34
  def build_has_positional_value_matcher(positions, value_matcher)
35
- ::Leftovers::MatcherBuilders::Or.each_or_self(positions) do |position|
36
- ::Leftovers::Matchers::NodeHasPositionalArgumentWithValue.new(position, value_matcher)
35
+ Or.each_or_self(positions) do |position|
36
+ Matchers::NodeHasPositionalArgumentWithValue.new(position, value_matcher)
37
37
  end
38
38
  end
39
39
  end
@@ -1,21 +1,19 @@
1
- # frozen-string-literal: true
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Leftovers
4
4
  module MatcherBuilders
5
5
  module NodeHasReceiver
6
6
  class << self
7
- def build(pattern) # rubocop:disable Metrics/MethodLength
7
+ def build(pattern)
8
8
  case pattern
9
9
  when true
10
- ::Leftovers::Matchers::NodeHasAnyReceiver
10
+ Matchers::NodeHasAnyReceiver
11
11
  when false, :_leftovers_nil_value
12
- ::Leftovers::Matchers::Not.new(
13
- ::Leftovers::Matchers::NodeHasAnyReceiver
14
- )
12
+ Matchers::Not.new(Matchers::NodeHasAnyReceiver)
15
13
  else
16
- matcher = ::Leftovers::MatcherBuilders::NodeValue.build(pattern)
14
+ matcher = NodeValue.build(pattern)
17
15
 
18
- ::Leftovers::Matchers::NodeHasReceiver.new(matcher) if matcher
16
+ Matchers::NodeHasReceiver.new(matcher) if matcher
19
17
  end
20
18
  end
21
19
  end
@@ -1,14 +1,12 @@
1
- # frozen-string-literal: true
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Leftovers
4
4
  module MatcherBuilders
5
5
  module NodeName
6
6
  def self.build(name_pattern)
7
- matcher = ::Leftovers::MatcherBuilders::Name.build(name_pattern)
7
+ matcher = Name.build(name_pattern)
8
8
 
9
- return unless matcher
10
-
11
- ::Leftovers::Matchers::NodeName.new(matcher)
9
+ Matchers::NodeName.new(matcher) if matcher
12
10
  end
13
11
  end
14
12
  end
@@ -1,4 +1,4 @@
1
- # frozen-string-literal: true
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Leftovers
4
4
  module MatcherBuilders
@@ -6,9 +6,9 @@ module Leftovers
6
6
  def self.build(key_matcher)
7
7
  return unless key_matcher
8
8
 
9
- ::Leftovers::MatcherBuilders::And.build([
10
- ::Leftovers::Matchers::NodeType.new(:pair),
11
- ::Leftovers::Matchers::NodePairKey.new(key_matcher)
9
+ And.build([
10
+ Matchers::NodeType.new(:pair),
11
+ Matchers::NodePairKey.new(key_matcher)
12
12
  ])
13
13
  end
14
14
  end
@@ -1,4 +1,4 @@
1
- # frozen-string-literal: true
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Leftovers
4
4
  module MatcherBuilders
@@ -6,9 +6,9 @@ module Leftovers
6
6
  def self.build(value_matcher)
7
7
  return unless value_matcher
8
8
 
9
- ::Leftovers::MatcherBuilders::And.build([
10
- ::Leftovers::Matchers::NodeType.new(:pair),
11
- ::Leftovers::Matchers::NodePairValue.new(value_matcher)
9
+ And.build([
10
+ Matchers::NodeType.new(:pair),
11
+ Matchers::NodePairValue.new(value_matcher)
12
12
  ])
13
13
  end
14
14
  end
@@ -1,13 +1,12 @@
1
- # frozen-string-literal: true
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Leftovers
4
4
  module MatcherBuilders
5
5
  module NodePath
6
6
  def self.build(path_pattern)
7
- matcher = ::Leftovers::MatcherBuilders::Path.build(path_pattern)
8
- return unless matcher
7
+ matcher = Path.build(path_pattern)
9
8
 
10
- ::Leftovers::Matchers::NodePath.new(matcher)
9
+ Matchers::NodePath.new(matcher) if matcher
11
10
  end
12
11
  end
13
12
  end
@@ -1,11 +1,11 @@
1
- # frozen-string-literal: true
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Leftovers
4
4
  module MatcherBuilders
5
5
  module NodePrivacy
6
6
  def self.build(privacy_settings)
7
- ::Leftovers::MatcherBuilders::Or.each_or_self(privacy_settings) do |privacy|
8
- ::Leftovers::Matchers::NodePrivacy.new(privacy)
7
+ Or.each_or_self(privacy_settings) do |privacy|
8
+ Matchers::NodePrivacy.new(privacy)
9
9
  end
10
10
  end
11
11
  end