rubocop 1.37.0 → 1.38.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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +6 -0
  4. data/lib/rubocop/cli/command/suggest_extensions.rb +8 -1
  5. data/lib/rubocop/comment_config.rb +36 -1
  6. data/lib/rubocop/cop/commissioner.rb +3 -1
  7. data/lib/rubocop/cop/internal_affairs/create_empty_file.rb +37 -0
  8. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +111 -0
  9. data/lib/rubocop/cop/internal_affairs.rb +2 -0
  10. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  11. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  12. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +2 -0
  13. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +6 -2
  14. data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
  15. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +18 -3
  16. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +11 -0
  17. data/lib/rubocop/cop/lint/redundant_require_statement.rb +10 -2
  18. data/lib/rubocop/cop/mixin/surrounding_space.rb +4 -3
  19. data/lib/rubocop/cop/registry.rb +10 -4
  20. data/lib/rubocop/cop/style/access_modifier_declarations.rb +3 -1
  21. data/lib/rubocop/cop/style/block_delimiters.rb +1 -1
  22. data/lib/rubocop/cop/style/character_literal.rb +1 -1
  23. data/lib/rubocop/cop/style/collection_compact.rb +6 -2
  24. data/lib/rubocop/cop/style/guard_clause.rb +62 -21
  25. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +25 -2
  26. data/lib/rubocop/cop/style/module_function.rb +28 -6
  27. data/lib/rubocop/cop/style/operator_method_call.rb +2 -1
  28. data/lib/rubocop/cop/style/redundant_each.rb +111 -0
  29. data/lib/rubocop/cop/style/redundant_string_escape.rb +13 -5
  30. data/lib/rubocop/cop/team.rb +3 -4
  31. data/lib/rubocop/cop/variable_force/variable_table.rb +1 -1
  32. data/lib/rubocop/cops_documentation_generator.rb +4 -2
  33. data/lib/rubocop/ext/processed_source.rb +2 -0
  34. data/lib/rubocop/formatter/offense_count_formatter.rb +8 -5
  35. data/lib/rubocop/formatter/worst_offenders_formatter.rb +6 -3
  36. data/lib/rubocop/options.rb +6 -2
  37. data/lib/rubocop/rspec/cop_helper.rb +21 -1
  38. data/lib/rubocop/rspec/shared_contexts.rb +13 -12
  39. data/lib/rubocop/runner.rb +15 -11
  40. data/lib/rubocop/server/core.rb +1 -0
  41. data/lib/rubocop/version.rb +1 -1
  42. data/lib/rubocop.rb +1 -0
  43. metadata +8 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e928a8547def9cafd9cddc36b5a407aef7d46fdf9825941c7906073492d88668
4
- data.tar.gz: 3ef9727850f93815ba310b7c3a8cf74e53a0ee18a0fcf6731fd97a3640ffe28d
3
+ metadata.gz: 1ed47ef39bb205db15249a399d0502f730c2656f712293357651cc0ddd328715
4
+ data.tar.gz: 5e6411a2b459e0ac426e0ef0d8b8508b9b1693fea0c5b8cb5d82ed23f71d39b9
5
5
  SHA512:
6
- metadata.gz: f57e5d25375fe47734a6e198924db74b341501762dc8f54277a888788ab821215c96847940cec1af4d90673fe79ab906b451bf25bec90f9c8c080e78efc01111
7
- data.tar.gz: 69cafbca956eaa49887596d255f6888057ede94f3621349398de95da5c477201f7bee7eae074ab4750ce0131dcb26d6dfdc77c31f5fcb478d2fc25d5ca73e68c
6
+ metadata.gz: 5cfd13ac3c283e77e300f87ee923be282740f2763e26c73d21d27b5ae176629d15d8d580d9d326349acf5b71c74e6335689c2192050a818577b9f2e0a6a4484f
7
+ data.tar.gz: 27f36547ccdf6cc1336e1c44c5e164410f65344cba77fda76ad2db463054adaa93c96a406939b3826412280463a1d6a2940708f4080bc3170999bcc81594ba9d
data/README.md CHANGED
@@ -53,7 +53,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
53
53
  in your `Gemfile`:
54
54
 
55
55
  ```rb
56
- gem 'rubocop', '~> 1.37', require: false
56
+ gem 'rubocop', '~> 1.38', require: false
57
57
  ```
58
58
 
59
59
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
data/config/default.yml CHANGED
@@ -4696,6 +4696,12 @@ Style/RedundantConditional:
4696
4696
  Enabled: true
4697
4697
  VersionAdded: '0.50'
4698
4698
 
4699
+ Style/RedundantEach:
4700
+ Description: 'Checks for redundant `each`.'
4701
+ Enabled: pending
4702
+ Safe: false
4703
+ VersionAdded: '1.38'
4704
+
4699
4705
  Style/RedundantException:
4700
4706
  Description: "Checks for an obsolete RuntimeException argument in raise/fail."
4701
4707
  StyleGuide: '#no-explicit-runtimeerror'
@@ -73,7 +73,14 @@ module RuboCop
73
73
  def all_extensions
74
74
  return [] unless lockfile.dependencies.any?
75
75
 
76
- extensions = @config_store.for_pwd.for_all_cops['SuggestExtensions'] || {}
76
+ extensions = @config_store.for_pwd.for_all_cops['SuggestExtensions']
77
+ case extensions
78
+ when true
79
+ extensions = ConfigLoader.default_configuration.for_all_cops['SuggestExtensions']
80
+ when false, nil
81
+ extensions = {}
82
+ end
83
+
77
84
  extensions.select { |_, v| (Array(v) & dependent_gems).any? }.keys
78
85
  end
79
86
 
@@ -4,10 +4,31 @@ module RuboCop
4
4
  # This class parses the special `rubocop:disable` comments in a source
5
5
  # and provides a way to check if each cop is enabled at arbitrary line.
6
6
  class CommentConfig
7
+ extend Forwardable
8
+
9
+ CONFIG_DISABLED_LINE_RANGE_MIN = -Float::INFINITY
10
+
11
+ # This class provides an API compatible with RuboCop::DirectiveComment
12
+ # to be used for cops that are disabled in the config file
13
+ class ConfigDisabledCopDirectiveComment
14
+ attr_reader :text, :loc, :line_number
15
+
16
+ Loc = Struct.new(:expression)
17
+ Expression = Struct.new(:line)
18
+
19
+ def initialize(cop_name)
20
+ @text = "# rubocop:disable #{cop_name}"
21
+ @line_number = CONFIG_DISABLED_LINE_RANGE_MIN
22
+ @loc = Loc.new(Expression.new(CONFIG_DISABLED_LINE_RANGE_MIN))
23
+ end
24
+ end
25
+
7
26
  CopAnalysis = Struct.new(:line_ranges, :start_line_number)
8
27
 
9
28
  attr_reader :processed_source
10
29
 
30
+ def_delegators :@processed_source, :config, :registry
31
+
11
32
  def initialize(processed_source)
12
33
  @processed_source = processed_source
13
34
  end
@@ -25,7 +46,11 @@ module RuboCop
25
46
  end
26
47
 
27
48
  def extra_enabled_comments
28
- extra_enabled_comments_with_names(extras: Hash.new { |h, k| h[k] = [] }, names: Hash.new(0))
49
+ disable_count = Hash.new(0)
50
+ registry.disabled(config).each do |cop|
51
+ disable_count[cop.cop_name] += 1
52
+ end
53
+ extra_enabled_comments_with_names(extras: Hash.new { |h, k| h[k] = [] }, names: disable_count)
29
54
  end
30
55
 
31
56
  def comment_only_line?(line_number)
@@ -50,6 +75,7 @@ module RuboCop
50
75
 
51
76
  def analyze # rubocop:todo Metrics/AbcSize
52
77
  analyses = Hash.new { |hash, key| hash[key] = CopAnalysis.new([], nil) }
78
+ inject_disabled_cops_directives(analyses)
53
79
 
54
80
  each_directive do |directive|
55
81
  directive.cop_names.each do |cop_name|
@@ -64,6 +90,15 @@ module RuboCop
64
90
  end
65
91
  end
66
92
 
93
+ def inject_disabled_cops_directives(analyses)
94
+ registry.disabled(config).each do |cop|
95
+ analyses[cop.cop_name] = analyze_cop(
96
+ analyses[cop.cop_name],
97
+ DirectiveComment.new(ConfigDisabledCopDirectiveComment.new(cop.cop_name))
98
+ )
99
+ end
100
+ end
101
+
67
102
  def analyze_cop(analysis, directive)
68
103
  # Disabling cops after comments like `#=SomeDslDirective` does not related to single line
69
104
  if !comment_only_line?(directive.line_number) || directive.single_line?
@@ -159,9 +159,11 @@ module RuboCop
159
159
  def with_cop_error_handling(cop, node = nil)
160
160
  yield
161
161
  rescue StandardError => e
162
- raise e if @options[:raise_error]
162
+ raise e if @options[:raise_error] # For internal testing
163
163
 
164
164
  err = ErrorWithAnalyzedFileLocation.new(cause: e, node: node, cop: cop)
165
+ raise err if @options[:raise_cop_error] # From user-input option
166
+
165
167
  @errors << err
166
168
  end
167
169
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # Checks for uses of `create_file` with empty string second argument.
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ # create_file(path, '')
12
+ #
13
+ # # good
14
+ # create_empty_file(path)
15
+ #
16
+ class CreateEmptyFile < Base
17
+ extend AutoCorrector
18
+
19
+ MSG = 'Use `%<replacement>s`.'
20
+ RESTRICT_ON_SEND = %i[create_file].freeze
21
+
22
+ def on_send(node)
23
+ return if node.receiver
24
+ return unless (argument = node.arguments[1])
25
+ return unless argument.str_type? && argument.value.empty?
26
+
27
+ replacement = "create_empty_file(#{node.first_argument.source})"
28
+ message = format(MSG, replacement: replacement)
29
+
30
+ add_offense(node, message: message) do |corrector|
31
+ corrector.replace(node, replacement)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # Use `RUBY` for heredoc delimiter of example Ruby code.
7
+ #
8
+ # Some editors may apply better syntax highlighting by using appropriate language names for
9
+ # the delimiter.
10
+ #
11
+ # @example
12
+ # # bad
13
+ # expect_offense(<<~CODE)
14
+ # example_ruby_code
15
+ # CODE
16
+ #
17
+ # # good
18
+ # expect_offense(<<~RUBY)
19
+ # example_ruby_code
20
+ # RUBY
21
+ class ExampleHeredocDelimiter < Base
22
+ extend AutoCorrector
23
+
24
+ EXPECTED_HEREDOC_DELIMITER = 'RUBY'
25
+
26
+ MSG = 'Use `RUBY` for heredoc delimiter of example Ruby code.'
27
+
28
+ RESTRICT_ON_SEND = %i[
29
+ expect_correction
30
+ expect_no_corrections
31
+ expect_no_offenses
32
+ expect_offense
33
+ ].freeze
34
+
35
+ # @param node [RuboCop::AST::SendNode]
36
+ # @return [void]
37
+ def on_send(node)
38
+ heredoc_node = heredoc_node_from(node)
39
+ return unless heredoc_node
40
+ return if expected_heredoc_delimiter?(heredoc_node)
41
+ return if expected_heredoc_delimiter_in_body?(heredoc_node)
42
+
43
+ add_offense(heredoc_node) do |corrector|
44
+ autocorrect(corrector, heredoc_node)
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ # @param corrector [RuboCop::Cop::Corrector]
51
+ # @param node [RuboCop::AST::StrNode]
52
+ # @return [void]
53
+ def autocorrect(corrector, node)
54
+ [
55
+ heredoc_openning_delimiter_range_from(node),
56
+ heredoc_closing_delimiter_range_from(node)
57
+ ].each do |range|
58
+ corrector.replace(range, EXPECTED_HEREDOC_DELIMITER)
59
+ end
60
+ end
61
+
62
+ # @param node [RuboCop::AST::StrNode]
63
+ # @return [Boolean]
64
+ def expected_heredoc_delimiter_in_body?(node)
65
+ node.location.heredoc_body.source.lines.any? do |line|
66
+ line.strip == EXPECTED_HEREDOC_DELIMITER
67
+ end
68
+ end
69
+
70
+ # @param node [RuboCop::AST::StrNode]
71
+ # @return [Boolean]
72
+ def expected_heredoc_delimiter?(node)
73
+ heredoc_delimiter_string_from(node) == EXPECTED_HEREDOC_DELIMITER
74
+ end
75
+
76
+ # @param node [RuboCop::AST::SendNode]
77
+ # @return [RuboCop::AST::StrNode, nil]
78
+ def heredoc_node_from(node)
79
+ return unless node.first_argument.respond_to?(:heredoc?)
80
+ return unless node.first_argument.heredoc?
81
+
82
+ node.first_argument
83
+ end
84
+
85
+ # @param node [RuboCop::AST::StrNode]
86
+ # @return [String]
87
+ def heredoc_delimiter_string_from(node)
88
+ node.source[Heredoc::OPENING_DELIMITER, 2]
89
+ end
90
+
91
+ # @param node [RuboCop::AST::StrNode]
92
+ # @return [Parser::Source::Range]
93
+ def heredoc_openning_delimiter_range_from(node)
94
+ match_data = node.source.match(Heredoc::OPENING_DELIMITER)
95
+ node.location.expression.begin.adjust(
96
+ begin_pos: match_data.begin(2),
97
+ end_pos: match_data.end(2)
98
+ )
99
+ end
100
+
101
+ # @param node [RuboCop::AST::StrNode]
102
+ # @return [Parser::Source::Range]
103
+ def heredoc_closing_delimiter_range_from(node)
104
+ node.location.heredoc_end.end.adjust(
105
+ begin_pos: -heredoc_delimiter_string_from(node).length
106
+ )
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'internal_affairs/cop_description'
4
+ require_relative 'internal_affairs/create_empty_file'
4
5
  require_relative 'internal_affairs/empty_line_between_expect_offense_and_correction'
5
6
  require_relative 'internal_affairs/example_description'
7
+ require_relative 'internal_affairs/example_heredoc_delimiter'
6
8
  require_relative 'internal_affairs/inherit_deprecated_cop_class'
7
9
  require_relative 'internal_affairs/location_line_equality_comparison'
8
10
  require_relative 'internal_affairs/method_name_end_with'
@@ -90,7 +90,7 @@ module RuboCop
90
90
  # which lines start inside a string literal?
91
91
  return [] if ast.nil?
92
92
 
93
- ast.each_node(:str, :dstr).each_with_object(Set.new) do |str, ranges|
93
+ ast.each_node(:str, :dstr).with_object(Set.new) do |str, ranges|
94
94
  loc = str.location
95
95
 
96
96
  if str.heredoc?
@@ -92,7 +92,7 @@ module RuboCop
92
92
  # which lines start inside a string literal?
93
93
  return [] if ast.nil?
94
94
 
95
- ast.each_node(:str, :dstr).each_with_object(Set.new) do |str, ranges|
95
+ ast.each_node(:str, :dstr).with_object(Set.new) do |str, ranges|
96
96
  loc = str.location
97
97
 
98
98
  if str.heredoc?
@@ -194,6 +194,8 @@ module RuboCop
194
194
  end
195
195
 
196
196
  def range_inside_hash(node)
197
+ return node.source_range if node.location.begin.nil?
198
+
197
199
  range_between(node.location.begin.end_pos, node.location.end.begin_pos)
198
200
  end
199
201
 
@@ -38,6 +38,8 @@ module RuboCop
38
38
  # # bad
39
39
  # foo[ ]
40
40
  # foo[ ]
41
+ # foo[
42
+ # ]
41
43
  #
42
44
  # # good
43
45
  # foo[]
@@ -49,6 +51,8 @@ module RuboCop
49
51
  # # bad
50
52
  # foo[]
51
53
  # foo[ ]
54
+ # foo[
55
+ # ]
52
56
  #
53
57
  # # good
54
58
  # foo[ ]
@@ -64,8 +68,6 @@ module RuboCop
64
68
  RESTRICT_ON_SEND = %i[[] []=].freeze
65
69
 
66
70
  def on_send(node)
67
- return if node.multiline?
68
-
69
71
  tokens = processed_source.tokens_within(node)
70
72
  left_token = left_ref_bracket(node, tokens)
71
73
  return unless left_token
@@ -76,6 +78,8 @@ module RuboCop
76
78
  return empty_offenses(node, left_token, right_token, EMPTY_MSG)
77
79
  end
78
80
 
81
+ return if node.multiline?
82
+
79
83
  if style == :no_space
80
84
  no_space_offenses(node, left_token, right_token, MSG)
81
85
  else
@@ -141,7 +141,7 @@ module RuboCop
141
141
  if empty_if_branch?(node) && else_branch?(node)
142
142
  node.source_range.with(end_pos: node.loc.else.begin_pos)
143
143
  elsif node.loc.else
144
- node.source_range.with(end_pos: node.loc.else.begin_pos - 1)
144
+ node.source_range.with(end_pos: node.condition.loc.expression.end_pos)
145
145
  elsif all_branches_body_missing?(node)
146
146
  if_node = node.ancestors.detect(&:if?)
147
147
  node.source_range.with(end_pos: if_node.loc.end.end_pos)
@@ -50,9 +50,7 @@ module RuboCop
50
50
 
51
51
  def on_new_investigation
52
52
  each_missing_enable do |cop, line_range|
53
- # This has to remain a strict inequality to handle
54
- # the case when max_range is Float::INFINITY
55
- next if line_range.max - line_range.min < max_range + 2
53
+ next if acceptable_range?(cop, line_range)
56
54
 
57
55
  range = source_range(processed_source.buffer, line_range.min, (0..0))
58
56
  comment = processed_source.comment_at_line(line_range.begin)
@@ -69,6 +67,23 @@ module RuboCop
69
67
  end
70
68
  end
71
69
 
70
+ def acceptable_range?(cop, line_range)
71
+ # This has to remain a strict inequality to handle
72
+ # the case when max_range is Float::INFINITY
73
+ return true if line_range.max - line_range.min < max_range + 2
74
+ # This cop is disabled in the config, it is not expected to be re-enabled
75
+ return true if line_range.min == CommentConfig::CONFIG_DISABLED_LINE_RANGE_MIN
76
+
77
+ cop_class = RuboCop::Cop::Registry.global.find_by_cop_name cop
78
+ if cop_class &&
79
+ !processed_source.registry.enabled?(cop_class, config) &&
80
+ line_range.max == Float::INFINITY
81
+ return true
82
+ end
83
+
84
+ false
85
+ end
86
+
72
87
  def max_range
73
88
  @max_range ||= cop_config['MaximumRangeSize']
74
89
  end
@@ -113,6 +113,7 @@ module RuboCop
113
113
  def each_line_range(cop, line_ranges)
114
114
  line_ranges.each_with_index do |line_range, line_range_index|
115
115
  next if ignore_offense?(line_range)
116
+ next if expected_final_disable?(cop, line_range)
116
117
 
117
118
  comment = processed_source.comment_at_line(line_range.begin)
118
119
  redundant = if all_disabled?(comment)
@@ -179,11 +180,21 @@ module RuboCop
179
180
  end
180
181
 
181
182
  def ignore_offense?(line_range)
183
+ return true if line_range.min == CommentConfig::CONFIG_DISABLED_LINE_RANGE_MIN
184
+
182
185
  disabled_ranges.any? do |range|
183
186
  range.cover?(line_range.min) && range.cover?(line_range.max)
184
187
  end
185
188
  end
186
189
 
190
+ def expected_final_disable?(cop, line_range)
191
+ # A cop which is disabled in the config is being re-disabled until end of file
192
+ cop_class = RuboCop::Cop::Registry.global.find_by_cop_name cop
193
+ cop_class &&
194
+ !processed_source.registry.enabled?(cop_class, config) &&
195
+ line_range.max == Float::INFINITY
196
+ end
197
+
187
198
  def department_disabled?(cop, comment)
188
199
  directive = DirectiveComment.new(comment)
189
200
  directive.in_directive_department?(cop) && !directive.overridden_by_department?(cop)
@@ -20,6 +20,7 @@ module RuboCop
20
20
  # * 2.5+ ... Add `pp` above
21
21
  # * 2.7+ ... Add `ruby2_keywords` above
22
22
  # * 3.1+ ... Add `fiber` above
23
+ # * 3.2+ ... `set`
23
24
  #
24
25
  # This cop target those features.
25
26
  #
@@ -48,7 +49,13 @@ module RuboCop
48
49
  return unless redundant_require_statement?(node)
49
50
 
50
51
  add_offense(node) do |corrector|
51
- range = range_with_surrounding_space(node.loc.expression, side: :right)
52
+ if node.parent.respond_to?(:modifier_form?) && node.parent.modifier_form?
53
+ corrector.insert_after(node.parent, "\nend")
54
+
55
+ range = range_with_surrounding_space(node.loc.expression, side: :right)
56
+ else
57
+ range = range_by_whole_lines(node.source_range, include_final_newline: true)
58
+ end
52
59
 
53
60
  corrector.remove(range)
54
61
  end
@@ -63,7 +70,8 @@ module RuboCop
63
70
  (target_ruby_version >= 2.2 && RUBY_22_LOADED_FEATURES.include?(feature_name)) ||
64
71
  (target_ruby_version >= 2.5 && feature_name == 'pp') ||
65
72
  (target_ruby_version >= 2.7 && feature_name == 'ruby2_keywords') ||
66
- (target_ruby_version >= 3.1 && feature_name == 'fiber')
73
+ (target_ruby_version >= 3.1 && feature_name == 'fiber') ||
74
+ (target_ruby_version >= 3.2 && feature_name == 'set')
67
75
  end
68
76
  # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
69
77
  end
@@ -118,14 +118,15 @@ module RuboCop
118
118
  end
119
119
 
120
120
  def offending_empty_no_space?(config, left_token, right_token)
121
- config == 'no_space' && !no_space_between?(left_token, right_token)
121
+ config == 'no_space' && !no_character_between?(left_token, right_token)
122
122
  end
123
123
 
124
124
  def space_between?(left_bracket_token, right_bracket_token)
125
- left_bracket_token.end_pos + 1 == right_bracket_token.begin_pos
125
+ left_bracket_token.end_pos + 1 == right_bracket_token.begin_pos &&
126
+ processed_source.buffer.source[left_bracket_token.end_pos] == ' '
126
127
  end
127
128
 
128
- def no_space_between?(left_bracket_token, right_bracket_token)
129
+ def no_character_between?(left_bracket_token, right_bracket_token)
129
130
  left_bracket_token.end_pos == right_bracket_token.begin_pos
130
131
  end
131
132
  end
@@ -149,16 +149,22 @@ module RuboCop
149
149
  @registry.size
150
150
  end
151
151
 
152
- def enabled(config, only = [], only_safe: false)
153
- select { |cop| only.include?(cop.cop_name) || enabled?(cop, config, only_safe) }
152
+ def enabled(config)
153
+ select { |cop| enabled?(cop, config) }
154
154
  end
155
155
 
156
- def enabled?(cop, config, only_safe)
156
+ def disabled(config)
157
+ reject { |cop| enabled?(cop, config) }
158
+ end
159
+
160
+ def enabled?(cop, config)
161
+ return true if options.fetch(:only, []).include?(cop.cop_name)
162
+
157
163
  cfg = config.for_cop(cop)
158
164
 
159
165
  cop_enabled = cfg.fetch('Enabled') == true || enabled_pending_cop?(cfg, config)
160
166
 
161
- if only_safe
167
+ if options.fetch(:safe, false)
162
168
  cop_enabled && cfg.fetch('Safe', true)
163
169
  else
164
170
  cop_enabled
@@ -85,6 +85,8 @@ module RuboCop
85
85
 
86
86
  RESTRICT_ON_SEND = %i[private protected public module_function].freeze
87
87
 
88
+ ALLOWED_NODE_TYPES = %i[pair block].freeze
89
+
88
90
  # @!method access_modifier_with_symbol?(node)
89
91
  def_node_matcher :access_modifier_with_symbol?, <<~PATTERN
90
92
  (send nil? {:private :protected :public :module_function} (sym _))
@@ -92,7 +94,7 @@ module RuboCop
92
94
 
93
95
  def on_send(node)
94
96
  return unless node.access_modifier?
95
- return if node.parent&.pair_type?
97
+ return if ALLOWED_NODE_TYPES.include?(node.parent&.type)
96
98
  return if allow_modifiers_on_symbols?(node)
97
99
 
98
100
  if offense?(node)
@@ -425,7 +425,7 @@ module RuboCop
425
425
  if node.parent.begin_type?
426
426
  return_value_used?(node.parent)
427
427
  else
428
- node.parent.assignment? || node.parent.send_type?
428
+ node.parent.assignment? || node.parent.call_type?
429
429
  end
430
430
  end
431
431
 
@@ -29,7 +29,7 @@ module RuboCop
29
29
 
30
30
  def offense?(node)
31
31
  # we don't register an offense for things like ?\C-\M-d
32
- node.loc.begin.is?('?') && node.source.size.between?(2, 3)
32
+ node.character_literal? && node.source.size.between?(2, 3)
33
33
  end
34
34
 
35
35
  def autocorrect(corrector, node)
@@ -8,7 +8,9 @@ module RuboCop
8
8
  #
9
9
  # @safety
10
10
  # It is unsafe by default because false positives may occur in the
11
- # `nil` check of block arguments to the receiver object.
11
+ # `nil` check of block arguments to the receiver object. Additionally,
12
+ # we can't know the type of the receiver object for sure, which may
13
+ # result in false positives as well.
12
14
  #
13
15
  # For example, `[[1, 2], [3, nil]].reject { |first, second| second.nil? }`
14
16
  # and `[[1, 2], [3, nil]].compact` are not compatible. This will work fine
@@ -96,7 +98,9 @@ module RuboCop
96
98
  end
97
99
 
98
100
  def to_enum_method?(node)
99
- TO_ENUM_METHODS.include?(node.children.first.method_name)
101
+ return false unless node.receiver.send_type?
102
+
103
+ TO_ENUM_METHODS.include?(node.receiver.method_name)
100
104
  end
101
105
 
102
106
  def good_method_name(node)