rubocop 1.75.1 → 1.75.5

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 (89) hide show
  1. checksums.yaml +4 -4
  2. data/config/default.yml +29 -18
  3. data/lib/rubocop/config_validator.rb +6 -6
  4. data/lib/rubocop/cop/internal_affairs/example_description.rb +1 -1
  5. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +1 -0
  6. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +6 -1
  7. data/lib/rubocop/cop/layout/block_alignment.rb +1 -2
  8. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  9. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
  10. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +2 -2
  11. data/lib/rubocop/cop/layout/hash_alignment.rb +2 -2
  12. data/lib/rubocop/cop/layout/leading_comment_space.rb +13 -1
  13. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +1 -1
  14. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +2 -4
  15. data/lib/rubocop/cop/layout/space_after_semicolon.rb +10 -0
  16. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +4 -1
  17. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +3 -0
  18. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +2 -3
  19. data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
  20. data/lib/rubocop/cop/lint/circular_argument_reference.rb +2 -5
  21. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
  22. data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -3
  23. data/lib/rubocop/cop/lint/literal_as_condition.rb +25 -11
  24. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -1
  25. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
  26. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +2 -2
  27. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -1
  28. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +7 -4
  29. data/lib/rubocop/cop/lint/return_in_void_context.rb +7 -2
  30. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  31. data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -1
  32. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  33. data/lib/rubocop/cop/lint/useless_rescue.rb +1 -1
  34. data/lib/rubocop/cop/lint/void.rb +2 -2
  35. data/lib/rubocop/cop/message_annotator.rb +7 -3
  36. data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
  37. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +1 -1
  38. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  39. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
  40. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +0 -1
  41. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +15 -14
  42. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -0
  43. data/lib/rubocop/cop/mixin/trailing_comma.rb +9 -5
  44. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
  45. data/lib/rubocop/cop/naming/method_name.rb +1 -1
  46. data/lib/rubocop/cop/style/arguments_forwarding.rb +8 -5
  47. data/lib/rubocop/cop/style/class_and_module_children.rb +19 -3
  48. data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
  49. data/lib/rubocop/cop/style/commented_keyword.rb +2 -2
  50. data/lib/rubocop/cop/style/comparable_between.rb +2 -2
  51. data/lib/rubocop/cop/style/conditional_assignment.rb +16 -4
  52. data/lib/rubocop/cop/style/double_negation.rb +1 -1
  53. data/lib/rubocop/cop/style/empty_literal.rb +4 -0
  54. data/lib/rubocop/cop/style/eval_with_location.rb +3 -3
  55. data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -2
  56. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -2
  57. data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
  58. data/lib/rubocop/cop/style/hash_fetch_chain.rb +0 -1
  59. data/lib/rubocop/cop/style/hash_syntax.rb +3 -0
  60. data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
  61. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
  62. data/lib/rubocop/cop/style/identical_conditional_branches.rb +3 -3
  63. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -1
  64. data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
  65. data/lib/rubocop/cop/style/lambda_call.rb +7 -2
  66. data/lib/rubocop/cop/style/map_into_array.rb +3 -1
  67. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +4 -1
  68. data/lib/rubocop/cop/style/redundant_condition.rb +13 -1
  69. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +1 -1
  70. data/lib/rubocop/cop/style/redundant_line_continuation.rb +0 -3
  71. data/lib/rubocop/cop/style/redundant_parentheses.rb +20 -3
  72. data/lib/rubocop/cop/style/return_nil.rb +2 -2
  73. data/lib/rubocop/cop/style/safe_navigation.rb +18 -3
  74. data/lib/rubocop/cop/style/super_arguments.rb +1 -2
  75. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +7 -1
  76. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +1 -1
  77. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +1 -1
  78. data/lib/rubocop/cop/util.rb +1 -1
  79. data/lib/rubocop/cop/variable_force/variable.rb +1 -1
  80. data/lib/rubocop/cops_documentation_generator.rb +6 -2
  81. data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
  82. data/lib/rubocop/formatter/pacman_formatter.rb +1 -1
  83. data/lib/rubocop/magic_comment.rb +8 -0
  84. data/lib/rubocop/rspec/cop_helper.rb +2 -2
  85. data/lib/rubocop/rspec/shared_contexts.rb +1 -2
  86. data/lib/rubocop/server/cache.rb +13 -10
  87. data/lib/rubocop/target_finder.rb +6 -2
  88. data/lib/rubocop/version.rb +1 -1
  89. metadata +9 -6
@@ -27,7 +27,8 @@ module RuboCop
27
27
  # In all cases, chaining one same `to_*` conversion methods listed above is redundant.
28
28
  #
29
29
  # The cop can also register an offense for chaining conversion methods on methods that are
30
- # expected to return a specific type regardless of receiver (eg. `foo.inspect.to_s`).
30
+ # expected to return a specific type regardless of receiver (eg. `foo.inspect.to_s` and
31
+ # `foo.to_json.to_s`).
31
32
  #
32
33
  # @example
33
34
  # # bad
@@ -69,10 +70,12 @@ module RuboCop
69
70
  # foo.to_s
70
71
  #
71
72
  # # bad - chaining a conversion to a method that is expected to return the same type
72
- # inspect.to_s
73
+ # foo.inspect.to_s
74
+ # foo.to_json.to_s
73
75
  #
74
76
  # # good
75
- # inspect
77
+ # foo.inspect
78
+ # foo.to_json
76
79
  #
77
80
  class RedundantTypeConversion < Base
78
81
  extend AutoCorrector
@@ -108,7 +111,7 @@ module RuboCop
108
111
 
109
112
  # Methods that already are expected to return a given type, which makes a further
110
113
  # conversion redundant.
111
- TYPED_METHODS = { to_s: %i[inspect] }.freeze
114
+ TYPED_METHODS = { to_s: %i[inspect to_json] }.freeze
112
115
 
113
116
  CONVERSION_METHODS = Set[*LITERAL_NODE_TYPES.keys].freeze
114
117
  RESTRICT_ON_SEND = CONVERSION_METHODS + [:to_d]
@@ -32,12 +32,17 @@ module RuboCop
32
32
  class ReturnInVoidContext < Base
33
33
  MSG = 'Do not return a value in `%<method>s`.'
34
34
 
35
+ # Returning out of these methods only exits the block itself.
36
+ SCOPE_CHANGING_METHODS = %i[lambda define_method define_singleton_method].freeze
37
+
35
38
  def on_return(return_node)
36
39
  return unless return_node.descendants.any?
37
40
 
38
- def_node = return_node.each_ancestor(:def).first
41
+ def_node = return_node.each_ancestor(:any_def).first
39
42
  return unless def_node&.void_context?
40
- return if return_node.each_ancestor(:any_block).any?(&:lambda?)
43
+ return if return_node.each_ancestor(:any_block).any? do |block_node|
44
+ SCOPE_CHANGING_METHODS.include?(block_node.method_name)
45
+ end
41
46
 
42
47
  add_offense(
43
48
  return_node.loc.keyword,
@@ -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, :any_block).first
119
+ ancestor = node.each_ancestor(:kwbegin, :any_def, :any_block).first
120
120
  return false unless ancestor
121
121
 
122
122
  end_line = ancestor.loc.end&.line || ancestor.loc.last_line
@@ -45,7 +45,7 @@ module RuboCop
45
45
  PATTERN
46
46
 
47
47
  def on_send(node)
48
- def_node = node.each_ancestor(:def, :defs).first
48
+ def_node = node.each_ancestor(:any_def).first
49
49
  return unless def_node
50
50
 
51
51
  enum_conversion_call?(node) do |method_node, arguments|
@@ -40,7 +40,7 @@ module RuboCop
40
40
  # top-level return node's ancestors should not be of block, def, or
41
41
  # defs type.
42
42
  def top_level_return?(return_node)
43
- return_node.each_ancestor(:block, :def, :defs).none?
43
+ return_node.each_ancestor(:block, :any_def).none?
44
44
  end
45
45
  end
46
46
  end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Checks for useless `rescue`s, which only reraise rescued exceptions.
6
+ # Checks for useless ``rescue``s, which only reraise rescued exceptions.
7
7
  #
8
8
  # @example
9
9
  # # bad
@@ -128,8 +128,8 @@ module RuboCop
128
128
 
129
129
  # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
130
130
  def check_void_op(node, &block)
131
- node = node.children.first while node.begin_type?
132
- return unless node.call_type? && OPERATORS.include?(node.method_name)
131
+ node = node.children.first while node&.begin_type?
132
+ return unless node&.call_type? && OPERATORS.include?(node.method_name)
133
133
  if !UNARY_OPERATORS.include?(node.method_name) && node.loc.dot && node.arguments.none?
134
134
  return
135
135
  end
@@ -32,7 +32,7 @@ module RuboCop
32
32
  # @param [String] cop_name for specific cop name
33
33
  # @param [Hash] cop_config configs for specific cop, from config#for_cop
34
34
  # @option cop_config [String] :StyleGuide Extension of base styleguide URL
35
- # @option cop_config [String] :Reference Full reference URL
35
+ # @option cop_config [String] :References Full reference URLs
36
36
  # @option cop_config [String] :Details
37
37
  #
38
38
  # @param [Hash, nil] options optional
@@ -100,8 +100,12 @@ module RuboCop
100
100
  end
101
101
 
102
102
  def reference_urls
103
- urls = Array(cop_config['Reference'])
104
- urls.nil? || urls.empty? ? nil : urls.reject(&:empty?)
103
+ urls = cop_config
104
+ .values_at('References', 'Reference') # Support legacy Reference key
105
+ .flat_map { Array(_1) }
106
+ .reject(&:empty?)
107
+
108
+ urls unless urls.empty?
105
109
  end
106
110
 
107
111
  def extra_details?
@@ -48,7 +48,7 @@ module RuboCop
48
48
 
49
49
  args = process_args(node.arguments)
50
50
  return extract_breakable_node_from_elements(node, args, max)
51
- elsif node.type?(:def, :defs)
51
+ elsif node.any_def_type?
52
52
  return extract_breakable_node_from_elements(node, node.arguments, max)
53
53
  elsif node.type?(:array, :hash)
54
54
  return extract_breakable_node_from_elements(node, node.children, max)
@@ -220,7 +220,7 @@ module RuboCop
220
220
 
221
221
  # @api private
222
222
  def already_on_multiple_lines?(node)
223
- return node.first_line != node.last_argument.last_line if node.type?(:def, :defs)
223
+ return node.first_line != node.last_argument.last_line if node.any_def_type?
224
224
 
225
225
  !node.single_line?
226
226
  end
@@ -40,7 +40,7 @@ module RuboCop
40
40
  end
41
41
 
42
42
  def safe_to_split?(node)
43
- node.each_descendant(:if, :case, :kwbegin, :def, :defs).none? &&
43
+ node.each_descendant(:if, :case, :kwbegin, :any_def).none? &&
44
44
  node.each_descendant(:dstr, :str).none? { |n| n.heredoc? || n.value.include?("\n") } &&
45
45
  node.each_descendant(:begin, :sym).none? { |b| !b.single_line? }
46
46
  end
@@ -19,7 +19,7 @@ module RuboCop
19
19
 
20
20
  # @!method non_public_modifier?(node)
21
21
  def_node_matcher :non_public_modifier?, <<~PATTERN
22
- (send nil? {:private :protected :private_class_method} ({def defs} ...))
22
+ (send nil? {:private :protected :private_class_method} (any_def ...))
23
23
  PATTERN
24
24
  end
25
25
  end
@@ -21,7 +21,7 @@ module RuboCop
21
21
 
22
22
  # @!method empty_line_required?(node)
23
23
  def_node_matcher :empty_line_required?,
24
- '{def defs class module (send nil? {:private :protected :public})}'
24
+ '{any_def class module (send nil? {:private :protected :public})}'
25
25
 
26
26
  def check(node, body, adjusted_first_line: nil)
27
27
  return if valid_body_style?(body)
@@ -6,7 +6,6 @@ module RuboCop
6
6
  module FrozenStringLiteral
7
7
  module_function
8
8
 
9
- FROZEN_STRING_LITERAL_REGEXP = /#\s*frozen[-_]?string[-_]?literal:/i.freeze
10
9
  FROZEN_STRING_LITERAL_ENABLED = '# frozen_string_literal: true'
11
10
  FROZEN_STRING_LITERAL_TYPES_RUBY27 = %i[str dstr].freeze
12
11
 
@@ -10,7 +10,7 @@ module RuboCop
10
10
  true
11
11
  end
12
12
 
13
- def deltas_for_first_pair(first_pair, _node)
13
+ def deltas_for_first_pair(first_pair)
14
14
  {
15
15
  separator: separator_delta(first_pair),
16
16
  value: value_delta(first_pair)
@@ -81,13 +81,7 @@ module RuboCop
81
81
  class TableAlignment
82
82
  include ValueAlignment
83
83
 
84
- def initialize
85
- self.max_key_width = 0
86
- end
87
-
88
- def deltas_for_first_pair(first_pair, node)
89
- self.max_key_width = node.keys.map { |key| key.source.length }.max
90
-
84
+ def deltas_for_first_pair(first_pair)
91
85
  separator_delta = separator_delta(first_pair, first_pair, 0)
92
86
  {
93
87
  separator: separator_delta,
@@ -97,30 +91,37 @@ module RuboCop
97
91
 
98
92
  private
99
93
 
100
- attr_accessor :max_key_width
101
-
102
94
  def key_delta(first_pair, current_pair)
103
95
  first_pair.key_delta(current_pair)
104
96
  end
105
97
 
106
98
  def hash_rocket_delta(first_pair, current_pair)
107
- first_pair.loc.column + max_key_width + 1 - current_pair.loc.operator.column
99
+ first_pair.loc.column + max_key_width(first_pair.parent) + 1 -
100
+ current_pair.loc.operator.column
108
101
  end
109
102
 
110
103
  def value_delta(first_pair, current_pair)
111
104
  correct_value_column = first_pair.key.loc.column +
112
- current_pair.delimiter(true).length +
113
- max_key_width
105
+ max_key_width(first_pair.parent) +
106
+ max_delimiter_width(first_pair.parent)
114
107
 
115
108
  current_pair.value_omission? ? 0 : correct_value_column - current_pair.value.loc.column
116
109
  end
110
+
111
+ def max_key_width(hash_node)
112
+ hash_node.keys.map { |key| key.source.length }.max
113
+ end
114
+
115
+ def max_delimiter_width(hash_node)
116
+ hash_node.pairs.map { |pair| pair.delimiter(true).length }.max
117
+ end
117
118
  end
118
119
 
119
120
  # Handles calculation of deltas when the enforced style is 'separator'.
120
121
  class SeparatorAlignment
121
122
  include ValueAlignment
122
123
 
123
- def deltas_for_first_pair(*_nodes)
124
+ def deltas_for_first_pair(_first_pair)
124
125
  {}
125
126
  end
126
127
 
@@ -17,6 +17,8 @@ module RuboCop
17
17
 
18
18
  lhs = left_hand_side(node.receiver)
19
19
  rhs = right_hand_side(node)
20
+ return unless rhs
21
+
20
22
  range = offending_range(node, lhs, rhs, style)
21
23
  check(range, node, lhs, rhs)
22
24
  end
@@ -107,7 +107,7 @@ module RuboCop
107
107
  # of the argument is not considered multiline, even if the argument
108
108
  # itself might span multiple lines.
109
109
  def allowed_multiline_argument?(node)
110
- elements(node).one? && !Util.begins_its_line?(node.loc.end)
110
+ elements(node).one? && !Util.begins_its_line?(node_end_location(node))
111
111
  end
112
112
 
113
113
  def elements(node)
@@ -127,18 +127,22 @@ module RuboCop
127
127
 
128
128
  def no_elements_on_same_line?(node)
129
129
  items = elements(node).map(&:source_range)
130
- items << node.loc.end
130
+ items << node_end_location(node)
131
131
  items.each_cons(2).none? { |a, b| on_same_line?(a, b) }
132
132
  end
133
133
 
134
+ def node_end_location(node)
135
+ node.loc.end || node.source_range.end.adjust(begin_pos: -1)
136
+ end
137
+
134
138
  def on_same_line?(range1, range2)
135
139
  range1.last_line == range2.line
136
140
  end
137
141
 
138
142
  def last_item_precedes_newline?(node)
139
- after_last_item =
140
- range_between(node.children.last.source_range.end_pos, node.loc.end.begin_pos)
141
- after_last_item.source =~ /\A,?\s*\n/
143
+ after_last_item = node.children.last.source_range.end.join(node.loc.end.begin)
144
+
145
+ after_last_item.source.start_with?(/,?\s*(#.*)?\n/)
142
146
  end
143
147
 
144
148
  def avoid_comma(kind, comma_begin_pos, extra_info)
@@ -242,7 +242,7 @@ module RuboCop
242
242
  def find_definition(node)
243
243
  # Methods can be defined in a `def` or `defs`,
244
244
  # or dynamically via a `block` node.
245
- node.each_ancestor(:def, :defs, :block).each do |ancestor|
245
+ node.each_ancestor(:any_def, :block).each do |ancestor|
246
246
  method_node, method_name = method_definition?(ancestor)
247
247
  return [method_node, method_name] if method_node
248
248
  end
@@ -105,7 +105,7 @@ module RuboCop
105
105
  end
106
106
 
107
107
  def register_forbidden_name(node)
108
- if node.type?(:def, :defs)
108
+ if node.any_def_type?
109
109
  name_node = node.loc.name
110
110
  method_name = node.method_name
111
111
  else
@@ -16,16 +16,16 @@ module RuboCop
16
16
  #
17
17
  # In Ruby 3.2, anonymous args/kwargs forwarding has been added.
18
18
  #
19
- # This cop also identifies places where `use_args(*args)`/`use_kwargs(**kwargs)` can be
20
- # replaced by `use_args(*)`/`use_kwargs(**)`; if desired, this functionality can be disabled
21
- # by setting `UseAnonymousForwarding: false`.
19
+ # This cop also identifies places where `+use_args(*args)+`/`+use_kwargs(**kwargs)+` can be
20
+ # replaced by `+use_args(*)+`/`+use_kwargs(**)+`; if desired, this functionality can be
21
+ # disabled by setting `UseAnonymousForwarding: false`.
22
22
  #
23
23
  # And this cop has `RedundantRestArgumentNames`, `RedundantKeywordRestArgumentNames`,
24
24
  # and `RedundantBlockArgumentNames` options. This configuration is a list of redundant names
25
25
  # that are sufficient for anonymizing meaningless naming.
26
26
  #
27
27
  # Meaningless names that are commonly used can be anonymized by default:
28
- # e.g., `*args`, `**options`, `&block`, and so on.
28
+ # e.g., `+*args+`, `+**options+`, `&block`, and so on.
29
29
  #
30
30
  # Names not on this list are likely to be meaningful and are allowed by default.
31
31
  #
@@ -146,7 +146,7 @@ module RuboCop
146
146
  minimum_target_ruby_version 2.7
147
147
 
148
148
  FORWARDING_LVAR_TYPES = %i[splat kwsplat block_pass].freeze
149
- ADDITIONAL_ARG_TYPES = %i[lvar arg].freeze
149
+ ADDITIONAL_ARG_TYPES = %i[lvar arg optarg].freeze
150
150
 
151
151
  FORWARDING_MSG = 'Use shorthand syntax `...` for arguments forwarding.'
152
152
  ARGS_MSG = 'Use anonymous positional arguments forwarding (`*`).'
@@ -479,6 +479,9 @@ module RuboCop
479
479
  end
480
480
 
481
481
  def ruby_32_only_anonymous_forwarding?
482
+ # A block argument and an anonymous block argument are never passed together.
483
+ return false if @send_node.each_ancestor(:any_block).any?
484
+
482
485
  def_all_anonymous_args?(@def_node) && send_all_anonymous_args?(@send_node)
483
486
  end
484
487
 
@@ -131,21 +131,27 @@ module RuboCop
131
131
  "#{node.body.children.first.const_name}"
132
132
  end
133
133
 
134
+ # rubocop:disable Metrics/AbcSize
134
135
  def remove_end(corrector, body)
135
- remove_begin_pos = body.loc.end.begin_pos - leading_spaces(body).size
136
+ remove_begin_pos = if same_line?(body.loc.name, body.loc.end)
137
+ body.loc.name.end_pos
138
+ else
139
+ body.loc.end.begin_pos - leading_spaces(body).size
140
+ end
136
141
  adjustment = processed_source.raw_source[remove_begin_pos] == ';' ? 0 : 1
137
142
  range = range_between(remove_begin_pos, body.loc.end.end_pos + adjustment)
138
143
 
139
144
  corrector.remove(range)
140
145
  end
146
+ # rubocop:enable Metrics/AbcSize
141
147
 
142
148
  def unindent(corrector, node)
143
149
  return unless node.body.children.last
144
150
 
145
151
  last_child_leading_spaces = leading_spaces(node.body.children.last)
146
- return if leading_spaces(node).size == last_child_leading_spaces.size
152
+ return if spaces_size(leading_spaces(node)) == spaces_size(last_child_leading_spaces)
147
153
 
148
- column_delta = configured_indentation_width - last_child_leading_spaces.size
154
+ column_delta = configured_indentation_width - spaces_size(last_child_leading_spaces)
149
155
  return if column_delta.zero?
150
156
 
151
157
  AlignmentCorrector.correct(corrector, processed_source, node, column_delta)
@@ -155,6 +161,16 @@ module RuboCop
155
161
  node.source_range.source_line[/\A\s*/]
156
162
  end
157
163
 
164
+ def spaces_size(spaces_string)
165
+ mapping = { "\t" => tab_indentation_width }
166
+ spaces_string.chars.sum { |character| mapping.fetch(character, 1) }
167
+ end
168
+
169
+ def tab_indentation_width
170
+ config.for_cop('Layout/IndentationStyle')['IndentationWidth'] ||
171
+ configured_indentation_width
172
+ end
173
+
158
174
  def check_style(node, body, style)
159
175
  return if node.identifier.namespace&.cbase_type?
160
176
 
@@ -68,7 +68,7 @@ module RuboCop
68
68
  PATTERN
69
69
 
70
70
  def on_send(node)
71
- def_node = node.each_ancestor(:def, :defs).first
71
+ def_node = node.each_ancestor(:any_def).first
72
72
  return if def_node &&
73
73
  (allowed_method?(def_node.method_name) ||
74
74
  matches_allowed_pattern?(def_node.method_name))
@@ -58,7 +58,7 @@ module RuboCop
58
58
  REGEXP = /(?<keyword>\S+).*#/.freeze
59
59
 
60
60
  SUBCLASS_DEFINITION = /\A\s*class\s+(\w|::)+\s*<\s*(\w|::)+/.freeze
61
- METHOD_DEFINITION = /\A\s*def\s/.freeze
61
+ METHOD_OR_END_DEFINITIONS = /\A\s*(def\s|end)/.freeze
62
62
 
63
63
  STEEP_REGEXP = /#\ssteep:ignore(\s|\z)/.freeze
64
64
 
@@ -102,7 +102,7 @@ module RuboCop
102
102
  case line
103
103
  when SUBCLASS_DEFINITION
104
104
  comment.text.start_with?(/#\[.+\]/)
105
- when METHOD_DEFINITION
105
+ when METHOD_OR_END_DEFINITIONS
106
106
  comment.text.start_with?('#:')
107
107
  else
108
108
  false
@@ -61,8 +61,8 @@ module RuboCop
61
61
 
62
62
  def register_offense(node, min_and_value, max_and_value)
63
63
  value = (min_and_value & max_and_value).first
64
- min = min_and_value.find { _1 != value }
65
- max = max_and_value.find { _1 != value }
64
+ min = min_and_value.find { _1 != value } || value
65
+ max = max_and_value.find { _1 != value } || value
66
66
 
67
67
  prefer = "#{value.source}.between?(#{min.source}, #{max.source})"
68
68
  add_offense(node, message: format(MSG, prefer: prefer)) do |corrector|
@@ -314,6 +314,7 @@ module RuboCop
314
314
 
315
315
  def assignment_node(node)
316
316
  assignment = node.send_type? ? node.last_argument : node.expression
317
+ return unless assignment
317
318
 
318
319
  # ignore pseudo-assignments without rhs in for nodes
319
320
  return if node.parent&.for_type?
@@ -436,19 +437,28 @@ module RuboCop
436
437
  # Helper module to provide common methods to ConditionalAssignment
437
438
  # correctors
438
439
  module ConditionalCorrectorHelper
440
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
439
441
  def remove_whitespace_in_branches(corrector, branch, condition, column)
440
442
  branch.each_node do |child|
441
443
  next if child.source_range.nil?
444
+ next if child.parent.dstr_type?
442
445
 
443
446
  white_space = white_space_range(child, column)
444
447
  corrector.remove(white_space) if white_space.source.strip.empty?
445
448
  end
446
449
 
447
- [condition.loc.else, condition.loc.end].each do |loc|
448
- next unless loc
449
-
450
- corrector.remove_preceding(loc, loc.column - column)
450
+ if condition.loc.else && !same_line?(condition.else_branch, condition)
451
+ corrector.remove_preceding(condition.loc.else, condition.loc.else.column - column)
451
452
  end
453
+
454
+ return unless condition.loc.end && !same_line?(condition.loc.end, condition)
455
+
456
+ corrector.remove_preceding(condition.loc.end, condition.loc.end.column - column)
457
+ end
458
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
459
+
460
+ def same_line?(node1, node2)
461
+ RuboCop::Cop::Util.same_line?(node1, node2)
452
462
  end
453
463
 
454
464
  def white_space_range(node, column)
@@ -595,6 +605,8 @@ module RuboCop
595
605
 
596
606
  return unless (branch_else = branch.parent.loc.else)
597
607
 
608
+ return if same_line?(branch_else, condition)
609
+
598
610
  corrector.remove_preceding(branch_else, branch_else.column - column)
599
611
  end
600
612
  end
@@ -102,7 +102,7 @@ module RuboCop
102
102
 
103
103
  def find_def_node_from_ascendant(node)
104
104
  return unless (parent = node.parent)
105
- return parent if parent.type?(:def, :defs)
105
+ return parent if parent.any_def_type?
106
106
  return node.parent.child_nodes.first if define_method?(parent)
107
107
 
108
108
  find_def_node_from_ascendant(node.parent)
@@ -6,6 +6,10 @@ module RuboCop
6
6
  # Checks for the use of a method, the result of which
7
7
  # would be a literal, like an empty array, hash, or string.
8
8
  #
9
+ # NOTE: When frozen string literals are enabled, `String.new`
10
+ # isn't corrected to an empty string since the former is
11
+ # mutable and the latter would be frozen.
12
+ #
9
13
  # @example
10
14
  # # bad
11
15
  # a = Array.new
@@ -4,12 +4,12 @@ module RuboCop
4
4
  module Cop
5
5
  module Style
6
6
  # Ensures that eval methods (`eval`, `instance_eval`, `class_eval`
7
- # and `module_eval`) are given filename and line number values (`\_\_FILE\_\_`
8
- # and `\_\_LINE\_\_`). This data is used to ensure that any errors raised
7
+ # and `module_eval`) are given filename and line number values (`+__FILE__+`
8
+ # and `+__LINE__+`). This data is used to ensure that any errors raised
9
9
  # within the evaluated code will be given the correct identification
10
10
  # in a backtrace.
11
11
  #
12
- # The cop also checks that the line number given relative to `\_\_LINE\_\_` is
12
+ # The cop also checks that the line number given relative to `+__LINE__+` is
13
13
  # correct.
14
14
  #
15
15
  # This cop will autocorrect incorrect or missing filename and line number
@@ -65,7 +65,7 @@ module RuboCop
65
65
  yielding_block?(block_node) do |send_node, block_args, yield_args|
66
66
  return unless yielding_arguments?(block_args, yield_args)
67
67
 
68
- def_node = block_node.each_ancestor(:def, :defs).first
68
+ def_node = block_node.each_ancestor(:any_def).first
69
69
  # if `yield` is being called outside of a method context, ignore
70
70
  # this is not a valid ruby pattern, but can happen in haml or erb,
71
71
  # so this can cause crashes in haml_lint
@@ -151,7 +151,7 @@ module RuboCop
151
151
  end
152
152
 
153
153
  def build_new_arguments_for_zsuper(node)
154
- def_node = node.each_ancestor(:def, :defs).first
154
+ def_node = node.each_ancestor(:any_def).first
155
155
  def_node.arguments.map do |arg|
156
156
  arg.optarg_type? ? arg.node_parts[0] : arg.source
157
157
  end
@@ -151,7 +151,7 @@ module RuboCop
151
151
 
152
152
  def frozen_string_literal_comment(processed_source)
153
153
  processed_source.tokens.find do |token|
154
- token.text.start_with?(FROZEN_STRING_LITERAL_REGEXP)
154
+ MagicComment.parse(token.text).frozen_string_literal_specified?
155
155
  end
156
156
  end
157
157
 
@@ -189,8 +189,9 @@ module RuboCop
189
189
 
190
190
  def enable_comment(corrector)
191
191
  comment = frozen_string_literal_comment(processed_source)
192
+ replacement = MagicComment.parse(comment.text).new_frozen_string_literal(true)
192
193
 
193
- corrector.replace(line_range(comment.line), FROZEN_STRING_LITERAL_ENABLED)
194
+ corrector.replace(line_range(comment.line), replacement)
194
195
  end
195
196
 
196
197
  def insert_comment(corrector)
@@ -8,6 +8,9 @@ module RuboCop
8
8
  # reassign (possibly to redirect some stream) constants in Ruby, you'll get
9
9
  # an interpreter warning if you do so.
10
10
  #
11
+ # Additionally, `$stdout/$stderr/$stdin` can safely be accessed in a Ractor because they
12
+ # are ractor-local, while `STDOUT/STDERR/STDIN` will raise `Ractor::IsolationError`.
13
+ #
11
14
  # @safety
12
15
  # Autocorrection is unsafe because `STDOUT` and `$stdout` may point to different
13
16
  # objects, for example.
@@ -40,7 +40,6 @@ module RuboCop
40
40
  class HashFetchChain < Base
41
41
  extend AutoCorrector
42
42
  extend TargetRubyVersion
43
- include IgnoredNode
44
43
 
45
44
  MSG = 'Use `%<replacement>s` instead.'
46
45
  RESTRICT_ON_SEND = %i[fetch].freeze
@@ -76,6 +76,9 @@ module RuboCop
76
76
  # # good
77
77
  # {foo:, bar:}
78
78
  #
79
+ # # good - allowed to mix syntaxes
80
+ # {foo:, bar: baz}
81
+ #
79
82
  # @example EnforcedShorthandSyntax: never
80
83
  #
81
84
  # # bad
@@ -3,8 +3,8 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Looks for uses of `\_.each_with_object({}) {...}`,
7
- # `\_.map {...}.to_h`, and `Hash[\_.map {...}]` that are actually just
6
+ # Looks for uses of `+_.each_with_object({}) {...}+`,
7
+ # `+_.map {...}.to_h+`, and `+Hash[_.map {...}]+` that are actually just
8
8
  # transforming the keys of a hash, and tries to use a simpler & faster
9
9
  # call to `transform_keys` instead.
10
10
  # It should only be enabled on Ruby version 2.5 or newer.
@@ -3,8 +3,8 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Looks for uses of `\_.each_with_object({}) {...}`,
7
- # `\_.map {...}.to_h`, and `Hash[\_.map {...}]` that are actually just
6
+ # Looks for uses of `+_.each_with_object({}) {...}+`,
7
+ # `+_.map {...}.to_h+`, and `+Hash[_.map {...}]+` that are actually just
8
8
  # transforming the values of a hash, and tries to use a simpler & faster
9
9
  # call to `transform_values` instead.
10
10
  #