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,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