rubocop 1.32.0 → 1.37.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 (189) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/config/default.yml +104 -16
  4. data/config/obsoletion.yml +23 -1
  5. data/lib/rubocop/arguments_env.rb +17 -0
  6. data/lib/rubocop/arguments_file.rb +17 -0
  7. data/lib/rubocop/cache_config.rb +29 -0
  8. data/lib/rubocop/cli/command/{auto_genenerate_config.rb → auto_generate_config.rb} +2 -2
  9. data/lib/rubocop/cli/command/execute_runner.rb +7 -7
  10. data/lib/rubocop/cli/command/init_dotfile.rb +1 -1
  11. data/lib/rubocop/cli/command/suggest_extensions.rb +53 -15
  12. data/lib/rubocop/config.rb +1 -1
  13. data/lib/rubocop/config_finder.rb +68 -0
  14. data/lib/rubocop/config_loader.rb +12 -40
  15. data/lib/rubocop/config_loader_resolver.rb +1 -5
  16. data/lib/rubocop/config_obsoletion/changed_parameter.rb +5 -0
  17. data/lib/rubocop/config_obsoletion/parameter_rule.rb +4 -0
  18. data/lib/rubocop/config_obsoletion.rb +7 -2
  19. data/lib/rubocop/cop/cop.rb +1 -1
  20. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +58 -0
  21. data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
  22. data/lib/rubocop/cop/generator/require_file_injector.rb +2 -2
  23. data/lib/rubocop/cop/generator.rb +1 -2
  24. data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +69 -0
  25. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +62 -0
  26. data/lib/rubocop/cop/internal_affairs.rb +2 -0
  27. data/lib/rubocop/cop/layout/block_alignment.rb +16 -12
  28. data/lib/rubocop/cop/layout/block_end_newline.rb +35 -5
  29. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +5 -2
  30. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +2 -0
  31. data/lib/rubocop/cop/layout/end_of_line.rb +4 -4
  32. data/lib/rubocop/cop/layout/first_argument_indentation.rb +7 -1
  33. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -2
  34. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -2
  35. data/lib/rubocop/cop/layout/indentation_width.rb +6 -2
  36. data/lib/rubocop/cop/layout/line_length.rb +4 -1
  37. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
  38. data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
  39. data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -1
  40. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
  41. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
  42. data/lib/rubocop/cop/layout/space_before_block_braces.rb +2 -0
  43. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +13 -9
  44. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +25 -9
  45. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +28 -3
  46. data/lib/rubocop/cop/legacy/corrections_proxy.rb +1 -1
  47. data/lib/rubocop/cop/legacy/corrector.rb +1 -1
  48. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +21 -8
  49. data/lib/rubocop/cop/lint/debugger.rb +26 -16
  50. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +4 -4
  51. data/lib/rubocop/cop/lint/duplicate_magic_comment.rb +73 -0
  52. data/lib/rubocop/cop/lint/duplicate_methods.rb +11 -1
  53. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +25 -6
  54. data/lib/rubocop/cop/lint/duplicate_require.rb +1 -1
  55. data/lib/rubocop/cop/lint/empty_block.rb +1 -1
  56. data/lib/rubocop/cop/lint/empty_class.rb +3 -1
  57. data/lib/rubocop/cop/lint/empty_conditional_body.rb +107 -1
  58. data/lib/rubocop/cop/lint/erb_new_arguments.rb +9 -9
  59. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +4 -0
  60. data/lib/rubocop/cop/lint/nested_method_definition.rb +50 -1
  61. data/lib/rubocop/cop/lint/next_without_accumulator.rb +25 -6
  62. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +6 -6
  63. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +12 -0
  64. data/lib/rubocop/cop/lint/number_conversion.rb +24 -8
  65. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +4 -5
  66. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -1
  67. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +12 -1
  68. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +7 -0
  69. data/lib/rubocop/cop/lint/redundant_require_statement.rb +29 -9
  70. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +9 -3
  71. data/lib/rubocop/cop/lint/redundant_with_index.rb +13 -10
  72. data/lib/rubocop/cop/lint/redundant_with_object.rb +12 -11
  73. data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
  74. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -2
  75. data/lib/rubocop/cop/lint/shadowed_exception.rb +15 -10
  76. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +27 -3
  77. data/lib/rubocop/cop/lint/unreachable_loop.rb +9 -3
  78. data/lib/rubocop/cop/lint/unused_method_argument.rb +4 -0
  79. data/lib/rubocop/cop/lint/useless_access_modifier.rb +8 -6
  80. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +1 -1
  81. data/lib/rubocop/cop/lint/void.rb +2 -0
  82. data/lib/rubocop/cop/metrics/abc_size.rb +3 -1
  83. data/lib/rubocop/cop/metrics/block_length.rb +6 -7
  84. data/lib/rubocop/cop/metrics/method_length.rb +8 -8
  85. data/lib/rubocop/cop/mixin/allowed_methods.rb +20 -1
  86. data/lib/rubocop/cop/mixin/allowed_pattern.rb +17 -1
  87. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  88. data/lib/rubocop/cop/mixin/comments_help.rb +17 -1
  89. data/lib/rubocop/cop/mixin/enforce_superclass.rb +2 -1
  90. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -0
  91. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +82 -4
  92. data/lib/rubocop/cop/mixin/hash_transform_method.rb +10 -6
  93. data/lib/rubocop/cop/mixin/method_complexity.rb +8 -13
  94. data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +1 -1
  95. data/lib/rubocop/cop/mixin/range_help.rb +4 -5
  96. data/lib/rubocop/cop/mixin/rescue_node.rb +3 -1
  97. data/lib/rubocop/cop/mixin/surrounding_space.rb +6 -5
  98. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  99. data/lib/rubocop/cop/naming/constant_name.rb +2 -2
  100. data/lib/rubocop/cop/naming/inclusive_language.rb +1 -1
  101. data/lib/rubocop/cop/naming/predicate_name.rb +24 -3
  102. data/lib/rubocop/cop/style/access_modifier_declarations.rb +97 -1
  103. data/lib/rubocop/cop/style/accessor_grouping.rb +7 -3
  104. data/lib/rubocop/cop/style/arguments_forwarding.rb +2 -2
  105. data/lib/rubocop/cop/style/block_delimiters.rb +26 -7
  106. data/lib/rubocop/cop/style/case_equality.rb +40 -10
  107. data/lib/rubocop/cop/style/class_and_module_children.rb +4 -4
  108. data/lib/rubocop/cop/style/class_equality_comparison.rb +32 -7
  109. data/lib/rubocop/cop/style/class_methods_definitions.rb +2 -1
  110. data/lib/rubocop/cop/style/collection_compact.rb +6 -1
  111. data/lib/rubocop/cop/style/collection_methods.rb +2 -0
  112. data/lib/rubocop/cop/style/combinable_loops.rb +3 -1
  113. data/lib/rubocop/cop/style/double_negation.rb +2 -0
  114. data/lib/rubocop/cop/style/each_for_simple_loop.rb +41 -6
  115. data/lib/rubocop/cop/style/each_with_object.rb +39 -8
  116. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  117. data/lib/rubocop/cop/style/empty_heredoc.rb +15 -1
  118. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  119. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  120. data/lib/rubocop/cop/style/endless_method.rb +1 -1
  121. data/lib/rubocop/cop/style/explicit_block_argument.rb +4 -0
  122. data/lib/rubocop/cop/style/for.rb +2 -0
  123. data/lib/rubocop/cop/style/format_string_token.rb +21 -8
  124. data/lib/rubocop/cop/style/guard_clause.rb +27 -16
  125. data/lib/rubocop/cop/style/hash_each_methods.rb +3 -1
  126. data/lib/rubocop/cop/style/hash_except.rb +0 -4
  127. data/lib/rubocop/cop/style/hash_syntax.rb +17 -0
  128. data/lib/rubocop/cop/style/if_unless_modifier.rb +1 -1
  129. data/lib/rubocop/cop/style/inverse_methods.rb +8 -6
  130. data/lib/rubocop/cop/style/magic_comment_format.rb +307 -0
  131. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +15 -4
  132. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +5 -1
  133. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -7
  134. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +11 -6
  135. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +4 -1
  136. data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -1
  137. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -1
  138. data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -1
  139. data/lib/rubocop/cop/style/next.rb +3 -5
  140. data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
  141. data/lib/rubocop/cop/style/numeric_literals.rb +16 -1
  142. data/lib/rubocop/cop/style/numeric_predicate.rb +28 -8
  143. data/lib/rubocop/cop/style/object_then.rb +2 -0
  144. data/lib/rubocop/cop/style/operator_method_call.rb +39 -0
  145. data/lib/rubocop/cop/style/perl_backrefs.rb +22 -1
  146. data/lib/rubocop/cop/style/proc.rb +4 -1
  147. data/lib/rubocop/cop/style/redundant_begin.rb +3 -0
  148. data/lib/rubocop/cop/style/redundant_condition.rb +24 -6
  149. data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
  150. data/lib/rubocop/cop/style/redundant_initialize.rb +3 -1
  151. data/lib/rubocop/cop/style/redundant_parentheses.rb +19 -22
  152. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +8 -1
  153. data/lib/rubocop/cop/style/redundant_self.rb +2 -0
  154. data/lib/rubocop/cop/style/redundant_sort.rb +21 -6
  155. data/lib/rubocop/cop/style/redundant_sort_by.rb +24 -8
  156. data/lib/rubocop/cop/style/redundant_string_escape.rb +173 -0
  157. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
  158. data/lib/rubocop/cop/style/safe_navigation.rb +4 -2
  159. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  160. data/lib/rubocop/cop/style/sole_nested_conditional.rb +14 -5
  161. data/lib/rubocop/cop/style/static_class.rb +32 -1
  162. data/lib/rubocop/cop/style/symbol_array.rb +3 -1
  163. data/lib/rubocop/cop/style/symbol_proc.rb +38 -12
  164. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -13
  165. data/lib/rubocop/cop/style/top_level_method_definition.rb +3 -1
  166. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
  167. data/lib/rubocop/cop/style/word_array.rb +3 -1
  168. data/lib/rubocop/cop/util.rb +1 -1
  169. data/lib/rubocop/ext/range.rb +15 -0
  170. data/lib/rubocop/feature_loader.rb +94 -0
  171. data/lib/rubocop/formatter/clang_style_formatter.rb +1 -1
  172. data/lib/rubocop/formatter/disabled_config_formatter.rb +9 -3
  173. data/lib/rubocop/formatter/html_formatter.rb +3 -3
  174. data/lib/rubocop/formatter/markdown_formatter.rb +1 -1
  175. data/lib/rubocop/formatter/tap_formatter.rb +1 -1
  176. data/lib/rubocop/options.rb +13 -13
  177. data/lib/rubocop/result_cache.rb +22 -20
  178. data/lib/rubocop/rspec/shared_contexts.rb +13 -1
  179. data/lib/rubocop/runner.rb +4 -0
  180. data/lib/rubocop/server/cache.rb +41 -2
  181. data/lib/rubocop/server/cli.rb +26 -2
  182. data/lib/rubocop/server/client_command/exec.rb +5 -0
  183. data/lib/rubocop/server/core.rb +2 -1
  184. data/lib/rubocop/server/socket_reader.rb +5 -1
  185. data/lib/rubocop/server.rb +1 -1
  186. data/lib/rubocop/version.rb +8 -2
  187. data/lib/rubocop.rb +8 -3
  188. metadata +20 -9
  189. data/lib/rubocop/cop/mixin/ignored_methods.rb +0 -52
@@ -31,19 +31,8 @@ module RuboCop
31
31
  extend AutoCorrector
32
32
 
33
33
  MSG_EACH_WITH_OBJECT = 'Use `each` instead of `each_with_object`.'
34
-
35
34
  MSG_WITH_OBJECT = 'Remove redundant `with_object`.'
36
35
 
37
- # @!method redundant_with_object?(node)
38
- def_node_matcher :redundant_with_object?, <<~PATTERN
39
- (block
40
- $(send _ {:each_with_object :with_object}
41
- _)
42
- (args
43
- (arg _))
44
- ...)
45
- PATTERN
46
-
47
36
  def on_block(node)
48
37
  return unless (send = redundant_with_object?(node))
49
38
 
@@ -59,8 +48,20 @@ module RuboCop
59
48
  end
60
49
  end
61
50
 
51
+ alias on_numblock on_block
52
+
62
53
  private
63
54
 
55
+ # @!method redundant_with_object?(node)
56
+ def_node_matcher :redundant_with_object?, <<~PATTERN
57
+ {
58
+ (block
59
+ $(send _ {:each_with_object :with_object} _) (args (arg _)) ...)
60
+ (numblock
61
+ $(send _ {:each_with_object :with_object} _) 1 ...)
62
+ }
63
+ PATTERN
64
+
64
65
  def message(node)
65
66
  if node.method?(:each_with_object)
66
67
  MSG_EACH_WITH_OBJECT
@@ -46,7 +46,7 @@ module RuboCop
46
46
  private
47
47
 
48
48
  def check_ternary(ternary, node)
49
- return unless ternary.condition.operator_keyword?
49
+ return if node.method?(:[]) || !ternary.condition.operator_keyword?
50
50
 
51
51
  range = range_between(node.source_range.begin_pos, ternary.condition.source_range.end_pos)
52
52
 
@@ -31,6 +31,7 @@ module RuboCop
31
31
  minimum_target_ruby_version 2.3
32
32
 
33
33
  MSG = 'Do not chain ordinary method call after safe navigation operator.'
34
+ PLUS_MINUS_METHODS = %i[+@ -@].freeze
34
35
 
35
36
  # @!method bad_method?(node)
36
37
  def_node_matcher :bad_method?, <<~PATTERN
@@ -42,7 +43,7 @@ module RuboCop
42
43
 
43
44
  def on_send(node)
44
45
  bad_method?(node) do |safe_nav, method|
45
- return if nil_methods.include?(method)
46
+ return if nil_methods.include?(method) || PLUS_MINUS_METHODS.include?(node.method_name)
46
47
 
47
48
  method_chain = method_chain(node)
48
49
  location =
@@ -71,7 +72,7 @@ module RuboCop
71
72
  else
72
73
  offense_range.source.dup
73
74
  end
74
- source.prepend('.') unless send_node.dot?
75
+ source.prepend('.') unless source.start_with?('.')
75
76
  source.prepend('&')
76
77
  end
77
78
 
@@ -7,6 +7,14 @@ module RuboCop
7
7
  # less specific exception being rescued before a more specific
8
8
  # exception is rescued.
9
9
  #
10
+ # An exception is considered shadowed if it is rescued after its
11
+ # ancestor is, or if it and its ancestor are both rescued in the
12
+ # same `rescue` statement. In both cases, the more specific rescue is
13
+ # unnecessary because it is covered by rescuing the less specific
14
+ # exception. (ie. `rescue Exception, StandardError` has the same behavior
15
+ # whether `StandardError` is included or not, because all ``StandardError``s
16
+ # are rescued by `rescue Exception`).
17
+ #
10
18
  # @example
11
19
  #
12
20
  # # bad
@@ -19,6 +27,13 @@ module RuboCop
19
27
  # handle_standard_error
20
28
  # end
21
29
  #
30
+ # # bad
31
+ # begin
32
+ # something
33
+ # rescue Exception, StandardError
34
+ # handle_error
35
+ # end
36
+ #
22
37
  # # good
23
38
  #
24
39
  # begin
@@ -140,16 +155,6 @@ module RuboCop
140
155
  end
141
156
  end
142
157
 
143
- # @param [RuboCop::AST::Node] rescue_group is a node of array_type
144
- def rescued_exceptions(rescue_group)
145
- klasses = *rescue_group
146
- klasses.map do |klass|
147
- next unless klass.const_type?
148
-
149
- klass.source
150
- end.compact
151
- end
152
-
153
158
  def find_shadowing_rescue(rescues)
154
159
  rescued_groups = rescued_groups_for(rescues)
155
160
  rescued_groups.zip(rescues).each do |group, res|
@@ -12,9 +12,12 @@ module RuboCop
12
12
  # because `Ractor` should not access outer variables.
13
13
  # eg. following style is encouraged:
14
14
  #
15
+ # [source,ruby]
16
+ # ----
15
17
  # worker_id, pipe = env
16
18
  # Ractor.new(worker_id, pipe) do |worker_id, pipe|
17
19
  # end
20
+ # ----
18
21
  #
19
22
  # @example
20
23
  #
@@ -64,12 +67,33 @@ module RuboCop
64
67
  end
65
68
 
66
69
  def same_conditions_node_different_branch?(variable, outer_local_variable)
67
- variable_node = variable.scope.node.parent
70
+ variable_node = variable_node(variable)
68
71
  return false unless variable_node.conditional?
69
72
 
70
- outer_local_variable_node = outer_local_variable.scope.node
73
+ outer_local_variable_node =
74
+ find_conditional_node_from_ascendant(outer_local_variable.declaration_node)
75
+ return true unless outer_local_variable_node
71
76
 
72
- outer_local_variable_node.conditional? && variable_node == outer_local_variable_node
77
+ outer_local_variable_node.conditional? &&
78
+ (variable_node == outer_local_variable_node ||
79
+ variable_node == outer_local_variable_node.else_branch)
80
+ end
81
+
82
+ def variable_node(variable)
83
+ parent_node = variable.scope.node.parent
84
+
85
+ if parent_node.when_type?
86
+ parent_node.parent
87
+ else
88
+ parent_node
89
+ end
90
+ end
91
+
92
+ def find_conditional_node_from_ascendant(node)
93
+ return unless (parent = node.parent)
94
+ return parent if parent.conditional?
95
+
96
+ find_conditional_node_from_ascendant(parent)
73
97
  end
74
98
  end
75
99
  end
@@ -9,7 +9,7 @@ module RuboCop
9
9
  # In rare cases where only one iteration (or at most one iteration) is intended behavior,
10
10
  # the code should be refactored to use `if` conditionals.
11
11
  #
12
- # NOTE: Block methods that are used with `Enumerable`s are considered to be loops.
12
+ # NOTE: Block methods that are used with ``Enumerable``s are considered to be loops.
13
13
  #
14
14
  # `AllowedPatterns` can be used to match against the block receiver in order to allow
15
15
  # code that would otherwise be registered as an offense (eg. `times` used not in an
@@ -79,7 +79,7 @@ module RuboCop
79
79
  # # bad
80
80
  # 2.times { raise ArgumentError }
81
81
  #
82
- # @example AllowedPatterns: [/(exactly|at_least|at_most)\(\d+\)\.times/] (default)
82
+ # @example AllowedPatterns: ['(exactly|at_least|at_most)\(\d+\)\.times'] (default)
83
83
  #
84
84
  # # good
85
85
  # exactly(2).times { raise StandardError }
@@ -101,10 +101,14 @@ module RuboCop
101
101
  check(node) if loop_method?(node)
102
102
  end
103
103
 
104
+ def on_numblock(node)
105
+ check(node) if loop_method?(node)
106
+ end
107
+
104
108
  private
105
109
 
106
110
  def loop_method?(node)
107
- return false unless node.block_type?
111
+ return false unless node.block_type? || node.numblock_type?
108
112
 
109
113
  send_node = node.send_node
110
114
  return false if matches_allowed_pattern?(send_node.source)
@@ -179,6 +183,8 @@ module RuboCop
179
183
 
180
184
  def preceded_by_continue_statement?(break_statement)
181
185
  break_statement.left_siblings.any? do |sibling|
186
+ # Numblocks have the arguments count as a number in the AST.
187
+ next if sibling.is_a?(Integer)
182
188
  next if sibling.loop_keyword? || loop_method?(sibling)
183
189
 
184
190
  sibling.each_descendant(*CONTINUE_KEYWORDS).any?
@@ -68,6 +68,10 @@ module RuboCop
68
68
  (send nil? :fail ...)}
69
69
  PATTERN
70
70
 
71
+ def self.autocorrect_incompatible_with
72
+ [Style::ExplicitBlockArgument]
73
+ end
74
+
71
75
  def self.joining_forces
72
76
  VariableForce
73
77
  end
@@ -31,8 +31,8 @@ module RuboCop
31
31
  # # bad
32
32
  # class Foo
33
33
  # # The following is redundant (methods defined on the class'
34
- # # singleton class are not affected by the public modifier)
35
- # public
34
+ # # singleton class are not affected by the private modifier)
35
+ # private
36
36
  #
37
37
  # def self.method3
38
38
  # end
@@ -142,6 +142,8 @@ module RuboCop
142
142
  check_node(node.body)
143
143
  end
144
144
 
145
+ alias on_numblock on_block
146
+
145
147
  private
146
148
 
147
149
  def autocorrect(corrector, node)
@@ -157,17 +159,17 @@ module RuboCop
157
159
 
158
160
  # @!method dynamic_method_definition?(node)
159
161
  def_node_matcher :dynamic_method_definition?, <<~PATTERN
160
- {(send nil? :define_method ...) (block (send nil? :define_method ...) ...)}
162
+ {(send nil? :define_method ...) ({block numblock} (send nil? :define_method ...) ...)}
161
163
  PATTERN
162
164
 
163
165
  # @!method class_or_instance_eval?(node)
164
166
  def_node_matcher :class_or_instance_eval?, <<~PATTERN
165
- (block (send _ {:class_eval :instance_eval}) ...)
167
+ ({block numblock} (send _ {:class_eval :instance_eval}) ...)
166
168
  PATTERN
167
169
 
168
170
  # @!method class_or_module_or_struct_new_call?(node)
169
171
  def_node_matcher :class_or_module_or_struct_new_call?, <<~PATTERN
170
- (block (send (const {nil? cbase} {:Class :Module :Struct}) :new ...) ...)
172
+ ({block numblock} (send (const {nil? cbase} {:Class :Module :Struct}) :new ...) ...)
171
173
  PATTERN
172
174
 
173
175
  def check_node(node)
@@ -277,7 +279,7 @@ module RuboCop
277
279
  matcher_name = "#{m}_block?".to_sym
278
280
  unless respond_to?(matcher_name)
279
281
  self.class.def_node_matcher matcher_name, <<~PATTERN
280
- (block (send {nil? const} {:#{m}} ...) ...)
282
+ ({block numblock} (send {nil? const} {:#{m}} ...) ...)
281
283
  PATTERN
282
284
  end
283
285
 
@@ -6,7 +6,7 @@ module RuboCop
6
6
  # Looks for `ruby2_keywords` calls for methods that do not need it.
7
7
  #
8
8
  # `ruby2_keywords` should only be called on methods that accept an argument splat
9
- # (`*args`) but do not explicit keyword arguments (`k:` or `k: true`) or
9
+ # (`\*args`) but do not explicit keyword arguments (`k:` or `k: true`) or
10
10
  # a keyword splat (`**kwargs`).
11
11
  #
12
12
  # @example
@@ -67,6 +67,8 @@ module RuboCop
67
67
  check_expression(node.body)
68
68
  end
69
69
 
70
+ alias on_numblock on_block
71
+
70
72
  def on_begin(node)
71
73
  check_begin(node)
72
74
  end
@@ -33,7 +33,9 @@ module RuboCop
33
33
  # render 'pages/search/page'
34
34
  # end
35
35
  #
36
- # This cop also takes into account `IgnoredMethods` (defaults to `[]`)
36
+ # This cop also takes into account `AllowedMethods` (defaults to `[]`)
37
+ # And `AllowedPatterns` (defaults to `[]`)
38
+ #
37
39
  class AbcSize < Base
38
40
  include MethodComplexity
39
41
 
@@ -14,8 +14,8 @@ module RuboCop
14
14
  #
15
15
  #
16
16
  # NOTE: The `ExcludedMethods` configuration is deprecated and only kept
17
- # for backwards compatibility. Please use `IgnoredMethods` instead.
18
- # By default, there are no methods to ignored.
17
+ # for backwards compatibility. Please use `AllowedMethods` and `AllowedPatterns`
18
+ # instead. By default, there are no methods to allowed.
19
19
  #
20
20
  # @example CountAsOne: ['array', 'heredoc']
21
21
  #
@@ -38,14 +38,13 @@ module RuboCop
38
38
  # NOTE: This cop does not apply for `Struct` definitions.
39
39
  class BlockLength < Base
40
40
  include CodeLength
41
- include IgnoredMethods
42
-
43
- ignored_methods deprecated_key: 'ExcludedMethods'
41
+ include AllowedMethods
42
+ include AllowedPattern
44
43
 
45
44
  LABEL = 'Block'
46
45
 
47
46
  def on_block(node)
48
- return if ignored_method?(node.method_name)
47
+ return if allowed_method?(node.method_name) || matches_allowed_pattern?(node.method_name)
49
48
  return if method_receiver_excluded?(node)
50
49
  return if node.class_constructor? || node.struct_constructor?
51
50
 
@@ -59,7 +58,7 @@ module RuboCop
59
58
  node_receiver = node.receiver&.source&.gsub(/\s+/, '')
60
59
  node_method = String(node.method_name)
61
60
 
62
- ignored_methods.any? do |config|
61
+ allowed_methods.any? do |config|
63
62
  next unless config.is_a?(String)
64
63
 
65
64
  receiver, method = config.split('.')
@@ -4,16 +4,17 @@ module RuboCop
4
4
  module Cop
5
5
  module Metrics
6
6
  # Checks if the length of a method exceeds some maximum value.
7
- # Comment lines can optionally be ignored.
7
+ # Comment lines can optionally be allowed.
8
8
  # The maximum allowed length is configurable.
9
9
  #
10
10
  # You can set literals you want to fold with `CountAsOne`.
11
11
  # Available are: 'array', 'hash', and 'heredoc'. Each literal
12
12
  # will be counted as one line regardless of its actual size.
13
13
  #
14
- # NOTE: The `ExcludedMethods` configuration is deprecated and only kept
15
- # for backwards compatibility. Please use `IgnoredMethods` instead.
16
- # By default, there are no methods to ignored.
14
+ # NOTE: The `ExcludedMethods` and `IgnoredMethods` configuration is
15
+ # deprecated and only kept for backwards compatibility.
16
+ # Please use `AllowedMethods` and `AllowedPatterns` instead.
17
+ # By default, there are no methods to allowed.
17
18
  #
18
19
  # @example CountAsOne: ['array', 'heredoc']
19
20
  #
@@ -35,14 +36,13 @@ module RuboCop
35
36
  #
36
37
  class MethodLength < Base
37
38
  include CodeLength
38
- include IgnoredMethods
39
-
40
- ignored_methods deprecated_key: 'ExcludedMethods'
39
+ include AllowedMethods
40
+ include AllowedPattern
41
41
 
42
42
  LABEL = 'Method'
43
43
 
44
44
  def on_def(node)
45
- return if ignored_method?(node.method_name)
45
+ return if allowed_method?(node.method_name) || matches_allowed_pattern?(node.method_name)
46
46
 
47
47
  check_code_length(node)
48
48
  end
@@ -12,10 +12,29 @@ module RuboCop
12
12
  allowed_methods.include?(name.to_s)
13
13
  end
14
14
 
15
+ # @deprecated Use allowed_method? instead
16
+ alias ignored_method? allowed_method?
17
+
15
18
  # @api public
16
19
  def allowed_methods
17
- cop_config.fetch('AllowedMethods', [])
20
+ if cop_config_deprecated_values.any?(Regexp)
21
+ cop_config_allowed_methods
22
+ else
23
+ cop_config_allowed_methods + cop_config_deprecated_values
24
+ end
25
+ end
26
+
27
+ def cop_config_allowed_methods
28
+ @cop_config_allowed_methods ||= Array(cop_config.fetch('AllowedMethods', []))
29
+ end
30
+
31
+ def cop_config_deprecated_values
32
+ @cop_config_deprecated_values ||=
33
+ Array(cop_config.fetch('IgnoredMethods', [])) +
34
+ Array(cop_config.fetch('ExcludedMethods', []))
18
35
  end
19
36
  end
37
+ # @deprecated IgnoredMethods class has been replaced with AllowedMethods.
38
+ IgnoredMethods = AllowedMethods
20
39
  end
21
40
  end
@@ -30,7 +30,23 @@ module RuboCop
30
30
  def allowed_patterns
31
31
  # Since there could be a pattern specified in the default config, merge the two
32
32
  # arrays together.
33
- Array(cop_config['AllowedPatterns']).concat(Array(cop_config['IgnoredPatterns']))
33
+ if cop_config_deprecated_methods_values.any?(Regexp)
34
+ cop_config_patterns_values + cop_config_deprecated_methods_values
35
+ else
36
+ cop_config_patterns_values
37
+ end
38
+ end
39
+
40
+ def cop_config_patterns_values
41
+ @cop_config_patterns_values ||=
42
+ Array(cop_config.fetch('AllowedPatterns', [])) +
43
+ Array(cop_config.fetch('IgnoredPatterns', []))
44
+ end
45
+
46
+ def cop_config_deprecated_methods_values
47
+ @cop_config_deprecated_methods_values ||=
48
+ Array(cop_config.fetch('IgnoredMethods', [])) +
49
+ Array(cop_config.fetch('ExcludedMethods', []))
34
50
  end
35
51
  end
36
52
 
@@ -220,7 +220,7 @@ module RuboCop
220
220
  def already_on_multiple_lines?(node)
221
221
  return node.first_line != node.arguments.last.last_line if node.def_type?
222
222
 
223
- node.first_line != node.last_line
223
+ !node.single_line?
224
224
  end
225
225
  end
226
226
  end
@@ -12,10 +12,26 @@ module RuboCop
12
12
  end
13
13
 
14
14
  def contains_comments?(node)
15
+ comments_in_range(node).any?
16
+ end
17
+
18
+ def comments_in_range(node)
15
19
  start_line = node.source_range.line
16
20
  end_line = find_end_line(node)
17
21
 
18
- processed_source.each_comment_in_lines(start_line...end_line).any?
22
+ processed_source.each_comment_in_lines(start_line...end_line)
23
+ end
24
+
25
+ def comments_contain_disables?(node, cop_name)
26
+ disabled_ranges = processed_source.disabled_line_ranges[cop_name]
27
+
28
+ return unless disabled_ranges
29
+
30
+ node_range = node.source_range.line...find_end_line(node)
31
+
32
+ disabled_ranges.any? do |disable_range|
33
+ disable_range.cover?(node_range) || node_range.cover?(disable_range)
34
+ end
19
35
  end
20
36
 
21
37
  private
@@ -6,7 +6,8 @@ module RuboCop
6
6
  #
7
7
  # IMPORTANT: RuboCop core depended on this module when it supported Rails department.
8
8
  # Rails department has been extracted to RuboCop Rails gem.
9
- # This module is deprecated and will be removed by RuboCop 2.0.
9
+ #
10
+ # @deprecated This module is deprecated and will be removed by RuboCop 2.0.
10
11
  # It will not be updated to `RuboCop::Cop::Base` v1 API to maintain compatibility
11
12
  # with existing RuboCop Rails 2.8 or lower.
12
13
  #
@@ -69,6 +69,10 @@ module RuboCop
69
69
  end
70
70
  end
71
71
 
72
+ def leading_magic_comments
73
+ leading_comment_lines.map { |line| MagicComment.parse(line) }
74
+ end
75
+
72
76
  def leading_comment_lines
73
77
  first_non_comment_token = processed_source.tokens.find { |token| !token.comment? }
74
78
 
@@ -5,7 +5,22 @@ module RuboCop
5
5
  # This module checks for Ruby 3.1's hash value omission syntax.
6
6
  module HashShorthandSyntax
7
7
  OMIT_HASH_VALUE_MSG = 'Omit the hash value.'
8
- EXPLICIT_HASH_VALUE_MSG = 'Explicit the hash value.'
8
+ EXPLICIT_HASH_VALUE_MSG = 'Include the hash value.'
9
+ DO_NOT_MIX_MSG_PREFIX = 'Do not mix explicit and implicit hash values.'
10
+ DO_NOT_MIX_OMIT_VALUE_MSG = "#{DO_NOT_MIX_MSG_PREFIX} #{OMIT_HASH_VALUE_MSG}"
11
+ DO_NOT_MIX_EXPLICIT_VALUE_MSG = "#{DO_NOT_MIX_MSG_PREFIX} #{EXPLICIT_HASH_VALUE_MSG}"
12
+
13
+ def on_hash_for_mixed_shorthand(hash_node)
14
+ return if ignore_mixed_hash_shorthand_syntax?(hash_node)
15
+
16
+ hash_value_type_breakdown = breakdown_value_types_of_hash(hash_node)
17
+
18
+ if hash_with_mixed_shorthand_syntax?(hash_value_type_breakdown)
19
+ mixed_shorthand_syntax_check(hash_value_type_breakdown)
20
+ else
21
+ no_mixed_shorthand_syntax_check(hash_value_type_breakdown)
22
+ end
23
+ end
9
24
 
10
25
  def on_pair(node)
11
26
  return if ignore_hash_shorthand_syntax?(node)
@@ -36,8 +51,14 @@ module RuboCop
36
51
  end
37
52
  end
38
53
 
54
+ def ignore_mixed_hash_shorthand_syntax?(hash_node)
55
+ target_ruby_version <= 3.0 || enforced_shorthand_syntax != 'consistent' ||
56
+ !hash_node.hash_type?
57
+ end
58
+
39
59
  def ignore_hash_shorthand_syntax?(pair_node)
40
60
  target_ruby_version <= 3.0 || enforced_shorthand_syntax == 'either' ||
61
+ enforced_shorthand_syntax == 'consistent' ||
41
62
  !pair_node.parent.hash_type?
42
63
  end
43
64
 
@@ -75,11 +96,68 @@ module RuboCop
75
96
  end
76
97
 
77
98
  def without_parentheses_call_expr_follows?(ancestor)
99
+ return false unless ancestor.respond_to?(:parenthesized?) && !ancestor.parenthesized?
100
+
78
101
  right_sibling = ancestor.right_sibling
79
- right_sibling ||= ancestor.each_ancestor.find(&:assignment?)&.right_sibling
80
- return false unless right_sibling
102
+ right_sibling ||= ancestor.each_ancestor.find do |node|
103
+ node.assignment? || node.send_type?
104
+ end&.right_sibling
105
+
106
+ !!right_sibling
107
+ end
81
108
 
82
- ancestor.respond_to?(:parenthesized?) && !ancestor.parenthesized? && !!right_sibling
109
+ def breakdown_value_types_of_hash(hash_node)
110
+ hash_node.pairs.group_by do |pair_node|
111
+ if pair_node.value_omission?
112
+ :value_omitted
113
+ elsif require_hash_value?(pair_node.key.source, pair_node)
114
+ :value_needed
115
+ else
116
+ :value_omittable
117
+ end
118
+ end
119
+ end
120
+
121
+ def hash_with_mixed_shorthand_syntax?(hash_value_type_breakdown)
122
+ hash_value_type_breakdown.keys.size > 1
123
+ end
124
+
125
+ def hash_with_values_that_cant_be_omitted?(hash_value_type_breakdown)
126
+ hash_value_type_breakdown[:value_needed]&.any?
127
+ end
128
+
129
+ def each_omitted_value_pair(hash_value_type_breakdown, &block)
130
+ hash_value_type_breakdown[:value_omitted]&.each(&block)
131
+ end
132
+
133
+ def each_omittable_value_pair(hash_value_type_breakdown, &block)
134
+ hash_value_type_breakdown[:value_omittable]&.each(&block)
135
+ end
136
+
137
+ def mixed_shorthand_syntax_check(hash_value_type_breakdown)
138
+ if hash_with_values_that_cant_be_omitted?(hash_value_type_breakdown)
139
+ each_omitted_value_pair(hash_value_type_breakdown) do |pair_node|
140
+ hash_key_source = pair_node.key.source
141
+ replacement = "#{hash_key_source}: #{hash_key_source}"
142
+ register_offense(pair_node, DO_NOT_MIX_EXPLICIT_VALUE_MSG, replacement)
143
+ end
144
+ else
145
+ each_omittable_value_pair(hash_value_type_breakdown) do |pair_node|
146
+ hash_key_source = pair_node.key.source
147
+ replacement = "#{hash_key_source}:"
148
+ register_offense(pair_node, DO_NOT_MIX_OMIT_VALUE_MSG, replacement)
149
+ end
150
+ end
151
+ end
152
+
153
+ def no_mixed_shorthand_syntax_check(hash_value_type_breakdown)
154
+ return if hash_with_values_that_cant_be_omitted?(hash_value_type_breakdown)
155
+
156
+ each_omittable_value_pair(hash_value_type_breakdown) do |pair_node|
157
+ hash_key_source = pair_node.key.source
158
+ replacement = "#{hash_key_source}:"
159
+ register_offense(pair_node, OMIT_HASH_VALUE_MSG, replacement)
160
+ end
83
161
  end
84
162
  end
85
163
  end
@@ -14,7 +14,7 @@ module RuboCop
14
14
  {(array ...) (send _ :each_with_index) (send _ :with_index _ ?) (send _ :zip ...)}
15
15
  PATTERN
16
16
 
17
- def on_block(node)
17
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
18
18
  on_bad_each_with_object(node) do |*match|
19
19
  handle_possible_offense(node, match, 'each_with_object')
20
20
  end
@@ -68,6 +68,8 @@ module RuboCop
68
68
  # `transform_values` if value transformation uses key.
69
69
  return if captures.transformation_uses_both_args?
70
70
 
71
+ return unless captures.use_transformed_argname?
72
+
71
73
  message = "Prefer `#{new_method_name}` over `#{match_desc}`."
72
74
  add_offense(node, message: message) do |corrector|
73
75
  correction = prepare_correction(node)
@@ -113,11 +115,7 @@ module RuboCop
113
115
  end
114
116
 
115
117
  # Internal helper class to hold match data
116
- Captures = Struct.new(
117
- :transformed_argname,
118
- :transforming_body_expr,
119
- :unchanged_body_expr
120
- ) do
118
+ Captures = Struct.new(:transformed_argname, :transforming_body_expr, :unchanged_body_expr) do
121
119
  def noop_transformation?
122
120
  transforming_body_expr.lvar_type? &&
123
121
  transforming_body_expr.children == [transformed_argname]
@@ -126,6 +124,12 @@ module RuboCop
126
124
  def transformation_uses_both_args?
127
125
  transforming_body_expr.descendants.include?(unchanged_body_expr)
128
126
  end
127
+
128
+ def use_transformed_argname?
129
+ transforming_body_expr.each_descendant(:lvar).any? do |node|
130
+ node.source == transformed_argname.to_s
131
+ end
132
+ end
129
133
  end
130
134
 
131
135
  # Internal helper class to hold autocorrect data