rubocop 0.67.2 → 0.68.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.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +86 -233
  4. data/exe/rubocop +0 -12
  5. data/lib/rubocop.rb +13 -30
  6. data/lib/rubocop/ast/builder.rb +4 -0
  7. data/lib/rubocop/ast/node/alias_node.rb +24 -0
  8. data/lib/rubocop/ast/node/class_node.rb +31 -0
  9. data/lib/rubocop/ast/node/module_node.rb +24 -0
  10. data/lib/rubocop/ast/node/range_node.rb +7 -0
  11. data/lib/rubocop/ast/node/resbody_node.rb +12 -0
  12. data/lib/rubocop/ast/node/self_class_node.rb +24 -0
  13. data/lib/rubocop/cli.rb +40 -4
  14. data/lib/rubocop/config.rb +9 -7
  15. data/lib/rubocop/config_loader.rb +48 -7
  16. data/lib/rubocop/config_loader_resolver.rb +5 -4
  17. data/lib/rubocop/cop/commissioner.rb +24 -0
  18. data/lib/rubocop/cop/correctors/unused_arg_corrector.rb +18 -6
  19. data/lib/rubocop/cop/internal_affairs/node_destructuring.rb +12 -14
  20. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +9 -20
  21. data/lib/rubocop/cop/layout/align_arguments.rb +93 -0
  22. data/lib/rubocop/cop/layout/align_parameters.rb +57 -33
  23. data/lib/rubocop/cop/layout/class_structure.rb +5 -5
  24. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +6 -8
  25. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +3 -6
  26. data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +1 -2
  27. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +1 -0
  28. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +292 -0
  29. data/lib/rubocop/cop/layout/{first_parameter_indentation.rb → indent_first_argument.rb} +11 -12
  30. data/lib/rubocop/cop/layout/{indent_array.rb → indent_first_array_element.rb} +2 -2
  31. data/lib/rubocop/cop/layout/{indent_hash.rb → indent_first_hash_element.rb} +2 -2
  32. data/lib/rubocop/cop/layout/indent_first_parameter.rb +96 -0
  33. data/lib/rubocop/cop/layout/indentation_width.rb +4 -16
  34. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +2 -4
  35. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +1 -16
  36. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +1 -2
  37. data/lib/rubocop/cop/lint/duplicate_methods.rb +6 -8
  38. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +4 -8
  39. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +157 -0
  40. data/lib/rubocop/cop/lint/inherit_exception.rb +3 -4
  41. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +18 -1
  42. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -5
  43. data/lib/rubocop/cop/lint/underscore_prefixed_variable_name.rb +25 -5
  44. data/lib/rubocop/cop/lint/useless_assignment.rb +2 -6
  45. data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -2
  46. data/lib/rubocop/cop/message_annotator.rb +1 -0
  47. data/lib/rubocop/cop/metrics/line_length.rb +139 -28
  48. data/lib/rubocop/cop/metrics/perceived_complexity.rb +3 -4
  49. data/lib/rubocop/cop/mixin/check_line_breakable.rb +190 -0
  50. data/lib/rubocop/cop/mixin/{array_hash_indentation.rb → multiline_element_indentation.rb} +3 -2
  51. data/lib/rubocop/cop/mixin/too_many_lines.rb +3 -7
  52. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +33 -4
  53. data/lib/rubocop/cop/rails/active_record_override.rb +23 -8
  54. data/lib/rubocop/cop/rails/delegate.rb +5 -8
  55. data/lib/rubocop/cop/rails/environment_comparison.rb +5 -3
  56. data/lib/rubocop/cop/rails/find_each.rb +1 -1
  57. data/lib/rubocop/cop/rails/redundant_allow_nil.rb +3 -3
  58. data/lib/rubocop/cop/rails/reflection_class_name.rb +1 -1
  59. data/lib/rubocop/cop/rails/skips_model_validations.rb +6 -7
  60. data/lib/rubocop/cop/rails/time_zone.rb +3 -10
  61. data/lib/rubocop/cop/rails/validation.rb +3 -0
  62. data/lib/rubocop/cop/registry.rb +3 -3
  63. data/lib/rubocop/cop/style/alias.rb +13 -7
  64. data/lib/rubocop/cop/style/block_delimiters.rb +20 -0
  65. data/lib/rubocop/cop/style/class_and_module_children.rb +19 -21
  66. data/lib/rubocop/cop/style/class_methods.rb +16 -24
  67. data/lib/rubocop/cop/style/conditional_assignment.rb +20 -49
  68. data/lib/rubocop/cop/style/documentation.rb +3 -7
  69. data/lib/rubocop/cop/style/format_string.rb +18 -21
  70. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  71. data/lib/rubocop/cop/style/inverse_methods.rb +4 -0
  72. data/lib/rubocop/cop/style/lambda.rb +12 -8
  73. data/lib/rubocop/cop/style/mixin_grouping.rb +8 -10
  74. data/lib/rubocop/cop/style/module_function.rb +2 -3
  75. data/lib/rubocop/cop/style/next.rb +10 -14
  76. data/lib/rubocop/cop/style/one_line_conditional.rb +5 -3
  77. data/lib/rubocop/cop/style/optional_arguments.rb +1 -4
  78. data/lib/rubocop/cop/style/random_with_offset.rb +44 -47
  79. data/lib/rubocop/cop/style/redundant_return.rb +6 -14
  80. data/lib/rubocop/cop/style/redundant_sort_by.rb +1 -1
  81. data/lib/rubocop/cop/style/safe_navigation.rb +3 -0
  82. data/lib/rubocop/cop/style/struct_inheritance.rb +2 -3
  83. data/lib/rubocop/cop/style/symbol_proc.rb +20 -40
  84. data/lib/rubocop/cop/style/unless_else.rb +1 -2
  85. data/lib/rubocop/cop/style/yoda_condition.rb +8 -7
  86. data/lib/rubocop/cop/util.rb +2 -4
  87. data/lib/rubocop/file_finder.rb +5 -10
  88. data/lib/rubocop/formatter/disabled_config_formatter.rb +5 -0
  89. data/lib/rubocop/node_pattern.rb +304 -170
  90. data/lib/rubocop/options.rb +4 -1
  91. data/lib/rubocop/rspec/shared_contexts.rb +3 -0
  92. data/lib/rubocop/version.rb +1 -1
  93. data/lib/rubocop/yaml_duplication_checker.rb +1 -1
  94. metadata +26 -50
  95. data/lib/rubocop/cop/performance/caller.rb +0 -69
  96. data/lib/rubocop/cop/performance/case_when_splat.rb +0 -177
  97. data/lib/rubocop/cop/performance/casecmp.rb +0 -108
  98. data/lib/rubocop/cop/performance/chain_array_allocation.rb +0 -78
  99. data/lib/rubocop/cop/performance/compare_with_block.rb +0 -122
  100. data/lib/rubocop/cop/performance/count.rb +0 -102
  101. data/lib/rubocop/cop/performance/detect.rb +0 -110
  102. data/lib/rubocop/cop/performance/double_start_end_with.rb +0 -94
  103. data/lib/rubocop/cop/performance/end_with.rb +0 -56
  104. data/lib/rubocop/cop/performance/fixed_size.rb +0 -97
  105. data/lib/rubocop/cop/performance/flat_map.rb +0 -78
  106. data/lib/rubocop/cop/performance/inefficient_hash_search.rb +0 -99
  107. data/lib/rubocop/cop/performance/open_struct.rb +0 -46
  108. data/lib/rubocop/cop/performance/range_include.rb +0 -50
  109. data/lib/rubocop/cop/performance/redundant_block_call.rb +0 -93
  110. data/lib/rubocop/cop/performance/redundant_match.rb +0 -56
  111. data/lib/rubocop/cop/performance/redundant_merge.rb +0 -183
  112. data/lib/rubocop/cop/performance/regexp_match.rb +0 -265
  113. data/lib/rubocop/cop/performance/reverse_each.rb +0 -42
  114. data/lib/rubocop/cop/performance/size.rb +0 -77
  115. data/lib/rubocop/cop/performance/start_with.rb +0 -59
  116. data/lib/rubocop/cop/performance/string_replacement.rb +0 -173
  117. data/lib/rubocop/cop/performance/times_map.rb +0 -71
  118. data/lib/rubocop/cop/performance/unfreeze_string.rb +0 -50
  119. data/lib/rubocop/cop/performance/uri_default_parser.rb +0 -47
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Layout
6
+ # This cop checks the indentation of the first parameter in a method call.
7
+ # Parameters after the first one are checked by Layout/AlignParameters,
8
+ # not by this cop.
9
+ #
10
+ # @example
11
+ #
12
+ # # bad
13
+ # def some_method(
14
+ # first_param,
15
+ # second_param)
16
+ # 123
17
+ # end
18
+ #
19
+ # @example EnforcedStyle: consistent
20
+ # # The first parameter should always be indented one step more than the
21
+ # # preceding line.
22
+ #
23
+ # # good
24
+ # def some_method(
25
+ # first_param,
26
+ # second_param)
27
+ # 123
28
+ # end
29
+ #
30
+ # @example EnforcedStyle: align_parentheses
31
+ # # The first parameter should always be indented one step more than the
32
+ # # opening parenthesis.
33
+ #
34
+ # # good
35
+ # def some_method(
36
+ # first_param,
37
+ # second_param)
38
+ # 123
39
+ # end
40
+ class IndentFirstParameter < Cop
41
+ include Alignment
42
+ include ConfigurableEnforcedStyle
43
+ include MultilineElementIndentation
44
+
45
+ MSG = 'Use %<configured_indentation_width>d spaces for indentation ' \
46
+ 'in method args, relative to %<base_description>s.'.freeze
47
+
48
+ def on_def(node)
49
+ return if node.arguments.empty?
50
+ return if node.arguments.loc.begin.nil?
51
+
52
+ check(node)
53
+ end
54
+ alias on_defs on_def
55
+
56
+ def autocorrect(node)
57
+ AlignmentCorrector.correct(processed_source, node, @column_delta)
58
+ end
59
+
60
+ private
61
+
62
+ def brace_alignment_style
63
+ :align_parentheses
64
+ end
65
+
66
+ def check(def_node)
67
+ return if ignored_node?(def_node)
68
+
69
+ left_parenthesis = def_node.arguments.loc.begin
70
+ first_elem = def_node.arguments.first
71
+ return unless first_elem
72
+ return if first_elem.source_range.line == left_parenthesis.line
73
+
74
+ check_first(first_elem, left_parenthesis, nil, 0)
75
+ end
76
+
77
+ # Returns the description of what the correct indentation is based on.
78
+ def base_description(_)
79
+ if style == brace_alignment_style
80
+ 'the position of the opening parenthesis'
81
+ else
82
+ 'the start of the line where the left parenthesis is'
83
+ end
84
+ end
85
+
86
+ def message(base_description)
87
+ format(
88
+ MSG,
89
+ configured_indentation_width: configured_indentation_width,
90
+ base_description: base_description
91
+ )
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -90,28 +90,16 @@ module RuboCop
90
90
  check_members(end_loc, [node.body])
91
91
  end
92
92
 
93
- def on_module(node)
94
- _module_name, *members = *node
95
- check_members(node.loc.keyword, members)
96
- end
97
-
98
93
  def on_class(node)
99
- _class_name, _base_class, *members = *node
100
- check_members(node.loc.keyword, members)
101
- end
102
-
103
- def on_sclass(node)
104
- _class_name, *members = *node
105
-
106
- check_members(node.loc.keyword, members)
94
+ check_members(node.loc.keyword, [node.body])
107
95
  end
96
+ alias on_sclass on_class
97
+ alias on_module on_class
108
98
 
109
99
  def on_send(node)
110
100
  super
111
101
  return unless node.adjacent_def_modifier?
112
102
 
113
- *_, body = *node.first_argument
114
-
115
103
  def_end_config = config.for_cop('Layout/DefEndAlignment')
116
104
  style = def_end_config['EnforcedStyleAlignWith'] || 'start_of_line'
117
105
  base = if style == 'def'
@@ -120,7 +108,7 @@ module RuboCop
120
108
  leftmost_modifier_of(node) || node
121
109
  end
122
110
 
123
- check_indentation(base.source_range, body)
111
+ check_indentation(base.source_range, node.first_argument.body)
124
112
  ignore_node(node.first_argument)
125
113
  end
126
114
  alias on_csend on_send
@@ -201,10 +201,8 @@ module RuboCop
201
201
  end
202
202
 
203
203
  def operation_rhs(node)
204
- receiver, = *node
205
-
206
- operation_rhs = receiver.each_ancestor(:send).find do |rhs|
207
- operator_rhs?(rhs, receiver)
204
+ operation_rhs = node.receiver.each_ancestor(:send).find do |rhs|
205
+ operator_rhs?(rhs, node.receiver)
208
206
  end
209
207
 
210
208
  return unless operation_rhs
@@ -23,7 +23,6 @@ module RuboCop
23
23
  include ConfigurableEnforcedStyle
24
24
  include RangeHelp
25
25
 
26
- ARROW = '->'.freeze
27
26
  MSG_REQUIRE_SPACE = 'Use a space between `->` and ' \
28
27
  '`(` in lambda literals.'.freeze
29
28
  MSG_REQUIRE_NO_SPACE = 'Do not use spaces between `->` and ' \
@@ -59,21 +58,7 @@ module RuboCop
59
58
  private
60
59
 
61
60
  def arrow_lambda_with_args?(node)
62
- lambda_node?(node) && arrow_form?(node) && args?(node)
63
- end
64
-
65
- def lambda_node?(node)
66
- receiver, call = *node
67
- receiver.nil? && call == :lambda
68
- end
69
-
70
- def arrow_form?(lambda_node)
71
- lambda_node.loc.selector.source == ARROW
72
- end
73
-
74
- def args?(lambda_node)
75
- _call, args, _body = *lambda_node.parent
76
- !args.children.empty?
61
+ node.lambda_literal? && node.parent.arguments?
77
62
  end
78
63
 
79
64
  def space_after_arrow?(lambda_node)
@@ -108,8 +108,7 @@ module RuboCop
108
108
  end
109
109
 
110
110
  def bracket_method?(node)
111
- _, method, = *node
112
- BRACKET_METHODS.include?(method)
111
+ BRACKET_METHODS.include?(node.method_name)
113
112
  end
114
113
 
115
114
  def left_ref_bracket(node, tokens)
@@ -64,20 +64,18 @@ module RuboCop
64
64
  return if node.ancestors.any?(&:if_type?)
65
65
  return if possible_dsl?(node)
66
66
 
67
- name, = *node
68
- found_instance_method(node, name)
67
+ found_instance_method(node, node.method_name)
69
68
  end
70
69
 
71
70
  def on_defs(node)
72
71
  return if node.ancestors.any?(&:if_type?)
73
72
  return if possible_dsl?(node)
74
73
 
75
- receiver, name, = *node
76
- if receiver.const_type?
77
- _, const_name = *receiver
78
- check_const_receiver(node, name, const_name)
79
- elsif receiver.self_type?
80
- check_self_receiver(node, name)
74
+ if node.receiver.const_type?
75
+ _, const_name = *node.receiver
76
+ check_const_receiver(node, node.method_name, const_name)
77
+ elsif node.receiver.self_type?
78
+ check_self_receiver(node, node.method_name)
81
79
  end
82
80
  end
83
81
 
@@ -61,14 +61,10 @@ module RuboCop
61
61
  end
62
62
  end
63
63
 
64
- def called_on_string?(node)
65
- receiver_node, _method, format_string, = *node
66
- if receiver_node.nil? || receiver_node.const_type?
67
- format_string && format_string.str_type?
68
- else
69
- receiver_node.str_type?
70
- end
71
- end
64
+ def_node_matcher :called_on_string?, <<-PATTERN
65
+ {(send {nil? const_type?} _ (str _) ...)
66
+ (send (str ...) ...)}
67
+ PATTERN
72
68
 
73
69
  def method_with_format_args?(node)
74
70
  sprintf?(node) || format?(node) || percent?(node)
@@ -0,0 +1,157 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # This cop checks for the ordering of a method call where
7
+ # the receiver of the call is a HEREDOC.
8
+ #
9
+ # @example
10
+ # # bad
11
+ #
12
+ # <<-SQL
13
+ # bar
14
+ # SQL
15
+ # .strip_indent
16
+ #
17
+ # <<-SQL
18
+ # bar
19
+ # SQL
20
+ # .strip_indent
21
+ # .trim
22
+ #
23
+ # # good
24
+ #
25
+ # <<-SQL.strip_indent
26
+ # bar
27
+ # SQL
28
+ #
29
+ # <<-SQL.strip_indent.trim
30
+ # bar
31
+ # SQL
32
+ #
33
+ class HeredocMethodCallPosition < Cop
34
+ include RangeHelp
35
+
36
+ MSG = 'Put a method call with a HEREDOC receiver on the ' \
37
+ 'same line as the HEREDOC opening.'.freeze
38
+
39
+ STRING_TYPES = %i[str dstr xstr].freeze
40
+ def on_send(node)
41
+ heredoc = heredoc_node_descendent_receiver(node)
42
+ return unless heredoc
43
+ return if correctly_positioned?(node, heredoc)
44
+
45
+ add_offense(node, location: call_after_heredoc_range(heredoc))
46
+ end
47
+ alias on_csend on_send
48
+
49
+ def autocorrect(node)
50
+ heredoc = heredoc_node_descendent_receiver(node)
51
+
52
+ lambda do |corrector|
53
+ call_range = call_range_to_safely_reposition(node, heredoc)
54
+ return if call_range.nil?
55
+
56
+ call_source = call_range.source.strip
57
+ corrector.remove(call_range)
58
+ corrector.insert_after(heredoc_begin_line_range(node), call_source)
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ def heredoc_node_descendent_receiver(node)
65
+ while send_node?(node)
66
+ return node.receiver if heredoc_node?(node.receiver)
67
+
68
+ node = node.receiver
69
+ end
70
+ end
71
+
72
+ def send_node?(node)
73
+ return nil unless node
74
+
75
+ node.send_type? || node.csend_type?
76
+ end
77
+
78
+ def heredoc_node?(node)
79
+ node && STRING_TYPES.include?(node.type) && node.heredoc?
80
+ end
81
+
82
+ def call_after_heredoc_range(heredoc)
83
+ pos = heredoc_end_pos(heredoc)
84
+ range_between(pos + 1, pos + 2)
85
+ end
86
+
87
+ def correctly_positioned?(node, heredoc)
88
+ heredoc_end_pos(heredoc) > call_end_pos(node)
89
+ end
90
+
91
+ def calls_on_multiple_lines?(node, _heredoc)
92
+ last_line = node.last_line
93
+ while send_node?(node)
94
+ return true unless last_line == node.last_line
95
+ return true unless all_on_same_line?(node.arguments)
96
+
97
+ node = node.receiver
98
+ end
99
+ false
100
+ end
101
+
102
+ def all_on_same_line?(nodes)
103
+ return true if nodes.empty?
104
+
105
+ nodes.first.first_line == nodes.last.last_line
106
+ end
107
+
108
+ def heredoc_end_pos(heredoc)
109
+ heredoc.location.heredoc_end.end_pos
110
+ end
111
+
112
+ def call_end_pos(node)
113
+ node.source_range.end_pos
114
+ end
115
+
116
+ def heredoc_begin_line_range(heredoc)
117
+ pos = heredoc.source_range.begin_pos
118
+ range_by_whole_lines(range_between(pos, pos))
119
+ end
120
+
121
+ def call_line_range(node)
122
+ pos = node.source_range.end_pos
123
+ range_by_whole_lines(range_between(pos, pos))
124
+ end
125
+
126
+ # Returns nil if no range can be safely repositioned.
127
+ def call_range_to_safely_reposition(node, heredoc)
128
+ return nil if calls_on_multiple_lines?(node, heredoc)
129
+
130
+ heredoc_end_pos = heredoc_end_pos(heredoc)
131
+ call_end_pos = call_end_pos(node)
132
+
133
+ call_range = range_between(heredoc_end_pos, call_end_pos)
134
+ call_line_range = call_line_range(node)
135
+
136
+ call_source = call_range.source.strip
137
+ call_line_source = call_line_range.source.strip
138
+
139
+ return call_range if call_source == call_line_source
140
+
141
+ if trailing_comma?(call_source, call_line_source)
142
+ # If there's some on the last line other than the call, e.g.
143
+ # a trailing comma, then we leave the "\n" following the
144
+ # heredoc_end in place.
145
+ return range_between(heredoc_end_pos, call_end_pos + 1)
146
+ end
147
+
148
+ nil
149
+ end
150
+
151
+ def trailing_comma?(call_source, call_line_source)
152
+ call_source + ',' == call_line_source
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
@@ -48,11 +48,10 @@ module RuboCop
48
48
  ].freeze
49
49
 
50
50
  def on_class(node)
51
- _class, base_class, _body = *node
51
+ return unless node.parent_class &&
52
+ illegal_class_name?(node.parent_class)
52
53
 
53
- return unless base_class && illegal_class_name?(base_class)
54
-
55
- add_offense(base_class)
54
+ add_offense(node.parent_class)
56
55
  end
57
56
 
58
57
  def autocorrect(node)
@@ -18,6 +18,7 @@ module RuboCop
18
18
  # "result is 10"
19
19
  class LiteralInInterpolation < Cop
20
20
  include RangeHelp
21
+ include PercentLiteral
21
22
 
22
23
  MSG = 'Literal interpolation detected.'.freeze
23
24
  COMPOSITE = %i[array hash pair irange erange].freeze
@@ -55,14 +56,24 @@ module RuboCop
55
56
  when :float
56
57
  node.children.last.to_f.to_s
57
58
  when :str
58
- node.children.last
59
+ autocorrected_value_for_string(node)
59
60
  when :sym
60
61
  autocorrected_value_for_symbol(node)
62
+ when :array
63
+ autocorrected_value_for_array(node)
61
64
  else
62
65
  node.source.gsub('"', '\"')
63
66
  end
64
67
  end
65
68
 
69
+ def autocorrected_value_for_string(node)
70
+ if node.source.start_with?("'", '%q')
71
+ node.children.last.inspect[1..-2]
72
+ else
73
+ node.children.last
74
+ end
75
+ end
76
+
66
77
  def autocorrected_value_for_symbol(node)
67
78
  end_pos =
68
79
  node.loc.end ? node.loc.end.begin_pos : node.loc.expression.end_pos
@@ -70,6 +81,12 @@ module RuboCop
70
81
  range_between(node.loc.begin.end_pos, end_pos).source
71
82
  end
72
83
 
84
+ def autocorrected_value_for_array(node)
85
+ return node.source.gsub('"', '\"') unless node.percent_literal?
86
+
87
+ contents_range(node).source.split(' ').to_s.gsub('"', '\"')
88
+ end
89
+
73
90
  # Does node print its own source when converted to a string?
74
91
  def prints_as_self?(node)
75
92
  node.basic_literal? ||