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,272 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This Cop checks whether alter queries are combinable.
7
+ # If combinable queries are detected, it suggests to you
8
+ # to use `change_table` with `bulk: true` instead.
9
+ # When use this method, make combinable alter queries
10
+ # a bulk alter query.
11
+ #
12
+ # The `bulk` option is only supported on the MySQL and
13
+ # the PostgreSQL (5.2 later) adapter; thus it will
14
+ # automatically detect an adapter from `development` environment
15
+ # in `config/database.yml` when the `Database` option is not set.
16
+ # If the adapter is not `mysql2` or `postgresql`,
17
+ # this Cop ignores offenses.
18
+ #
19
+ # @example
20
+ # # bad
21
+ # def change
22
+ # add_column :users, :name, :string, null: false
23
+ # add_column :users, :nickname, :string
24
+ #
25
+ # # ALTER TABLE `users` ADD `name` varchar(255) NOT NULL
26
+ # # ALTER TABLE `users` ADD `nickname` varchar(255)
27
+ # end
28
+ #
29
+ # # good
30
+ # def change
31
+ # change_table :users, bulk: true do |t|
32
+ # t.string :name, null: false
33
+ # t.string :nickname
34
+ # end
35
+ #
36
+ # # ALTER TABLE `users` ADD `name` varchar(255) NOT NULL,
37
+ # # ADD `nickname` varchar(255)
38
+ # end
39
+ #
40
+ # @example
41
+ # # bad
42
+ # def change
43
+ # change_table :users do |t|
44
+ # t.string :name, null: false
45
+ # t.string :nickname
46
+ # end
47
+ # end
48
+ #
49
+ # # good
50
+ # def change
51
+ # change_table :users, bulk: true do |t|
52
+ # t.string :name, null: false
53
+ # t.string :nickname
54
+ # end
55
+ # end
56
+ #
57
+ # # good
58
+ # # When you don't want to combine alter queries.
59
+ # def change
60
+ # change_table :users, bulk: false do |t|
61
+ # t.string :name, null: false
62
+ # t.string :nickname
63
+ # end
64
+ # end
65
+ #
66
+ # @see http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-change_table
67
+ # @see http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html
68
+ class BulkChangeTable < Cop
69
+ MSG_FOR_CHANGE_TABLE = <<-MSG.strip_indent.chomp
70
+ You can combine alter queries using `bulk: true` options.
71
+ MSG
72
+ MSG_FOR_ALTER_METHODS = <<-MSG.strip_indent.chomp
73
+ You can use `change_table :%<table>s, bulk: true` to combine alter queries.
74
+ MSG
75
+
76
+ MYSQL = 'mysql'.freeze
77
+ POSTGRESQL = 'postgresql'.freeze
78
+
79
+ MIGRATIION_METHODS = %i[change up down].freeze
80
+
81
+ COMBINABLE_TRANSFORMATIONS = %i[
82
+ primary_key
83
+ column
84
+ string
85
+ text
86
+ integer
87
+ bigint
88
+ float
89
+ decimal
90
+ numeric
91
+ datetime
92
+ timestamp
93
+ time
94
+ date
95
+ binary
96
+ boolean
97
+ json
98
+ virtual
99
+ remove
100
+ change
101
+ timestamps
102
+ remove_timestamps
103
+ ].freeze
104
+
105
+ COMBINABLE_ALTER_METHODS = %i[
106
+ add_column
107
+ remove_column
108
+ remove_columns
109
+ change_column
110
+ add_timestamps
111
+ remove_timestamps
112
+ ].freeze
113
+
114
+ MYSQL_COMBINABLE_TRANSFORMATIONS = %i[
115
+ rename
116
+ index
117
+ remove_index
118
+ ].freeze
119
+
120
+ MYSQL_COMBINABLE_ALTER_METHODS = %i[
121
+ rename_column
122
+ add_index
123
+ remove_index
124
+ ].freeze
125
+
126
+ POSTGRESQL_COMBINABLE_TRANSFORMATIONS = %i[
127
+ change_default
128
+ ].freeze
129
+
130
+ POSTGRESQL_COMBINABLE_ALTER_METHODS = %i[
131
+ change_column_default
132
+ change_column_null
133
+ ].freeze
134
+
135
+ def on_def(node)
136
+ return unless support_bulk_alter?
137
+ return unless MIGRATIION_METHODS.include?(node.method_name)
138
+
139
+ recorder = AlterMethodsRecorder.new
140
+
141
+ node.body.each_child_node(:send) do |send_node|
142
+ if combinable_alter_methods.include?(send_node.method_name)
143
+ recorder.process(send_node)
144
+ else
145
+ recorder.flush
146
+ end
147
+ end
148
+
149
+ recorder.offensive_nodes.each { |n| add_offense_for_alter_methods(n) }
150
+ end
151
+
152
+ def on_send(node)
153
+ return unless support_bulk_alter?
154
+ return unless node.command?(:change_table)
155
+ return if include_bulk_options?(node)
156
+ return unless node.block_node
157
+ send_nodes = node.block_node.body.each_child_node(:send).to_a
158
+
159
+ transformations = send_nodes.select do |send_node|
160
+ combinable_transformations.include?(send_node.method_name)
161
+ end
162
+
163
+ add_offense_for_change_table(node) if transformations.size > 1
164
+ end
165
+
166
+ private
167
+
168
+ # @param node [RuboCop::AST::SendNode] (send nil? :change_table ...)
169
+ def include_bulk_options?(node)
170
+ # arguments: [(sym :table) (hash (pair (sym :bulk) _))]
171
+ options = node.arguments[1]
172
+ return false unless options
173
+ options.hash_type? &&
174
+ options.keys.any? { |key| key.sym_type? && key.value == :bulk }
175
+ end
176
+
177
+ def database
178
+ cop_config['Database'] || database_from_yaml
179
+ end
180
+
181
+ def database_from_yaml
182
+ return nil unless database_yaml
183
+ case database_yaml['adapter']
184
+ when 'mysql2'
185
+ MYSQL
186
+ when 'postgresql'
187
+ POSTGRESQL
188
+ end
189
+ end
190
+
191
+ def database_yaml
192
+ return nil unless File.exist?('config/database.yml')
193
+ yaml = YAML.load_file('config/database.yml')
194
+ return nil unless yaml.is_a? Hash
195
+ config = yaml['development']
196
+ return nil unless config.is_a?(Hash)
197
+ config
198
+ end
199
+
200
+ def support_bulk_alter?
201
+ case database
202
+ when MYSQL
203
+ true
204
+ when POSTGRESQL
205
+ # Add bulk alter support for PostgreSQL in 5.2.0
206
+ # @see https://github.com/rails/rails/pull/31331
207
+ target_rails_version >= 5.2
208
+ else
209
+ false
210
+ end
211
+ end
212
+
213
+ def combinable_alter_methods
214
+ case database
215
+ when MYSQL
216
+ COMBINABLE_ALTER_METHODS + MYSQL_COMBINABLE_ALTER_METHODS
217
+ when POSTGRESQL
218
+ COMBINABLE_ALTER_METHODS + POSTGRESQL_COMBINABLE_ALTER_METHODS
219
+ end
220
+ end
221
+
222
+ def combinable_transformations
223
+ case database
224
+ when MYSQL
225
+ COMBINABLE_TRANSFORMATIONS + MYSQL_COMBINABLE_TRANSFORMATIONS
226
+ when POSTGRESQL
227
+ COMBINABLE_TRANSFORMATIONS + POSTGRESQL_COMBINABLE_TRANSFORMATIONS
228
+ end
229
+ end
230
+
231
+ # @param node [RuboCop::AST::SendNode]
232
+ def add_offense_for_alter_methods(node)
233
+ # arguments: [(sym :table) ...]
234
+ table_name = node.arguments[0].value
235
+ message = format(MSG_FOR_ALTER_METHODS, table: table_name)
236
+ add_offense(node, message: message)
237
+ end
238
+
239
+ # @param node [RuboCop::AST::SendNode]
240
+ def add_offense_for_change_table(node)
241
+ add_offense(node, message: MSG_FOR_CHANGE_TABLE)
242
+ end
243
+
244
+ # Record combinable alter methods and register offensive nodes.
245
+ class AlterMethodsRecorder
246
+ def initialize
247
+ @nodes = []
248
+ @offensive_nodes = []
249
+ end
250
+
251
+ # @param new_node [RuboCop::AST::SendNode]
252
+ def process(new_node)
253
+ # arguments: [(sym :table) ...]
254
+ table_name = new_node.arguments[0]
255
+ flush unless @nodes.all? { |node| node.arguments[0] == table_name }
256
+ @nodes << new_node
257
+ end
258
+
259
+ def flush
260
+ @offensive_nodes << @nodes.first if @nodes.size > 1
261
+ @nodes = []
262
+ end
263
+
264
+ def offensive_nodes
265
+ flush
266
+ @offensive_nodes
267
+ end
268
+ end
269
+ end
270
+ end
271
+ end
272
+ end
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module Rails
6
6
  # This cop checks dynamic `find_by_*` methods.
7
7
  # Use `find_by` instead of dynamic method.
8
- # See. https://github.com/bbatsov/rails-style-guide#find_by
8
+ # See. https://github.com/rubocop-hq/rails-style-guide#find_by
9
9
  #
10
10
  # @example
11
11
  # # bad
@@ -4,21 +4,35 @@ module RuboCop
4
4
  module Cop
5
5
  module Rails
6
6
  # This cop is used to identify usages of file path joining process
7
- # to use `Rails.root.join` clause. This is to avoid bugs on operating
8
- # system that don't use '/' as the path separator.
7
+ # to use `Rails.root.join` clause. It is used to add uniformity when
8
+ # joining paths.
9
9
  #
10
- # @example
11
- # # bad
12
- # Rails.root.join('app/models/goober')
13
- # File.join(Rails.root, 'app/models/goober')
14
- # "#{Rails.root}/app/models/goober"
10
+ # @example EnforcedStyle: arguments (default)
11
+ # # bad
12
+ # Rails.root.join('app/models/goober')
13
+ # File.join(Rails.root, 'app/models/goober')
14
+ # "#{Rails.root}/app/models/goober"
15
+ #
16
+ # # good
17
+ # Rails.root.join('app', 'models', 'goober')
18
+ #
19
+ # @example EnforcedStyle: slashes
20
+ # # bad
21
+ # Rails.root.join('app', 'models', 'goober')
22
+ # File.join(Rails.root, 'app/models/goober')
23
+ # "#{Rails.root}/app/models/goober"
24
+ #
25
+ # # good
26
+ # Rails.root.join('app/models/goober')
15
27
  #
16
- # # good
17
- # Rails.root.join('app', 'models', 'goober')
18
28
  class FilePath < Cop
29
+ include ConfigurableEnforcedStyle
19
30
  include RangeHelp
20
31
 
21
- MSG = 'Please use `Rails.root.join(\'path\', \'to\')` instead.'.freeze
32
+ MSG_SLASHES = 'Please use `Rails.root.join(\'path/to\')` ' \
33
+ 'instead.'.freeze
34
+ MSG_ARGUMENTS = 'Please use `Rails.root.join(\'path\', \'to\')` ' \
35
+ 'instead.'.freeze
22
36
 
23
37
  def_node_matcher :file_join_nodes?, <<-PATTERN
24
38
  (send (const nil? :File) :join ...)
@@ -43,6 +57,7 @@ module RuboCop
43
57
  def on_send(node)
44
58
  check_for_file_join_with_rails_root(node)
45
59
  check_for_rails_root_join_with_slash_separated_path(node)
60
+ check_for_rails_root_join_with_string_arguments(node)
46
61
  end
47
62
 
48
63
  private
@@ -54,7 +69,18 @@ module RuboCop
54
69
  register_offense(node)
55
70
  end
56
71
 
72
+ def check_for_rails_root_join_with_string_arguments(node)
73
+ return unless style == :slashes
74
+ return unless rails_root_nodes?(node)
75
+ return unless rails_root_join_nodes?(node)
76
+ return unless node.arguments.size > 1
77
+ return unless node.arguments.all?(&:str_type?)
78
+
79
+ register_offense(node)
80
+ end
81
+
57
82
  def check_for_rails_root_join_with_slash_separated_path(node)
83
+ return unless style == :arguments
58
84
  return unless rails_root_nodes?(node)
59
85
  return unless rails_root_join_nodes?(node)
60
86
  return unless node.arguments.any? { |arg| string_with_slash?(arg) }
@@ -72,6 +98,10 @@ module RuboCop
72
98
  line_range)
73
99
  add_offense(node, location: source_range)
74
100
  end
101
+
102
+ def message(_node)
103
+ format(style == :arguments ? MSG_ARGUMENTS : MSG_SLASHES)
104
+ end
75
105
  end
76
106
  end
77
107
  end
@@ -22,7 +22,7 @@ module RuboCop
22
22
  MSG = 'Use keyword arguments instead of ' \
23
23
  'positional arguments for http call: `%<verb>s`.'.freeze
24
24
  KEYWORD_ARGS = %i[
25
- method params session body flash xhr as
25
+ method params session body flash xhr as headers env
26
26
  ].freeze
27
27
  HTTP_METHODS = %i[get post put patch delete head].freeze
28
28
 
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module Rails
6
6
  # This cop checks for the use of Time methods without zone.
7
7
  #
8
- # Built on top of Ruby on Rails style guide (https://github.com/bbatsov/rails-style-guide#time)
8
+ # Built on top of Ruby on Rails style guide (https://github.com/rubocop-hq/rails-style-guide#time)
9
9
  # and the article http://danilenko.org/2012/7/6/rails_timezones/ .
10
10
  #
11
11
  # Two styles are supported for this cop. When EnforcedStyle is 'strict'
@@ -66,8 +66,8 @@ module RuboCop
66
66
  parse at current].freeze
67
67
 
68
68
  ACCEPTED_METHODS = %i[in_time_zone utc getlocal
69
- iso8601 jisx0301 rfc3339
70
- to_i to_f].freeze
69
+ xmlschema iso8601 jisx0301 rfc3339
70
+ httpdate to_i to_f].freeze
71
71
 
72
72
  def on_const(node)
73
73
  mod, klass = *node
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Access modifiers should be declared to apply to a group of methods
7
+ # or inline before each method, depending on configuration.
8
+ #
9
+ # @example EnforcedStyle: group (default)
10
+ #
11
+ # # bad
12
+ #
13
+ # class Foo
14
+ #
15
+ # private def bar; end
16
+ # private def baz; end
17
+ #
18
+ # end
19
+ #
20
+ # # good
21
+ #
22
+ # class Foo
23
+ #
24
+ # private
25
+ #
26
+ # def bar; end
27
+ # def baz; end
28
+ #
29
+ # end
30
+ # @example EnforcedStyle: inline
31
+ #
32
+ # # bad
33
+ #
34
+ # class Foo
35
+ #
36
+ # private
37
+ #
38
+ # def bar; end
39
+ # def baz; end
40
+ #
41
+ # end
42
+ #
43
+ # # good
44
+ #
45
+ # class Foo
46
+ #
47
+ # private def bar; end
48
+ # private def baz; end
49
+ #
50
+ # end
51
+ class AccessModifierDeclarations < Cop
52
+ include ConfigurableEnforcedStyle
53
+
54
+ GROUP_STYLE_MESSAGE = [
55
+ '`%<access_modifier>s` should not be',
56
+ 'inlined in method definitions.'
57
+ ].join(' ')
58
+
59
+ INLINE_STYLE_MESSAGE = [
60
+ '`%<access_modifier>s` should be',
61
+ 'inlined in method definitions.'
62
+ ].join(' ')
63
+
64
+ def on_send(node)
65
+ return unless node.access_modifier?
66
+
67
+ if offense?(node)
68
+ add_offense(node, location: :selector) do
69
+ opposite_style_detected
70
+ end
71
+ else
72
+ correct_style_detected
73
+ end
74
+ end
75
+
76
+ private
77
+
78
+ def offense?(node)
79
+ (group_style? && access_modifier_is_inlined?(node)) ||
80
+ (inline_style? && access_modifier_is_not_inlined?(node))
81
+ end
82
+
83
+ def group_style?
84
+ style == :group
85
+ end
86
+
87
+ def inline_style?
88
+ style == :inline
89
+ end
90
+
91
+ def access_modifier_is_inlined?(node)
92
+ node.arguments.any?
93
+ end
94
+
95
+ def access_modifier_is_not_inlined?(node)
96
+ !access_modifier_is_inlined?(node)
97
+ end
98
+
99
+ def message(node)
100
+ access_modifier = node.loc.selector.source
101
+
102
+ if group_style?
103
+ format(GROUP_STYLE_MESSAGE, access_modifier: access_modifier)
104
+ elsif inline_style?
105
+ format(INLINE_STYLE_MESSAGE, access_modifier: access_modifier)
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end