rubocop 0.56.0 → 0.57.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -4
  3. data/assets/output.html.erb +1 -1
  4. data/bin/console +9 -0
  5. data/config/default.yml +23 -3
  6. data/config/disabled.yml +2 -2
  7. data/config/enabled.yml +29 -13
  8. data/{bin → exe}/rubocop +0 -0
  9. data/lib/rubocop.rb +6 -2
  10. data/lib/rubocop/ast/node.rb +3 -1
  11. data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +26 -5
  12. data/lib/rubocop/config_loader.rb +0 -1
  13. data/lib/rubocop/config_loader_resolver.rb +4 -2
  14. data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -1
  15. data/lib/rubocop/cop/generator.rb +1 -1
  16. data/lib/rubocop/cop/layout/class_structure.rb +1 -1
  17. data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +130 -0
  18. data/lib/rubocop/cop/layout/dot_position.rb +2 -6
  19. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -1
  20. data/lib/rubocop/cop/layout/empty_lines_around_begin_body.rb +0 -1
  21. data/lib/rubocop/cop/layout/extra_spacing.rb +2 -2
  22. data/lib/rubocop/cop/layout/indent_heredoc.rb +29 -5
  23. data/lib/rubocop/cop/layout/indentation_consistency.rb +1 -1
  24. data/lib/rubocop/cop/layout/indentation_width.rb +2 -2
  25. data/lib/rubocop/cop/layout/leading_blank_lines.rb +53 -0
  26. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +11 -2
  27. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
  28. data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +4 -3
  29. data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
  30. data/lib/rubocop/cop/mixin/array_syntax.rb +1 -1
  31. data/lib/rubocop/cop/mixin/range_help.rb +3 -7
  32. data/lib/rubocop/cop/rails/assert_not.rb +1 -1
  33. data/lib/rubocop/cop/rails/bulk_change_table.rb +272 -0
  34. data/lib/rubocop/cop/rails/dynamic_find_by.rb +1 -1
  35. data/lib/rubocop/cop/rails/file_path.rb +40 -10
  36. data/lib/rubocop/cop/rails/http_positional_arguments.rb +1 -1
  37. data/lib/rubocop/cop/rails/time_zone.rb +3 -3
  38. data/lib/rubocop/cop/style/access_modifier_declarations.rb +111 -0
  39. data/lib/rubocop/cop/style/bare_percent_literals.rb +1 -1
  40. data/lib/rubocop/cop/style/command_literal.rb +1 -5
  41. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +30 -7
  42. data/lib/rubocop/cop/style/mixin_grouping.rb +8 -3
  43. data/lib/rubocop/cop/style/next.rb +1 -1
  44. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +26 -3
  45. data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
  46. data/lib/rubocop/cop/style/unneeded_condition.rb +73 -0
  47. data/lib/rubocop/cop/style/unneeded_percent_q.rb +13 -0
  48. data/lib/rubocop/cop/variable_force.rb +16 -17
  49. data/lib/rubocop/options.rb +15 -5
  50. data/lib/rubocop/result_cache.rb +3 -3
  51. data/lib/rubocop/string_util.rb +2 -147
  52. data/lib/rubocop/token.rb +2 -1
  53. data/lib/rubocop/version.rb +1 -1
  54. metadata +28 -9
  55. data/lib/rubocop/cop/lint/splat_keyword_arguments.rb +0 -36
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Layout
6
+ #
7
+ # Checks the indentation of here document closings.
8
+ #
9
+ # @example
10
+ #
11
+ # # bad
12
+ # class Foo
13
+ # def bar
14
+ # <<~SQL
15
+ # 'Hi'
16
+ # SQL
17
+ # end
18
+ # end
19
+ #
20
+ # # good
21
+ # class Foo
22
+ # def bar
23
+ # <<~SQL
24
+ # 'Hi'
25
+ # SQL
26
+ # end
27
+ # end
28
+ #
29
+ # # bad
30
+ #
31
+ # # heredoc contents is before closing heredoc.
32
+ # foo arg,
33
+ # <<~EOS
34
+ # Hi
35
+ # EOS
36
+ #
37
+ # # good
38
+ # foo arg,
39
+ # <<~EOS
40
+ # Hi
41
+ # EOS
42
+ #
43
+ # # good
44
+ # foo arg,
45
+ # <<~EOS
46
+ # Hi
47
+ # EOS
48
+ #
49
+ class ClosingHeredocIndentation < Cop
50
+ include Heredoc
51
+
52
+ MSG = '`%<closing>s` is not aligned with `%<opening>s`.'.freeze
53
+ MSG_ARG = '`%<closing>s` is not aligned with `%<opening>s` or ' \
54
+ 'beginning of method definition.'.freeze
55
+
56
+ def on_heredoc(node)
57
+ if node.loc.heredoc_body.source.empty? ||
58
+ contents_indentation(node) >= closing_indentation(node)
59
+ return if opening_indentation(node) == closing_indentation(node)
60
+ return if node.argument? &&
61
+ opening_indentation(
62
+ find_node_used_heredoc_argument(node.parent)
63
+ ) == closing_indentation(node)
64
+ end
65
+
66
+ add_offense(node, location: :heredoc_end)
67
+ end
68
+
69
+ def autocorrect(node)
70
+ lambda do |corrector|
71
+ corrector.replace(node.loc.heredoc_end, indented_end(node))
72
+ end
73
+ end
74
+
75
+ private
76
+
77
+ def opening_indentation(node)
78
+ indent_level(heredoc_opening(node))
79
+ end
80
+
81
+ def contents_indentation(node)
82
+ source_lines = node.loc.heredoc_body.source.split("\n")
83
+
84
+ source_lines.reject(&:empty?).map do |line|
85
+ indent_level(line)
86
+ end.min
87
+ end
88
+
89
+ def closing_indentation(node)
90
+ indent_level(heredoc_closing(node))
91
+ end
92
+
93
+ def heredoc_opening(node)
94
+ node.loc.expression.source_line
95
+ end
96
+
97
+ def heredoc_closing(node)
98
+ node.loc.heredoc_end.source_line
99
+ end
100
+
101
+ def indented_end(node)
102
+ closing_indent = closing_indentation(node)
103
+ opening_indent = opening_indentation(node)
104
+ closing_text = heredoc_closing(node)
105
+ closing_text.gsub(/^\s{#{closing_indent}}/, ' ' * opening_indent)
106
+ end
107
+
108
+ def find_node_used_heredoc_argument(node)
109
+ if node.parent && node.parent.send_type?
110
+ find_node_used_heredoc_argument(node.parent)
111
+ else
112
+ node
113
+ end
114
+ end
115
+
116
+ def message(node)
117
+ format(
118
+ node.argument? ? MSG_ARG : MSG,
119
+ closing: heredoc_closing(node).strip,
120
+ opening: heredoc_opening(node).strip
121
+ )
122
+ end
123
+
124
+ def indent_level(source_line)
125
+ source_line[/\A */].length
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -89,12 +89,8 @@ module RuboCop
89
89
  end
90
90
 
91
91
  def selector_range(node)
92
- if node.loc.selector
93
- node.loc.selector
94
- else
95
- # l.(1) has no selector, so we use the opening parenthesis instead
96
- node.loc.begin
97
- end
92
+ # l.(1) has no selector, so we use the opening parenthesis instead
93
+ node.loc.selector || node.loc.begin
98
94
  end
99
95
  end
100
96
  end
@@ -30,7 +30,7 @@ module RuboCop
30
30
  '`%<modifier>s`.'.freeze
31
31
 
32
32
  def on_send(node)
33
- return unless node.access_modifier?
33
+ return unless node.bare_access_modifier?
34
34
 
35
35
  return if empty_lines_around?(node)
36
36
 
@@ -1,4 +1,3 @@
1
-
2
1
  # frozen_string_literal: true
3
2
 
4
3
  module RuboCop
@@ -13,12 +13,12 @@ module RuboCop
13
13
  # name = "RuboCop"
14
14
  # # Some comment and an empty line
15
15
  #
16
- # website += "/bbatsov/rubocop" unless cond
16
+ # website += "/rubocop-hq/rubocop" unless cond
17
17
  # puts "rubocop" if debug
18
18
  #
19
19
  # # bad for any configuration
20
20
  # set_app("RuboCop")
21
- # website = "https://github.com/bbatsov/rubocop"
21
+ # website = "https://github.com/rubocop-hq/rubocop"
22
22
  class ExtraSpacing < Cop
23
23
  include PrecedingFollowingAlignment
24
24
  include RangeHelp
@@ -8,7 +8,7 @@ module RuboCop
8
8
  # In Ruby 2.3 or newer, squiggly heredocs (`<<~`) should be used. If you
9
9
  # use the older rubies, you should introduce some library to your project
10
10
  # (e.g. ActiveSupport, Powerpack or Unindent).
11
- # Note: When `Metrics/LineLength`'s `AllowHeredoc` is false(not default),
11
+ # Note: When `Metrics/LineLength`'s `AllowHeredoc` is false (not default),
12
12
  # this cop does not add any offenses for long here documents to
13
13
  # avoid `Metrics/LineLength`'s offenses.
14
14
  #
@@ -193,15 +193,24 @@ module RuboCop
193
193
  return if target_ruby_version < 2.3
194
194
  lambda do |corrector|
195
195
  if heredoc_indent_type(node) == '~'
196
- corrector.replace(node.loc.heredoc_body, indented_body(node))
196
+ adjust_squiggly(corrector, node)
197
197
  else
198
- heredoc_beginning = node.loc.expression.source
199
- corrected = heredoc_beginning.sub(/<<-?/, '<<~')
200
- corrector.replace(node.loc.expression, corrected)
198
+ adjust_minus(corrector, node)
201
199
  end
202
200
  end
203
201
  end
204
202
 
203
+ def adjust_squiggly(corrector, node)
204
+ corrector.replace(node.loc.heredoc_body, indented_body(node))
205
+ corrector.replace(node.loc.heredoc_end, indented_end(node))
206
+ end
207
+
208
+ def adjust_minus(corrector, node)
209
+ heredoc_beginning = node.loc.expression.source
210
+ corrected = heredoc_beginning.sub(/<<-?/, '<<~')
211
+ corrector.replace(node.loc.expression, corrected)
212
+ end
213
+
205
214
  def correct_by_library(node)
206
215
  lambda do |corrector|
207
216
  corrector.replace(node.loc.heredoc_body, indented_body(node))
@@ -230,6 +239,17 @@ module RuboCop
230
239
  body.gsub(/^\s{#{body_indent_level}}/, ' ' * correct_indent_level)
231
240
  end
232
241
 
242
+ def indented_end(node)
243
+ end_ = heredoc_end(node)
244
+ end_indent_level = indent_level(end_)
245
+ correct_indent_level = base_indent_level(node)
246
+ if end_indent_level < correct_indent_level
247
+ end_.gsub(/^\s{#{end_indent_level}}/, ' ' * correct_indent_level)
248
+ else
249
+ end_
250
+ end
251
+ end
252
+
233
253
  def base_indent_level(node)
234
254
  base_line_num = node.loc.expression.line
235
255
  base_line = processed_source.lines[base_line_num - 1]
@@ -255,6 +275,10 @@ module RuboCop
255
275
  def heredoc_body(node)
256
276
  node.loc.heredoc_body.source.scrub
257
277
  end
278
+
279
+ def heredoc_end(node)
280
+ node.loc.heredoc_end.source.scrub
281
+ end
258
282
  end
259
283
  end
260
284
  end
@@ -144,7 +144,7 @@ module RuboCop
144
144
  # the AccessModifierIndentation cop. This cop uses them as dividers
145
145
  # in rails mode. Then consistency is checked only within each
146
146
  # section delimited by a modifier node.
147
- if child.send_type? && child.access_modifier?
147
+ if child.send_type? && child.bare_access_modifier?
148
148
  children_to_check << [] if style == :rails
149
149
  else
150
150
  children_to_check.last << child
@@ -173,7 +173,7 @@ module RuboCop
173
173
  end
174
174
 
175
175
  def special_modifier?(node)
176
- node.access_modifier? && SPECIAL_MODIFIERS.include?(node.source)
176
+ node.bare_access_modifier? && SPECIAL_MODIFIERS.include?(node.source)
177
177
  end
178
178
 
179
179
  def indentation_consistency_style
@@ -307,7 +307,7 @@ module RuboCop
307
307
  return unless body_node.begin_type?
308
308
 
309
309
  starting_node = body_node.children.first
310
- starting_node.send_type? && starting_node.access_modifier?
310
+ starting_node.send_type? && starting_node.bare_access_modifier?
311
311
  end
312
312
 
313
313
  def configured_indentation_width
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Layout
6
+ # This cop checks for unnecessary leading blank lines at the beginning
7
+ # of a file.
8
+ #
9
+ # @example
10
+ #
11
+ # # bad
12
+ # # (start of file)
13
+ #
14
+ # class Foo
15
+ # end
16
+ #
17
+ # # bad
18
+ # # (start of file)
19
+ #
20
+ # # a comment
21
+ #
22
+ # # good
23
+ # # (start of file)
24
+ # class Foo
25
+ # end
26
+ #
27
+ # # good
28
+ # # (start of file)
29
+ # # a comment
30
+ class LeadingBlankLines < Cop
31
+ MSG = 'Unnecessary blank line at the beginning of the source.'.freeze
32
+
33
+ def investigate(processed_source)
34
+ token = processed_source.tokens[0]
35
+ return unless token && token.line > 1
36
+
37
+ add_offense(processed_source.tokens[0],
38
+ location: processed_source.tokens[0].pos)
39
+ end
40
+
41
+ def autocorrect(node)
42
+ range = Parser::Source::Range.new(processed_source.raw_source,
43
+ 0,
44
+ node.begin_pos)
45
+
46
+ lambda do |corrector|
47
+ corrector.remove(range)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -111,10 +111,14 @@ module RuboCop
111
111
  end
112
112
 
113
113
  def left_ref_bracket(node, tokens)
114
- if node.method?(:[]=)
114
+ current_token = tokens.reverse.find(&:left_ref_bracket?)
115
+ previous_token = previous_token(current_token)
116
+
117
+ if node.method?(:[]=) ||
118
+ previous_token && !previous_token.right_bracket?
115
119
  tokens.find(&:left_ref_bracket?)
116
120
  else
117
- tokens.reverse.find(&:left_ref_bracket?)
121
+ current_token
118
122
  end
119
123
  end
120
124
 
@@ -131,6 +135,11 @@ module RuboCop
131
135
  end
132
136
  end
133
137
 
138
+ def previous_token(current_token)
139
+ index = processed_source.tokens.index(current_token)
140
+ index.nil? || index.zero? ? nil : processed_source.tokens[index - 1]
141
+ end
142
+
134
143
  def empty_config
135
144
  cop_config['EnforcedStyleForEmptyBrackets']
136
145
  end
@@ -116,7 +116,7 @@ module RuboCop
116
116
  end
117
117
 
118
118
  def check_send(node, cur_vis)
119
- if node.access_modifier? && !node.method?(:module_function)
119
+ if node.bare_access_modifier? && !node.method?(:module_function)
120
120
  @last_access_modifier = node
121
121
  return node.method_name
122
122
  elsif (methods = private_class_method(node))
@@ -22,12 +22,13 @@ module RuboCop
22
22
  MSG_SELF = 'Use `self` instead of `Object#to_s` in ' \
23
23
  'interpolation.'.freeze
24
24
 
25
+ def_node_matcher :to_s_without_args?, '(send _ :to_s)'
26
+
25
27
  def on_dstr(node)
26
28
  node.each_child_node(:begin) do |begin_node|
27
29
  final_node = begin_node.children.last
28
30
 
29
- next unless final_node && final_node.send_type? &&
30
- final_node.method?(:to_s) && !final_node.arguments?
31
+ next unless to_s_without_args?(final_node)
31
32
 
32
33
  add_offense(final_node, location: :selector)
33
34
  end
@@ -35,7 +36,7 @@ module RuboCop
35
36
 
36
37
  def autocorrect(node)
37
38
  lambda do |corrector|
38
- receiver, _method_name, *_args = *node
39
+ receiver = node.receiver
39
40
  corrector.replace(
40
41
  node.source_range,
41
42
  if receiver
@@ -134,7 +134,7 @@ module RuboCop
134
134
 
135
135
  if node.begin_type?
136
136
  check_scope(node)
137
- elsif node.send_type? && node.access_modifier?
137
+ elsif node.send_type? && node.bare_access_modifier?
138
138
  add_offense(node, message: format(MSG, current: node.method_name))
139
139
  end
140
140
  end
@@ -147,7 +147,7 @@ module RuboCop
147
147
 
148
148
  def check_child_nodes(node, unused, cur_vis)
149
149
  node.child_nodes.each do |child|
150
- if child.send_type? && child.access_modifier?
150
+ if child.send_type? && child.bare_access_modifier?
151
151
  cur_vis, unused =
152
152
  check_new_visibility(child, unused, child.method_name, cur_vis)
153
153
  elsif method_definition?(child)
@@ -8,7 +8,7 @@ module RuboCop
8
8
  private
9
9
 
10
10
  def bracketed_array_of?(element_type, node)
11
- return false unless node.square_brackets? && node.values.size > 1
11
+ return false unless node.square_brackets? && !node.values.empty?
12
12
 
13
13
  node.values.all? { |value| value.type == element_type }
14
14
  end
@@ -63,17 +63,13 @@ module RuboCop
63
63
  def range_by_whole_lines(range, include_final_newline: false)
64
64
  buffer = @processed_source.buffer
65
65
 
66
- begin_pos = range.begin_pos
67
- begin_offset = range.column
68
- begin_of_first_line = begin_pos - begin_offset
69
-
70
66
  last_line = buffer.source_line(range.last_line)
71
- end_pos = range.end_pos
72
67
  end_offset = last_line.length - range.last_column
73
68
  end_offset += 1 if include_final_newline
74
- end_of_last_line = end_pos + end_offset
75
69
 
76
- Parser::Source::Range.new(buffer, begin_of_first_line, end_of_last_line)
70
+ range
71
+ .adjust(begin_pos: -range.column, end_pos: end_offset)
72
+ .intersect(buffer.source_range)
77
73
  end
78
74
 
79
75
  ## Helpers for above range methods. Do not use inside Cops.
@@ -16,7 +16,7 @@ module RuboCop
16
16
  class AssertNot < RuboCop::Cop::Cop
17
17
  MSG = 'Prefer `assert_not` over `assert !`.'.freeze
18
18
 
19
- def_node_matcher :offensive?, '(send nil? :assert (send ... :!))'
19
+ def_node_matcher :offensive?, '(send nil? :assert (send ... :!) ...)'
20
20
 
21
21
  def on_send(node)
22
22
  add_offense(node) if offensive?(node)