rubocop 0.69.0 → 0.70.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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +17 -1
  4. data/lib/rubocop.rb +1 -0
  5. data/lib/rubocop/ast/builder.rb +37 -37
  6. data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +10 -0
  7. data/lib/rubocop/cached_data.rb +2 -2
  8. data/lib/rubocop/config.rb +9 -1
  9. data/lib/rubocop/config_loader.rb +2 -2
  10. data/lib/rubocop/config_loader_resolver.rb +3 -2
  11. data/lib/rubocop/cop/generator.rb +7 -1
  12. data/lib/rubocop/cop/layout/align_hash.rb +74 -31
  13. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +6 -6
  14. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +75 -4
  15. data/lib/rubocop/cop/layout/indentation_width.rb +1 -7
  16. data/lib/rubocop/cop/lint/ambiguous_operator.rb +5 -5
  17. data/lib/rubocop/cop/lint/handle_exceptions.rb +47 -8
  18. data/lib/rubocop/cop/lint/number_conversion.rb +7 -0
  19. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +3 -0
  20. data/lib/rubocop/cop/mixin/configurable_naming.rb +1 -1
  21. data/lib/rubocop/cop/mixin/configurable_numbering.rb +2 -2
  22. data/lib/rubocop/cop/mixin/ignored_method_patterns.rb +19 -0
  23. data/lib/rubocop/cop/rails/refute_methods.rb +13 -13
  24. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +17 -3
  25. data/lib/rubocop/cop/variable_force/scope.rb +3 -3
  26. data/lib/rubocop/formatter/formatter_set.rb +13 -13
  27. data/lib/rubocop/formatter/html_formatter.rb +4 -4
  28. data/lib/rubocop/formatter/json_formatter.rb +16 -16
  29. data/lib/rubocop/formatter/simple_text_formatter.rb +4 -4
  30. data/lib/rubocop/options.rb +89 -83
  31. data/lib/rubocop/version.rb +1 -1
  32. metadata +4 -24
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1ceeff27cb7a9a5422da99021b22d3d729445de0cfc8db0fcd451a7b59644564
4
- data.tar.gz: 975afb9f919e4b698091be763cbe0ae668aff0a76e79eea297eaf46113156049
3
+ metadata.gz: f98c70ae4897b3f4c793fa73cb716986f9d63815928c278accf6879a0190e97e
4
+ data.tar.gz: 89111e2312bdf926aab76ca58bfb90a414ff3b5f58ba48257e5d1949763d4776
5
5
  SHA512:
6
- metadata.gz: 502807f9a65b63922679174a7e32e7232d1191ea30b06199811f2c7485cdd47b02548a576f88e6bbadee9ed5e2a525eec570674d6b69fdfe5bfa2843edad465f
7
- data.tar.gz: fdd08613fb4d3292b99f2b9764df4b91981b5c31300c879cfdd80203f2965b8994187dff36f79e0c16c38665f9b76bf93ad57f1b0df834a42ffe9aa057f82070
6
+ metadata.gz: 83462908a6383ab72503c4af338d395a118e435d8f4f73e7cdda54b6d8d1cc05f40a5ebdb6a3197bf9a2734046665c7c2d6616e0bb0847f198d11b410ae4b7f8
7
+ data.tar.gz: 39c1a0fca5a9251e3a60f9ca3958d228d79f5797de21da608f69cb133611c683913673bbdc426a537c9578bc4394607a20617d394d1abc3454878373589a0fdd
data/README.md CHANGED
@@ -53,7 +53,7 @@ haven't reached version 1.0 yet). To prevent an unwanted RuboCop update you
53
53
  might want to use a conservative version lock in your `Gemfile`:
54
54
 
55
55
  ```rb
56
- gem 'rubocop', '~> 0.69.0', require: false
56
+ gem 'rubocop', '~> 0.70.0', require: false
57
57
  ```
58
58
 
59
59
  ## Quickstart
@@ -260,6 +260,7 @@ Layout/AlignHash:
260
260
  Align the elements of a hash literal if they span more than
261
261
  one line.
262
262
  Enabled: true
263
+ AllowMultipleStyles: true
263
264
  VersionAdded: '0.49'
264
265
  # Alignment of entries using hash rocket as separator. Valid values are:
265
266
  #
@@ -508,6 +509,13 @@ Layout/EmptyLinesAroundAccessModifier:
508
509
  StyleGuide: '#empty-lines-around-access-modifier'
509
510
  Enabled: true
510
511
  VersionAdded: '0.49'
512
+ EnforcedStyle: around
513
+ SupportedStyles:
514
+ - around
515
+ - only_before
516
+ Reference:
517
+ # A reference to `EnforcedStyle: only_before`.
518
+ - https://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html#follow-the-coding-conventions
511
519
 
512
520
  Layout/EmptyLinesAroundArguments:
513
521
  Description: "Keeps track of empty lines around method arguments."
@@ -780,6 +788,9 @@ Layout/IndentationConsistency:
780
788
  SupportedStyles:
781
789
  - normal
782
790
  - rails
791
+ Reference:
792
+ # A reference to `EnforcedStyle: rails`.
793
+ - https://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html#follow-the-coding-conventions
783
794
 
784
795
  Layout/IndentationWidth:
785
796
  Description: 'Use 2 spaces for indentation.'
@@ -1359,7 +1370,9 @@ Lint/HandleExceptions:
1359
1370
  Description: "Don't suppress exception."
1360
1371
  StyleGuide: '#dont-hide-exceptions'
1361
1372
  Enabled: true
1373
+ AllowComments: false
1362
1374
  VersionAdded: '0.9'
1375
+ VersionChanged: '0.70'
1363
1376
 
1364
1377
  Lint/HeredocMethodCallPosition:
1365
1378
  Description: >-
@@ -1462,6 +1475,8 @@ Lint/NumberConversion:
1462
1475
  Description: 'Checks unsafe usage of number conversion methods.'
1463
1476
  Enabled: false
1464
1477
  VersionAdded: '0.53'
1478
+ VersionChanged: '0.70'
1479
+ SafeAutoCorrect: false
1465
1480
 
1466
1481
  Lint/OrderedMagicComments:
1467
1482
  Description: 'Checks the proper ordering of magic comments and whether a magic comment is not placed before a shebang.'
@@ -3752,8 +3767,9 @@ Style/PreferredHashMethods:
3752
3767
  Description: 'Checks use of `has_key?` and `has_value?` Hash methods.'
3753
3768
  StyleGuide: '#hash-key'
3754
3769
  Enabled: true
3770
+ Safe: false
3755
3771
  VersionAdded: '0.41'
3756
- VersionChanged: '0.44'
3772
+ VersionChanged: '0.70'
3757
3773
  EnforcedStyle: short
3758
3774
  SupportedStyles:
3759
3775
  - short
@@ -117,6 +117,7 @@ require_relative 'rubocop/cop/mixin/frozen_string_literal'
117
117
  require_relative 'rubocop/cop/mixin/hash_alignment'
118
118
  require_relative 'rubocop/cop/mixin/ignored_pattern'
119
119
  require_relative 'rubocop/cop/mixin/ignored_methods'
120
+ require_relative 'rubocop/cop/mixin/ignored_method_patterns'
120
121
  require_relative 'rubocop/cop/mixin/integer_node'
121
122
  require_relative 'rubocop/cop/mixin/match_range'
122
123
  require_relative 'rubocop/cop/mixin/method_complexity'
@@ -15,45 +15,45 @@ module RuboCop
15
15
  # root_node = parser.parse(buffer)
16
16
  class Builder < Parser::Builders::Default
17
17
  NODE_MAP = {
18
- and: AndNode,
19
- alias: AliasNode,
20
- args: ArgsNode,
21
- array: ArrayNode,
22
- block: BlockNode,
23
- break: BreakNode,
24
- case: CaseNode,
25
- class: ClassNode,
26
- def: DefNode,
27
- defined?: DefinedNode,
28
- defs: DefNode,
29
- ensure: EnsureNode,
30
- for: ForNode,
31
- hash: HashNode,
32
- if: IfNode,
33
- irange: RangeNode,
34
- erange: RangeNode,
35
- kwsplat: KeywordSplatNode,
36
- module: ModuleNode,
37
- or: OrNode,
38
- pair: PairNode,
39
- regexp: RegexpNode,
40
- resbody: ResbodyNode,
41
- retry: RetryNode,
42
- csend: SendNode,
43
- send: SendNode,
44
- str: StrNode,
45
- dstr: StrNode,
46
- xstr: StrNode,
47
- sclass: SelfClassNode,
48
- super: SuperNode,
49
- zsuper: SuperNode,
50
- sym: SymbolNode,
51
- until: UntilNode,
18
+ and: AndNode,
19
+ alias: AliasNode,
20
+ args: ArgsNode,
21
+ array: ArrayNode,
22
+ block: BlockNode,
23
+ break: BreakNode,
24
+ case: CaseNode,
25
+ class: ClassNode,
26
+ def: DefNode,
27
+ defined?: DefinedNode,
28
+ defs: DefNode,
29
+ ensure: EnsureNode,
30
+ for: ForNode,
31
+ hash: HashNode,
32
+ if: IfNode,
33
+ irange: RangeNode,
34
+ erange: RangeNode,
35
+ kwsplat: KeywordSplatNode,
36
+ module: ModuleNode,
37
+ or: OrNode,
38
+ pair: PairNode,
39
+ regexp: RegexpNode,
40
+ resbody: ResbodyNode,
41
+ retry: RetryNode,
42
+ csend: SendNode,
43
+ send: SendNode,
44
+ str: StrNode,
45
+ dstr: StrNode,
46
+ xstr: StrNode,
47
+ sclass: SelfClassNode,
48
+ super: SuperNode,
49
+ zsuper: SuperNode,
50
+ sym: SymbolNode,
51
+ until: UntilNode,
52
52
  until_post: UntilNode,
53
- when: WhenNode,
54
- while: WhileNode,
53
+ when: WhenNode,
54
+ while: WhileNode,
55
55
  while_post: WhileNode,
56
- yield: YieldNode
56
+ yield: YieldNode
57
57
  }.freeze
58
58
 
59
59
  # Generates {Node} from the given information.
@@ -9,6 +9,7 @@ module RuboCop
9
9
  include MethodIdentifierPredicates
10
10
 
11
11
  ARITHMETIC_OPERATORS = %i[+ - * / % **].freeze
12
+ SPECIAL_MODIFIERS = %w[private protected].freeze
12
13
 
13
14
  # The receiving node of the method dispatch.
14
15
  #
@@ -75,6 +76,15 @@ module RuboCop
75
76
  macro? && non_bare_access_modifier_declaration?
76
77
  end
77
78
 
79
+ # Checks whether the dispatched method is a bare `private` or `protected`
80
+ # access modifier that affects all methods defined after the macro.
81
+ #
82
+ # @return [Boolean] whether the dispatched method is a bare
83
+ # `private` or `protected` access modifier
84
+ def special_modifier?
85
+ bare_access_modifier? && SPECIAL_MODIFIERS.include?(source)
86
+ end
87
+
78
88
  # Checks whether the name of the dispatched method matches the argument
79
89
  # and has an implicit receiver.
80
90
  #
@@ -29,9 +29,9 @@ module RuboCop
29
29
  begin_pos: offense.location.begin_pos,
30
30
  end_pos: offense.location.end_pos
31
31
  },
32
- message: message(offense),
32
+ message: message(offense),
33
33
  cop_name: offense.cop_name,
34
- status: :uncorrected
34
+ status: :uncorrected
35
35
  }
36
36
  end
37
37
 
@@ -543,8 +543,10 @@ module RuboCop
543
543
  styles.each do |style_name, style|
544
544
  supported_key = RuboCop::Cop::Util.to_supported_styles(style_name)
545
545
  valid = ConfigLoader.default_configuration[name][supported_key]
546
+
546
547
  next unless valid
547
548
  next if valid.include?(style)
549
+ next if validate_support_and_has_list(name, style, valid)
548
550
 
549
551
  msg = "invalid #{style_name} '#{style}' for #{name} found in " \
550
552
  "#{smart_loaded_path}\n" \
@@ -554,6 +556,12 @@ module RuboCop
554
556
  end
555
557
  end
556
558
 
559
+ def validate_support_and_has_list(name, formats, valid)
560
+ ConfigLoader.default_configuration[name]['AllowMultipleStyles'] &&
561
+ formats.is_a?(Array) &&
562
+ formats.all? { |format| valid.include?(format) }
563
+ end
564
+
557
565
  def reject_obsolete_cops_and_parameters
558
566
  messages = [
559
567
  obsolete_cops,
@@ -712,7 +720,7 @@ module RuboCop
712
720
  end
713
721
  end
714
722
 
715
- cop_options.fetch('Enabled', true)
723
+ cop_options.fetch('Enabled') { !for_all_cops['DisabledByDefault'] }
716
724
  end
717
725
 
718
726
  def smart_loaded_path
@@ -120,8 +120,8 @@ module RuboCop
120
120
  # If AllCops::EnabledByDefault is true, it changes the Enabled params
121
121
  # so that only cops explicitly disabled in user configuration are
122
122
  # disabled.
123
- def merge_with_default(config, config_file)
124
- resolver.merge_with_default(config, config_file)
123
+ def merge_with_default(config, config_file, unset_nil: true)
124
+ resolver.merge_with_default(config, config_file, unset_nil: unset_nil)
125
125
  end
126
126
 
127
127
  def add_inheritance_from_auto_generated_file
@@ -55,7 +55,7 @@ module RuboCop
55
55
  # only cops from user configuration are enabled. If
56
56
  # AllCops::EnabledByDefault is true, it changes the Enabled params so that
57
57
  # only cops explicitly disabled in user configuration are disabled.
58
- def merge_with_default(config, config_file)
58
+ def merge_with_default(config, config_file, unset_nil:)
59
59
  default_configuration = ConfigLoader.default_configuration
60
60
 
61
61
  disabled_by_default = config.for_all_cops['DisabledByDefault']
@@ -71,7 +71,8 @@ module RuboCop
71
71
  config = handle_disabled_by_default(config, default_configuration)
72
72
  end
73
73
 
74
- opts = { inherit_mode: config['inherit_mode'] || {}, unset_nil: true }
74
+ opts = { inherit_mode: config['inherit_mode'] || {},
75
+ unset_nil: unset_nil }
75
76
  Config.new(merge(default_configuration, config, opts), config_file)
76
77
  end
77
78
 
@@ -7,7 +7,13 @@ module RuboCop
7
7
  # This generator will take a cop name and generate a source file
8
8
  # and spec file when given a valid qualified cop name.
9
9
  class Generator
10
- SOURCE_TEMPLATE = <<~RUBY
10
+ # Note: RDoc 5.1.0 or lower has the following issue.
11
+ # https://github.com/rubocop-hq/rubocop/issues/7043
12
+ #
13
+ # The following `String#strip_indent` can be replaced with
14
+ # squiggly heredoc when RuboCop supports Ruby 2.5 or higher
15
+ # (RDoc 6.0 or higher).
16
+ SOURCE_TEMPLATE = <<-RUBY.strip_indent
11
17
  # frozen_string_literal: true
12
18
 
13
19
  # TODO: when finished, run `rake generate_cops_documentation` to update the docs
@@ -17,7 +17,9 @@ module RuboCop
17
17
  # - always_inspect
18
18
  # - always_ignore
19
19
  # - ignore_implicit (without curly braces)
20
- # - ignore_explicit (with curly braces)
20
+ #
21
+ # Alternatively you can specify multiple allowed styles. That's done by
22
+ # passing a list of styles to EnforcedStyles.
21
23
  #
22
24
  # @example EnforcedHashRocketStyle: key (default)
23
25
  # # bad
@@ -198,48 +200,65 @@ module RuboCop
198
200
  return if ignored_node?(node)
199
201
  return if node.pairs.empty? || node.single_line?
200
202
 
201
- return unless alignment_for_hash_rockets.checkable_layout?(node) &&
202
- alignment_for_colons.checkable_layout?(node)
203
+ return unless alignment_for_hash_rockets
204
+ .any? { |a| a.checkable_layout?(node) } &&
205
+ alignment_for_colons
206
+ .any? { |a| a.checkable_layout?(node) }
203
207
 
204
208
  check_pairs(node)
205
209
  end
206
210
 
207
211
  def autocorrect(node)
208
- # We can't use the instance variable inside the lambda. That would
209
- # just give each lambda the same reference and they would all get the
210
- # last value of each. A local variable fixes the problem.
211
- key_delta = column_deltas[:key] || 0
212
+ delta = column_deltas[alignment_for(node).first.class][node]
213
+ return if delta.nil?
212
214
 
213
- if !node.value
214
- correct_no_value(key_delta, node.source_range)
215
- else
216
- correct_key_value(key_delta, node.key.source_range,
217
- node.value.source_range,
218
- node.loc.operator)
219
- end
215
+ correct_node(node, delta)
220
216
  end
221
217
 
222
- private
223
-
218
+ attr_accessor :offences_by
224
219
  attr_accessor :column_deltas
225
220
 
221
+ private
222
+
226
223
  def double_splat?(node)
227
224
  node.children.last.is_a?(Symbol)
228
225
  end
229
226
 
230
227
  def check_pairs(node)
231
228
  first_pair = node.pairs.first
232
- self.column_deltas = alignment_for(first_pair)
233
- .deltas_for_first_pair(first_pair, node)
234
- add_offense(first_pair) unless good_alignment?
229
+ self.offences_by = {}
230
+ self.column_deltas = Hash.new { |hash, key| hash[key] = {} }
231
+
232
+ alignment_for(first_pair).each do |alignment|
233
+ delta = alignment.deltas_for_first_pair(first_pair, node)
234
+ check_delta delta, node: first_pair, alignment: alignment
235
+ end
235
236
 
236
237
  node.children.each do |current|
237
- self.column_deltas = alignment_for(current)
238
- .deltas(first_pair, current)
239
- add_offense(current) unless good_alignment?
238
+ alignment_for(current).each do |alignment|
239
+ delta = alignment.deltas(first_pair, current)
240
+ check_delta delta, node: current, alignment: alignment
241
+ end
242
+ end
243
+
244
+ add_offences
245
+ end
246
+
247
+ def add_offences
248
+ _format, offences = offences_by.min_by { |_, v| v.length }
249
+ (offences || []).each do |offence|
250
+ add_offense offence
240
251
  end
241
252
  end
242
253
 
254
+ def check_delta(delta, node:, alignment:)
255
+ offences_by[alignment.class] ||= []
256
+ return if good_alignment? delta
257
+
258
+ column_deltas[alignment.class][node] = delta
259
+ offences_by[alignment.class].push(node)
260
+ end
261
+
243
262
  def ignore_hash_argument?(node)
244
263
  case cop_config['EnforcedLastArgumentHashStyle']
245
264
  when 'always_inspect' then false
@@ -267,16 +286,31 @@ module RuboCop
267
286
  new_alignment('EnforcedColonStyle')
268
287
  end
269
288
 
289
+ def correct_node(node, delta)
290
+ # We can't use the instance variable inside the lambda. That would
291
+ # just give each lambda the same reference and they would all get the
292
+ # last value of each. A local variable fixes the problem.
293
+
294
+ if !node.value
295
+ correct_no_value(delta[:key] || 0, node.source_range)
296
+ else
297
+ correct_key_value(delta, node.key.source_range,
298
+ node.value.source_range,
299
+ node.loc.operator)
300
+ end
301
+ end
302
+
270
303
  def correct_no_value(key_delta, key)
271
304
  ->(corrector) { adjust(corrector, key_delta, key) }
272
305
  end
273
306
 
274
- def correct_key_value(key_delta, key, value, separator)
307
+ def correct_key_value(delta, key, value, separator)
275
308
  # We can't use the instance variable inside the lambda. That would
276
309
  # just give each lambda the same reference and they would all get the
277
310
  # last value of each. Some local variables fix the problem.
278
- separator_delta = column_deltas[:separator] || 0
279
- value_delta = column_deltas[:value] || 0
311
+ separator_delta = delta[:separator] || 0
312
+ value_delta = delta[:value] || 0
313
+ key_delta = delta[:key] || 0
280
314
 
281
315
  key_column = key.column
282
316
  key_delta = -key_column if key_delta < -key_column
@@ -289,11 +323,20 @@ module RuboCop
289
323
  end
290
324
 
291
325
  def new_alignment(key)
292
- case cop_config[key]
293
- when 'key' then KeyAlignment.new
294
- when 'table' then TableAlignment.new
295
- when 'separator' then SeparatorAlignment.new
296
- else raise "Unknown #{key}: #{cop_config[key]}"
326
+ formats = cop_config[key]
327
+ formats = [formats] if formats.is_a? String
328
+
329
+ formats.uniq.map do |format|
330
+ case format
331
+ when 'key'
332
+ KeyAlignment.new
333
+ when 'table'
334
+ TableAlignment.new
335
+ when 'separator'
336
+ SeparatorAlignment.new
337
+ else
338
+ raise "Unknown #{key}: #{formats}"
339
+ end
297
340
  end
298
341
  end
299
342
 
@@ -306,7 +349,7 @@ module RuboCop
306
349
  end
307
350
  end
308
351
 
309
- def good_alignment?
352
+ def good_alignment?(column_deltas)
310
353
  column_deltas.values.all?(&:zero?)
311
354
  end
312
355
  end