rubocop-performance 1.6.1 → 1.9.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/README.md +8 -0
- data/config/default.yml +95 -8
- data/lib/rubocop/cop/mixin/regexp_metacharacter.rb +4 -4
- data/lib/rubocop/cop/mixin/sort_block.rb +28 -0
- data/lib/rubocop/cop/performance/ancestors_include.rb +49 -0
- data/lib/rubocop/cop/performance/array_semi_infinite_range_slice.rb +74 -0
- data/lib/rubocop/cop/performance/big_decimal_with_numeric_argument.rb +46 -0
- data/lib/rubocop/cop/performance/bind_call.rb +9 -18
- data/lib/rubocop/cop/performance/block_given_with_explicit_block.rb +52 -0
- data/lib/rubocop/cop/performance/caller.rb +14 -15
- data/lib/rubocop/cop/performance/case_when_splat.rb +18 -11
- data/lib/rubocop/cop/performance/casecmp.rb +13 -20
- data/lib/rubocop/cop/performance/chain_array_allocation.rb +4 -10
- data/lib/rubocop/cop/performance/collection_literal_in_loop.rb +140 -0
- data/lib/rubocop/cop/performance/compare_with_block.rb +10 -21
- data/lib/rubocop/cop/performance/constant_regexp.rb +68 -0
- data/lib/rubocop/cop/performance/count.rb +14 -16
- data/lib/rubocop/cop/performance/delete_prefix.rb +14 -22
- data/lib/rubocop/cop/performance/delete_suffix.rb +14 -22
- data/lib/rubocop/cop/performance/detect.rb +65 -32
- data/lib/rubocop/cop/performance/double_start_end_with.rb +16 -24
- data/lib/rubocop/cop/performance/end_with.rb +9 -13
- data/lib/rubocop/cop/performance/fixed_size.rb +2 -1
- data/lib/rubocop/cop/performance/flat_map.rb +21 -22
- data/lib/rubocop/cop/performance/inefficient_hash_search.rb +15 -14
- data/lib/rubocop/cop/performance/io_readlines.rb +112 -0
- data/lib/rubocop/cop/performance/method_object_as_block.rb +32 -0
- data/lib/rubocop/cop/performance/open_struct.rb +3 -2
- data/lib/rubocop/cop/performance/range_include.rb +15 -11
- data/lib/rubocop/cop/performance/redundant_block_call.rb +15 -10
- data/lib/rubocop/cop/performance/redundant_match.rb +12 -6
- data/lib/rubocop/cop/performance/redundant_merge.rb +19 -17
- data/lib/rubocop/cop/performance/redundant_sort_block.rb +43 -0
- data/lib/rubocop/cop/performance/redundant_string_chars.rb +129 -0
- data/lib/rubocop/cop/performance/regexp_match.rb +20 -20
- data/lib/rubocop/cop/performance/reverse_each.rb +10 -5
- data/lib/rubocop/cop/performance/reverse_first.rb +73 -0
- data/lib/rubocop/cop/performance/size.rb +42 -43
- data/lib/rubocop/cop/performance/sort_reverse.rb +45 -0
- data/lib/rubocop/cop/performance/squeeze.rb +67 -0
- data/lib/rubocop/cop/performance/start_with.rb +9 -13
- data/lib/rubocop/cop/performance/string_include.rb +56 -0
- data/lib/rubocop/cop/performance/string_replacement.rb +24 -27
- data/lib/rubocop/cop/performance/sum.rb +236 -0
- data/lib/rubocop/cop/performance/times_map.rb +12 -18
- data/lib/rubocop/cop/performance/unfreeze_string.rb +20 -2
- data/lib/rubocop/cop/performance/uri_default_parser.rb +7 -12
- data/lib/rubocop/cop/performance_cops.rb +16 -0
- data/lib/rubocop/performance/version.rb +6 -1
- metadata +35 -13
@@ -41,11 +41,13 @@ module RuboCop
|
|
41
41
|
# 'abc'.match(/bc$/)
|
42
42
|
# /bc$/.match('abc')
|
43
43
|
#
|
44
|
-
class EndWith <
|
44
|
+
class EndWith < Base
|
45
45
|
include RegexpMetacharacter
|
46
|
+
extend AutoCorrector
|
46
47
|
|
47
48
|
MSG = 'Use `String#end_with?` instead of a regex match anchored to ' \
|
48
49
|
'the end of the string.'
|
50
|
+
RESTRICT_ON_SEND = %i[match =~ match?].freeze
|
49
51
|
|
50
52
|
def_node_matcher :redundant_regex?, <<~PATTERN
|
51
53
|
{(send $!nil? {:match :=~ :match?} (regexp (str $#literal_at_end?) (regopt)))
|
@@ -54,25 +56,19 @@ module RuboCop
|
|
54
56
|
PATTERN
|
55
57
|
|
56
58
|
def on_send(node)
|
57
|
-
return unless redundant_regex?(node)
|
59
|
+
return unless (receiver, regex_str = redundant_regex?(node))
|
58
60
|
|
59
|
-
add_offense(node)
|
60
|
-
end
|
61
|
-
alias on_match_with_lvasgn on_send
|
62
|
-
|
63
|
-
def autocorrect(node)
|
64
|
-
redundant_regex?(node) do |receiver, regex_str|
|
61
|
+
add_offense(node) do |corrector|
|
65
62
|
receiver, regex_str = regex_str, receiver if receiver.is_a?(String)
|
66
63
|
regex_str = drop_end_metacharacter(regex_str)
|
67
64
|
regex_str = interpret_string_escapes(regex_str)
|
68
65
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
corrector.replace(node.source_range, new_source)
|
73
|
-
end
|
66
|
+
new_source = "#{receiver.source}.end_with?(#{to_string_literal(regex_str)})"
|
67
|
+
|
68
|
+
corrector.replace(node.source_range, new_source)
|
74
69
|
end
|
75
70
|
end
|
71
|
+
alias on_match_with_lvasgn on_send
|
76
72
|
end
|
77
73
|
end
|
78
74
|
end
|
@@ -45,8 +45,9 @@ module RuboCop
|
|
45
45
|
# waldo = { a: corge, b: grault }
|
46
46
|
# waldo.size
|
47
47
|
#
|
48
|
-
class FixedSize <
|
48
|
+
class FixedSize < Base
|
49
49
|
MSG = 'Do not compute the size of statically sized objects.'
|
50
|
+
RESTRICT_ON_SEND = %i[count length size].freeze
|
50
51
|
|
51
52
|
def_node_matcher :counter, <<~MATCHER
|
52
53
|
(send ${array hash str sym} {:count :length :size} $...)
|
@@ -14,10 +14,12 @@ module RuboCop
|
|
14
14
|
# [1, 2, 3, 4].flat_map { |e| [e, e] }
|
15
15
|
# [1, 2, 3, 4].map { |e| [e, e] }.flatten
|
16
16
|
# [1, 2, 3, 4].collect { |e| [e, e] }.flatten
|
17
|
-
class FlatMap <
|
17
|
+
class FlatMap < Base
|
18
18
|
include RangeHelp
|
19
|
+
extend AutoCorrector
|
19
20
|
|
20
21
|
MSG = 'Use `flat_map` instead of `%<method>s...%<flatten>s`.'
|
22
|
+
RESTRICT_ON_SEND = %i[flatten flatten!].freeze
|
21
23
|
FLATTEN_MULTIPLE_LEVELS = ' Beware, `flat_map` only flattens 1 level ' \
|
22
24
|
'and `flatten` can be used to flatten ' \
|
23
25
|
'multiple levels.'
|
@@ -44,25 +46,11 @@ module RuboCop
|
|
44
46
|
end
|
45
47
|
end
|
46
48
|
|
47
|
-
def autocorrect(node)
|
48
|
-
map_node, _first_method, _flatten, params = flat_map_candidate?(node)
|
49
|
-
flatten_level, = *params.first
|
50
|
-
|
51
|
-
return unless flatten_level
|
52
|
-
|
53
|
-
range = range_between(node.loc.dot.begin_pos,
|
54
|
-
node.source_range.end_pos)
|
55
|
-
|
56
|
-
lambda do |corrector|
|
57
|
-
corrector.remove(range)
|
58
|
-
corrector.replace(map_node.loc.selector, 'flat_map')
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
49
|
private
|
63
50
|
|
64
51
|
def offense_for_levels(node, map_node, first_method, flatten)
|
65
52
|
message = MSG + FLATTEN_MULTIPLE_LEVELS
|
53
|
+
|
66
54
|
register_offense(node, map_node, first_method, flatten, message)
|
67
55
|
end
|
68
56
|
|
@@ -71,13 +59,24 @@ module RuboCop
|
|
71
59
|
end
|
72
60
|
|
73
61
|
def register_offense(node, map_node, first_method, flatten, message)
|
74
|
-
range = range_between(map_node.loc.selector.begin_pos,
|
75
|
-
|
62
|
+
range = range_between(map_node.loc.selector.begin_pos, node.loc.expression.end_pos)
|
63
|
+
message = format(message, method: first_method, flatten: flatten)
|
64
|
+
|
65
|
+
add_offense(range, message: message) do |corrector|
|
66
|
+
autocorrect(corrector, node)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def autocorrect(corrector, node)
|
71
|
+
map_node, _first_method, _flatten, params = flat_map_candidate?(node)
|
72
|
+
flatten_level, = *params.first
|
73
|
+
|
74
|
+
return unless flatten_level
|
75
|
+
|
76
|
+
range = range_between(node.loc.dot.begin_pos, node.source_range.end_pos)
|
76
77
|
|
77
|
-
|
78
|
-
|
79
|
-
message: format(message, method: first_method,
|
80
|
-
flatten: flatten))
|
78
|
+
corrector.remove(range)
|
79
|
+
corrector.replace(map_node.loc.selector, 'flat_map')
|
81
80
|
end
|
82
81
|
end
|
83
82
|
end
|
@@ -36,7 +36,11 @@ module RuboCop
|
|
36
36
|
# { a: 1, b: 2 }.has_value?('garbage')
|
37
37
|
# h = { a: 1, b: 2 }; h.value?(nil)
|
38
38
|
#
|
39
|
-
class InefficientHashSearch <
|
39
|
+
class InefficientHashSearch < Base
|
40
|
+
extend AutoCorrector
|
41
|
+
|
42
|
+
RESTRICT_ON_SEND = %i[include?].freeze
|
43
|
+
|
40
44
|
def_node_matcher :inefficient_include?, <<~PATTERN
|
41
45
|
(send (send $_ {:keys :values}) :include? _)
|
42
46
|
PATTERN
|
@@ -45,19 +49,16 @@ module RuboCop
|
|
45
49
|
inefficient_include?(node) do |receiver|
|
46
50
|
return if receiver.nil?
|
47
51
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
"#{autocorrect_hash_expression(node)}."\
|
59
|
-
"#{autocorrect_method(node)}(#{autocorrect_argument(node)})"
|
60
|
-
)
|
52
|
+
message = message(node)
|
53
|
+
add_offense(node, message: message) do |corrector|
|
54
|
+
# Replace `keys.include?` or `values.include?` with the appropriate
|
55
|
+
# `key?`/`value?` method.
|
56
|
+
corrector.replace(
|
57
|
+
node.loc.expression,
|
58
|
+
"#{autocorrect_hash_expression(node)}."\
|
59
|
+
"#{autocorrect_method(node)}(#{autocorrect_argument(node)})"
|
60
|
+
)
|
61
|
+
end
|
61
62
|
end
|
62
63
|
end
|
63
64
|
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Performance
|
6
|
+
# This cop identifies places where inefficient `readlines` method
|
7
|
+
# can be replaced by `each_line` to avoid fully loading file content into memory.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
#
|
11
|
+
# # bad
|
12
|
+
# File.readlines('testfile').each { |l| puts l }
|
13
|
+
# IO.readlines('testfile', chomp: true).each { |l| puts l }
|
14
|
+
#
|
15
|
+
# conn.readlines(10).map { |l| l.size }
|
16
|
+
# file.readlines.find { |l| l.start_with?('#') }
|
17
|
+
# file.readlines.each { |l| puts l }
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# File.open('testfile', 'r').each_line { |l| puts l }
|
21
|
+
# IO.open('testfile').each_line(chomp: true) { |l| puts l }
|
22
|
+
#
|
23
|
+
# conn.each_line(10).map { |l| l.size }
|
24
|
+
# file.each_line.find { |l| l.start_with?('#') }
|
25
|
+
# file.each_line { |l| puts l }
|
26
|
+
#
|
27
|
+
class IoReadlines < Base
|
28
|
+
include RangeHelp
|
29
|
+
extend AutoCorrector
|
30
|
+
|
31
|
+
MSG = 'Use `%<good>s` instead of `%<bad>s`.'
|
32
|
+
RESTRICT_ON_SEND = (Enumerable.instance_methods + [:each]).freeze
|
33
|
+
|
34
|
+
def_node_matcher :readlines_on_class?, <<~PATTERN
|
35
|
+
$(send $(send (const nil? {:IO :File}) :readlines ...) _)
|
36
|
+
PATTERN
|
37
|
+
|
38
|
+
def_node_matcher :readlines_on_instance?, <<~PATTERN
|
39
|
+
$(send $(send ${nil? !const_type?} :readlines ...) _ ...)
|
40
|
+
PATTERN
|
41
|
+
|
42
|
+
def on_send(node)
|
43
|
+
return unless (captured_values = readlines_on_class?(node) || readlines_on_instance?(node))
|
44
|
+
|
45
|
+
enumerable_call, readlines_call, receiver = *captured_values
|
46
|
+
|
47
|
+
range = offense_range(enumerable_call, readlines_call)
|
48
|
+
good_method = build_good_method(enumerable_call)
|
49
|
+
bad_method = build_bad_method(enumerable_call)
|
50
|
+
|
51
|
+
add_offense(range, message: format(MSG, good: good_method, bad: bad_method)) do |corrector|
|
52
|
+
autocorrect(corrector, enumerable_call, readlines_call, receiver)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def autocorrect(corrector, enumerable_call, readlines_call, receiver)
|
59
|
+
# We cannot safely correct `.readlines` method called on IO/File classes
|
60
|
+
# due to its signature and we are not sure with implicit receiver
|
61
|
+
# if it is called in the context of some instance or mentioned class.
|
62
|
+
return if receiver.nil?
|
63
|
+
|
64
|
+
range = correction_range(enumerable_call, readlines_call)
|
65
|
+
|
66
|
+
if readlines_call.arguments?
|
67
|
+
call_args = build_call_args(readlines_call.arguments)
|
68
|
+
replacement = "each_line(#{call_args})"
|
69
|
+
else
|
70
|
+
replacement = 'each_line'
|
71
|
+
end
|
72
|
+
|
73
|
+
corrector.replace(range, replacement)
|
74
|
+
end
|
75
|
+
|
76
|
+
def offense_range(enumerable_call, readlines_call)
|
77
|
+
readlines_pos = readlines_call.loc.selector.begin_pos
|
78
|
+
enumerable_pos = enumerable_call.loc.selector.end_pos
|
79
|
+
range_between(readlines_pos, enumerable_pos)
|
80
|
+
end
|
81
|
+
|
82
|
+
def build_good_method(enumerable_call)
|
83
|
+
if enumerable_call.method?(:each)
|
84
|
+
'each_line'
|
85
|
+
else
|
86
|
+
"each_line.#{enumerable_call.method_name}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def build_bad_method(enumerable_call)
|
91
|
+
"readlines.#{enumerable_call.method_name}"
|
92
|
+
end
|
93
|
+
|
94
|
+
def correction_range(enumerable_call, readlines_call)
|
95
|
+
begin_pos = readlines_call.loc.selector.begin_pos
|
96
|
+
|
97
|
+
end_pos = if enumerable_call.method?(:each)
|
98
|
+
enumerable_call.loc.expression.end_pos
|
99
|
+
else
|
100
|
+
enumerable_call.loc.dot.begin_pos
|
101
|
+
end
|
102
|
+
|
103
|
+
range_between(begin_pos, end_pos)
|
104
|
+
end
|
105
|
+
|
106
|
+
def build_call_args(call_args_node)
|
107
|
+
call_args_node.map(&:source).join(', ')
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Performance
|
6
|
+
# This cop identifies places where methods are converted to blocks, with the
|
7
|
+
# use of `&method`, and passed as arguments to method calls.
|
8
|
+
# It is faster to replace those with explicit blocks, calling those methods inside.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# # bad
|
12
|
+
# array.map(&method(:do_something))
|
13
|
+
# [1, 2, 3].each(&out.method(:puts))
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# array.map { |x| do_something(x) }
|
17
|
+
# [1, 2, 3].each { |x| out.puts(x) }
|
18
|
+
#
|
19
|
+
class MethodObjectAsBlock < Base
|
20
|
+
MSG = 'Use block explicitly instead of block-passing a method object.'
|
21
|
+
|
22
|
+
def_node_matcher :method_object_as_argument?, <<~PATTERN
|
23
|
+
(^send (send _ :method sym))
|
24
|
+
PATTERN
|
25
|
+
|
26
|
+
def on_block_pass(node)
|
27
|
+
add_offense(node) if method_object_as_argument?(node)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -27,9 +27,10 @@ module RuboCop
|
|
27
27
|
# end
|
28
28
|
# end
|
29
29
|
#
|
30
|
-
class OpenStruct <
|
30
|
+
class OpenStruct < Base
|
31
31
|
MSG = 'Consider using `Struct` over `OpenStruct` ' \
|
32
32
|
'to optimize the performance.'
|
33
|
+
RESTRICT_ON_SEND = %i[new].freeze
|
33
34
|
|
34
35
|
def_node_matcher :open_struct, <<~PATTERN
|
35
36
|
(send (const {nil? cbase} :OpenStruct) :new ...)
|
@@ -37,7 +38,7 @@ module RuboCop
|
|
37
38
|
|
38
39
|
def on_send(node)
|
39
40
|
open_struct(node) do
|
40
|
-
add_offense(node
|
41
|
+
add_offense(node.loc.selector)
|
41
42
|
end
|
42
43
|
end
|
43
44
|
end
|
@@ -3,18 +3,19 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Performance
|
6
|
-
# This cop identifies uses of `Range#include?`, which iterates over each
|
6
|
+
# This cop identifies uses of `Range#include?` and `Range#member?`, which iterates over each
|
7
7
|
# item in a `Range` to see if a specified item is there. In contrast,
|
8
8
|
# `Range#cover?` simply compares the target item with the beginning and
|
9
9
|
# end points of the `Range`. In a great majority of cases, this is what
|
10
10
|
# is wanted.
|
11
11
|
#
|
12
|
-
# This cop is `Safe: false` by default because `Range#include?` and
|
12
|
+
# This cop is `Safe: false` by default because `Range#include?` (or `Range#member?`) and
|
13
13
|
# `Range#cover?` are not equivalent behaviour.
|
14
14
|
#
|
15
15
|
# @example
|
16
16
|
# # bad
|
17
17
|
# ('a'..'z').include?('b') # => true
|
18
|
+
# ('a'..'z').member?('b') # => true
|
18
19
|
#
|
19
20
|
# # good
|
20
21
|
# ('a'..'z').cover?('b') # => true
|
@@ -23,8 +24,11 @@ module RuboCop
|
|
23
24
|
# # the desired result:
|
24
25
|
#
|
25
26
|
# ('a'..'z').cover?('yellow') # => true
|
26
|
-
class RangeInclude <
|
27
|
-
|
27
|
+
class RangeInclude < Base
|
28
|
+
extend AutoCorrector
|
29
|
+
|
30
|
+
MSG = 'Use `Range#cover?` instead of `Range#%<bad_method>s`.'
|
31
|
+
RESTRICT_ON_SEND = %i[include? member?].freeze
|
28
32
|
|
29
33
|
# TODO: If we traced out assignments of variables to their uses, we
|
30
34
|
# might pick up on a few more instances of this issue
|
@@ -32,17 +36,17 @@ module RuboCop
|
|
32
36
|
# (We don't even catch it if the Range is in double parens)
|
33
37
|
|
34
38
|
def_node_matcher :range_include, <<~PATTERN
|
35
|
-
(send {irange erange (begin {irange erange})} :include? ...)
|
39
|
+
(send {irange erange (begin {irange erange})} ${:include? :member?} ...)
|
36
40
|
PATTERN
|
37
41
|
|
38
42
|
def on_send(node)
|
39
|
-
|
40
|
-
|
41
|
-
add_offense(node, location: :selector)
|
42
|
-
end
|
43
|
+
range_include(node) do |bad_method|
|
44
|
+
message = format(MSG, bad_method: bad_method)
|
43
45
|
|
44
|
-
|
45
|
-
|
46
|
+
add_offense(node.loc.selector, message: message) do |corrector|
|
47
|
+
corrector.replace(node.loc.selector, 'cover?')
|
48
|
+
end
|
49
|
+
end
|
46
50
|
end
|
47
51
|
end
|
48
52
|
end
|
@@ -22,7 +22,9 @@ module RuboCop
|
|
22
22
|
# def another
|
23
23
|
# yield 1, 2, 3
|
24
24
|
# end
|
25
|
-
class RedundantBlockCall <
|
25
|
+
class RedundantBlockCall < Base
|
26
|
+
extend AutoCorrector
|
27
|
+
|
26
28
|
MSG = 'Use `yield` instead of `%<argname>s.call`.'
|
27
29
|
YIELD = 'yield'
|
28
30
|
OPEN_PAREN = '('
|
@@ -47,13 +49,17 @@ module RuboCop
|
|
47
49
|
next unless body
|
48
50
|
|
49
51
|
calls_to_report(argname, body).each do |blockcall|
|
50
|
-
add_offense(blockcall, message: format(MSG, argname: argname))
|
52
|
+
add_offense(blockcall, message: format(MSG, argname: argname)) do |corrector|
|
53
|
+
autocorrect(corrector, blockcall)
|
54
|
+
end
|
51
55
|
end
|
52
56
|
end
|
53
57
|
end
|
54
58
|
|
59
|
+
private
|
60
|
+
|
55
61
|
# offenses are registered on the `block.call` nodes
|
56
|
-
def autocorrect(node)
|
62
|
+
def autocorrect(corrector, node)
|
57
63
|
_receiver, _method, *args = *node
|
58
64
|
new_source = String.new(YIELD)
|
59
65
|
unless args.empty?
|
@@ -67,19 +73,18 @@ module RuboCop
|
|
67
73
|
end
|
68
74
|
|
69
75
|
new_source << CLOSE_PAREN if parentheses?(node) && !args.empty?
|
70
|
-
->(corrector) { corrector.replace(node.source_range, new_source) }
|
71
|
-
end
|
72
76
|
|
73
|
-
|
77
|
+
corrector.replace(node.source_range, new_source)
|
78
|
+
end
|
74
79
|
|
75
80
|
def calls_to_report(argname, body)
|
76
81
|
return [] if blockarg_assigned?(body, argname)
|
77
82
|
|
78
|
-
|
83
|
+
blockarg_calls(body, argname).map do |call|
|
84
|
+
return [] if args_include_block_pass?(call)
|
79
85
|
|
80
|
-
|
81
|
-
|
82
|
-
calls
|
86
|
+
call
|
87
|
+
end
|
83
88
|
end
|
84
89
|
|
85
90
|
def args_include_block_pass?(blockcall)
|