rubocop 1.25.0 → 1.26.1
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/config/default.yml +25 -15
- data/lib/rubocop/cli.rb +1 -1
- data/lib/rubocop/cop/badge.rb +7 -1
- data/lib/rubocop/cop/gemspec/require_mfa.rb +4 -3
- data/lib/rubocop/cop/generator.rb +2 -7
- data/lib/rubocop/cop/internal_affairs/redundant_context_config_parameter.rb +46 -0
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/case_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +5 -1
- data/lib/rubocop/cop/layout/hash_alignment.rb +6 -1
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +7 -8
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -1
- data/lib/rubocop/cop/lint/inherit_exception.rb +19 -28
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +3 -2
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +5 -0
- data/lib/rubocop/cop/lint/symbol_conversion.rb +3 -2
- data/lib/rubocop/cop/lint/useless_times.rb +13 -9
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +27 -13
- data/lib/rubocop/cop/mixin/line_length_help.rb +17 -6
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -1
- data/lib/rubocop/cop/naming/method_parameter_name.rb +1 -1
- data/lib/rubocop/cop/security/yaml_load.rb +9 -3
- data/lib/rubocop/cop/style/def_with_parentheses.rb +16 -11
- data/lib/rubocop/cop/style/for.rb +4 -0
- data/lib/rubocop/cop/style/lambda_call.rb +12 -20
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +11 -5
- data/lib/rubocop/cop/style/nested_file_dirname.rb +66 -0
- data/lib/rubocop/cop/style/optional_boolean_parameter.rb +3 -2
- data/lib/rubocop/cop/style/redundant_begin.rb +2 -6
- data/lib/rubocop/cop/style/select_by_regexp.rb +6 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +50 -12
- data/lib/rubocop/cop/style/string_concatenation.rb +7 -1
- data/lib/rubocop/cop/style/swap_values.rb +2 -0
- data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +1 -1
- data/lib/rubocop/cop/style/unless_else.rb +4 -0
- data/lib/rubocop/cop/variable_force.rb +1 -5
- data/lib/rubocop/cops_documentation_generator.rb +2 -2
- data/lib/rubocop/formatter/disabled_config_formatter.rb +16 -2
- data/lib/rubocop/options.rb +8 -2
- data/lib/rubocop/rspec/shared_contexts.rb +4 -0
- data/lib/rubocop/runner.rb +1 -1
- data/lib/rubocop/target_ruby.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +1 -0
- metadata +7 -5
@@ -7,17 +7,21 @@ module RuboCop
|
|
7
7
|
# potential security issues leading to remote code execution when
|
8
8
|
# loading from an untrusted source.
|
9
9
|
#
|
10
|
+
# NOTE: Ruby 3.1+ (Psych 4) uses `Psych.load` as `Psych.safe_load` by default.
|
11
|
+
#
|
10
12
|
# @safety
|
11
13
|
# The behaviour of the code might change depending on what was
|
12
14
|
# in the YAML payload, since `YAML.safe_load` is more restrictive.
|
13
15
|
#
|
14
16
|
# @example
|
15
17
|
# # bad
|
16
|
-
# YAML.load("---
|
18
|
+
# YAML.load("--- !ruby/object:Foo {}") # Psych 3 is unsafe by default
|
17
19
|
#
|
18
20
|
# # good
|
19
|
-
# YAML.safe_load("---
|
20
|
-
# YAML.
|
21
|
+
# YAML.safe_load("--- !ruby/object:Foo {}", [Foo]) # Ruby 2.5 (Psych 3)
|
22
|
+
# YAML.safe_load("--- !ruby/object:Foo {}", permitted_classes: [Foo]) # Ruby 3.0- (Psych 3)
|
23
|
+
# YAML.load("--- !ruby/object:Foo {}", permitted_classes: [Foo]) # Ruby 3.1+ (Psych 4)
|
24
|
+
# YAML.dump(foo)
|
21
25
|
#
|
22
26
|
class YAMLLoad < Base
|
23
27
|
extend AutoCorrector
|
@@ -31,6 +35,8 @@ module RuboCop
|
|
31
35
|
PATTERN
|
32
36
|
|
33
37
|
def on_send(node)
|
38
|
+
return if target_ruby_version >= 3.1
|
39
|
+
|
34
40
|
yaml_load(node) do
|
35
41
|
add_offense(node.loc.selector) do |corrector|
|
36
42
|
corrector.replace(node.loc.selector, 'safe_load')
|
@@ -11,27 +11,33 @@ module RuboCop
|
|
11
11
|
#
|
12
12
|
# # bad
|
13
13
|
# def foo()
|
14
|
-
#
|
14
|
+
# do_something
|
15
15
|
# end
|
16
16
|
#
|
17
17
|
# # good
|
18
18
|
# def foo
|
19
|
-
#
|
19
|
+
# do_something
|
20
20
|
# end
|
21
21
|
#
|
22
|
-
# #
|
23
|
-
# def foo()
|
22
|
+
# # bad
|
23
|
+
# def foo() = do_something
|
24
|
+
#
|
25
|
+
# # good
|
26
|
+
# def foo = do_something
|
27
|
+
#
|
28
|
+
# # good (without parentheses it's a syntax error)
|
29
|
+
# def foo() do_something end
|
24
30
|
#
|
25
31
|
# @example
|
26
32
|
#
|
27
33
|
# # bad
|
28
34
|
# def Baz.foo()
|
29
|
-
#
|
35
|
+
# do_something
|
30
36
|
# end
|
31
37
|
#
|
32
38
|
# # good
|
33
39
|
# def Baz.foo
|
34
|
-
#
|
40
|
+
# do_something
|
35
41
|
# end
|
36
42
|
class DefWithParentheses < Base
|
37
43
|
extend AutoCorrector
|
@@ -39,12 +45,11 @@ module RuboCop
|
|
39
45
|
MSG = "Omit the parentheses in defs when the method doesn't accept any arguments."
|
40
46
|
|
41
47
|
def on_def(node)
|
42
|
-
return if node.single_line?
|
43
|
-
return unless !node.arguments? && (
|
48
|
+
return if node.single_line? && !node.endless?
|
49
|
+
return unless !node.arguments? && (node_arguments = node.arguments.source_range)
|
44
50
|
|
45
|
-
add_offense(
|
46
|
-
corrector.remove(
|
47
|
-
corrector.remove(node.arguments.loc.end)
|
51
|
+
add_offense(node_arguments) do |corrector|
|
52
|
+
corrector.remove(node_arguments)
|
48
53
|
end
|
49
54
|
end
|
50
55
|
alias on_defs on_def
|
@@ -22,45 +22,37 @@ module RuboCop
|
|
22
22
|
include ConfigurableEnforcedStyle
|
23
23
|
extend AutoCorrector
|
24
24
|
|
25
|
+
MSG = 'Prefer the use of `%<prefer>s` over `%<current>s`.'
|
25
26
|
RESTRICT_ON_SEND = %i[call].freeze
|
26
27
|
|
27
28
|
def on_send(node)
|
28
29
|
return unless node.receiver
|
29
30
|
|
30
31
|
if offense?(node)
|
31
|
-
|
32
|
+
prefer = prefer(node)
|
33
|
+
current = node.source
|
34
|
+
|
35
|
+
add_offense(node, message: format(MSG, prefer: prefer, current: current)) do |corrector|
|
32
36
|
opposite_style_detected
|
33
|
-
|
37
|
+
corrector.replace(node, prefer)
|
34
38
|
end
|
35
39
|
else
|
36
40
|
correct_style_detected
|
37
41
|
end
|
38
42
|
end
|
39
43
|
|
40
|
-
def autocorrect(corrector, node)
|
41
|
-
if explicit_style?
|
42
|
-
receiver = node.receiver.source
|
43
|
-
replacement = node.source.sub("#{receiver}.", "#{receiver}.call")
|
44
|
-
|
45
|
-
corrector.replace(node, replacement)
|
46
|
-
else
|
47
|
-
add_parentheses(node, corrector) unless node.parenthesized?
|
48
|
-
corrector.remove(node.loc.selector)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
44
|
private
|
53
45
|
|
54
46
|
def offense?(node)
|
55
47
|
(explicit_style? && node.implicit_call?) || (implicit_style? && !node.implicit_call?)
|
56
48
|
end
|
57
49
|
|
58
|
-
def
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
50
|
+
def prefer(node)
|
51
|
+
receiver = node.receiver.source
|
52
|
+
arguments = node.arguments.map(&:source).join(', ')
|
53
|
+
method = explicit_style? ? "call(#{arguments})" : "(#{arguments})"
|
54
|
+
|
55
|
+
"#{receiver}.#{method}"
|
64
56
|
end
|
65
57
|
|
66
58
|
def implicit_style?
|
@@ -48,15 +48,21 @@ module RuboCop
|
|
48
48
|
node.each_ancestor(:def, :defs).any?(&:endless?) && node.arguments.any?
|
49
49
|
end
|
50
50
|
|
51
|
-
# Require hash value omission be enclosed in parentheses to prevent the following issue:
|
52
|
-
# https://bugs.ruby-lang.org/issues/18396.
|
53
51
|
def require_parentheses_for_hash_value_omission?(node)
|
54
52
|
return false unless (last_argument = node.last_argument)
|
53
|
+
return false if !last_argument.hash_type? || !last_argument.pairs.last&.value_omission?
|
55
54
|
|
56
|
-
|
57
|
-
|
55
|
+
modifier_form?(node) || exist_next_line_expression?(node)
|
56
|
+
end
|
58
57
|
|
59
|
-
|
58
|
+
def modifier_form?(node)
|
59
|
+
node.parent.respond_to?(:modifier_form?) && node.parent.modifier_form?
|
60
|
+
end
|
61
|
+
|
62
|
+
# Require hash value omission be enclosed in parentheses to prevent the following issue:
|
63
|
+
# https://bugs.ruby-lang.org/issues/18396.
|
64
|
+
def exist_next_line_expression?(node)
|
65
|
+
node.parent&.assignment? ? node.parent.right_sibling : node.right_sibling
|
60
66
|
end
|
61
67
|
|
62
68
|
def syntax_like_method_call?(node)
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cop checks for nested `File.dirname`.
|
7
|
+
# It replaces nested `File.dirname` with the level argument introduced in Ruby 3.1.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
#
|
11
|
+
# # bad
|
12
|
+
# File.dirname(File.dirname(path))
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# File.dirname(path, 2)
|
16
|
+
#
|
17
|
+
class NestedFileDirname < Base
|
18
|
+
include RangeHelp
|
19
|
+
extend AutoCorrector
|
20
|
+
extend TargetRubyVersion
|
21
|
+
|
22
|
+
MSG = 'Use `dirname(%<path>s, %<level>s)` instead.'
|
23
|
+
RESTRICT_ON_SEND = %i[dirname].freeze
|
24
|
+
|
25
|
+
minimum_target_ruby_version 3.1
|
26
|
+
|
27
|
+
# @!method file_dirname?(node)
|
28
|
+
def_node_matcher :file_dirname?, <<~PATTERN
|
29
|
+
(send
|
30
|
+
(const {cbase nil?} :File) :dirname ...)
|
31
|
+
PATTERN
|
32
|
+
|
33
|
+
def on_send(node)
|
34
|
+
return if file_dirname?(node.parent) || !file_dirname?(node.first_argument)
|
35
|
+
|
36
|
+
path, level = path_with_dir_level(node, 1)
|
37
|
+
return if level < 2
|
38
|
+
|
39
|
+
message = format(MSG, path: path, level: level)
|
40
|
+
range = offense_range(node)
|
41
|
+
|
42
|
+
add_offense(range, message: message) do |corrector|
|
43
|
+
corrector.replace(range, "dirname(#{path}, #{level})")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def path_with_dir_level(node, level)
|
50
|
+
first_argument = node.first_argument
|
51
|
+
|
52
|
+
if file_dirname?(first_argument)
|
53
|
+
level += 1
|
54
|
+
path_with_dir_level(first_argument, level)
|
55
|
+
else
|
56
|
+
[first_argument.source, level]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def offense_range(node)
|
61
|
+
range_between(node.loc.selector.begin_pos, node.source_range.end_pos)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -54,8 +54,9 @@ module RuboCop
|
|
54
54
|
private
|
55
55
|
|
56
56
|
def format_message(argument)
|
57
|
-
|
58
|
-
|
57
|
+
replacement = "#{argument.name}: #{argument.default_value.source}"
|
58
|
+
|
59
|
+
format(MSG, original: argument.source, replacement: replacement)
|
59
60
|
end
|
60
61
|
end
|
61
62
|
end
|
@@ -97,7 +97,7 @@ module RuboCop
|
|
97
97
|
offense_range = node.loc.begin
|
98
98
|
|
99
99
|
add_offense(offense_range) do |corrector|
|
100
|
-
if
|
100
|
+
if node.parent&.assignment?
|
101
101
|
replace_begin_with_statement(corrector, offense_range, node)
|
102
102
|
else
|
103
103
|
corrector.remove(offense_range)
|
@@ -170,11 +170,7 @@ module RuboCop
|
|
170
170
|
end
|
171
171
|
|
172
172
|
def valid_begin_assignment?(node)
|
173
|
-
|
174
|
-
end
|
175
|
-
|
176
|
-
def any_ancestor_assignment_node?(node)
|
177
|
-
node.each_ancestor.any?(&:assignment?)
|
173
|
+
node.parent&.assignment? && !node.children.one?
|
178
174
|
end
|
179
175
|
end
|
180
176
|
end
|
@@ -69,6 +69,11 @@ module RuboCop
|
|
69
69
|
}
|
70
70
|
PATTERN
|
71
71
|
|
72
|
+
# @!method env_const?(node)
|
73
|
+
def_node_matcher :env_const?, <<~PATTERN
|
74
|
+
(const {nil? cbase} :ENV)
|
75
|
+
PATTERN
|
76
|
+
|
72
77
|
# @!method calls_lvar?(node, name)
|
73
78
|
def_node_matcher :calls_lvar?, <<~PATTERN
|
74
79
|
{
|
@@ -94,7 +99,7 @@ module RuboCop
|
|
94
99
|
def receiver_allowed?(node)
|
95
100
|
return false unless node
|
96
101
|
|
97
|
-
node.hash_type? || creates_hash?(node)
|
102
|
+
node.hash_type? || creates_hash?(node) || env_const?(node)
|
98
103
|
end
|
99
104
|
|
100
105
|
def register_offense(node, block_node, regexp)
|
@@ -15,6 +15,11 @@ module RuboCop
|
|
15
15
|
# end
|
16
16
|
# end
|
17
17
|
#
|
18
|
+
# # bad
|
19
|
+
# if condition_b
|
20
|
+
# do_something
|
21
|
+
# end if condition_a
|
22
|
+
#
|
18
23
|
# # good
|
19
24
|
# if condition_a && condition_b
|
20
25
|
# do_something
|
@@ -26,12 +31,21 @@ module RuboCop
|
|
26
31
|
# do_something if condition_b
|
27
32
|
# end
|
28
33
|
#
|
34
|
+
# # bad
|
35
|
+
# if condition_b
|
36
|
+
# do_something
|
37
|
+
# end if condition_a
|
38
|
+
#
|
29
39
|
# @example AllowModifier: true
|
30
40
|
# # good
|
31
41
|
# if condition_a
|
32
42
|
# do_something if condition_b
|
33
43
|
# end
|
34
44
|
#
|
45
|
+
# # good
|
46
|
+
# if condition_b
|
47
|
+
# do_something
|
48
|
+
# end if condition_a
|
35
49
|
class SoleNestedConditional < Base
|
36
50
|
include RangeHelp
|
37
51
|
extend AutoCorrector
|
@@ -47,7 +61,7 @@ module RuboCop
|
|
47
61
|
|
48
62
|
if_branch = node.if_branch
|
49
63
|
return if use_variable_assignment_in_condition?(node.condition, if_branch)
|
50
|
-
return unless offending_branch?(if_branch)
|
64
|
+
return unless offending_branch?(node, if_branch)
|
51
65
|
|
52
66
|
message = format(MSG, conditional_type: node.keyword)
|
53
67
|
add_offense(if_branch.loc.keyword, message: message) do |corrector|
|
@@ -72,13 +86,13 @@ module RuboCop
|
|
72
86
|
end
|
73
87
|
end
|
74
88
|
|
75
|
-
def offending_branch?(branch)
|
89
|
+
def offending_branch?(node, branch)
|
76
90
|
return false unless branch
|
77
91
|
|
78
92
|
branch.if_type? &&
|
79
93
|
!branch.else? &&
|
80
94
|
!branch.ternary? &&
|
81
|
-
!(branch.modifier_form? && allow_modifier?)
|
95
|
+
!((node.modifier_form? || branch.modifier_form?) && allow_modifier?)
|
82
96
|
end
|
83
97
|
|
84
98
|
def autocorrect(corrector, node, if_branch)
|
@@ -86,6 +100,14 @@ module RuboCop
|
|
86
100
|
corrector.wrap(node.condition, '(', ')')
|
87
101
|
end
|
88
102
|
|
103
|
+
if outer_condition_modify_form?(node, if_branch)
|
104
|
+
autocorrect_outer_condition_modify_form(corrector, node, if_branch)
|
105
|
+
else
|
106
|
+
autocorrect_outer_condition_basic(corrector, node, if_branch)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def autocorrect_outer_condition_basic(corrector, node, if_branch)
|
89
111
|
correct_from_unless_to_if(corrector, node) if node.unless?
|
90
112
|
|
91
113
|
and_operator = if_branch.unless? ? ' && !' : ' && '
|
@@ -97,11 +119,17 @@ module RuboCop
|
|
97
119
|
end
|
98
120
|
end
|
99
121
|
|
100
|
-
def
|
122
|
+
def autocorrect_outer_condition_modify_form(corrector, node, if_branch)
|
123
|
+
correct_from_unless_to_if(corrector, if_branch, is_modify_form: true) if if_branch.unless?
|
124
|
+
correct_for_outer_condition_modify_form_style(corrector, node, if_branch)
|
125
|
+
end
|
126
|
+
|
127
|
+
def correct_from_unless_to_if(corrector, node, is_modify_form: false)
|
101
128
|
corrector.replace(node.loc.keyword, 'if')
|
102
129
|
|
103
130
|
condition = node.condition
|
104
|
-
if condition.send_type? && condition.comparison_method? && !condition.parenthesized?
|
131
|
+
if (condition.send_type? && condition.comparison_method? && !condition.parenthesized?) ||
|
132
|
+
(is_modify_form && wrap_condition?(condition))
|
105
133
|
corrector.wrap(node.condition, '!(', ')')
|
106
134
|
else
|
107
135
|
corrector.insert_before(node.condition, '!')
|
@@ -113,7 +141,7 @@ module RuboCop
|
|
113
141
|
correct_outer_condition(corrector, outer_condition)
|
114
142
|
|
115
143
|
condition = if_branch.condition
|
116
|
-
corrector.insert_after(outer_condition,
|
144
|
+
corrector.insert_after(outer_condition, "#{and_operator}#{replace_condition(condition)}")
|
117
145
|
|
118
146
|
range = range_between(if_branch.loc.keyword.begin_pos, condition.source_range.end_pos)
|
119
147
|
corrector.remove(range_with_surrounding_space(range: range, newlines: false))
|
@@ -129,6 +157,16 @@ module RuboCop
|
|
129
157
|
corrector.wrap(if_branch.condition, '(', ')') if wrap_condition?(if_branch.condition)
|
130
158
|
end
|
131
159
|
|
160
|
+
def correct_for_outer_condition_modify_form_style(corrector, node, if_branch)
|
161
|
+
condition = if_branch.condition
|
162
|
+
corrector.insert_before(condition,
|
163
|
+
"#{'!' if node.unless?}#{replace_condition(node.condition)} && ")
|
164
|
+
|
165
|
+
corrector.remove(node.condition.loc.expression)
|
166
|
+
corrector.remove(range_with_surrounding_space(range: node.loc.keyword, newlines: false))
|
167
|
+
corrector.replace(if_branch.loc.keyword, 'if')
|
168
|
+
end
|
169
|
+
|
132
170
|
def correct_for_comment(corrector, node, if_branch)
|
133
171
|
return if config.for_cop('Style/IfUnlessModifier')['Enabled']
|
134
172
|
|
@@ -165,17 +203,17 @@ module RuboCop
|
|
165
203
|
(node.send_type? && node.arguments.any? && !node.parenthesized?)
|
166
204
|
end
|
167
205
|
|
168
|
-
def
|
169
|
-
|
170
|
-
"#{and_operator}(#{condition.source})"
|
171
|
-
else
|
172
|
-
"#{and_operator}#{condition.source}"
|
173
|
-
end
|
206
|
+
def replace_condition(condition)
|
207
|
+
wrap_condition?(condition) ? "(#{condition.source})" : condition.source
|
174
208
|
end
|
175
209
|
|
176
210
|
def allow_modifier?
|
177
211
|
cop_config['AllowModifier']
|
178
212
|
end
|
213
|
+
|
214
|
+
def outer_condition_modify_form?(node, if_branch)
|
215
|
+
node.condition.loc.expression.begin_pos > if_branch.condition.loc.expression.begin_pos
|
216
|
+
end
|
179
217
|
end
|
180
218
|
end
|
181
219
|
end
|
@@ -134,7 +134,13 @@ module RuboCop
|
|
134
134
|
end
|
135
135
|
|
136
136
|
def uncorrectable?(part)
|
137
|
-
part.multiline? || (part
|
137
|
+
part.multiline? || heredoc?(part) || part.each_descendant(:block).any?
|
138
|
+
end
|
139
|
+
|
140
|
+
def heredoc?(node)
|
141
|
+
return false unless node.str_type? || node.dstr_type?
|
142
|
+
|
143
|
+
node.heredoc?
|
138
144
|
end
|
139
145
|
|
140
146
|
def corrected_ancestor?(node)
|
@@ -10,7 +10,7 @@ module RuboCop
|
|
10
10
|
# last item of all non-empty, multiline array literals.
|
11
11
|
# * `comma`: Requires a comma after last item in an array,
|
12
12
|
# but only when each item is on its own line.
|
13
|
-
# * `no_comma`: Does not
|
13
|
+
# * `no_comma`: Does not require a comma after the
|
14
14
|
# last item in an array
|
15
15
|
#
|
16
16
|
# @example EnforcedStyleForMultiline: consistent_comma
|
@@ -10,7 +10,7 @@ module RuboCop
|
|
10
10
|
# last item of all non-empty, multiline hash literals.
|
11
11
|
# * `comma`: Requires a comma after the last item in a hash,
|
12
12
|
# but only when each item is on its own line.
|
13
|
-
# * `no_comma`: Does not
|
13
|
+
# * `no_comma`: Does not require a comma after the
|
14
14
|
# last item in a hash
|
15
15
|
#
|
16
16
|
# @example EnforcedStyleForMultiline: consistent_comma
|
@@ -32,10 +32,14 @@ module RuboCop
|
|
32
32
|
body_range = range_between_condition_and_else(node, node.condition)
|
33
33
|
else_range = range_between_else_and_end(node)
|
34
34
|
|
35
|
+
next if part_of_ignored_node?(node)
|
36
|
+
|
35
37
|
corrector.replace(node.loc.keyword, 'if')
|
36
38
|
corrector.replace(body_range, else_range.source)
|
37
39
|
corrector.replace(else_range, body_range.source)
|
38
40
|
end
|
41
|
+
|
42
|
+
ignore_node(node)
|
39
43
|
end
|
40
44
|
|
41
45
|
def range_between_condition_and_else(node, condition)
|
@@ -186,11 +186,7 @@ module RuboCop
|
|
186
186
|
end
|
187
187
|
|
188
188
|
def regexp_captured_names(node)
|
189
|
-
|
190
|
-
child.children.first
|
191
|
-
end.join || ''
|
192
|
-
|
193
|
-
regexp = Regexp.new(regexp_string)
|
189
|
+
regexp = node.to_regexp
|
194
190
|
|
195
191
|
regexp.named_captures.keys
|
196
192
|
end
|
@@ -191,8 +191,8 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
191
191
|
|
192
192
|
def wrap_backtick(value)
|
193
193
|
if value.is_a?(String)
|
194
|
-
# Use `+` to prevent text like `**/*.gemspec` from being bold.
|
195
|
-
value.
|
194
|
+
# Use `+` to prevent text like `**/*.gemspec`, `spec/**/*` from being bold.
|
195
|
+
value.include?('*') ? "`+#{value}+`" : "`#{value}`"
|
196
196
|
else
|
197
197
|
"`#{value}`"
|
198
198
|
end
|
@@ -121,9 +121,14 @@ module RuboCop
|
|
121
121
|
output_buffer.puts "# Offense count: #{offense_count}" if show_offense_counts?
|
122
122
|
|
123
123
|
cop_class = Cop::Registry.global.find_by_cop_name(cop_name)
|
124
|
-
output_buffer.puts '# Cop supports --auto-correct.' if cop_class&.support_autocorrect?
|
125
|
-
|
126
124
|
default_cfg = default_config(cop_name)
|
125
|
+
|
126
|
+
if supports_safe_auto_correct?(cop_class, default_cfg)
|
127
|
+
output_buffer.puts '# This cop supports safe auto-correction (--auto-correct).'
|
128
|
+
elsif supports_unsafe_autocorrect?(cop_class, default_cfg)
|
129
|
+
output_buffer.puts '# This cop supports unsafe auto-correction (--auto-correct-all).'
|
130
|
+
end
|
131
|
+
|
127
132
|
return unless default_cfg
|
128
133
|
|
129
134
|
params = cop_config_params(default_cfg, cfg)
|
@@ -132,6 +137,15 @@ module RuboCop
|
|
132
137
|
output_cop_param_comments(output_buffer, params, default_cfg)
|
133
138
|
end
|
134
139
|
|
140
|
+
def supports_safe_auto_correct?(cop_class, default_cfg)
|
141
|
+
cop_class&.support_autocorrect? &&
|
142
|
+
(default_cfg.nil? || default_cfg['Safe'] || default_cfg['Safe'].nil?)
|
143
|
+
end
|
144
|
+
|
145
|
+
def supports_unsafe_autocorrect?(cop_class, default_cfg)
|
146
|
+
cop_class&.support_autocorrect? && !default_cfg.nil? && default_cfg['Safe'] == false
|
147
|
+
end
|
148
|
+
|
135
149
|
def cop_config_params(default_cfg, cfg)
|
136
150
|
default_cfg.keys -
|
137
151
|
%w[Description StyleGuide Reference Enabled Exclude Safe
|
data/lib/rubocop/options.rb
CHANGED
@@ -467,8 +467,14 @@ module RuboCop
|
|
467
467
|
'This option applies to the previously',
|
468
468
|
'specified --format, or the default format',
|
469
469
|
'if no format is specified.'],
|
470
|
-
fail_level: ['Minimum severity
|
471
|
-
'
|
470
|
+
fail_level: ['Minimum severity for exit with error code.',
|
471
|
+
' [A] autocorrect',
|
472
|
+
' [I] info',
|
473
|
+
' [R] refactor',
|
474
|
+
' [C] convention',
|
475
|
+
' [W] warning',
|
476
|
+
' [E] error',
|
477
|
+
' [F] fatal'],
|
472
478
|
display_time: 'Display elapsed time in seconds.',
|
473
479
|
display_only_failed: ['Only output offense messages. Omit passing',
|
474
480
|
'cops. Only valid for --format junit.'],
|
data/lib/rubocop/runner.rb
CHANGED
@@ -8,7 +8,7 @@ module RuboCop
|
|
8
8
|
class Runner # rubocop:disable Metrics/ClassLength
|
9
9
|
# An exception indicating that the inspection loop got stuck correcting
|
10
10
|
# offenses back and forth.
|
11
|
-
class InfiniteCorrectionLoop <
|
11
|
+
class InfiniteCorrectionLoop < StandardError
|
12
12
|
attr_reader :offenses
|
13
13
|
|
14
14
|
def initialize(path, offenses_by_iteration, loop_start: -1)
|
data/lib/rubocop/target_ruby.rb
CHANGED
@@ -4,7 +4,7 @@ module RuboCop
|
|
4
4
|
# The kind of Ruby that code inspected by RuboCop is written in.
|
5
5
|
# @api private
|
6
6
|
class TargetRuby
|
7
|
-
KNOWN_RUBIES = [2.5, 2.6, 2.7, 3.0, 3.1].freeze
|
7
|
+
KNOWN_RUBIES = [2.5, 2.6, 2.7, 3.0, 3.1, 3.2].freeze
|
8
8
|
DEFAULT_VERSION = KNOWN_RUBIES.first
|
9
9
|
|
10
10
|
OBSOLETE_RUBIES = {
|
data/lib/rubocop/version.rb
CHANGED
data/lib/rubocop.rb
CHANGED
@@ -552,6 +552,7 @@ require_relative 'rubocop/cop/style/negated_if'
|
|
552
552
|
require_relative 'rubocop/cop/style/negated_if_else_condition'
|
553
553
|
require_relative 'rubocop/cop/style/negated_unless'
|
554
554
|
require_relative 'rubocop/cop/style/negated_while'
|
555
|
+
require_relative 'rubocop/cop/style/nested_file_dirname'
|
555
556
|
require_relative 'rubocop/cop/style/nested_modifier'
|
556
557
|
require_relative 'rubocop/cop/style/nested_parenthesized_calls'
|
557
558
|
require_relative 'rubocop/cop/style/nested_ternary_operator'
|