rubocop 0.41.2 → 0.42.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.

Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -3
  3. data/config/default.yml +13 -0
  4. data/config/disabled.yml +5 -0
  5. data/config/enabled.yml +20 -0
  6. data/lib/rubocop.rb +4 -0
  7. data/lib/rubocop/ast_node.rb +4 -3
  8. data/lib/rubocop/config.rb +1 -1
  9. data/lib/rubocop/config_loader.rb +2 -7
  10. data/lib/rubocop/cop/cop.rb +3 -3
  11. data/lib/rubocop/cop/lint/block_alignment.rb +18 -16
  12. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +34 -19
  13. data/lib/rubocop/cop/lint/next_without_accumulator.rb +9 -1
  14. data/lib/rubocop/cop/lint/shadowed_exception.rb +23 -3
  15. data/lib/rubocop/cop/lint/unneeded_disable.rb +1 -1
  16. data/lib/rubocop/cop/lint/useless_access_modifier.rb +41 -4
  17. data/lib/rubocop/cop/mixin/array_hash_indentation.rb +1 -1
  18. data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +1 -1
  19. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +3 -5
  20. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +4 -4
  21. data/lib/rubocop/cop/mixin/space_inside.rb +23 -8
  22. data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -1
  23. data/lib/rubocop/cop/offense.rb +33 -10
  24. data/lib/rubocop/cop/performance/case_when_splat.rb +16 -14
  25. data/lib/rubocop/cop/performance/sample.rb +0 -1
  26. data/lib/rubocop/cop/rails/save_bang.rb +77 -0
  27. data/lib/rubocop/cop/rails/validation.rb +15 -15
  28. data/lib/rubocop/cop/style/access_modifier_indentation.rb +1 -1
  29. data/lib/rubocop/cop/style/align_hash.rb +1 -1
  30. data/lib/rubocop/cop/style/block_comments.rb +1 -3
  31. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +19 -10
  32. data/lib/rubocop/cop/style/closing_parenthesis_indentation.rb +1 -1
  33. data/lib/rubocop/cop/style/comment_annotation.rb +14 -14
  34. data/lib/rubocop/cop/style/comment_indentation.rb +1 -1
  35. data/lib/rubocop/cop/style/conditional_assignment.rb +25 -26
  36. data/lib/rubocop/cop/style/dot_position.rb +24 -19
  37. data/lib/rubocop/cop/style/each_for_simple_loop.rb +22 -8
  38. data/lib/rubocop/cop/style/each_with_object.rb +11 -1
  39. data/lib/rubocop/cop/style/else_alignment.rb +1 -1
  40. data/lib/rubocop/cop/style/empty_lines.rb +22 -11
  41. data/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb +9 -6
  42. data/lib/rubocop/cop/style/empty_lines_around_block_body.rb +14 -14
  43. data/lib/rubocop/cop/style/empty_lines_around_class_body.rb +8 -5
  44. data/lib/rubocop/cop/style/empty_lines_around_method_body.rb +12 -8
  45. data/lib/rubocop/cop/style/empty_lines_around_module_body.rb +17 -4
  46. data/lib/rubocop/cop/style/empty_literal.rb +12 -7
  47. data/lib/rubocop/cop/style/for.rb +1 -1
  48. data/lib/rubocop/cop/style/indent_array.rb +1 -1
  49. data/lib/rubocop/cop/style/indent_hash.rb +1 -1
  50. data/lib/rubocop/cop/style/indentation_width.rb +1 -1
  51. data/lib/rubocop/cop/style/initial_indentation.rb +1 -1
  52. data/lib/rubocop/cop/style/lambda.rb +2 -3
  53. data/lib/rubocop/cop/style/method_call_parentheses.rb +6 -4
  54. data/lib/rubocop/cop/style/method_missing.rb +74 -0
  55. data/lib/rubocop/cop/style/multiline_method_call_indentation.rb +1 -1
  56. data/lib/rubocop/cop/style/multiline_operation_indentation.rb +1 -1
  57. data/lib/rubocop/cop/style/nested_modifier.rb +23 -13
  58. data/lib/rubocop/cop/style/next.rb +1 -1
  59. data/lib/rubocop/cop/style/numeric_predicate.rb +142 -0
  60. data/lib/rubocop/cop/style/op_method.rb +12 -4
  61. data/lib/rubocop/cop/style/parallel_assignment.rb +11 -3
  62. data/lib/rubocop/cop/style/rescue_ensure_alignment.rb +9 -6
  63. data/lib/rubocop/cop/style/single_line_block_params.rb +3 -2
  64. data/lib/rubocop/cop/style/space_inside_block_braces.rb +1 -1
  65. data/lib/rubocop/cop/style/space_inside_string_interpolation.rb +1 -1
  66. data/lib/rubocop/cop/style/symbol_array.rb +18 -10
  67. data/lib/rubocop/cop/style/ternary_parentheses.rb +94 -0
  68. data/lib/rubocop/cop/style/trailing_blank_lines.rb +1 -1
  69. data/lib/rubocop/cop/style/unneeded_percent_q.rb +12 -6
  70. data/lib/rubocop/cop/util.rb +1 -1
  71. data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
  72. data/lib/rubocop/cop/variable_force/locatable.rb +1 -1
  73. data/lib/rubocop/formatter/disabled_config_formatter.rb +18 -7
  74. data/lib/rubocop/formatter/html_formatter.rb +25 -11
  75. data/lib/rubocop/formatter/text_util.rb +1 -1
  76. data/lib/rubocop/node_pattern.rb +2 -0
  77. data/lib/rubocop/processed_source.rb +3 -0
  78. data/lib/rubocop/rake_task.rb +1 -1
  79. data/lib/rubocop/rspec/shared_contexts.rb +4 -0
  80. data/lib/rubocop/runner.rb +18 -7
  81. data/lib/rubocop/string_util.rb +2 -5
  82. data/lib/rubocop/version.rb +1 -1
  83. metadata +7 -3
@@ -56,7 +56,7 @@ module RuboCop
56
56
 
57
57
  correct_column = expected_column(node, elements)
58
58
  @column_delta = correct_column - right_paren.column
59
- return if @column_delta == 0
59
+ return if @column_delta.zero?
60
60
 
61
61
  left_paren = node.loc.begin
62
62
  msg = correct_column == left_paren.column ? MSG_ALIGN : MSG_INDENT
@@ -23,7 +23,7 @@ module RuboCop
23
23
  next unless annotation?(comment) &&
24
24
  !correct_annotation?(first_word, colon, space, note)
25
25
 
26
- length = first_word.length + colon.to_s.length + space.to_s.length
26
+ length = concat_length(first_word, colon, space)
27
27
  add_offense(comment, annotation_range(comment, margin, length),
28
28
  format(note ? MSG : MISSING_NOTE, first_word))
29
29
  end
@@ -32,7 +32,17 @@ module RuboCop
32
32
  private
33
33
 
34
34
  def first_comment_line?(comments, ix)
35
- ix == 0 || comments[ix - 1].loc.line < comments[ix].loc.line - 1
35
+ ix.zero? || comments[ix - 1].loc.line < comments[ix].loc.line - 1
36
+ end
37
+
38
+ def autocorrect(comment)
39
+ margin, first_word, colon, space, note = split_comment(comment)
40
+ return if note.nil?
41
+
42
+ length = concat_length(first_word, colon, space)
43
+ range = annotation_range(comment, margin, length)
44
+
45
+ ->(corrector) { corrector.replace(range, "#{first_word.upcase}: ") }
36
46
  end
37
47
 
38
48
  def annotation_range(comment, margin, length)
@@ -41,18 +51,8 @@ module RuboCop
41
51
  Parser::Source::Range.new(source_buffer, start, start + length)
42
52
  end
43
53
 
44
- def autocorrect(comment)
45
- margin, first_word, colon, space, note = split_comment(comment)
46
- start = comment.loc.expression.begin_pos + margin.length
47
- return if note.nil?
48
-
49
- lambda do |corrector|
50
- length = first_word.length + colon.to_s.length + space.to_s.length
51
- range = Parser::Source::Range.new(comment.loc.expression.source,
52
- start,
53
- start + length)
54
- corrector.replace(range, "#{first_word.upcase}: ")
55
- end
54
+ def concat_length(*args)
55
+ args.reduce(0) { |a, e| a + e.to_s.length }
56
56
  end
57
57
 
58
58
  def correct_annotation?(first_word, colon, space, note)
@@ -24,7 +24,7 @@ module RuboCop
24
24
  column = comment.loc.column
25
25
 
26
26
  @column_delta = correct_comment_indentation - column
27
- return if @column_delta == 0
27
+ return if @column_delta.zero?
28
28
 
29
29
  if two_alternatives?(next_line)
30
30
  # Try the other
@@ -420,6 +420,21 @@ module RuboCop
420
420
  condition.loc.expression.begin_pos)
421
421
  end
422
422
 
423
+ def correct_if_branches(corrector, cop, node)
424
+ if_branch, elsif_branches, else_branch = extract_tail_branches(node)
425
+
426
+ corrector.insert_before(node.source_range, lhs(if_branch))
427
+ replace_branch_assignment(corrector, if_branch)
428
+ correct_branches(corrector, elsif_branches)
429
+ replace_branch_assignment(corrector, else_branch)
430
+ corrector.insert_before(node.loc.end, indent(cop, lhs(if_branch)))
431
+ end
432
+
433
+ def replace_branch_assignment(corrector, branch)
434
+ _variable, *_operator, assignment = *branch
435
+ corrector.replace(branch.source_range, assignment.source)
436
+ end
437
+
423
438
  def correct_branches(corrector, branches)
424
439
  branches.each do |branch|
425
440
  *_, assignment = *branch
@@ -495,18 +510,7 @@ module RuboCop
495
510
  include ConditionalCorrectorHelper
496
511
 
497
512
  def correct(cop, node)
498
- if_branch, elsif_branches, else_branch = extract_tail_branches(node)
499
- _variable, *_operator, if_assignment = *if_branch
500
- _else_variable, *_operator, else_assignment = *else_branch
501
-
502
- lambda do |corrector|
503
- corrector.insert_before(node.source_range, lhs(if_branch))
504
- corrector.replace(if_branch.source_range, if_assignment.source)
505
- correct_branches(corrector, elsif_branches)
506
- corrector.replace(else_branch.source_range,
507
- else_assignment.source)
508
- corrector.insert_before(node.loc.end, indent(cop, lhs(if_branch)))
509
- end
513
+ ->(corrector) { correct_if_branches(corrector, cop, node) }
510
514
  end
511
515
 
512
516
  def move_assignment_inside_condition(node)
@@ -562,13 +566,11 @@ module RuboCop
562
566
 
563
567
  def correct(cop, node)
564
568
  when_branches, else_branch = extract_tail_branches(node)
565
- _variable, *_operator, else_assignment = *else_branch
566
569
 
567
570
  lambda do |corrector|
568
571
  corrector.insert_before(node.source_range, lhs(else_branch))
569
572
  correct_branches(corrector, when_branches)
570
- corrector.replace(else_branch.source_range,
571
- else_assignment.source)
573
+ replace_branch_assignment(corrector, else_branch)
572
574
 
573
575
  corrector.insert_before(node.loc.end,
574
576
  indent(cop, lhs(else_branch)))
@@ -623,21 +625,18 @@ module RuboCop
623
625
  class UnlessCorrector
624
626
  class << self
625
627
  include ConditionalAssignmentHelper
628
+ include ConditionalCorrectorHelper
626
629
 
627
630
  def correct(cop, node)
631
+ ->(corrector) { correct_if_branches(corrector, cop, node) }
632
+ end
633
+
634
+ private
635
+
636
+ def extract_tail_branches(node)
628
637
  _condition, else_branch, if_branch = *node
629
- if_branch = tail(if_branch)
630
- else_branch = tail(else_branch)
631
- _variable, *_operator, if_assignment = *if_branch
632
- _else_variable, *_operator, else_assignment = *else_branch
633
638
 
634
- lambda do |corrector|
635
- corrector.insert_before(node.source_range, lhs(if_branch))
636
- corrector.replace(if_branch.source_range, if_assignment.source)
637
- corrector.replace(else_branch.source_range,
638
- else_assignment.source)
639
- corrector.insert_before(node.loc.end, indent(cop, lhs(if_branch)))
640
- end
639
+ [tail(if_branch), [], tail(else_branch)]
641
640
  end
642
641
  end
643
642
  end
@@ -34,25 +34,27 @@ module RuboCop
34
34
  receiver, _method_name, *_args = *node
35
35
 
36
36
  receiver_line = receiver.source_range.end.line
37
-
38
- if node.loc.selector
39
- selector_line = node.loc.selector.line
40
- else
41
- # l.(1) has no selector, so we use the opening parenthesis instead
42
- selector_line = node.loc.begin.line
43
- end
37
+ selector_line = selector_range(node).line
44
38
 
45
39
  # receiver and selector are on the same line
46
40
  return true if selector_line == receiver_line
47
41
 
48
42
  dot_line = node.loc.dot.line
49
43
 
50
- # don't register an offense if there is a line comment between
51
- # the dot and the selector
52
- # otherwise, we might break the code while "correcting" it
53
- # (even if there is just an extra blank line, treat it the same)
54
- return true if (selector_line - dot_line) > 1
44
+ # don't register an offense if there is a line comment between the
45
+ # dot and the selector otherwise, we might break the code while
46
+ # "correcting" it (even if there is just an extra blank line, treat
47
+ # it the same)
48
+ return true if line_between?(selector_line, dot_line)
55
49
 
50
+ correct_dot_position_style?(dot_line, selector_line)
51
+ end
52
+
53
+ def line_between?(first_line, second_line)
54
+ (first_line - second_line) > 1
55
+ end
56
+
57
+ def correct_dot_position_style?(dot_line, selector_line)
56
58
  case style
57
59
  when :leading then dot_line == selector_line
58
60
  when :trailing then dot_line != selector_line
@@ -61,23 +63,26 @@ module RuboCop
61
63
 
62
64
  def autocorrect(node)
63
65
  receiver, _method_name, *_args = *node
64
- if node.loc.selector
65
- selector = node.loc.selector
66
- else
67
- # l.(1) has no selector, so we use the opening parenthesis instead
68
- selector = node.loc.begin
69
- end
70
66
 
71
67
  lambda do |corrector|
72
68
  corrector.remove(node.loc.dot)
73
69
  case style
74
70
  when :leading
75
- corrector.insert_before(selector, '.')
71
+ corrector.insert_before(selector_range(node), '.')
76
72
  when :trailing
77
73
  corrector.insert_after(receiver.source_range, '.')
78
74
  end
79
75
  end
80
76
  end
77
+
78
+ def selector_range(node)
79
+ if node.loc.selector
80
+ node.loc.selector
81
+ else
82
+ # l.(1) has no selector, so we use the opening parenthesis instead
83
+ node.loc.begin
84
+ end
85
+ end
81
86
  end
82
87
  end
83
88
  end
@@ -12,30 +12,44 @@ module RuboCop
12
12
  #
13
13
  # @example
14
14
  # @bad
15
- # (0..10).each { }
15
+ # (1..5).each { }
16
16
  #
17
17
  # @good
18
- # 10.times { }
18
+ # 5.times { }
19
+ #
20
+ # @example
21
+ # @bad
22
+ # (0...10).each {}
23
+ #
24
+ # @good
25
+ # 10.times {}
19
26
  class EachForSimpleLoop < Cop
27
+ MSG = 'Use `Integer#times` for a simple loop which iterates a fixed ' \
28
+ 'number of times.'.freeze
29
+
20
30
  def on_block(node)
21
- if bad_each_range(node)
31
+ if offending_each_range(node)
22
32
  send_node, = *node
23
33
  range = send_node.receiver.source_range.join(send_node.loc.selector)
24
- add_offense(node, range, 'Use `Integer#times` for a simple loop ' \
25
- 'which iterates a fixed number of times.')
34
+ add_offense(node, range)
26
35
  end
27
36
  end
28
37
 
38
+ private
39
+
29
40
  def autocorrect(node)
30
41
  lambda do |corrector|
31
- min, max = bad_each_range(node)
42
+ range_type, min, max = offending_each_range(node)
43
+
44
+ max += 1 if range_type == :irange
45
+
32
46
  corrector.replace(node.children.first.source_range,
33
47
  "#{max - min}.times")
34
48
  end
35
49
  end
36
50
 
37
- def_node_matcher :bad_each_range, <<-PATTERN
38
- (block (send (begin ({irange erange} (int $_) (int $_))) :each) (args) ...)
51
+ def_node_matcher :offending_each_range, <<-PATTERN
52
+ (block (send (begin (${irange erange} (int $_) (int $_))) :each) (args) ...)
39
53
  PATTERN
40
54
  end
41
55
  end
@@ -33,7 +33,17 @@ module RuboCop
33
33
  return unless first_argument_returned?(args, return_value)
34
34
  return if accumulator_param_assigned_to?(body, args)
35
35
 
36
- add_offense(method, :selector, format(MSG, method_name))
36
+ add_offense(node, method.loc.selector, format(MSG, method_name))
37
+ end
38
+
39
+ def autocorrect(node)
40
+ lambda do |corrector|
41
+ method, args, _body = *node
42
+ corrector.replace(method.loc.selector, 'each_with_object')
43
+ first_arg, second_arg = *args
44
+ corrector.replace(first_arg.loc.expression, second_arg.source)
45
+ corrector.replace(second_arg.loc.expression, first_arg.source)
46
+ end
37
47
  end
38
48
 
39
49
  private
@@ -100,7 +100,7 @@ module RuboCop
100
100
  return unless begins_its_line?(else_range)
101
101
 
102
102
  @column_delta = effective_column(base_range) - else_range.column
103
- return if @column_delta == 0
103
+ return if @column_delta.zero?
104
104
 
105
105
  add_offense(else_range, else_range,
106
106
  format(MSG, else_range.source, base_range.source[/^\S*/]))
@@ -19,21 +19,28 @@ module RuboCop
19
19
  lines << token.pos.line
20
20
  end
21
21
 
22
- prev_line = 1
22
+ each_extra_empty_line(lines.sort) do |range|
23
+ add_offense(range, range)
24
+ end
25
+ end
26
+
27
+ def autocorrect(range)
28
+ ->(corrector) { corrector.remove(range) }
29
+ end
23
30
 
24
- lines.sort.each do |cur_line|
25
- line_diff = cur_line - prev_line
31
+ private
26
32
 
27
- if line_diff > LINE_OFFSET
33
+ def each_extra_empty_line(lines)
34
+ prev_line = 1
35
+
36
+ lines.each do |cur_line|
37
+ if exceeds_line_offset?(cur_line - prev_line)
28
38
  # we need to be wary of comments since they
29
39
  # don't show up in the tokens
30
40
  ((prev_line + 1)...cur_line).each do |line|
31
- # we check if the prev and current lines are empty
32
- next unless processed_source[line - 2].empty? &&
33
- processed_source[line - 1].empty?
41
+ next unless previous_and_current_lines_empty?(line)
34
42
 
35
- range = source_range(processed_source.buffer, line, 0)
36
- add_offense(range, range)
43
+ yield source_range(processed_source.buffer, line, 0)
37
44
  end
38
45
  end
39
46
 
@@ -41,8 +48,12 @@ module RuboCop
41
48
  end
42
49
  end
43
50
 
44
- def autocorrect(range)
45
- ->(corrector) { corrector.remove(range) }
51
+ def exceeds_line_offset?(line_diff)
52
+ line_diff > LINE_OFFSET
53
+ end
54
+
55
+ def previous_and_current_lines_empty?(line)
56
+ processed_source[line - 2].empty? && processed_source[line - 1].empty?
46
57
  end
47
58
  end
48
59
  end
@@ -23,12 +23,7 @@ module RuboCop
23
23
  send_line = node.loc.line
24
24
  previous_line = processed_source[send_line - 2]
25
25
  next_line = processed_source[send_line]
26
-
27
- line = Parser::Source::Range.new(
28
- processed_source.buffer,
29
- node.source_range.begin_pos - node.loc.column,
30
- node.source_range.end_pos
31
- )
26
+ line = line_range(node)
32
27
 
33
28
  unless previous_line_empty?(previous_line)
34
29
  corrector.insert_before(line, "\n")
@@ -42,6 +37,14 @@ module RuboCop
42
37
 
43
38
  private
44
39
 
40
+ def line_range(node)
41
+ Parser::Source::Range.new(
42
+ processed_source.buffer,
43
+ node.source_range.begin_pos - node.loc.column,
44
+ node.source_range.end_pos
45
+ )
46
+ end
47
+
45
48
  def previous_line_ignoring_comments(processed_source, send_line)
46
49
  processed_source[0..send_line - 2].reverse.find do |line|
47
50
  !comment_line?(line)
@@ -9,11 +9,23 @@ module RuboCop
9
9
  #
10
10
  # @example
11
11
  #
12
- # something do
12
+ # # EnforcedStyle: empty_lines
13
+ #
14
+ # # good
15
+ #
16
+ # foo do |bar|
13
17
  #
14
18
  # ...
19
+ #
15
20
  # end
16
21
  #
22
+ # # EnforcedStyle: no_empty_lines
23
+ #
24
+ # # good
25
+ #
26
+ # foo do |bar|
27
+ # ...
28
+ # end
17
29
  class EmptyLinesAroundBlockBody < Cop
18
30
  include EmptyLinesAroundBody
19
31
 
@@ -21,20 +33,8 @@ module RuboCop
21
33
 
22
34
  def on_block(node)
23
35
  _send, _args, body = *node
24
- check(node, body)
25
- end
26
-
27
- private
28
-
29
- def check(node, body)
30
- return unless body || style == :no_empty_lines
31
36
 
32
- start_line = node.loc.begin.line
33
- end_line = node.loc.end.line
34
-
35
- return if start_line == end_line
36
-
37
- check_source(start_line, end_line)
37
+ check(node, body)
38
38
  end
39
39
  end
40
40
  end
@@ -4,19 +4,22 @@
4
4
  module RuboCop
5
5
  module Cop
6
6
  module Style
7
- # This cops checks if empty lines around the bodies of classes match the
8
- # configuration.
7
+ # This cops checks if empty lines around the bodies of classes match
8
+ # the configuration.
9
9
  #
10
10
  # @example
11
11
  #
12
- # class Test
12
+ # EnforcedStyle: empty_lines
13
13
  #
14
- # def something
14
+ # # good
15
+ #
16
+ # class Foo
17
+ #
18
+ # def bar
15
19
  # ...
16
20
  # end
17
21
  #
18
22
  # end
19
- #
20
23
  class EmptyLinesAroundClassBody < Cop
21
24
  include EmptyLinesAroundBody
22
25