rubocop 0.74.0 → 0.75.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 +2 -1
- data/config/default.yml +28 -4
- data/lib/rubocop.rb +6 -1
- data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +1 -12
- data/lib/rubocop/comment_config.rb +3 -2
- data/lib/rubocop/config.rb +4 -0
- data/lib/rubocop/config_loader.rb +20 -2
- data/lib/rubocop/config_loader_resolver.rb +2 -2
- data/lib/rubocop/config_obsoletion.rb +12 -0
- data/lib/rubocop/cop/autocorrect_logic.rb +2 -2
- data/lib/rubocop/cop/cop.rb +4 -3
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +43 -17
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +2 -2
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +1 -1
- data/lib/rubocop/cop/generator.rb +3 -3
- data/lib/rubocop/cop/generator/configuration_injector.rb +9 -4
- data/lib/rubocop/cop/generator/require_file_injector.rb +1 -1
- data/lib/rubocop/cop/layout/block_alignment.rb +2 -2
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +22 -7
- data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +2 -2
- data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +2 -2
- data/lib/rubocop/cop/layout/extra_spacing.rb +0 -6
- data/lib/rubocop/cop/layout/indent_assignment.rb +10 -1
- data/lib/rubocop/cop/layout/indent_heredoc.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +24 -2
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +5 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +7 -0
- data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +2 -0
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +17 -4
- data/lib/rubocop/cop/lint/debugger.rb +1 -1
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +10 -36
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +91 -0
- data/lib/rubocop/cop/lint/unneeded_cop_disable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/unused_block_argument.rb +22 -6
- data/lib/rubocop/cop/lint/unused_method_argument.rb +23 -5
- data/lib/rubocop/cop/lint/void.rb +3 -22
- data/lib/rubocop/cop/message_annotator.rb +16 -7
- data/lib/rubocop/cop/migration/department_name.rb +44 -0
- data/lib/rubocop/cop/mixin/alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
- data/lib/rubocop/cop/mixin/safe_mode.rb +2 -0
- data/lib/rubocop/cop/naming/method_name.rb +12 -1
- data/lib/rubocop/cop/naming/variable_name.rb +1 -0
- data/lib/rubocop/cop/offense.rb +18 -7
- data/lib/rubocop/cop/registry.rb +22 -1
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +1 -0
- data/lib/rubocop/cop/style/block_delimiters.rb +2 -1
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +29 -10
- data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
- data/lib/rubocop/cop/style/commented_keyword.rb +8 -2
- data/lib/rubocop/cop/style/conditional_assignment.rb +4 -4
- data/lib/rubocop/cop/style/documentation_method.rb +44 -0
- data/lib/rubocop/cop/style/double_cop_disable_directive.rb +8 -2
- data/lib/rubocop/cop/style/expand_path_arguments.rb +1 -1
- data/lib/rubocop/cop/style/format_string_token.rb +18 -69
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +18 -33
- data/lib/rubocop/cop/style/if_unless_modifier.rb +51 -15
- data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +25 -25
- data/lib/rubocop/cop/style/mixin_usage.rb +11 -1
- data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
- data/lib/rubocop/cop/style/nested_modifier.rb +18 -2
- data/lib/rubocop/cop/style/or_assignment.rb +6 -1
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +14 -0
- data/lib/rubocop/cop/style/redundant_parentheses.rb +13 -4
- data/lib/rubocop/cop/style/redundant_return.rb +12 -0
- data/lib/rubocop/cop/style/redundant_self.rb +18 -1
- data/lib/rubocop/cop/style/rescue_modifier.rb +24 -0
- data/lib/rubocop/cop/style/safe_navigation.rb +17 -0
- data/lib/rubocop/cop/style/semicolon.rb +11 -0
- data/lib/rubocop/cop/style/single_line_methods.rb +8 -1
- data/lib/rubocop/cop/style/ternary_parentheses.rb +19 -0
- data/lib/rubocop/cop/utils/format_string.rb +128 -0
- data/lib/rubocop/cop/variable_force/variable.rb +15 -2
- data/lib/rubocop/core_ext/string.rb +0 -24
- data/lib/rubocop/formatter/clang_style_formatter.rb +8 -3
- data/lib/rubocop/formatter/emacs_style_formatter.rb +22 -9
- data/lib/rubocop/formatter/file_list_formatter.rb +1 -1
- data/lib/rubocop/formatter/formatter_set.rb +16 -15
- data/lib/rubocop/formatter/pacman_formatter.rb +80 -0
- data/lib/rubocop/formatter/simple_text_formatter.rb +16 -4
- data/lib/rubocop/formatter/tap_formatter.rb +17 -4
- data/lib/rubocop/magic_comment.rb +4 -0
- data/lib/rubocop/options.rb +5 -16
- data/lib/rubocop/runner.rb +14 -8
- data/lib/rubocop/version.rb +1 -1
- metadata +6 -3
- data/lib/rubocop/cop/mixin/ignored_method_patterns.rb +0 -19
@@ -10,10 +10,10 @@ module RuboCop
|
|
10
10
|
# Note: RDoc 5.1.0 or lower has the following issue.
|
11
11
|
# https://github.com/rubocop-hq/rubocop/issues/7043
|
12
12
|
#
|
13
|
-
# The following `String#
|
13
|
+
# The following `String#gsub` can be replaced with
|
14
14
|
# squiggly heredoc when RuboCop supports Ruby 2.5 or higher
|
15
15
|
# (RDoc 6.0 or higher).
|
16
|
-
SOURCE_TEMPLATE = <<-RUBY.
|
16
|
+
SOURCE_TEMPLATE = <<-RUBY.gsub(/^ {8}/, '')
|
17
17
|
# frozen_string_literal: true
|
18
18
|
|
19
19
|
# TODO: when finished, run `rake generate_cops_documentation` to update the docs
|
@@ -61,7 +61,7 @@ module RuboCop
|
|
61
61
|
# See https://github.com/rubocop-hq/rubocop/blob/master/lib/rubocop/node_pattern.rb
|
62
62
|
#
|
63
63
|
# For example
|
64
|
-
MSG = 'Use `#good_method` instead of `#bad_method`.'
|
64
|
+
MSG = 'Use `#good_method` instead of `#bad_method`.'
|
65
65
|
|
66
66
|
def_node_matcher :bad_method?, <<~PATTERN
|
67
67
|
(send nil? :bad_method ...)
|
@@ -12,7 +12,6 @@ module RuboCop
|
|
12
12
|
Description: 'TODO: Write a description of the cop.'
|
13
13
|
Enabled: true
|
14
14
|
VersionAdded: '%<version_added>s'
|
15
|
-
|
16
15
|
YAML
|
17
16
|
|
18
17
|
def initialize(configuration_file_path:, badge:, version_added:)
|
@@ -23,8 +22,13 @@ module RuboCop
|
|
23
22
|
end
|
24
23
|
|
25
24
|
def inject
|
26
|
-
|
27
|
-
|
25
|
+
target_line = find_target_line
|
26
|
+
if target_line
|
27
|
+
configuration_entries.insert(find_target_line,
|
28
|
+
new_configuration_entry + "\n")
|
29
|
+
else
|
30
|
+
configuration_entries.push("\n" + new_configuration_entry)
|
31
|
+
end
|
28
32
|
|
29
33
|
File.write(configuration_file_path, configuration_entries.join)
|
30
34
|
|
@@ -49,7 +53,8 @@ module RuboCop
|
|
49
53
|
|
50
54
|
return index if badge.to_s < line
|
51
55
|
end
|
52
|
-
|
56
|
+
|
57
|
+
nil
|
53
58
|
end
|
54
59
|
|
55
60
|
def cop_name_line?(yaml)
|
@@ -45,7 +45,7 @@ module RuboCop
|
|
45
45
|
return if correct_style?(node)
|
46
46
|
|
47
47
|
if node.modifier_form? && last_argument_is_heredoc?(node)
|
48
|
-
heredoc_node =
|
48
|
+
heredoc_node = last_heredoc_argument(node)
|
49
49
|
|
50
50
|
return if next_line_empty?(heredoc_line(node, heredoc_node))
|
51
51
|
|
@@ -109,16 +109,27 @@ module RuboCop
|
|
109
109
|
|
110
110
|
def last_argument_is_heredoc?(node)
|
111
111
|
last_children = node.if_branch
|
112
|
-
|
113
112
|
return false unless last_children&.send_type?
|
114
113
|
|
115
|
-
|
116
|
-
|
117
|
-
last_argument.respond_to?(:heredoc?) && last_argument.heredoc?
|
114
|
+
heredoc?(last_heredoc_argument(node))
|
118
115
|
end
|
119
116
|
|
120
|
-
def
|
121
|
-
node.if_branch
|
117
|
+
def last_heredoc_argument(node)
|
118
|
+
n = if node.respond_to?(:if_branch)
|
119
|
+
node.if_branch.children.last
|
120
|
+
else
|
121
|
+
node
|
122
|
+
end
|
123
|
+
|
124
|
+
return n if heredoc?(n)
|
125
|
+
return unless n.respond_to?(:arguments)
|
126
|
+
|
127
|
+
n.arguments.each do |argument|
|
128
|
+
node = last_heredoc_argument(argument)
|
129
|
+
return node if node
|
130
|
+
end
|
131
|
+
|
132
|
+
return last_heredoc_argument(n.receiver) if n.respond_to?(:receiver)
|
122
133
|
end
|
123
134
|
|
124
135
|
def heredoc_line(node, heredoc_node)
|
@@ -129,6 +140,10 @@ module RuboCop
|
|
129
140
|
node.last_line + num_of_heredoc_lines + END_OF_HEREDOC_LINE
|
130
141
|
end
|
131
142
|
|
143
|
+
def heredoc?(node)
|
144
|
+
node.respond_to?(:heredoc?) && node.heredoc?
|
145
|
+
end
|
146
|
+
|
132
147
|
def offense_location(node)
|
133
148
|
if node.loc.respond_to?(:end) && node.loc.end
|
134
149
|
:end
|
@@ -55,8 +55,8 @@ module RuboCop
|
|
55
55
|
source
|
56
56
|
.comments
|
57
57
|
.take_while { |comment| comment.loc.line < source.ast.loc.line }
|
58
|
-
.
|
59
|
-
.
|
58
|
+
.reverse
|
59
|
+
.find { |comment| MagicComment.parse(comment.text).any? }
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
@@ -36,7 +36,7 @@ module RuboCop
|
|
36
36
|
#
|
37
37
|
# end
|
38
38
|
#
|
39
|
-
# @example
|
39
|
+
# @example EnforcedStyle: beginning_only
|
40
40
|
# # good
|
41
41
|
#
|
42
42
|
# class Foo
|
@@ -46,7 +46,7 @@ module RuboCop
|
|
46
46
|
# end
|
47
47
|
# end
|
48
48
|
#
|
49
|
-
# @example
|
49
|
+
# @example EnforcedStyle: ending_only
|
50
50
|
# # good
|
51
51
|
#
|
52
52
|
# class Foo
|
@@ -82,9 +82,7 @@ module RuboCop
|
|
82
82
|
token2.text.start_with?('#')
|
83
83
|
|
84
84
|
extra_space_range(token1, token2) do |range|
|
85
|
-
# Unary + doesn't appear as a token and needs special handling.
|
86
85
|
next if ignored_range?(ast, range.begin_pos)
|
87
|
-
next if unary_plus_non_offense?(range)
|
88
86
|
|
89
87
|
add_offense(range, location: range, message: MSG_UNNECESSARY)
|
90
88
|
end
|
@@ -114,10 +112,6 @@ module RuboCop
|
|
114
112
|
ignored_ranges(ast).any? { |r| r.include?(start_pos) }
|
115
113
|
end
|
116
114
|
|
117
|
-
def unary_plus_non_offense?(range)
|
118
|
-
range.resize(range.size + 1).source =~ /^ ?\+$/
|
119
|
-
end
|
120
|
-
|
121
115
|
# Returns an array of ranges that should not be reported. It's the
|
122
116
|
# extra spaces between the keys and values in a multiline hash,
|
123
117
|
# since those are handled by the Style/AlignHash cop.
|
@@ -33,13 +33,22 @@ module RuboCop
|
|
33
33
|
return unless node.loc.operator
|
34
34
|
return if node.loc.operator.line == rhs.first_line
|
35
35
|
|
36
|
-
base = display_column(node.source_range)
|
36
|
+
base = display_column(leftmost_multiple_assignment(node).source_range)
|
37
37
|
check_alignment([rhs], base + configured_indentation_width)
|
38
38
|
end
|
39
39
|
|
40
40
|
def autocorrect(node)
|
41
41
|
AlignmentCorrector.correct(processed_source, node, column_delta)
|
42
42
|
end
|
43
|
+
|
44
|
+
def leftmost_multiple_assignment(node)
|
45
|
+
return node unless same_line?(node, node.parent) &&
|
46
|
+
node.parent.assignment?
|
47
|
+
|
48
|
+
leftmost_multiple_assignment(node.parent)
|
49
|
+
|
50
|
+
node.parent
|
51
|
+
end
|
43
52
|
end
|
44
53
|
end
|
45
54
|
end
|
@@ -5,7 +5,9 @@ module RuboCop
|
|
5
5
|
module Layout
|
6
6
|
# This cop checks whether the multiline do end blocks have a newline
|
7
7
|
# after the start of the block. Additionally, it checks whether the block
|
8
|
-
# arguments, if any, are on the same line as the start of the
|
8
|
+
# arguments, if any, are on the same line as the start of the
|
9
|
+
# block. Putting block arguments on separate lines, because the whole
|
10
|
+
# line would otherwise be too long, is accepted.
|
9
11
|
#
|
10
12
|
# @example
|
11
13
|
# # bad
|
@@ -35,6 +37,17 @@ module RuboCop
|
|
35
37
|
# foo(i)
|
36
38
|
# bar(i)
|
37
39
|
# }
|
40
|
+
#
|
41
|
+
# # good
|
42
|
+
# blah { |
|
43
|
+
# long_list,
|
44
|
+
# of_parameters,
|
45
|
+
# that_would_not,
|
46
|
+
# fit_on_one_line
|
47
|
+
# |
|
48
|
+
# foo(i)
|
49
|
+
# bar(i)
|
50
|
+
# }
|
38
51
|
class MultilineBlockLayout < Cop
|
39
52
|
include RangeHelp
|
40
53
|
|
@@ -42,11 +55,13 @@ module RuboCop
|
|
42
55
|
'the block start.'
|
43
56
|
ARG_MSG = 'Block argument expression is not on the same line as the ' \
|
44
57
|
'block start.'
|
58
|
+
PIPE_SIZE = '|'.length
|
45
59
|
|
46
60
|
def on_block(node)
|
47
61
|
return if node.single_line?
|
48
62
|
|
49
|
-
unless args_on_beginning_line?(node)
|
63
|
+
unless args_on_beginning_line?(node) ||
|
64
|
+
line_break_necessary_in_args?(node)
|
50
65
|
add_offense_for_expression(node, node.arguments, ARG_MSG)
|
51
66
|
end
|
52
67
|
|
@@ -79,6 +94,13 @@ module RuboCop
|
|
79
94
|
node.loc.begin.line == node.arguments.loc.last_line
|
80
95
|
end
|
81
96
|
|
97
|
+
def line_break_necessary_in_args?(node)
|
98
|
+
needed_length = node.source_range.column +
|
99
|
+
node.source.lines.first.length +
|
100
|
+
block_arg_string(node.arguments).length + PIPE_SIZE
|
101
|
+
needed_length > max_line_length
|
102
|
+
end
|
103
|
+
|
82
104
|
def add_offense_for_expression(node, expr, msg)
|
83
105
|
expression = expr.source_range
|
84
106
|
range = range_between(expression.begin_pos, expression.end_pos)
|
@@ -3,7 +3,9 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Layout
|
6
|
-
# Checks the spacing inside and after block parameters pipes.
|
6
|
+
# Checks the spacing inside and after block parameters pipes. Line breaks
|
7
|
+
# inside parameter pipes are checked by `Layout/MultilineBlockLayout` and
|
8
|
+
# not by this cop.
|
7
9
|
#
|
8
10
|
# @example EnforcedStyleInsidePipes: no_space (default)
|
9
11
|
# # bad
|
@@ -156,6 +158,8 @@ module RuboCop
|
|
156
158
|
return if space_begin_pos >= space_end_pos
|
157
159
|
|
158
160
|
range = range_between(space_begin_pos, space_end_pos)
|
161
|
+
return if range.source.include?("\n")
|
162
|
+
|
159
163
|
add_offense(range, location: range,
|
160
164
|
message: "#{msg} block parameter detected.")
|
161
165
|
end
|
@@ -84,6 +84,13 @@ module RuboCop
|
|
84
84
|
def on_block(node)
|
85
85
|
return if node.keywords?
|
86
86
|
|
87
|
+
# Do not register an offense for multi-line empty braces. That means
|
88
|
+
# preventing auto-correction to single-line empty braces. It will
|
89
|
+
# conflict with auto-correction by `Layout/SpaceInsideBlockBraces` cop
|
90
|
+
# if auto-corrected to a single-line empty braces.
|
91
|
+
# See: https://github.com/rubocop-hq/rubocop/issues/7363
|
92
|
+
return if node.body.nil? && node.multiline?
|
93
|
+
|
87
94
|
left_brace = node.loc.begin
|
88
95
|
right_brace = node.loc.end
|
89
96
|
|
@@ -6,21 +6,34 @@ module RuboCop
|
|
6
6
|
# This cop checks for assignments in the conditions of
|
7
7
|
# if/while/until.
|
8
8
|
#
|
9
|
-
#
|
9
|
+
# `AllowSafeAssignment` option for safe assignment.
|
10
|
+
# By safe assignment we mean putting parentheses around
|
11
|
+
# an assignment to indicate "I know I'm using an assignment
|
12
|
+
# as a condition. It's not a mistake."
|
10
13
|
#
|
14
|
+
# @example
|
11
15
|
# # bad
|
12
|
-
#
|
13
16
|
# if some_var = true
|
14
17
|
# do_something
|
15
18
|
# end
|
16
19
|
#
|
17
|
-
#
|
20
|
+
# # good
|
21
|
+
# if some_var == true
|
22
|
+
# do_something
|
23
|
+
# end
|
18
24
|
#
|
25
|
+
# @example AllowSafeAssignment: true (default)
|
19
26
|
# # good
|
27
|
+
# if (some_var = true)
|
28
|
+
# do_something
|
29
|
+
# end
|
20
30
|
#
|
21
|
-
#
|
31
|
+
# @example AllowSafeAssignment: false
|
32
|
+
# # bad
|
33
|
+
# if (some_var = true)
|
22
34
|
# do_something
|
23
35
|
# end
|
36
|
+
#
|
24
37
|
class AssignmentInCondition < Cop
|
25
38
|
include SafeAssignment
|
26
39
|
|
@@ -43,7 +43,7 @@ module RuboCop
|
|
43
43
|
PATTERN
|
44
44
|
|
45
45
|
def_node_matcher :debugger_call?, <<~PATTERN
|
46
|
-
{(send {nil? #kernel?} {:debugger :byebug} ...)
|
46
|
+
{(send {nil? #kernel?} {:debugger :byebug :remote_byebug} ...)
|
47
47
|
(send (send {#kernel? nil?} :binding)
|
48
48
|
{:pry :remote_pry :pry_remote} ...)
|
49
49
|
(send (const {nil? (cbase)} :Pry) :rescue ...)
|
@@ -22,16 +22,10 @@ module RuboCop
|
|
22
22
|
# http://rubular.com/r/CvpbxkcTzy
|
23
23
|
MSG = "Number of arguments (%<arg_num>i) to `%<method>s` doesn't " \
|
24
24
|
'match the number of fields (%<field_num>i).'
|
25
|
-
|
26
|
-
/(%(([\s#+-0\*]*)(\d*)?(\.\d+)?[bBdiouxXeEfgGaAcps]|%))/.freeze
|
27
|
-
NAMED_FIELD_REGEX = /%\{[_a-zA-Z][_a-zA-Z]+\}/.freeze
|
25
|
+
|
28
26
|
KERNEL = 'Kernel'
|
29
27
|
SHOVEL = '<<'
|
30
|
-
PERCENT = '%'
|
31
|
-
PERCENT_PERCENT = '%%'
|
32
|
-
DIGIT_DOLLAR_FLAG = /%(\d+)\$/.freeze
|
33
28
|
STRING_TYPES = %i[str dstr].freeze
|
34
|
-
NAMED_INTERPOLATION = /%(?:<\w+>|\{\w+\})/.freeze
|
35
29
|
|
36
30
|
def on_send(node)
|
37
31
|
return unless offending_node?(node)
|
@@ -44,7 +38,7 @@ module RuboCop
|
|
44
38
|
def offending_node?(node)
|
45
39
|
return false unless called_on_string?(node)
|
46
40
|
return false unless method_with_format_args?(node)
|
47
|
-
return false if
|
41
|
+
return false if splat_args?(node)
|
48
42
|
|
49
43
|
num_of_format_args, num_of_expected_fields = count_matches(node)
|
50
44
|
|
@@ -70,16 +64,6 @@ module RuboCop
|
|
70
64
|
sprintf?(node) || format?(node) || percent?(node)
|
71
65
|
end
|
72
66
|
|
73
|
-
def named_mode?(node)
|
74
|
-
relevant_node = if sprintf?(node) || format?(node)
|
75
|
-
node.first_argument
|
76
|
-
elsif percent?(node)
|
77
|
-
node.receiver
|
78
|
-
end
|
79
|
-
|
80
|
-
!relevant_node.source.scan(NAMED_FIELD_REGEX).empty?
|
81
|
-
end
|
82
|
-
|
83
67
|
def splat_args?(node)
|
84
68
|
return false if percent?(node)
|
85
69
|
|
@@ -127,27 +111,17 @@ module RuboCop
|
|
127
111
|
|
128
112
|
def expected_fields_count(node)
|
129
113
|
return :unknown unless node.str_type?
|
130
|
-
return 1 if node.source =~ NAMED_INTERPOLATION
|
131
114
|
|
132
|
-
|
133
|
-
return
|
115
|
+
format_string = RuboCop::Cop::Utils::FormatString.new(node.source)
|
116
|
+
return 1 if format_string.named_interpolation?
|
134
117
|
|
135
|
-
|
136
|
-
|
137
|
-
.scan(FIELD_REGEX)
|
138
|
-
.reject { |x| x.first == PERCENT_PERCENT }
|
139
|
-
.reduce(0) { |acc, elem| acc + arguments_count(elem[2]) }
|
140
|
-
end
|
141
|
-
|
142
|
-
def max_digit_dollar_num(node)
|
143
|
-
node.source.scan(DIGIT_DOLLAR_FLAG).map do |digit_dollar_num|
|
144
|
-
digit_dollar_num.first.to_i
|
145
|
-
end.max
|
146
|
-
end
|
118
|
+
max_digit_dollar_num = format_string.max_digit_dollar_num
|
119
|
+
return max_digit_dollar_num if max_digit_dollar_num&.nonzero?
|
147
120
|
|
148
|
-
|
149
|
-
|
150
|
-
|
121
|
+
format_string
|
122
|
+
.format_sequences
|
123
|
+
.reject(&:percent?)
|
124
|
+
.reduce(0) { |acc, seq| acc + seq.arity }
|
151
125
|
end
|
152
126
|
|
153
127
|
def format?(node)
|