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
@@ -4,7 +4,7 @@
|
|
4
4
|
module RuboCop
|
5
5
|
module Cop
|
6
6
|
module Style
|
7
|
-
# This cop checks for places where
|
7
|
+
# This cop checks for places where Integer#even? or Integer#odd?
|
8
8
|
# should have been used.
|
9
9
|
#
|
10
10
|
# @example
|
@@ -15,20 +15,25 @@ module RuboCop
|
|
15
15
|
# # good
|
16
16
|
# if x.even?
|
17
17
|
class EvenOdd < Cop
|
18
|
-
MSG = 'Replace with `
|
18
|
+
MSG = 'Replace with `Integer#%s?`.'.freeze
|
19
19
|
|
20
20
|
ZERO = s(:int, 0)
|
21
21
|
ONE = s(:int, 1)
|
22
22
|
TWO = s(:int, 2)
|
23
23
|
|
24
|
+
EQUALITY_OPERATORS = [:==, :!=].freeze
|
25
|
+
|
24
26
|
def on_send(node)
|
25
|
-
|
26
|
-
|
27
|
+
offense_type(node) do |replacement_method|
|
28
|
+
add_offense(node, :expression, format(MSG, replacement_method))
|
29
|
+
end
|
27
30
|
end
|
28
31
|
|
29
32
|
def autocorrect(node)
|
30
|
-
|
31
|
-
|
33
|
+
offense_type(node) do |replacement_method|
|
34
|
+
correction = "#{base_number(node)}.#{replacement_method}?"
|
35
|
+
->(corrector) { corrector.replace(node.source_range, correction) }
|
36
|
+
end
|
32
37
|
end
|
33
38
|
|
34
39
|
private
|
@@ -36,20 +41,20 @@ module RuboCop
|
|
36
41
|
def base_number(node)
|
37
42
|
receiver, = *node
|
38
43
|
node = expression(receiver)
|
39
|
-
node.children
|
44
|
+
node.children.first.source
|
40
45
|
end
|
41
46
|
|
42
47
|
def offense_type(node)
|
43
48
|
receiver, method, args = *node
|
44
49
|
|
45
|
-
return unless
|
50
|
+
return unless equality_operator?(method)
|
46
51
|
return unless div_by_2?(receiver)
|
47
52
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
+
replacement_method(args, method) { |odd_or_even| yield odd_or_even }
|
54
|
+
end
|
55
|
+
|
56
|
+
def equality_operator?(method_name)
|
57
|
+
EQUALITY_OPERATORS.include?(method_name)
|
53
58
|
end
|
54
59
|
|
55
60
|
def div_by_2?(node)
|
@@ -60,15 +65,21 @@ module RuboCop
|
|
60
65
|
method == :% && args == TWO
|
61
66
|
end
|
62
67
|
|
68
|
+
def replacement_method(args, method)
|
69
|
+
if args == ZERO
|
70
|
+
yield method == :== ? :even : :odd
|
71
|
+
elsif args == ONE
|
72
|
+
yield method == :== ? :odd : :even
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
63
76
|
def expression(node)
|
64
77
|
return unless node
|
65
78
|
|
66
79
|
# check for scenarios like (x % 2) == 0
|
67
|
-
|
68
|
-
node = node.children.first
|
69
|
-
end
|
80
|
+
node = node.children.first if node.begin_type? && node.children.one?
|
70
81
|
|
71
|
-
return unless node.
|
82
|
+
return unless node.send_type?
|
72
83
|
node
|
73
84
|
end
|
74
85
|
end
|
@@ -30,14 +30,7 @@ module RuboCop
|
|
30
30
|
return if processed_source.ast.nil?
|
31
31
|
|
32
32
|
if force_equal_sign_alignment?
|
33
|
-
@asgn_tokens =
|
34
|
-
# we don't want to operate on equals signs which are part of an
|
35
|
-
# optarg in a method definition
|
36
|
-
# e.g.: def method(optarg = default_val); end
|
37
|
-
@asgn_tokens = remove_optarg_equals(@asgn_tokens, processed_source)
|
38
|
-
|
39
|
-
# Only attempt to align the first = on each line
|
40
|
-
@asgn_tokens = Set.new(@asgn_tokens.uniq { |t| t.pos.line })
|
33
|
+
@asgn_tokens = assignment_tokens
|
41
34
|
@asgn_lines = @asgn_tokens.map { |t| t.pos.line }
|
42
35
|
# Don't attempt to correct the same = more than once
|
43
36
|
@corrected = Set.new
|
@@ -51,7 +44,7 @@ module RuboCop
|
|
51
44
|
def autocorrect(range)
|
52
45
|
lambda do |corrector|
|
53
46
|
if range.source.end_with?('=')
|
54
|
-
|
47
|
+
align_equal_signs(range, corrector)
|
55
48
|
else
|
56
49
|
corrector.remove(range)
|
57
50
|
end
|
@@ -60,6 +53,17 @@ module RuboCop
|
|
60
53
|
|
61
54
|
private
|
62
55
|
|
56
|
+
def assignment_tokens
|
57
|
+
tokens = processed_source.tokens.select { |t| equal_sign?(t) }
|
58
|
+
# we don't want to operate on equals signs which are part of an
|
59
|
+
# optarg in a method definition
|
60
|
+
# e.g.: def method(optarg = default_val); end
|
61
|
+
tokens = remove_optarg_equals(tokens, processed_source)
|
62
|
+
|
63
|
+
# Only attempt to align the first = on each line
|
64
|
+
Set.new(tokens.uniq { |t| t.pos.line })
|
65
|
+
end
|
66
|
+
|
63
67
|
def check_tokens(ast, t1, t2)
|
64
68
|
return if t2.type == :tNL
|
65
69
|
|
@@ -100,20 +104,24 @@ module RuboCop
|
|
100
104
|
end
|
101
105
|
|
102
106
|
def check_other(t1, t2, ast)
|
107
|
+
extra_space_range(t1, t2) do |range|
|
108
|
+
# Unary + doesn't appear as a token and needs special handling.
|
109
|
+
next if ignored_range?(ast, range.begin_pos)
|
110
|
+
next if unary_plus_non_offense?(range)
|
111
|
+
|
112
|
+
add_offense(range, range, MSG_UNNECESSARY)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def extra_space_range(t1, t2)
|
103
117
|
return if t1.pos.line != t2.pos.line
|
104
118
|
return if allow_for_alignment? && aligned_tok?(t2)
|
105
119
|
|
106
120
|
start_pos = t1.pos.end_pos
|
107
121
|
end_pos = t2.pos.begin_pos - 1
|
108
122
|
return if end_pos <= start_pos
|
109
|
-
return if ignored_range?(ast, start_pos)
|
110
|
-
|
111
|
-
range = Parser::Source::Range.new(processed_source.buffer,
|
112
|
-
start_pos, end_pos)
|
113
|
-
# Unary + doesn't appear as a token and needs special handling.
|
114
|
-
return if unary_plus_non_offense?(range)
|
115
123
|
|
116
|
-
|
124
|
+
yield range_between(start_pos, end_pos)
|
117
125
|
end
|
118
126
|
|
119
127
|
def aligned_tok?(token)
|
@@ -172,22 +180,25 @@ module RuboCop
|
|
172
180
|
token.type == :tEQL || token.type == :tOP_ASGN
|
173
181
|
end
|
174
182
|
|
175
|
-
def
|
183
|
+
def align_equal_signs(range, corrector)
|
176
184
|
lines = contiguous_assignment_lines(range)
|
177
185
|
tokens = @asgn_tokens.select { |t| lines.include?(t.pos.line) }
|
178
186
|
|
179
187
|
columns = tokens.map { |t| align_column(t) }
|
180
188
|
align_to = columns.max
|
181
189
|
|
182
|
-
tokens.each
|
183
|
-
|
184
|
-
|
190
|
+
tokens.each { |token| align_equal_sign(corrector, token, align_to) }
|
191
|
+
end
|
192
|
+
|
193
|
+
def align_equal_sign(corrector, token, align_to)
|
194
|
+
return unless @corrected.add?(token)
|
185
195
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
196
|
+
diff = align_to - token.pos.last_column
|
197
|
+
|
198
|
+
if diff > 0
|
199
|
+
corrector.insert_before(token.pos, ' ' * diff)
|
200
|
+
elsif diff < 0
|
201
|
+
corrector.remove_preceding(token.pos, -diff)
|
191
202
|
end
|
192
203
|
end
|
193
204
|
|
@@ -97,16 +97,7 @@ module RuboCop
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def match_namespace(node, namespace, expected)
|
100
|
-
|
101
|
-
|
102
|
-
match_partial = lambda do |ns|
|
103
|
-
next if ns.nil?
|
104
|
-
while ns
|
105
|
-
return expected.empty? || expected == [:Object] if ns.cbase_type?
|
106
|
-
ns, name = *ns
|
107
|
-
name == expected.last ? expected.pop : (return false)
|
108
|
-
end
|
109
|
-
end
|
100
|
+
match_partial = partial_matcher!(expected)
|
110
101
|
|
111
102
|
match_partial.call(namespace)
|
112
103
|
|
@@ -115,6 +106,24 @@ module RuboCop
|
|
115
106
|
match_partial.call(ancestor.defined_module)
|
116
107
|
end
|
117
108
|
|
109
|
+
match?(expected)
|
110
|
+
end
|
111
|
+
|
112
|
+
def partial_matcher!(expected)
|
113
|
+
lambda do |namespace|
|
114
|
+
while namespace
|
115
|
+
return match?(expected) if namespace.cbase_type?
|
116
|
+
|
117
|
+
namespace, name = *namespace
|
118
|
+
|
119
|
+
expected.pop if name == expected.last
|
120
|
+
end
|
121
|
+
|
122
|
+
false
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def match?(expected)
|
118
127
|
expected.empty? || expected == [:Object]
|
119
128
|
end
|
120
129
|
|
@@ -74,9 +74,8 @@ module RuboCop
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def base_range(send_node, arg_node)
|
77
|
-
|
78
|
-
|
79
|
-
arg_node.source_range.begin_pos)
|
77
|
+
range_between(send_node.source_range.begin_pos,
|
78
|
+
arg_node.source_range.begin_pos)
|
80
79
|
end
|
81
80
|
|
82
81
|
# Returns the column of the given range. For single line ranges, this
|
@@ -26,23 +26,27 @@ module RuboCop
|
|
26
26
|
return if block_length(node).zero?
|
27
27
|
|
28
28
|
method, _args, _body = *node
|
29
|
-
return unless method.
|
29
|
+
return unless method.send_type?
|
30
30
|
|
31
31
|
_receiver, method_name, *args = *method
|
32
32
|
return unless method_name == :each && args.empty?
|
33
33
|
|
34
34
|
if style == :for
|
35
|
-
|
36
|
-
range = Parser::Source::Range.new(processed_source.buffer,
|
37
|
-
end_pos - EACH_LENGTH,
|
38
|
-
end_pos)
|
39
|
-
add_offense(range, range, 'Prefer `for` over `each`.') do
|
40
|
-
opposite_style_detected
|
41
|
-
end
|
35
|
+
incorrect_style_detected(method)
|
42
36
|
else
|
43
37
|
correct_style_detected
|
44
38
|
end
|
45
39
|
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def incorrect_style_detected(method)
|
44
|
+
end_pos = method.source_range.end_pos
|
45
|
+
range = range_between(end_pos - EACH_LENGTH, end_pos)
|
46
|
+
add_offense(range, range, 'Prefer `for` over `each`.') do
|
47
|
+
opposite_style_detected
|
48
|
+
end
|
49
|
+
end
|
46
50
|
end
|
47
51
|
end
|
48
52
|
end
|
@@ -37,94 +37,60 @@ module RuboCop
|
|
37
37
|
# raise 'exception' if something
|
38
38
|
# ok
|
39
39
|
class GuardClause < Cop
|
40
|
-
include ConfigurableEnforcedStyle
|
41
40
|
include IfNode
|
42
41
|
include MinBodyLength
|
43
42
|
|
44
43
|
MSG = 'Use a guard clause instead of wrapping the code inside a ' \
|
45
44
|
'conditional expression.'.freeze
|
46
45
|
|
47
|
-
def_node_matcher :single_line_control_flow_exit?, <<-PATTERN
|
48
|
-
[{(send nil {:raise :fail} ...) return break next} single_line?]
|
49
|
-
PATTERN
|
50
|
-
|
51
46
|
def on_def(node)
|
52
47
|
_, _, body = *node
|
48
|
+
|
53
49
|
return unless body
|
54
50
|
|
55
|
-
if
|
56
|
-
|
51
|
+
if body.if_type?
|
52
|
+
check_ending_if(body)
|
57
53
|
elsif body.begin_type?
|
58
|
-
|
59
|
-
check_trailing_if(last_expr) if if?(last_expr)
|
54
|
+
check_ending_if(body.children.last)
|
60
55
|
end
|
61
56
|
end
|
62
57
|
|
63
58
|
def on_if(node)
|
64
|
-
return if
|
65
|
-
return unless any_single_line_control_flow_exit?(node)
|
66
|
-
return if line_too_long_when_corrected?(node)
|
59
|
+
return if accepted_form?(node) || !contains_guard_clause?(node)
|
67
60
|
|
68
61
|
add_offense(node, :keyword, MSG)
|
69
62
|
end
|
70
63
|
|
71
64
|
private
|
72
65
|
|
73
|
-
def
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
cond.multiline?
|
79
|
-
end
|
80
|
-
|
81
|
-
def any_single_line_control_flow_exit?(node)
|
82
|
-
_cond, body, else_body = *node
|
83
|
-
|
84
|
-
single_line_control_flow_exit?(body) ||
|
85
|
-
single_line_control_flow_exit?(else_body)
|
86
|
-
end
|
66
|
+
def check_ending_if(node)
|
67
|
+
return if !node.if_type? ||
|
68
|
+
accepted_form?(node, true) ||
|
69
|
+
!min_body_length?(node)
|
87
70
|
|
88
|
-
|
89
|
-
node && node.if_type?
|
90
|
-
end
|
91
|
-
|
92
|
-
def elsif?(node)
|
93
|
-
return false unless node.parent && node.parent.if_type?
|
94
|
-
_condition, _if_branch, else_branch = *node.parent
|
95
|
-
else_branch.equal?(node)
|
71
|
+
add_offense(node, :keyword, MSG)
|
96
72
|
end
|
97
73
|
|
98
|
-
def
|
99
|
-
|
74
|
+
def accepted_form?(node, ending = false)
|
75
|
+
condition, = *node
|
100
76
|
|
101
|
-
|
102
|
-
# discard modifier ifs and ternary_ops
|
103
|
-
return if modifier_if?(node) || ternary?(node)
|
104
|
-
return if cond.multiline?
|
105
|
-
# discard short ifs
|
106
|
-
return unless min_body_length?(node)
|
107
|
-
return if line_too_long_when_corrected?(node)
|
108
|
-
|
109
|
-
add_offense(node, :keyword, MSG)
|
77
|
+
ignored_node?(node, ending) || condition.multiline?
|
110
78
|
end
|
111
79
|
|
112
|
-
def
|
113
|
-
|
80
|
+
def ignored_node?(node, ending)
|
81
|
+
return true if modifier_if?(node) || ternary?(node)
|
114
82
|
|
115
|
-
if
|
116
|
-
|
83
|
+
if ending
|
84
|
+
if_else?(node)
|
117
85
|
else
|
118
|
-
|
86
|
+
!if_else?(node) || elsif?(node)
|
119
87
|
end
|
120
88
|
end
|
121
89
|
|
122
|
-
def
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
# 2 is for spaces on left and right of keyword
|
127
|
-
indent + (source + keyword + condition.source).length + 2 > max
|
90
|
+
def contains_guard_clause?(node)
|
91
|
+
_, body, else_body = *node
|
92
|
+
|
93
|
+
guard_clause?(body) || guard_clause?(else_body)
|
128
94
|
end
|
129
95
|
end
|
130
96
|
end
|
@@ -10,11 +10,64 @@ module RuboCop
|
|
10
10
|
# the use of the newer Ruby 1.9 syntax (when applicable).
|
11
11
|
#
|
12
12
|
# A separate offense is registered for each problematic pair.
|
13
|
+
#
|
14
|
+
# The supported styles are:
|
15
|
+
#
|
16
|
+
# * ruby19 - forces use of the 1.9 syntax (e.g. {a: 1}) when hashes have
|
17
|
+
# all symbols for keys
|
18
|
+
# * hash_rockets - forces use of hash rockets for all hashes
|
19
|
+
# * no_mixed_keys - simply checks for hashes with mixed syntaxes
|
20
|
+
# * ruby19_mixed_keys - forces use of ruby 1.9 syntax and forbids mixed
|
21
|
+
# syntax hashes
|
22
|
+
#
|
23
|
+
# @example
|
24
|
+
# "EnforcedStyle => 'ruby19'"
|
25
|
+
#
|
26
|
+
# @good
|
27
|
+
# {a: 2, b: 1}
|
28
|
+
# {:c => 2, 'd' => 2} # acceptable since 'd' isn't a symbol
|
29
|
+
# {d: 1, 'e' => 2} # technically not forbidden
|
30
|
+
#
|
31
|
+
# @bad
|
32
|
+
# {:a => 2}
|
33
|
+
# {b: 1, :c => 2}
|
34
|
+
#
|
35
|
+
# @example
|
36
|
+
# "EnforcedStyle => 'hash_rockets'"
|
37
|
+
#
|
38
|
+
# @good
|
39
|
+
# {:a => 1, :b => 2}
|
40
|
+
#
|
41
|
+
# @bad
|
42
|
+
# {a: 1, b: 2}
|
43
|
+
# {c: 1, 'd' => 5}
|
44
|
+
#
|
45
|
+
# @example
|
46
|
+
# "EnforcedStyle => 'no_mixed_keys'"
|
47
|
+
#
|
48
|
+
# @good
|
49
|
+
# {:a => 1, :b => 2}
|
50
|
+
# {c: 1, d: 2}
|
51
|
+
#
|
52
|
+
# @bad
|
53
|
+
# {:a => 1, b: 2}
|
54
|
+
# {c: 1, 'd' => 2}
|
55
|
+
#
|
56
|
+
# @example
|
57
|
+
# "EnforcedStyle => 'ruby19_no_mixed_keys'"
|
58
|
+
#
|
59
|
+
# @good
|
60
|
+
# {a: 1, b: 2}
|
61
|
+
# {:c => 3, 'd' => 4}
|
62
|
+
#
|
63
|
+
# @bad
|
64
|
+
# {:a => 1, :b => 2}
|
65
|
+
# {c: 2, 'd' => 3} # should just use hash rockets
|
13
66
|
class HashSyntax < Cop
|
14
67
|
include ConfigurableEnforcedStyle
|
15
68
|
|
16
69
|
MSG_19 = 'Use the new Ruby 1.9 hash syntax.'.freeze
|
17
|
-
|
70
|
+
MSG_NO_MIXED_KEYS = "Don't mix styles in the same hash.".freeze
|
18
71
|
MSG_HASH_ROCKETS = 'Use hash rockets syntax.'.freeze
|
19
72
|
|
20
73
|
@force_hash_rockets = false
|
@@ -29,6 +82,8 @@ module RuboCop
|
|
29
82
|
hash_rockets_check(node)
|
30
83
|
elsif style == :ruby19_no_mixed_keys
|
31
84
|
ruby19_no_mixed_keys_check(node)
|
85
|
+
elsif style == :no_mixed_keys
|
86
|
+
no_mixed_keys_check(node)
|
32
87
|
else
|
33
88
|
ruby19_check(node)
|
34
89
|
end
|
@@ -54,7 +109,18 @@ module RuboCop
|
|
54
109
|
elsif sym_indices?(pairs)
|
55
110
|
check(pairs, '=>', MSG_19)
|
56
111
|
else
|
57
|
-
check(pairs, ':',
|
112
|
+
check(pairs, ':', MSG_NO_MIXED_KEYS)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def no_mixed_keys_check(node)
|
117
|
+
pairs = *node
|
118
|
+
|
119
|
+
if !sym_indices?(pairs)
|
120
|
+
check(pairs, ':', MSG_NO_MIXED_KEYS)
|
121
|
+
else
|
122
|
+
delim = pairs.first.loc.operator.source == ':' ? '=>' : ':'
|
123
|
+
check(pairs, delim, MSG_NO_MIXED_KEYS)
|
58
124
|
end
|
59
125
|
end
|
60
126
|
|
@@ -62,8 +128,8 @@ module RuboCop
|
|
62
128
|
lambda do |corrector|
|
63
129
|
if style == :hash_rockets || @force_hash_rockets
|
64
130
|
autocorrect_hash_rockets(corrector, node)
|
65
|
-
elsif style == :ruby19_no_mixed_keys
|
66
|
-
|
131
|
+
elsif style == :ruby19_no_mixed_keys || style == :no_mixed_keys
|
132
|
+
autocorrect_no_mixed_keys(corrector, node)
|
67
133
|
else
|
68
134
|
autocorrect_ruby19(corrector, node)
|
69
135
|
end
|
@@ -134,8 +200,7 @@ module RuboCop
|
|
134
200
|
key = node.children.first.source_range
|
135
201
|
op = node.loc.operator
|
136
202
|
|
137
|
-
range =
|
138
|
-
key.begin_pos, op.end_pos)
|
203
|
+
range = range_between(key.begin_pos, op.end_pos)
|
139
204
|
range = range_with_surrounding_space(range, :right)
|
140
205
|
corrector.replace(range,
|
141
206
|
range.source.sub(/^:(.*\S)\s*=>\s*$/, '\1: '))
|
@@ -150,7 +215,7 @@ module RuboCop
|
|
150
215
|
corrector.remove(range_with_surrounding_space(op))
|
151
216
|
end
|
152
217
|
|
153
|
-
def
|
218
|
+
def autocorrect_no_mixed_keys(corrector, node)
|
154
219
|
op = node.loc.operator
|
155
220
|
|
156
221
|
if op.is?(':')
|