rubocop 1.30.1 → 1.31.2

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 (132) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +41 -8
  4. data/config/obsoletion.yml +2 -0
  5. data/exe/rubocop +15 -7
  6. data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
  7. data/lib/rubocop/cli/command/suggest_extensions.rb +3 -3
  8. data/lib/rubocop/config.rb +4 -0
  9. data/lib/rubocop/config_loader.rb +1 -0
  10. data/lib/rubocop/config_loader_resolver.rb +1 -1
  11. data/lib/rubocop/config_validator.rb +3 -3
  12. data/lib/rubocop/cop/base.rb +5 -1
  13. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
  14. data/lib/rubocop/cop/bundler/gem_filename.rb +4 -4
  15. data/lib/rubocop/cop/bundler/ordered_gems.rb +2 -2
  16. data/lib/rubocop/cop/corrector.rb +2 -2
  17. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +3 -3
  18. data/lib/rubocop/cop/correctors/unused_arg_corrector.rb +1 -1
  19. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +31 -16
  20. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +1 -1
  21. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
  22. data/lib/rubocop/cop/gemspec/require_mfa.rb +20 -20
  23. data/lib/rubocop/cop/generator.rb +5 -1
  24. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -5
  25. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -1
  26. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +1 -1
  27. data/lib/rubocop/cop/internal_affairs/useless_restrict_on_send.rb +54 -0
  28. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  29. data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
  30. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +25 -4
  31. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +20 -13
  32. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +51 -12
  33. data/lib/rubocop/cop/layout/initial_indentation.rb +1 -1
  34. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +68 -0
  35. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +130 -0
  36. data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -1
  37. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +2 -2
  38. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -2
  39. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
  40. data/lib/rubocop/cop/layout/space_around_operators.rb +1 -1
  41. data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -1
  42. data/lib/rubocop/cop/layout/space_before_first_arg.rb +1 -1
  43. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +5 -3
  44. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  45. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +51 -0
  46. data/lib/rubocop/cop/lint/interpolation_check.rb +1 -1
  47. data/lib/rubocop/cop/lint/literal_as_condition.rb +5 -0
  48. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +126 -0
  49. data/lib/rubocop/cop/lint/number_conversion.rb +3 -3
  50. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
  51. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +5 -5
  52. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
  53. data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -1
  54. data/lib/rubocop/cop/lint/regexp_as_condition.rb +2 -2
  55. data/lib/rubocop/cop/lint/struct_new_override.rb +2 -2
  56. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -1
  57. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +44 -0
  58. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  59. data/lib/rubocop/cop/mixin/def_node.rb +2 -7
  60. data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +34 -12
  61. data/lib/rubocop/cop/mixin/range_help.rb +7 -3
  62. data/lib/rubocop/cop/style/accessor_grouping.rb +1 -1
  63. data/lib/rubocop/cop/style/arguments_forwarding.rb +1 -1
  64. data/lib/rubocop/cop/style/block_delimiters.rb +4 -2
  65. data/lib/rubocop/cop/style/commented_keyword.rb +1 -1
  66. data/lib/rubocop/cop/style/conditional_assignment.rb +1 -0
  67. data/lib/rubocop/cop/style/empty_method.rb +16 -1
  68. data/lib/rubocop/cop/style/encoding.rb +1 -1
  69. data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
  70. data/lib/rubocop/cop/style/format_string_token.rb +48 -17
  71. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  72. data/lib/rubocop/cop/style/guard_clause.rb +8 -6
  73. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +1 -1
  74. data/lib/rubocop/cop/style/hash_except.rb +88 -8
  75. data/lib/rubocop/cop/style/hash_syntax.rb +2 -2
  76. data/lib/rubocop/cop/style/implicit_runtime_error.rb +2 -2
  77. data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
  78. data/lib/rubocop/cop/style/line_end_concatenation.rb +1 -1
  79. data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
  80. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -2
  81. data/lib/rubocop/cop/style/module_function.rb +2 -2
  82. data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -2
  83. data/lib/rubocop/cop/style/multiline_if_then.rb +1 -1
  84. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -3
  85. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -1
  86. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -1
  87. data/lib/rubocop/cop/style/multiline_when_then.rb +1 -3
  88. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  89. data/lib/rubocop/cop/style/nested_ternary_operator.rb +19 -7
  90. data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
  91. data/lib/rubocop/cop/style/not.rb +1 -1
  92. data/lib/rubocop/cop/style/redundant_argument.rb +1 -1
  93. data/lib/rubocop/cop/style/redundant_parentheses.rb +2 -1
  94. data/lib/rubocop/cop/style/redundant_return.rb +1 -1
  95. data/lib/rubocop/cop/style/redundant_self_assignment.rb +1 -1
  96. data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -2
  97. data/lib/rubocop/cop/style/struct_inheritance.rb +2 -2
  98. data/lib/rubocop/cop/style/swap_values.rb +1 -1
  99. data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
  100. data/lib/rubocop/cop/style/top_level_method_definition.rb +0 -2
  101. data/lib/rubocop/cop/style/unpack_first.rb +1 -1
  102. data/lib/rubocop/cop/util.rb +1 -1
  103. data/lib/rubocop/formatter/formatter_set.rb +20 -19
  104. data/lib/rubocop/formatter/git_hub_actions_formatter.rb +15 -2
  105. data/lib/rubocop/formatter/html_formatter.rb +0 -1
  106. data/lib/rubocop/formatter/offense_count_formatter.rb +2 -0
  107. data/lib/rubocop/formatter/simple_text_formatter.rb +6 -7
  108. data/lib/rubocop/formatter.rb +31 -0
  109. data/lib/rubocop/options.rb +24 -1
  110. data/lib/rubocop/rake_task.rb +34 -9
  111. data/lib/rubocop/server/cache.rb +109 -0
  112. data/lib/rubocop/server/cli.rb +104 -0
  113. data/lib/rubocop/server/client_command/base.rb +44 -0
  114. data/lib/rubocop/server/client_command/exec.rb +59 -0
  115. data/lib/rubocop/server/client_command/restart.rb +25 -0
  116. data/lib/rubocop/server/client_command/start.rb +43 -0
  117. data/lib/rubocop/server/client_command/status.rb +28 -0
  118. data/lib/rubocop/server/client_command/stop.rb +31 -0
  119. data/lib/rubocop/server/client_command.rb +26 -0
  120. data/lib/rubocop/server/core.rb +79 -0
  121. data/lib/rubocop/server/errors.rb +23 -0
  122. data/lib/rubocop/server/helper.rb +34 -0
  123. data/lib/rubocop/server/server_command/base.rb +50 -0
  124. data/lib/rubocop/server/server_command/exec.rb +34 -0
  125. data/lib/rubocop/server/server_command/stop.rb +24 -0
  126. data/lib/rubocop/server/server_command.rb +21 -0
  127. data/lib/rubocop/server/socket_reader.rb +65 -0
  128. data/lib/rubocop/server.rb +53 -0
  129. data/lib/rubocop/version.rb +15 -8
  130. data/lib/rubocop.rb +8 -27
  131. metadata +42 -4
  132. data/lib/rubocop/cop/gemspec/date_assignment.rb +0 -49
@@ -70,18 +70,39 @@ module RuboCop
70
70
  def on_send(node)
71
71
  return unless node.attribute_accessor?
72
72
  return if next_line_empty?(node.last_line)
73
+ return if next_line_empty_or_enable_directive_comment?(node.last_line)
73
74
 
74
75
  next_line_node = next_line_node(node)
75
76
  return unless require_empty_line?(next_line_node)
76
77
 
77
- add_offense(node) do |corrector|
78
- range = range_by_whole_lines(node.source_range)
78
+ add_offense(node) { |corrector| autocorrect(corrector, node) }
79
+ end
80
+
81
+ private
79
82
 
80
- corrector.insert_after(range, "\n")
83
+ def autocorrect(corrector, node)
84
+ node_range = range_by_whole_lines(node.source_range)
85
+
86
+ next_line = node_range.last_line + 1
87
+ if next_line_enable_directive_comment?(next_line)
88
+ node_range = processed_source.comment_at_line(next_line)
81
89
  end
90
+
91
+ corrector.insert_after(node_range, "\n")
82
92
  end
83
93
 
84
- private
94
+ def next_line_empty_or_enable_directive_comment?(line)
95
+ return true if next_line_empty?(line)
96
+
97
+ next_line = line + 1
98
+ next_line_enable_directive_comment?(next_line) && next_line_empty?(next_line)
99
+ end
100
+
101
+ def next_line_enable_directive_comment?(line)
102
+ return false unless (comment = processed_source.comment_at_line(line))
103
+
104
+ DirectiveComment.new(comment).enabled?
105
+ end
85
106
 
86
107
  def next_line_empty?(line)
87
108
  processed_source[line].nil? || processed_source[line].blank?
@@ -120,29 +120,33 @@ module RuboCop
120
120
  check_first(first_elem, left_bracket, left_parenthesis, 0)
121
121
  end
122
122
 
123
- check_right_bracket(array_node.loc.end, left_bracket, left_parenthesis)
123
+ check_right_bracket(array_node.loc.end, first_elem, left_bracket, left_parenthesis)
124
124
  end
125
125
 
126
- def check_right_bracket(right_bracket, left_bracket, left_parenthesis)
126
+ def check_right_bracket(right_bracket, first_elem, left_bracket, left_parenthesis)
127
127
  # if the right bracket is on the same line as the last value, accept
128
128
  return if /\S/.match?(right_bracket.source_line[0...right_bracket.column])
129
129
 
130
- expected_column = base_column(left_bracket, left_parenthesis)
130
+ expected_column, indent_base_type = indent_base(left_bracket, first_elem,
131
+ left_parenthesis)
131
132
  @column_delta = expected_column - right_bracket.column
132
133
  return if @column_delta.zero?
133
134
 
134
- msg = msg(left_parenthesis)
135
+ msg = message_for_right_bracket(indent_base_type)
135
136
  add_offense(right_bracket, message: msg) do |corrector|
136
137
  autocorrect(corrector, right_bracket)
137
138
  end
138
139
  end
139
140
 
140
141
  # Returns the description of what the correct indentation is based on.
141
- def base_description(left_parenthesis)
142
- if style == :align_brackets
142
+ def base_description(indent_base_type)
143
+ case indent_base_type
144
+ when :left_brace_or_bracket
143
145
  'the position of the opening bracket'
144
- elsif left_parenthesis && style == :special_inside_parentheses
146
+ when :first_colmn_after_left_parenthesis
145
147
  'the first position after the preceding left parenthesis'
148
+ when :parent_hash_key
149
+ 'the parent hash key'
146
150
  else
147
151
  'the start of the line where the left square bracket is'
148
152
  end
@@ -156,15 +160,18 @@ module RuboCop
156
160
  )
157
161
  end
158
162
 
159
- def msg(left_parenthesis)
160
- if style == :align_brackets
163
+ def message_for_right_bracket(indent_base_type)
164
+ case indent_base_type
165
+ when :left_brace_or_bracket
161
166
  'Indent the right bracket the same as the left bracket.'
162
- elsif style == :special_inside_parentheses && left_parenthesis
167
+ when :first_colmn_after_left_parenthesis
163
168
  'Indent the right bracket the same as the first position ' \
164
- 'after the preceding left parenthesis.'
169
+ 'after the preceding left parenthesis.'
170
+ when :parent_hash_key
171
+ 'Indent the right bracket the same as the parent hash key.' \
165
172
  else
166
- 'Indent the right bracket the same as the start of the line' \
167
- ' where the left bracket is.'
173
+ 'Indent the right bracket the same as the start of the line ' \
174
+ 'where the left bracket is.'
168
175
  end
169
176
  end
170
177
  end
@@ -32,6 +32,14 @@ module RuboCop
32
32
  # and_in_a_method_call({
33
33
  # no: :difference
34
34
  # })
35
+ # takes_multi_pairs_hash(x: {
36
+ # a: 1,
37
+ # b: 2
38
+ # },
39
+ # y: {
40
+ # c: 1,
41
+ # d: 2
42
+ # })
35
43
  #
36
44
  # # good
37
45
  # special_inside_parentheses
@@ -41,6 +49,14 @@ module RuboCop
41
49
  # but_in_a_method_call({
42
50
  # its_like: :this
43
51
  # })
52
+ # takes_multi_pairs_hash(x: {
53
+ # a: 1,
54
+ # b: 2
55
+ # },
56
+ # y: {
57
+ # c: 1,
58
+ # d: 2
59
+ # })
44
60
  #
45
61
  # @example EnforcedStyle: consistent
46
62
  # # The `consistent` style enforces that the first key in a hash
@@ -64,6 +80,7 @@ module RuboCop
64
80
  # no: :difference
65
81
  # })
66
82
  #
83
+ #
67
84
  # @example EnforcedStyle: align_braces
68
85
  # # The `align_brackets` style enforces that the opening and closing
69
86
  # # braces are indented to the same position.
@@ -72,11 +89,27 @@ module RuboCop
72
89
  # and_now_for_something = {
73
90
  # completely: :different
74
91
  # }
92
+ # takes_multi_pairs_hash(x: {
93
+ # a: 1,
94
+ # b: 2
95
+ # },
96
+ # y: {
97
+ # c: 1,
98
+ # d: 2
99
+ # })
75
100
  #
76
101
  # # good
77
102
  # and_now_for_something = {
78
103
  # completely: :different
79
104
  # }
105
+ # takes_multi_pairs_hash(x: {
106
+ # a: 1,
107
+ # b: 2
108
+ # },
109
+ # y: {
110
+ # c: 1,
111
+ # d: 2
112
+ # })
80
113
  class FirstHashElementIndentation < Base
81
114
  include Alignment
82
115
  include ConfigurableEnforcedStyle
@@ -125,18 +158,18 @@ module RuboCop
125
158
  end
126
159
  end
127
160
 
128
- check_right_brace(hash_node.loc.end, left_brace, left_parenthesis)
161
+ check_right_brace(hash_node.loc.end, first_pair, left_brace, left_parenthesis)
129
162
  end
130
163
 
131
- def check_right_brace(right_brace, left_brace, left_parenthesis)
164
+ def check_right_brace(right_brace, first_pair, left_brace, left_parenthesis)
132
165
  # if the right brace is on the same line as the last value, accept
133
166
  return if /\S/.match?(right_brace.source_line[0...right_brace.column])
134
167
 
135
- expected_column = base_column(left_brace, left_parenthesis)
168
+ expected_column, indent_base_type = indent_base(left_brace, first_pair, left_parenthesis)
136
169
  @column_delta = expected_column - right_brace.column
137
170
  return if @column_delta.zero?
138
171
 
139
- message = message_for_right_brace(left_parenthesis)
172
+ message = message_for_right_brace(indent_base_type)
140
173
  add_offense(right_brace, message: message) do |corrector|
141
174
  autocorrect(corrector, right_brace)
142
175
  end
@@ -155,11 +188,14 @@ module RuboCop
155
188
  end
156
189
 
157
190
  # Returns the description of what the correct indentation is based on.
158
- def base_description(left_parenthesis)
159
- if style == :align_braces
191
+ def base_description(indent_base_type)
192
+ case indent_base_type
193
+ when :left_brace_or_bracket
160
194
  'the position of the opening brace'
161
- elsif left_parenthesis && style == :special_inside_parentheses
195
+ when :first_colmn_after_left_parenthesis
162
196
  'the first position after the preceding left parenthesis'
197
+ when :parent_hash_key
198
+ 'the parent hash key'
163
199
  else
164
200
  'the start of the line where the left curly brace is'
165
201
  end
@@ -173,15 +209,18 @@ module RuboCop
173
209
  )
174
210
  end
175
211
 
176
- def message_for_right_brace(left_parenthesis)
177
- if style == :align_braces
212
+ def message_for_right_brace(indent_base_type)
213
+ case indent_base_type
214
+ when :left_brace_or_bracket
178
215
  'Indent the right brace the same as the left brace.'
179
- elsif style == :special_inside_parentheses && left_parenthesis
216
+ when :first_colmn_after_left_parenthesis
180
217
  'Indent the right brace the same as the first position ' \
181
- 'after the preceding left parenthesis.'
218
+ 'after the preceding left parenthesis.'
219
+ when :parent_hash_key
220
+ 'Indent the right brace the same as the parent hash key.'
182
221
  else
183
222
  'Indent the right brace the same as the start of the line ' \
184
- 'where the left brace is.'
223
+ 'where the left brace is.'
185
224
  end
186
225
  end
187
226
 
@@ -41,7 +41,7 @@ module RuboCop
41
41
  return unless token
42
42
  return if token.column.zero?
43
43
 
44
- space_range = range_with_surrounding_space(range: token.pos, side: :left, newlines: false)
44
+ space_range = range_with_surrounding_space(token.pos, side: :left, newlines: false)
45
45
  # If the file starts with a byte order mark (BOM), the column can be
46
46
  # non-zero, but then we find out here if there's no space to the left
47
47
  # of the first token.
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Layout
6
+ # Checks that strings broken over multiple lines (by a backslash) contain
7
+ # trailing spaces instead of leading spaces.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # 'this text contains a lot of' \
12
+ # ' spaces'
13
+ #
14
+ # # good
15
+ # 'this text contains a lot of ' \
16
+ # 'spaces'
17
+ #
18
+ # # bad
19
+ # 'this text is too' \
20
+ # ' long'
21
+ #
22
+ # # good
23
+ # 'this text is too ' \
24
+ # 'long'
25
+ #
26
+ class LineContinuationLeadingSpace < Base
27
+ include RangeHelp
28
+
29
+ MSG = 'Move leading spaces to the end of previous line.'
30
+
31
+ def on_dstr(node)
32
+ range_start = node.loc.expression.begin_pos - node.loc.expression.column
33
+
34
+ raw_lines(node).each_cons(2) do |raw_line_one, raw_line_two|
35
+ range_start += raw_line_one.length
36
+
37
+ investigate(raw_line_one, raw_line_two, range_start)
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def raw_lines(node)
44
+ processed_source.raw_source.lines[node.first_line - 1, line_range(node).size]
45
+ end
46
+
47
+ def investigate(first_line, second_line, range_start)
48
+ return unless continuation?(first_line)
49
+
50
+ matches = second_line.match(/\A(?<indent>\s*['"])(?<leading_spaces>\s+)/)
51
+ return if matches.nil?
52
+
53
+ add_offense(offense_range(range_start, matches))
54
+ end
55
+
56
+ def continuation?(line)
57
+ line.end_with?("\\\n")
58
+ end
59
+
60
+ def offense_range(range_start, matches)
61
+ begin_pos = range_start + matches[:indent].length
62
+ end_pos = begin_pos + matches[:leading_spaces].length
63
+ range_between(begin_pos, end_pos)
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Layout
6
+ # Checks that the backslash of a line continuation is separated from
7
+ # preceding text by exactly one space (default) or zero spaces.
8
+ #
9
+ # @example EnforcedStyle: space (default)
10
+ # # bad
11
+ # 'a'\
12
+ # 'b' \
13
+ # 'c'
14
+ #
15
+ # # good
16
+ # 'a' \
17
+ # 'b' \
18
+ # 'c'
19
+ #
20
+ # @example EnforcedStyle: no_space
21
+ # # bad
22
+ # 'a' \
23
+ # 'b' \
24
+ # 'c'
25
+ #
26
+ # # good
27
+ # 'a'\
28
+ # 'b'\
29
+ # 'c'
30
+ class LineContinuationSpacing < Base
31
+ include RangeHelp
32
+ extend AutoCorrector
33
+
34
+ def on_new_investigation
35
+ last_line = last_line(processed_source)
36
+
37
+ @ignored_ranges = string_literal_ranges(processed_source.ast) +
38
+ comment_ranges(processed_source.comments)
39
+
40
+ processed_source.raw_source.lines.each_with_index do |line, index|
41
+ break if index >= last_line
42
+
43
+ line_number = index + 1
44
+ investigate(line, line_number)
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def investigate(line, line_number)
51
+ offensive_spacing = find_offensive_spacing(line)
52
+ return unless offensive_spacing
53
+
54
+ range = source_range(
55
+ processed_source.buffer,
56
+ line_number,
57
+ line.length - offensive_spacing.length - 1,
58
+ offensive_spacing.length
59
+ )
60
+
61
+ return if ignore_range?(range)
62
+
63
+ add_offense(range) { |corrector| autocorrect(corrector, range) }
64
+ end
65
+
66
+ def find_offensive_spacing(line)
67
+ if no_space_style?
68
+ line[/\s+\\$/, 0]
69
+ elsif space_style?
70
+ line[/((?<!\s)|\s{2,})\\$/, 0]
71
+ end
72
+ end
73
+
74
+ def message(_range)
75
+ if no_space_style?
76
+ 'Use zero spaces in front of backslash.'
77
+ elsif space_style?
78
+ 'Use one space in front of backslash.'
79
+ end
80
+ end
81
+
82
+ def autocorrect(corrector, range)
83
+ correction = if no_space_style?
84
+ '\\'
85
+ elsif space_style?
86
+ ' \\'
87
+ end
88
+ corrector.replace(range, correction)
89
+ end
90
+
91
+ def string_literal_ranges(ast)
92
+ # which lines start inside a string literal?
93
+ return [] if ast.nil?
94
+
95
+ ast.each_node(:str, :dstr).each_with_object(Set.new) do |str, ranges|
96
+ loc = str.location
97
+
98
+ if str.heredoc?
99
+ ranges << loc.heredoc_body
100
+ elsif loc.respond_to?(:begin) && loc.begin
101
+ ranges << loc.expression
102
+ end
103
+ end
104
+ end
105
+
106
+ def comment_ranges(comments)
107
+ comments.map(&:loc).map(&:expression)
108
+ end
109
+
110
+ def last_line(processed_source)
111
+ last_token = processed_source.tokens.last
112
+
113
+ last_token ? last_token.line : processed_source.lines.length
114
+ end
115
+
116
+ def ignore_range?(backtick_range)
117
+ @ignored_ranges.any? { |range| range.contains?(backtick_range) }
118
+ end
119
+
120
+ def no_space_style?
121
+ cop_config['EnforcedStyle'] == 'no_space'
122
+ end
123
+
124
+ def space_style?
125
+ cop_config['EnforcedStyle'] == 'space'
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -117,7 +117,7 @@ module RuboCop
117
117
 
118
118
  def autocorrect_arguments(corrector, node)
119
119
  end_pos = range_with_surrounding_space(
120
- range: node.arguments.source_range,
120
+ node.arguments.source_range,
121
121
  side: :right,
122
122
  newlines: false
123
123
  ).end_pos
@@ -56,8 +56,8 @@ module RuboCop
56
56
  return unless style == :aligned && cop_config['IndentationWidth']
57
57
 
58
58
  raise ValidationError,
59
- 'The `Layout/MultilineMethodCallIndentation`' \
60
- ' cop only accepts an `IndentationWidth` ' \
59
+ 'The `Layout/MultilineMethodCallIndentation` ' \
60
+ 'cop only accepts an `IndentationWidth` ' \
61
61
  'configuration parameter when ' \
62
62
  '`EnforcedStyle` is `indented`.'
63
63
  end
@@ -57,8 +57,8 @@ module RuboCop
57
57
  def validate_config
58
58
  return unless style == :aligned && cop_config['IndentationWidth']
59
59
 
60
- raise ValidationError, 'The `Layout/MultilineOperationIndentation`' \
61
- ' cop only accepts an `IndentationWidth` ' \
60
+ raise ValidationError, 'The `Layout/MultilineOperationIndentation` ' \
61
+ 'cop only accepts an `IndentationWidth` ' \
62
62
  'configuration parameter when ' \
63
63
  '`EnforcedStyle` is `indented`.'
64
64
  end
@@ -127,7 +127,7 @@ module RuboCop
127
127
 
128
128
  expr = arg.source_range
129
129
  check_no_space(
130
- range_with_surrounding_space(range: expr, side: :left).begin_pos,
130
+ range_with_surrounding_space(expr, side: :left).begin_pos,
131
131
  expr.begin_pos - 1,
132
132
  'Extra space before'
133
133
  )
@@ -161,7 +161,7 @@ module RuboCop
161
161
  end
162
162
 
163
163
  def check_operator(type, operator, right_operand)
164
- with_space = range_with_surrounding_space(range: operator)
164
+ with_space = range_with_surrounding_space(operator)
165
165
  return if with_space.source.start_with?("\n")
166
166
 
167
167
  offense(type, operator, with_space, right_operand) do |msg|
@@ -65,7 +65,7 @@ module RuboCop
65
65
  return if conflict_with_block_delimiters?(node)
66
66
 
67
67
  left_brace = node.loc.begin
68
- space_plus_brace = range_with_surrounding_space(range: left_brace)
68
+ space_plus_brace = range_with_surrounding_space(left_brace)
69
69
  used_style =
70
70
  space_plus_brace.source.start_with?('{') ? :no_space : :space
71
71
 
@@ -36,7 +36,7 @@ module RuboCop
36
36
  return unless regular_method_call_with_arguments?(node)
37
37
 
38
38
  first_arg = node.first_argument.source_range
39
- first_arg_with_space = range_with_surrounding_space(range: first_arg, side: :left)
39
+ first_arg_with_space = range_with_surrounding_space(first_arg, side: :left)
40
40
  space = range_between(first_arg_with_space.begin_pos, first_arg.begin_pos)
41
41
  return if space.length == 1
42
42
  return unless expect_params_after_method_name?(node)
@@ -98,6 +98,8 @@ module RuboCop
98
98
  check_inside(node, left_brace, right_brace)
99
99
  end
100
100
 
101
+ alias on_numblock on_block
102
+
101
103
  private
102
104
 
103
105
  def check_inside(node, left_brace, right_brace)
@@ -126,7 +128,7 @@ module RuboCop
126
128
  end
127
129
 
128
130
  def braces_with_contents_inside(node, inner)
129
- args_delimiter = node.arguments.loc.begin # Can be ( | or nil.
131
+ args_delimiter = node.arguments.loc.begin if node.block_type? # Can be ( | or nil.
130
132
 
131
133
  check_left_brace(inner, node.loc.begin, args_delimiter)
132
134
  check_right_brace(inner, node.loc.begin, node.loc.end, node.single_line?)
@@ -185,7 +187,7 @@ module RuboCop
185
187
  'Space between { and | detected.')
186
188
  end
187
189
  else
188
- brace_with_space = range_with_surrounding_space(range: left_brace, side: :right)
190
+ brace_with_space = range_with_surrounding_space(left_brace, side: :right)
189
191
  space(brace_with_space.begin_pos + 1, brace_with_space.end_pos,
190
192
  'Space inside { detected.')
191
193
  end
@@ -196,7 +198,7 @@ module RuboCop
196
198
  end
197
199
 
198
200
  def space_inside_right_brace(right_brace)
199
- brace_with_space = range_with_surrounding_space(range: right_brace, side: :left)
201
+ brace_with_space = range_with_surrounding_space(right_brace, side: :left)
200
202
  space(brace_with_space.begin_pos, brace_with_space.end_pos - 1,
201
203
  'Space inside } detected.')
202
204
  end
@@ -89,7 +89,7 @@ module RuboCop
89
89
  end
90
90
 
91
91
  def whitespace_only?(range)
92
- source = range_with_surrounding_space(range: range).source
92
+ source = range_with_surrounding_space(range).source
93
93
  source.start_with?("\n") && source.end_with?("\n")
94
94
  end
95
95
 
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for overwriting an exception with an exception result by use `rescue =>`.
7
+ #
8
+ # You intended to write as `rescue StandardError`.
9
+ # However, you have written `rescue => StandardError`.
10
+ # In that case, the result of `rescue` will overwrite `StandardError`.
11
+ #
12
+ # @example
13
+ #
14
+ # # bad
15
+ # begin
16
+ # something
17
+ # rescue => StandardError
18
+ # end
19
+ #
20
+ # # good
21
+ # begin
22
+ # something
23
+ # rescue StandardError
24
+ # end
25
+ #
26
+ class ConstantOverwrittenInRescue < Base
27
+ extend AutoCorrector
28
+ include RangeHelp
29
+
30
+ MSG = '`%<constant>s` is overwritten by `rescue =>`.'
31
+
32
+ # @!method overwritten_constant(node)
33
+ def_node_matcher :overwritten_constant, <<~PATTERN
34
+ (resbody nil? (casgn nil? $_) nil?)
35
+ PATTERN
36
+
37
+ def self.autocorrect_incompatible_with
38
+ [Naming::RescuedExceptionsVariableName, Style::RescueStandardError]
39
+ end
40
+
41
+ def on_resbody(node)
42
+ return unless (constant = overwritten_constant(node))
43
+
44
+ add_offense(node.loc.assoc, message: format(MSG, constant: constant)) do |corrector|
45
+ corrector.remove(range_between(node.loc.keyword.end_pos, node.loc.assoc.end_pos))
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -24,7 +24,7 @@ module RuboCop
24
24
  class InterpolationCheck < Base
25
25
  extend AutoCorrector
26
26
 
27
- MSG = 'Interpolation in single quoted string detected. '\
27
+ MSG = 'Interpolation in single quoted string detected. ' \
28
28
  'Use double quoted strings if you need interpolation.'
29
29
 
30
30
  def on_str(node)
@@ -7,6 +7,9 @@ module RuboCop
7
7
  # operands in and/or expressions serving as the conditions of
8
8
  # if/while/until/case-when/case-in.
9
9
  #
10
+ # NOTE: Literals in `case-in` condition where the match variable is used in
11
+ # `in` are accepted as a pattern matching.
12
+ #
10
13
  # @example
11
14
  #
12
15
  # # bad
@@ -69,6 +72,8 @@ module RuboCop
69
72
 
70
73
  def on_case_match(case_match_node)
71
74
  if case_match_node.condition
75
+ return if case_match_node.descendants.any?(&:match_var_type?)
76
+
72
77
  check_case(case_match_node)
73
78
  else
74
79
  case_match_node.each_in_pattern do |in_pattern_node|