rubocop 1.23.0 → 1.24.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +45 -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 +5 -5
  15. data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +46 -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/incompatible_io_select_with_fiber_scheduler.rb +4 -0
  27. data/lib/rubocop/cop/metrics/block_length.rb +1 -0
  28. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -9
  29. data/lib/rubocop/cop/metrics/method_length.rb +1 -0
  30. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  31. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  32. data/lib/rubocop/cop/mixin/enforce_superclass.rb +5 -0
  33. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +4 -3
  34. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +56 -0
  35. data/lib/rubocop/cop/naming/block_forwarding.rb +102 -0
  36. data/lib/rubocop/cop/security/open.rb +11 -1
  37. data/lib/rubocop/cop/style/character_literal.rb +8 -1
  38. data/lib/rubocop/cop/style/collection_compact.rb +31 -13
  39. data/lib/rubocop/cop/style/combinable_loops.rb +2 -2
  40. data/lib/rubocop/cop/style/empty_case_condition.rb +10 -0
  41. data/lib/rubocop/cop/style/file_read.rb +112 -0
  42. data/lib/rubocop/cop/style/file_write.rb +98 -0
  43. data/lib/rubocop/cop/style/hash_conversion.rb +2 -1
  44. data/lib/rubocop/cop/style/hash_syntax.rb +22 -0
  45. data/lib/rubocop/cop/style/if_inside_else.rb +15 -0
  46. data/lib/rubocop/cop/style/map_to_hash.rb +68 -0
  47. data/lib/rubocop/cop/style/numeric_literals.rb +10 -1
  48. data/lib/rubocop/cop/style/one_line_conditional.rb +18 -39
  49. data/lib/rubocop/cop/style/redundant_interpolation.rb +17 -3
  50. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +5 -1
  51. data/lib/rubocop/cop/style/redundant_self.rb +1 -1
  52. data/lib/rubocop/cop/style/safe_navigation.rb +1 -5
  53. data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
  54. data/lib/rubocop/cop/style/sole_nested_conditional.rb +3 -1
  55. data/lib/rubocop/cop/team.rb +1 -1
  56. data/lib/rubocop/options.rb +6 -1
  57. data/lib/rubocop/remote_config.rb +1 -3
  58. data/lib/rubocop/result_cache.rb +1 -1
  59. data/lib/rubocop/version.rb +1 -1
  60. data/lib/rubocop.rb +7 -0
  61. 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: 3080860c5102e2d42274c71316c7d9910e6e26019c9f39005e38fba136657c8e
4
+ data.tar.gz: 879fa716afcb1051f05f0ebc6832291cfb06655763e1aaac752cf6997096bcf2
5
5
  SHA512:
6
- metadata.gz: 4014183525b58378a0e628ae5136d17c148a41c6c25dd51eddc810ca08fbd89d652f6c715b58eef149005af1145469936416864869b6e63a4c9e521627ab1cb4
7
- data.tar.gz: 6e0e2a9a9d6fae829b73bd49814965a28d447207aaf7d1dda073f34130343557df965c77cc998d6ddb0d59eca09f1307d6ca56cbd3fcade575ca52950d1a56d3
6
+ metadata.gz: 21bd87b421b7cae8c95a44cdfc9ef85e4b4259fc08bfd53b37f02f16d9808ef487d1ec385a4e5047fed1d3358cf185f8bc2ca2bfa504eeedd05c47d4ea9cb411
7
+ data.tar.gz: 933d030bae14fbaf659e21901ab49db9418dcb8afcaff33b68d765c9fa47576f6c957fe1b0771f23a3faa94c100353f739298d85b68c8a96e65b6b15c1a8f60e
data/README.md CHANGED
@@ -54,7 +54,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
54
54
  in your `Gemfile`:
55
55
 
56
56
  ```rb
57
- gem 'rubocop', '~> 1.23', require: false
57
+ gem 'rubocop', '~> 1.24', require: false
58
58
  ```
59
59
 
60
60
  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,15 @@ Naming/BinaryOperatorParameterName:
2479
2487
  VersionAdded: '0.50'
2480
2488
  VersionChanged: '1.2'
2481
2489
 
2490
+ Naming/BlockForwarding:
2491
+ Description: 'Use anonymous block forwarding.'
2492
+ Enabled: pending
2493
+ VersionAdded: '1.24'
2494
+ EnforcedStyle: anonymous
2495
+ SupportedStyles:
2496
+ - anonymous
2497
+ - explicit
2498
+
2482
2499
  Naming/BlockParameterName:
2483
2500
  Description: >-
2484
2501
  Checks for block parameter names that contain capital letters,
@@ -3492,6 +3509,18 @@ Style/ExponentialNotation:
3492
3509
  - engineering
3493
3510
  - integral
3494
3511
 
3512
+ Style/FileRead:
3513
+ Description: 'Favor `File.(bin)read` convenience methods.'
3514
+ StyleGuide: '#file-read'
3515
+ Enabled: pending
3516
+ VersionAdded: '1.24'
3517
+
3518
+ Style/FileWrite:
3519
+ Description: 'Favor `File.(bin)write` convenience methods.'
3520
+ StyleGuide: '#file-write'
3521
+ Enabled: pending
3522
+ VersionAdded: '1.24'
3523
+
3495
3524
  Style/FloatDivision:
3496
3525
  Description: 'For performing float division, coerce one side only.'
3497
3526
  StyleGuide: '#float-division'
@@ -3650,7 +3679,7 @@ Style/HashSyntax:
3650
3679
  StyleGuide: '#hash-literals'
3651
3680
  Enabled: true
3652
3681
  VersionAdded: '0.9'
3653
- VersionChanged: '0.43'
3682
+ VersionChanged: '1.24'
3654
3683
  EnforcedStyle: ruby19
3655
3684
  SupportedStyles:
3656
3685
  # checks for 1.9 syntax (e.g. {a: 1}) for all symbol keys
@@ -3661,6 +3690,13 @@ Style/HashSyntax:
3661
3690
  - no_mixed_keys
3662
3691
  # enforces both ruby19 and no_mixed_keys styles
3663
3692
  - ruby19_no_mixed_keys
3693
+ # Force hashes that have a hash value omission
3694
+ EnforcedShorthandSyntax: always
3695
+ SupportedShorthandSyntax:
3696
+ # forces use of the 3.1 syntax (e.g. {foo:}) when the hash key and value are the same.
3697
+ - always
3698
+ # forces use of explicit hash literal value.
3699
+ - never
3664
3700
  # Force hashes that have a symbol value to use hash rockets
3665
3701
  UseHashRocketsWithSymbolValues: false
3666
3702
  # Do not suggest { a?: 1 } over { :a? => 1 } in ruby19 style
@@ -3837,6 +3873,12 @@ Style/LineEndConcatenation:
3837
3873
  VersionAdded: '0.18'
3838
3874
  VersionChanged: '0.64'
3839
3875
 
3876
+ Style/MapToHash:
3877
+ Description: 'Prefer `to_h` with a block over `map.to_h`.'
3878
+ Enabled: pending
3879
+ VersionAdded: '1.24'
3880
+ Safe: false
3881
+
3840
3882
  Style/MethodCallWithArgsParentheses:
3841
3883
  Description: 'Use parentheses for method calls with arguments.'
3842
3884
  StyleGuide: '#method-invocation-parens'
@@ -4205,6 +4247,8 @@ Style/NumericLiterals:
4205
4247
  VersionChanged: '0.48'
4206
4248
  MinDigits: 5
4207
4249
  Strict: false
4250
+ # You can specify allowed numbers. (e.g. port number 3000, 8080, and etc)
4251
+ AllowedNumbers: []
4208
4252
 
4209
4253
  Style/NumericPredicate:
4210
4254
  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
@@ -0,0 +1,46 @@
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
+
37
+ range = range_between(dispatch_node.loc.dot.begin_pos, dispatch_node.loc.selector.end_pos)
38
+
39
+ add_offense(range) do |corrector|
40
+ corrector.remove(range)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ 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)
@@ -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
 
@@ -50,6 +50,7 @@ module RuboCop
50
50
 
51
51
  check_code_length(node)
52
52
  end
53
+ alias on_numblock on_block
53
54
 
54
55
  private
55
56
 
@@ -46,15 +46,6 @@ module RuboCop
46
46
  1
47
47
  end
48
48
 
49
- def block_method(node)
50
- case node.type
51
- when :block
52
- node.method_name
53
- when :block_pass
54
- node.parent.method_name
55
- end
56
- end
57
-
58
49
  def count_block?(block)
59
50
  KNOWN_ITERATING_METHODS.include? block.method_name
60
51
  end
@@ -52,6 +52,7 @@ module RuboCop
52
52
 
53
53
  check_code_length(node)
54
54
  end
55
+ alias on_numblock on_block
55
56
 
56
57
  private
57
58
 
@@ -44,7 +44,7 @@ module RuboCop
44
44
 
45
45
  # @!method module_definition?(node)
46
46
  def_node_matcher :module_definition?, <<~PATTERN
47
- (casgn nil? _ (block (send (const {nil? cbase} :Module) :new) ...))
47
+ (casgn nil? _ ({block numblock} (send (const {nil? cbase} :Module) :new) ...))
48
48
  PATTERN
49
49
 
50
50
  def message(length, max_length)