rubocop 1.11.0 → 1.12.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 +2 -2
- data/config/default.yml +16 -1
- data/lib/rubocop.rb +1 -0
- data/lib/rubocop/cli/command/suggest_extensions.rb +3 -2
- data/lib/rubocop/comment_config.rb +43 -94
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +3 -6
- data/lib/rubocop/cop/layout/access_modifier_indentation.rb +11 -8
- data/lib/rubocop/cop/layout/argument_alignment.rb +6 -5
- data/lib/rubocop/cop/layout/array_alignment.rb +7 -6
- data/lib/rubocop/cop/layout/assignment_indentation.rb +6 -3
- data/lib/rubocop/cop/layout/block_end_newline.rb +4 -8
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +14 -15
- data/lib/rubocop/cop/layout/comment_indentation.rb +16 -16
- data/lib/rubocop/cop/layout/else_alignment.rb +9 -6
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +6 -5
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +9 -6
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +22 -15
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +6 -5
- data/lib/rubocop/cop/layout/indentation_consistency.rb +9 -6
- data/lib/rubocop/cop/layout/indentation_style.rb +27 -30
- data/lib/rubocop/cop/layout/indentation_width.rb +19 -9
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +6 -5
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +6 -5
- data/lib/rubocop/cop/layout/parameter_alignment.rb +6 -5
- data/lib/rubocop/cop/lint/number_conversion.rb +7 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +1 -2
- data/lib/rubocop/cop/lint/suppressed_exception.rb +44 -1
- data/lib/rubocop/cop/lint/symbol_conversion.rb +89 -2
- data/lib/rubocop/cop/mixin/alignment.rb +10 -3
- data/lib/rubocop/cop/mixin/comments_help.rb +5 -1
- data/lib/rubocop/cop/mixin/documentation_comment.rb +1 -1
- data/lib/rubocop/cop/mixin/line_length_help.rb +11 -6
- data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +3 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +4 -3
- data/lib/rubocop/cop/mixin/preferred_delimiters.rb +1 -1
- data/lib/rubocop/cop/mixin/uncommunicative_name.rb +4 -6
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +4 -0
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +10 -0
- data/lib/rubocop/cop/registry.rb +9 -0
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +1 -1
- data/lib/rubocop/cop/style/bisected_attr_accessor.rb +59 -71
- data/lib/rubocop/cop/style/bisected_attr_accessor/macro.rb +62 -0
- data/lib/rubocop/cop/style/case_like_if.rb +15 -4
- data/lib/rubocop/cop/style/class_equality_comparison.rb +2 -0
- data/lib/rubocop/cop/style/command_literal.rb +1 -1
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +2 -2
- data/lib/rubocop/cop/style/documentation.rb +25 -3
- data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +16 -15
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +40 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +20 -2
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +15 -2
- data/lib/rubocop/cop/style/redundant_begin.rb +26 -3
- data/lib/rubocop/cop/style/redundant_return.rb +4 -0
- data/lib/rubocop/cop/style/redundant_self.rb +7 -3
- data/lib/rubocop/cop/style/regexp_literal.rb +1 -1
- data/lib/rubocop/cop/style/rescue_modifier.rb +17 -14
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +16 -0
- data/lib/rubocop/cop/style/string_chars.rb +38 -0
- data/lib/rubocop/cop/style/struct_inheritance.rb +2 -0
- data/lib/rubocop/cop/style/trailing_body_on_method_definition.rb +5 -1
- data/lib/rubocop/cop/style/unless_logical_operators.rb +8 -2
- data/lib/rubocop/directive_comment.rb +64 -9
- data/lib/rubocop/ext/regexp_parser.rb +3 -6
- data/lib/rubocop/magic_comment.rb +1 -1
- data/lib/rubocop/target_finder.rb +1 -0
- data/lib/rubocop/version.rb +1 -1
- metadata +5 -3
@@ -42,12 +42,13 @@ module RuboCop
|
|
42
42
|
# end
|
43
43
|
# end
|
44
44
|
# end
|
45
|
-
class IndentationWidth <
|
45
|
+
class IndentationWidth < Base # rubocop:disable Metrics/ClassLength
|
46
46
|
include EndKeywordAlignment
|
47
47
|
include Alignment
|
48
48
|
include CheckAssignment
|
49
49
|
include IgnoredPattern
|
50
50
|
include RangeHelp
|
51
|
+
extend AutoCorrector
|
51
52
|
|
52
53
|
MSG = 'Use %<configured_indentation_width>d (not %<indentation>d) ' \
|
53
54
|
'spaces for%<name>s indentation.'
|
@@ -145,12 +146,12 @@ module RuboCop
|
|
145
146
|
check_if(node, node.body, node.else_branch, base.loc)
|
146
147
|
end
|
147
148
|
|
148
|
-
def autocorrect(node)
|
149
|
-
AlignmentCorrector.correct(processed_source, node, @column_delta)
|
150
|
-
end
|
151
|
-
|
152
149
|
private
|
153
150
|
|
151
|
+
def autocorrect(corrector, node)
|
152
|
+
AlignmentCorrector.correct(corrector, processed_source, node, @column_delta)
|
153
|
+
end
|
154
|
+
|
154
155
|
def check_members(base, members)
|
155
156
|
check_indentation(base, select_check_member(members.first))
|
156
157
|
|
@@ -280,8 +281,9 @@ module RuboCop
|
|
280
281
|
name = style == 'normal' ? '' : " #{style}"
|
281
282
|
message = message(configured_indentation_width, indentation, name)
|
282
283
|
|
283
|
-
add_offense(
|
284
|
-
|
284
|
+
add_offense(offending_range(body_node, indentation), message: message) do |corrector|
|
285
|
+
autocorrect(corrector, node)
|
286
|
+
end
|
285
287
|
end
|
286
288
|
|
287
289
|
def message(configured_indentation_width, indentation, name)
|
@@ -308,12 +310,20 @@ module RuboCop
|
|
308
310
|
def indentation_to_check?(base_loc, body_node)
|
309
311
|
return false if skip_check?(base_loc, body_node)
|
310
312
|
|
311
|
-
if
|
313
|
+
if body_node.rescue_type?
|
314
|
+
check_rescue?(body_node)
|
315
|
+
elsif body_node.ensure_type?
|
312
316
|
block_body, = *body_node
|
313
317
|
return unless block_body
|
318
|
+
|
319
|
+
check_rescue?(block_body) if block_body.rescue_type?
|
320
|
+
else
|
321
|
+
true
|
314
322
|
end
|
323
|
+
end
|
315
324
|
|
316
|
-
|
325
|
+
def check_rescue?(rescue_node)
|
326
|
+
rescue_node.body
|
317
327
|
end
|
318
328
|
|
319
329
|
def skip_check?(base_loc, body_node)
|
@@ -46,10 +46,11 @@ module RuboCop
|
|
46
46
|
# .a
|
47
47
|
# .b
|
48
48
|
# .c
|
49
|
-
class MultilineMethodCallIndentation <
|
49
|
+
class MultilineMethodCallIndentation < Base
|
50
50
|
include ConfigurableEnforcedStyle
|
51
51
|
include Alignment
|
52
52
|
include MultilineExpressionIndentation
|
53
|
+
extend AutoCorrector
|
53
54
|
|
54
55
|
def validate_config
|
55
56
|
return unless style == :aligned && cop_config['IndentationWidth']
|
@@ -61,12 +62,12 @@ module RuboCop
|
|
61
62
|
'`EnforcedStyle` is `indented`.'
|
62
63
|
end
|
63
64
|
|
64
|
-
def autocorrect(node)
|
65
|
-
AlignmentCorrector.correct(processed_source, node, @column_delta)
|
66
|
-
end
|
67
|
-
|
68
65
|
private
|
69
66
|
|
67
|
+
def autocorrect(corrector, node)
|
68
|
+
AlignmentCorrector.correct(corrector, processed_source, node, @column_delta)
|
69
|
+
end
|
70
|
+
|
70
71
|
def relevant_node?(send_node)
|
71
72
|
send_node.loc.dot # Only check method calls with dot operator
|
72
73
|
end
|
@@ -41,10 +41,11 @@ module RuboCop
|
|
41
41
|
# something_else
|
42
42
|
# end
|
43
43
|
#
|
44
|
-
class MultilineOperationIndentation <
|
44
|
+
class MultilineOperationIndentation < Base
|
45
45
|
include ConfigurableEnforcedStyle
|
46
46
|
include Alignment
|
47
47
|
include MultilineExpressionIndentation
|
48
|
+
extend AutoCorrector
|
48
49
|
|
49
50
|
def on_and(node)
|
50
51
|
check_and_or(node)
|
@@ -63,12 +64,12 @@ module RuboCop
|
|
63
64
|
'`EnforcedStyle` is `indented`.'
|
64
65
|
end
|
65
66
|
|
66
|
-
def autocorrect(node)
|
67
|
-
AlignmentCorrector.correct(processed_source, node, @column_delta)
|
68
|
-
end
|
69
|
-
|
70
67
|
private
|
71
68
|
|
69
|
+
def autocorrect(corrector, node)
|
70
|
+
AlignmentCorrector.correct(corrector, processed_source, node, @column_delta)
|
71
|
+
end
|
72
|
+
|
72
73
|
def relevant_node?(node)
|
73
74
|
return false if node.send_type? && node.unary_operation?
|
74
75
|
|
@@ -68,8 +68,9 @@ module RuboCop
|
|
68
68
|
# baz)
|
69
69
|
# 123
|
70
70
|
# end
|
71
|
-
class ParameterAlignment <
|
71
|
+
class ParameterAlignment < Base
|
72
72
|
include Alignment
|
73
|
+
extend AutoCorrector
|
73
74
|
|
74
75
|
ALIGN_PARAMS_MSG = 'Align the parameters of a method definition if ' \
|
75
76
|
'they span more than one line.'
|
@@ -84,12 +85,12 @@ module RuboCop
|
|
84
85
|
end
|
85
86
|
alias on_defs on_def
|
86
87
|
|
87
|
-
def autocorrect(node)
|
88
|
-
AlignmentCorrector.correct(processed_source, node, column_delta)
|
89
|
-
end
|
90
|
-
|
91
88
|
private
|
92
89
|
|
90
|
+
def autocorrect(corrector, node)
|
91
|
+
AlignmentCorrector.correct(corrector, processed_source, node, column_delta)
|
92
|
+
end
|
93
|
+
|
93
94
|
def message(_node)
|
94
95
|
fixed_indentation? ? FIXED_INDENT_MSG : ALIGN_PARAMS_MSG
|
95
96
|
end
|
@@ -105,6 +105,8 @@ module RuboCop
|
|
105
105
|
corrected_method: correct_sym_method(to_method)
|
106
106
|
)
|
107
107
|
add_offense(node, message: message) do |corrector|
|
108
|
+
remove_parentheses(corrector, node) if node.parenthesized?
|
109
|
+
|
108
110
|
corrector.replace(sym_node, correct_sym_method(to_method))
|
109
111
|
end
|
110
112
|
end
|
@@ -120,6 +122,11 @@ module RuboCop
|
|
120
122
|
"{ |i| #{body} }"
|
121
123
|
end
|
122
124
|
|
125
|
+
def remove_parentheses(corrector, node)
|
126
|
+
corrector.replace(node.loc.begin, ' ')
|
127
|
+
corrector.remove(node.loc.end)
|
128
|
+
end
|
129
|
+
|
123
130
|
def ignore_receiver?(receiver)
|
124
131
|
if receiver.send_type? && ignored_method?(receiver.method_name)
|
125
132
|
true
|
@@ -174,8 +174,7 @@ module RuboCop
|
|
174
174
|
end
|
175
175
|
|
176
176
|
def directive_count(comment)
|
177
|
-
|
178
|
-
_, cops_string = match.captures
|
177
|
+
_, cops_string = DirectiveComment.new(comment).match_captures
|
179
178
|
cops_string.split(/,\s*/).size
|
180
179
|
end
|
181
180
|
|
@@ -64,12 +64,51 @@ module RuboCop
|
|
64
64
|
# rescue
|
65
65
|
# # do nothing
|
66
66
|
# end
|
67
|
+
#
|
68
|
+
# @example AllowNil: true (default)
|
69
|
+
#
|
70
|
+
# # good
|
71
|
+
# def some_method
|
72
|
+
# do_something
|
73
|
+
# rescue
|
74
|
+
# nil
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# # good
|
78
|
+
# begin
|
79
|
+
# do_something
|
80
|
+
# rescue
|
81
|
+
# # do nothing
|
82
|
+
# end
|
83
|
+
#
|
84
|
+
# # good
|
85
|
+
# do_something rescue nil
|
86
|
+
#
|
87
|
+
# @example AllowNil: false
|
88
|
+
#
|
89
|
+
# # bad
|
90
|
+
# def some_method
|
91
|
+
# do_something
|
92
|
+
# rescue
|
93
|
+
# nil
|
94
|
+
# end
|
95
|
+
#
|
96
|
+
# # bad
|
97
|
+
# begin
|
98
|
+
# do_something
|
99
|
+
# rescue
|
100
|
+
# nil
|
101
|
+
# end
|
102
|
+
#
|
103
|
+
# # bad
|
104
|
+
# do_something rescue nil
|
67
105
|
class SuppressedException < Base
|
68
106
|
MSG = 'Do not suppress exceptions.'
|
69
107
|
|
70
108
|
def on_resbody(node)
|
71
|
-
return if node.body
|
109
|
+
return if node.body && !nil_body?(node)
|
72
110
|
return if cop_config['AllowComments'] && comment_between_rescue_and_end?(node)
|
111
|
+
return if cop_config['AllowNil'] && nil_body?(node)
|
73
112
|
|
74
113
|
add_offense(node)
|
75
114
|
end
|
@@ -83,6 +122,10 @@ module RuboCop
|
|
83
122
|
end_line = ancestor.loc.end.line
|
84
123
|
processed_source[node.first_line...end_line].any? { |line| comment_line?(line) }
|
85
124
|
end
|
125
|
+
|
126
|
+
def nil_body?(node)
|
127
|
+
node.body&.nil_type?
|
128
|
+
end
|
86
129
|
end
|
87
130
|
end
|
88
131
|
end
|
@@ -6,6 +6,12 @@ module RuboCop
|
|
6
6
|
# This cop checks for uses of literal strings converted to
|
7
7
|
# a symbol where a literal symbol could be used instead.
|
8
8
|
#
|
9
|
+
# There are two possible styles for this cop.
|
10
|
+
# `strict` (default) will register an offense for any incorrect usage.
|
11
|
+
# `consistent` additionally requires hashes to use the same style for
|
12
|
+
# every symbol key (ie. if any symbol key needs to be quoted it requires
|
13
|
+
# all keys to be quoted).
|
14
|
+
#
|
9
15
|
# @example
|
10
16
|
# # bad
|
11
17
|
# 'string'.to_sym
|
@@ -21,10 +27,49 @@ module RuboCop
|
|
21
27
|
# :underscored_symbol
|
22
28
|
# :'hyphenated-string'
|
23
29
|
#
|
30
|
+
# @example EnforcedStyle: strict (default)
|
31
|
+
#
|
32
|
+
# # bad
|
33
|
+
# {
|
34
|
+
# 'a': 1,
|
35
|
+
# "b": 2,
|
36
|
+
# 'c-d': 3
|
37
|
+
# }
|
38
|
+
#
|
39
|
+
# # good (don't quote keys that don't require quoting)
|
40
|
+
# {
|
41
|
+
# a: 1,
|
42
|
+
# b: 2,
|
43
|
+
# 'c-d': 3
|
44
|
+
# }
|
45
|
+
#
|
46
|
+
# @example EnforcedStyle: consistent
|
47
|
+
#
|
48
|
+
# # bad
|
49
|
+
# {
|
50
|
+
# a: 1,
|
51
|
+
# 'b-c': 2
|
52
|
+
# }
|
53
|
+
#
|
54
|
+
# # good (quote all keys if any need quoting)
|
55
|
+
# {
|
56
|
+
# 'a': 1,
|
57
|
+
# 'b-c': 2
|
58
|
+
# }
|
59
|
+
#
|
60
|
+
# # good (no quoting required)
|
61
|
+
# {
|
62
|
+
# a: 1,
|
63
|
+
# b: 2
|
64
|
+
# }
|
65
|
+
#
|
24
66
|
class SymbolConversion < Base
|
25
67
|
extend AutoCorrector
|
68
|
+
include ConfigurableEnforcedStyle
|
26
69
|
|
27
70
|
MSG = 'Unnecessary symbol conversion; use `%<correction>s` instead.'
|
71
|
+
MSG_CONSISTENCY = 'Symbol hash key should be quoted for consistency; ' \
|
72
|
+
'use `%<correction>s` instead.'
|
28
73
|
RESTRICT_ON_SEND = %i[to_sym intern].freeze
|
29
74
|
|
30
75
|
def on_send(node)
|
@@ -35,7 +80,7 @@ module RuboCop
|
|
35
80
|
end
|
36
81
|
|
37
82
|
def on_sym(node)
|
38
|
-
return if properly_quoted?(node.source, node.value.inspect)
|
83
|
+
return if ignored_node?(node) || properly_quoted?(node.source, node.value.inspect)
|
39
84
|
|
40
85
|
# `alias` arguments are symbols but since a symbol that requires
|
41
86
|
# being quoted is not a valid method identifier, it can be ignored
|
@@ -51,6 +96,21 @@ module RuboCop
|
|
51
96
|
register_offense(node, correction: node.value.inspect)
|
52
97
|
end
|
53
98
|
|
99
|
+
def on_hash(node)
|
100
|
+
# For `EnforcedStyle: strict`, hash keys are evaluated in `on_sym`
|
101
|
+
return unless style == :consistent
|
102
|
+
|
103
|
+
keys = node.keys.select(&:sym_type?)
|
104
|
+
|
105
|
+
if keys.any? { |key| requires_quotes?(key) }
|
106
|
+
correct_inconsistent_hash_keys(keys)
|
107
|
+
else
|
108
|
+
# If there are no symbol keys requiring quoting,
|
109
|
+
# treat the hash like `EnforcedStyle: strict`.
|
110
|
+
keys.each { |key| correct_hash_key(key) }
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
54
114
|
private
|
55
115
|
|
56
116
|
def register_offense(node, correction:, message: format(MSG, correction: correction))
|
@@ -60,7 +120,7 @@ module RuboCop
|
|
60
120
|
end
|
61
121
|
|
62
122
|
def properly_quoted?(source, value)
|
63
|
-
return true if !source.match?(/['"]/) || value.end_with?('=')
|
123
|
+
return true if style == :strict && (!source.match?(/['"]/) || value.end_with?('='))
|
64
124
|
|
65
125
|
source == value ||
|
66
126
|
# `Symbol#inspect` uses double quotes, but allow single-quoted
|
@@ -68,6 +128,10 @@ module RuboCop
|
|
68
128
|
source.tr("'", '"') == value
|
69
129
|
end
|
70
130
|
|
131
|
+
def requires_quotes?(sym_node)
|
132
|
+
sym_node.value.inspect.match?(/^:".*?"|=$/)
|
133
|
+
end
|
134
|
+
|
71
135
|
def in_alias?(node)
|
72
136
|
node.parent&.alias_type?
|
73
137
|
end
|
@@ -97,6 +161,29 @@ module RuboCop
|
|
97
161
|
message: format(MSG, correction: "#{correction}:")
|
98
162
|
)
|
99
163
|
end
|
164
|
+
|
165
|
+
def correct_inconsistent_hash_keys(keys)
|
166
|
+
keys.each do |key|
|
167
|
+
ignore_node(key)
|
168
|
+
|
169
|
+
next if requires_quotes?(key)
|
170
|
+
next if properly_quoted?(key.source, %("#{key.value}"))
|
171
|
+
|
172
|
+
correction = "#{quote_type}#{key.value}#{quote_type}"
|
173
|
+
register_offense(
|
174
|
+
key,
|
175
|
+
correction: correction,
|
176
|
+
message: format(MSG_CONSISTENCY, correction: "#{correction}:")
|
177
|
+
)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def quote_type
|
182
|
+
# Use the `Style/StringLiterals` configuration for quoting symbols
|
183
|
+
return '"' unless config.for_cop('Style/StringLiterals')['Enabled']
|
184
|
+
|
185
|
+
config.for_cop('Style/StringLiterals')['EnforcedStyle'] == 'single_quotes' ? "'" : '"'
|
186
|
+
end
|
100
187
|
end
|
101
188
|
end
|
102
189
|
end
|
@@ -29,15 +29,15 @@ module RuboCop
|
|
29
29
|
|
30
30
|
each_bad_alignment(items, base_column) do |current|
|
31
31
|
expr = current.source_range
|
32
|
-
if
|
32
|
+
if @current_offenses.any? { |o| within?(expr, o.location) }
|
33
33
|
# If this offense is within a line range that is already being
|
34
34
|
# realigned by autocorrect, we report the offense without
|
35
35
|
# autocorrecting it. Two rewrites in the same area by the same
|
36
36
|
# cop cannot be handled. The next iteration will find the
|
37
37
|
# offense again and correct it.
|
38
|
-
|
38
|
+
register_offense(expr, nil)
|
39
39
|
else
|
40
|
-
|
40
|
+
register_offense(current, current)
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
@@ -71,6 +71,13 @@ module RuboCop
|
|
71
71
|
def end_of_line_comment(line)
|
72
72
|
processed_source.line_with_comment?(line)
|
73
73
|
end
|
74
|
+
|
75
|
+
# @api private
|
76
|
+
def register_offense(offense_node, message_node)
|
77
|
+
add_offense(offense_node, message: message(message_node)) do |corrector|
|
78
|
+
autocorrect(corrector, message_node)
|
79
|
+
end
|
80
|
+
end
|
74
81
|
end
|
75
82
|
end
|
76
83
|
end
|
@@ -23,7 +23,11 @@ module RuboCop
|
|
23
23
|
def begin_pos_with_comment(node)
|
24
24
|
first_comment = processed_source.ast_with_comments[node].first
|
25
25
|
|
26
|
-
|
26
|
+
if first_comment && (first_comment.loc.line < node.loc.line)
|
27
|
+
start_line_position(first_comment)
|
28
|
+
else
|
29
|
+
start_line_position(node)
|
30
|
+
end
|
27
31
|
end
|
28
32
|
|
29
33
|
def start_line_position(node)
|