rubocop 1.23.0 → 1.24.1

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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -2
  3. data/config/default.yml +46 -1
  4. data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
  5. data/lib/rubocop/cli/command/init_dotfile.rb +1 -1
  6. data/lib/rubocop/cli/command/show_docs_url.rb +48 -0
  7. data/lib/rubocop/cli/command/suggest_extensions.rb +1 -1
  8. data/lib/rubocop/cli.rb +1 -0
  9. data/lib/rubocop/config_loader_resolver.rb +1 -1
  10. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
  11. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +1 -1
  12. data/lib/rubocop/cop/correctors/if_then_corrector.rb +55 -0
  13. data/lib/rubocop/cop/documentation.rb +19 -2
  14. data/lib/rubocop/cop/gemspec/require_mfa.rb +8 -10
  15. data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +47 -0
  16. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +3 -1
  17. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  18. data/lib/rubocop/cop/layout/comment_indentation.rb +31 -2
  19. data/lib/rubocop/cop/layout/dot_position.rb +4 -0
  20. data/lib/rubocop/cop/layout/hash_alignment.rb +1 -1
  21. data/lib/rubocop/cop/layout/space_after_colon.rb +1 -1
  22. data/lib/rubocop/cop/layout/space_before_first_arg.rb +4 -0
  23. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +1 -1
  24. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +16 -4
  25. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +6 -0
  26. data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -1
  27. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +4 -0
  28. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +7 -4
  29. data/lib/rubocop/cop/metrics/block_length.rb +1 -0
  30. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -9
  31. data/lib/rubocop/cop/metrics/method_length.rb +1 -0
  32. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  33. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  34. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +1 -1
  35. data/lib/rubocop/cop/mixin/enforce_superclass.rb +5 -0
  36. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +4 -3
  37. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +56 -0
  38. data/lib/rubocop/cop/naming/block_forwarding.rb +107 -0
  39. data/lib/rubocop/cop/security/open.rb +11 -1
  40. data/lib/rubocop/cop/style/character_literal.rb +8 -1
  41. data/lib/rubocop/cop/style/collection_compact.rb +31 -13
  42. data/lib/rubocop/cop/style/combinable_loops.rb +2 -2
  43. data/lib/rubocop/cop/style/empty_case_condition.rb +10 -0
  44. data/lib/rubocop/cop/style/file_read.rb +112 -0
  45. data/lib/rubocop/cop/style/file_write.rb +124 -0
  46. data/lib/rubocop/cop/style/hash_conversion.rb +2 -1
  47. data/lib/rubocop/cop/style/hash_syntax.rb +22 -0
  48. data/lib/rubocop/cop/style/hash_transform_keys.rb +6 -6
  49. data/lib/rubocop/cop/style/hash_transform_values.rb +6 -6
  50. data/lib/rubocop/cop/style/if_inside_else.rb +15 -0
  51. data/lib/rubocop/cop/style/map_to_hash.rb +68 -0
  52. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +13 -0
  53. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +3 -1
  54. data/lib/rubocop/cop/style/method_def_parentheses.rb +17 -13
  55. data/lib/rubocop/cop/style/numeric_literals.rb +10 -1
  56. data/lib/rubocop/cop/style/one_line_conditional.rb +18 -39
  57. data/lib/rubocop/cop/style/redundant_interpolation.rb +17 -3
  58. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +5 -1
  59. data/lib/rubocop/cop/style/redundant_self.rb +1 -1
  60. data/lib/rubocop/cop/style/safe_navigation.rb +1 -5
  61. data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
  62. data/lib/rubocop/cop/style/sole_nested_conditional.rb +3 -1
  63. data/lib/rubocop/cop/team.rb +1 -1
  64. data/lib/rubocop/cop/util.rb +9 -1
  65. data/lib/rubocop/options.rb +6 -1
  66. data/lib/rubocop/remote_config.rb +1 -3
  67. data/lib/rubocop/result_cache.rb +1 -1
  68. data/lib/rubocop/version.rb +1 -1
  69. data/lib/rubocop.rb +7 -0
  70. metadata +13 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf11fe2d8f8be8879d6afc63d6f3be50b970c7910c83f1d22847d1fc9654d4aa
4
- data.tar.gz: fd4c7ef3838a286efe3d1729672cc7a0e72f47cfb4c8d815699d53d2a974a372
3
+ metadata.gz: a2e7d2cbe48c6ff81a071b353132db29ed017af57a32bcd142038e2e551f3a5b
4
+ data.tar.gz: 8ae72a3ce8b6ab13b4d451bbdb1dbcdf54f898711a3009dae81450a49fb037e0
5
5
  SHA512:
6
- metadata.gz: 4014183525b58378a0e628ae5136d17c148a41c6c25dd51eddc810ca08fbd89d652f6c715b58eef149005af1145469936416864869b6e63a4c9e521627ab1cb4
7
- data.tar.gz: 6e0e2a9a9d6fae829b73bd49814965a28d447207aaf7d1dda073f34130343557df965c77cc998d6ddb0d59eca09f1307d6ca56cbd3fcade575ca52950d1a56d3
6
+ metadata.gz: d868781732056622d0f5157a50553c0b521f81f2ca14d2ede65b4c7372ef0e3b89be5146db8664fac5b28a39c82be52fc297a43d8280647b1b7426ce9ee87337
7
+ data.tar.gz: e3d8f4dc8ab53859197eb3f05c62290cf72ba11c7e742869d619d6c4564e28f5c0fc70e4e15f90fc4f9bfe2d46cafdeedde8aa16d982adfc7d6eb482f7d20093
data/README.md CHANGED
@@ -9,7 +9,6 @@
9
9
  [![Actions Status](https://github.com/rubocop/rubocop/workflows/CI/badge.svg?branch=master)](https://github.com/rubocop/rubocop/actions?query=workflow%3ACI)
10
10
  [![Test Coverage](https://api.codeclimate.com/v1/badges/d2d67f728e88ea84ac69/test_coverage)](https://codeclimate.com/github/rubocop/rubocop/test_coverage)
11
11
  [![Maintainability](https://api.codeclimate.com/v1/badges/d2d67f728e88ea84ac69/maintainability)](https://codeclimate.com/github/rubocop/rubocop/maintainability)
12
- [![SemVer](https://api.dependabot.com/badges/compatibility_score?dependency-name=rubocop&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=rubocop&package-manager=bundler&version-scheme=semver)
13
12
  [![Discord](https://img.shields.io/badge/chat-on%20discord-7289da.svg?sanitize=true)](https://discord.gg/wJjWvGRDmm)
14
13
 
15
14
  > Role models are important. <br/>
@@ -54,7 +53,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
54
53
  in your `Gemfile`:
55
54
 
56
55
  ```rb
57
- gem 'rubocop', '~> 1.23', require: false
56
+ gem 'rubocop', '~> 1.24', require: false
58
57
  ```
59
58
 
60
59
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
data/config/default.yml CHANGED
@@ -78,6 +78,8 @@ AllCops:
78
78
  # When specifying style guide URLs, any paths and/or fragments will be
79
79
  # evaluated relative to the base URL.
80
80
  StyleGuideBaseURL: https://rubystyle.guide
81
+ # Documentation URLs will be constructed using the base URL.
82
+ DocumentationBaseURL: https://docs.rubocop.org/rubocop
81
83
  # Extra details are not displayed in offense messages by default. Change
82
84
  # behavior by overriding ExtraDetails, or by giving the
83
85
  # `-E/--extra-details` option.
@@ -449,7 +451,11 @@ Layout/ClosingParenthesisIndentation:
449
451
  Layout/CommentIndentation:
450
452
  Description: 'Indentation of comments.'
451
453
  Enabled: true
454
+ # When true, allows comments to have extra indentation if that aligns them
455
+ # with a comment on the preceding line.
456
+ AllowForAlignment: false
452
457
  VersionAdded: '0.49'
458
+ VersionChanged: '1.24'
453
459
 
454
460
  Layout/ConditionPosition:
455
461
  Description: >-
@@ -1796,7 +1802,9 @@ Lint/ImplicitStringConcatenation:
1796
1802
  Lint/IncompatibleIoSelectWithFiberScheduler:
1797
1803
  Description: 'Checks for `IO.select` that is incompatible with Fiber Scheduler.'
1798
1804
  Enabled: pending
1805
+ SafeAutoCorrect: false
1799
1806
  VersionAdded: '1.21'
1807
+ VersionChanged: '1.24'
1800
1808
 
1801
1809
  Lint/IneffectiveAccessModifier:
1802
1810
  Description: >-
@@ -2479,6 +2487,16 @@ Naming/BinaryOperatorParameterName:
2479
2487
  VersionAdded: '0.50'
2480
2488
  VersionChanged: '1.2'
2481
2489
 
2490
+ Naming/BlockForwarding:
2491
+ Description: 'Use anonymous block forwarding.'
2492
+ StyleGuide: '#block-forwarding'
2493
+ Enabled: pending
2494
+ VersionAdded: '1.24'
2495
+ EnforcedStyle: anonymous
2496
+ SupportedStyles:
2497
+ - anonymous
2498
+ - explicit
2499
+
2482
2500
  Naming/BlockParameterName:
2483
2501
  Description: >-
2484
2502
  Checks for block parameter names that contain capital letters,
@@ -3492,6 +3510,18 @@ Style/ExponentialNotation:
3492
3510
  - engineering
3493
3511
  - integral
3494
3512
 
3513
+ Style/FileRead:
3514
+ Description: 'Favor `File.(bin)read` convenience methods.'
3515
+ StyleGuide: '#file-read'
3516
+ Enabled: pending
3517
+ VersionAdded: '1.24'
3518
+
3519
+ Style/FileWrite:
3520
+ Description: 'Favor `File.(bin)write` convenience methods.'
3521
+ StyleGuide: '#file-write'
3522
+ Enabled: pending
3523
+ VersionAdded: '1.24'
3524
+
3495
3525
  Style/FloatDivision:
3496
3526
  Description: 'For performing float division, coerce one side only.'
3497
3527
  StyleGuide: '#float-division'
@@ -3650,7 +3680,7 @@ Style/HashSyntax:
3650
3680
  StyleGuide: '#hash-literals'
3651
3681
  Enabled: true
3652
3682
  VersionAdded: '0.9'
3653
- VersionChanged: '0.43'
3683
+ VersionChanged: '1.24'
3654
3684
  EnforcedStyle: ruby19
3655
3685
  SupportedStyles:
3656
3686
  # checks for 1.9 syntax (e.g. {a: 1}) for all symbol keys
@@ -3661,6 +3691,13 @@ Style/HashSyntax:
3661
3691
  - no_mixed_keys
3662
3692
  # enforces both ruby19 and no_mixed_keys styles
3663
3693
  - ruby19_no_mixed_keys
3694
+ # Force hashes that have a hash value omission
3695
+ EnforcedShorthandSyntax: always
3696
+ SupportedShorthandSyntax:
3697
+ # forces use of the 3.1 syntax (e.g. {foo:}) when the hash key and value are the same.
3698
+ - always
3699
+ # forces use of explicit hash literal value.
3700
+ - never
3664
3701
  # Force hashes that have a symbol value to use hash rockets
3665
3702
  UseHashRocketsWithSymbolValues: false
3666
3703
  # Do not suggest { a?: 1 } over { :a? => 1 } in ruby19 style
@@ -3837,6 +3874,12 @@ Style/LineEndConcatenation:
3837
3874
  VersionAdded: '0.18'
3838
3875
  VersionChanged: '0.64'
3839
3876
 
3877
+ Style/MapToHash:
3878
+ Description: 'Prefer `to_h` with a block over `map.to_h`.'
3879
+ Enabled: pending
3880
+ VersionAdded: '1.24'
3881
+ Safe: false
3882
+
3840
3883
  Style/MethodCallWithArgsParentheses:
3841
3884
  Description: 'Use parentheses for method calls with arguments.'
3842
3885
  StyleGuide: '#method-invocation-parens'
@@ -4205,6 +4248,8 @@ Style/NumericLiterals:
4205
4248
  VersionChanged: '0.48'
4206
4249
  MinDigits: 5
4207
4250
  Strict: false
4251
+ # You can specify allowed numbers. (e.g. port number 3000, 8080, and etc)
4252
+ AllowedNumbers: []
4208
4253
 
4209
4254
  Style/NumericPredicate:
4210
4255
  Description: >-
@@ -124,7 +124,7 @@ module RuboCop
124
124
  lines = /\S/.match?(rubocop_yml_contents) ? rubocop_yml_contents.split("\n", -1) : []
125
125
  doc_start_index = lines.index { |line| YAML_OPTIONAL_DOC_START.match?(line) } || -1
126
126
  lines.insert(doc_start_index + 1, "inherit_from:#{file_string}\n")
127
- File.open(file_name, 'w') { |f| f.write lines.join("\n") }
127
+ File.write(file_name, lines.join("\n"))
128
128
  end
129
129
  end
130
130
  end
@@ -31,7 +31,7 @@ module RuboCop
31
31
  # See https://docs.rubocop.org/rubocop/configuration
32
32
  DESC
33
33
 
34
- File.open(DOTFILE, 'w') { |f| f.write(description) }
34
+ File.write(DOTFILE, description)
35
35
 
36
36
  puts "Writing new #{DOTFILE} to #{path}"
37
37
 
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ class CLI
5
+ module Command
6
+ # Prints out url to documentation of provided cops
7
+ # or documentation base url by default.
8
+ # @api private
9
+ class ShowDocsUrl < Base
10
+ self.command_name = :show_docs_url
11
+
12
+ def initialize(env)
13
+ super
14
+
15
+ @config = @config_store.for(Dir.pwd)
16
+ end
17
+
18
+ def run
19
+ print_documentation_url
20
+ end
21
+
22
+ private
23
+
24
+ def print_documentation_url
25
+ puts Cop::Documentation.default_base_url if cops_array.empty?
26
+
27
+ cops_array.each do |cop_name|
28
+ cop = registry_hash[cop_name]
29
+
30
+ next if cop.empty?
31
+
32
+ puts Cop::Documentation.url_for(cop.first, @config)
33
+ end
34
+
35
+ puts
36
+ end
37
+
38
+ def cops_array
39
+ @cops_array ||= @options[:show_docs_url]
40
+ end
41
+
42
+ def registry_hash
43
+ @registry_hash ||= Cop::Registry.global.to_h
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -22,7 +22,7 @@ module RuboCop
22
22
  'RuboCop extension libraries might be helpful:'
23
23
 
24
24
  extensions.sort.each do |extension|
25
- puts " * #{extension} (https://github.com/rubocop/#{extension})"
25
+ puts " * #{extension} (https://rubygems.org/gems/#{extension})"
26
26
  end
27
27
 
28
28
  puts
data/lib/rubocop/cli.rb CHANGED
@@ -131,6 +131,7 @@ module RuboCop
131
131
 
132
132
  run_command(:version) if @options[:version] || @options[:verbose_version]
133
133
  run_command(:show_cops) if @options[:show_cops]
134
+ run_command(:show_docs_url) if @options[:show_docs_url]
134
135
  raise Finished
135
136
  end
136
137
 
@@ -74,7 +74,7 @@ module RuboCop
74
74
  # Merges the given configuration with the default one. If
75
75
  # AllCops:DisabledByDefault is true, it changes the Enabled params so that
76
76
  # only cops from user configuration are enabled. If
77
- # AllCops::EnabledByDefault is true, it changes the Enabled params so that
77
+ # AllCops:EnabledByDefault is true, it changes the Enabled params so that
78
78
  # only cops explicitly disabled in user configuration are disabled.
79
79
  def merge_with_default(config, config_file, unset_nil:)
80
80
  default_configuration = ConfigLoader.default_configuration
@@ -68,7 +68,7 @@ module RuboCop
68
68
  end
69
69
 
70
70
  def conditional_declaration?(nodes)
71
- parent = nodes[0].parent
71
+ parent = nodes[0].each_ancestor.find { |ancestor| !ancestor.begin_type? }
72
72
  return false unless parent&.if_type? || parent&.when_type?
73
73
 
74
74
  root_conditional_node = parent.if_type? ? parent : parent.parent
@@ -11,7 +11,7 @@ module RuboCop
11
11
 
12
12
  def initialize(block_node)
13
13
  @block_node = block_node
14
- @collection_node = block_node.send_node.receiver
14
+ @collection_node = block_node.receiver
15
15
  @argument_node = block_node.arguments
16
16
  end
17
17
 
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # This class auto-corrects `if...then` structures to a multiline `if` statement
6
+ class IfThenCorrector
7
+ DEFAULT_INDENTATION_WIDTH = 2
8
+
9
+ def initialize(if_node, indentation: nil)
10
+ @if_node = if_node
11
+ @indentation = indentation || DEFAULT_INDENTATION_WIDTH
12
+ end
13
+
14
+ def call(corrector)
15
+ corrector.replace(if_node, replacement)
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :if_node, :indentation
21
+
22
+ def replacement(node = if_node, indentation = nil)
23
+ indentation = ' ' * node.source_range.column if indentation.nil?
24
+ if_branch_source = node.if_branch&.source || 'nil'
25
+ elsif_indentation = indentation if node.respond_to?(:elsif?) && node.elsif?
26
+
27
+ if_branch = <<~RUBY
28
+ #{elsif_indentation}#{node.keyword} #{node.condition.source}
29
+ #{indentation}#{branch_body_indentation}#{if_branch_source}
30
+ RUBY
31
+
32
+ else_branch = rewrite_else_branch(node.else_branch, indentation)
33
+ if_branch + else_branch
34
+ end
35
+
36
+ def rewrite_else_branch(else_branch, indentation)
37
+ if else_branch.nil?
38
+ 'end'
39
+ elsif else_branch.if_type? && else_branch.elsif?
40
+ replacement(else_branch, indentation)
41
+ else
42
+ <<~RUBY.chomp
43
+ #{indentation}else
44
+ #{indentation}#{branch_body_indentation}#{else_branch.source}
45
+ #{indentation}end
46
+ RUBY
47
+ end
48
+ end
49
+
50
+ def branch_body_indentation
51
+ @branch_body_indentation ||= (' ' * indentation).freeze
52
+ end
53
+ end
54
+ end
55
+ end
@@ -12,10 +12,27 @@ module RuboCop
12
12
  end
13
13
 
14
14
  # @api private
15
- def url_for(cop_class)
15
+ def url_for(cop_class, config = nil)
16
16
  base = department_to_basename(cop_class.department)
17
17
  fragment = cop_class.cop_name.downcase.gsub(/[^a-z]/, '')
18
- "https://docs.rubocop.org/rubocop/#{base}.html##{fragment}"
18
+ base_url = base_url_for(cop_class, config)
19
+
20
+ "#{base_url}/#{base}.html##{fragment}"
21
+ end
22
+
23
+ # @api private
24
+ def base_url_for(cop_class, config)
25
+ return default_base_url unless config
26
+
27
+ department_name = cop_class.department.to_s
28
+
29
+ config.for_department(department_name)['DocumentationBaseURL'] ||
30
+ config.for_all_cops['DocumentationBaseURL']
31
+ end
32
+
33
+ # @api private
34
+ def default_base_url
35
+ 'https://docs.rubocop.org/rubocop'
19
36
  end
20
37
  end
21
38
  end
@@ -6,18 +6,18 @@ module RuboCop
6
6
  # Requires a gemspec to have `rubygems_mfa_required` metadata set.
7
7
  #
8
8
  # This setting tells RubyGems that MFA is required for accounts to
9
- # be able perform any of these privileged operations:
9
+ # be able perform privileged operations, such as (see
10
+ # RubyGems' documentation for the full list of privileged operations):
10
11
  #
11
- # * gem push
12
- # * gem yank
13
- # * gem owner --add/remove
12
+ # * `gem push`
13
+ # * `gem yank`
14
+ # * `gem owner --add/remove`
14
15
  # * adding or removing owners using gem ownership page
15
16
  #
16
17
  # This helps make your gem more secure, as users can be more
17
18
  # confident that gem updates were pushed by maintainers.
18
19
  #
19
20
  # @example
20
- #
21
21
  # # bad
22
22
  # Gem::Specification.new do |spec|
23
23
  # # no `rubygems_mfa_required` metadata specified
@@ -117,7 +117,7 @@ module RuboCop
117
117
 
118
118
  correct_metadata(corrector, metadata)
119
119
  else
120
- correct_missing_metadata(corrector, node, block_var)
120
+ insert_mfa_required(corrector, node, block_var)
121
121
  end
122
122
  end
123
123
 
@@ -129,11 +129,9 @@ module RuboCop
129
129
  end
130
130
  end
131
131
 
132
- def correct_missing_metadata(corrector, node, block_var)
132
+ def insert_mfa_required(corrector, node, block_var)
133
133
  corrector.insert_before(node.loc.end, <<~RUBY)
134
- #{block_var}.metadata = {
135
- 'rubygems_mfa_required' => 'true'
136
- }
134
+ #{block_var}.metadata['rubygems_mfa_required'] = 'true'
137
135
  RUBY
138
136
  end
139
137
 
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # Checks for redundant `send_node` method dispatch node.
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ # node.send_node.method_name
12
+ #
13
+ # # good
14
+ # node.method_name
15
+ #
16
+ # # bad
17
+ # node.send_node.receiver
18
+ #
19
+ # # good
20
+ # node.receiver
21
+ #
22
+ class RedundantMethodDispatchNode < Base
23
+ include RangeHelp
24
+ extend AutoCorrector
25
+
26
+ MSG = 'Remove the redundant `send_node`.'
27
+ RESTRICT_ON_SEND = %i[method_name receiver].freeze
28
+
29
+ # @!method dispatch_method(node)
30
+ def_node_matcher :dispatch_method, <<~PATTERN
31
+ (send $(send _ :send_node) _)
32
+ PATTERN
33
+
34
+ def on_send(node)
35
+ return unless (dispatch_node = dispatch_method(node))
36
+ return unless (dot = dispatch_node.loc.dot)
37
+
38
+ range = range_between(dot.begin_pos, dispatch_node.loc.selector.end_pos)
39
+
40
+ add_offense(range) do |corrector|
41
+ corrector.remove(range)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -14,7 +14,9 @@ module RuboCop
14
14
 
15
15
  # @!method cop_class_def(node)
16
16
  def_node_search :cop_class_def, <<~PATTERN
17
- (class _ (const _ {:Base :Cop}) ...)
17
+ (class _
18
+ (const {nil? (const nil? :Cop) (const (const {cbase nil?} :RuboCop) :Cop)}
19
+ {:Base :Cop}) ...)
18
20
  PATTERN
19
21
 
20
22
  # @!method cop_config_accessor?(node)
@@ -13,6 +13,7 @@ require_relative 'internal_affairs/redundant_described_class_as_subject'
13
13
  require_relative 'internal_affairs/redundant_let_rubocop_config_new'
14
14
  require_relative 'internal_affairs/redundant_location_argument'
15
15
  require_relative 'internal_affairs/redundant_message_argument'
16
+ require_relative 'internal_affairs/redundant_method_dispatch_node'
16
17
  require_relative 'internal_affairs/style_detected_api_use'
17
18
  require_relative 'internal_affairs/undefined_config'
18
19
  require_relative 'internal_affairs/useless_message_assertion'
@@ -32,6 +32,19 @@ module RuboCop
32
32
  # true
33
33
  # end
34
34
  #
35
+ # @example AllowForAlignment: false (default)
36
+ # # bad
37
+ # a = 1 # A really long comment
38
+ # # spanning two lines.
39
+ #
40
+ # # good
41
+ # # A really long comment spanning one line.
42
+ # a = 1
43
+ #
44
+ # @example AllowForAlignment: true
45
+ # # good
46
+ # a = 1 # A really long comment
47
+ # # spanning two lines.
35
48
  class CommentIndentation < Base
36
49
  include Alignment
37
50
  extend AutoCorrector
@@ -40,7 +53,7 @@ module RuboCop
40
53
  'instead of %<correct_comment_indentation>d).'
41
54
 
42
55
  def on_new_investigation
43
- processed_source.comments.each { |comment| check(comment) }
56
+ processed_source.comments.each_with_index { |comment, ix| check(comment, ix) }
44
57
  end
45
58
 
46
59
  private
@@ -76,7 +89,7 @@ module RuboCop
76
89
  AlignmentCorrector.correct(corrector, processed_source, comment, @column_delta)
77
90
  end
78
91
 
79
- def check(comment)
92
+ def check(comment, comment_index)
80
93
  return unless own_line_comment?(comment)
81
94
 
82
95
  next_line = line_after_comment(comment)
@@ -94,11 +107,27 @@ module RuboCop
94
107
  return if column == correct_comment_indentation
95
108
  end
96
109
 
110
+ return if correctly_aligned_with_preceding_comment?(comment_index, column)
111
+
97
112
  add_offense(comment, message: message(column, correct_comment_indentation)) do |corrector|
98
113
  autocorrect(corrector, comment)
99
114
  end
100
115
  end
101
116
 
117
+ # Returns true if:
118
+ # a) the cop is configured to allow extra indentation for alignment, and
119
+ # b) the currently inspected comment is aligned with the nearest preceding end-of-line
120
+ # comment.
121
+ def correctly_aligned_with_preceding_comment?(comment_index, column)
122
+ return false unless cop_config['AllowForAlignment']
123
+
124
+ processed_source.comments[0...comment_index].reverse_each do |other_comment|
125
+ return other_comment.loc.column == column unless own_line_comment?(other_comment)
126
+ end
127
+
128
+ false
129
+ end
130
+
102
131
  def message(column, correct_comment_indentation)
103
132
  format(MSG, column: column, correct_comment_indentation: correct_comment_indentation)
104
133
  end
@@ -27,6 +27,10 @@ module RuboCop
27
27
  include RangeHelp
28
28
  extend AutoCorrector
29
29
 
30
+ def self.autocorrect_incompatible_with
31
+ [Style::RedundantSelf]
32
+ end
33
+
30
34
  def on_send(node)
31
35
  return unless node.dot? || ampersand_dot?(node)
32
36
 
@@ -313,7 +313,7 @@ module RuboCop
313
313
  # just give each lambda the same reference and they would all get the
314
314
  # last value of each. A local variable fixes the problem.
315
315
 
316
- if node.value
316
+ if node.value && node.respond_to?(:value_omission?) && !node.value_omission?
317
317
  correct_key_value(corrector, delta, node.key.source_range,
318
318
  node.value.source_range,
319
319
  node.loc.operator)
@@ -19,7 +19,7 @@ module RuboCop
19
19
  MSG = 'Space missing after colon.'
20
20
 
21
21
  def on_pair(node)
22
- return unless node.colon?
22
+ return if !node.colon? || node.value_omission?
23
23
 
24
24
  colon = node.loc.operator
25
25
 
@@ -28,6 +28,10 @@ module RuboCop
28
28
 
29
29
  MSG = 'Put one space between the method name and the first argument.'
30
30
 
31
+ def self.autocorrect_incompatible_with
32
+ [Style::MethodCallWithArgsParentheses]
33
+ end
34
+
31
35
  def on_send(node)
32
36
  return unless regular_method_call_with_arguments?(node)
33
37
 
@@ -92,7 +92,7 @@ module RuboCop
92
92
  private
93
93
 
94
94
  def method_name(node)
95
- node.ancestors.find(&:block_type?).send_node.method_name
95
+ node.ancestors.find(&:block_type?).method_name
96
96
  end
97
97
  end
98
98
  end
@@ -12,6 +12,7 @@ module RuboCop
12
12
  # File.exists?(some_path)
13
13
  # Dir.exists?(some_path)
14
14
  # iterator?
15
+ # ENV.freeze # Calling `Env.freeze` raises `TypeError` since Ruby 2.7.
15
16
  # Socket.gethostbyname(host)
16
17
  # Socket.gethostbyaddr(host)
17
18
  #
@@ -22,6 +23,7 @@ module RuboCop
22
23
  # File.exist?(some_path)
23
24
  # Dir.exist?(some_path)
24
25
  # block_given?
26
+ # ENV # `ENV.freeze` cannot prohibit changes to environment variables.
25
27
  # Addrinfo.getaddrinfo(nodename, service)
26
28
  # Addrinfo.tcp(host, port).getnameinfo
27
29
  class DeprecatedClassMethods < Base
@@ -106,6 +108,9 @@ module RuboCop
106
108
 
107
109
  DeprecatedClassMethod.new(:iterator?) => Replacement.new(:block_given?),
108
110
 
111
+ DeprecatedClassMethod.new(:freeze, class_constant: :ENV) =>
112
+ Replacement.new(nil, class_constant: :ENV),
113
+
109
114
  DeprecatedClassMethod.new(:gethostbyaddr, class_constant: :Socket, correctable: false) =>
110
115
  Replacement.new(:getnameinfo, class_constant: :Addrinfo, instance_method: true),
111
116
 
@@ -120,11 +125,18 @@ module RuboCop
120
125
 
121
126
  def on_send(node)
122
127
  check(node) do |deprecated|
123
- message = format(MSG, current: deprecated, prefer: replacement(deprecated))
128
+ prefer = replacement(deprecated)
129
+ message = format(MSG, current: deprecated, prefer: prefer)
130
+ current_method = node.loc.selector
131
+
132
+ add_offense(current_method, message: message) do |corrector|
133
+ next unless deprecated.correctable?
124
134
 
125
- add_offense(node.loc.selector, message: message) do |corrector|
126
- if deprecated.correctable?
127
- corrector.replace(node.loc.selector, replacement(deprecated).method)
135
+ if (preferred_method = prefer.method)
136
+ corrector.replace(current_method, preferred_method)
137
+ else
138
+ corrector.remove(node.loc.dot)
139
+ corrector.remove(current_method)
128
140
  end
129
141
  end
130
142
  end
@@ -55,8 +55,14 @@ module RuboCop
55
55
  ...)
56
56
  PATTERN
57
57
 
58
+ # @!method digest_const?(node)
59
+ def_node_matcher :digest_const?, <<~PATTERN
60
+ (const _ :Digest)
61
+ PATTERN
62
+
58
63
  def on_send(node)
59
64
  return if node.arguments.any? { |arg| arg.variable? || arg.send_type? || arg.const_type? }
65
+ return if digest_const?(node.receiver)
60
66
  return unless algorithm_const(node)
61
67
 
62
68
  message = message(node)
@@ -27,7 +27,7 @@ module RuboCop
27
27
 
28
28
  # @!method each_with_object?(node)
29
29
  def_node_matcher :each_with_object?, <<~PATTERN
30
- ({send csend} _ :each_with_object $_)
30
+ (call _ :each_with_object $_)
31
31
  PATTERN
32
32
 
33
33
  def on_send(node)
@@ -20,6 +20,10 @@ module RuboCop
20
20
  # # good
21
21
  # io.wait_writable(timeout)
22
22
  #
23
+ # @safety
24
+ # This cop's autocorrection is unsafe because `NoMethodError` occurs
25
+ # if `require 'io/wait'` is not called.
26
+ #
23
27
  class IncompatibleIoSelectWithFiberScheduler < Base
24
28
  extend AutoCorrector
25
29