rubocop 1.36.0 → 1.39.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +31 -3
  4. data/lib/rubocop/arguments_env.rb +17 -0
  5. data/lib/rubocop/arguments_file.rb +17 -0
  6. data/lib/rubocop/cli/command/execute_runner.rb +7 -7
  7. data/lib/rubocop/cli/command/suggest_extensions.rb +8 -1
  8. data/lib/rubocop/comment_config.rb +36 -1
  9. data/lib/rubocop/cop/commissioner.rb +3 -1
  10. data/lib/rubocop/cop/generator.rb +1 -2
  11. data/lib/rubocop/cop/internal_affairs/create_empty_file.rb +37 -0
  12. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +111 -0
  13. data/lib/rubocop/cop/internal_affairs.rb +2 -0
  14. data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -0
  15. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  16. data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
  17. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +29 -8
  18. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  19. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +13 -9
  20. data/lib/rubocop/cop/layout/space_inside_array_percent_literal.rb +3 -0
  21. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +30 -3
  22. data/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb +34 -0
  23. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +6 -2
  24. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  25. data/lib/rubocop/cop/lint/duplicate_magic_comment.rb +73 -0
  26. data/lib/rubocop/cop/lint/duplicate_methods.rb +28 -9
  27. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +25 -6
  28. data/lib/rubocop/cop/lint/empty_class.rb +3 -1
  29. data/lib/rubocop/cop/lint/empty_conditional_body.rb +20 -8
  30. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +18 -3
  31. data/lib/rubocop/cop/lint/nested_method_definition.rb +50 -1
  32. data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
  33. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +4 -5
  34. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -1
  35. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +23 -1
  36. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +7 -0
  37. data/lib/rubocop/cop/lint/redundant_require_statement.rb +38 -10
  38. data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
  39. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -2
  40. data/lib/rubocop/cop/lint/shadowed_exception.rb +0 -10
  41. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +3 -0
  42. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  43. data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
  44. data/lib/rubocop/cop/lint/unused_method_argument.rb +4 -0
  45. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  46. data/lib/rubocop/cop/mixin/comments_help.rb +12 -0
  47. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -0
  48. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +6 -3
  49. data/lib/rubocop/cop/mixin/range_help.rb +23 -0
  50. data/lib/rubocop/cop/mixin/rescue_node.rb +3 -1
  51. data/lib/rubocop/cop/mixin/surrounding_space.rb +10 -8
  52. data/lib/rubocop/cop/mixin/visibility_help.rb +40 -5
  53. data/lib/rubocop/cop/naming/inclusive_language.rb +1 -1
  54. data/lib/rubocop/cop/registry.rb +10 -4
  55. data/lib/rubocop/cop/style/access_modifier_declarations.rb +5 -7
  56. data/lib/rubocop/cop/style/accessor_grouping.rb +7 -3
  57. data/lib/rubocop/cop/style/block_delimiters.rb +2 -2
  58. data/lib/rubocop/cop/style/character_literal.rb +1 -1
  59. data/lib/rubocop/cop/style/class_equality_comparison.rb +8 -6
  60. data/lib/rubocop/cop/style/collection_compact.rb +12 -3
  61. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  62. data/lib/rubocop/cop/style/endless_method.rb +1 -1
  63. data/lib/rubocop/cop/style/explicit_block_argument.rb +4 -0
  64. data/lib/rubocop/cop/style/format_string_token.rb +1 -1
  65. data/lib/rubocop/cop/style/guard_clause.rb +62 -21
  66. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +1 -0
  67. data/lib/rubocop/cop/style/hash_each_methods.rb +32 -10
  68. data/lib/rubocop/cop/style/hash_except.rb +4 -0
  69. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  70. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +25 -2
  71. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +13 -2
  72. data/lib/rubocop/cop/style/module_function.rb +28 -6
  73. data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -1
  74. data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
  75. data/lib/rubocop/cop/style/object_then.rb +3 -0
  76. data/lib/rubocop/cop/style/operator_method_call.rb +53 -0
  77. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  78. data/lib/rubocop/cop/style/redundant_begin.rb +1 -0
  79. data/lib/rubocop/cop/style/redundant_condition.rb +5 -2
  80. data/lib/rubocop/cop/style/redundant_each.rb +116 -0
  81. data/lib/rubocop/cop/style/redundant_initialize.rb +3 -1
  82. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +8 -1
  83. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +12 -3
  84. data/lib/rubocop/cop/style/redundant_string_escape.rb +181 -0
  85. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
  86. data/lib/rubocop/cop/style/static_class.rb +32 -1
  87. data/lib/rubocop/cop/style/symbol_array.rb +2 -0
  88. data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
  89. data/lib/rubocop/cop/style/word_array.rb +2 -0
  90. data/lib/rubocop/cop/team.rb +3 -4
  91. data/lib/rubocop/cop/util.rb +1 -1
  92. data/lib/rubocop/cop/variable_force/variable_table.rb +1 -1
  93. data/lib/rubocop/cops_documentation_generator.rb +2 -1
  94. data/lib/rubocop/ext/processed_source.rb +2 -0
  95. data/lib/rubocop/formatter/disabled_config_formatter.rb +8 -2
  96. data/lib/rubocop/formatter/offense_count_formatter.rb +8 -5
  97. data/lib/rubocop/formatter/worst_offenders_formatter.rb +6 -3
  98. data/lib/rubocop/options.rb +19 -15
  99. data/lib/rubocop/rspec/cop_helper.rb +21 -1
  100. data/lib/rubocop/rspec/shared_contexts.rb +14 -1
  101. data/lib/rubocop/runner.rb +15 -11
  102. data/lib/rubocop/server/cache.rb +5 -1
  103. data/lib/rubocop/server/cli.rb +9 -2
  104. data/lib/rubocop/server/client_command/exec.rb +5 -0
  105. data/lib/rubocop/server/core.rb +18 -1
  106. data/lib/rubocop/server/socket_reader.rb +5 -1
  107. data/lib/rubocop/server.rb +1 -1
  108. data/lib/rubocop/version.rb +8 -3
  109. data/lib/rubocop.rb +4 -0
  110. metadata +13 -5
@@ -41,6 +41,7 @@ module RuboCop
41
41
  return unless (receiver = node.receiver)
42
42
  return unless receiver.receiver&.const_type? && receiver.receiver.short_name == :Dir
43
43
  return unless GLOB_METHODS.include?(receiver.method_name)
44
+ return if multiple_argument?(receiver)
44
45
 
45
46
  selector = node.loc.selector
46
47
 
@@ -49,6 +50,12 @@ module RuboCop
49
50
  corrector.remove(node.loc.dot)
50
51
  end
51
52
  end
53
+
54
+ private
55
+
56
+ def multiple_argument?(glob_method)
57
+ glob_method.arguments.count >= 2 || glob_method.first_argument&.splat_type?
58
+ end
52
59
  end
53
60
  end
54
61
  end
@@ -6,13 +6,23 @@ module RuboCop
6
6
  # Checks for unnecessary `require` statement.
7
7
  #
8
8
  # The following features are unnecessary `require` statement because
9
- # they are already loaded.
9
+ # they are already loaded. e.g. Ruby 2.2:
10
10
  #
11
11
  # ruby -ve 'p $LOADED_FEATURES.reject { |feature| %r|/| =~ feature }'
12
12
  # ruby 2.2.8p477 (2017-09-14 revision 59906) [x86_64-darwin13]
13
13
  # ["enumerator.so", "rational.so", "complex.so", "thread.rb"]
14
14
  #
15
- # This cop targets Ruby 2.2 or higher containing these 4 features.
15
+ # Below are the features that each `TargetRubyVersion` targets.
16
+ #
17
+ # * 2.0+ ... `enumerator`
18
+ # * 2.1+ ... `thread`
19
+ # * 2.2+ ... Add `rational` and `complex` above
20
+ # * 2.5+ ... Add `pp` above
21
+ # * 2.7+ ... Add `ruby2_keywords` above
22
+ # * 3.1+ ... Add `fiber` above
23
+ # * 3.2+ ... `set`
24
+ #
25
+ # This cop target those features.
16
26
  #
17
27
  # @example
18
28
  # # bad
@@ -24,28 +34,46 @@ module RuboCop
24
34
  class RedundantRequireStatement < Base
25
35
  include RangeHelp
26
36
  extend AutoCorrector
27
- extend TargetRubyVersion
28
-
29
- minimum_target_ruby_version 2.2
30
37
 
31
38
  MSG = 'Remove unnecessary `require` statement.'
32
39
  RESTRICT_ON_SEND = %i[require].freeze
40
+ RUBY_22_LOADED_FEATURES = %w[rational complex].freeze
33
41
 
34
- # @!method unnecessary_require_statement?(node)
35
- def_node_matcher :unnecessary_require_statement?, <<~PATTERN
42
+ # @!method redundant_require_statement?(node)
43
+ def_node_matcher :redundant_require_statement?, <<~PATTERN
36
44
  (send nil? :require
37
- (str {"enumerator" "rational" "complex" "thread"}))
45
+ (str #redundant_feature?))
38
46
  PATTERN
39
47
 
40
48
  def on_send(node)
41
- return unless unnecessary_require_statement?(node)
49
+ return unless redundant_require_statement?(node)
42
50
 
43
51
  add_offense(node) do |corrector|
44
- 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
45
59
 
46
60
  corrector.remove(range)
47
61
  end
48
62
  end
63
+
64
+ private
65
+
66
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
67
+ def redundant_feature?(feature_name)
68
+ feature_name == 'enumerator' ||
69
+ (target_ruby_version >= 2.1 && feature_name == 'thread') ||
70
+ (target_ruby_version >= 2.2 && RUBY_22_LOADED_FEATURES.include?(feature_name)) ||
71
+ (target_ruby_version >= 2.5 && feature_name == 'pp') ||
72
+ (target_ruby_version >= 2.7 && feature_name == 'ruby2_keywords') ||
73
+ (target_ruby_version >= 3.1 && feature_name == 'fiber') ||
74
+ (target_ruby_version >= 3.2 && feature_name == 'set')
75
+ end
76
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
49
77
  end
50
78
  end
51
79
  end
@@ -46,7 +46,7 @@ module RuboCop
46
46
  private
47
47
 
48
48
  def check_ternary(ternary, node)
49
- return unless ternary.condition.operator_keyword?
49
+ return if node.method?(:[]) || !ternary.condition.operator_keyword?
50
50
 
51
51
  range = range_between(node.source_range.begin_pos, ternary.condition.source_range.end_pos)
52
52
 
@@ -31,6 +31,7 @@ module RuboCop
31
31
  minimum_target_ruby_version 2.3
32
32
 
33
33
  MSG = 'Do not chain ordinary method call after safe navigation operator.'
34
+ PLUS_MINUS_METHODS = %i[+@ -@].freeze
34
35
 
35
36
  # @!method bad_method?(node)
36
37
  def_node_matcher :bad_method?, <<~PATTERN
@@ -42,7 +43,7 @@ module RuboCop
42
43
 
43
44
  def on_send(node)
44
45
  bad_method?(node) do |safe_nav, method|
45
- return if nil_methods.include?(method)
46
+ return if nil_methods.include?(method) || PLUS_MINUS_METHODS.include?(node.method_name)
46
47
 
47
48
  method_chain = method_chain(node)
48
49
  location =
@@ -71,7 +72,7 @@ module RuboCop
71
72
  else
72
73
  offense_range.source.dup
73
74
  end
74
- source.prepend('.') unless send_node.dot?
75
+ source.prepend('.') unless source.start_with?('.')
75
76
  source.prepend('&')
76
77
  end
77
78
 
@@ -155,16 +155,6 @@ module RuboCop
155
155
  end
156
156
  end
157
157
 
158
- # @param [RuboCop::AST::Node] rescue_group is a node of array_type
159
- def rescued_exceptions(rescue_group)
160
- klasses = *rescue_group
161
- klasses.map do |klass|
162
- next unless klass.const_type?
163
-
164
- klass.source
165
- end.compact
166
- end
167
-
168
158
  def find_shadowing_rescue(rescues)
169
159
  rescued_groups = rescued_groups_for(rescues)
170
160
  rescued_groups.zip(rescues).each do |group, res|
@@ -12,9 +12,12 @@ module RuboCop
12
12
  # because `Ractor` should not access outer variables.
13
13
  # eg. following style is encouraged:
14
14
  #
15
+ # [source,ruby]
16
+ # ----
15
17
  # worker_id, pipe = env
16
18
  # Ractor.new(worker_id, pipe) do |worker_id, pipe|
17
19
  # end
20
+ # ----
18
21
  #
19
22
  # @example
20
23
  #
@@ -116,7 +116,7 @@ module RuboCop
116
116
  private
117
117
 
118
118
  def comment_between_rescue_and_end?(node)
119
- ancestor = node.each_ancestor(:kwbegin, :def, :defs, :block).first
119
+ ancestor = node.each_ancestor(:kwbegin, :def, :defs, :block, :numblock).first
120
120
  return unless ancestor
121
121
 
122
122
  end_line = ancestor.loc.end.line
@@ -79,7 +79,7 @@ module RuboCop
79
79
  # # bad
80
80
  # 2.times { raise ArgumentError }
81
81
  #
82
- # @example AllowedPatterns: [/(exactly|at_least|at_most)\(\d+\)\.times/] (default)
82
+ # @example AllowedPatterns: ['(exactly|at_least|at_most)\(\d+\)\.times'] (default)
83
83
  #
84
84
  # # good
85
85
  # exactly(2).times { raise StandardError }
@@ -68,6 +68,10 @@ module RuboCop
68
68
  (send nil? :fail ...)}
69
69
  PATTERN
70
70
 
71
+ def self.autocorrect_incompatible_with
72
+ [Style::ExplicitBlockArgument]
73
+ end
74
+
71
75
  def self.joining_forces
72
76
  VariableForce
73
77
  end
@@ -20,7 +20,7 @@ module RuboCop
20
20
  #
21
21
  # @example CountRepeatedAttributes: false (default is true)
22
22
  #
23
- # # `model` and `current_user`, refenced 3 times each,
23
+ # # `model` and `current_user`, referenced 3 times each,
24
24
  # # are each counted as only 1 branch each if
25
25
  # # `CountRepeatedAttributes` is set to 'false'
26
26
  #
@@ -22,6 +22,18 @@ module RuboCop
22
22
  processed_source.each_comment_in_lines(start_line...end_line)
23
23
  end
24
24
 
25
+ def comments_contain_disables?(node, cop_name)
26
+ disabled_ranges = processed_source.disabled_line_ranges[cop_name]
27
+
28
+ return unless disabled_ranges
29
+
30
+ node_range = node.source_range.line...find_end_line(node)
31
+
32
+ disabled_ranges.any? do |disable_range|
33
+ disable_range.cover?(node_range) || node_range.cover?(disable_range)
34
+ end
35
+ end
36
+
25
37
  private
26
38
 
27
39
  def end_position_for(node)
@@ -69,6 +69,10 @@ module RuboCop
69
69
  end
70
70
  end
71
71
 
72
+ def leading_magic_comments
73
+ leading_comment_lines.map { |line| MagicComment.parse(line) }
74
+ end
75
+
72
76
  def leading_comment_lines
73
77
  first_non_comment_token = processed_source.tokens.find { |token| !token.comment? }
74
78
 
@@ -96,11 +96,14 @@ module RuboCop
96
96
  end
97
97
 
98
98
  def without_parentheses_call_expr_follows?(ancestor)
99
+ return false unless ancestor.respond_to?(:parenthesized?) && !ancestor.parenthesized?
100
+
99
101
  right_sibling = ancestor.right_sibling
100
- right_sibling ||= ancestor.each_ancestor.find(&:assignment?)&.right_sibling
101
- return false unless right_sibling
102
+ right_sibling ||= ancestor.each_ancestor.find do |node|
103
+ node.assignment? || node.send_type?
104
+ end&.right_sibling
102
105
 
103
- ancestor.respond_to?(:parenthesized?) && !ancestor.parenthesized? && !!right_sibling
106
+ !!right_sibling
104
107
  end
105
108
 
106
109
  def breakdown_value_types_of_hash(hash_node)
@@ -126,6 +126,29 @@ module RuboCop
126
126
  pos += size * step while condition && src[pos + offset, size] == needle
127
127
  pos.negative? ? 0 : pos
128
128
  end
129
+
130
+ def range_with_comments_and_lines(node)
131
+ range_by_whole_lines(range_with_comments(node), include_final_newline: true)
132
+ end
133
+
134
+ def range_with_comments(node)
135
+ ranges = [
136
+ node,
137
+ *@processed_source.ast_with_comments[node]
138
+ ].map do |element|
139
+ element.location.expression
140
+ end
141
+ ranges.reduce do |result, range|
142
+ add_range(result, range)
143
+ end
144
+ end
145
+
146
+ def add_range(range1, range2)
147
+ range1.with(
148
+ begin_pos: [range1.begin_pos, range2.begin_pos].min,
149
+ end_pos: [range1.end_pos, range2.end_pos].max
150
+ )
151
+ end
129
152
  end
130
153
  end
131
154
  end
@@ -11,7 +11,9 @@ module RuboCop
11
11
  private
12
12
 
13
13
  def rescue_modifier?(node)
14
- node&.resbody_type? && @modifier_locations.include?(node.loc.keyword)
14
+ return false unless node.respond_to?(:resbody_type?)
15
+
16
+ node.resbody_type? && @modifier_locations.include?(node.loc.keyword)
15
17
  end
16
18
 
17
19
  # @deprecated Use ResbodyNode#exceptions instead
@@ -13,7 +13,7 @@ module RuboCop
13
13
 
14
14
  private
15
15
 
16
- def side_space_range(range:, side:)
16
+ def side_space_range(range:, side:, include_newlines: false)
17
17
  buffer = processed_source.buffer
18
18
  src = buffer.source
19
19
 
@@ -21,11 +21,11 @@ module RuboCop
21
21
  end_pos = range.end_pos
22
22
  if side == :left
23
23
  end_pos = begin_pos
24
- begin_pos = reposition(src, begin_pos, -1)
24
+ begin_pos = reposition(src, begin_pos, -1, include_newlines: include_newlines)
25
25
  end
26
26
  if side == :right
27
27
  begin_pos = end_pos
28
- end_pos = reposition(src, end_pos, 1)
28
+ end_pos = reposition(src, end_pos, 1, include_newlines: include_newlines)
29
29
  end
30
30
  Parser::Source::Range.new(buffer, begin_pos, end_pos)
31
31
  end
@@ -75,9 +75,10 @@ module RuboCop
75
75
  end
76
76
  end
77
77
 
78
- def reposition(src, pos, step)
78
+ def reposition(src, pos, step, include_newlines: false)
79
79
  offset = step == -1 ? -1 : 0
80
- pos += step while SINGLE_SPACE_REGEXP.match?(src[pos + offset])
80
+ pos += step while SINGLE_SPACE_REGEXP.match?(src[pos + offset]) ||
81
+ (include_newlines && src[pos + offset] == "\n")
81
82
  pos.negative? ? 0 : pos
82
83
  end
83
84
 
@@ -117,14 +118,15 @@ module RuboCop
117
118
  end
118
119
 
119
120
  def offending_empty_no_space?(config, left_token, right_token)
120
- config == 'no_space' && !no_space_between?(left_token, right_token)
121
+ config == 'no_space' && !no_character_between?(left_token, right_token)
121
122
  end
122
123
 
123
124
  def space_between?(left_bracket_token, right_bracket_token)
124
- 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] == ' '
125
127
  end
126
128
 
127
- def no_space_between?(left_bracket_token, right_bracket_token)
129
+ def no_character_between?(left_bracket_token, right_bracket_token)
128
130
  left_bracket_token.end_pos == right_bracket_token.begin_pos
129
131
  end
130
132
  end
@@ -1,18 +1,43 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'set'
4
+
3
5
  module RuboCop
4
6
  module Cop
5
7
  # Help methods for determining node visibility.
6
8
  module VisibilityHelp
7
9
  extend NodePattern::Macros
8
10
 
9
- VISIBILITY_SCOPES = %i[private protected public].freeze
11
+ VISIBILITY_SCOPES = ::Set[:private, :protected, :public].freeze
10
12
 
11
13
  private
12
14
 
13
15
  def node_visibility(node)
14
- scope = find_visibility_start(node)
15
- scope&.method_name || :public
16
+ node_visibility_from_visibility_inline(node) ||
17
+ node_visibility_from_visibility_block(node) ||
18
+ :public
19
+ end
20
+
21
+ def node_visibility_from_visibility_inline(node)
22
+ return unless node.def_type?
23
+
24
+ node_visibility_from_visibility_inline_on_def(node) ||
25
+ node_visibility_from_visibility_inline_on_method_name(node)
26
+ end
27
+
28
+ def node_visibility_from_visibility_inline_on_def(node)
29
+ parent = node.parent
30
+ parent.method_name if visibility_inline_on_def?(parent)
31
+ end
32
+
33
+ def node_visibility_from_visibility_inline_on_method_name(node)
34
+ node.right_siblings.reverse.find do |sibling|
35
+ visibility_inline_on_method_name?(sibling, method_name: node.method_name)
36
+ end&.method_name
37
+ end
38
+
39
+ def node_visibility_from_visibility_block(node)
40
+ find_visibility_start(node)&.method_name
16
41
  end
17
42
 
18
43
  def find_visibility_start(node)
@@ -21,7 +46,7 @@ module RuboCop
21
46
 
22
47
  # Navigate to find the last protected method
23
48
  def find_visibility_end(node)
24
- possible_visibilities = VISIBILITY_SCOPES - [node_visibility(node)]
49
+ possible_visibilities = VISIBILITY_SCOPES - ::Set[node_visibility(node)]
25
50
  right = node.right_siblings
26
51
  right.find do |child_node|
27
52
  possible_visibilities.include?(node_visibility(child_node))
@@ -30,7 +55,17 @@ module RuboCop
30
55
 
31
56
  # @!method visibility_block?(node)
32
57
  def_node_matcher :visibility_block?, <<~PATTERN
33
- (send nil? { :private :protected :public })
58
+ (send nil? VISIBILITY_SCOPES)
59
+ PATTERN
60
+
61
+ # @!method visibility_inline_on_def?(node)
62
+ def_node_matcher :visibility_inline_on_def?, <<~PATTERN
63
+ (send nil? VISIBILITY_SCOPES def)
64
+ PATTERN
65
+
66
+ # @!method visibility_inline_on_method_name?(node, method_name:)
67
+ def_node_matcher :visibility_inline_on_method_name?, <<~PATTERN
68
+ (send nil? VISIBILITY_SCOPES (sym %method_name))
34
69
  PATTERN
35
70
  end
36
71
  end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Naming
6
- # This cops recommends the use of inclusive language instead of problematic terms.
6
+ # Recommends the use of inclusive language instead of problematic terms.
7
7
  # The cop can check the following locations for offenses:
8
8
  # - identifiers
9
9
  # - constants
@@ -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)
@@ -183,6 +185,7 @@ module RuboCop
183
185
  end
184
186
 
185
187
  def insert_def(corrector, node, source)
188
+ source = [*processed_source.ast_with_comments[node].map(&:text), source].join("\n")
186
189
  argument_less_modifier_node = find_argument_less_modifier_node(node)
187
190
  if argument_less_modifier_node
188
191
  corrector.insert_after(argument_less_modifier_node, "\n\n#{source}")
@@ -199,12 +202,7 @@ module RuboCop
199
202
  end
200
203
 
201
204
  def remove_node(corrector, node)
202
- corrector.remove(
203
- range_by_whole_lines(
204
- node.location.expression,
205
- include_final_newline: true
206
- )
207
- )
205
+ corrector.remove(range_with_comments_and_lines(node))
208
206
  end
209
207
  end
210
208
  end
@@ -135,12 +135,16 @@ module RuboCop
135
135
  end
136
136
 
137
137
  def separate_accessors(node)
138
- node.arguments.map do |arg|
139
- if arg == node.arguments.first
138
+ node.arguments.flat_map do |arg|
139
+ lines = [
140
+ *processed_source.ast_with_comments[arg].map(&:text),
140
141
  "#{node.method_name} #{arg.source}"
142
+ ]
143
+ if arg == node.arguments.first
144
+ lines
141
145
  else
142
146
  indent = ' ' * node.loc.column
143
- "#{indent}#{node.method_name} #{arg.source}"
147
+ lines.map { |line| "#{indent}#{line}" }
144
148
  end
145
149
  end.join("\n")
146
150
  end
@@ -157,7 +157,7 @@ module RuboCop
157
157
  # process(something)
158
158
  # }
159
159
  #
160
- # @example AllowedPatterns: [/map/]
160
+ # @example AllowedPatterns: ['map']
161
161
  #
162
162
  # # good
163
163
  # things.map { |thing|
@@ -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)
@@ -48,7 +48,7 @@ module RuboCop
48
48
  # var.class.eql?(Date)
49
49
  # var.class.name == 'Date'
50
50
  #
51
- # @example AllowedPatterns: [`/eq/`]
51
+ # @example AllowedPatterns: ['eq']
52
52
  # # good
53
53
  # var.instance_of?(Date)
54
54
  # var.class.equal?(Date)
@@ -97,12 +97,14 @@ module RuboCop
97
97
  if node.children.first.method?(:name)
98
98
  return class_node.receiver.source if class_node.receiver
99
99
 
100
- value = class_node.source.delete('"').delete("'")
101
- value.prepend('::') if class_node.each_ancestor(:class, :module).any?
102
- value
103
- else
104
- class_node.source
100
+ if class_node.str_type?
101
+ value = class_node.source.delete('"').delete("'")
102
+ value.prepend('::') if class_node.each_ancestor(:class, :module).any?
103
+ return value
104
+ end
105
105
  end
106
+
107
+ class_node.source
106
108
  end
107
109
 
108
110
  def offense_range(receiver_node, 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
@@ -36,8 +38,8 @@ module RuboCop
36
38
  extend AutoCorrector
37
39
 
38
40
  MSG = 'Use `%<good>s` instead of `%<bad>s`.'
39
-
40
41
  RESTRICT_ON_SEND = %i[reject reject! select select!].freeze
42
+ TO_ENUM_METHODS = %i[to_enum lazy].freeze
41
43
 
42
44
  # @!method reject_method_with_block_pass?(node)
43
45
  def_node_matcher :reject_method_with_block_pass?, <<~PATTERN
@@ -69,6 +71,7 @@ module RuboCop
69
71
 
70
72
  def on_send(node)
71
73
  return unless (range = offense_range(node))
74
+ return if target_ruby_version <= 3.0 && to_enum_method?(node)
72
75
 
73
76
  good = good_method_name(node)
74
77
  message = format(MSG, good: good, bad: range.source)
@@ -94,6 +97,12 @@ module RuboCop
94
97
  end
95
98
  end
96
99
 
100
+ def to_enum_method?(node)
101
+ return false unless node.receiver.send_type?
102
+
103
+ TO_ENUM_METHODS.include?(node.receiver.method_name)
104
+ end
105
+
97
106
  def good_method_name(node)
98
107
  if node.bang_method?
99
108
  'compact!'
@@ -103,7 +112,7 @@ module RuboCop
103
112
  end
104
113
 
105
114
  def range(begin_pos_node, end_pos_node)
106
- range_between(begin_pos_node.loc.selector.begin_pos, end_pos_node.loc.end.end_pos)
115
+ range_between(begin_pos_node.loc.selector.begin_pos, end_pos_node.loc.expression.end_pos)
107
116
  end
108
117
  end
109
118
  end
@@ -52,7 +52,7 @@ module RuboCop
52
52
  MSG_EXPANDED = 'Put the `end` of empty method definitions on the next line.'
53
53
 
54
54
  def on_def(node)
55
- return if node.body || comment_lines?(node)
55
+ return if node.body || processed_source.contains_comment?(node.source_range)
56
56
  return if correct_style?(node)
57
57
 
58
58
  add_offense(node) do |corrector|
@@ -39,7 +39,7 @@ module RuboCop
39
39
  #
40
40
  # @example EnforcedStyle: disallow
41
41
  # # bad
42
- # def my_method; x end
42
+ # def my_method() = x
43
43
  #
44
44
  # # bad
45
45
  # def my_method() = x.foo