rubocop 0.73.0 → 0.74.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/bin/console +1 -0
- data/config/default.yml +2 -1
- data/lib/rubocop.rb +3 -0
- data/lib/rubocop/ast/node.rb +1 -7
- data/lib/rubocop/config.rb +17 -537
- data/lib/rubocop/config_obsoletion.rb +201 -0
- data/lib/rubocop/config_validator.rb +239 -0
- data/lib/rubocop/cop/layout/extra_spacing.rb +14 -53
- data/lib/rubocop/cop/layout/indentation_width.rb +19 -5
- data/lib/rubocop/cop/layout/space_around_operators.rb +42 -23
- data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +22 -40
- data/lib/rubocop/cop/lint/debugger.rb +0 -2
- data/lib/rubocop/cop/lint/empty_interpolation.rb +4 -4
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +56 -0
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +7 -8
- data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +6 -6
- data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +6 -1
- data/lib/rubocop/cop/metrics/line_length.rb +6 -0
- data/lib/rubocop/cop/mixin/documentation_comment.rb +0 -2
- data/lib/rubocop/cop/mixin/interpolation.rb +27 -0
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +87 -0
- data/lib/rubocop/cop/mixin/surrounding_space.rb +7 -5
- data/lib/rubocop/cop/style/commented_keyword.rb +8 -28
- data/lib/rubocop/cop/style/conditional_assignment.rb +1 -3
- data/lib/rubocop/cop/style/constant_visibility.rb +13 -2
- data/lib/rubocop/cop/style/guard_clause.rb +39 -10
- data/lib/rubocop/cop/style/lambda.rb +0 -2
- data/lib/rubocop/cop/style/trailing_method_end_statement.rb +4 -6
- data/lib/rubocop/cop/style/variable_interpolation.rb +6 -16
- data/lib/rubocop/path_util.rb +1 -1
- data/lib/rubocop/processed_source.rb +4 -0
- data/lib/rubocop/rspec/expect_offense.rb +4 -1
- data/lib/rubocop/version.rb +1 -1
- metadata +5 -2
@@ -158,11 +158,7 @@ module RuboCop
|
|
158
158
|
if indentation_consistency_style == 'indented_internal_methods'
|
159
159
|
check_members_for_indented_internal_methods_style(members)
|
160
160
|
else
|
161
|
-
members
|
162
|
-
next if member.send_type? && member.access_modifier?
|
163
|
-
|
164
|
-
check_indentation(base, member)
|
165
|
-
end
|
161
|
+
check_members_for_normal_style(base, members)
|
166
162
|
end
|
167
163
|
end
|
168
164
|
|
@@ -170,6 +166,8 @@ module RuboCop
|
|
170
166
|
return unless member
|
171
167
|
|
172
168
|
if access_modifier?(member.children.first)
|
169
|
+
return if access_modifier_indentation_style == 'outdent'
|
170
|
+
|
173
171
|
member.children.first
|
174
172
|
else
|
175
173
|
member
|
@@ -183,6 +181,14 @@ module RuboCop
|
|
183
181
|
end
|
184
182
|
end
|
185
183
|
|
184
|
+
def check_members_for_normal_style(base, members)
|
185
|
+
members.first.children.each do |member|
|
186
|
+
next if member.send_type? && member.access_modifier?
|
187
|
+
|
188
|
+
check_indentation(base, member)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
186
192
|
def each_member(members)
|
187
193
|
previous_modifier = nil
|
188
194
|
members.first.children.each do |member|
|
@@ -199,6 +205,14 @@ module RuboCop
|
|
199
205
|
indentation_consistency_style == 'indented_internal_methods'
|
200
206
|
end
|
201
207
|
|
208
|
+
def special_modifier?(node)
|
209
|
+
node.bare_access_modifier? && SPECIAL_MODIFIERS.include?(node.source)
|
210
|
+
end
|
211
|
+
|
212
|
+
def access_modifier_indentation_style
|
213
|
+
config.for_cop('Layout/AccessModifierIndentation')['EnforcedStyle']
|
214
|
+
end
|
215
|
+
|
202
216
|
def indentation_consistency_style
|
203
217
|
config.for_cop('Layout/IndentationConsistency')['EnforcedStyle']
|
204
218
|
end
|
@@ -34,14 +34,14 @@ module RuboCop
|
|
34
34
|
|
35
35
|
return if hash_table_style? && !node.parent.pairs_on_same_line?
|
36
36
|
|
37
|
-
check_operator(node.loc.operator, node.source_range)
|
37
|
+
check_operator(:pair, node.loc.operator, node.source_range)
|
38
38
|
end
|
39
39
|
|
40
40
|
def on_if(node)
|
41
41
|
return unless node.ternary?
|
42
42
|
|
43
|
-
check_operator(node.loc.question, node.if_branch.source_range)
|
44
|
-
check_operator(node.loc.colon, node.else_branch.source_range)
|
43
|
+
check_operator(:if, node.loc.question, node.if_branch.source_range)
|
44
|
+
check_operator(:if, node.loc.colon, node.else_branch.source_range)
|
45
45
|
end
|
46
46
|
|
47
47
|
def on_resbody(node)
|
@@ -49,23 +49,33 @@ module RuboCop
|
|
49
49
|
|
50
50
|
_, variable, = *node
|
51
51
|
|
52
|
-
check_operator(node.loc.assoc, variable.source_range)
|
52
|
+
check_operator(:resbody, node.loc.assoc, variable.source_range)
|
53
53
|
end
|
54
54
|
|
55
55
|
def on_send(node)
|
56
56
|
if node.setter_method?
|
57
57
|
on_special_asgn(node)
|
58
58
|
elsif regular_operator?(node)
|
59
|
-
check_operator(
|
59
|
+
check_operator(:send,
|
60
|
+
node.loc.selector,
|
61
|
+
node.first_argument.source_range)
|
60
62
|
end
|
61
63
|
end
|
62
64
|
|
65
|
+
def on_assignment(node)
|
66
|
+
_, rhs, = *node
|
67
|
+
|
68
|
+
return unless rhs
|
69
|
+
|
70
|
+
check_operator(:assignment, node.loc.operator, rhs.source_range)
|
71
|
+
end
|
72
|
+
|
63
73
|
def on_binary(node)
|
64
74
|
_, rhs, = *node
|
65
75
|
|
66
76
|
return unless rhs
|
67
77
|
|
68
|
-
check_operator(node.loc.operator, rhs.source_range)
|
78
|
+
check_operator(:binary, node.loc.operator, rhs.source_range)
|
69
79
|
end
|
70
80
|
|
71
81
|
def on_special_asgn(node)
|
@@ -73,20 +83,20 @@ module RuboCop
|
|
73
83
|
|
74
84
|
return unless right
|
75
85
|
|
76
|
-
check_operator(node.loc.operator, right.source_range)
|
86
|
+
check_operator(:special_asgn, node.loc.operator, right.source_range)
|
77
87
|
end
|
78
88
|
|
79
89
|
alias on_or on_binary
|
80
90
|
alias on_and on_binary
|
81
|
-
alias on_lvasgn
|
82
|
-
alias on_masgn
|
91
|
+
alias on_lvasgn on_assignment
|
92
|
+
alias on_masgn on_assignment
|
83
93
|
alias on_casgn on_special_asgn
|
84
|
-
alias on_ivasgn
|
85
|
-
alias on_cvasgn
|
86
|
-
alias on_gvasgn
|
94
|
+
alias on_ivasgn on_assignment
|
95
|
+
alias on_cvasgn on_assignment
|
96
|
+
alias on_gvasgn on_assignment
|
87
97
|
alias on_class on_binary
|
88
|
-
alias on_or_asgn
|
89
|
-
alias on_and_asgn
|
98
|
+
alias on_or_asgn on_assignment
|
99
|
+
alias on_and_asgn on_assignment
|
90
100
|
alias on_op_asgn on_special_asgn
|
91
101
|
|
92
102
|
def autocorrect(range)
|
@@ -113,35 +123,44 @@ module RuboCop
|
|
113
123
|
!IRREGULAR_METHODS.include?(send_node.method_name)
|
114
124
|
end
|
115
125
|
|
116
|
-
def check_operator(operator, right_operand)
|
126
|
+
def check_operator(type, operator, right_operand)
|
117
127
|
with_space = range_with_surrounding_space(range: operator)
|
118
128
|
return if with_space.source.start_with?("\n")
|
119
129
|
|
120
|
-
offense(operator, with_space, right_operand) do |msg|
|
130
|
+
offense(type, operator, with_space, right_operand) do |msg|
|
121
131
|
add_offense(with_space, location: operator, message: msg)
|
122
132
|
end
|
123
133
|
end
|
124
134
|
|
125
|
-
def offense(operator, with_space, right_operand)
|
126
|
-
msg = offense_message(operator, with_space, right_operand)
|
135
|
+
def offense(type, operator, with_space, right_operand)
|
136
|
+
msg = offense_message(type, operator, with_space, right_operand)
|
127
137
|
yield msg if msg
|
128
138
|
end
|
129
139
|
|
130
|
-
def offense_message(operator, with_space, right_operand)
|
140
|
+
def offense_message(type, operator, with_space, right_operand)
|
131
141
|
if operator.is?('**')
|
132
142
|
'Space around operator `**` detected.' unless with_space.is?('**')
|
133
143
|
elsif with_space.source !~ /^\s.*\s$/
|
134
144
|
"Surrounding space missing for operator `#{operator.source}`."
|
135
|
-
elsif excess_leading_space?(operator, with_space) ||
|
145
|
+
elsif excess_leading_space?(type, operator, with_space) ||
|
136
146
|
excess_trailing_space?(right_operand, with_space)
|
137
147
|
"Operator `#{operator.source}` should be surrounded " \
|
138
148
|
'by a single space.'
|
139
149
|
end
|
140
150
|
end
|
141
151
|
|
142
|
-
def excess_leading_space?(operator, with_space)
|
143
|
-
|
144
|
-
|
152
|
+
def excess_leading_space?(type, operator, with_space)
|
153
|
+
return false unless allow_for_alignment?
|
154
|
+
return false unless with_space.source.start_with?(EXCESSIVE_SPACE)
|
155
|
+
|
156
|
+
return !aligned_with_operator?(operator) unless type == :assignment
|
157
|
+
|
158
|
+
token = Token.new(operator, nil, operator.source)
|
159
|
+
align_preceding = aligned_with_preceding_assignment(token)
|
160
|
+
|
161
|
+
return align_preceding == :no unless align_preceding == :none
|
162
|
+
|
163
|
+
aligned_with_subsequent_assignment(token) != :yes
|
145
164
|
end
|
146
165
|
|
147
166
|
def excess_trailing_space?(right_operand, with_space)
|
@@ -19,61 +19,43 @@ module RuboCop
|
|
19
19
|
# # good
|
20
20
|
# var = "This is the #{ space } example"
|
21
21
|
class SpaceInsideStringInterpolation < Cop
|
22
|
+
include Interpolation
|
23
|
+
include SurroundingSpace
|
22
24
|
include ConfigurableEnforcedStyle
|
23
25
|
include RangeHelp
|
24
26
|
|
25
27
|
NO_SPACE_MSG = 'Space inside string interpolation detected.'
|
26
|
-
SPACE_MSG = 'Missing space
|
28
|
+
SPACE_MSG = 'Missing space inside string interpolation detected.'
|
27
29
|
|
28
|
-
def
|
29
|
-
|
30
|
-
|
31
|
-
end
|
32
|
-
end
|
30
|
+
def on_interpolation(begin_node)
|
31
|
+
delims = delimiters(begin_node)
|
32
|
+
return if empty_brackets?(*delims)
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
range_with_surrounding_space(range: node.source_range),
|
39
|
-
new_source
|
40
|
-
)
|
34
|
+
if style == :no_space
|
35
|
+
no_space_offenses(begin_node, *delims, NO_SPACE_MSG)
|
36
|
+
else
|
37
|
+
space_offenses(begin_node, *delims, SPACE_MSG)
|
41
38
|
end
|
42
39
|
end
|
43
40
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
node.each_child_node(:begin) do |begin_node|
|
48
|
-
final_node = begin_node.children.last
|
49
|
-
next unless final_node
|
41
|
+
def autocorrect(begin_node)
|
42
|
+
lambda do |corrector|
|
43
|
+
delims = delimiters(begin_node)
|
50
44
|
|
51
|
-
if style == :no_space
|
52
|
-
|
53
|
-
|
54
|
-
|
45
|
+
if style == :no_space
|
46
|
+
SpaceCorrector.remove_space(processed_source, corrector, *delims)
|
47
|
+
else
|
48
|
+
SpaceCorrector.add_space(processed_source, corrector, *delims)
|
55
49
|
end
|
56
50
|
end
|
57
51
|
end
|
58
52
|
|
59
|
-
|
60
|
-
style == :no_space ? NO_SPACE_MSG : SPACE_MSG
|
61
|
-
end
|
62
|
-
|
63
|
-
def space_on_any_side?(node)
|
64
|
-
interp = node.source_range
|
65
|
-
interp_with_surrounding_space =
|
66
|
-
range_with_surrounding_space(range: interp)
|
67
|
-
|
68
|
-
interp_with_surrounding_space != interp
|
69
|
-
end
|
70
|
-
|
71
|
-
def space_on_each_side?(node)
|
72
|
-
interp = node.source_range
|
73
|
-
interp_with_surrounding_space =
|
74
|
-
range_with_surrounding_space(range: interp)
|
53
|
+
private
|
75
54
|
|
76
|
-
|
55
|
+
def delimiters(begin_node)
|
56
|
+
left = processed_source.tokens[index_of_first_token(begin_node)]
|
57
|
+
right = processed_source.tokens[index_of_last_token(begin_node)]
|
58
|
+
[left, right]
|
77
59
|
end
|
78
60
|
end
|
79
61
|
end
|
@@ -17,12 +17,12 @@ module RuboCop
|
|
17
17
|
#
|
18
18
|
# "result is #{some_result}"
|
19
19
|
class EmptyInterpolation < Cop
|
20
|
+
include Interpolation
|
21
|
+
|
20
22
|
MSG = 'Empty interpolation detected.'
|
21
23
|
|
22
|
-
def
|
23
|
-
|
24
|
-
add_offense(begin_node) if begin_node.children.empty?
|
25
|
-
end
|
24
|
+
def on_interpolation(begin_node)
|
25
|
+
add_offense(begin_node) if begin_node.children.empty?
|
26
26
|
end
|
27
27
|
|
28
28
|
def autocorrect(node)
|
@@ -61,6 +61,7 @@ module RuboCop
|
|
61
61
|
#
|
62
62
|
class ErbNewArguments < Cop
|
63
63
|
extend TargetRubyVersion
|
64
|
+
include RangeHelp
|
64
65
|
|
65
66
|
minimum_target_ruby_version 2.6
|
66
67
|
|
@@ -97,10 +98,65 @@ module RuboCop
|
|
97
98
|
end
|
98
99
|
end
|
99
100
|
|
101
|
+
def autocorrect(node)
|
102
|
+
str_arg = node.arguments[0].source
|
103
|
+
|
104
|
+
kwargs = build_kwargs(node)
|
105
|
+
overridden_kwargs = override_by_legacy_args(kwargs, node)
|
106
|
+
|
107
|
+
good_arguments = [
|
108
|
+
str_arg, overridden_kwargs
|
109
|
+
].flatten.compact.join(', ')
|
110
|
+
|
111
|
+
lambda do |corrector|
|
112
|
+
corrector.replace(arguments_range(node), good_arguments)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
100
118
|
def correct_arguments?(arguments)
|
101
119
|
arguments.size == 1 ||
|
102
120
|
arguments.size == 2 && arguments[1].hash_type?
|
103
121
|
end
|
122
|
+
|
123
|
+
def build_kwargs(node)
|
124
|
+
return [nil, nil] unless node.arguments.last.hash_type?
|
125
|
+
|
126
|
+
trim_mode_arg, eoutvar_arg = nil
|
127
|
+
|
128
|
+
node.arguments.last.pairs.each do |pair|
|
129
|
+
case pair.key.source
|
130
|
+
when 'trim_mode'
|
131
|
+
trim_mode_arg = "trim_mode: #{pair.value.source}"
|
132
|
+
when 'eoutvar'
|
133
|
+
eoutvar_arg = "eoutvar: #{pair.value.source}"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
[trim_mode_arg, eoutvar_arg]
|
138
|
+
end
|
139
|
+
|
140
|
+
def override_by_legacy_args(kwargs, node)
|
141
|
+
overridden_kwargs = kwargs.dup
|
142
|
+
|
143
|
+
if node.arguments[2]
|
144
|
+
overridden_kwargs[0] = "trim_mode: #{node.arguments[2].source}"
|
145
|
+
end
|
146
|
+
|
147
|
+
if node.arguments[3] && !node.arguments[3].hash_type?
|
148
|
+
overridden_kwargs[1] = "eoutvar: #{node.arguments[3].source}"
|
149
|
+
end
|
150
|
+
|
151
|
+
overridden_kwargs
|
152
|
+
end
|
153
|
+
|
154
|
+
def arguments_range(node)
|
155
|
+
arguments = node.arguments
|
156
|
+
|
157
|
+
range_between(arguments.first.source_range.begin_pos,
|
158
|
+
arguments.last.source_range.end_pos)
|
159
|
+
end
|
104
160
|
end
|
105
161
|
end
|
106
162
|
end
|
@@ -17,21 +17,20 @@ module RuboCop
|
|
17
17
|
#
|
18
18
|
# "result is 10"
|
19
19
|
class LiteralInInterpolation < Cop
|
20
|
+
include Interpolation
|
20
21
|
include RangeHelp
|
21
22
|
include PercentLiteral
|
22
23
|
|
23
24
|
MSG = 'Literal interpolation detected.'
|
24
25
|
COMPOSITE = %i[array hash pair irange erange].freeze
|
25
26
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
next unless prints_as_self?(final_node)
|
27
|
+
def on_interpolation(begin_node)
|
28
|
+
final_node = begin_node.children.last
|
29
|
+
return unless final_node
|
30
|
+
return if special_keyword?(final_node)
|
31
|
+
return unless prints_as_self?(final_node)
|
32
32
|
|
33
|
-
|
34
|
-
end
|
33
|
+
add_offense(final_node)
|
35
34
|
end
|
36
35
|
|
37
36
|
def autocorrect(node)
|
@@ -18,20 +18,20 @@ module RuboCop
|
|
18
18
|
#
|
19
19
|
# "result is #{something}"
|
20
20
|
class StringConversionInInterpolation < Cop
|
21
|
+
include Interpolation
|
22
|
+
|
21
23
|
MSG_DEFAULT = 'Redundant use of `Object#to_s` in interpolation.'
|
22
24
|
MSG_SELF = 'Use `self` instead of `Object#to_s` in ' \
|
23
25
|
'interpolation.'
|
24
26
|
|
25
27
|
def_node_matcher :to_s_without_args?, '(send _ :to_s)'
|
26
28
|
|
27
|
-
def
|
28
|
-
|
29
|
-
final_node = begin_node.children.last
|
29
|
+
def on_interpolation(begin_node)
|
30
|
+
final_node = begin_node.children.last
|
30
31
|
|
31
|
-
|
32
|
+
return unless to_s_without_args?(final_node)
|
32
33
|
|
33
|
-
|
34
|
-
end
|
34
|
+
add_offense(final_node, location: :selector)
|
35
35
|
end
|
36
36
|
|
37
37
|
def autocorrect(node)
|
@@ -58,7 +58,12 @@ module RuboCop
|
|
58
58
|
PERCENT_CAPITAL_I = '%I'
|
59
59
|
ASSIGNMENT_TYPES = %i[lvasgn ivasgn cvasgn gvasgn].freeze
|
60
60
|
|
61
|
-
def_node_matcher :array_new?,
|
61
|
+
def_node_matcher :array_new?, <<~PATTERN
|
62
|
+
{
|
63
|
+
$(send (const nil? :Array) :new ...)
|
64
|
+
$(block (send (const nil? :Array) :new ...) ...)
|
65
|
+
}
|
66
|
+
PATTERN
|
62
67
|
|
63
68
|
def_node_matcher :literal_expansion, <<~PATTERN
|
64
69
|
(splat {$({str dstr int float array} ...) (block $#array_new? ...) $#array_new?} ...)
|
@@ -10,6 +10,7 @@ module RuboCop
|
|
10
10
|
# The maximum length is configurable.
|
11
11
|
# The tab size is configured in the `IndentationWidth`
|
12
12
|
# of the `Layout/Tab` cop.
|
13
|
+
# It also ignores a shebang line by default.
|
13
14
|
#
|
14
15
|
# This cop has some autocorrection capabilities.
|
15
16
|
# It can programmatically shorten certain long lines by
|
@@ -138,9 +139,14 @@ module RuboCop
|
|
138
139
|
|
139
140
|
def ignored_line?(line, line_index)
|
140
141
|
matches_ignored_pattern?(line) ||
|
142
|
+
shebang?(line, line_index) ||
|
141
143
|
heredocs && line_in_permitted_heredoc?(line_index.succ)
|
142
144
|
end
|
143
145
|
|
146
|
+
def shebang?(line, line_index)
|
147
|
+
line_index.zero? && line.start_with?('#!')
|
148
|
+
end
|
149
|
+
|
144
150
|
def register_offense(loc, line, line_index)
|
145
151
|
message = format(MSG, length: line_length(line), max: max)
|
146
152
|
|