rubocop 1.67.0 → 1.69.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +81 -6
  4. data/lib/rubocop/cached_data.rb +12 -4
  5. data/lib/rubocop/cli/command/execute_runner.rb +1 -1
  6. data/lib/rubocop/cli/command/version.rb +2 -2
  7. data/lib/rubocop/cop/autocorrect_logic.rb +22 -2
  8. data/lib/rubocop/cop/base.rb +1 -1
  9. data/lib/rubocop/cop/bundler/gem_filename.rb +0 -1
  10. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +0 -1
  11. data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -12
  12. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +1 -1
  13. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +10 -0
  14. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -2
  15. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +0 -2
  16. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +2 -4
  17. data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +1 -1
  18. data/lib/rubocop/cop/internal_affairs/operator_keyword.rb +46 -0
  19. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +0 -2
  20. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  21. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -2
  22. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  23. data/lib/rubocop/cop/layout/begin_end_alignment.rb +0 -1
  24. data/lib/rubocop/cop/layout/block_alignment.rb +1 -2
  25. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
  26. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +2 -3
  27. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +3 -4
  28. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +3 -1
  29. data/lib/rubocop/cop/layout/indentation_width.rb +7 -7
  30. data/lib/rubocop/cop/layout/leading_comment_space.rb +44 -1
  31. data/lib/rubocop/cop/layout/line_length.rb +118 -4
  32. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -1
  33. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +1 -1
  34. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -3
  35. data/lib/rubocop/cop/layout/parameter_alignment.rb +3 -4
  36. data/lib/rubocop/cop/layout/redundant_line_break.rb +3 -35
  37. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +3 -2
  38. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
  39. data/lib/rubocop/cop/layout/space_around_operators.rb +16 -17
  40. data/lib/rubocop/cop/layout/space_before_brackets.rb +5 -5
  41. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +6 -0
  42. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +4 -0
  43. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +4 -0
  44. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +0 -1
  45. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +11 -12
  46. data/lib/rubocop/cop/lint/circular_argument_reference.rb +2 -0
  47. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
  48. data/lib/rubocop/cop/lint/duplicate_branch.rb +39 -4
  49. data/lib/rubocop/cop/lint/empty_ensure.rb +1 -1
  50. data/lib/rubocop/cop/lint/empty_file.rb +0 -2
  51. data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
  52. data/lib/rubocop/cop/lint/float_comparison.rb +14 -6
  53. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -3
  54. data/lib/rubocop/cop/lint/hash_new_with_keyword_arguments_as_default.rb +55 -0
  55. data/lib/rubocop/cop/lint/interpolation_check.rb +9 -0
  56. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +3 -0
  57. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
  58. data/lib/rubocop/cop/lint/mixed_case_range.rb +2 -5
  59. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
  60. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +2 -2
  61. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +8 -1
  62. data/lib/rubocop/cop/lint/number_conversion.rb +0 -1
  63. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -2
  64. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +106 -0
  65. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -2
  66. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -1
  67. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
  68. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +12 -7
  69. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -7
  70. data/lib/rubocop/cop/lint/regexp_as_condition.rb +0 -1
  71. data/lib/rubocop/cop/lint/rescue_type.rb +3 -7
  72. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +9 -0
  73. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +5 -1
  74. data/lib/rubocop/cop/lint/self_assignment.rb +8 -10
  75. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  76. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +88 -0
  77. data/lib/rubocop/cop/lint/unused_method_argument.rb +18 -2
  78. data/lib/rubocop/cop/lint/useless_defined.rb +55 -0
  79. data/lib/rubocop/cop/lint/useless_rescue.rb +1 -1
  80. data/lib/rubocop/cop/lint/useless_setter_call.rb +14 -25
  81. data/lib/rubocop/cop/lint/void.rb +3 -2
  82. data/lib/rubocop/cop/metrics/class_length.rb +7 -7
  83. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +4 -1
  84. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
  85. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -2
  86. data/lib/rubocop/cop/mixin/check_assignment.rb +4 -12
  87. data/lib/rubocop/cop/mixin/check_line_breakable.rb +10 -0
  88. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +49 -0
  89. data/lib/rubocop/cop/mixin/dig_help.rb +27 -0
  90. data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +24 -0
  91. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +3 -1
  92. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +5 -9
  93. data/lib/rubocop/cop/mixin/range_help.rb +0 -1
  94. data/lib/rubocop/cop/mixin/target_ruby_version.rb +17 -1
  95. data/lib/rubocop/cop/naming/block_forwarding.rb +1 -1
  96. data/lib/rubocop/cop/naming/constant_name.rb +6 -7
  97. data/lib/rubocop/cop/naming/file_name.rb +0 -2
  98. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +11 -12
  99. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +3 -11
  100. data/lib/rubocop/cop/naming/variable_name.rb +3 -4
  101. data/lib/rubocop/cop/naming/variable_number.rb +2 -3
  102. data/lib/rubocop/cop/offense.rb +2 -3
  103. data/lib/rubocop/cop/style/access_modifier_declarations.rb +53 -24
  104. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +79 -0
  105. data/lib/rubocop/cop/style/array_intersect.rb +5 -4
  106. data/lib/rubocop/cop/style/bitwise_predicate.rb +100 -0
  107. data/lib/rubocop/cop/style/block_delimiters.rb +18 -3
  108. data/lib/rubocop/cop/style/case_like_if.rb +8 -11
  109. data/lib/rubocop/cop/style/combinable_defined.rb +115 -0
  110. data/lib/rubocop/cop/style/commented_keyword.rb +11 -1
  111. data/lib/rubocop/cop/style/conditional_assignment.rb +19 -21
  112. data/lib/rubocop/cop/style/constant_visibility.rb +3 -12
  113. data/lib/rubocop/cop/style/dig_chain.rb +90 -0
  114. data/lib/rubocop/cop/style/endless_method.rb +1 -14
  115. data/lib/rubocop/cop/style/file_null.rb +73 -0
  116. data/lib/rubocop/cop/style/file_touch.rb +75 -0
  117. data/lib/rubocop/cop/style/for.rb +0 -1
  118. data/lib/rubocop/cop/style/global_vars.rb +1 -3
  119. data/lib/rubocop/cop/style/guard_clause.rb +15 -2
  120. data/lib/rubocop/cop/style/hash_conversion.rb +1 -2
  121. data/lib/rubocop/cop/style/if_inside_else.rb +0 -1
  122. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -2
  123. data/lib/rubocop/cop/style/if_with_semicolon.rb +14 -5
  124. data/lib/rubocop/cop/style/inverse_methods.rb +0 -1
  125. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +67 -0
  126. data/lib/rubocop/cop/style/lambda_call.rb +0 -1
  127. data/lib/rubocop/cop/style/map_into_array.rb +6 -1
  128. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +1 -1
  129. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +7 -11
  130. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +33 -3
  131. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  132. data/lib/rubocop/cop/style/multiple_comparison.rb +28 -39
  133. data/lib/rubocop/cop/style/mutable_constant.rb +4 -5
  134. data/lib/rubocop/cop/style/negated_if_else_condition.rb +6 -4
  135. data/lib/rubocop/cop/style/nested_ternary_operator.rb +5 -4
  136. data/lib/rubocop/cop/style/not.rb +1 -1
  137. data/lib/rubocop/cop/style/one_line_conditional.rb +25 -4
  138. data/lib/rubocop/cop/style/operator_method_call.rb +5 -6
  139. data/lib/rubocop/cop/style/or_assignment.rb +3 -6
  140. data/lib/rubocop/cop/style/parallel_assignment.rb +8 -13
  141. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  142. data/lib/rubocop/cop/style/redundant_assignment.rb +1 -1
  143. data/lib/rubocop/cop/style/redundant_condition.rb +36 -21
  144. data/lib/rubocop/cop/style/redundant_line_continuation.rb +21 -2
  145. data/lib/rubocop/cop/style/redundant_parentheses.rb +9 -11
  146. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +1 -0
  147. data/lib/rubocop/cop/style/redundant_return.rb +2 -2
  148. data/lib/rubocop/cop/style/redundant_self.rb +7 -14
  149. data/lib/rubocop/cop/style/redundant_self_assignment.rb +7 -5
  150. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +4 -4
  151. data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
  152. data/lib/rubocop/cop/style/rescue_modifier.rb +2 -3
  153. data/lib/rubocop/cop/style/safe_navigation.rb +13 -1
  154. data/lib/rubocop/cop/style/safe_navigation_chain_length.rb +52 -0
  155. data/lib/rubocop/cop/style/select_by_regexp.rb +1 -1
  156. data/lib/rubocop/cop/style/self_assignment.rb +11 -17
  157. data/lib/rubocop/cop/style/signal_exception.rb +2 -3
  158. data/lib/rubocop/cop/style/single_argument_dig.rb +9 -5
  159. data/lib/rubocop/cop/style/single_line_do_end_block.rb +13 -3
  160. data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -3
  161. data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
  162. data/lib/rubocop/cop/style/string_concatenation.rb +0 -1
  163. data/lib/rubocop/cop/style/swap_values.rb +4 -15
  164. data/lib/rubocop/cop/style/ternary_parentheses.rb +25 -4
  165. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +4 -4
  166. data/lib/rubocop/cop/style/variable_interpolation.rb +1 -2
  167. data/lib/rubocop/cop/variable_force/assignment.rb +18 -3
  168. data/lib/rubocop/cop/variable_force/branch.rb +1 -1
  169. data/lib/rubocop/cop/variable_force/variable.rb +5 -1
  170. data/lib/rubocop/cop/variable_force/variable_table.rb +2 -2
  171. data/lib/rubocop/cop/variable_force.rb +4 -10
  172. data/lib/rubocop/cops_documentation_generator.rb +20 -10
  173. data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
  174. data/lib/rubocop/runner.rb +16 -8
  175. data/lib/rubocop/target_ruby.rb +1 -1
  176. data/lib/rubocop/version.rb +27 -8
  177. data/lib/rubocop.rb +16 -0
  178. metadata +28 -12
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Looks for places where an subset of an Enumerable (array,
6
+ # Looks for places where a subset of an Enumerable (array,
7
7
  # range, set, etc.; see note below) is calculated based on a `Regexp`
8
8
  # match, and suggests `grep` or `grep_v` instead.
9
9
  #
@@ -37,33 +37,29 @@ module RuboCop
37
37
  private
38
38
 
39
39
  def check(node, var_type)
40
- var_name, rhs = *node
41
- return unless rhs
40
+ return unless (rhs = node.expression)
42
41
 
43
- if rhs.send_type?
44
- check_send_node(node, rhs, var_name, var_type)
42
+ if rhs.send_type? && rhs.arguments.one?
43
+ check_send_node(node, rhs, node.name, var_type)
45
44
  elsif rhs.operator_keyword?
46
- check_boolean_node(node, rhs, var_name, var_type)
45
+ check_boolean_node(node, rhs, node.name, var_type)
47
46
  end
48
47
  end
49
48
 
50
49
  def check_send_node(node, rhs, var_name, var_type)
51
- receiver, method_name, *_args = *rhs
52
- return unless OPS.include?(method_name)
50
+ return unless OPS.include?(rhs.method_name)
53
51
 
54
52
  target_node = s(var_type, var_name)
55
- return unless receiver == target_node
53
+ return unless rhs.receiver == target_node
56
54
 
57
- add_offense(node, message: format(MSG, method: method_name)) do |corrector|
55
+ add_offense(node, message: format(MSG, method: rhs.method_name)) do |corrector|
58
56
  autocorrect(corrector, node)
59
57
  end
60
58
  end
61
59
 
62
60
  def check_boolean_node(node, rhs, var_name, var_type)
63
- first_operand, _second_operand = *rhs
64
-
65
61
  target_node = s(var_type, var_name)
66
- return unless first_operand == target_node
62
+ return unless rhs.lhs == target_node
67
63
 
68
64
  operator = rhs.loc.operator.source
69
65
  add_offense(node, message: format(MSG, method: operator)) do |corrector|
@@ -72,7 +68,7 @@ module RuboCop
72
68
  end
73
69
 
74
70
  def autocorrect(corrector, node)
75
- _var_name, rhs = *node
71
+ rhs = node.expression
76
72
 
77
73
  if rhs.send_type?
78
74
  autocorrect_send_node(corrector, node, rhs)
@@ -82,13 +78,11 @@ module RuboCop
82
78
  end
83
79
 
84
80
  def autocorrect_send_node(corrector, node, rhs)
85
- _receiver, method_name, args = *rhs
86
- apply_autocorrect(corrector, node, rhs, method_name.to_s, args)
81
+ apply_autocorrect(corrector, node, rhs, rhs.method_name, rhs.first_argument)
87
82
  end
88
83
 
89
84
  def autocorrect_boolean_node(corrector, node, rhs)
90
- _first_operand, second_operand = *rhs
91
- apply_autocorrect(corrector, node, rhs, rhs.loc.operator.source, second_operand)
85
+ apply_autocorrect(corrector, node, rhs, rhs.loc.operator.source, rhs.rhs)
92
86
  end
93
87
 
94
88
  def apply_autocorrect(corrector, node, rhs, operator, new_rhs)
@@ -122,10 +122,9 @@ module RuboCop
122
122
  def on_rescue(node)
123
123
  return unless style == :semantic
124
124
 
125
- begin_node, *rescue_nodes, _else_node = *node
126
- check_scope(:raise, begin_node)
125
+ check_scope(:raise, node.body)
127
126
 
128
- rescue_nodes.each do |rescue_node|
127
+ node.resbody_branches.each do |rescue_node|
129
128
  check_scope(:fail, rescue_node)
130
129
  allow(:raise, rescue_node)
131
130
  end
@@ -33,22 +33,19 @@ module RuboCop
33
33
  #
34
34
  class SingleArgumentDig < Base
35
35
  extend AutoCorrector
36
+ include DigHelp
36
37
 
37
38
  MSG = 'Use `%<receiver>s[%<argument>s]` instead of `%<original>s`.'
38
39
  RESTRICT_ON_SEND = %i[dig].freeze
39
40
  IGNORED_ARGUMENT_TYPES = %i[block_pass forwarded_restarg forwarded_args hash].freeze
40
41
 
41
- # @!method single_argument_dig?(node)
42
- def_node_matcher :single_argument_dig?, <<~PATTERN
43
- (send _ :dig $!splat)
44
- PATTERN
45
-
46
42
  def on_send(node)
47
43
  return unless node.receiver
48
44
 
49
45
  expression = single_argument_dig?(node)
50
46
  return unless expression
51
47
  return if IGNORED_ARGUMENT_TYPES.include?(expression.type)
48
+ return if ignore_dig_chain?(node)
52
49
 
53
50
  receiver = node.receiver.source
54
51
  argument = expression.source
@@ -63,6 +60,13 @@ module RuboCop
63
60
 
64
61
  ignore_node(node)
65
62
  end
63
+
64
+ private
65
+
66
+ def ignore_dig_chain?(node)
67
+ dig_chain_enabled? &&
68
+ (dig?(node.receiver) || dig?(node.parent))
69
+ end
66
70
  end
67
71
  end
68
72
  end
@@ -6,8 +6,13 @@ module RuboCop
6
6
  # Checks for single-line `do`...`end` block.
7
7
  #
8
8
  # In practice a single line `do`...`end` is autocorrected when `EnforcedStyle: semantic`
9
- # in `Style/BlockDelimiters`. The autocorrection maintains the `do` ... `end` syntax to
10
- # preserve semantics and does not change it to `{`...`}` block.
9
+ # is configured for `Style/BlockDelimiters`. The autocorrection maintains the
10
+ # `do` ... `end` syntax to preserve semantics and does not change it to `{`...`}` block.
11
+ #
12
+ # NOTE: If `InspectBlocks` is set to `true` for `Layout/RedundantLineBreak`, blocks will
13
+ # be autocorrected to be on a single line if possible. This cop respects that configuration
14
+ # by not registering an offense if it would subsequently cause a
15
+ # `Layout/RedundantLineBreak` offense.
11
16
  #
12
17
  # @example
13
18
  #
@@ -27,12 +32,14 @@ module RuboCop
27
32
  #
28
33
  class SingleLineDoEndBlock < Base
29
34
  extend AutoCorrector
35
+ include CheckSingleLineSuitability
30
36
 
31
37
  MSG = 'Prefer multiline `do`...`end` block.'
32
38
 
33
39
  # rubocop:disable Metrics/AbcSize
34
40
  def on_block(node)
35
41
  return if !node.single_line? || node.braces?
42
+ return if single_line_blocks_preferred? && suitable_as_single_line?(node)
36
43
 
37
44
  add_offense(node) do |corrector|
38
45
  corrector.insert_after(do_line(node), "\n")
@@ -60,7 +67,10 @@ module RuboCop
60
67
  end
61
68
  end
62
69
 
63
- def x(corrector, node); end
70
+ def single_line_blocks_preferred?
71
+ redundant_line_break_config = @config.for_cop('Layout/RedundantLineBreak')
72
+ redundant_line_break_config['Enabled'] && redundant_line_break_config['InspectBlocks']
73
+ end
64
74
  end
65
75
  end
66
76
  end
@@ -214,7 +214,7 @@ module RuboCop
214
214
  end
215
215
 
216
216
  def insert_bang_for_and(corrector, node)
217
- lhs, rhs = *node
217
+ lhs, rhs = *node # rubocop:disable InternalAffairs/NodeDestructuring
218
218
 
219
219
  if lhs.and_type?
220
220
  insert_bang_for_and(corrector, lhs)
@@ -237,8 +237,7 @@ module RuboCop
237
237
  end
238
238
 
239
239
  def wrap_condition?(node)
240
- node.and_type? || node.or_type? ||
241
- (node.call_type? && node.arguments.any? && !node.parenthesized?)
240
+ node.operator_keyword? || (node.call_type? && node.arguments.any? && !node.parenthesized?)
242
241
  end
243
242
 
244
243
  def replace_condition(condition)
@@ -149,7 +149,7 @@ module RuboCop
149
149
  end
150
150
 
151
151
  def on_gvar(node)
152
- global_var, = *node
152
+ global_var = node.name
153
153
 
154
154
  return unless (preferred = preferred_names(global_var))
155
155
 
@@ -51,7 +51,6 @@ module RuboCop
51
51
  # Pathname.new('/') + 'test'
52
52
  #
53
53
  class StringConcatenation < Base
54
- include Util
55
54
  include RangeHelp
56
55
  extend AutoCorrector
57
56
 
@@ -79,26 +79,15 @@ module RuboCop
79
79
  end
80
80
 
81
81
  def lhs(node)
82
- case node.type
83
- when :casgn
84
- namespace, name, = *node
85
- if namespace
86
- "#{namespace.const_name}::#{name}"
87
- else
88
- name.to_s
89
- end
82
+ if node.casgn_type?
83
+ "#{'::' if node.absolute?}#{node.const_name}"
90
84
  else
91
- node.children[0].to_s
85
+ node.name.to_s
92
86
  end
93
87
  end
94
88
 
95
89
  def rhs(node)
96
- case node.type
97
- when :casgn
98
- node.children[2].source
99
- else
100
- node.children[1].source
101
- end
90
+ node.expression.source
102
91
  end
103
92
 
104
93
  def correction_range(tmp_assign, y_assign)
@@ -171,9 +171,7 @@ module RuboCop
171
171
  end
172
172
 
173
173
  def unsafe_autocorrect?(condition)
174
- condition.children.any? do |child|
175
- unparenthesized_method_call?(child) || below_ternary_precedence?(child)
176
- end
174
+ condition.children.any? { |child| below_ternary_precedence?(child) }
177
175
  end
178
176
 
179
177
  def unparenthesized_method_call?(child)
@@ -192,7 +190,7 @@ module RuboCop
192
190
  # @!method method_name(node)
193
191
  def_node_matcher :method_name, <<~PATTERN
194
192
  {($:defined? _ ...)
195
- (send {_ nil?} $_ _ ...)}
193
+ (call {_ nil?} $_ _ ...)}
196
194
  PATTERN
197
195
 
198
196
  def correct_parenthesized(corrector, condition)
@@ -203,16 +201,39 @@ module RuboCop
203
201
  # If we remove the parentheses, we need to add a space or we'll
204
202
  # generate invalid code.
205
203
  corrector.insert_after(condition.loc.end, ' ') unless whitespace_after?(condition)
204
+
205
+ if (send_node = condition.child_nodes.last) && node_args_need_parens?(send_node)
206
+ parenthesize_condition_arguments(corrector, send_node)
207
+ end
206
208
  end
207
209
 
208
210
  def correct_unparenthesized(corrector, condition)
209
211
  corrector.wrap(condition, '(', ')')
210
212
  end
211
213
 
214
+ def parenthesize_condition_arguments(corrector, send_node)
215
+ range_start = send_node.defined_type? ? send_node.loc.keyword : send_node.loc.selector
216
+ opening_range = range_start.end.join(send_node.first_argument.source_range.begin)
217
+
218
+ corrector.replace(opening_range, '(')
219
+ corrector.insert_after(send_node.last_argument, ')')
220
+ end
221
+
212
222
  def whitespace_after?(node)
213
223
  last_token = processed_source.last_token_of(node)
214
224
  last_token.space_after?
215
225
  end
226
+
227
+ def node_args_need_parens?(send_node)
228
+ return false unless node_with_args?(send_node)
229
+ return false if send_node.arguments.none? || send_node.parenthesized?
230
+
231
+ send_node.dot? || send_node.safe_navigation? || unparenthesized_method_call?(send_node)
232
+ end
233
+
234
+ def node_with_args?(node)
235
+ node.call_type? || node.defined_type?
236
+ end
216
237
  end
217
238
  end
218
239
  end
@@ -94,7 +94,7 @@ module RuboCop
94
94
  end
95
95
 
96
96
  def unneeded_ranges(node)
97
- node.masgn_type? ? (mlhs_node, = *node) : mlhs_node = node
97
+ mlhs_node = node.masgn_type? ? node.lhs : node
98
98
  variables = *mlhs_node
99
99
 
100
100
  main_offense = main_node_offense(node)
@@ -106,15 +106,15 @@ module RuboCop
106
106
  end
107
107
 
108
108
  def main_node_offense(node)
109
- node.masgn_type? ? (mlhs_node, right = *node) : mlhs_node = node
110
-
109
+ mlhs_node = node.masgn_type? ? node.lhs : node
111
110
  variables = *mlhs_node
111
+
112
112
  first_offense = find_first_offense(variables)
113
113
 
114
114
  return unless first_offense
115
115
 
116
116
  if unused_variables_only?(first_offense, variables)
117
- return unused_range(node.type, mlhs_node, right)
117
+ return unused_range(node.type, mlhs_node, node.rhs)
118
118
  end
119
119
 
120
120
  return range_for_parentheses(first_offense, mlhs_node) if Util.parentheses?(mlhs_node)
@@ -19,8 +19,7 @@ module RuboCop
19
19
  include Interpolation
20
20
  extend AutoCorrector
21
21
 
22
- MSG = 'Replace interpolated variable `%<variable>s` ' \
23
- 'with expression `#{%<variable>s}`.' # rubocop:disable Lint/InterpolationCheck
22
+ MSG = 'Replace interpolated variable `%<variable>s` with expression `#{%<variable>s}`.'
24
23
 
25
24
  def on_node_with_interpolations(node)
26
25
  var_nodes(node.children).each do |var_node|
@@ -9,9 +9,10 @@ module RuboCop
9
9
 
10
10
  MULTIPLE_LEFT_HAND_SIDE_TYPE = :mlhs
11
11
 
12
- attr_reader :node, :variable, :referenced, :references
12
+ attr_reader :node, :variable, :referenced, :references, :reassigned
13
13
 
14
14
  alias referenced? referenced
15
+ alias reassigned? reassigned
15
16
 
16
17
  def initialize(node, variable)
17
18
  unless VARIABLE_ASSIGNMENT_TYPES.include?(node.type)
@@ -24,6 +25,7 @@ module RuboCop
24
25
  @variable = variable
25
26
  @referenced = false
26
27
  @references = []
28
+ @reassigned = false
27
29
  end
28
30
 
29
31
  def name
@@ -39,8 +41,14 @@ module RuboCop
39
41
  @referenced = true
40
42
  end
41
43
 
44
+ def reassigned!
45
+ return if referenced?
46
+
47
+ @reassigned = true
48
+ end
49
+
42
50
  def used?
43
- @variable.captured_by_block? || @referenced
51
+ (!reassigned? && @variable.captured_by_block?) || @referenced
44
52
  end
45
53
 
46
54
  def regexp_named_capture?
@@ -102,6 +110,7 @@ module RuboCop
102
110
  end
103
111
 
104
112
  def multiple_assignment_node
113
+ return nil unless node.parent&.mlhs_type?
105
114
  return nil unless (grandparent_node = node.parent&.parent)
106
115
  if (node = find_multiple_assignment_node(grandparent_node))
107
116
  return node
@@ -119,7 +128,13 @@ module RuboCop
119
128
  end
120
129
 
121
130
  def for_assignment_node
122
- node.ancestors.find(&:for_type?)
131
+ return unless (parent_node = node.parent)
132
+ return parent_node if parent_node.for_type?
133
+
134
+ grandparent_node = parent_node.parent
135
+ return grandparent_node if parent_node.mlhs_type? && grandparent_node&.for_type?
136
+
137
+ nil
123
138
  end
124
139
 
125
140
  def find_multiple_assignment_node(grandparent_node)
@@ -74,7 +74,7 @@ module RuboCop
74
74
  def parent
75
75
  return @parent if instance_variable_defined?(:@parent)
76
76
 
77
- @branch = Branch.of(control_node, scope: scope)
77
+ @parent = Branch.of(control_node, scope: scope)
78
78
  end
79
79
 
80
80
  def each_ancestor(include_self: false, &block)
@@ -29,7 +29,11 @@ module RuboCop
29
29
  end
30
30
 
31
31
  def assign(node)
32
- @assignments << Assignment.new(node, self)
32
+ assignment = Assignment.new(node, self)
33
+
34
+ @assignments.last&.reassigned! unless captured_by_block?
35
+
36
+ @assignments << assignment
33
37
  end
34
38
 
35
39
  def referenced?
@@ -61,8 +61,8 @@ module RuboCop
61
61
  "at #{node.source_range}, #{node.inspect}"
62
62
  end
63
63
 
64
- variable.assign(node)
65
64
  mark_variable_as_captured_by_block_if_so(variable)
65
+ variable.assign(node)
66
66
  end
67
67
 
68
68
  def reference_variable(name, node)
@@ -87,8 +87,8 @@ module RuboCop
87
87
  # So just skip.
88
88
  return unless variable
89
89
 
90
- variable.reference!(node)
91
90
  mark_variable_as_captured_by_block_if_so(variable)
91
+ variable.reference!(node)
92
92
  end
93
93
 
94
94
  def find_variable(name)
@@ -194,15 +194,10 @@ module RuboCop
194
194
  end
195
195
 
196
196
  def process_variable_operator_assignment(node)
197
- if LOGICAL_OPERATOR_ASSIGNMENT_TYPES.include?(node.type)
198
- asgn_node, rhs_node = *node
199
- else
200
- asgn_node, _operator, rhs_node = *node
201
- end
202
-
197
+ asgn_node = node.lhs
203
198
  return unless asgn_node.lvasgn_type?
204
199
 
205
- name = asgn_node.children.first
200
+ name = asgn_node.name
206
201
 
207
202
  variable_table.declare_variable(name, asgn_node) unless variable_table.variable_exist?(name)
208
203
 
@@ -222,7 +217,7 @@ module RuboCop
222
217
  # before processing rhs nodes.
223
218
 
224
219
  variable_table.reference_variable(name, node)
225
- process_node(rhs_node)
220
+ process_node(node.rhs)
226
221
  variable_table.assign_to_variable(name, asgn_node)
227
222
 
228
223
  skip_children!
@@ -355,8 +350,7 @@ module RuboCop
355
350
  when :lvasgn
356
351
  AssignmentReference.new(node)
357
352
  when *OPERATOR_ASSIGNMENT_TYPES
358
- asgn_node = node.children.first
359
- VariableReference.new(asgn_node.children.first) if asgn_node.lvasgn_type?
353
+ VariableReference.new(node.lhs.name) if node.lhs.lvasgn_type?
360
354
  end
361
355
  end
362
356
 
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'fileutils'
4
+ require 'yard'
4
5
 
5
6
  # Class for generating documentation of all cops departments
6
7
  # @api private
@@ -35,13 +36,14 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
35
36
  # This will insert the string returned from the lambda _after_ the section from RuboCop itself.
36
37
  # See `CopsDocumentationGenerator::STRUCTURE` for available sections.
37
38
  #
38
- def initialize(departments: [], extra_info: {})
39
+ def initialize(departments: [], extra_info: {}, base_dir: Dir.pwd)
39
40
  @departments = departments.map(&:to_sym).sort!
40
41
  @extra_info = extra_info
41
42
  @cops = RuboCop::Cop::Registry.global
42
43
  @config = RuboCop::ConfigLoader.default_configuration
43
- @docs_path = "#{Dir.pwd}/docs/modules/ROOT/pages/"
44
- FileUtils.mkdir_p(@docs_path)
44
+ @base_dir = base_dir
45
+ @docs_path = "#{base_dir}/docs/modules/ROOT"
46
+ FileUtils.mkdir_p("#{@docs_path}/pages")
45
47
  end
46
48
 
47
49
  def call
@@ -112,7 +114,15 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
112
114
  def required_ruby_version(cop)
113
115
  return '' unless cop.respond_to?(:required_minimum_ruby_version)
114
116
 
115
- "NOTE: Required Ruby version: #{cop.required_minimum_ruby_version}\n\n"
117
+ if cop.required_minimum_ruby_version
118
+ requirement = cop.required_minimum_ruby_version
119
+ elsif cop.required_maximum_ruby_version
120
+ requirement = "<= #{cop.required_maximum_ruby_version}"
121
+ else
122
+ return ''
123
+ end
124
+
125
+ "NOTE: Requires Ruby version #{requirement}\n\n"
116
126
  end
117
127
 
118
128
  # rubocop:disable Metrics/MethodLength
@@ -157,8 +167,8 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
157
167
  end
158
168
 
159
169
  def example_header(title, cop)
160
- content = "[##{to_anchor(title)}-#{to_anchor(cop.cop_name)}]\n"
161
- content << +"==== #{title}\n"
170
+ content = +"[##{to_anchor(title)}-#{to_anchor(cop.cop_name)}]\n"
171
+ content << "==== #{title}\n"
162
172
  content << "\n"
163
173
  content
164
174
  end
@@ -246,7 +256,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
246
256
  else
247
257
  wrap_backtick(val.nil? ? '<none>' : val)
248
258
  end
249
- value.gsub("#{Dir.pwd}/", '').rstrip
259
+ value.gsub("#{@base_dir}/", '').rstrip
250
260
  end
251
261
 
252
262
  def wrap_backtick(value)
@@ -275,7 +285,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
275
285
  return '' unless department == :Layout
276
286
 
277
287
  filename = "#{department_to_basename(department)}_footer.adoc"
278
- file = "#{Dir.pwd}/docs/modules/ROOT/partials/#{filename}"
288
+ file = "#{docs_path}/partials/#{filename}"
279
289
  return '' unless File.exist?(file)
280
290
 
281
291
  "\ninclude::../partials/#{filename}[]\n"
@@ -295,7 +305,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
295
305
  HEADER
296
306
  selected_cops.each { |cop| content << print_cop_with_doc(cop) }
297
307
  content << footer_for_department(department)
298
- file_name = "#{docs_path}/#{department_to_basename(department)}.adoc"
308
+ file_name = "#{docs_path}/pages/#{department_to_basename(department)}.adoc"
299
309
  File.open(file_name, 'w') do |file|
300
310
  puts "* generated #{file_name}"
301
311
  file.write("#{content.strip}\n")
@@ -344,7 +354,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
344
354
  end
345
355
 
346
356
  def print_table_of_contents
347
- path = "#{docs_path}/cops.adoc"
357
+ path = "#{docs_path}/pages/cops.adoc"
348
358
 
349
359
  File.write(path, table_contents) and return unless File.exist?(path)
350
360
 
@@ -10,7 +10,7 @@ module RuboCop
10
10
  HEADING = <<~COMMENTS
11
11
  # This configuration was generated by
12
12
  # `%<command>s`
13
- # %<timestamp>susing RuboCop version #{Version.version}.
13
+ # %<timestamp>susing RuboCop version #{Version::STRING}.
14
14
  # The point is for the user to remove these configuration records
15
15
  # one by one as the offenses are removed from the code base.
16
16
  # Note that changes in the inspected code, or installation of new
@@ -139,7 +139,7 @@ module RuboCop
139
139
  offenses = process_file(file)
140
140
  yield file
141
141
 
142
- if offenses.any? { |o| considered_failure?(o) }
142
+ if offenses.any? { |o| considered_failure?(o) && offense_displayed?(o) }
143
143
  break false if @options[:fail_fast]
144
144
 
145
145
  next false
@@ -363,8 +363,12 @@ module RuboCop
363
363
  result = ruby_extractor.call(processed_source)
364
364
  break result if result
365
365
  rescue StandardError
366
- raise Error, "Ruby extractor #{ruby_extractor.source_location[0]} failed to process " \
367
- "#{processed_source.path}."
366
+ location = if ruby_extractor.is_a?(Proc)
367
+ ruby_extractor.source_location
368
+ else
369
+ ruby_extractor.method(:call).source_location
370
+ end
371
+ raise Error, "Ruby extractor #{location[0]} failed to process #{processed_source.path}."
368
372
  end
369
373
  end
370
374
 
@@ -436,18 +440,22 @@ module RuboCop
436
440
  !offense.corrected? && offense.severity >= minimum_severity_to_fail
437
441
  end
438
442
 
439
- def offenses_to_report(offenses)
443
+ def offense_displayed?(offense)
440
444
  if @options[:display_only_fail_level_offenses]
441
- offenses.select { |o| considered_failure?(o) }
445
+ considered_failure?(offense)
442
446
  elsif @options[:display_only_safe_correctable]
443
- offenses.select { |o| supports_safe_autocorrect?(o) }
447
+ supports_safe_autocorrect?(offense)
444
448
  elsif @options[:display_only_correctable]
445
- offenses.select(&:correctable?)
449
+ offense.correctable?
446
450
  else
447
- offenses
451
+ true
448
452
  end
449
453
  end
450
454
 
455
+ def offenses_to_report(offenses)
456
+ offenses.select { |o| offense_displayed?(o) }
457
+ end
458
+
451
459
  def supports_safe_autocorrect?(offense)
452
460
  cop_class = Cop::Registry.global.find_by_cop_name(offense.cop_name)
453
461
  default_cfg = default_config(offense.cop_name)
@@ -273,7 +273,7 @@ module RuboCop
273
273
 
274
274
  def rubocop_version_with_support
275
275
  if supported?
276
- RuboCop::Version.version
276
+ RuboCop::Version::STRING
277
277
  else
278
278
  OBSOLETE_RUBIES[version]
279
279
  end