rubocop 0.91.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +8 -5
- data/config/default.yml +143 -56
- data/lib/rubocop.rb +17 -5
- data/lib/rubocop/cached_data.rb +2 -1
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
- data/lib/rubocop/cli/command/version.rb +1 -1
- data/lib/rubocop/comment_config.rb +1 -1
- data/lib/rubocop/config.rb +4 -0
- data/lib/rubocop/config_loader.rb +19 -2
- data/lib/rubocop/config_loader_resolver.rb +7 -5
- data/lib/rubocop/config_regeneration.rb +33 -0
- data/lib/rubocop/config_validator.rb +7 -6
- data/lib/rubocop/cop/badge.rb +9 -24
- data/lib/rubocop/cop/base.rb +16 -1
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +23 -3
- data/lib/rubocop/cop/commissioner.rb +36 -22
- data/lib/rubocop/cop/corrector.rb +3 -1
- data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -2
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +1 -1
- data/lib/rubocop/cop/force.rb +1 -1
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +10 -10
- data/lib/rubocop/cop/layout/array_alignment.rb +1 -0
- data/lib/rubocop/cop/layout/class_structure.rb +7 -0
- data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/dot_position.rb +6 -9
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +7 -7
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -1
- data/lib/rubocop/cop/layout/extra_spacing.rb +1 -2
- data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +2 -11
- data/lib/rubocop/cop/layout/space_around_operators.rb +4 -1
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +0 -4
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +37 -13
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +2 -0
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +18 -1
- data/lib/rubocop/cop/lint/boolean_symbol.rb +3 -0
- data/lib/rubocop/cop/lint/debugger.rb +2 -3
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +77 -0
- data/lib/rubocop/cop/lint/empty_block.rb +46 -0
- data/lib/rubocop/cop/lint/flip_flop.rb +8 -2
- data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +37 -0
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +17 -3
- data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
- data/lib/rubocop/cop/lint/number_conversion.rb +46 -13
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +27 -8
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +78 -0
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +95 -0
- data/lib/rubocop/cop/lint/to_json.rb +1 -1
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +185 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
- data/lib/rubocop/cop/metrics/block_length.rb +3 -1
- data/lib/rubocop/cop/metrics/class_length.rb +14 -6
- data/lib/rubocop/cop/metrics/parameter_lists.rb +4 -1
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -1
- data/lib/rubocop/cop/mixin/line_length_help.rb +1 -1
- data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/predicate_name.rb +2 -1
- data/lib/rubocop/cop/offense.rb +18 -5
- data/lib/rubocop/cop/security/open.rb +12 -10
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +6 -2
- data/lib/rubocop/cop/style/accessor_grouping.rb +3 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +142 -0
- data/lib/rubocop/cop/style/array_coercion.rb +4 -0
- data/lib/rubocop/cop/style/case_like_if.rb +20 -4
- data/lib/rubocop/cop/style/class_equality_comparison.rb +64 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +8 -1
- data/lib/rubocop/cop/style/comment_annotation.rb +6 -0
- data/lib/rubocop/cop/style/date_time.rb +12 -1
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +67 -0
- data/lib/rubocop/cop/style/explicit_block_argument.rb +6 -2
- data/lib/rubocop/cop/style/for.rb +0 -4
- data/lib/rubocop/cop/style/format_string_token.rb +48 -3
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +10 -13
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +6 -11
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +7 -11
- data/lib/rubocop/cop/style/method_def_parentheses.rb +0 -4
- data/lib/rubocop/cop/style/mixin_usage.rb +7 -27
- data/lib/rubocop/cop/style/multiple_comparison.rb +54 -7
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +2 -0
- data/lib/rubocop/cop/style/optional_boolean_parameter.rb +11 -3
- data/lib/rubocop/cop/style/raise_args.rb +0 -3
- data/lib/rubocop/cop/style/redundant_begin.rb +36 -8
- data/lib/rubocop/cop/style/redundant_condition.rb +5 -1
- data/lib/rubocop/cop/style/redundant_interpolation.rb +6 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +4 -0
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +45 -24
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -15
- data/lib/rubocop/cop/style/redundant_self.rb +3 -0
- data/lib/rubocop/cop/style/safe_navigation.rb +16 -4
- data/lib/rubocop/cop/style/semicolon.rb +3 -0
- data/lib/rubocop/cop/style/string_concatenation.rb +14 -2
- data/lib/rubocop/cop/style/swap_values.rb +108 -0
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +3 -1
- data/lib/rubocop/cop/team.rb +6 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/variable_force/branch.rb +0 -4
- data/lib/rubocop/ext/regexp_node.rb +29 -10
- data/lib/rubocop/ext/regexp_parser.rb +77 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +12 -5
- data/lib/rubocop/formatter/formatter_set.rb +1 -1
- data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
- data/lib/rubocop/magic_comment.rb +2 -2
- data/lib/rubocop/options.rb +22 -17
- data/lib/rubocop/result_cache.rb +8 -2
- data/lib/rubocop/rspec/cop_helper.rb +1 -1
- data/lib/rubocop/rspec/expect_offense.rb +5 -5
- data/lib/rubocop/rspec/shared_contexts.rb +4 -0
- data/lib/rubocop/runner.rb +9 -5
- data/lib/rubocop/target_finder.rb +27 -26
- data/lib/rubocop/target_ruby.rb +1 -1
- data/lib/rubocop/version.rb +61 -6
- metadata +21 -16
- data/lib/rubocop/cop/mixin/regexp_literal_help.rb +0 -43
@@ -75,7 +75,7 @@ module RuboCop
|
|
75
75
|
def offense?(node)
|
76
76
|
condition, if_branch, else_branch = *node
|
77
77
|
|
78
|
-
return false if use_if_branch?(else_branch)
|
78
|
+
return false if use_if_branch?(else_branch) || use_hash_key_assignment?(else_branch)
|
79
79
|
|
80
80
|
condition == if_branch && !node.elsif? && (
|
81
81
|
node.ternary? ||
|
@@ -88,6 +88,10 @@ module RuboCop
|
|
88
88
|
else_branch&.if_type?
|
89
89
|
end
|
90
90
|
|
91
|
+
def use_hash_key_assignment?(else_branch)
|
92
|
+
else_branch&.send_type? && else_branch&.method?(:[]=)
|
93
|
+
end
|
94
|
+
|
91
95
|
def else_source(else_branch)
|
92
96
|
if require_parentheses?(else_branch)
|
93
97
|
"(#{else_branch.source})"
|
@@ -51,7 +51,12 @@ module RuboCop
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def single_variable_interpolation?(node)
|
54
|
-
node.children.one?
|
54
|
+
return false unless node.children.one?
|
55
|
+
|
56
|
+
first_child = node.children.first
|
57
|
+
|
58
|
+
variable_interpolation?(first_child) ||
|
59
|
+
first_child.send_type? && !first_child.operator_method?
|
55
60
|
end
|
56
61
|
|
57
62
|
def interpolation?(node)
|
@@ -104,9 +104,13 @@ module RuboCop
|
|
104
104
|
return offense(begin_node, 'a variable') if node.variable?
|
105
105
|
return offense(begin_node, 'a constant') if node.const_type?
|
106
106
|
|
107
|
+
return offense(begin_node, 'an interpolated expression') if interpolation?(begin_node)
|
108
|
+
|
107
109
|
check_send(begin_node, node) if node.call_type?
|
108
110
|
end
|
109
111
|
|
112
|
+
def_node_matcher :interpolation?, '[^begin ^^dstr]'
|
113
|
+
|
110
114
|
def check_send(begin_node, node)
|
111
115
|
return check_unary(begin_node, node) if node.unary_operation?
|
112
116
|
|
@@ -19,35 +19,23 @@ module RuboCop
|
|
19
19
|
# # good
|
20
20
|
# r = /\s/
|
21
21
|
#
|
22
|
+
# # bad
|
23
|
+
# r = %r{/[b]}
|
24
|
+
#
|
25
|
+
# # good
|
26
|
+
# r = %r{/b}
|
27
|
+
#
|
22
28
|
# # good
|
23
29
|
# r = /[ab]/
|
24
30
|
class RedundantRegexpCharacterClass < Base
|
25
|
-
include MatchRange
|
26
|
-
include RegexpLiteralHelp
|
27
31
|
extend AutoCorrector
|
28
32
|
|
33
|
+
REQUIRES_ESCAPE_OUTSIDE_CHAR_CLASS_CHARS = '.*+?{}()|$'.chars.freeze
|
29
34
|
MSG_REDUNDANT_CHARACTER_CLASS = 'Redundant single-element character class, ' \
|
30
35
|
'`%<char_class>s` can be replaced with `%<element>s`.'
|
31
36
|
|
32
|
-
PATTERN = /
|
33
|
-
(
|
34
|
-
(?<!\\) # No \-prefix (i.e. not escaped)
|
35
|
-
\[ # Literal [
|
36
|
-
(?!\#\{) # Not (the start of) an interpolation
|
37
|
-
(?: # Either...
|
38
|
-
\\[^b] | # Any escaped character except b (which would change behaviour)
|
39
|
-
[^.*+?{}()|$] | # or one that doesn't require escaping outside the character class
|
40
|
-
\\[upP]\{[^}]+\} # or a unicode code-point or property
|
41
|
-
)
|
42
|
-
(?<!\\) # No \-prefix (i.e. not escaped)
|
43
|
-
\] # Literal ]
|
44
|
-
)
|
45
|
-
/x.freeze
|
46
|
-
|
47
37
|
def on_regexp(node)
|
48
38
|
each_redundant_character_class(node) do |loc|
|
49
|
-
next if whitespace_in_free_space_mode?(node, loc)
|
50
|
-
|
51
39
|
add_offense(
|
52
40
|
loc, message: format(
|
53
41
|
MSG_REDUNDANT_CHARACTER_CLASS,
|
@@ -63,19 +51,52 @@ module RuboCop
|
|
63
51
|
private
|
64
52
|
|
65
53
|
def each_redundant_character_class(node)
|
66
|
-
|
67
|
-
|
54
|
+
each_single_element_character_class(node) do |char_class|
|
55
|
+
next unless redundant_single_element_character_class?(node, char_class)
|
56
|
+
|
57
|
+
yield char_class.loc.body
|
68
58
|
end
|
69
59
|
end
|
70
60
|
|
61
|
+
def each_single_element_character_class(node)
|
62
|
+
node.parsed_tree&.each_expression do |expr|
|
63
|
+
next if expr.type != :set || expr.expressions.size != 1
|
64
|
+
next if expr.negative?
|
65
|
+
next if %i[set posixclass nonposixclass].include?(expr.expressions.first.type)
|
66
|
+
|
67
|
+
yield expr
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def redundant_single_element_character_class?(node, char_class)
|
72
|
+
class_elem = char_class.expressions.first.text
|
73
|
+
|
74
|
+
non_redundant =
|
75
|
+
whitespace_in_free_space_mode?(node, class_elem) ||
|
76
|
+
backslash_b?(class_elem) ||
|
77
|
+
requires_escape_outside_char_class?(class_elem)
|
78
|
+
|
79
|
+
!non_redundant
|
80
|
+
end
|
81
|
+
|
71
82
|
def without_character_class(loc)
|
72
83
|
loc.source[1..-2]
|
73
84
|
end
|
74
85
|
|
75
|
-
def whitespace_in_free_space_mode?(node,
|
76
|
-
return false unless
|
86
|
+
def whitespace_in_free_space_mode?(node, elem)
|
87
|
+
return false unless node.extended?
|
88
|
+
|
89
|
+
/\s/.match?(elem)
|
90
|
+
end
|
91
|
+
|
92
|
+
def backslash_b?(elem)
|
93
|
+
# \b's behaviour is different inside and outside of a character class, matching word
|
94
|
+
# boundaries outside but backspace (0x08) when inside.
|
95
|
+
elem == '\b'
|
96
|
+
end
|
77
97
|
|
78
|
-
|
98
|
+
def requires_escape_outside_char_class?(elem)
|
99
|
+
REQUIRES_ESCAPE_OUTSIDE_CHAR_CLASS_CHARS.include?(elem)
|
79
100
|
end
|
80
101
|
end
|
81
102
|
end
|
@@ -34,7 +34,6 @@ module RuboCop
|
|
34
34
|
# /[+\-]\d/
|
35
35
|
class RedundantRegexpEscape < Base
|
36
36
|
include RangeHelp
|
37
|
-
include RegexpLiteralHelp
|
38
37
|
extend AutoCorrector
|
39
38
|
|
40
39
|
MSG_REDUNDANT_ESCAPE = 'Redundant escape inside regexp literal'
|
@@ -59,9 +58,9 @@ module RuboCop
|
|
59
58
|
|
60
59
|
def allowed_escape?(node, char, within_character_class)
|
61
60
|
# Strictly speaking a few single-letter metachars are currently
|
62
|
-
# unnecessary to "escape", e.g.
|
61
|
+
# unnecessary to "escape", e.g. i, E, F, but enumerating them is
|
63
62
|
# rather difficult, and their behaviour could change over time with
|
64
|
-
# different versions of Ruby so that e.g. /\
|
63
|
+
# different versions of Ruby so that e.g. /\i/ != /i/
|
65
64
|
return true if /[[:alnum:]]/.match?(char)
|
66
65
|
return true if ALLOWED_ALWAYS_ESCAPES.include?(char) || delimiter?(node, char)
|
67
66
|
|
@@ -82,19 +81,13 @@ module RuboCop
|
|
82
81
|
end
|
83
82
|
|
84
83
|
def each_escape(node)
|
85
|
-
|
86
|
-
[
|
87
|
-
|
88
|
-
if
|
89
|
-
|
90
|
-
|
91
|
-
[nil, char_class_depth]
|
92
|
-
elsif previous == '['
|
93
|
-
[current, char_class_depth + 1]
|
94
|
-
elsif current == ']'
|
95
|
-
[current, char_class_depth - 1]
|
84
|
+
node.parsed_tree&.traverse&.reduce(0) do |char_class_depth, (event, expr)|
|
85
|
+
yield(expr.text[1], expr.ts, !char_class_depth.zero?) if expr.type == :escape
|
86
|
+
|
87
|
+
if expr.type == :set
|
88
|
+
char_class_depth + (event == :enter ? 1 : -1)
|
96
89
|
else
|
97
|
-
|
90
|
+
char_class_depth
|
98
91
|
end
|
99
92
|
end
|
100
93
|
end
|
@@ -129,6 +129,9 @@ module RuboCop
|
|
129
129
|
def allowed_send_node?(node)
|
130
130
|
@allowed_send_nodes.include?(node) ||
|
131
131
|
@local_variables_scopes[node].include?(node.method_name) ||
|
132
|
+
node.each_ancestor.any? do |ancestor|
|
133
|
+
@local_variables_scopes[ancestor].include?(node.method_name)
|
134
|
+
end ||
|
132
135
|
KERNEL_METHODS.include?(node.method_name)
|
133
136
|
end
|
134
137
|
|
@@ -142,10 +142,22 @@ module RuboCop
|
|
142
142
|
end
|
143
143
|
|
144
144
|
def comments(node)
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
145
|
+
relevant_comment_ranges(node).each.with_object([]) do |range, comments|
|
146
|
+
comments.concat(processed_source.each_comment_in_lines(range).to_a)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def relevant_comment_ranges(node)
|
151
|
+
# Get source lines ranges inside the if node that aren't inside an inner node
|
152
|
+
# Comments inside an inner node should remain attached to that node, and not
|
153
|
+
# moved.
|
154
|
+
begin_pos = node.loc.first_line
|
155
|
+
end_pos = node.loc.last_line
|
156
|
+
|
157
|
+
node.child_nodes.each.with_object([]) do |child, ranges|
|
158
|
+
ranges << (begin_pos...child.loc.first_line)
|
159
|
+
begin_pos = child.loc.last_line
|
160
|
+
end << (begin_pos...end_pos)
|
149
161
|
end
|
150
162
|
|
151
163
|
def allowed_if_condition?(node)
|
@@ -33,6 +33,10 @@ module RuboCop
|
|
33
33
|
}
|
34
34
|
PATTERN
|
35
35
|
|
36
|
+
def on_new_investigation
|
37
|
+
@corrected_nodes = nil
|
38
|
+
end
|
39
|
+
|
36
40
|
def on_send(node)
|
37
41
|
return unless string_concatenation?(node)
|
38
42
|
|
@@ -42,8 +46,12 @@ module RuboCop
|
|
42
46
|
collect_parts(topmost_plus_node, parts)
|
43
47
|
|
44
48
|
add_offense(topmost_plus_node) do |corrector|
|
45
|
-
|
49
|
+
correctable_parts = parts.none? { |part| uncorrectable?(part) }
|
50
|
+
if correctable_parts && !corrected_ancestor?(topmost_plus_node)
|
46
51
|
corrector.replace(topmost_plus_node, replacement(parts))
|
52
|
+
|
53
|
+
@corrected_nodes ||= Set.new.compare_by_identity
|
54
|
+
@corrected_nodes.add(topmost_plus_node)
|
47
55
|
end
|
48
56
|
end
|
49
57
|
end
|
@@ -80,6 +88,10 @@ module RuboCop
|
|
80
88
|
part.each_descendant(:block).any?
|
81
89
|
end
|
82
90
|
|
91
|
+
def corrected_ancestor?(node)
|
92
|
+
node.each_ancestor(:send).any? { |ancestor| @corrected_nodes&.include?(ancestor) }
|
93
|
+
end
|
94
|
+
|
83
95
|
def replacement(parts)
|
84
96
|
interpolated_parts =
|
85
97
|
parts.map do |part|
|
@@ -87,7 +99,7 @@ module RuboCop
|
|
87
99
|
if single_quoted?(part)
|
88
100
|
part.value.gsub('\\') { '\\\\' }
|
89
101
|
else
|
90
|
-
|
102
|
+
part.value.inspect[1..-2]
|
91
103
|
end
|
92
104
|
else
|
93
105
|
"\#{#{part.source}}"
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cop enforces the use of shorthand-style swapping of 2 variables.
|
7
|
+
# Its autocorrection is marked as unsafe, because it can erroneously remove
|
8
|
+
# the temporary variable which is used later.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# # bad
|
12
|
+
# tmp = x
|
13
|
+
# x = y
|
14
|
+
# y = tmp
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# x, y = y, x
|
18
|
+
#
|
19
|
+
class SwapValues < Base
|
20
|
+
include RangeHelp
|
21
|
+
extend AutoCorrector
|
22
|
+
|
23
|
+
MSG = 'Replace this and assignments at lines %<x_line>d '\
|
24
|
+
'and %<y_line>d with `%<replacement>s`.'
|
25
|
+
|
26
|
+
SIMPLE_ASSIGNMENT_TYPES = %i[lvasgn ivasgn cvasgn gvasgn casgn].to_set.freeze
|
27
|
+
|
28
|
+
def on_asgn(node)
|
29
|
+
return if allowed_assignment?(node)
|
30
|
+
|
31
|
+
tmp_assign = node
|
32
|
+
x_assign, y_assign = *node.right_siblings.take(2)
|
33
|
+
return unless x_assign && y_assign && swapping_values?(tmp_assign, x_assign, y_assign)
|
34
|
+
|
35
|
+
add_offense(node, message: message(x_assign, y_assign)) do |corrector|
|
36
|
+
range = correction_range(tmp_assign, y_assign)
|
37
|
+
corrector.replace(range, replacement(x_assign))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
SIMPLE_ASSIGNMENT_TYPES.each { |asgn_type| alias_method :"on_#{asgn_type}", :on_asgn }
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def allowed_assignment?(node)
|
46
|
+
node.parent&.mlhs_type? || node.parent&.shorthand_asgn?
|
47
|
+
end
|
48
|
+
|
49
|
+
def swapping_values?(tmp_assign, x_assign, y_assign)
|
50
|
+
simple_assignment?(tmp_assign) &&
|
51
|
+
simple_assignment?(x_assign) &&
|
52
|
+
simple_assignment?(y_assign) &&
|
53
|
+
lhs(x_assign) == rhs(tmp_assign) &&
|
54
|
+
lhs(y_assign) == rhs(x_assign) &&
|
55
|
+
rhs(y_assign) == lhs(tmp_assign)
|
56
|
+
end
|
57
|
+
|
58
|
+
def simple_assignment?(node)
|
59
|
+
SIMPLE_ASSIGNMENT_TYPES.include?(node.type)
|
60
|
+
end
|
61
|
+
|
62
|
+
def message(x_assign, y_assign)
|
63
|
+
format(
|
64
|
+
MSG,
|
65
|
+
x_line: x_assign.first_line,
|
66
|
+
y_line: y_assign.first_line,
|
67
|
+
replacement: replacement(x_assign)
|
68
|
+
)
|
69
|
+
end
|
70
|
+
|
71
|
+
def replacement(x_assign)
|
72
|
+
x = lhs(x_assign)
|
73
|
+
y = rhs(x_assign)
|
74
|
+
"#{x}, #{y} = #{y}, #{x}"
|
75
|
+
end
|
76
|
+
|
77
|
+
def lhs(node)
|
78
|
+
case node.type
|
79
|
+
when :casgn
|
80
|
+
namespace, name, = *node
|
81
|
+
if namespace
|
82
|
+
"#{namespace.const_name}::#{name}"
|
83
|
+
else
|
84
|
+
name.to_s
|
85
|
+
end
|
86
|
+
else
|
87
|
+
node.children[0].to_s
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def rhs(node)
|
92
|
+
case node.type
|
93
|
+
when :casgn
|
94
|
+
node.children[2].source
|
95
|
+
else
|
96
|
+
node.children[1].source
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def correction_range(tmp_assign, y_assign)
|
101
|
+
range_by_whole_lines(
|
102
|
+
range_between(tmp_assign.source_range.begin_pos, y_assign.source_range.end_pos)
|
103
|
+
)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -36,6 +36,8 @@ module RuboCop
|
|
36
36
|
MSG = 'Do not use trailing `_`s in parallel assignment. ' \
|
37
37
|
'Prefer `%<code>s`.'
|
38
38
|
UNDERSCORE = '_'
|
39
|
+
DISALLOW = %i[lvasgn splat].freeze
|
40
|
+
private_constant :DISALLOW
|
39
41
|
|
40
42
|
def on_masgn(node)
|
41
43
|
ranges = unneeded_ranges(node)
|
@@ -64,7 +66,7 @@ module RuboCop
|
|
64
66
|
|
65
67
|
def find_first_possible_offense(variables)
|
66
68
|
variables.reduce(nil) do |offense, variable|
|
67
|
-
break offense unless
|
69
|
+
break offense unless DISALLOW.include?(variable.type)
|
68
70
|
|
69
71
|
var, = *variable
|
70
72
|
var, = *var
|
data/lib/rubocop/cop/team.rb
CHANGED
@@ -99,7 +99,12 @@ module RuboCop
|
|
99
99
|
def self.forces_for(cops)
|
100
100
|
needed = Hash.new { |h, k| h[k] = [] }
|
101
101
|
cops.each do |cop|
|
102
|
-
|
102
|
+
forces = cop.class.joining_forces
|
103
|
+
if forces.is_a?(Array)
|
104
|
+
forces.each { |force| needed[force] << cop }
|
105
|
+
elsif forces
|
106
|
+
needed[forces] << cop
|
107
|
+
end
|
103
108
|
end
|
104
109
|
|
105
110
|
needed.map do |force_class, joining_cops|
|
data/lib/rubocop/cop/util.rb
CHANGED