leftovers 0.11.1 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +1 -0
- data/docs/Configuration.md +7 -0
- data/exe/leftovers +3 -1
- data/leftovers.gemspec +3 -4
- data/lib/config/activesupport.yml +1 -1
- data/lib/config/rspec.yml +21 -0
- data/lib/leftovers/ast/array_node.rb +2 -2
- data/lib/leftovers/ast/block_node.rb +1 -1
- data/lib/leftovers/ast/builder.rb +19 -18
- data/lib/leftovers/ast/casgn_node.rb +2 -2
- data/lib/leftovers/ast/const_node.rb +1 -1
- data/lib/leftovers/ast/def_node.rb +1 -1
- data/lib/leftovers/ast/defs_node.rb +1 -1
- data/lib/leftovers/ast/false_node.rb +1 -1
- data/lib/leftovers/ast/hash_node.rb +2 -2
- data/lib/leftovers/ast/module_node.rb +1 -1
- data/lib/leftovers/ast/nil_node.rb +1 -1
- data/lib/leftovers/ast/node.rb +13 -1
- data/lib/leftovers/ast/numeric_node.rb +1 -1
- data/lib/leftovers/ast/send_node.rb +16 -3
- data/lib/leftovers/ast/str_node.rb +1 -1
- data/lib/leftovers/ast/sym_node.rb +1 -1
- data/lib/leftovers/ast/true_node.rb +1 -1
- data/lib/leftovers/ast/var_node.rb +1 -1
- data/lib/leftovers/ast/vasgn_node.rb +2 -2
- data/lib/leftovers/ast.rb +2 -21
- data/lib/leftovers/autoloader.rb +36 -0
- data/lib/leftovers/cli.rb +64 -45
- data/lib/leftovers/collection.rb +66 -0
- data/lib/leftovers/collector.rb +17 -27
- data/lib/leftovers/config.rb +17 -5
- data/lib/leftovers/config_loader/attribute.rb +2 -2
- data/lib/leftovers/config_loader/bool_schema.rb +21 -0
- data/lib/leftovers/config_loader/document_schema.rb +2 -2
- data/lib/leftovers/config_loader/inherit_schema_attributes.rb +1 -1
- data/lib/leftovers/config_loader/node.rb +8 -8
- data/lib/leftovers/config_loader/regexp_schema.rb +1 -1
- data/lib/leftovers/config_loader/rule_pattern_schema.rb +1 -0
- data/lib/leftovers/config_loader/schema.rb +1 -1
- data/lib/leftovers/config_loader/string_enum_schema.rb +1 -1
- data/lib/leftovers/config_loader/value_or_array_schema.rb +1 -1
- data/lib/leftovers/config_loader.rb +8 -48
- data/lib/leftovers/definition.rb +4 -4
- data/lib/leftovers/definition_collection.rb +3 -3
- data/lib/leftovers/definition_node.rb +2 -2
- data/lib/leftovers/definition_node_set.rb +1 -1
- data/lib/leftovers/definition_set.rb +4 -4
- data/lib/leftovers/definition_to_add.rb +2 -2
- data/lib/leftovers/error.rb +6 -0
- data/lib/leftovers/file.rb +4 -4
- data/lib/leftovers/file_collector/comments_processor.rb +23 -18
- data/lib/leftovers/file_collector/node_processor/error.rb +16 -0
- data/lib/leftovers/file_collector/node_processor.rb +19 -2
- data/lib/leftovers/file_collector.rb +28 -20
- data/lib/leftovers/file_list.rb +4 -6
- data/lib/leftovers/matcher_builders/and.rb +5 -5
- data/lib/leftovers/matcher_builders/document.rb +1 -3
- data/lib/leftovers/matcher_builders/name.rb +4 -7
- data/lib/leftovers/matcher_builders/node.rb +21 -35
- data/lib/leftovers/matcher_builders/node_has_argument.rb +17 -29
- data/lib/leftovers/matcher_builders/node_has_block.rb +17 -0
- data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +7 -9
- data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +10 -10
- data/lib/leftovers/matcher_builders/node_has_receiver.rb +6 -8
- data/lib/leftovers/matcher_builders/node_name.rb +3 -5
- data/lib/leftovers/matcher_builders/node_pair_key.rb +4 -4
- data/lib/leftovers/matcher_builders/node_pair_value.rb +4 -4
- data/lib/leftovers/matcher_builders/node_path.rb +3 -4
- data/lib/leftovers/matcher_builders/node_privacy.rb +3 -3
- data/lib/leftovers/matcher_builders/node_type.rb +18 -13
- data/lib/leftovers/matcher_builders/node_value.rb +18 -31
- data/lib/leftovers/matcher_builders/or.rb +10 -10
- data/lib/leftovers/matcher_builders/path.rb +3 -3
- data/lib/leftovers/matcher_builders/string_pattern.rb +2 -0
- data/lib/leftovers/matcher_builders/unless.rb +1 -3
- data/lib/leftovers/matcher_builders.rb +2 -22
- data/lib/leftovers/matchers/node_has_block.rb +13 -0
- data/lib/leftovers/matchers/node_scalar_value.rb +1 -1
- data/lib/leftovers/matchers.rb +2 -27
- data/lib/leftovers/merged_config.rb +16 -17
- data/lib/leftovers/parser.rb +1 -1
- data/lib/leftovers/precompile_error.rb +31 -0
- data/lib/leftovers/precompilers/haml.rb +23 -3
- data/lib/leftovers/precompilers/json.rb +1 -1
- data/lib/leftovers/precompilers/precompiler.rb +3 -3
- data/lib/leftovers/precompilers/slim.rb +1 -1
- data/lib/leftovers/precompilers/yaml/builder.rb +62 -0
- data/lib/leftovers/precompilers/yaml.rb +3 -56
- data/lib/leftovers/precompilers.rb +11 -16
- data/lib/leftovers/processor_builders/action.rb +15 -19
- data/lib/leftovers/processor_builders/add_prefix.rb +4 -6
- data/lib/leftovers/processor_builders/add_suffix.rb +4 -6
- data/lib/leftovers/processor_builders/argument.rb +10 -15
- data/lib/leftovers/processor_builders/dynamic.rb +12 -30
- data/lib/leftovers/processor_builders/each.rb +63 -76
- data/lib/leftovers/processor_builders/each_for_definition_set.rb +15 -0
- data/lib/leftovers/processor_builders/itself.rb +2 -4
- data/lib/leftovers/processor_builders/keyword.rb +4 -4
- data/lib/leftovers/processor_builders/keyword_argument.rb +4 -4
- data/lib/leftovers/processor_builders/receiver.rb +2 -4
- data/lib/leftovers/processor_builders/transform.rb +26 -49
- data/lib/leftovers/processor_builders/transform_chain.rb +4 -7
- data/lib/leftovers/processor_builders/transform_set.rb +6 -7
- data/lib/leftovers/processor_builders/value.rb +2 -2
- data/lib/leftovers/processor_builders.rb +2 -15
- data/lib/leftovers/processors/add_definition_node.rb +2 -2
- data/lib/leftovers/processors/camelize.rb +3 -3
- data/lib/leftovers/processors/deconstantize.rb +3 -3
- data/lib/leftovers/processors/demodulize.rb +3 -3
- data/lib/leftovers/processors/each_for_definition_set.rb +2 -2
- data/lib/leftovers/processors/eval.rb +1 -1
- data/lib/leftovers/processors/parameterize.rb +3 -3
- data/lib/leftovers/processors/placeholder.rb +1 -1
- data/lib/leftovers/processors/pluralize.rb +3 -3
- data/lib/leftovers/processors/set_default_privacy.rb +1 -1
- data/lib/leftovers/processors/set_privacy.rb +1 -1
- data/lib/leftovers/processors/singularize.rb +3 -3
- data/lib/leftovers/processors/titleize.rb +3 -3
- data/lib/leftovers/processors/underscore.rb +3 -3
- data/lib/leftovers/processors.rb +2 -44
- data/lib/leftovers/rake_task.rb +2 -2
- data/lib/leftovers/reporter.rb +44 -42
- data/lib/leftovers/runner.rb +40 -0
- data/lib/leftovers/todo_reporter.rb +96 -94
- data/lib/leftovers/unexpected_case.rb +8 -0
- data/lib/leftovers/version.rb +1 -1
- data/lib/leftovers.rb +23 -108
- metadata +15 -18
- 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
|
-
#
|
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
|
-
|
8
|
-
|
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 =
|
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
|
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 =
|
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
|
-
|
45
|
-
|
46
|
-
|
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
|
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
|
-
|
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
|
data/lib/leftovers/file_list.rb
CHANGED
@@ -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
|
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
|
13
|
-
else
|
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
|
21
|
+
when Matchers::And
|
22
22
|
[*flatten(value.lhs), *flatten(value.rhs)]
|
23
23
|
# :nocov: # not sure how to make this happen
|
24
|
-
when
|
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]
|
@@ -5,12 +5,12 @@ module Leftovers
|
|
5
5
|
module Name
|
6
6
|
class << self
|
7
7
|
def build(patterns)
|
8
|
-
|
8
|
+
Or.each_or_self(patterns) do |pat|
|
9
9
|
case pat
|
10
|
-
when ::String then
|
10
|
+
when ::String then String.build(pat)
|
11
11
|
when ::Hash then build_from_hash(**pat)
|
12
12
|
# :nocov:
|
13
|
-
else raise
|
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
|
-
|
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
|
-
#
|
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
|
-
|
8
|
+
Or.each_or_self(patterns) do |pattern|
|
9
9
|
case pattern
|
10
|
-
when ::String then
|
10
|
+
when ::String then NodeName.build(pattern)
|
11
11
|
when ::Hash then build_from_hash(**pattern)
|
12
12
|
# :nocov:
|
13
|
-
else raise
|
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
|
-
|
30
|
+
And.build([
|
30
31
|
build_node_name_matcher(names, match, has_prefix, has_suffix),
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
45
|
-
|
46
|
-
|
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
|
-
|
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
|
-
#
|
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
|
-
|
8
|
+
Or.each_or_self(patterns) do |pat|
|
9
9
|
case pat
|
10
|
-
when ::String
|
11
|
-
|
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
|
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
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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.
|
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
|
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
|
-
|
45
|
+
NodeHasKeywordArgument.build(keys, value_matcher)
|
58
46
|
elsif positions && !keys
|
59
|
-
|
47
|
+
NodeHasPositionalArgument.build(positions, value_matcher)
|
60
48
|
else
|
61
|
-
|
62
|
-
|
63
|
-
|
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
|
-
#
|
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 =
|
8
|
+
value_matcher = NodePairValue.build(value_matcher)
|
9
9
|
keyword_matcher = build_keyword_matcher(keywords)
|
10
|
-
pair_matcher =
|
10
|
+
pair_matcher = And.build([keyword_matcher, value_matcher])
|
11
11
|
|
12
12
|
return unless pair_matcher
|
13
13
|
|
14
|
-
|
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.
|
21
|
-
|
20
|
+
if ::Leftovers.wrap_array(keywords).include?('**')
|
21
|
+
Matchers::NodeType.new(:pair)
|
22
22
|
else
|
23
|
-
|
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
|
-
#
|
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
|
-
|
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
|
-
|
21
|
+
positions.include?('*')
|
21
22
|
end
|
22
23
|
|
23
24
|
def build_has_position_matcher(positions)
|
24
|
-
|
25
|
-
position ||= ::Leftovers.each_or_self(positions).min
|
25
|
+
last_position = all_positions?(positions) ? 0 : positions.min
|
26
26
|
|
27
|
-
|
27
|
+
Matchers::NodeHasPositionalArgument.new(last_position)
|
28
28
|
end
|
29
29
|
|
30
30
|
def build_has_any_positional_value_matcher(value_matcher)
|
31
|
-
|
31
|
+
Matchers::NodeHasAnyPositionalArgumentWithValue.new(value_matcher)
|
32
32
|
end
|
33
33
|
|
34
34
|
def build_has_positional_value_matcher(positions, value_matcher)
|
35
|
-
|
36
|
-
|
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
|
-
#
|
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)
|
7
|
+
def build(pattern)
|
8
8
|
case pattern
|
9
9
|
when true
|
10
|
-
|
10
|
+
Matchers::NodeHasAnyReceiver
|
11
11
|
when false, :_leftovers_nil_value
|
12
|
-
|
13
|
-
::Leftovers::Matchers::NodeHasAnyReceiver
|
14
|
-
)
|
12
|
+
Matchers::Not.new(Matchers::NodeHasAnyReceiver)
|
15
13
|
else
|
16
|
-
matcher =
|
14
|
+
matcher = NodeValue.build(pattern)
|
17
15
|
|
18
|
-
|
16
|
+
Matchers::NodeHasReceiver.new(matcher) if matcher
|
19
17
|
end
|
20
18
|
end
|
21
19
|
end
|
@@ -1,14 +1,12 @@
|
|
1
|
-
#
|
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 =
|
7
|
+
matcher = Name.build(name_pattern)
|
8
8
|
|
9
|
-
|
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
|
-
#
|
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
|
-
|
10
|
-
|
11
|
-
|
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
|
-
#
|
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
|
-
|
10
|
-
|
11
|
-
|
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
|
-
#
|
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 =
|
8
|
-
return unless matcher
|
7
|
+
matcher = Path.build(path_pattern)
|
9
8
|
|
10
|
-
|
9
|
+
Matchers::NodePath.new(matcher) if matcher
|
11
10
|
end
|
12
11
|
end
|
13
12
|
end
|
@@ -1,11 +1,11 @@
|
|
1
|
-
#
|
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
|
-
|
8
|
-
|
7
|
+
Or.each_or_self(privacy_settings) do |privacy|
|
8
|
+
Matchers::NodePrivacy.new(privacy)
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|