rubocop 1.17.0 → 1.18.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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +73 -28
  4. data/lib/rubocop.rb +2 -0
  5. data/lib/rubocop/cli/command/suggest_extensions.rb +3 -3
  6. data/lib/rubocop/config_loader.rb +1 -1
  7. data/lib/rubocop/config_validator.rb +5 -5
  8. data/lib/rubocop/cop/base.rb +2 -2
  9. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
  10. data/lib/rubocop/cop/bundler/gem_version.rb +38 -4
  11. data/lib/rubocop/cop/corrector.rb +4 -4
  12. data/lib/rubocop/cop/generator.rb +1 -1
  13. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  14. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  15. data/lib/rubocop/cop/layout/array_alignment.rb +2 -2
  16. data/lib/rubocop/cop/layout/block_alignment.rb +1 -1
  17. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +7 -1
  18. data/lib/rubocop/cop/layout/comment_indentation.rb +1 -1
  19. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -2
  20. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -2
  21. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
  22. data/lib/rubocop/cop/layout/hash_alignment.rb +9 -8
  23. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -1
  24. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +122 -0
  25. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +6 -6
  26. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +2 -2
  27. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +6 -6
  28. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +6 -6
  29. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +6 -6
  30. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +3 -3
  31. data/lib/rubocop/cop/layout/parameter_alignment.rb +2 -2
  32. data/lib/rubocop/cop/layout/space_around_operators.rb +1 -1
  33. data/lib/rubocop/cop/lint/nested_percent_literal.rb +1 -1
  34. data/lib/rubocop/cop/lint/percent_string_array.rb +1 -1
  35. data/lib/rubocop/cop/lint/percent_symbol_array.rb +1 -1
  36. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  37. data/lib/rubocop/cop/lint/unused_block_argument.rb +1 -1
  38. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
  39. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  40. data/lib/rubocop/cop/mixin/check_line_breakable.rb +10 -1
  41. data/lib/rubocop/cop/naming/inclusive_language.rb +249 -0
  42. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +2 -2
  43. data/lib/rubocop/cop/style/class_and_module_children.rb +14 -0
  44. data/lib/rubocop/cop/style/multiple_comparison.rb +1 -1
  45. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  46. data/lib/rubocop/cop/style/quoted_symbols.rb +2 -2
  47. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  48. data/lib/rubocop/cop/style/regexp_literal.rb +3 -2
  49. data/lib/rubocop/cop/style/special_global_vars.rb +3 -3
  50. data/lib/rubocop/cop/style/string_concatenation.rb +32 -5
  51. data/lib/rubocop/cop/style/string_literals.rb +2 -2
  52. data/lib/rubocop/cop/style/swap_values.rb +1 -1
  53. data/lib/rubocop/cop/style/unpack_first.rb +1 -1
  54. data/lib/rubocop/cop/variable_force/variable_table.rb +1 -1
  55. data/lib/rubocop/options.rb +4 -4
  56. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  57. data/lib/rubocop/rspec/expect_offense.rb +1 -1
  58. data/lib/rubocop/version.rb +1 -1
  59. metadata +9 -7
@@ -25,7 +25,7 @@ module RuboCop
25
25
 
26
26
  MSG = 'Preceed `%<method>s` with a `@!method` YARD directive.'
27
27
  MSG_WRONG_NAME = '`@!method` YARD directive has invalid method name, ' \
28
- 'use `%<expected>s` instead of `%<actual>s`.'
28
+ 'use `%<expected>s` instead of `%<actual>s`.'
29
29
  MSG_TOO_MANY = 'Multiple `@!method` YARD directives found for this matcher.'
30
30
 
31
31
  RESTRICT_ON_SEND = %i[def_node_matcher def_node_search].to_set.freeze
@@ -50,7 +50,7 @@ module RuboCop
50
50
  ALIGN_PARAMS_MSG = 'Align the arguments of a method call if they span more than one line.'
51
51
 
52
52
  FIXED_INDENT_MSG = 'Use one level of indentation for arguments ' \
53
- 'following the first line of a multi-line method call.'
53
+ 'following the first line of a multi-line method call.'
54
54
 
55
55
  def on_send(node)
56
56
  first_arg = node.first_argument
@@ -38,10 +38,10 @@ module RuboCop
38
38
  extend AutoCorrector
39
39
 
40
40
  ALIGN_ELEMENTS_MSG = 'Align the elements of an array literal ' \
41
- 'if they span more than one line.'
41
+ 'if they span more than one line.'
42
42
 
43
43
  FIXED_INDENT_MSG = 'Use one level of indentation for elements ' \
44
- 'following the first line of a multi-line array.'
44
+ 'following the first line of a multi-line array.'
45
45
 
46
46
  def on_array(node)
47
47
  return if node.children.size < 2
@@ -210,7 +210,7 @@ module RuboCop
210
210
 
211
211
  def format_source_line_column(source_line_column)
212
212
  "`#{source_line_column[:source]}` at #{source_line_column[:line]}, " \
213
- "#{source_line_column[:column]}"
213
+ "#{source_line_column[:column]}"
214
214
  end
215
215
 
216
216
  def compute_start_col(ancestor_node, node)
@@ -155,7 +155,13 @@ module RuboCop
155
155
  end
156
156
 
157
157
  def all_elements_aligned?(elements)
158
- elements.map { |e| e.loc.column }.uniq.count == 1
158
+ elements.flat_map do |e|
159
+ if e.hash_type?
160
+ e.each_pair.map { |pair| pair.loc.column }
161
+ else
162
+ e.loc.column
163
+ end
164
+ end.uniq.count == 1
159
165
  end
160
166
 
161
167
  def first_argument_line(elements)
@@ -37,7 +37,7 @@ module RuboCop
37
37
  extend AutoCorrector
38
38
 
39
39
  MSG = 'Incorrect indentation detected (column %<column>d ' \
40
- 'instead of %<correct_comment_indentation>d).'
40
+ 'instead of %<correct_comment_indentation>d).'
41
41
 
42
42
  def on_new_investigation
43
43
  processed_source.comments.each { |comment| check(comment) }
@@ -161,10 +161,10 @@ module RuboCop
161
161
  'Indent the right bracket the same as the left bracket.'
162
162
  elsif style == :special_inside_parentheses && left_parenthesis
163
163
  'Indent the right bracket the same as the first position ' \
164
- 'after the preceding left parenthesis.'
164
+ 'after the preceding left parenthesis.'
165
165
  else
166
166
  'Indent the right bracket the same as the start of the line' \
167
- ' where the left bracket is.'
167
+ ' where the left bracket is.'
168
168
  end
169
169
  end
170
170
  end
@@ -178,10 +178,10 @@ module RuboCop
178
178
  'Indent the right brace the same as the left brace.'
179
179
  elsif style == :special_inside_parentheses && left_parenthesis
180
180
  'Indent the right brace the same as the first position ' \
181
- 'after the preceding left parenthesis.'
181
+ 'after the preceding left parenthesis.'
182
182
  else
183
183
  'Indent the right brace the same as the start of the line ' \
184
- 'where the left brace is.'
184
+ 'where the left brace is.'
185
185
  end
186
186
  end
187
187
 
@@ -48,7 +48,7 @@ module RuboCop
48
48
  extend AutoCorrector
49
49
 
50
50
  MSG = 'Use %<configured_indentation_width>d spaces for indentation ' \
51
- 'in method args, relative to %<base_description>s.'
51
+ 'in method args, relative to %<base_description>s.'
52
52
 
53
53
  def on_def(node)
54
54
  return if node.arguments.empty?
@@ -180,14 +180,15 @@ module RuboCop
180
180
  include RangeHelp
181
181
  extend AutoCorrector
182
182
 
183
- MESSAGES = { KeyAlignment => 'Align the keys of a hash literal if ' \
184
- 'they span more than one line.',
185
- SeparatorAlignment => 'Align the separators of a hash ' \
186
- 'literal if they span more than one line.',
187
- TableAlignment => 'Align the keys and values of a hash ' \
188
- 'literal if they span more than one line.',
189
- KeywordSplatAlignment => 'Align keyword splats with the ' \
190
- 'rest of the hash if it spans more than one line.' }.freeze
183
+ MESSAGES = {
184
+ KeyAlignment => 'Align the keys of a hash literal if they span more than one line.',
185
+ SeparatorAlignment => 'Align the separators of a hash literal if they span more than ' \
186
+ 'one line.',
187
+ TableAlignment => 'Align the keys and values of a hash literal if they span more than ' \
188
+ 'one line.',
189
+ KeywordSplatAlignment => 'Align keyword splats with the rest of the hash if it spans ' \
190
+ 'more than one line.'
191
+ }.freeze
191
192
 
192
193
  def on_send(node)
193
194
  return if double_splat?(node)
@@ -55,7 +55,7 @@ module RuboCop
55
55
  extend AutoCorrector
56
56
 
57
57
  MSG = 'Put the closing parenthesis for a method call with a ' \
58
- 'HEREDOC parameter on the same line as the HEREDOC opening.'
58
+ 'HEREDOC parameter on the same line as the HEREDOC opening.'
59
59
 
60
60
  def self.autocorrect_incompatible_with
61
61
  [Style::TrailingCommaInArguments]
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Layout
6
+ # This cop checks the indentation of the next line after a line that ends with a string
7
+ # literal and a backslash.
8
+ #
9
+ # If `EnforcedStyle: aligned` is set, the concatenated string parts shall be aligned with the
10
+ # first part. There are some exceptions, such as implicit return values, where the
11
+ # concatenated string parts shall be indented regardless of `EnforcedStyle` configuration.
12
+ #
13
+ # If `EnforcedStyle: indented` is set, it's the second line that shall be indented one step
14
+ # more than the first line. Lines 3 and forward shall be aligned with line 2. Here too there
15
+ # are exceptions. Values in a hash literal are always aligned.
16
+ #
17
+ # @example
18
+ # # bad
19
+ # def some_method
20
+ # 'x' \
21
+ # 'y' \
22
+ # 'z'
23
+ # end
24
+ #
25
+ # my_hash = {
26
+ # first: 'a message' \
27
+ # 'in two parts'
28
+ # }
29
+ #
30
+ # # good
31
+ # def some_method
32
+ # 'x' \
33
+ # 'y' \
34
+ # 'z'
35
+ # end
36
+ #
37
+ # my_hash = {
38
+ # first: 'a message' \
39
+ # 'in two parts'
40
+ # }
41
+ #
42
+ # @example EnforcedStyle: aligned (default)
43
+ # # bad
44
+ # puts 'x' \
45
+ # 'y'
46
+ #
47
+ # # good
48
+ # puts 'x' \
49
+ # 'y'
50
+ #
51
+ # @example EnforcedStyle: indented
52
+ # # bad
53
+ # result = 'x' \
54
+ # 'y'
55
+ #
56
+ # # good
57
+ # result = 'x' \
58
+ # 'y'
59
+ #
60
+ class LineEndStringConcatenationIndentation < Base
61
+ include ConfigurableEnforcedStyle
62
+ include Alignment
63
+ extend AutoCorrector
64
+
65
+ MSG_ALIGN = 'Align parts of a string concatenated with backslash.'
66
+ MSG_INDENT = 'Indent the first part of a string concatenated with backslash.'
67
+ PARENT_TYPES_FOR_INDENTED = [nil, :block, :begin, :def, :defs, :if].freeze
68
+
69
+ def on_dstr(node)
70
+ return unless strings_concatenated_with_backslash?(node)
71
+
72
+ children = node.children
73
+ if style == :aligned && !always_indented?(node) || always_aligned?(node)
74
+ check_aligned(children, 1)
75
+ else
76
+ check_indented(children)
77
+ check_aligned(children, 2)
78
+ end
79
+ end
80
+
81
+ def autocorrect(corrector, node)
82
+ AlignmentCorrector.correct(corrector, processed_source, node, @column_delta)
83
+ end
84
+
85
+ private
86
+
87
+ def strings_concatenated_with_backslash?(dstr_node)
88
+ !dstr_node.heredoc? &&
89
+ dstr_node.children.length > 1 &&
90
+ dstr_node.children.all? { |c| c.str_type? || c.dstr_type? }
91
+ end
92
+
93
+ def always_indented?(dstr_node)
94
+ PARENT_TYPES_FOR_INDENTED.include?(dstr_node.parent&.type)
95
+ end
96
+
97
+ def always_aligned?(dstr_node)
98
+ dstr_node.parent&.pair_type?
99
+ end
100
+
101
+ def check_aligned(children, start_index)
102
+ base_column = children[start_index - 1].loc.column
103
+ children[start_index..-1].each do |child|
104
+ @column_delta = base_column - child.loc.column
105
+ add_offense_and_correction(child, MSG_ALIGN) if @column_delta != 0
106
+ base_column = child.loc.column
107
+ end
108
+ end
109
+
110
+ def check_indented(children)
111
+ base_column = children[0].source_range.source_line =~ /\S/
112
+ @column_delta = base_column + configured_indentation_width - children[1].loc.column
113
+ add_offense_and_correction(children[1], MSG_INDENT) if @column_delta != 0
114
+ end
115
+
116
+ def add_offense_and_correction(node, message)
117
+ add_offense(node, message: message) { |corrector| autocorrect(corrector, node) }
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
@@ -93,18 +93,18 @@ module RuboCop
93
93
  extend AutoCorrector
94
94
 
95
95
  SAME_LINE_MESSAGE = 'The closing array brace must be on the same ' \
96
- 'line as the last array element when the opening brace is on the ' \
97
- 'same line as the first array element.'
96
+ 'line as the last array element when the opening brace is on the ' \
97
+ 'same line as the first array element.'
98
98
 
99
99
  NEW_LINE_MESSAGE = 'The closing array brace must be on the line ' \
100
- 'after the last array element when the opening brace is on a ' \
101
- 'separate line from the first array element.'
100
+ 'after the last array element when the opening brace is on a ' \
101
+ 'separate line from the first array element.'
102
102
 
103
103
  ALWAYS_NEW_LINE_MESSAGE = 'The closing array brace must be on the ' \
104
- 'line after the last array element.'
104
+ 'line after the last array element.'
105
105
 
106
106
  ALWAYS_SAME_LINE_MESSAGE = 'The closing array brace must be on the ' \
107
- 'same line as the last array element.'
107
+ 'same line as the last array element.'
108
108
 
109
109
  def on_array(node)
110
110
  check_brace_layout(node)
@@ -64,10 +64,10 @@ module RuboCop
64
64
  extend AutoCorrector
65
65
 
66
66
  NEW_LINE_OFFENSE = 'Right hand side of multi-line assignment is on ' \
67
- 'the same line as the assignment operator `=`.'
67
+ 'the same line as the assignment operator `=`.'
68
68
 
69
69
  SAME_LINE_OFFENSE = 'Right hand side of multi-line assignment is not ' \
70
- 'on the same line as the assignment operator `=`.'
70
+ 'on the same line as the assignment operator `=`.'
71
71
 
72
72
  def check_assignment(node, rhs)
73
73
  return if node.send_type? && node.loc.operator&.source != '='
@@ -93,18 +93,18 @@ module RuboCop
93
93
  extend AutoCorrector
94
94
 
95
95
  SAME_LINE_MESSAGE = 'Closing hash brace must be on the same line as ' \
96
- 'the last hash element when opening brace is on the same line as ' \
97
- 'the first hash element.'
96
+ 'the last hash element when opening brace is on the same line as ' \
97
+ 'the first hash element.'
98
98
 
99
99
  NEW_LINE_MESSAGE = 'Closing hash brace must be on the line after ' \
100
- 'the last hash element when opening brace is on a separate line ' \
101
- 'from the first hash element.'
100
+ 'the last hash element when opening brace is on a separate line ' \
101
+ 'from the first hash element.'
102
102
 
103
103
  ALWAYS_NEW_LINE_MESSAGE = 'Closing hash brace must be on the line ' \
104
- 'after the last hash element.'
104
+ 'after the last hash element.'
105
105
 
106
106
  ALWAYS_SAME_LINE_MESSAGE = 'Closing hash brace must be on the same ' \
107
- 'line as the last hash element.'
107
+ 'line as the last hash element.'
108
108
 
109
109
  def on_hash(node)
110
110
  check_brace_layout(node)
@@ -93,18 +93,18 @@ module RuboCop
93
93
  extend AutoCorrector
94
94
 
95
95
  SAME_LINE_MESSAGE = 'Closing method call brace must be on the ' \
96
- 'same line as the last argument when opening brace is on the same ' \
97
- 'line as the first argument.'
96
+ 'same line as the last argument when opening brace is on the same ' \
97
+ 'line as the first argument.'
98
98
 
99
99
  NEW_LINE_MESSAGE = 'Closing method call brace must be on the ' \
100
- 'line after the last argument when opening brace is on a separate ' \
101
- 'line from the first argument.'
100
+ 'line after the last argument when opening brace is on a separate ' \
101
+ 'line from the first argument.'
102
102
 
103
103
  ALWAYS_NEW_LINE_MESSAGE = 'Closing method call brace must be on ' \
104
- 'the line after the last argument.'
104
+ 'the line after the last argument.'
105
105
 
106
106
  ALWAYS_SAME_LINE_MESSAGE = 'Closing method call brace must be on ' \
107
- 'the same line as the last argument.'
107
+ 'the same line as the last argument.'
108
108
 
109
109
  def on_send(node)
110
110
  check_brace_layout(node)
@@ -105,18 +105,18 @@ module RuboCop
105
105
  extend AutoCorrector
106
106
 
107
107
  SAME_LINE_MESSAGE = 'Closing method definition brace must be on the ' \
108
- 'same line as the last parameter when opening brace is on the same ' \
109
- 'line as the first parameter.'
108
+ 'same line as the last parameter when opening brace is on the same ' \
109
+ 'line as the first parameter.'
110
110
 
111
111
  NEW_LINE_MESSAGE = 'Closing method definition brace must be on the ' \
112
- 'line after the last parameter when opening brace is on a separate ' \
113
- 'line from the first parameter.'
112
+ 'line after the last parameter when opening brace is on a separate ' \
113
+ 'line from the first parameter.'
114
114
 
115
115
  ALWAYS_NEW_LINE_MESSAGE = 'Closing method definition brace must be ' \
116
- 'on the line after the last parameter.'
116
+ 'on the line after the last parameter.'
117
117
 
118
118
  ALWAYS_SAME_LINE_MESSAGE = 'Closing method definition brace must be ' \
119
- 'on the same line as the last parameter.'
119
+ 'on the same line as the last parameter.'
120
120
 
121
121
  def on_def(node)
122
122
  check_brace_layout(node.arguments)
@@ -59,9 +59,9 @@ module RuboCop
59
59
  return unless style == :aligned && cop_config['IndentationWidth']
60
60
 
61
61
  raise ValidationError, 'The `Layout/MultilineOperationIndentation`' \
62
- ' cop only accepts an `IndentationWidth` ' \
63
- 'configuration parameter when ' \
64
- '`EnforcedStyle` is `indented`.'
62
+ ' cop only accepts an `IndentationWidth` ' \
63
+ 'configuration parameter when ' \
64
+ '`EnforcedStyle` is `indented`.'
65
65
  end
66
66
 
67
67
  private
@@ -73,10 +73,10 @@ module RuboCop
73
73
  extend AutoCorrector
74
74
 
75
75
  ALIGN_PARAMS_MSG = 'Align the parameters of a method definition if ' \
76
- 'they span more than one line.'
76
+ 'they span more than one line.'
77
77
 
78
78
  FIXED_INDENT_MSG = 'Use one level of indentation for parameters ' \
79
- 'following the first line of a multi-line method definition.'
79
+ 'following the first line of a multi-line method definition.'
80
80
 
81
81
  def on_def(node)
82
82
  return if node.arguments.size < 2
@@ -198,7 +198,7 @@ module RuboCop
198
198
  elsif excess_leading_space?(type, operator, with_space) ||
199
199
  excess_trailing_space?(right_operand, with_space)
200
200
  "Operator `#{operator.source}` should be surrounded " \
201
- 'by a single space.'
201
+ 'by a single space.'
202
202
  end
203
203
  end
204
204
 
@@ -33,7 +33,7 @@ module RuboCop
33
33
  include PercentLiteral
34
34
 
35
35
  MSG = 'Within percent literals, nested percent literals do not ' \
36
- 'function and may be unwanted in the result.'
36
+ 'function and may be unwanted in the result.'
37
37
 
38
38
  # The array of regular expressions representing percent literals that,
39
39
  # if found within a percent literal expression, will cause a
@@ -29,7 +29,7 @@ module RuboCop
29
29
  TRAILING_QUOTE = /['"]?,?$/.freeze
30
30
 
31
31
  MSG = "Within `%w`/`%W`, quotes and ',' are unnecessary and may be " \
32
- 'unwanted in the resulting strings.'
32
+ 'unwanted in the resulting strings.'
33
33
 
34
34
  def on_array(node)
35
35
  process(node, '%w', '%W')
@@ -25,7 +25,7 @@ module RuboCop
25
25
  extend AutoCorrector
26
26
 
27
27
  MSG = "Within `%i`/`%I`, ':' and ',' are unnecessary and may be " \
28
- 'unwanted in the resulting symbols.'
28
+ 'unwanted in the resulting symbols.'
29
29
 
30
30
  def on_array(node)
31
31
  process(node, '%i', '%I')