rubocop 0.56.0 → 0.57.0

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