rubocop 0.67.2 → 0.68.0

Sign up to get free protection for your applications and to get access to all the features.
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? ||