rubocop 0.42.0 → 0.43.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubocop might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/assets/output.html.erb +21 -10
- data/config/default.yml +32 -2
- data/config/disabled.yml +8 -1
- data/config/enabled.yml +40 -12
- data/lib/rubocop.rb +14 -2
- data/lib/rubocop/ast_node.rb +2 -0
- data/lib/rubocop/cached_data.rb +13 -11
- data/lib/rubocop/cli.rb +5 -5
- data/lib/rubocop/config.rb +68 -24
- data/lib/rubocop/config_loader.rb +13 -11
- data/lib/rubocop/config_loader_resolver.rb +4 -2
- data/lib/rubocop/cop/cop.rb +16 -5
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +21 -20
- data/lib/rubocop/cop/lint/block_alignment.rb +3 -4
- data/lib/rubocop/cop/lint/def_end_alignment.rb +2 -3
- data/lib/rubocop/cop/lint/duplicate_methods.rb +16 -6
- data/lib/rubocop/cop/lint/else_layout.rb +1 -1
- data/lib/rubocop/cop/lint/empty_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/end_alignment.rb +4 -6
- data/lib/rubocop/cop/lint/eval.rb +1 -1
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
- data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +8 -8
- data/lib/rubocop/cop/lint/inherit_exception.rb +22 -7
- data/lib/rubocop/cop/lint/literal_in_condition.rb +5 -5
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +3 -5
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +9 -8
- data/lib/rubocop/cop/lint/percent_string_array.rb +17 -6
- data/lib/rubocop/cop/lint/percent_symbol_array.rb +4 -4
- data/lib/rubocop/cop/lint/rand_one.rb +3 -3
- data/lib/rubocop/cop/lint/require_parentheses.rb +1 -3
- data/lib/rubocop/cop/lint/shadowed_exception.rb +39 -44
- data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +2 -2
- data/lib/rubocop/cop/lint/underscore_prefixed_variable_name.rb +1 -2
- data/lib/rubocop/cop/lint/unified_integer.rb +38 -0
- data/lib/rubocop/cop/lint/unneeded_disable.rb +51 -38
- data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +114 -0
- data/lib/rubocop/cop/lint/useless_assignment.rb +25 -12
- data/lib/rubocop/cop/lint/useless_setter_call.rb +27 -28
- data/lib/rubocop/cop/lint/void.rb +2 -4
- data/lib/rubocop/cop/mixin/access_modifier_node.rb +5 -5
- data/lib/rubocop/cop/mixin/array_hash_indentation.rb +19 -17
- data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +3 -5
- data/lib/rubocop/cop/mixin/configurable_naming.rb +4 -5
- data/lib/rubocop/cop/mixin/configurable_numbering.rb +52 -0
- data/lib/rubocop/cop/mixin/def_node.rb +28 -0
- data/lib/rubocop/cop/mixin/documentation_comment.rb +41 -0
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +18 -13
- data/lib/rubocop/cop/mixin/if_node.rb +6 -0
- data/lib/rubocop/cop/mixin/match_range.rb +2 -5
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -2
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +40 -28
- data/lib/rubocop/cop/mixin/negative_conditional.rb +6 -6
- data/lib/rubocop/cop/mixin/percent_literal.rb +1 -5
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +14 -4
- data/lib/rubocop/cop/mixin/safe_mode.rb +23 -0
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +2 -4
- data/lib/rubocop/cop/mixin/space_inside.rb +1 -3
- data/lib/rubocop/cop/mixin/statement_modifier.rb +30 -20
- data/lib/rubocop/cop/mixin/trailing_comma.rb +19 -17
- data/lib/rubocop/cop/performance/case_when_splat.rb +16 -41
- data/lib/rubocop/cop/performance/casecmp.rb +28 -16
- data/lib/rubocop/cop/performance/count.rb +58 -34
- data/lib/rubocop/cop/performance/detect.rb +3 -7
- data/lib/rubocop/cop/performance/double_start_end_with.rb +17 -13
- data/lib/rubocop/cop/performance/fixed_size.rb +19 -14
- data/lib/rubocop/cop/performance/flat_map.rb +16 -9
- data/lib/rubocop/cop/performance/hash_each.rb +2 -3
- data/lib/rubocop/cop/performance/lstrip_rstrip.rb +4 -6
- data/lib/rubocop/cop/performance/redundant_match.rb +4 -1
- data/lib/rubocop/cop/performance/redundant_merge.rb +63 -32
- data/lib/rubocop/cop/performance/redundant_sort_by.rb +8 -7
- data/lib/rubocop/cop/performance/reverse_each.rb +1 -4
- data/lib/rubocop/cop/performance/size.rb +21 -8
- data/lib/rubocop/cop/performance/sort_with_block.rb +54 -0
- data/lib/rubocop/cop/performance/string_replacement.rb +3 -7
- data/lib/rubocop/cop/rails/delegate.rb +2 -3
- data/lib/rubocop/cop/rails/find_by.rb +4 -8
- data/lib/rubocop/cop/rails/not_null_column.rb +45 -0
- data/lib/rubocop/cop/rails/request_referer.rb +3 -3
- data/lib/rubocop/cop/rails/safe_navigation.rb +89 -0
- data/lib/rubocop/cop/rails/save_bang.rb +78 -9
- data/lib/rubocop/cop/rails/scope_args.rb +3 -1
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +2 -3
- data/lib/rubocop/cop/rails/validation.rb +1 -1
- data/lib/rubocop/cop/security/json_load.rb +36 -0
- data/lib/rubocop/cop/style/alias.rb +1 -1
- data/lib/rubocop/cop/style/align_hash.rb +25 -14
- data/lib/rubocop/cop/style/and_or.rb +13 -3
- data/lib/rubocop/cop/style/array_join.rb +3 -3
- data/lib/rubocop/cop/style/ascii_comments.rb +1 -2
- data/lib/rubocop/cop/style/ascii_identifiers.rb +1 -2
- data/lib/rubocop/cop/style/attr.rb +1 -3
- data/lib/rubocop/cop/style/block_comments.rb +2 -6
- data/lib/rubocop/cop/style/block_delimiters.rb +35 -21
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +4 -4
- data/lib/rubocop/cop/style/case_indentation.rb +1 -3
- data/lib/rubocop/cop/style/class_methods.rb +3 -4
- data/lib/rubocop/cop/style/collection_methods.rb +1 -1
- data/lib/rubocop/cop/style/command_literal.rb +15 -8
- data/lib/rubocop/cop/style/comment_annotation.rb +1 -2
- data/lib/rubocop/cop/style/conditional_assignment.rb +68 -36
- data/lib/rubocop/cop/style/copyright.rb +1 -5
- data/lib/rubocop/cop/style/def_with_parentheses.rb +3 -5
- data/lib/rubocop/cop/style/documentation.rb +28 -56
- data/lib/rubocop/cop/style/documentation_method.rb +80 -0
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +6 -5
- data/lib/rubocop/cop/style/each_with_object.rb +2 -2
- data/lib/rubocop/cop/style/else_alignment.rb +10 -9
- data/lib/rubocop/cop/style/empty_case_condition.rb +2 -4
- data/lib/rubocop/cop/style/empty_else.rb +1 -4
- data/lib/rubocop/cop/style/empty_line_between_defs.rb +1 -3
- data/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb +2 -5
- data/lib/rubocop/cop/style/encoding.rb +28 -14
- data/lib/rubocop/cop/style/even_odd.rb +28 -17
- data/lib/rubocop/cop/style/extra_spacing.rb +36 -25
- data/lib/rubocop/cop/style/file_name.rb +19 -10
- data/lib/rubocop/cop/style/first_parameter_indentation.rb +2 -3
- data/lib/rubocop/cop/style/for.rb +12 -8
- data/lib/rubocop/cop/style/format_string.rb +1 -1
- data/lib/rubocop/cop/style/guard_clause.rb +22 -56
- data/lib/rubocop/cop/style/hash_syntax.rb +72 -7
- data/lib/rubocop/cop/style/if_unless_modifier.rb +23 -19
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +3 -3
- data/lib/rubocop/cop/style/indentation_width.rb +30 -16
- data/lib/rubocop/cop/style/infinite_loop.rb +16 -13
- data/lib/rubocop/cop/style/initial_indentation.rb +23 -18
- data/lib/rubocop/cop/style/inline_comment.rb +16 -3
- data/lib/rubocop/cop/style/lambda.rb +22 -10
- data/lib/rubocop/cop/style/leading_comment_space.rb +12 -1
- data/lib/rubocop/cop/style/line_end_concatenation.rb +24 -6
- data/lib/rubocop/cop/style/method_call_parentheses.rb +18 -9
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +3 -4
- data/lib/rubocop/cop/style/method_def_parentheses.rb +3 -4
- data/lib/rubocop/cop/style/method_missing.rb +10 -2
- data/lib/rubocop/cop/style/module_function.rb +14 -6
- data/lib/rubocop/cop/style/multiline_assignment_layout.rb +2 -5
- data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -5
- data/lib/rubocop/cop/style/multiline_block_layout.rb +22 -15
- data/lib/rubocop/cop/style/multiline_method_call_brace_layout.rb +9 -0
- data/lib/rubocop/cop/style/multiline_method_call_indentation.rb +41 -20
- data/lib/rubocop/cop/style/multiline_operation_indentation.rb +6 -6
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +3 -5
- data/lib/rubocop/cop/style/mutable_constant.rb +21 -13
- data/lib/rubocop/cop/style/negated_if.rb +1 -1
- data/lib/rubocop/cop/style/negated_while.rb +3 -3
- data/lib/rubocop/cop/style/nested_modifier.rb +2 -4
- data/lib/rubocop/cop/style/next.rb +4 -4
- data/lib/rubocop/cop/style/non_nil_check.rb +18 -10
- data/lib/rubocop/cop/style/numeric_literal_prefix.rb +8 -0
- data/lib/rubocop/cop/style/numeric_predicate.rb +9 -9
- data/lib/rubocop/cop/style/one_line_conditional.rb +11 -1
- data/lib/rubocop/cop/style/op_method.rb +1 -1
- data/lib/rubocop/cop/style/option_hash.rb +8 -8
- data/lib/rubocop/cop/style/optional_arguments.rb +21 -8
- data/lib/rubocop/cop/style/parallel_assignment.rb +51 -35
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/raise_args.rb +2 -2
- data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +26 -15
- data/lib/rubocop/cop/style/redundant_return.rb +5 -5
- data/lib/rubocop/cop/style/redundant_self.rb +20 -11
- data/lib/rubocop/cop/style/regexp_literal.rb +16 -10
- data/lib/rubocop/cop/style/rescue_ensure_alignment.rb +8 -6
- data/lib/rubocop/cop/style/safe_navigation.rb +125 -0
- data/lib/rubocop/cop/style/self_assignment.rb +2 -2
- data/lib/rubocop/cop/style/semicolon.rb +9 -10
- data/lib/rubocop/cop/style/signal_exception.rb +2 -4
- data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +18 -11
- data/lib/rubocop/cop/style/space_after_method_name.rb +2 -3
- data/lib/rubocop/cop/style/space_after_not.rb +4 -6
- data/lib/rubocop/cop/style/space_around_block_parameters.rb +1 -2
- data/lib/rubocop/cop/style/space_around_equals_in_parameter_default.rb +1 -3
- data/lib/rubocop/cop/style/space_around_operators.rb +21 -16
- data/lib/rubocop/cop/style/space_before_block_braces.rb +2 -12
- data/lib/rubocop/cop/style/space_before_first_arg.rb +1 -3
- data/lib/rubocop/cop/style/space_inside_array_percent_literal.rb +1 -1
- data/lib/rubocop/cop/style/space_inside_block_braces.rb +33 -40
- data/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb +38 -23
- data/lib/rubocop/cop/style/space_inside_percent_literal_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/space_inside_string_interpolation.rb +26 -12
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +2 -4
- data/lib/rubocop/cop/style/symbol_array.rb +10 -10
- data/lib/rubocop/cop/style/symbol_proc.rb +28 -13
- data/lib/rubocop/cop/style/ternary_parentheses.rb +35 -5
- data/lib/rubocop/cop/style/trailing_blank_lines.rb +2 -4
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +29 -17
- data/lib/rubocop/cop/style/trivial_accessors.rb +6 -6
- data/lib/rubocop/cop/style/unless_else.rb +2 -6
- data/lib/rubocop/cop/style/unneeded_capital_w.rb +8 -4
- data/lib/rubocop/cop/style/unneeded_interpolation.rb +4 -5
- data/lib/rubocop/cop/style/unneeded_percent_q.rb +13 -7
- data/lib/rubocop/cop/style/variable_number.rb +79 -0
- data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +25 -15
- data/lib/rubocop/cop/style/zero_length_predicate.rb +2 -0
- data/lib/rubocop/cop/util.rb +23 -4
- data/lib/rubocop/cop/variable_force.rb +59 -25
- data/lib/rubocop/cop/variable_force/locatable.rb +8 -6
- data/lib/rubocop/cop/variable_force/variable.rb +2 -2
- data/lib/rubocop/cop/variable_force/variable_table.rb +3 -3
- data/lib/rubocop/formatter/disabled_config_formatter.rb +16 -11
- data/lib/rubocop/formatter/formatter_set.rb +12 -10
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +4 -4
- data/lib/rubocop/node_pattern.rb +79 -35
- data/lib/rubocop/options.rb +4 -4
- data/lib/rubocop/processed_source.rb +9 -5
- data/lib/rubocop/remote_config.rb +14 -10
- data/lib/rubocop/result_cache.rb +14 -6
- data/lib/rubocop/runner.rb +55 -34
- data/lib/rubocop/string_util.rb +9 -5
- data/lib/rubocop/target_finder.rb +1 -1
- data/lib/rubocop/token.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- metadata +15 -4
- data/lib/rubocop/cop/lint/useless_array_splat.rb +0 -56
- data/lib/rubocop/cop/performance/push_splat.rb +0 -47
@@ -0,0 +1,38 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RuboCop
|
5
|
+
module Cop
|
6
|
+
module Lint
|
7
|
+
# This cop checks for using Fixnum or Bignum constant.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# 1.is_a?(Fixnum)
|
12
|
+
# 1.is_a?(Bignum)
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# 1.is_a?(Integer)
|
16
|
+
class UnifiedInteger < Cop
|
17
|
+
MSG = 'Use `Integer` instead of `%s`.'.freeze
|
18
|
+
|
19
|
+
def_node_matcher :fixnum_or_bignum_const?, <<-PATTERN
|
20
|
+
(:const {nil (:cbase)} ${:Fixnum :Bignum})
|
21
|
+
PATTERN
|
22
|
+
|
23
|
+
def on_const(node)
|
24
|
+
klass = fixnum_or_bignum_const?(node)
|
25
|
+
return unless klass
|
26
|
+
|
27
|
+
add_offense(node, :expression, format(MSG, klass))
|
28
|
+
end
|
29
|
+
|
30
|
+
def autocorrect(node)
|
31
|
+
lambda do |corrector|
|
32
|
+
corrector.replace(node.loc.name, 'Integer')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -33,30 +33,11 @@ module RuboCop
|
|
33
33
|
lambda do |corrector|
|
34
34
|
ranges, range = *args # Ranges are sorted by position.
|
35
35
|
|
36
|
-
if range.source.start_with?('#')
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
range = range_with_surrounding_space(range, :right,
|
42
|
-
# Special for a comment that
|
43
|
-
# begins the file: remove
|
44
|
-
# the newline at the end.
|
45
|
-
original_begin.zero?)
|
46
|
-
else
|
47
|
-
# Is there any cop between this one and the end of the line, which
|
48
|
-
# is NOT being removed?
|
49
|
-
|
50
|
-
if ends_its_line?(ranges.last) && trailing_range?(ranges, range)
|
51
|
-
# Eat the comma on the left.
|
52
|
-
range = range_with_surrounding_space(range, :left)
|
53
|
-
range = range_with_surrounding_comma(range, :left)
|
54
|
-
end
|
55
|
-
|
56
|
-
range = range_with_surrounding_comma(range, :right)
|
57
|
-
# Eat following spaces up to EOL, but not the newline itself.
|
58
|
-
range = range_with_surrounding_space(range, :right, false)
|
59
|
-
end
|
36
|
+
range = if range.source.start_with?('#')
|
37
|
+
comment_range_with_surrounding_space(range)
|
38
|
+
else
|
39
|
+
directive_range_in_list(range, ranges)
|
40
|
+
end
|
60
41
|
|
61
42
|
corrector.remove(range)
|
62
43
|
end
|
@@ -64,6 +45,32 @@ module RuboCop
|
|
64
45
|
|
65
46
|
private
|
66
47
|
|
48
|
+
def comment_range_with_surrounding_space(range)
|
49
|
+
# Eat the entire comment, the preceding space, and the preceding
|
50
|
+
# newline if there is one.
|
51
|
+
original_begin = range.begin_pos
|
52
|
+
range = range_with_surrounding_space(range, :left, true)
|
53
|
+
range_with_surrounding_space(range, :right,
|
54
|
+
# Special for a comment that
|
55
|
+
# begins the file: remove
|
56
|
+
# the newline at the end.
|
57
|
+
original_begin.zero?)
|
58
|
+
end
|
59
|
+
|
60
|
+
def directive_range_in_list(range, ranges)
|
61
|
+
# Is there any cop between this one and the end of the line, which
|
62
|
+
# is NOT being removed?
|
63
|
+
if ends_its_line?(ranges.last) && trailing_range?(ranges, range)
|
64
|
+
# Eat the comma on the left.
|
65
|
+
range = range_with_surrounding_space(range, :left)
|
66
|
+
range = range_with_surrounding_comma(range, :left)
|
67
|
+
end
|
68
|
+
|
69
|
+
range = range_with_surrounding_comma(range, :right)
|
70
|
+
# Eat following spaces up to EOL, but not the newline itself.
|
71
|
+
range_with_surrounding_space(range, :right, false)
|
72
|
+
end
|
73
|
+
|
67
74
|
def each_unneeded_disable(cop_disabled_line_ranges, offenses, comments)
|
68
75
|
disabled_ranges = cop_disabled_line_ranges[COP_NAME] || [0..0]
|
69
76
|
|
@@ -124,27 +131,33 @@ module RuboCop
|
|
124
131
|
|
125
132
|
def add_offenses(unneeded_cops)
|
126
133
|
unneeded_cops.each do |comment, cops|
|
127
|
-
# Is the entire rubocop:disable line useless, or should just
|
128
|
-
# some of the mentioned cops be removed?
|
129
134
|
if all_disabled?(comment) ||
|
130
135
|
directive_count(comment) == cops.size
|
131
|
-
|
132
|
-
cop_list = cops.sort.map { |c| describe(c) }
|
133
|
-
add_offense([[location], location], location,
|
134
|
-
"Unnecessary disabling of #{cop_list.join(', ')}.")
|
136
|
+
add_offense_for_entire_comment(comment, cops)
|
135
137
|
else
|
136
|
-
|
137
|
-
cop_ranges.sort_by! { |_, r| r.begin_pos }
|
138
|
-
ranges = cop_ranges.map { |_, r| r }
|
139
|
-
|
140
|
-
cop_ranges.each do |cop, range|
|
141
|
-
add_offense([ranges, range], range,
|
142
|
-
"Unnecessary disabling of #{describe(cop)}.")
|
143
|
-
end
|
138
|
+
add_offense_for_some_cops(comment, cops)
|
144
139
|
end
|
145
140
|
end
|
146
141
|
end
|
147
142
|
|
143
|
+
def add_offense_for_entire_comment(comment, cops)
|
144
|
+
location = comment.loc.expression
|
145
|
+
cop_list = cops.sort.map { |c| describe(c) }
|
146
|
+
add_offense([[location], location], location,
|
147
|
+
"Unnecessary disabling of #{cop_list.join(', ')}.")
|
148
|
+
end
|
149
|
+
|
150
|
+
def add_offense_for_some_cops(comment, cops)
|
151
|
+
cop_ranges = cops.map { |c| [c, cop_range(comment, c)] }
|
152
|
+
cop_ranges.sort_by! { |_, r| r.begin_pos }
|
153
|
+
ranges = cop_ranges.map { |_, r| r }
|
154
|
+
|
155
|
+
cop_ranges.each do |cop, range|
|
156
|
+
add_offense([ranges, range], range,
|
157
|
+
"Unnecessary disabling of #{describe(cop)}.")
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
148
161
|
def cop_range(comment, cop)
|
149
162
|
matching_range(comment.loc.expression, cop) ||
|
150
163
|
matching_range(comment.loc.expression, cop.split('/').last) ||
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RuboCop
|
5
|
+
module Cop
|
6
|
+
module Lint
|
7
|
+
# This cop checks for unneeded usages of splat expansion
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# a = *[1, 2, 3]
|
12
|
+
# a = *'a'
|
13
|
+
# a = *1
|
14
|
+
#
|
15
|
+
# begin
|
16
|
+
# foo
|
17
|
+
# rescue *[StandardError, ApplicationError]
|
18
|
+
# bar
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# case foo
|
22
|
+
# when *[1, 2, 3]
|
23
|
+
# bar
|
24
|
+
# else
|
25
|
+
# baz
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# # good
|
29
|
+
# c = [1, 2, 3]
|
30
|
+
# a = *c
|
31
|
+
# a, b = *c
|
32
|
+
# a, *b = *c
|
33
|
+
# a = *1..10
|
34
|
+
# a = ['a']
|
35
|
+
#
|
36
|
+
# begin
|
37
|
+
# foo
|
38
|
+
# rescue StandardError, ApplicationError
|
39
|
+
# bar
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# case foo
|
43
|
+
# when *[1, 2, 3]
|
44
|
+
# bar
|
45
|
+
# else
|
46
|
+
# baz
|
47
|
+
# end
|
48
|
+
class UnneededSplatExpansion < Cop
|
49
|
+
MSG = 'Unnecessary splat expansion.'.freeze
|
50
|
+
PERCENT_W = '%w'.freeze
|
51
|
+
PERCENT_CAPITAL_W = '%W'.freeze
|
52
|
+
PERCENT_I = '%i'.freeze
|
53
|
+
PERCENT_CAPITAL_I = '%I'.freeze
|
54
|
+
ARRAY_NEW_PATTERN = '$(send (const nil :Array) :new ...)'.freeze
|
55
|
+
ASSIGNMENT_TYPES = [:lvasgn, :ivasgn, :cvasgn, :gvasgn].freeze
|
56
|
+
|
57
|
+
def_node_matcher :literal_expansion?, <<-PATTERN
|
58
|
+
(splat {$({str dstr int float array} ...) (block #{ARRAY_NEW_PATTERN} ...) #{ARRAY_NEW_PATTERN}} ...)
|
59
|
+
PATTERN
|
60
|
+
|
61
|
+
def on_splat(node)
|
62
|
+
literal_expansion?(node) do |object|
|
63
|
+
if object.send_type?
|
64
|
+
return unless ASSIGNMENT_TYPES.include?(node.parent.parent.type)
|
65
|
+
end
|
66
|
+
add_offense(node, :expression)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def autocorrect(node)
|
73
|
+
variable, = *node
|
74
|
+
parent = node.parent
|
75
|
+
loc = node.loc
|
76
|
+
|
77
|
+
lambda do |corrector|
|
78
|
+
if !variable.array_type?
|
79
|
+
corrector.replace(loc.expression, "[#{variable.source}]")
|
80
|
+
elsif unneeded_brackets?(parent)
|
81
|
+
corrector.replace(loc.expression, remove_brackets(variable))
|
82
|
+
else
|
83
|
+
corrector.remove(loc.operator)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def unneeded_brackets?(node)
|
89
|
+
parent = node.parent
|
90
|
+
|
91
|
+
node.when_type? || node.send_type? || (parent && parent.resbody_type?)
|
92
|
+
end
|
93
|
+
|
94
|
+
def remove_brackets(array)
|
95
|
+
array_start = array.loc.begin.source
|
96
|
+
elements = *array
|
97
|
+
elements = elements.map(&:source)
|
98
|
+
|
99
|
+
if array_start.start_with?(PERCENT_W)
|
100
|
+
"'#{elements.join("', '")}'"
|
101
|
+
elsif array_start.start_with?(PERCENT_CAPITAL_W)
|
102
|
+
%("#{elements.join('", "')}")
|
103
|
+
elsif array_start.start_with?(PERCENT_I)
|
104
|
+
":#{elements.join(', :')}"
|
105
|
+
elsif array_start.start_with?(PERCENT_CAPITAL_I)
|
106
|
+
%(:"#{elements.join('", :"')}")
|
107
|
+
else
|
108
|
+
elements.join(', ')
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -48,30 +48,43 @@ module RuboCop
|
|
48
48
|
def message_for_useless_assignment(assignment)
|
49
49
|
variable = assignment.variable
|
50
50
|
|
51
|
-
|
51
|
+
format(MSG, variable.name) +
|
52
|
+
message_specification(assignment, variable).to_s
|
53
|
+
end
|
52
54
|
|
55
|
+
def message_specification(assignment, variable)
|
53
56
|
if assignment.multiple_assignment?
|
54
|
-
|
55
|
-
"to indicate that it won't be used."
|
57
|
+
multiple_assignment_message(variable.name)
|
56
58
|
elsif assignment.operator_assignment?
|
57
|
-
|
58
|
-
if assignment.meta_assignment_node.equal?(return_value_node)
|
59
|
-
non_assignment_operator = assignment.operator.sub(/=$/, '')
|
60
|
-
message << " Use just operator `#{non_assignment_operator}`."
|
61
|
-
end
|
59
|
+
operator_assignment_message(variable.scope, assignment)
|
62
60
|
else
|
63
|
-
|
64
|
-
message << " Did you mean `#{similar_name}`?" if similar_name
|
61
|
+
similar_name_message(variable)
|
65
62
|
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def multiple_assignment_message(variable_name)
|
66
|
+
" Use `_` or `_#{variable_name}` as a variable name to indicate " \
|
67
|
+
"that it won't be used."
|
68
|
+
end
|
69
|
+
|
70
|
+
def operator_assignment_message(scope, assignment)
|
71
|
+
return_value_node = return_value_node_of_scope(scope)
|
72
|
+
return unless assignment.meta_assignment_node
|
73
|
+
.equal?(return_value_node)
|
74
|
+
|
75
|
+
" Use just operator `#{assignment.operator.sub(/=$/, '')}`."
|
76
|
+
end
|
66
77
|
|
67
|
-
|
78
|
+
def similar_name_message(variable)
|
79
|
+
similar_name = find_similar_name(variable.name, variable.scope)
|
80
|
+
" Did you mean `#{similar_name}`?" if similar_name
|
68
81
|
end
|
69
82
|
|
70
83
|
# TODO: More precise handling (rescue, ensure, nested begin, etc.)
|
71
84
|
def return_value_node_of_scope(scope)
|
72
85
|
body_node = scope.body_node
|
73
86
|
|
74
|
-
if body_node.
|
87
|
+
if body_node.begin_type?
|
75
88
|
body_node.children.last
|
76
89
|
else
|
77
90
|
body_node
|
@@ -24,14 +24,7 @@ module RuboCop
|
|
24
24
|
def on_method_def(_node, _method_name, _args, body)
|
25
25
|
return unless body
|
26
26
|
|
27
|
-
|
28
|
-
body.children
|
29
|
-
else
|
30
|
-
body
|
31
|
-
end
|
32
|
-
|
33
|
-
last_expr = expression.is_a?(Array) ? expression.last : expression
|
34
|
-
|
27
|
+
last_expr = last_expression(body)
|
35
28
|
return unless setter_call_to_local_variable?(last_expr)
|
36
29
|
|
37
30
|
tracker = MethodVariableTracker.new(body)
|
@@ -39,15 +32,19 @@ module RuboCop
|
|
39
32
|
variable_name, = *receiver
|
40
33
|
return unless tracker.contain_local_object?(variable_name)
|
41
34
|
|
42
|
-
add_offense(receiver,
|
43
|
-
|
44
|
-
|
35
|
+
add_offense(receiver, :name, format(MSG, receiver.loc.name.source))
|
36
|
+
end
|
37
|
+
|
38
|
+
def last_expression(body)
|
39
|
+
expression = body.begin_type? ? body.children : body
|
40
|
+
|
41
|
+
expression.is_a?(Array) ? expression.last : expression
|
45
42
|
end
|
46
43
|
|
47
44
|
def setter_call_to_local_variable?(node)
|
48
|
-
return unless node && node.
|
45
|
+
return unless node && node.send_type?
|
49
46
|
receiver, method, _args = *node
|
50
|
-
return unless receiver && receiver.
|
47
|
+
return unless receiver && receiver.lvar_type?
|
51
48
|
method =~ /(?:\w|\[\])=$/
|
52
49
|
end
|
53
50
|
|
@@ -64,19 +61,7 @@ module RuboCop
|
|
64
61
|
|
65
62
|
@local = {}
|
66
63
|
|
67
|
-
scan(@body_node)
|
68
|
-
case node.type
|
69
|
-
when :masgn
|
70
|
-
process_multiple_assignment(node)
|
71
|
-
when :or_asgn, :and_asgn
|
72
|
-
process_logical_operator_assignment(node)
|
73
|
-
when :op_asgn
|
74
|
-
process_binary_operator_assignment(node)
|
75
|
-
when *ASSIGNMENT_TYPES
|
76
|
-
_, rhs_node = *node
|
77
|
-
process_assignment(node, rhs_node) if rhs_node
|
78
|
-
end
|
79
|
-
end
|
64
|
+
scan(@body_node) { |node| process_assignment_node(node) }
|
80
65
|
|
81
66
|
@local[variable_name]
|
82
67
|
end
|
@@ -91,6 +76,20 @@ module RuboCop
|
|
91
76
|
end
|
92
77
|
end
|
93
78
|
|
79
|
+
def process_assignment_node(node)
|
80
|
+
case node.type
|
81
|
+
when :masgn
|
82
|
+
process_multiple_assignment(node)
|
83
|
+
when :or_asgn, :and_asgn
|
84
|
+
process_logical_operator_assignment(node)
|
85
|
+
when :op_asgn
|
86
|
+
process_binary_operator_assignment(node)
|
87
|
+
when *ASSIGNMENT_TYPES
|
88
|
+
_, rhs_node = *node
|
89
|
+
process_assignment(node, rhs_node) if rhs_node
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
94
93
|
def process_multiple_assignment(masgn_node)
|
95
94
|
mlhs_node, mrhs_node = *masgn_node
|
96
95
|
|
@@ -100,7 +99,7 @@ module RuboCop
|
|
100
99
|
lhs_variable_name, = *lhs_node
|
101
100
|
rhs_node = mrhs_node.children[index]
|
102
101
|
|
103
|
-
if mrhs_node.
|
102
|
+
if mrhs_node.array_type? && rhs_node
|
104
103
|
process_assignment(lhs_variable_name, rhs_node)
|
105
104
|
else
|
106
105
|
@local[lhs_variable_name] = true
|
@@ -140,7 +139,7 @@ module RuboCop
|
|
140
139
|
|
141
140
|
def constructor?(node)
|
142
141
|
return true if node.literal?
|
143
|
-
return false unless node.
|
142
|
+
return false unless node.send_type?
|
144
143
|
_receiver, method = *node
|
145
144
|
method == :new
|
146
145
|
end
|
@@ -34,8 +34,7 @@ module RuboCop
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def check_for_void_op(node)
|
37
|
-
return unless node.
|
38
|
-
return unless node.loc.selector
|
37
|
+
return unless node.send_type? && node.loc.selector
|
39
38
|
|
40
39
|
op = node.loc.selector.source
|
41
40
|
|
@@ -48,8 +47,7 @@ module RuboCop
|
|
48
47
|
end
|
49
48
|
|
50
49
|
def check_for_literal(node)
|
51
|
-
return
|
52
|
-
return if node.xstr_type?
|
50
|
+
return if !node.literal? || node.xstr_type?
|
53
51
|
|
54
52
|
add_offense(node, :expression, format(LIT_MSG, node.source))
|
55
53
|
end
|
@@ -29,11 +29,11 @@ module RuboCop
|
|
29
29
|
# is a Class or Module. Filters out simple method calls to similarly
|
30
30
|
# named private, protected or public.
|
31
31
|
def class_or_module_parent?(node)
|
32
|
-
node.each_ancestor do |
|
33
|
-
if
|
34
|
-
return true if
|
35
|
-
elsif
|
36
|
-
return [:casgn, :sclass, :class, :module].include?(
|
32
|
+
node.each_ancestor do |ancestor|
|
33
|
+
if ancestor.block_type?
|
34
|
+
return true if ancestor.class_constructor?
|
35
|
+
elsif !ancestor.begin_type?
|
36
|
+
return [:casgn, :sclass, :class, :module].include?(ancestor.type)
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|