rubocop 1.36.0 → 1.37.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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +21 -1
  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/cop/generator.rb +1 -2
  9. data/lib/rubocop/cop/internal_affairs/create_empty_file.rb +37 -0
  10. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +111 -0
  11. data/lib/rubocop/cop/internal_affairs.rb +2 -0
  12. data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -0
  13. data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
  14. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +13 -9
  15. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +28 -3
  16. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  17. data/lib/rubocop/cop/lint/duplicate_magic_comment.rb +73 -0
  18. data/lib/rubocop/cop/lint/duplicate_methods.rb +11 -1
  19. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +25 -6
  20. data/lib/rubocop/cop/lint/empty_class.rb +3 -1
  21. data/lib/rubocop/cop/lint/empty_conditional_body.rb +19 -7
  22. data/lib/rubocop/cop/lint/nested_method_definition.rb +50 -1
  23. data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
  24. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +4 -5
  25. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -1
  26. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +12 -1
  27. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +7 -0
  28. data/lib/rubocop/cop/lint/redundant_require_statement.rb +29 -9
  29. data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
  30. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -2
  31. data/lib/rubocop/cop/lint/shadowed_exception.rb +0 -10
  32. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +3 -0
  33. data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
  34. data/lib/rubocop/cop/lint/unused_method_argument.rb +4 -0
  35. data/lib/rubocop/cop/mixin/comments_help.rb +12 -0
  36. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -0
  37. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +6 -3
  38. data/lib/rubocop/cop/mixin/rescue_node.rb +3 -1
  39. data/lib/rubocop/cop/mixin/surrounding_space.rb +6 -5
  40. data/lib/rubocop/cop/naming/inclusive_language.rb +1 -1
  41. data/lib/rubocop/cop/style/access_modifier_declarations.rb +24 -2
  42. data/lib/rubocop/cop/style/accessor_grouping.rb +7 -3
  43. data/lib/rubocop/cop/style/block_delimiters.rb +1 -1
  44. data/lib/rubocop/cop/style/character_literal.rb +1 -1
  45. data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
  46. data/lib/rubocop/cop/style/collection_compact.rb +8 -1
  47. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  48. data/lib/rubocop/cop/style/endless_method.rb +1 -1
  49. data/lib/rubocop/cop/style/explicit_block_argument.rb +4 -0
  50. data/lib/rubocop/cop/style/format_string_token.rb +1 -1
  51. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  52. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +13 -2
  53. data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -1
  54. data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
  55. data/lib/rubocop/cop/style/operator_method_call.rb +40 -0
  56. data/lib/rubocop/cop/style/redundant_begin.rb +1 -0
  57. data/lib/rubocop/cop/style/redundant_condition.rb +5 -2
  58. data/lib/rubocop/cop/style/redundant_initialize.rb +3 -1
  59. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +8 -1
  60. data/lib/rubocop/cop/style/redundant_string_escape.rb +181 -0
  61. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
  62. data/lib/rubocop/cop/style/static_class.rb +32 -1
  63. data/lib/rubocop/cop/style/symbol_array.rb +2 -0
  64. data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
  65. data/lib/rubocop/cop/style/word_array.rb +2 -0
  66. data/lib/rubocop/formatter/disabled_config_formatter.rb +8 -2
  67. data/lib/rubocop/options.rb +13 -13
  68. data/lib/rubocop/rspec/shared_contexts.rb +13 -1
  69. data/lib/rubocop/server/cache.rb +5 -1
  70. data/lib/rubocop/server/cli.rb +9 -2
  71. data/lib/rubocop/server/client_command/exec.rb +5 -0
  72. data/lib/rubocop/server/core.rb +2 -1
  73. data/lib/rubocop/server/socket_reader.rb +5 -1
  74. data/lib/rubocop/server.rb +1 -1
  75. data/lib/rubocop/version.rb +8 -3
  76. data/lib/rubocop.rb +3 -0
  77. metadata +12 -5
@@ -92,13 +92,17 @@ module RuboCop
92
92
  end
93
93
 
94
94
  def remove_empty_branch(corrector, node)
95
- corrector.remove(deletion_range(branch_range(node)))
95
+ if empty_if_branch?(node) && else_branch?(node)
96
+ corrector.remove(branch_range(node))
97
+ else
98
+ corrector.remove(deletion_range(branch_range(node)))
99
+ end
96
100
  end
97
101
 
98
102
  def correct_other_branches(corrector, node)
99
103
  return unless require_other_branches_correction?(node)
100
104
 
101
- if node.else_branch.if_type?
105
+ if node.else_branch&.if_type?
102
106
  # Replace an orphaned `elsif` with `if`
103
107
  corrector.replace(node.else_branch.loc.keyword, 'if')
104
108
  else
@@ -108,10 +112,10 @@ module RuboCop
108
112
  end
109
113
 
110
114
  def require_other_branches_correction?(node)
111
- return false unless node.if_type? && node.else_branch
115
+ return false unless node.if_type? && node.else?
112
116
  return false if !empty_if_branch?(node) && node.elsif?
113
117
 
114
- !empty_else_branch?(node)
118
+ !empty_elsif_branch?(node)
115
119
  end
116
120
 
117
121
  def empty_if_branch?(node)
@@ -122,13 +126,21 @@ module RuboCop
122
126
  if_branch.if_type? && !if_branch.body
123
127
  end
124
128
 
125
- def empty_else_branch?(node)
126
- node.else_branch.if_type? && !node.else_branch.body
129
+ def empty_elsif_branch?(node)
130
+ return false unless (else_branch = node.else_branch)
131
+
132
+ else_branch.if_type? && !else_branch.body
133
+ end
134
+
135
+ def else_branch?(node)
136
+ node.else_branch && !node.else_branch.if_type?
127
137
  end
128
138
 
129
139
  # rubocop:disable Metrics/AbcSize
130
140
  def branch_range(node)
131
- if node.loc.else
141
+ if empty_if_branch?(node) && else_branch?(node)
142
+ node.source_range.with(end_pos: node.loc.else.begin_pos)
143
+ elsif node.loc.else
132
144
  node.source_range.with(end_pos: node.loc.else.begin_pos - 1)
133
145
  elsif all_branches_body_missing?(node)
134
146
  if_node = node.ancestors.detect(&:if?)
@@ -30,6 +30,9 @@ module RuboCop
30
30
  #
31
31
  # # good
32
32
  #
33
+ # # `class_eval`, `instance_eval`, `module_eval`, `class_exec`, `instance_exec`, and
34
+ # # `module_exec` blocks are allowed by default.
35
+ #
33
36
  # def foo
34
37
  # self.class.class_eval do
35
38
  # def bar
@@ -54,7 +57,47 @@ module RuboCop
54
57
  # end
55
58
  # end
56
59
  # end
60
+ #
61
+ # @example AllowedMethods: [] (default)
62
+ # # bad
63
+ # def do_something
64
+ # has_many :articles do
65
+ # def find_or_create_by_name(name)
66
+ # end
67
+ # end
68
+ # end
69
+ #
70
+ # @example AllowedMethods: ['has_many']
71
+ # # bad
72
+ # def do_something
73
+ # has_many :articles do
74
+ # def find_or_create_by_name(name)
75
+ # end
76
+ # end
77
+ # end
78
+ #
79
+ # @example AllowedPatterns: [] (default)
80
+ # # bad
81
+ # def foo(obj)
82
+ # obj.do_baz do
83
+ # def bar
84
+ # end
85
+ # end
86
+ # end
87
+ #
88
+ # @example AllowedPatterns: ['baz']
89
+ # # good
90
+ # def foo(obj)
91
+ # obj.do_baz do
92
+ # def bar
93
+ # end
94
+ # end
95
+ # end
96
+ #
57
97
  class NestedMethodDefinition < Base
98
+ include AllowedMethods
99
+ include AllowedPattern
100
+
58
101
  MSG = 'Method definitions must not be nested. Use `lambda` instead.'
59
102
 
60
103
  def on_def(node)
@@ -77,7 +120,13 @@ module RuboCop
77
120
 
78
121
  def scoping_method_call?(child)
79
122
  child.sclass_type? || eval_call?(child) || exec_call?(child) ||
80
- class_or_module_or_struct_new_call?(child)
123
+ class_or_module_or_struct_new_call?(child) || allowed_method_name?(child)
124
+ end
125
+
126
+ def allowed_method_name?(node)
127
+ name = node.method_name
128
+
129
+ allowed_method?(name) || matches_allowed_pattern?(name)
81
130
  end
82
131
 
83
132
  # @!method eval_call?(node)
@@ -61,7 +61,7 @@ module RuboCop
61
61
  # # bad
62
62
  # 10.minutes.to_i
63
63
  #
64
- # @example AllowedPatterns: [/min*/]
64
+ # @example AllowedPatterns: ['min*']
65
65
  #
66
66
  # # good
67
67
  # 10.minutes.to_i
@@ -7,6 +7,9 @@ module RuboCop
7
7
  # Checks the proper ordering of magic comments and whether
8
8
  # a magic comment is not placed before a shebang.
9
9
  #
10
+ # @safety
11
+ # This cop's autocorrection is unsafe because file encoding may change.
12
+ #
10
13
  # @example
11
14
  # # bad
12
15
  #
@@ -61,7 +64,7 @@ module RuboCop
61
64
  def magic_comment_lines
62
65
  lines = [nil, nil]
63
66
 
64
- magic_comments.each.with_index do |comment, index|
67
+ leading_magic_comments.each.with_index do |comment, index|
65
68
  if comment.encoding_specified?
66
69
  lines[0] = index
67
70
  elsif comment.frozen_string_literal_specified?
@@ -73,10 +76,6 @@ module RuboCop
73
76
 
74
77
  lines
75
78
  end
76
-
77
- def magic_comments
78
- leading_comment_lines.map { |line| MagicComment.parse(line) }
79
- end
80
79
  end
81
80
  end
82
81
  end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # This cops looks for references of Regexp captures that are out of range
6
+ # Looks for references of Regexp captures that are out of range
7
7
  # and thus always returns nil.
8
8
  #
9
9
  # @safety
@@ -209,7 +209,12 @@ module RuboCop
209
209
 
210
210
  add_offense(location, message: message(cop_names)) do |corrector|
211
211
  range = comment_range_with_surrounding_space(location, comment.loc.expression)
212
- corrector.remove(range)
212
+
213
+ if leave_free_comment?(comment, range)
214
+ corrector.replace(range, ' # ')
215
+ else
216
+ corrector.remove(range)
217
+ end
213
218
  end
214
219
  end
215
220
 
@@ -227,6 +232,12 @@ module RuboCop
227
232
  end
228
233
  end
229
234
 
235
+ def leave_free_comment?(comment, range)
236
+ free_comment = comment.text.gsub(range.source.strip, '')
237
+
238
+ !free_comment.empty? && !free_comment.start_with?('#')
239
+ end
240
+
230
241
  def cop_range(comment, cop)
231
242
  cop = remove_department_marker(cop)
232
243
  matching_range(comment.loc.expression, cop) ||
@@ -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,22 @@ 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
+ #
24
+ # This cop target those features.
16
25
  #
17
26
  # @example
18
27
  # # bad
@@ -24,21 +33,19 @@ module RuboCop
24
33
  class RedundantRequireStatement < Base
25
34
  include RangeHelp
26
35
  extend AutoCorrector
27
- extend TargetRubyVersion
28
-
29
- minimum_target_ruby_version 2.2
30
36
 
31
37
  MSG = 'Remove unnecessary `require` statement.'
32
38
  RESTRICT_ON_SEND = %i[require].freeze
39
+ RUBY_22_LOADED_FEATURES = %w[rational complex].freeze
33
40
 
34
- # @!method unnecessary_require_statement?(node)
35
- def_node_matcher :unnecessary_require_statement?, <<~PATTERN
41
+ # @!method redundant_require_statement?(node)
42
+ def_node_matcher :redundant_require_statement?, <<~PATTERN
36
43
  (send nil? :require
37
- (str {"enumerator" "rational" "complex" "thread"}))
44
+ (str #redundant_feature?))
38
45
  PATTERN
39
46
 
40
47
  def on_send(node)
41
- return unless unnecessary_require_statement?(node)
48
+ return unless redundant_require_statement?(node)
42
49
 
43
50
  add_offense(node) do |corrector|
44
51
  range = range_with_surrounding_space(node.loc.expression, side: :right)
@@ -46,6 +53,19 @@ module RuboCop
46
53
  corrector.remove(range)
47
54
  end
48
55
  end
56
+
57
+ private
58
+
59
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
60
+ def redundant_feature?(feature_name)
61
+ feature_name == 'enumerator' ||
62
+ (target_ruby_version >= 2.1 && feature_name == 'thread') ||
63
+ (target_ruby_version >= 2.2 && RUBY_22_LOADED_FEATURES.include?(feature_name)) ||
64
+ (target_ruby_version >= 2.5 && feature_name == 'pp') ||
65
+ (target_ruby_version >= 2.7 && feature_name == 'ruby2_keywords') ||
66
+ (target_ruby_version >= 3.1 && feature_name == 'fiber')
67
+ end
68
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
49
69
  end
50
70
  end
51
71
  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
  #
@@ -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
@@ -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)
@@ -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
 
@@ -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
@@ -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}")
@@ -201,11 +204,30 @@ module RuboCop
201
204
  def remove_node(corrector, node)
202
205
  corrector.remove(
203
206
  range_by_whole_lines(
204
- node.location.expression,
207
+ range_with_comments(node),
205
208
  include_final_newline: true
206
209
  )
207
210
  )
208
211
  end
212
+
213
+ def range_with_comments(node)
214
+ ranges = [
215
+ node,
216
+ *processed_source.ast_with_comments[node]
217
+ ].map do |element|
218
+ element.location.expression
219
+ end
220
+ ranges.reduce do |result, range|
221
+ add_range(result, range)
222
+ end
223
+ end
224
+
225
+ def add_range(range1, range2)
226
+ range1.with(
227
+ begin_pos: [range1.begin_pos, range2.begin_pos].min,
228
+ end_pos: [range1.end_pos, range2.end_pos].max
229
+ )
230
+ end
209
231
  end
210
232
  end
211
233
  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|
@@ -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)
@@ -36,8 +36,8 @@ module RuboCop
36
36
  extend AutoCorrector
37
37
 
38
38
  MSG = 'Use `%<good>s` instead of `%<bad>s`.'
39
-
40
39
  RESTRICT_ON_SEND = %i[reject reject! select select!].freeze
40
+ TO_ENUM_METHODS = %i[to_enum lazy].freeze
41
41
 
42
42
  # @!method reject_method_with_block_pass?(node)
43
43
  def_node_matcher :reject_method_with_block_pass?, <<~PATTERN
@@ -69,6 +69,7 @@ module RuboCop
69
69
 
70
70
  def on_send(node)
71
71
  return unless (range = offense_range(node))
72
+ return if target_ruby_version <= 3.0 && to_enum_method?(node)
72
73
 
73
74
  good = good_method_name(node)
74
75
  message = format(MSG, good: good, bad: range.source)
@@ -94,6 +95,12 @@ module RuboCop
94
95
  end
95
96
  end
96
97
 
98
+ def to_enum_method?(node)
99
+ return false unless node.receiver.send_type?
100
+
101
+ TO_ENUM_METHODS.include?(node.receiver.method_name)
102
+ end
103
+
97
104
  def good_method_name(node)
98
105
  if node.bang_method?
99
106
  'compact!'
@@ -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