rubocop 1.75.1 → 1.75.6

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 (99) hide show
  1. checksums.yaml +4 -4
  2. data/config/default.yml +31 -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 +5 -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_class_methods.rb +1 -1
  22. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
  23. data/lib/rubocop/cop/lint/duplicate_methods.rb +46 -5
  24. data/lib/rubocop/cop/lint/literal_as_condition.rb +25 -11
  25. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -1
  26. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
  27. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +2 -2
  28. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -1
  29. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +7 -4
  30. data/lib/rubocop/cop/lint/return_in_void_context.rb +7 -2
  31. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  32. data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -1
  33. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  34. data/lib/rubocop/cop/lint/useless_assignment.rb +2 -0
  35. data/lib/rubocop/cop/lint/useless_rescue.rb +1 -1
  36. data/lib/rubocop/cop/lint/void.rb +2 -2
  37. data/lib/rubocop/cop/message_annotator.rb +7 -3
  38. data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
  39. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +1 -1
  40. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  41. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
  42. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +0 -1
  43. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +15 -14
  44. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -0
  45. data/lib/rubocop/cop/mixin/trailing_comma.rb +9 -5
  46. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
  47. data/lib/rubocop/cop/naming/method_name.rb +1 -1
  48. data/lib/rubocop/cop/style/arguments_forwarding.rb +8 -5
  49. data/lib/rubocop/cop/style/class_and_module_children.rb +19 -3
  50. data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
  51. data/lib/rubocop/cop/style/commented_keyword.rb +2 -2
  52. data/lib/rubocop/cop/style/comparable_between.rb +5 -2
  53. data/lib/rubocop/cop/style/conditional_assignment.rb +16 -4
  54. data/lib/rubocop/cop/style/data_inheritance.rb +7 -0
  55. data/lib/rubocop/cop/style/double_negation.rb +1 -1
  56. data/lib/rubocop/cop/style/empty_literal.rb +4 -0
  57. data/lib/rubocop/cop/style/eval_with_location.rb +3 -3
  58. data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -2
  59. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -2
  60. data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
  61. data/lib/rubocop/cop/style/hash_fetch_chain.rb +0 -1
  62. data/lib/rubocop/cop/style/hash_syntax.rb +3 -0
  63. data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
  64. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
  65. data/lib/rubocop/cop/style/identical_conditional_branches.rb +3 -3
  66. data/lib/rubocop/cop/style/if_unless_modifier.rb +20 -0
  67. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -1
  68. data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
  69. data/lib/rubocop/cop/style/lambda_call.rb +7 -2
  70. data/lib/rubocop/cop/style/map_into_array.rb +3 -1
  71. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +4 -1
  72. data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -0
  73. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  74. data/lib/rubocop/cop/style/redundant_condition.rb +13 -1
  75. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +1 -1
  76. data/lib/rubocop/cop/style/redundant_line_continuation.rb +0 -3
  77. data/lib/rubocop/cop/style/redundant_parentheses.rb +20 -3
  78. data/lib/rubocop/cop/style/return_nil.rb +2 -2
  79. data/lib/rubocop/cop/style/safe_navigation.rb +18 -3
  80. data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -2
  81. data/lib/rubocop/cop/style/string_concatenation.rb +1 -2
  82. data/lib/rubocop/cop/style/struct_inheritance.rb +8 -1
  83. data/lib/rubocop/cop/style/super_arguments.rb +1 -2
  84. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +7 -1
  85. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +1 -1
  86. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +1 -1
  87. data/lib/rubocop/cop/util.rb +1 -1
  88. data/lib/rubocop/cop/variable_force/variable.rb +1 -1
  89. data/lib/rubocop/cops_documentation_generator.rb +6 -2
  90. data/lib/rubocop/formatter/disabled_config_formatter.rb +2 -1
  91. data/lib/rubocop/formatter/html_formatter.rb +1 -1
  92. data/lib/rubocop/formatter/pacman_formatter.rb +1 -1
  93. data/lib/rubocop/magic_comment.rb +8 -0
  94. data/lib/rubocop/rspec/cop_helper.rb +2 -2
  95. data/lib/rubocop/rspec/shared_contexts.rb +1 -2
  96. data/lib/rubocop/server/cache.rb +13 -10
  97. data/lib/rubocop/target_finder.rb +6 -2
  98. data/lib/rubocop/version.rb +1 -1
  99. metadata +5 -5
@@ -4,6 +4,7 @@ module RuboCop
4
4
  module Cop
5
5
  module Style
6
6
  # Checks for inheritance from `Data.define` to avoid creating the anonymous parent class.
7
+ # Inheriting from `Data.define` adds a superfluous level in inheritance tree.
7
8
  #
8
9
  # @safety
9
10
  # Autocorrection is unsafe because it will change the inheritance
@@ -17,12 +18,18 @@ module RuboCop
17
18
  # end
18
19
  # end
19
20
  #
21
+ # Person.ancestors
22
+ # # => [Person, #<Class:0x000000010b4e14a0>, Data, (...)]
23
+ #
20
24
  # # good
21
25
  # Person = Data.define(:first_name, :last_name) do
22
26
  # def age
23
27
  # 42
24
28
  # end
25
29
  # end
30
+ #
31
+ # Person.ancestors
32
+ # # => [Person, Data, (...)]
26
33
  class DataInheritance < Base
27
34
  include RangeHelp
28
35
  extend AutoCorrector
@@ -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
  #
@@ -189,7 +189,7 @@ module RuboCop
189
189
  end
190
190
  end
191
191
 
192
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
192
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
193
193
  def check_expressions(node, expressions, insert_position)
194
194
  return if expressions.any?(&:nil?)
195
195
 
@@ -197,7 +197,7 @@ module RuboCop
197
197
 
198
198
  expressions.each do |expression|
199
199
  add_offense(expression) do |corrector|
200
- next if node.if_type? && node.ternary?
200
+ next if node.if_type? && (node.ternary? || node.then?)
201
201
 
202
202
  range = range_by_whole_lines(expression.source_range, include_final_newline: true)
203
203
  corrector.remove(range)
@@ -213,7 +213,7 @@ module RuboCop
213
213
  end
214
214
  end
215
215
  end
216
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
216
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
217
217
 
218
218
  def correct_assignment(corrector, node, expression, insert_position)
219
219
  if insert_position == :after_condition
@@ -23,6 +23,17 @@ module RuboCop
23
23
  # end
24
24
  # ----
25
25
  #
26
+ # The code `def method_name = body if condition` is considered a bad case by
27
+ # `Style/AmbiguousEndlessMethodDefinition` cop. So, to respect the user's intention to use
28
+ # an endless method definition in the `if` body, the following code is allowed:
29
+ #
30
+ # [source,ruby]
31
+ # ----
32
+ # if condition
33
+ # def method_name = body
34
+ # end
35
+ # ----
36
+ #
26
37
  # NOTE: It is allowed when `defined?` argument has an undefined value,
27
38
  # because using the modifier form causes the following incompatibility:
28
39
  #
@@ -77,10 +88,14 @@ module RuboCop
77
88
  [Style::SoleNestedConditional]
78
89
  end
79
90
 
91
+ # rubocop:disable Metrics/AbcSize
80
92
  def on_if(node)
93
+ return if endless_method?(node.body)
94
+
81
95
  condition = node.condition
82
96
  return if defined_nodes(condition).any? { |n| defined_argument_is_undefined?(node, n) } ||
83
97
  pattern_matching_nodes(condition).any?
98
+
84
99
  return unless (msg = message(node))
85
100
 
86
101
  add_offense(node.loc.keyword, message: format(msg, keyword: node.keyword)) do |corrector|
@@ -90,9 +105,14 @@ module RuboCop
90
105
  ignore_node(node)
91
106
  end
92
107
  end
108
+ # rubocop:enable Metrics/AbcSize
93
109
 
94
110
  private
95
111
 
112
+ def endless_method?(body)
113
+ body&.any_def_type? && body.endless?
114
+ end
115
+
96
116
  def defined_nodes(condition)
97
117
  if condition.defined_type?
98
118
  [condition]
@@ -10,7 +10,7 @@ module RuboCop
10
10
  # `nonzero?` method is allowed by default.
11
11
  # These are customizable with `AllowedMethods` option.
12
12
  #
13
- # This cop targets only `if`s with a single `elsif` or `else` branch. The following
13
+ # This cop targets only ``if``s with a single `elsif` or `else` branch. The following
14
14
  # code will be allowed, because it has two `elsif` branches:
15
15
  #
16
16
  # [source,ruby]
@@ -42,7 +42,7 @@ module RuboCop
42
42
  return if kwarg_nodes.empty?
43
43
 
44
44
  add_offense(node) do |corrector|
45
- defining_node = node.each_ancestor(:def, :defs, :block).first
45
+ defining_node = node.each_ancestor(:any_def, :block).first
46
46
  next if processed_source.contains_comment?(arguments_range(defining_node))
47
47
  next unless node.parent.find(&:kwoptarg_type?) == node
48
48
 
@@ -54,9 +54,14 @@ module RuboCop
54
54
 
55
55
  def prefer(node)
56
56
  receiver = node.receiver.source
57
- arguments = node.arguments.map(&:source).join(', ')
58
57
  dot = node.loc.dot.source
59
- method = explicit_style? ? "call(#{arguments})" : "(#{arguments})"
58
+ call_arguments = if node.arguments.empty?
59
+ ''
60
+ else
61
+ arguments = node.arguments.map(&:source).join(', ')
62
+ "(#{arguments})"
63
+ end
64
+ method = explicit_style? ? "call#{call_arguments}" : "(#{arguments})"
60
65
 
61
66
  "#{receiver}#{dot}#{method}"
62
67
  end
@@ -212,9 +212,11 @@ module RuboCop
212
212
  end
213
213
 
214
214
  def correct_push_node(corrector, push_node)
215
+ arg_node = push_node.first_argument
215
216
  range = push_node.source_range
216
- arg_range = push_node.first_argument.source_range
217
+ arg_range = arg_node.source_range
217
218
 
219
+ corrector.wrap(arg_node, '{ ', ' }') if arg_node.hash_type? && !arg_node.braces?
218
220
  corrector.remove(range_between(range.begin_pos, arg_range.begin_pos))
219
221
  corrector.remove(range_between(arg_range.end_pos, range.end_pos))
220
222
  end
@@ -49,7 +49,7 @@ module RuboCop
49
49
 
50
50
  def inside_endless_method_def?(node)
51
51
  # parens are required around arguments inside an endless method
52
- node.each_ancestor(:def, :defs).any?(&:endless?) && node.arguments.any?
52
+ node.each_ancestor(:any_def).any?(&:endless?) && node.arguments.any?
53
53
  end
54
54
 
55
55
  def require_parentheses_for_hash_value_omission?(node) # rubocop:disable Metrics/PerceivedComplexity
@@ -222,6 +222,9 @@ module RuboCop
222
222
  end
223
223
 
224
224
  def unary_literal?(node)
225
+ # NOTE: should be removed after releasing https://github.com/rubocop/rubocop-ast/pull/379
226
+ return node.source.match?(/\A[+-]/) if node.complex_type?
227
+
225
228
  (node.numeric_type? && node.sign?) ||
226
229
  (node.parent&.send_type? && node.parent.unary_operation?)
227
230
  end
@@ -23,11 +23,13 @@ module RuboCop
23
23
  'clause in a multiline statement.'
24
24
 
25
25
  def on_if(node)
26
+ return if part_of_ignored_node?(node)
26
27
  return unless node.modifier_form? && node.body.multiline?
27
28
 
28
29
  add_offense(node, message: format(MSG, keyword: node.keyword)) do |corrector|
29
30
  corrector.replace(node, to_normal_if(node))
30
31
  end
32
+ ignore_node(node)
31
33
  end
32
34
 
33
35
  private
@@ -45,7 +45,7 @@ module RuboCop
45
45
  # Report offense only if changing case doesn't change semantics,
46
46
  # i.e., if the string would become dynamic or has special characters.
47
47
  ast = parse(corrected(node.source)).ast
48
- return if node.children != ast.children
48
+ return if node.children != ast&.children
49
49
 
50
50
  add_offense(node.loc.begin) do |corrector|
51
51
  corrector.replace(node, corrected(node.source))
@@ -230,6 +230,14 @@ module RuboCop
230
230
  node.type?(:kwsplat, :forwarded_kwrestarg)
231
231
  end
232
232
 
233
+ def wrap_arguments_with_parens(condition)
234
+ method = condition.source_range.begin.join(condition.loc.selector.end)
235
+ arguments = condition.first_argument.source_range.begin.join(condition.source_range.end)
236
+
237
+ "#{method.source}(#{arguments.source})"
238
+ end
239
+
240
+ # rubocop:disable Metrics/AbcSize
233
241
  def if_source(if_branch, arithmetic_operation)
234
242
  if branches_have_method?(if_branch.parent) && if_branch.parenthesized?
235
243
  if_branch.source.delete_suffix(')')
@@ -238,11 +246,15 @@ module RuboCop
238
246
 
239
247
  "#{if_branch.receiver.source} #{if_branch.method_name} (#{argument_source}"
240
248
  elsif if_branch.true_type?
241
- if_branch.parent.condition.source
249
+ condition = if_branch.parent.condition
250
+ return condition.source if condition.arguments.empty?
251
+
252
+ wrap_arguments_with_parens(condition)
242
253
  else
243
254
  if_branch.source
244
255
  end
245
256
  end
257
+ # rubocop:enable Metrics/AbcSize
246
258
 
247
259
  def else_source(else_branch, arithmetic_operation) # rubocop:disable Metrics/AbcSize
248
260
  if arithmetic_operation
@@ -20,7 +20,7 @@ module RuboCop
20
20
 
21
21
  MSG = 'Remove the redundant current directory path.'
22
22
  RESTRICT_ON_SEND = %i[require_relative].freeze
23
- CURRENT_DIRECTORY_PREFIX = %r{./+}.freeze
23
+ CURRENT_DIRECTORY_PREFIX = %r{\./+}.freeze
24
24
  REDUNDANT_CURRENT_DIRECTORY_PREFIX = /\A#{CURRENT_DIRECTORY_PREFIX}/.freeze
25
25
 
26
26
  def on_send(node)
@@ -181,9 +181,7 @@ module RuboCop
181
181
  ARGUMENT_TYPES.include?(next_token.type)
182
182
  end
183
183
 
184
- # rubocop:disable Metrics/AbcSize
185
184
  def argument_newline?(node)
186
- node = node.to_a.last if node.assignment?
187
185
  return false if node.parenthesized_call?
188
186
 
189
187
  node = node.children.first if node.root? && node.begin_type?
@@ -196,7 +194,6 @@ module RuboCop
196
194
  node.loc.selector.line != node.first_argument.loc.line
197
195
  end
198
196
  end
199
- # rubocop:enable Metrics/AbcSize
200
197
 
201
198
  def find_node_for_line(last_line)
202
199
  processed_source.ast.each_node do |node|
@@ -78,7 +78,7 @@ module RuboCop
78
78
  ancestor = node.ancestors.first
79
79
  return false unless ancestor
80
80
 
81
- !ancestor.type?(:begin, :def, :any_block)
81
+ !ancestor.type?(:begin, :any_def, :any_block)
82
82
  end
83
83
 
84
84
  def allowed_ternary?(node)
@@ -98,7 +98,7 @@ module RuboCop
98
98
  return false unless node.type?(:send, :super, :yield)
99
99
 
100
100
  node.arguments.one? && !node.parenthesized? &&
101
- !node.arithmetic_operation? && node.first_argument.begin_type?
101
+ !node.operator_method? && node.first_argument.begin_type?
102
102
  end
103
103
 
104
104
  def multiline_control_flow_statements?(node)
@@ -134,7 +134,9 @@ module RuboCop
134
134
  node = begin_node.children.first
135
135
 
136
136
  if (message = find_offense_message(begin_node, node))
137
- begin_node = begin_node.parent if node.range_type?
137
+ if node.range_type? && !argument_of_parenthesized_method_call?(begin_node)
138
+ begin_node = begin_node.parent
139
+ end
138
140
 
139
141
  return offense(begin_node, message)
140
142
  end
@@ -155,6 +157,7 @@ module RuboCop
155
157
  return 'an expression'
156
158
  end
157
159
  return 'an interpolated expression' if interpolation?(begin_node)
160
+ return 'a method argument' if argument_of_parenthesized_method_call?(begin_node)
158
161
 
159
162
  return if begin_node.chained?
160
163
 
@@ -177,6 +180,20 @@ module RuboCop
177
180
  # @!method interpolation?(node)
178
181
  def_node_matcher :interpolation?, '[^begin ^^dstr]'
179
182
 
183
+ def argument_of_parenthesized_method_call?(begin_node)
184
+ node = begin_node.children.first
185
+ return false if node.basic_conditional? || method_call_parentheses_required?(node)
186
+ return false unless (parent = begin_node.parent)
187
+
188
+ parent.call_type? && parent.parenthesized? && parent.receiver != begin_node
189
+ end
190
+
191
+ def method_call_parentheses_required?(node)
192
+ return false unless node.call_type?
193
+
194
+ (node.receiver.nil? || node.loc.dot) && node.arguments.any?
195
+ end
196
+
180
197
  def allow_in_multiline_conditions?
181
198
  !!config.for_enabled_cop('Style/ParenthesesAroundCondition')['AllowInMultilineConditions']
182
199
  end
@@ -47,7 +47,7 @@ module RuboCop
47
47
 
48
48
  def on_return(node)
49
49
  # Check Lint/NonLocalExitFromIterator first before this cop
50
- node.each_ancestor(:block, :def, :defs) do |n|
50
+ node.each_ancestor(:block, :any_def) do |n|
51
51
  break if scoped_node?(n)
52
52
 
53
53
  send_node, args_node, _body_node = *n
@@ -83,7 +83,7 @@ module RuboCop
83
83
  end
84
84
 
85
85
  def scoped_node?(node)
86
- node.type?(:def, :defs) || node.lambda?
86
+ node.any_def_type? || node.lambda?
87
87
  end
88
88
 
89
89
  # @!method chained_send?(node)
@@ -174,12 +174,17 @@ module RuboCop
174
174
  range_with_surrounding_space(range: lhs.source_range, side: :right),
175
175
  range_with_surrounding_space(range: lhs_operator_range, side: :right),
176
176
  offense_range: range_between(lhs.source_range.begin_pos, rhs.source_range.end_pos)
177
- )
177
+ ) do |corrector|
178
+ corrector.replace(rhs_receiver, lhs_receiver.source)
179
+ end
180
+ ignore_node(node)
178
181
  end
179
182
  end
180
183
 
181
184
  def report_offense(node, rhs, rhs_receiver, *removal_ranges, offense_range: node)
182
185
  add_offense(offense_range) do |corrector|
186
+ next if ignored_node?(node)
187
+
183
188
  # If the RHS is an `or` we cannot safely autocorrect because in order to remove
184
189
  # the non-nil check we need to add safe-navs to all clauses where the receiver is used
185
190
  next if and_with_rhs_or?(node)
@@ -227,7 +232,7 @@ module RuboCop
227
232
  end
228
233
 
229
234
  def offending_node?(node, lhs_receiver, rhs, rhs_receiver) # rubocop:disable Metrics/CyclomaticComplexity
230
- return false if lhs_receiver != rhs_receiver || rhs_receiver.nil?
235
+ return false if !matching_nodes?(lhs_receiver, rhs_receiver) || rhs_receiver.nil?
231
236
  return false if use_var_only_in_unless_modifier?(node, lhs_receiver)
232
237
  return false if chain_length(rhs, rhs_receiver) > max_chain_length
233
238
  return false if unsafe_method_used?(rhs, rhs_receiver.parent)
@@ -306,11 +311,21 @@ module RuboCop
306
311
 
307
312
  receiver = method_chain.receiver
308
313
 
309
- return receiver if receiver == checked_variable
314
+ return receiver if matching_nodes?(receiver, checked_variable)
310
315
 
311
316
  find_matching_receiver_invocation(receiver, checked_variable)
312
317
  end
313
318
 
319
+ def matching_nodes?(left, right)
320
+ left == right || matching_call_nodes?(left, right)
321
+ end
322
+
323
+ def matching_call_nodes?(left, right)
324
+ return false unless left && right.respond_to?(:call_type?)
325
+
326
+ left.call_type? && right.call_type? && left.children == right.children
327
+ end
328
+
314
329
  def chain_length(method_chain, method)
315
330
  method.each_ancestor(:call).inject(0) do |total, ancestor|
316
331
  break total + 1 if ancestor == method_chain
@@ -185,8 +185,10 @@ module RuboCop
185
185
  end
186
186
 
187
187
  def add_parentheses?(node)
188
- node.assignment? || (node.operator_keyword? && !node.and_type?) ||
189
- (node.call_type? && node.arguments.any? && !node.parenthesized?)
188
+ return true if node.assignment? || (node.operator_keyword? && !node.and_type?)
189
+ return false unless node.call_type?
190
+
191
+ (node.arguments.any? && !node.parenthesized?) || node.prefix_not?
190
192
  end
191
193
 
192
194
  def parenthesized_method_arguments(node)
@@ -51,7 +51,6 @@ module RuboCop
51
51
  # Pathname.new('/') + 'test'
52
52
  #
53
53
  class StringConcatenation < Base
54
- include RangeHelp
55
54
  extend AutoCorrector
56
55
 
57
56
  MSG = 'Prefer string interpolation to string concatenation.'
@@ -147,7 +146,7 @@ module RuboCop
147
146
  when :str
148
147
  adjust_str(part)
149
148
  when :dstr
150
- part.children.all?(&:str_type?) ? adjust_str(part) : contents_range(part).source
149
+ part.children.all?(&:str_type?) ? adjust_str(part) : part.value
151
150
  else
152
151
  "\#{#{part.source}}"
153
152
  end
@@ -3,7 +3,8 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for inheritance from Struct.new.
6
+ # Checks for inheritance from `Struct.new`. Inheriting from `Struct.new`
7
+ # adds a superfluous level in inheritance tree.
7
8
  #
8
9
  # @safety
9
10
  # Autocorrection is unsafe because it will change the inheritance
@@ -17,12 +18,18 @@ module RuboCop
17
18
  # end
18
19
  # end
19
20
  #
21
+ # Person.ancestors
22
+ # # => [Person, #<Class:0x000000010b4e14a0>, Struct, (...)]
23
+ #
20
24
  # # good
21
25
  # Person = Struct.new(:first_name, :last_name) do
22
26
  # def age
23
27
  # 42
24
28
  # end
25
29
  # end
30
+ #
31
+ # Person.ancestors
32
+ # # => [Person, Struct, (...)]
26
33
  class StructInheritance < Base
27
34
  include RangeHelp
28
35
  extend AutoCorrector
@@ -68,7 +68,6 @@ module RuboCop
68
68
  class SuperArguments < Base
69
69
  extend AutoCorrector
70
70
 
71
- DEF_TYPES = %i[def defs].freeze
72
71
  ASSIGN_TYPES = %i[or_asgn lvasgn].freeze
73
72
 
74
73
  MSG = 'Call `super` without arguments and parentheses when the signature is identical.'
@@ -100,7 +99,7 @@ module RuboCop
100
99
  # `super` used within the block is always allowed.
101
100
  break if node.any_block_type? && !block_sends_to_super?(super_node, node)
102
101
 
103
- break node if DEF_TYPES.include?(node.type)
102
+ break node if node.any_def_type?
104
103
  end
105
104
  end
106
105
 
@@ -79,10 +79,16 @@ module RuboCop
79
79
  # # bad
80
80
  # method(1, 2,)
81
81
  #
82
+ # # bad
83
+ # object[1, 2,]
84
+ #
82
85
  # # good
83
86
  # method(1, 2)
84
87
  #
85
88
  # # good
89
+ # object[1, 2]
90
+ #
91
+ # # good
86
92
  # method(
87
93
  # 1,
88
94
  # 2
@@ -96,7 +102,7 @@ module RuboCop
96
102
  end
97
103
 
98
104
  def on_send(node)
99
- return unless node.arguments? && node.parenthesized?
105
+ return unless node.arguments? && (node.parenthesized? || node.method?(:[]))
100
106
 
101
107
  check(node, node.arguments, 'parameter of %<article>s method call',
102
108
  node.last_argument.source_range.end_pos,
@@ -11,7 +11,7 @@ module RuboCop
11
11
  # * `comma`: Requires a comma after the last item in an array, but only when each item is on
12
12
  # its own line.
13
13
  # * `diff_comma`: Requires a comma after the last item in an array, but only when that item is
14
- # followed by an immediate newline.
14
+ # followed by an immediate newline, even if there is an inline comment on the same line.
15
15
  # * `no_comma`: Does not require a comma after the last item in an array
16
16
  #
17
17
  # @example EnforcedStyleForMultiline: consistent_comma
@@ -11,7 +11,7 @@ module RuboCop
11
11
  # * `comma`: Requires a comma after the last item in a hash, but only when each item is on its
12
12
  # own line.
13
13
  # * `diff_comma`: Requires a comma after the last item in a hash, but only when that item is
14
- # followed by an immediate newline.
14
+ # followed by an immediate newline, even if there is an inline comment on the same line.
15
15
  # * `no_comma`: Does not require a comma after the last item in a hash
16
16
  #
17
17
  # @example EnforcedStyleForMultiline: consistent_comma