rubocop 0.92.0 → 1.2.0
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 +21 -7
- data/config/default.yml +169 -59
- data/exe/rubocop +1 -1
- data/lib/rubocop.rb +15 -3
- 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_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/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/else_alignment.rb +15 -2
- 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/end_alignment.rb +3 -3
- data/lib/rubocop/cop/layout/extra_spacing.rb +1 -2
- data/lib/rubocop/cop/layout/hash_alignment.rb +4 -4
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +24 -18
- 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/space_inside_parens.rb +35 -13
- 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/else_layout.rb +29 -3
- data/lib/rubocop/cop/lint/empty_block.rb +59 -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/loop.rb +0 -4
- data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
- data/lib/rubocop/cop/lint/nested_percent_literal.rb +14 -0
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +58 -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/lint/useless_setter_call.rb +6 -1
- 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/configurable_numbering.rb +3 -3
- 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 +12 -2
- data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +11 -5
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +67 -18
- data/lib/rubocop/cop/naming/predicate_name.rb +2 -1
- data/lib/rubocop/cop/naming/variable_number.rb +82 -8
- 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/bisected_attr_accessor.rb +0 -4
- data/lib/rubocop/cop/style/case_like_if.rb +18 -6
- data/lib/rubocop/cop/style/class_equality_comparison.rb +64 -0
- data/lib/rubocop/cop/style/collection_compact.rb +85 -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/document_dynamic_eval_definition.rb +67 -0
- data/lib/rubocop/cop/style/double_negation.rb +6 -1
- 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/hash_syntax.rb +3 -3
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +12 -0
- 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_grouping.rb +0 -4
- data/lib/rubocop/cop/style/multiple_comparison.rb +54 -7
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +99 -0
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +2 -0
- data/lib/rubocop/cop/style/raise_args.rb +21 -9
- 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 +5 -1
- data/lib/rubocop/cop/variable_force/branch.rb +0 -4
- data/lib/rubocop/ext/regexp_node.rb +35 -11
- data/lib/rubocop/ext/regexp_parser.rb +84 -0
- data/lib/rubocop/formatter/formatter_set.rb +2 -1
- data/lib/rubocop/formatter/git_hub_actions_formatter.rb +47 -0
- 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 +6 -1
- data/lib/rubocop/result_cache.rb +8 -2
- data/lib/rubocop/rspec/cop_helper.rb +1 -1
- data/lib/rubocop/rspec/shared_contexts.rb +4 -0
- data/lib/rubocop/runner.rb +4 -4
- data/lib/rubocop/target_finder.rb +23 -25
- data/lib/rubocop/version.rb +56 -6
- metadata +22 -8
- 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.start_index, !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
@@ -62,7 +62,7 @@ module RuboCop
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def begins_its_line?(range)
|
65
|
-
|
65
|
+
range.source_line.index(/\S/) == range.column
|
66
66
|
end
|
67
67
|
|
68
68
|
# Returns, for example, a bare `if` node if the given node is an `if`
|
@@ -123,6 +123,10 @@ module RuboCop
|
|
123
123
|
node1.loc.line == node2.loc.line
|
124
124
|
end
|
125
125
|
|
126
|
+
def indent(node)
|
127
|
+
' ' * node.loc.column
|
128
|
+
end
|
129
|
+
|
126
130
|
def to_supported_styles(enforced_style)
|
127
131
|
enforced_style
|
128
132
|
.sub(/^Enforced/, 'Supported')
|