rubocop 1.65.1 → 1.66.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 +67 -67
- data/config/default.yml +18 -2
- data/exe/rubocop +4 -3
- data/lib/rubocop/comment_config.rb +1 -1
- data/lib/rubocop/config.rb +5 -1
- data/lib/rubocop/config_loader.rb +14 -8
- data/lib/rubocop/config_loader_resolver.rb +1 -2
- data/lib/rubocop/config_validator.rb +1 -1
- data/lib/rubocop/cop/base.rb +4 -0
- data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -0
- data/lib/rubocop/cop/documentation.rb +18 -1
- data/lib/rubocop/cop/internal_affairs/empty_line_between_expect_offense_and_correction.rb +2 -1
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +11 -1
- data/lib/rubocop/cop/layout/block_alignment.rb +30 -12
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +2 -1
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +8 -3
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +0 -3
- data/lib/rubocop/cop/layout/line_length.rb +14 -14
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +27 -6
- data/lib/rubocop/cop/lint/float_comparison.rb +1 -3
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +4 -2
- data/lib/rubocop/cop/lint/useless_assignment.rb +18 -11
- data/lib/rubocop/cop/lint/useless_numeric_operation.rb +77 -0
- data/lib/rubocop/cop/lint/void.rb +30 -8
- data/lib/rubocop/cop/metrics/block_length.rb +6 -5
- data/lib/rubocop/cop/metrics/class_length.rb +6 -5
- data/lib/rubocop/cop/metrics/method_length.rb +6 -5
- data/lib/rubocop/cop/metrics/module_length.rb +6 -5
- data/lib/rubocop/cop/mixin/annotation_comment.rb +0 -2
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +19 -9
- data/lib/rubocop/cop/mixin/line_length_help.rb +7 -2
- data/lib/rubocop/cop/mixin/string_literals_help.rb +12 -0
- data/lib/rubocop/cop/naming/accessor_method_name.rb +5 -0
- data/lib/rubocop/cop/naming/predicate_name.rb +1 -1
- data/lib/rubocop/cop/style/alias.rb +1 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +8 -3
- data/lib/rubocop/cop/style/empty_else.rb +6 -5
- data/lib/rubocop/cop/style/empty_heredoc.rb +1 -14
- data/lib/rubocop/cop/style/empty_literal.rb +31 -22
- data/lib/rubocop/cop/style/format_string_token.rb +2 -2
- data/lib/rubocop/cop/style/guard_clause.rb +2 -0
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +1 -1
- data/lib/rubocop/cop/style/if_with_semicolon.rb +45 -6
- data/lib/rubocop/cop/style/in_pattern_then.rb +6 -2
- data/lib/rubocop/cop/style/magic_comment_format.rb +1 -1
- data/lib/rubocop/cop/style/map_into_array.rb +12 -5
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -2
- data/lib/rubocop/cop/style/multiple_comparison.rb +3 -11
- data/lib/rubocop/cop/style/numeric_predicate.rb +2 -2
- data/lib/rubocop/cop/style/one_line_conditional.rb +1 -1
- data/lib/rubocop/cop/style/parallel_assignment.rb +5 -4
- data/lib/rubocop/cop/style/quoted_symbols.rb +0 -2
- data/lib/rubocop/cop/style/redundant_condition.rb +3 -2
- data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +46 -0
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +2 -2
- data/lib/rubocop/cop/team.rb +6 -2
- data/lib/rubocop/formatter/junit_formatter.rb +70 -23
- data/lib/rubocop/lockfile.rb +6 -4
- data/lib/rubocop/remote_config.rb +5 -1
- data/lib/rubocop/result_cache.rb +2 -8
- data/lib/rubocop/rspec/shared_contexts.rb +2 -2
- data/lib/rubocop/server/cache.rb +1 -1
- data/lib/rubocop/target_ruby.rb +7 -3
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop/yaml_duplication_checker.rb +1 -0
- data/lib/rubocop.rb +2 -1
- metadata +12 -30
@@ -334,13 +334,18 @@ module RuboCop
|
|
334
334
|
end
|
335
335
|
end
|
336
336
|
|
337
|
+
# rubocop:disable Metrics/AbcSize
|
337
338
|
def arguments_range(node, first_node)
|
338
|
-
arguments = node.arguments.reject
|
339
|
+
arguments = node.arguments.reject do |arg|
|
340
|
+
next true if ADDITIONAL_ARG_TYPES.include?(arg.type) || arg.variable? || arg.call_type?
|
339
341
|
|
340
|
-
|
342
|
+
arg.literal? && arg.each_descendant(:kwsplat).none?
|
343
|
+
end
|
341
344
|
|
342
|
-
|
345
|
+
start_node = first_node || arguments.first
|
346
|
+
start_node.source_range.begin.join(arguments.last.source_range.end)
|
343
347
|
end
|
348
|
+
# rubocop:enable Metrics/AbcSize
|
344
349
|
|
345
350
|
def allow_only_rest_arguments?
|
346
351
|
cop_config.fetch('AllowOnlyRestArgument', true)
|
@@ -143,7 +143,7 @@ module RuboCop
|
|
143
143
|
private
|
144
144
|
|
145
145
|
def check(node)
|
146
|
-
return if cop_config['AllowComments'] && comment_in_else?(node
|
146
|
+
return if cop_config['AllowComments'] && comment_in_else?(node)
|
147
147
|
|
148
148
|
empty_check(node) if empty_style?
|
149
149
|
nil_check(node) if nil_style?
|
@@ -171,16 +171,17 @@ module RuboCop
|
|
171
171
|
|
172
172
|
def autocorrect(corrector, node)
|
173
173
|
return false if autocorrect_forbidden?(node.type.to_s)
|
174
|
-
return false if comment_in_else?(node
|
174
|
+
return false if comment_in_else?(node)
|
175
175
|
|
176
176
|
end_pos = base_node(node).loc.end.begin_pos
|
177
177
|
corrector.remove(range_between(node.loc.else.begin_pos, end_pos))
|
178
178
|
end
|
179
179
|
|
180
|
-
def comment_in_else?(
|
181
|
-
|
180
|
+
def comment_in_else?(node)
|
181
|
+
node = node.parent while node.if_type? && node.elsif?
|
182
|
+
return false unless node.else?
|
182
183
|
|
183
|
-
processed_source.contains_comment?(loc.else.join(
|
184
|
+
processed_source.contains_comment?(node.loc.else.join(node.source_range.end))
|
184
185
|
end
|
185
186
|
|
186
187
|
def base_node(node)
|
@@ -36,6 +36,7 @@ module RuboCop
|
|
36
36
|
class EmptyHeredoc < Base
|
37
37
|
include Heredoc
|
38
38
|
include RangeHelp
|
39
|
+
include StringLiteralsHelp
|
39
40
|
extend AutoCorrector
|
40
41
|
|
41
42
|
MSG = 'Use an empty string literal instead of heredoc.'
|
@@ -53,20 +54,6 @@ module RuboCop
|
|
53
54
|
corrector.remove(range_by_whole_lines(heredoc_end, include_final_newline: true))
|
54
55
|
end
|
55
56
|
end
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
def preferred_string_literal
|
60
|
-
enforce_double_quotes? ? '""' : "''"
|
61
|
-
end
|
62
|
-
|
63
|
-
def enforce_double_quotes?
|
64
|
-
string_literals_config['EnforcedStyle'] == 'double_quotes'
|
65
|
-
end
|
66
|
-
|
67
|
-
def string_literals_config
|
68
|
-
config.for_cop('Style/StringLiterals')
|
69
|
-
end
|
70
57
|
end
|
71
58
|
end
|
72
59
|
end
|
@@ -9,7 +9,9 @@ module RuboCop
|
|
9
9
|
# @example
|
10
10
|
# # bad
|
11
11
|
# a = Array.new
|
12
|
+
# a = Array[]
|
12
13
|
# h = Hash.new
|
14
|
+
# h = Hash[]
|
13
15
|
# s = String.new
|
14
16
|
#
|
15
17
|
# # good
|
@@ -19,16 +21,17 @@ module RuboCop
|
|
19
21
|
class EmptyLiteral < Base
|
20
22
|
include FrozenStringLiteral
|
21
23
|
include RangeHelp
|
24
|
+
include StringLiteralsHelp
|
22
25
|
extend AutoCorrector
|
23
26
|
|
24
|
-
ARR_MSG = 'Use array literal `[]` instead of
|
25
|
-
HASH_MSG = 'Use hash literal `{}` instead of
|
27
|
+
ARR_MSG = 'Use array literal `[]` instead of `%<current>s`.'
|
28
|
+
HASH_MSG = 'Use hash literal `{}` instead of `%<current>s`.'
|
26
29
|
STR_MSG = 'Use string literal `%<prefer>s` instead of `String.new`.'
|
27
30
|
|
28
|
-
RESTRICT_ON_SEND = %i[new].freeze
|
31
|
+
RESTRICT_ON_SEND = %i[new [] Array Hash].freeze
|
29
32
|
|
30
33
|
# @!method array_node(node)
|
31
|
-
def_node_matcher :array_node, '(send (const {nil? cbase} :Array) :new)'
|
34
|
+
def_node_matcher :array_node, '(send (const {nil? cbase} :Array) :new (array)?)'
|
32
35
|
|
33
36
|
# @!method hash_node(node)
|
34
37
|
def_node_matcher :hash_node, '(send (const {nil? cbase} :Hash) :new)'
|
@@ -47,6 +50,22 @@ module RuboCop
|
|
47
50
|
}
|
48
51
|
PATTERN
|
49
52
|
|
53
|
+
# @!method array_with_index(node)
|
54
|
+
def_node_matcher :array_with_index, <<~PATTERN
|
55
|
+
{
|
56
|
+
(send (const {nil? cbase} :Array) :[])
|
57
|
+
(send nil? :Array (array))
|
58
|
+
}
|
59
|
+
PATTERN
|
60
|
+
|
61
|
+
# @!method hash_with_index(node)
|
62
|
+
def_node_matcher :hash_with_index, <<~PATTERN
|
63
|
+
{
|
64
|
+
(send (const {nil? cbase} :Hash) :[])
|
65
|
+
(send nil? :Hash (array))
|
66
|
+
}
|
67
|
+
PATTERN
|
68
|
+
|
50
69
|
def on_send(node)
|
51
70
|
return unless (message = offense_message(node))
|
52
71
|
|
@@ -59,26 +78,14 @@ module RuboCop
|
|
59
78
|
|
60
79
|
def offense_message(node)
|
61
80
|
if offense_array_node?(node)
|
62
|
-
ARR_MSG
|
81
|
+
format(ARR_MSG, current: node.source)
|
63
82
|
elsif offense_hash_node?(node)
|
64
|
-
HASH_MSG
|
83
|
+
format(HASH_MSG, current: node.source)
|
65
84
|
elsif str_node(node) && !frozen_strings?
|
66
85
|
format(STR_MSG, prefer: preferred_string_literal)
|
67
86
|
end
|
68
87
|
end
|
69
88
|
|
70
|
-
def preferred_string_literal
|
71
|
-
enforce_double_quotes? ? '""' : "''"
|
72
|
-
end
|
73
|
-
|
74
|
-
def enforce_double_quotes?
|
75
|
-
string_literals_config['EnforcedStyle'] == 'double_quotes'
|
76
|
-
end
|
77
|
-
|
78
|
-
def string_literals_config
|
79
|
-
config.for_cop('Style/StringLiterals')
|
80
|
-
end
|
81
|
-
|
82
89
|
def first_argument_unparenthesized?(node)
|
83
90
|
parent = node.parent
|
84
91
|
return false unless parent && %i[send super zsuper].include?(parent.type)
|
@@ -100,12 +107,12 @@ module RuboCop
|
|
100
107
|
end
|
101
108
|
|
102
109
|
def offense_array_node?(node)
|
103
|
-
array_node(node) && !array_with_block(node.parent)
|
110
|
+
(array_node(node) && !array_with_block(node.parent)) || array_with_index(node)
|
104
111
|
end
|
105
112
|
|
106
113
|
def offense_hash_node?(node)
|
107
114
|
# If Hash.new takes a block, it can't be changed to {}.
|
108
|
-
hash_node(node) && !hash_with_block(node.parent)
|
115
|
+
(hash_node(node) && !hash_with_block(node.parent)) || hash_with_index(node)
|
109
116
|
end
|
110
117
|
|
111
118
|
def correction(node)
|
@@ -129,8 +136,10 @@ module RuboCop
|
|
129
136
|
def frozen_strings?
|
130
137
|
return true if frozen_string_literals_enabled?
|
131
138
|
|
132
|
-
frozen_string_cop_enabled = config.for_cop('Style/
|
133
|
-
frozen_string_cop_enabled &&
|
139
|
+
frozen_string_cop_enabled = config.for_cop('Style/FrozenStringLiteralComment')['Enabled']
|
140
|
+
frozen_string_cop_enabled &&
|
141
|
+
!frozen_string_literals_disabled? &&
|
142
|
+
string_literals_frozen_by_default?.nil?
|
134
143
|
end
|
135
144
|
end
|
136
145
|
end
|
@@ -11,8 +11,8 @@ module RuboCop
|
|
11
11
|
# The reason is that _unannotated_ format is very similar
|
12
12
|
# to encoded URLs or Date/Time formatting strings.
|
13
13
|
#
|
14
|
-
# This cop can be customized
|
15
|
-
# By default, there are no methods
|
14
|
+
# This cop's allowed methods can be customized with `AllowedMethods`.
|
15
|
+
# By default, there are no allowed methods.
|
16
16
|
#
|
17
17
|
# @example EnforcedStyle: annotated (default)
|
18
18
|
#
|
@@ -155,7 +155,7 @@ module RuboCop
|
|
155
155
|
condition_variable = assignable_condition_value(node)
|
156
156
|
|
157
157
|
head = heads.first
|
158
|
-
if head.assignment?
|
158
|
+
if head.respond_to?(:assignment?) && head.assignment?
|
159
159
|
# The `send` node is used instead of the `indexasgn` node, so `name` cannot be used.
|
160
160
|
# https://github.com/rubocop/rubocop-ast/blob/v1.29.0/lib/rubocop/ast/node/indexasgn_node.rb
|
161
161
|
#
|
@@ -18,6 +18,7 @@ module RuboCop
|
|
18
18
|
extend AutoCorrector
|
19
19
|
|
20
20
|
MSG_IF_ELSE = 'Do not use `if %<expr>s;` - use `if/else` instead.'
|
21
|
+
MSG_NEWLINE = 'Do not use `if %<expr>s;` - use a newline instead.'
|
21
22
|
MSG_TERNARY = 'Do not use `if %<expr>s;` - use a ternary operator instead.'
|
22
23
|
|
23
24
|
def on_normal_if_unless(node)
|
@@ -26,20 +27,47 @@ module RuboCop
|
|
26
27
|
beginning = node.loc.begin
|
27
28
|
return unless beginning&.is?(';')
|
28
29
|
|
29
|
-
message = node
|
30
|
+
message = message(node)
|
30
31
|
|
31
|
-
add_offense(node, message:
|
32
|
-
corrector
|
32
|
+
add_offense(node, message: message) do |corrector|
|
33
|
+
autocorrect(corrector, node)
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
36
37
|
private
|
37
38
|
|
38
|
-
|
39
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
40
|
+
def message(node)
|
41
|
+
template = if node.if_branch&.begin_type?
|
42
|
+
MSG_NEWLINE
|
43
|
+
elsif node.else_branch&.if_type? || node.else_branch&.begin_type? ||
|
44
|
+
use_block_in_branches?(node)
|
45
|
+
MSG_IF_ELSE
|
46
|
+
else
|
47
|
+
MSG_TERNARY
|
48
|
+
end
|
49
|
+
|
50
|
+
format(template, expr: node.condition.source)
|
51
|
+
end
|
52
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
53
|
+
|
54
|
+
def autocorrect(corrector, node)
|
55
|
+
if node.branches.compact.any?(&:begin_type?) || use_block_in_branches?(node)
|
56
|
+
corrector.replace(node.loc.begin, "\n")
|
57
|
+
else
|
58
|
+
corrector.replace(node, replacement(node))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def use_block_in_branches?(node)
|
63
|
+
node.branches.compact.any? { |branch| branch.block_type? || branch.numblock_type? }
|
64
|
+
end
|
65
|
+
|
66
|
+
def replacement(node)
|
39
67
|
return correct_elsif(node) if node.else_branch&.if_type?
|
40
68
|
|
41
|
-
then_code = node.if_branch ? node.if_branch
|
42
|
-
else_code = node.else_branch ? node.else_branch
|
69
|
+
then_code = node.if_branch ? build_expression(node.if_branch) : 'nil'
|
70
|
+
else_code = node.else_branch ? build_expression(node.else_branch) : 'nil'
|
43
71
|
|
44
72
|
"#{node.condition.source} ? #{then_code} : #{else_code}"
|
45
73
|
end
|
@@ -53,6 +81,17 @@ module RuboCop
|
|
53
81
|
RUBY
|
54
82
|
end
|
55
83
|
|
84
|
+
# rubocop:disable Metrics/AbcSize
|
85
|
+
def build_expression(expr)
|
86
|
+
return expr.source if !expr.call_type? || expr.parenthesized? || expr.arguments.empty?
|
87
|
+
|
88
|
+
method = expr.source_range.begin.join(expr.loc.selector.end)
|
89
|
+
arguments = expr.first_argument.source_range.begin.join(expr.source_range.end)
|
90
|
+
|
91
|
+
"#{method.source}(#{arguments.source})"
|
92
|
+
end
|
93
|
+
# rubocop:enable Metrics/AbcSize
|
94
|
+
|
56
95
|
def build_else_branch(second_condition)
|
57
96
|
result = <<~RUBY
|
58
97
|
elsif #{second_condition.condition.source}
|
@@ -44,11 +44,15 @@ module RuboCop
|
|
44
44
|
private
|
45
45
|
|
46
46
|
def alternative_pattern_source(pattern)
|
47
|
+
collect_alternative_patterns(pattern).join(' | ')
|
48
|
+
end
|
49
|
+
|
50
|
+
def collect_alternative_patterns(pattern)
|
47
51
|
return pattern.children.map(&:source) unless pattern.children.first.match_alt_type?
|
48
52
|
|
49
|
-
pattern_sources =
|
53
|
+
pattern_sources = collect_alternative_patterns(pattern.children.first)
|
50
54
|
|
51
|
-
|
55
|
+
pattern_sources << pattern.children[1].source
|
52
56
|
end
|
53
57
|
end
|
54
58
|
end
|
@@ -105,7 +105,7 @@ module RuboCop
|
|
105
105
|
|
106
106
|
# Value object to extract source ranges for the different parts of a magic comment
|
107
107
|
class CommentRange
|
108
|
-
extend
|
108
|
+
extend SimpleForwardable
|
109
109
|
|
110
110
|
DIRECTIVE_REGEXP = Regexp.union(MagicComment::KEYWORDS.map do |_, v|
|
111
111
|
Regexp.new(v, Regexp::IGNORECASE)
|
@@ -58,12 +58,21 @@ module RuboCop
|
|
58
58
|
[
|
59
59
|
^({begin kwbegin} ...)
|
60
60
|
({block numblock} (send !{nil? self} :each) _
|
61
|
-
(send (lvar _) {:<< :push :append}
|
61
|
+
(send (lvar _) {:<< :push :append} {send lvar begin}))
|
62
62
|
]
|
63
63
|
PATTERN
|
64
64
|
|
65
65
|
# @!method empty_array_asgn?(node)
|
66
|
-
def_node_matcher :empty_array_asgn?,
|
66
|
+
def_node_matcher :empty_array_asgn?, <<~PATTERN
|
67
|
+
(
|
68
|
+
lvasgn _ {
|
69
|
+
(array)
|
70
|
+
(send (const {nil? cbase} :Array) :[])
|
71
|
+
(send (const {nil? cbase} :Array) :new (array)?)
|
72
|
+
(send nil? :Array (array))
|
73
|
+
}
|
74
|
+
)
|
75
|
+
PATTERN
|
67
76
|
|
68
77
|
# @!method lvar_ref?(node, name)
|
69
78
|
def_node_matcher :lvar_ref?, '(lvar %1)'
|
@@ -138,10 +147,8 @@ module RuboCop
|
|
138
147
|
false
|
139
148
|
when :begin, :kwbegin
|
140
149
|
!node.right_sibling && return_value_used?(parent)
|
141
|
-
when :block, :numblock
|
142
|
-
!parent.void_context?
|
143
150
|
else
|
144
|
-
|
151
|
+
!parent.respond_to?(:void_context?) || !parent.void_context?
|
145
152
|
end
|
146
153
|
end
|
147
154
|
|
@@ -5,8 +5,8 @@ module RuboCop
|
|
5
5
|
module Style
|
6
6
|
# Checks for unwanted parentheses in parameterless method calls.
|
7
7
|
#
|
8
|
-
# This cop can be customized
|
9
|
-
# By default, there are no methods
|
8
|
+
# This cop's allowed methods can be customized with `AllowedMethods`.
|
9
|
+
# By default, there are no allowed methods.
|
10
10
|
#
|
11
11
|
# NOTE: This cop allows the use of `it()` without arguments in blocks,
|
12
12
|
# as in `0.times { it() }`, following `Lint/ItWithoutArgumentsInBlock` cop.
|
@@ -56,12 +56,10 @@ module RuboCop
|
|
56
56
|
'in a conditional, use `Array#include?` instead.'
|
57
57
|
|
58
58
|
def on_new_investigation
|
59
|
-
|
59
|
+
reset_comparison
|
60
60
|
end
|
61
61
|
|
62
62
|
def on_or(node)
|
63
|
-
reset_comparison if switch_comparison?(node)
|
64
|
-
|
65
63
|
root_of_or_node = root_of_or_node(node)
|
66
64
|
|
67
65
|
return unless node == root_of_or_node
|
@@ -74,9 +72,9 @@ module RuboCop
|
|
74
72
|
prefer_method = "[#{elements}].include?(#{variables_in_node(node).first})"
|
75
73
|
|
76
74
|
corrector.replace(node, prefer_method)
|
77
|
-
end
|
78
75
|
|
79
|
-
|
76
|
+
reset_comparison
|
77
|
+
end
|
80
78
|
end
|
81
79
|
|
82
80
|
private
|
@@ -147,12 +145,6 @@ module RuboCop
|
|
147
145
|
end
|
148
146
|
end
|
149
147
|
|
150
|
-
def switch_comparison?(node)
|
151
|
-
return true if @last_comparison.nil?
|
152
|
-
|
153
|
-
@last_comparison.descendants.none?(node)
|
154
|
-
end
|
155
|
-
|
156
148
|
def reset_comparison
|
157
149
|
@compared_elements = []
|
158
150
|
@allowed_method_comparison = false
|
@@ -8,8 +8,8 @@ module RuboCop
|
|
8
8
|
# These can be replaced by their respective predicate methods.
|
9
9
|
# This cop can also be configured to do the reverse.
|
10
10
|
#
|
11
|
-
# This cop can be customized
|
12
|
-
# By default, there are no methods
|
11
|
+
# This cop's allowed methods can be customized with `AllowedMethods`.
|
12
|
+
# By default, there are no allowed methods.
|
13
13
|
#
|
14
14
|
# This cop disregards `#nonzero?` as its value is truthy or falsey,
|
15
15
|
# but not `true` and `false`, and thus not always interchangeable with
|
@@ -42,7 +42,7 @@ module RuboCop
|
|
42
42
|
def on_normal_if_unless(node)
|
43
43
|
return unless node.single_line?
|
44
44
|
return unless node.else_branch
|
45
|
-
return if node.elsif?
|
45
|
+
return if node.elsif? || node.if_branch&.begin_type?
|
46
46
|
|
47
47
|
message = message(node)
|
48
48
|
add_offense(node, message: message) do |corrector|
|
@@ -211,15 +211,16 @@ module RuboCop
|
|
211
211
|
protected
|
212
212
|
|
213
213
|
def assignment
|
214
|
-
@new_elements.map { |lhs, rhs| "#{lhs.source} = #{source(rhs)}" }
|
214
|
+
@new_elements.map { |lhs, rhs| "#{lhs.source} = #{source(rhs, rhs.loc)}" }
|
215
215
|
end
|
216
216
|
|
217
217
|
private
|
218
218
|
|
219
|
-
def source(node)
|
220
|
-
|
219
|
+
def source(node, loc)
|
220
|
+
# __FILE__ is treated as a StrNode but has no begin
|
221
|
+
if node.str_type? && loc.respond_to?(:begin) && loc.begin.nil?
|
221
222
|
"'#{node.source}'"
|
222
|
-
elsif node.sym_type? &&
|
223
|
+
elsif node.sym_type? && loc.begin.nil?
|
223
224
|
":#{node.source}"
|
224
225
|
else
|
225
226
|
node.source
|
@@ -98,8 +98,6 @@ module RuboCop
|
|
98
98
|
|
99
99
|
def style
|
100
100
|
return super unless super == :same_as_string_literals
|
101
|
-
|
102
|
-
string_literals_config = config.for_cop('Style/StringLiterals')
|
103
101
|
return :single_quotes unless string_literals_config['Enabled']
|
104
102
|
|
105
103
|
string_literals_config['EnforcedStyle'].to_sym
|
@@ -39,9 +39,9 @@ module RuboCop
|
|
39
39
|
splat block_pass forwarded_restarg forwarded_kwrestarg forwarded_args
|
40
40
|
].freeze
|
41
41
|
|
42
|
+
# rubocop:disable Metrics/AbcSize
|
42
43
|
def on_if(node)
|
43
|
-
return if node.elsif_conditional?
|
44
|
-
return unless offense?(node)
|
44
|
+
return if node.modifier_form? || node.elsif_conditional? || !offense?(node)
|
45
45
|
|
46
46
|
message = message(node)
|
47
47
|
|
@@ -57,6 +57,7 @@ module RuboCop
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
end
|
60
|
+
# rubocop:enable Metrics/AbcSize
|
60
61
|
|
61
62
|
private
|
62
63
|
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Before Ruby 3.0, interpolated strings followed the frozen string literal
|
7
|
+
# magic comment which sometimes made it necessary to explicitly unfreeze them.
|
8
|
+
# Ruby 3.0 changed interpolated strings to always be unfrozen which makes
|
9
|
+
# unfreezing them redundant.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# # bad
|
13
|
+
# +"#{foo} bar"
|
14
|
+
#
|
15
|
+
# # bad
|
16
|
+
# "#{foo} bar".dup
|
17
|
+
#
|
18
|
+
# # good
|
19
|
+
# "#{foo} bar"
|
20
|
+
#
|
21
|
+
class RedundantInterpolationUnfreeze < Base
|
22
|
+
include FrozenStringLiteral
|
23
|
+
extend AutoCorrector
|
24
|
+
extend TargetRubyVersion
|
25
|
+
|
26
|
+
MSG = "Don't unfreeze interpolated strings as they are already unfrozen."
|
27
|
+
|
28
|
+
RESTRICT_ON_SEND = %i[+@ dup].freeze
|
29
|
+
|
30
|
+
minimum_target_ruby_version 3.0
|
31
|
+
|
32
|
+
def on_send(node)
|
33
|
+
return if node.arguments?
|
34
|
+
return unless (receiver = node.receiver)
|
35
|
+
return unless receiver.dstr_type?
|
36
|
+
return if uninterpolated_string?(receiver) || uninterpolated_heredoc?(receiver)
|
37
|
+
|
38
|
+
add_offense(node.loc.selector) do |corrector|
|
39
|
+
corrector.remove(node.loc.selector)
|
40
|
+
corrector.remove(node.loc.dot) unless node.unary_operation?
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -33,6 +33,7 @@ module RuboCop
|
|
33
33
|
# 'foo'.sub('f', 'x')
|
34
34
|
# 'foo'.sub!('f', 'x')
|
35
35
|
class RedundantRegexpArgument < Base
|
36
|
+
include StringLiteralsHelp
|
36
37
|
extend AutoCorrector
|
37
38
|
|
38
39
|
MSG = 'Use string `%<prefer>s` as argument instead of regexp `%<current>s`.'
|
@@ -71,8 +72,10 @@ module RuboCop
|
|
71
72
|
if new_argument.include?('"')
|
72
73
|
new_argument.gsub!("'", "\\\\'")
|
73
74
|
quote = "'"
|
74
|
-
|
75
|
+
elsif new_argument.include?('\\')
|
75
76
|
quote = '"'
|
77
|
+
else
|
78
|
+
quote = enforce_double_quotes? ? '"' : "'"
|
76
79
|
end
|
77
80
|
|
78
81
|
"#{quote}#{new_argument}#{quote}"
|
@@ -17,9 +17,9 @@ module RuboCop
|
|
17
17
|
# `foo&.bar` can start returning `nil` as well as what the method
|
18
18
|
# returns.
|
19
19
|
#
|
20
|
-
# The default for `MaxChainLength` is `2
|
20
|
+
# The default for `MaxChainLength` is `2`.
|
21
21
|
# We have limited the cop to not register an offense for method chains
|
22
|
-
# that exceed this option
|
22
|
+
# that exceed this option's value.
|
23
23
|
#
|
24
24
|
# @safety
|
25
25
|
# Autocorrection is unsafe because if a value is `false`, the resulting
|
data/lib/rubocop/cop/team.rb
CHANGED
@@ -120,8 +120,12 @@ module RuboCop
|
|
120
120
|
end
|
121
121
|
|
122
122
|
def external_dependency_checksum
|
123
|
-
|
124
|
-
|
123
|
+
# The external dependency checksums are cached per RuboCop team so that
|
124
|
+
# the checksums don't need to be recomputed for each file.
|
125
|
+
@external_dependency_checksum ||= begin
|
126
|
+
keys = cops.filter_map(&:external_dependency_checksum)
|
127
|
+
Digest::SHA1.hexdigest(keys.join)
|
128
|
+
end
|
125
129
|
end
|
126
130
|
|
127
131
|
private
|