rubocop 1.3.1 → 1.5.1
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 +1 -1
- data/config/default.yml +67 -11
- data/lib/rubocop.rb +5 -0
- data/lib/rubocop/cli.rb +5 -1
- data/lib/rubocop/cli/command/execute_runner.rb +26 -11
- data/lib/rubocop/cli/command/suggest_extensions.rb +80 -0
- data/lib/rubocop/config_loader.rb +1 -1
- data/lib/rubocop/config_loader_resolver.rb +5 -1
- data/lib/rubocop/config_obsoletion.rb +21 -3
- data/lib/rubocop/config_regeneration.rb +1 -1
- data/lib/rubocop/config_validator.rb +8 -1
- data/lib/rubocop/cop/autocorrect_logic.rb +21 -6
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +1 -1
- data/lib/rubocop/cop/generator.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +80 -10
- data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +6 -1
- data/lib/rubocop/cop/layout/end_of_line.rb +5 -5
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +7 -2
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +2 -1
- data/lib/rubocop/cop/lint/interpolation_check.rb +7 -2
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/missing_super.rb +7 -4
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +1 -1
- data/lib/rubocop/cop/lint/unexpected_block_arity.rb +85 -0
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +20 -6
- data/lib/rubocop/cop/metrics/abc_size.rb +25 -1
- data/lib/rubocop/cop/metrics/block_length.rb +13 -7
- data/lib/rubocop/cop/metrics/method_length.rb +7 -2
- data/lib/rubocop/cop/metrics/parameter_lists.rb +64 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +20 -10
- data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +146 -0
- data/lib/rubocop/cop/metrics/utils/repeated_csend_discount.rb +6 -1
- data/lib/rubocop/cop/mixin/configurable_numbering.rb +3 -2
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +9 -1
- data/lib/rubocop/cop/mixin/ignored_methods.rb +36 -3
- data/lib/rubocop/cop/mixin/method_complexity.rb +6 -0
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/visibility_help.rb +1 -3
- data/lib/rubocop/cop/naming/variable_number.rb +3 -1
- data/lib/rubocop/cop/style/and_or.rb +10 -0
- data/lib/rubocop/cop/style/class_and_module_children.rb +8 -3
- data/lib/rubocop/cop/style/documentation.rb +12 -1
- data/lib/rubocop/cop/style/format_string.rb +8 -3
- data/lib/rubocop/cop/style/if_with_semicolon.rb +39 -4
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -2
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +11 -2
- data/lib/rubocop/cop/style/numeric_literals.rb +14 -11
- data/lib/rubocop/cop/style/redundant_argument.rb +75 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +2 -1
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +49 -3
- data/lib/rubocop/cop/style/symbol_proc.rb +5 -3
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/variable_force/branch.rb +1 -1
- data/lib/rubocop/cop/variable_force/scope.rb +1 -1
- data/lib/rubocop/core_ext/hash.rb +20 -0
- data/lib/rubocop/ext/regexp_node.rb +5 -10
- data/lib/rubocop/ext/regexp_parser.rb +2 -9
- data/lib/rubocop/formatter/disabled_config_formatter.rb +21 -6
- data/lib/rubocop/options.rb +5 -0
- data/lib/rubocop/rake_task.rb +2 -2
- data/lib/rubocop/runner.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- metadata +12 -10
- data/bin/console +0 -10
- data/bin/rubocop-profile +0 -32
- data/bin/setup +0 -7
@@ -42,7 +42,7 @@ module RuboCop
|
|
42
42
|
ConfigLoader.default_configuration.key?(key)
|
43
43
|
end
|
44
44
|
|
45
|
-
|
45
|
+
check_obsoletions
|
46
46
|
|
47
47
|
alert_about_unrecognized_cops(invalid_cop_names)
|
48
48
|
check_target_ruby
|
@@ -68,6 +68,13 @@ module RuboCop
|
|
68
68
|
|
69
69
|
attr_reader :target_ruby
|
70
70
|
|
71
|
+
def check_obsoletions
|
72
|
+
@config_obsoletion.reject_obsolete_cops_and_parameters
|
73
|
+
return unless @config_obsoletion.warnings.any?
|
74
|
+
|
75
|
+
warn Rainbow("Warning: #{@config_obsoletion.warnings.join("\n")}").yellow
|
76
|
+
end
|
77
|
+
|
71
78
|
def check_target_ruby
|
72
79
|
return if target_ruby.supported?
|
73
80
|
|
@@ -39,16 +39,31 @@ module RuboCop
|
|
39
39
|
private
|
40
40
|
|
41
41
|
def disable_offense(range)
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
disable_offense_at_end_of_line(range_of_first_line(range),
|
46
|
-
eol_comment)
|
42
|
+
heredoc_range = surrounding_heredoc(range)
|
43
|
+
if heredoc_range
|
44
|
+
disable_offense_before_and_after(range_by_lines(heredoc_range))
|
47
45
|
else
|
48
|
-
|
46
|
+
eol_comment = " # rubocop:todo #{cop_name}"
|
47
|
+
needed_line_length = (range.source_line + eol_comment).length
|
48
|
+
if needed_line_length <= max_line_length
|
49
|
+
disable_offense_at_end_of_line(range_of_first_line(range), eol_comment)
|
50
|
+
else
|
51
|
+
disable_offense_before_and_after(range_by_lines(range))
|
52
|
+
end
|
49
53
|
end
|
50
54
|
end
|
51
55
|
|
56
|
+
def surrounding_heredoc(offense_range)
|
57
|
+
# The empty offense range is an edge case that can be reached from the Lint/Syntax cop.
|
58
|
+
return nil if offense_range.empty?
|
59
|
+
|
60
|
+
heredoc_nodes = processed_source.ast.each_descendant.select do |node|
|
61
|
+
node.respond_to?(:heredoc?) && node.heredoc?
|
62
|
+
end
|
63
|
+
heredoc_nodes.map { |node| node.loc.expression.join(node.loc.heredoc_end) }
|
64
|
+
.find { |range| range.contains?(offense_range) }
|
65
|
+
end
|
66
|
+
|
52
67
|
def range_of_first_line(range)
|
53
68
|
begin_of_first_line = range.begin_pos - range.column
|
54
69
|
end_of_first_line = begin_of_first_line + range.source_line.length
|
@@ -48,7 +48,7 @@ module RuboCop
|
|
48
48
|
def autocorrect_multiline_words(node, escape, delimiters)
|
49
49
|
contents = process_multiline_words(node, escape, delimiters)
|
50
50
|
contents << end_content(node.source)
|
51
|
-
contents.join
|
51
|
+
contents.join
|
52
52
|
end
|
53
53
|
|
54
54
|
def autocorrect_words(node, escape, delimiters)
|
@@ -139,7 +139,7 @@ module RuboCop
|
|
139
139
|
badge: badge,
|
140
140
|
version_added: version_added)
|
141
141
|
|
142
|
-
injector.inject do
|
142
|
+
injector.inject do # rubocop:disable Lint/UnexpectedBlockArity
|
143
143
|
output.puts(format(CONFIGURATION_ADDED_MESSAGE,
|
144
144
|
configuration_file_path: config_file_path))
|
145
145
|
end
|
@@ -38,7 +38,7 @@ module RuboCop
|
|
38
38
|
|
39
39
|
def assertions_using_described_class_msg
|
40
40
|
described_class_msg(processed_source.ast).reject do |node|
|
41
|
-
node.ancestors.any?
|
41
|
+
node.ancestors.any? { |ancestor| rspec_expectation_on_msg?(ancestor) }
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
@@ -3,17 +3,18 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Layout
|
6
|
-
# This cop checks whether method definitions are
|
7
|
-
# separated by one empty
|
6
|
+
# This cop checks whether class/module/method definitions are
|
7
|
+
# separated by one or more empty lines.
|
8
8
|
#
|
9
9
|
# `NumberOfEmptyLines` can be an integer (default is 1) or
|
10
10
|
# an array (e.g. [1, 2]) to specify a minimum and maximum
|
11
11
|
# number of empty lines permitted.
|
12
12
|
#
|
13
13
|
# `AllowAdjacentOneLineDefs` configures whether adjacent
|
14
|
-
# one-line
|
14
|
+
# one-line definitions are considered an offense.
|
15
15
|
#
|
16
|
-
# @example
|
16
|
+
# @example EmptyLineBetweenMethodDefs: true (default)
|
17
|
+
# # checks for empty lines between method definitions.
|
17
18
|
#
|
18
19
|
# # bad
|
19
20
|
# def a
|
@@ -29,11 +30,57 @@ module RuboCop
|
|
29
30
|
#
|
30
31
|
# def b
|
31
32
|
# end
|
33
|
+
#
|
34
|
+
# @example EmptyLineBetweenClassDefs: true (default)
|
35
|
+
# # checks for empty lines between class definitions.
|
36
|
+
#
|
37
|
+
# # bad
|
38
|
+
# class A
|
39
|
+
# end
|
40
|
+
# class B
|
41
|
+
# end
|
42
|
+
# def b
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# @example
|
46
|
+
#
|
47
|
+
# # good
|
48
|
+
# class A
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# class B
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# def b
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# @example EmptyLineBetweenModuleDefs: true (default)
|
58
|
+
# # checks for empty lines between module definitions.
|
59
|
+
#
|
60
|
+
# # bad
|
61
|
+
# module A
|
62
|
+
# end
|
63
|
+
# module B
|
64
|
+
# end
|
65
|
+
# def b
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# @example
|
69
|
+
#
|
70
|
+
# # good
|
71
|
+
# module A
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# module B
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# def b
|
78
|
+
# end
|
32
79
|
class EmptyLineBetweenDefs < Base
|
33
80
|
include RangeHelp
|
34
81
|
extend AutoCorrector
|
35
82
|
|
36
|
-
MSG = 'Use empty lines between
|
83
|
+
MSG = 'Use empty lines between %<type>s definitions.'
|
37
84
|
|
38
85
|
def self.autocorrect_incompatible_with
|
39
86
|
[Layout::EmptyLines]
|
@@ -47,7 +94,7 @@ module RuboCop
|
|
47
94
|
def on_begin(node)
|
48
95
|
node.children.each_cons(2) do |prev, n|
|
49
96
|
nodes = [prev, n]
|
50
|
-
check_defs(nodes) if nodes.all?(
|
97
|
+
check_defs(nodes) if nodes.all? { |def_candidate| candidate?(def_candidate) }
|
51
98
|
end
|
52
99
|
end
|
53
100
|
|
@@ -57,8 +104,9 @@ module RuboCop
|
|
57
104
|
return if nodes.all?(&:single_line?) &&
|
58
105
|
cop_config['AllowAdjacentOneLineDefs']
|
59
106
|
|
60
|
-
|
61
|
-
|
107
|
+
correction_node = nodes.last
|
108
|
+
location = correction_node.loc.keyword.join(correction_node.loc.name)
|
109
|
+
add_offense(location, message: message(correction_node)) do |corrector|
|
62
110
|
autocorrect(corrector, *nodes)
|
63
111
|
end
|
64
112
|
end
|
@@ -83,10 +131,32 @@ module RuboCop
|
|
83
131
|
|
84
132
|
private
|
85
133
|
|
86
|
-
def
|
134
|
+
def candidate?(node)
|
87
135
|
return unless node
|
88
136
|
|
89
|
-
node
|
137
|
+
method_candidate?(node) || class_candidate?(node) || module_candidate?(node)
|
138
|
+
end
|
139
|
+
|
140
|
+
def method_candidate?(node)
|
141
|
+
cop_config['EmptyLineBetweenMethodDefs'] && (node.def_type? || node.defs_type?)
|
142
|
+
end
|
143
|
+
|
144
|
+
def class_candidate?(node)
|
145
|
+
cop_config['EmptyLineBetweenClassDefs'] && node.class_type?
|
146
|
+
end
|
147
|
+
|
148
|
+
def module_candidate?(node)
|
149
|
+
cop_config['EmptyLineBetweenModuleDefs'] && node.module_type?
|
150
|
+
end
|
151
|
+
|
152
|
+
def message(node)
|
153
|
+
type = case node.type
|
154
|
+
when :def, :defs
|
155
|
+
:method
|
156
|
+
else
|
157
|
+
node.type
|
158
|
+
end
|
159
|
+
format(MSG, type: type)
|
90
160
|
end
|
91
161
|
|
92
162
|
def multiple_blank_lines_groups?(first_def_node, second_def_node)
|
@@ -45,7 +45,8 @@ module RuboCop
|
|
45
45
|
MSG = 'Empty line detected around arguments.'
|
46
46
|
|
47
47
|
def on_send(node)
|
48
|
-
return if node.single_line? || node.arguments.empty?
|
48
|
+
return if node.single_line? || node.arguments.empty? ||
|
49
|
+
receiver_and_method_call_on_different_lines?(node)
|
49
50
|
|
50
51
|
extra_lines(node) do |range|
|
51
52
|
add_offense(range) do |corrector|
|
@@ -57,6 +58,10 @@ module RuboCop
|
|
57
58
|
|
58
59
|
private
|
59
60
|
|
61
|
+
def receiver_and_method_call_on_different_lines?(node)
|
62
|
+
node.receiver && node.receiver.loc.last_line != node.loc.selector&.line
|
63
|
+
end
|
64
|
+
|
60
65
|
def empty_lines(node)
|
61
66
|
lines = processed_lines(node)
|
62
67
|
lines.select! { |code, _| code.empty? }
|
@@ -37,14 +37,14 @@ module RuboCop
|
|
37
37
|
# # good
|
38
38
|
# puts 'Hello' # Return character is CR+LF on all platfoms.
|
39
39
|
#
|
40
|
-
class EndOfLine <
|
40
|
+
class EndOfLine < Base
|
41
41
|
include ConfigurableEnforcedStyle
|
42
42
|
include RangeHelp
|
43
43
|
|
44
44
|
MSG_DETECTED = 'Carriage return character detected.'
|
45
45
|
MSG_MISSING = 'Carriage return character missing.'
|
46
46
|
|
47
|
-
def
|
47
|
+
def on_new_investigation
|
48
48
|
last_line = last_line(processed_source)
|
49
49
|
|
50
50
|
processed_source.raw_source.each_line.with_index do |line, index|
|
@@ -54,9 +54,9 @@ module RuboCop
|
|
54
54
|
next unless msg
|
55
55
|
next if unimportant_missing_cr?(index, last_line, line)
|
56
56
|
|
57
|
-
range =
|
58
|
-
|
59
|
-
add_offense(
|
57
|
+
range = source_range(processed_source.buffer, index + 1, 0, line.length)
|
58
|
+
|
59
|
+
add_offense(range, message: msg)
|
60
60
|
# Usually there will be carriage return characters on all or none
|
61
61
|
# of the lines in a file, so we report only one offense.
|
62
62
|
break
|
@@ -207,8 +207,13 @@ module RuboCop
|
|
207
207
|
PATTERN
|
208
208
|
|
209
209
|
def base_range(send_node, arg_node)
|
210
|
-
|
211
|
-
|
210
|
+
parent = send_node.parent
|
211
|
+
start_node = if parent && (parent.splat_type? || parent.kwsplat_type?)
|
212
|
+
send_node.parent
|
213
|
+
else
|
214
|
+
send_node
|
215
|
+
end
|
216
|
+
range_between(start_node.source_range.begin_pos, arg_node.source_range.begin_pos)
|
212
217
|
end
|
213
218
|
|
214
219
|
# Returns the column of the given range. For single line ranges, this
|
@@ -53,7 +53,8 @@ module RuboCop
|
|
53
53
|
def find_offense_node(node, regexp_receiver)
|
54
54
|
return node unless node.parent
|
55
55
|
|
56
|
-
if node.parent.send_type?
|
56
|
+
if (node.parent.send_type? && node.receiver) ||
|
57
|
+
method_chain_to_regexp_receiver?(node, regexp_receiver)
|
57
58
|
node = find_offense_node(node.parent, regexp_receiver)
|
58
59
|
end
|
59
60
|
|
@@ -23,10 +23,11 @@ module RuboCop
|
|
23
23
|
'Use double quoted strings if you need interpolation.'
|
24
24
|
|
25
25
|
def on_str(node)
|
26
|
-
|
27
|
-
return if
|
26
|
+
return unless node
|
27
|
+
return if string_or_regex?(node.parent)
|
28
28
|
return unless /(?<!\\)#\{.*\}/.match?(node.source)
|
29
29
|
return if heredoc?(node)
|
30
|
+
return unless node.loc.begin && node.loc.end
|
30
31
|
|
31
32
|
add_offense(node) do |corrector|
|
32
33
|
autocorrect(corrector, node)
|
@@ -35,6 +36,10 @@ module RuboCop
|
|
35
36
|
|
36
37
|
private
|
37
38
|
|
39
|
+
def string_or_regex?(node)
|
40
|
+
node&.dstr_type? || node&.regexp_type?
|
41
|
+
end
|
42
|
+
|
38
43
|
def autocorrect(corrector, node)
|
39
44
|
starting_token, ending_token = if node.source.include?('"')
|
40
45
|
['%{', '}']
|
@@ -95,7 +95,7 @@ module RuboCop
|
|
95
95
|
def autocorrected_value_for_array(node)
|
96
96
|
return node.source.gsub('"', '\"') unless node.percent_literal?
|
97
97
|
|
98
|
-
contents_range(node).source.split
|
98
|
+
contents_range(node).source.split.to_s.gsub('"', '\"')
|
99
99
|
end
|
100
100
|
|
101
101
|
# Does node print its own source when converted to a string?
|
@@ -6,6 +6,11 @@ module RuboCop
|
|
6
6
|
# This cop checks for the presence of constructors and lifecycle callbacks
|
7
7
|
# without calls to `super`.
|
8
8
|
#
|
9
|
+
# This cop does not consider `method_missing` (and `respond_to_missing?`)
|
10
|
+
# because in some cases it makes sense to overtake what is considered a
|
11
|
+
# missing method. In other cases, the theoretical ideal handling could be
|
12
|
+
# challenging or verbose for no actual gain.
|
13
|
+
#
|
9
14
|
# @example
|
10
15
|
# # bad
|
11
16
|
# class Employee < Person
|
@@ -43,15 +48,13 @@ module RuboCop
|
|
43
48
|
|
44
49
|
STATELESS_CLASSES = %w[BasicObject Object].freeze
|
45
50
|
|
46
|
-
OBJECT_LIFECYCLE_CALLBACKS = %i[method_missing respond_to_missing?].freeze
|
47
51
|
CLASS_LIFECYCLE_CALLBACKS = %i[inherited].freeze
|
48
52
|
METHOD_LIFECYCLE_CALLBACKS = %i[method_added method_removed method_undefined
|
49
53
|
singleton_method_added singleton_method_removed
|
50
54
|
singleton_method_undefined].freeze
|
51
55
|
|
52
|
-
CALLBACKS = (
|
53
|
-
|
54
|
-
METHOD_LIFECYCLE_CALLBACKS).to_set.freeze
|
56
|
+
CALLBACKS = (CLASS_LIFECYCLE_CALLBACKS +
|
57
|
+
METHOD_LIFECYCLE_CALLBACKS).to_set.freeze
|
55
58
|
|
56
59
|
def on_def(node)
|
57
60
|
return unless offender?(node)
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# This cop checks for a block that is known to need more positional
|
7
|
+
# block arguments than are given (by default this is configured for
|
8
|
+
# `Enumerable` methods needing 2 arguments). Optional arguments are allowed,
|
9
|
+
# although they don't generally make sense as the default value will
|
10
|
+
# be used. Blocks that have no receiver, or take splatted arguments
|
11
|
+
# (ie. `*args`) are always accepted.
|
12
|
+
#
|
13
|
+
# Keyword arguments (including `**kwargs`) do not get counted towards
|
14
|
+
# this, as they are not used by the methods in question.
|
15
|
+
#
|
16
|
+
# NOTE: This cop matches for method names only and hence cannot tell apart
|
17
|
+
# methods with same name in different classes.
|
18
|
+
#
|
19
|
+
# Method names and their expected arity can be configured like this:
|
20
|
+
#
|
21
|
+
# Methods:
|
22
|
+
# inject: 2
|
23
|
+
# reduce: 2
|
24
|
+
#
|
25
|
+
# @example
|
26
|
+
# # bad
|
27
|
+
# values.reduce {}
|
28
|
+
# values.min { |a| a }
|
29
|
+
# values.sort { |a; b| a + b }
|
30
|
+
#
|
31
|
+
# # good
|
32
|
+
# values.reduce { |memo, obj| memo << obj }
|
33
|
+
# values.min { |a, b| a <=> b }
|
34
|
+
# values.sort { |*x| x[0] <=> x[1] }
|
35
|
+
#
|
36
|
+
class UnexpectedBlockArity < Base
|
37
|
+
MSG = '`%<method>s` expects at least %<expected>i positional arguments, got %<actual>i.'
|
38
|
+
|
39
|
+
def on_block(node)
|
40
|
+
return if acceptable?(node)
|
41
|
+
|
42
|
+
expected = expected_arity(node.method_name)
|
43
|
+
actual = arg_count(node)
|
44
|
+
return if actual >= expected
|
45
|
+
|
46
|
+
message = format(MSG, method: node.method_name, expected: expected, actual: actual)
|
47
|
+
add_offense(node, message: message)
|
48
|
+
end
|
49
|
+
|
50
|
+
alias on_numblock on_block
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def methods
|
55
|
+
cop_config.fetch('Methods', [])
|
56
|
+
end
|
57
|
+
|
58
|
+
def acceptable?(node)
|
59
|
+
!(included_method?(node.method_name) && node.receiver)
|
60
|
+
end
|
61
|
+
|
62
|
+
def included_method?(name)
|
63
|
+
methods.key?(name.to_s)
|
64
|
+
end
|
65
|
+
|
66
|
+
def expected_arity(method)
|
67
|
+
cop_config['Methods'][method.to_s]
|
68
|
+
end
|
69
|
+
|
70
|
+
def arg_count(node)
|
71
|
+
return node.children[1] if node.numblock_type? # the maximum numbered param for the block
|
72
|
+
|
73
|
+
# Only `arg`, `optarg` and `mlhs` (destructuring) count as arguments that
|
74
|
+
# can be used. Keyword arguments are not used for these methods so are
|
75
|
+
# ignored.
|
76
|
+
node.arguments.count do |arg|
|
77
|
+
return Float::INFINITY if arg.restarg_type?
|
78
|
+
|
79
|
+
arg.arg_type? || arg.optarg_type? || arg.mlhs_type?
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|