rubocop 1.65.0 → 1.66.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 +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)
|