rubocop 1.65.0 → 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/cop.rb +2 -2
- 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/assignment_indentation.rb +3 -2
- data/lib/rubocop/cop/layout/block_alignment.rb +30 -12
- data/lib/rubocop/cop/layout/condition_position.rb +0 -4
- 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/ambiguous_block_association.rb +0 -2
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +0 -2
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +0 -2
- data/lib/rubocop/cop/lint/boolean_symbol.rb +0 -2
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +0 -13
- data/lib/rubocop/cop/lint/debugger.rb +0 -4
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +0 -10
- data/lib/rubocop/cop/lint/duplicate_case_condition.rb +0 -4
- data/lib/rubocop/cop/lint/duplicate_hash_key.rb +0 -4
- data/lib/rubocop/cop/lint/duplicate_methods.rb +0 -10
- data/lib/rubocop/cop/lint/each_with_object_argument.rb +0 -4
- data/lib/rubocop/cop/lint/else_layout.rb +0 -2
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +27 -6
- data/lib/rubocop/cop/lint/empty_ensure.rb +1 -11
- data/lib/rubocop/cop/lint/empty_interpolation.rb +0 -4
- data/lib/rubocop/cop/lint/empty_when.rb +0 -2
- data/lib/rubocop/cop/lint/ensure_return.rb +1 -6
- data/lib/rubocop/cop/lint/float_out_of_range.rb +0 -4
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +0 -10
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +5 -7
- data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +0 -7
- data/lib/rubocop/cop/lint/interpolation_check.rb +0 -4
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +0 -4
- data/lib/rubocop/cop/lint/loop.rb +6 -12
- data/lib/rubocop/cop/lint/nested_method_definition.rb +0 -6
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +0 -4
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +0 -5
- data/lib/rubocop/cop/lint/percent_string_array.rb +0 -4
- data/lib/rubocop/cop/lint/percent_symbol_array.rb +0 -4
- data/lib/rubocop/cop/lint/rand_one.rb +0 -4
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +3 -1
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +0 -4
- data/lib/rubocop/cop/lint/require_parentheses.rb +0 -4
- data/lib/rubocop/cop/lint/rescue_exception.rb +0 -4
- data/lib/rubocop/cop/lint/return_in_void_context.rb +0 -2
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +0 -4
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +6 -10
- data/lib/rubocop/cop/lint/unified_integer.rb +0 -4
- data/lib/rubocop/cop/lint/unreachable_code.rb +0 -5
- data/lib/rubocop/cop/lint/useless_assignment.rb +19 -16
- data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +0 -4
- data/lib/rubocop/cop/lint/useless_numeric_operation.rb +77 -0
- data/lib/rubocop/cop/lint/useless_setter_call.rb +0 -4
- 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 +52 -26
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +10 -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/def_with_parentheses.rb +0 -2
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +0 -1
- 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/eval_with_location.rb +12 -11
- data/lib/rubocop/cop/style/file_read.rb +2 -5
- data/lib/rubocop/cop/style/file_write.rb +2 -5
- data/lib/rubocop/cop/style/format_string_token.rb +2 -2
- data/lib/rubocop/cop/style/global_std_stream.rb +7 -1
- 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_boolean_literal_branches.rb +0 -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/invertible_unless_condition.rb +2 -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_with_args_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -2
- data/lib/rubocop/cop/style/missing_else.rb +0 -4
- data/lib/rubocop/cop/style/multiline_when_then.rb +0 -4
- 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 -3
- 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/redundant_regexp_escape.rb +8 -24
- data/lib/rubocop/cop/style/safe_navigation.rb +2 -2
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +21 -2
- data/lib/rubocop/cop/style/while_until_do.rb +0 -2
- data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
- data/lib/rubocop/cop/style/zero_length_predicate.rb +5 -1
- data/lib/rubocop/cop/team.rb +6 -2
- data/lib/rubocop/cop/variable_force.rb +13 -1
- data/lib/rubocop/core_ext/string.rb +2 -6
- data/lib/rubocop/ext/regexp_node.rb +9 -31
- data/lib/rubocop/formatter/junit_formatter.rb +70 -23
- data/lib/rubocop/lockfile.rb +6 -4
- data/lib/rubocop/options.rb +3 -1
- 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 +7 -1
- metadata +8 -26
@@ -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
|
|
@@ -4,7 +4,7 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
6
|
# Enforces the presence (default) or absence of parentheses in
|
7
|
-
# method calls containing
|
7
|
+
# method calls containing arguments.
|
8
8
|
#
|
9
9
|
# In the default style (require_parentheses), macro methods are allowed.
|
10
10
|
# Additional methods can be added to the `AllowedMethods` or
|
@@ -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
|
@@ -12,7 +12,6 @@ module RuboCop
|
|
12
12
|
# # good
|
13
13
|
# a = b || c
|
14
14
|
#
|
15
|
-
# @example
|
16
15
|
# # bad
|
17
16
|
# if b
|
18
17
|
# b
|
@@ -40,9 +39,9 @@ module RuboCop
|
|
40
39
|
splat block_pass forwarded_restarg forwarded_kwrestarg forwarded_args
|
41
40
|
].freeze
|
42
41
|
|
42
|
+
# rubocop:disable Metrics/AbcSize
|
43
43
|
def on_if(node)
|
44
|
-
return if node.elsif_conditional?
|
45
|
-
return unless offense?(node)
|
44
|
+
return if node.modifier_form? || node.elsif_conditional? || !offense?(node)
|
46
45
|
|
47
46
|
message = message(node)
|
48
47
|
|
@@ -58,6 +57,7 @@ module RuboCop
|
|
58
57
|
end
|
59
58
|
end
|
60
59
|
end
|
60
|
+
# rubocop:enable Metrics/AbcSize
|
61
61
|
|
62
62
|
private
|
63
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}"
|
@@ -95,30 +95,14 @@ module RuboCop
|
|
95
95
|
delimiters.include?(char)
|
96
96
|
end
|
97
97
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
char_class_depth
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
# Please remove this `else` branch when support for regexp_parser 1.8 will be dropped.
|
111
|
-
# It's for compatibility with regexp_parser 1.8 and will never be maintained.
|
112
|
-
else
|
113
|
-
def each_escape(node)
|
114
|
-
node.parsed_tree&.traverse&.reduce(0) do |char_class_depth, (event, expr)|
|
115
|
-
yield(expr.text[1], expr.start_index, !char_class_depth.zero?) if expr.type == :escape
|
116
|
-
|
117
|
-
if expr.type == :set
|
118
|
-
char_class_depth + (event == :enter ? 1 : -1)
|
119
|
-
else
|
120
|
-
char_class_depth
|
121
|
-
end
|
98
|
+
def each_escape(node)
|
99
|
+
node.parsed_tree&.traverse&.reduce(0) do |char_class_depth, (event, expr)|
|
100
|
+
yield(expr.text[1], expr.ts, !char_class_depth.zero?) if expr.type == :escape
|
101
|
+
|
102
|
+
if expr.type == :set
|
103
|
+
char_class_depth + (event == :enter ? 1 : -1)
|
104
|
+
else
|
105
|
+
char_class_depth
|
122
106
|
end
|
123
107
|
end
|
124
108
|
end
|
@@ -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
|
@@ -159,7 +159,13 @@ module RuboCop
|
|
159
159
|
node_to_check = condition&.block_type? ? condition.send_node : condition
|
160
160
|
return unless wrap_condition?(node_to_check)
|
161
161
|
|
162
|
-
|
162
|
+
if condition.call_type?
|
163
|
+
source = parenthesized_method_arguments(condition)
|
164
|
+
|
165
|
+
corrector.replace(condition, source)
|
166
|
+
else
|
167
|
+
corrector.wrap(condition, '(', ')')
|
168
|
+
end
|
163
169
|
end
|
164
170
|
|
165
171
|
def correct_for_outer_condition_modify_form_style(corrector, node, if_branch)
|
@@ -236,7 +242,20 @@ module RuboCop
|
|
236
242
|
end
|
237
243
|
|
238
244
|
def replace_condition(condition)
|
239
|
-
|
245
|
+
return condition.source unless wrap_condition?(condition)
|
246
|
+
|
247
|
+
if condition.call_type?
|
248
|
+
parenthesized_method_arguments(condition)
|
249
|
+
else
|
250
|
+
"(#{condition.source})"
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
def parenthesized_method_arguments(node)
|
255
|
+
method_call = node.source_range.begin.join(node.loc.selector.end).source
|
256
|
+
arguments = node.first_argument.source_range.begin.join(node.source_range.end).source
|
257
|
+
|
258
|
+
"#{method_call}(#{arguments})"
|
240
259
|
end
|
241
260
|
|
242
261
|
def allow_modifier?
|
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
|
@@ -27,7 +27,10 @@ module RuboCop
|
|
27
27
|
class VariableForce < Force # rubocop:disable Metrics/ClassLength
|
28
28
|
VARIABLE_ASSIGNMENT_TYPE = :lvasgn
|
29
29
|
REGEXP_NAMED_CAPTURE_TYPE = :match_with_lvasgn
|
30
|
-
|
30
|
+
PATTERN_MATCH_VARIABLE_TYPE = :match_var
|
31
|
+
VARIABLE_ASSIGNMENT_TYPES = [
|
32
|
+
VARIABLE_ASSIGNMENT_TYPE, REGEXP_NAMED_CAPTURE_TYPE, PATTERN_MATCH_VARIABLE_TYPE
|
33
|
+
].freeze
|
31
34
|
|
32
35
|
ARGUMENT_DECLARATION_TYPES = [
|
33
36
|
:arg, :optarg, :restarg,
|
@@ -112,6 +115,7 @@ module RuboCop
|
|
112
115
|
NODE_HANDLER_METHOD_NAMES = [
|
113
116
|
[VARIABLE_ASSIGNMENT_TYPE, :process_variable_assignment],
|
114
117
|
[REGEXP_NAMED_CAPTURE_TYPE, :process_regexp_named_captures],
|
118
|
+
[PATTERN_MATCH_VARIABLE_TYPE, :process_pattern_match_variable],
|
115
119
|
[MULTIPLE_ASSIGNMENT_TYPE, :process_variable_multiple_assignment],
|
116
120
|
[VARIABLE_REFERENCE_TYPE, :process_variable_referencing],
|
117
121
|
[RESCUE_TYPE, :process_rescue],
|
@@ -175,6 +179,14 @@ module RuboCop
|
|
175
179
|
skip_children!
|
176
180
|
end
|
177
181
|
|
182
|
+
def process_pattern_match_variable(node)
|
183
|
+
name = node.children.first
|
184
|
+
|
185
|
+
variable_table.declare_variable(name, node) unless variable_table.variable_exist?(name)
|
186
|
+
|
187
|
+
skip_children!
|
188
|
+
end
|
189
|
+
|
178
190
|
def regexp_captured_names(node)
|
179
191
|
regexp = node.to_regexp
|
180
192
|
|
@@ -9,12 +9,8 @@ class String
|
|
9
9
|
# @return [Boolean] true is the string is blank, false otherwise
|
10
10
|
#
|
11
11
|
# @example
|
12
|
-
# ''.blank?
|
13
|
-
#
|
14
|
-
# @example
|
15
|
-
# ' '.blank? #=> true
|
16
|
-
#
|
17
|
-
# @example
|
12
|
+
# ''.blank? #=> true
|
13
|
+
# ' '.blank? #=> true
|
18
14
|
# ' test'.blank? #=> false
|
19
15
|
def blank?
|
20
16
|
empty? || lstrip.empty?
|
@@ -15,39 +15,17 @@ module RuboCop
|
|
15
15
|
# see `ext/regexp_parser`.
|
16
16
|
attr_reader :parsed_tree
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
super
|
18
|
+
def assign_properties(*)
|
19
|
+
super
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
28
|
-
origin = loc.begin.end
|
29
|
-
@parsed_tree&.each_expression(true) { |e| e.origin = origin }
|
30
|
-
end
|
31
|
-
# Please remove this `else` branch when support for regexp_parser 1.8 will be dropped.
|
32
|
-
# It's for compatibility with regexp_parser 1.8 and will never be maintained.
|
33
|
-
else
|
34
|
-
def assign_properties(*)
|
35
|
-
super
|
36
|
-
|
37
|
-
str = with_interpolations_blanked
|
38
|
-
begin
|
39
|
-
@parsed_tree = Regexp::Parser.parse(str, options: options)
|
40
|
-
rescue StandardError
|
41
|
-
@parsed_tree = nil
|
42
|
-
else
|
43
|
-
origin = loc.begin.end
|
44
|
-
source = @parsed_tree.to_s
|
45
|
-
@parsed_tree.each_expression(true) do |e|
|
46
|
-
e.origin = origin
|
47
|
-
e.source = source
|
48
|
-
end
|
49
|
-
end
|
21
|
+
str = with_interpolations_blanked
|
22
|
+
@parsed_tree = begin
|
23
|
+
Regexp::Parser.parse(str, options: options)
|
24
|
+
rescue StandardError
|
25
|
+
nil
|
50
26
|
end
|
27
|
+
origin = loc.begin.end
|
28
|
+
@parsed_tree&.each_expression(true) { |e| e.origin = origin }
|
51
29
|
end
|
52
30
|
|
53
31
|
def each_capture(named: ANY)
|