rubocop 1.62.1 → 1.67.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 (276) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +67 -68
  3. data/config/default.yml +82 -12
  4. data/config/internal_affairs.yml +11 -0
  5. data/exe/rubocop +4 -3
  6. data/lib/rubocop/cached_data.rb +11 -3
  7. data/lib/rubocop/cli/command/auto_generate_config.rb +6 -7
  8. data/lib/rubocop/cli/command/lsp.rb +2 -2
  9. data/lib/rubocop/cli/command/show_docs_url.rb +2 -2
  10. data/lib/rubocop/cli.rb +4 -0
  11. data/lib/rubocop/comment_config.rb +1 -1
  12. data/lib/rubocop/config.rb +37 -11
  13. data/lib/rubocop/config_loader.rb +15 -9
  14. data/lib/rubocop/config_loader_resolver.rb +13 -8
  15. data/lib/rubocop/config_obsoletion.rb +1 -1
  16. data/lib/rubocop/config_validator.rb +3 -2
  17. data/lib/rubocop/cop/base.rb +56 -16
  18. data/lib/rubocop/cop/bundler/gem_version.rb +4 -5
  19. data/lib/rubocop/cop/cop.rb +30 -4
  20. data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -0
  21. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
  22. data/lib/rubocop/cop/documentation.rb +32 -5
  23. data/lib/rubocop/cop/force.rb +12 -0
  24. data/lib/rubocop/cop/gemspec/add_runtime_dependency.rb +38 -0
  25. data/lib/rubocop/cop/gemspec/dependency_version.rb +3 -5
  26. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -2
  27. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +3 -3
  28. data/lib/rubocop/cop/internal_affairs/cop_description.rb +0 -4
  29. data/lib/rubocop/cop/internal_affairs/empty_line_between_expect_offense_and_correction.rb +2 -1
  30. data/lib/rubocop/cop/internal_affairs/example_description.rb +2 -1
  31. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  32. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +6 -21
  33. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +8 -1
  34. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +11 -1
  35. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +0 -5
  36. data/lib/rubocop/cop/internal_affairs.rb +16 -0
  37. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +5 -1
  38. data/lib/rubocop/cop/layout/assignment_indentation.rb +3 -2
  39. data/lib/rubocop/cop/layout/block_alignment.rb +30 -12
  40. data/lib/rubocop/cop/layout/case_indentation.rb +1 -1
  41. data/lib/rubocop/cop/layout/comment_indentation.rb +1 -1
  42. data/lib/rubocop/cop/layout/condition_position.rb +0 -4
  43. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  44. data/lib/rubocop/cop/layout/empty_comment.rb +3 -1
  45. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
  46. data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +1 -1
  47. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +2 -1
  48. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +8 -3
  49. data/lib/rubocop/cop/layout/first_argument_indentation.rb +2 -2
  50. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -3
  51. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +8 -0
  52. data/lib/rubocop/cop/layout/heredoc_indentation.rb +1 -1
  53. data/lib/rubocop/cop/layout/indentation_width.rb +5 -6
  54. data/lib/rubocop/cop/layout/leading_comment_space.rb +28 -1
  55. data/lib/rubocop/cop/layout/line_length.rb +20 -20
  56. data/lib/rubocop/cop/layout/space_around_operators.rb +3 -0
  57. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +3 -4
  58. data/lib/rubocop/cop/legacy/corrector.rb +12 -2
  59. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +0 -2
  60. data/lib/rubocop/cop/lint/ambiguous_operator.rb +0 -2
  61. data/lib/rubocop/cop/lint/ambiguous_range.rb +4 -1
  62. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +0 -2
  63. data/lib/rubocop/cop/lint/assignment_in_condition.rb +2 -2
  64. data/lib/rubocop/cop/lint/big_decimal_new.rb +4 -7
  65. data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -3
  66. data/lib/rubocop/cop/lint/circular_argument_reference.rb +0 -13
  67. data/lib/rubocop/cop/lint/debugger.rb +27 -6
  68. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  69. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +0 -10
  70. data/lib/rubocop/cop/lint/duplicate_case_condition.rb +1 -5
  71. data/lib/rubocop/cop/lint/duplicate_hash_key.rb +0 -4
  72. data/lib/rubocop/cop/lint/duplicate_methods.rb +0 -10
  73. data/lib/rubocop/cop/lint/duplicate_set_element.rb +74 -0
  74. data/lib/rubocop/cop/lint/each_with_object_argument.rb +0 -4
  75. data/lib/rubocop/cop/lint/else_layout.rb +0 -2
  76. data/lib/rubocop/cop/lint/empty_conditional_body.rb +28 -7
  77. data/lib/rubocop/cop/lint/empty_ensure.rb +1 -11
  78. data/lib/rubocop/cop/lint/empty_interpolation.rb +0 -4
  79. data/lib/rubocop/cop/lint/empty_when.rb +1 -3
  80. data/lib/rubocop/cop/lint/ensure_return.rb +1 -9
  81. data/lib/rubocop/cop/lint/erb_new_arguments.rb +21 -14
  82. data/lib/rubocop/cop/lint/float_comparison.rb +1 -1
  83. data/lib/rubocop/cop/lint/float_out_of_range.rb +0 -4
  84. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +0 -10
  85. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +23 -12
  86. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +0 -7
  87. data/lib/rubocop/cop/lint/interpolation_check.rb +0 -4
  88. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +5 -14
  89. data/lib/rubocop/cop/lint/literal_as_condition.rb +1 -1
  90. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
  91. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +25 -6
  92. data/lib/rubocop/cop/lint/loop.rb +6 -12
  93. data/lib/rubocop/cop/lint/mixed_case_range.rb +9 -4
  94. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -7
  95. data/lib/rubocop/cop/lint/next_without_accumulator.rb +0 -4
  96. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +0 -5
  97. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +1 -1
  98. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +5 -6
  99. data/lib/rubocop/cop/lint/percent_string_array.rb +0 -4
  100. data/lib/rubocop/cop/lint/percent_symbol_array.rb +0 -4
  101. data/lib/rubocop/cop/lint/rand_one.rb +0 -4
  102. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +3 -1
  103. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +1 -1
  104. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
  105. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +0 -4
  106. data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -0
  107. data/lib/rubocop/cop/lint/require_parentheses.rb +0 -4
  108. data/lib/rubocop/cop/lint/rescue_exception.rb +0 -4
  109. data/lib/rubocop/cop/lint/return_in_void_context.rb +0 -2
  110. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +0 -4
  111. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +105 -41
  112. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +6 -10
  113. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  114. data/lib/rubocop/cop/lint/to_enum_arguments.rb +2 -9
  115. data/lib/rubocop/cop/lint/unified_integer.rb +0 -4
  116. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -0
  117. data/lib/rubocop/cop/lint/unreachable_code.rb +4 -7
  118. data/lib/rubocop/cop/lint/unreachable_loop.rb +8 -2
  119. data/lib/rubocop/cop/lint/uri_regexp.rb +25 -7
  120. data/lib/rubocop/cop/lint/useless_assignment.rb +19 -16
  121. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +0 -4
  122. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +77 -0
  123. data/lib/rubocop/cop/lint/useless_setter_call.rb +0 -4
  124. data/lib/rubocop/cop/lint/void.rb +35 -8
  125. data/lib/rubocop/cop/metrics/block_length.rb +6 -5
  126. data/lib/rubocop/cop/metrics/block_nesting.rb +19 -7
  127. data/lib/rubocop/cop/metrics/class_length.rb +6 -5
  128. data/lib/rubocop/cop/metrics/method_length.rb +6 -5
  129. data/lib/rubocop/cop/metrics/module_length.rb +6 -5
  130. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +5 -5
  131. data/lib/rubocop/cop/mixin/alignment.rb +5 -1
  132. data/lib/rubocop/cop/mixin/allowed_methods.rb +7 -1
  133. data/lib/rubocop/cop/mixin/allowed_pattern.rb +15 -3
  134. data/lib/rubocop/cop/mixin/annotation_comment.rb +0 -2
  135. data/lib/rubocop/cop/mixin/code_length.rb +12 -1
  136. data/lib/rubocop/cop/mixin/configurable_max.rb +5 -1
  137. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +19 -9
  138. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +9 -2
  139. data/lib/rubocop/cop/mixin/line_length_help.rb +7 -2
  140. data/lib/rubocop/cop/mixin/method_complexity.rb +15 -6
  141. data/lib/rubocop/cop/mixin/percent_array.rb +1 -1
  142. data/lib/rubocop/cop/mixin/rescue_node.rb +4 -0
  143. data/lib/rubocop/cop/mixin/safe_assignment.rb +1 -1
  144. data/lib/rubocop/cop/mixin/statement_modifier.rb +3 -2
  145. data/lib/rubocop/cop/mixin/string_literals_help.rb +12 -0
  146. data/lib/rubocop/cop/naming/accessor_method_name.rb +5 -0
  147. data/lib/rubocop/cop/naming/block_forwarding.rb +31 -12
  148. data/lib/rubocop/cop/naming/file_name.rb +2 -2
  149. data/lib/rubocop/cop/naming/inclusive_language.rb +13 -5
  150. data/lib/rubocop/cop/naming/predicate_name.rb +53 -27
  151. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +10 -1
  152. data/lib/rubocop/cop/offense.rb +2 -2
  153. data/lib/rubocop/cop/security/compound_hash.rb +2 -2
  154. data/lib/rubocop/cop/style/access_modifier_declarations.rb +62 -2
  155. data/lib/rubocop/cop/style/accessor_grouping.rb +10 -2
  156. data/lib/rubocop/cop/style/alias.rb +2 -1
  157. data/lib/rubocop/cop/style/arguments_forwarding.rb +59 -11
  158. data/lib/rubocop/cop/style/block_delimiters.rb +14 -1
  159. data/lib/rubocop/cop/style/collection_compact.rb +9 -9
  160. data/lib/rubocop/cop/style/combinable_loops.rb +7 -0
  161. data/lib/rubocop/cop/style/commented_keyword.rb +7 -1
  162. data/lib/rubocop/cop/style/conditional_assignment.rb +2 -2
  163. data/lib/rubocop/cop/style/copyright.rb +31 -21
  164. data/lib/rubocop/cop/style/data_inheritance.rb +1 -1
  165. data/lib/rubocop/cop/style/def_with_parentheses.rb +0 -2
  166. data/lib/rubocop/cop/style/documentation.rb +24 -24
  167. data/lib/rubocop/cop/style/documentation_method.rb +20 -0
  168. data/lib/rubocop/cop/style/each_for_simple_loop.rb +0 -1
  169. data/lib/rubocop/cop/style/empty_else.rb +6 -5
  170. data/lib/rubocop/cop/style/empty_heredoc.rb +1 -14
  171. data/lib/rubocop/cop/style/empty_literal.rb +31 -22
  172. data/lib/rubocop/cop/style/eval_with_location.rb +16 -13
  173. data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -1
  174. data/lib/rubocop/cop/style/file_read.rb +2 -5
  175. data/lib/rubocop/cop/style/file_write.rb +2 -5
  176. data/lib/rubocop/cop/style/format_string.rb +9 -9
  177. data/lib/rubocop/cop/style/format_string_token.rb +2 -2
  178. data/lib/rubocop/cop/style/global_std_stream.rb +7 -1
  179. data/lib/rubocop/cop/style/guard_clause.rb +3 -1
  180. data/lib/rubocop/cop/style/hash_each_methods.rb +6 -0
  181. data/lib/rubocop/cop/style/hash_except.rb +8 -5
  182. data/lib/rubocop/cop/style/hash_syntax.rb +20 -2
  183. data/lib/rubocop/cop/style/identical_conditional_branches.rb +1 -1
  184. data/lib/rubocop/cop/style/if_inside_else.rb +1 -1
  185. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +5 -4
  186. data/lib/rubocop/cop/style/if_with_semicolon.rb +49 -6
  187. data/lib/rubocop/cop/style/in_pattern_then.rb +6 -2
  188. data/lib/rubocop/cop/style/invertible_unless_condition.rb +2 -2
  189. data/lib/rubocop/cop/style/lambda.rb +1 -1
  190. data/lib/rubocop/cop/style/magic_comment_format.rb +1 -1
  191. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +77 -43
  192. data/lib/rubocop/cop/style/map_into_array.rb +228 -0
  193. data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
  194. data/lib/rubocop/cop/style/map_to_set.rb +1 -1
  195. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +17 -7
  196. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +1 -1
  197. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -2
  198. data/lib/rubocop/cop/style/missing_else.rb +0 -4
  199. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  200. data/lib/rubocop/cop/style/multiline_when_then.rb +0 -4
  201. data/lib/rubocop/cop/style/multiple_comparison.rb +3 -11
  202. data/lib/rubocop/cop/style/nested_modifier.rb +1 -1
  203. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  204. data/lib/rubocop/cop/style/numeric_predicate.rb +12 -4
  205. data/lib/rubocop/cop/style/one_line_conditional.rb +6 -2
  206. data/lib/rubocop/cop/style/operator_method_call.rb +25 -6
  207. data/lib/rubocop/cop/style/parallel_assignment.rb +5 -4
  208. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -3
  209. data/lib/rubocop/cop/style/redundant_argument.rb +24 -1
  210. data/lib/rubocop/cop/style/redundant_begin.rb +5 -1
  211. data/lib/rubocop/cop/style/redundant_condition.rb +4 -4
  212. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +1 -1
  213. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  214. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +1 -1
  215. data/lib/rubocop/cop/style/redundant_filter_chain.rb +1 -1
  216. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +46 -0
  217. data/lib/rubocop/cop/style/redundant_line_continuation.rb +15 -18
  218. data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -1
  219. data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
  220. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -1
  221. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -24
  222. data/lib/rubocop/cop/style/require_order.rb +2 -2
  223. data/lib/rubocop/cop/style/rescue_modifier.rb +13 -1
  224. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +54 -12
  225. data/lib/rubocop/cop/style/safe_navigation.rb +94 -52
  226. data/lib/rubocop/cop/style/select_by_regexp.rb +9 -6
  227. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  228. data/lib/rubocop/cop/style/send.rb +4 -4
  229. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +104 -0
  230. data/lib/rubocop/cop/style/sole_nested_conditional.rb +21 -2
  231. data/lib/rubocop/cop/style/special_global_vars.rb +1 -2
  232. data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
  233. data/lib/rubocop/cop/style/super_arguments.rb +174 -0
  234. data/lib/rubocop/cop/style/symbol_proc.rb +39 -5
  235. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  236. data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
  237. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  238. data/lib/rubocop/cop/style/while_until_do.rb +0 -2
  239. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  240. data/lib/rubocop/cop/style/zero_length_predicate.rb +32 -24
  241. data/lib/rubocop/cop/team.rb +27 -3
  242. data/lib/rubocop/cop/util.rb +8 -2
  243. data/lib/rubocop/cop/variable_force.rb +13 -1
  244. data/lib/rubocop/cops_documentation_generator.rb +73 -34
  245. data/lib/rubocop/core_ext/string.rb +2 -6
  246. data/lib/rubocop/ext/regexp_node.rb +9 -31
  247. data/lib/rubocop/ext/regexp_parser.rb +4 -21
  248. data/lib/rubocop/file_finder.rb +9 -4
  249. data/lib/rubocop/formatter/clang_style_formatter.rb +3 -7
  250. data/lib/rubocop/formatter/disabled_config_formatter.rb +13 -9
  251. data/lib/rubocop/formatter/formatter_set.rb +7 -1
  252. data/lib/rubocop/formatter/html_formatter.rb +3 -1
  253. data/lib/rubocop/formatter/junit_formatter.rb +70 -23
  254. data/lib/rubocop/formatter/tap_formatter.rb +3 -7
  255. data/lib/rubocop/lockfile.rb +58 -7
  256. data/lib/rubocop/lsp/routes.rb +10 -13
  257. data/lib/rubocop/lsp/runtime.rb +2 -0
  258. data/lib/rubocop/lsp/server.rb +2 -1
  259. data/lib/rubocop/lsp.rb +9 -2
  260. data/lib/rubocop/options.rb +6 -4
  261. data/lib/rubocop/rake_task.rb +1 -1
  262. data/lib/rubocop/remote_config.rb +5 -1
  263. data/lib/rubocop/result_cache.rb +2 -8
  264. data/lib/rubocop/rspec/expect_offense.rb +9 -0
  265. data/lib/rubocop/rspec/shared_contexts.rb +35 -3
  266. data/lib/rubocop/rspec/support.rb +1 -0
  267. data/lib/rubocop/runner.rb +8 -1
  268. data/lib/rubocop/server/cache.rb +16 -1
  269. data/lib/rubocop/server/client_command/exec.rb +2 -2
  270. data/lib/rubocop/server/client_command/start.rb +1 -1
  271. data/lib/rubocop/server/core.rb +5 -0
  272. data/lib/rubocop/target_ruby.rb +19 -15
  273. data/lib/rubocop/version.rb +7 -5
  274. data/lib/rubocop/yaml_duplication_checker.rb +20 -26
  275. data/lib/rubocop.rb +13 -1
  276. metadata +20 -32
@@ -66,7 +66,6 @@ module RuboCop
66
66
  BINARY_OPERATORS = %i[* / % + - == === != < > <= >= <=>].freeze
67
67
  UNARY_OPERATORS = %i[+@ -@ ~ !].freeze
68
68
  OPERATORS = (BINARY_OPERATORS + UNARY_OPERATORS).freeze
69
- VOID_CONTEXT_TYPES = %i[def for block].freeze
70
69
  NONMUTATING_METHODS_WITH_BANG_VERSION = %i[capitalize chomp chop compact
71
70
  delete_prefix delete_suffix downcase
72
71
  encode flatten gsub lstrip merge next
@@ -86,7 +85,6 @@ module RuboCop
86
85
  check_void_op(node.body) { node.method?(:each) }
87
86
  check_expression(node.body)
88
87
  end
89
-
90
88
  alias on_numblock on_block
91
89
 
92
90
  def on_begin(node)
@@ -94,6 +92,10 @@ module RuboCop
94
92
  end
95
93
  alias on_kwbegin on_begin
96
94
 
95
+ def on_ensure(node)
96
+ check_ensure(node)
97
+ end
98
+
97
99
  private
98
100
 
99
101
  def check_begin(node)
@@ -111,6 +113,8 @@ module RuboCop
111
113
  end
112
114
 
113
115
  def check_expression(expr)
116
+ expr = expr.body if expr.if_type? && expr.modifier_form?
117
+
114
118
  check_literal(expr)
115
119
  check_var(expr)
116
120
  check_self(expr)
@@ -121,6 +125,7 @@ module RuboCop
121
125
  end
122
126
 
123
127
  def check_void_op(node, &block)
128
+ node = node.children.first while node.begin_type?
124
129
  return unless node.send_type? && OPERATORS.include?(node.method_name)
125
130
  return if block && yield(node)
126
131
 
@@ -190,12 +195,24 @@ module RuboCop
190
195
  end
191
196
  end
192
197
 
198
+ def check_ensure(node)
199
+ return unless (body = node.body)
200
+ # NOTE: the `begin` node case is already handled via `on_begin`
201
+ return if body.begin_type?
202
+
203
+ check_void_op(body) do
204
+ block_node = node.each_ancestor(:block).first
205
+ block_node&.method?(:each)
206
+ end
207
+
208
+ check_expression(body)
209
+ end
210
+
193
211
  def in_void_context?(node)
194
212
  parent = node.parent
195
-
196
213
  return false unless parent && parent.children.last == node
197
214
 
198
- VOID_CONTEXT_TYPES.include?(parent.type) && parent.void_context?
215
+ parent.respond_to?(:void_context?) && parent.void_context?
199
216
  end
200
217
 
201
218
  def autocorrect_void_op(corrector, node)
@@ -211,6 +228,8 @@ module RuboCop
211
228
  end
212
229
 
213
230
  def autocorrect_void_expression(corrector, node)
231
+ return if node.parent.if_type? && node.parent.modifier_form?
232
+
214
233
  corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
215
234
  end
216
235
 
@@ -226,15 +245,23 @@ module RuboCop
226
245
  def entirely_literal?(node)
227
246
  case node.type
228
247
  when :array
229
- node.each_value.all? { |value| entirely_literal?(value) }
248
+ all_values_entirely_literal?(node)
230
249
  when :hash
231
- return false unless node.each_key.all? { |key| entirely_literal?(key) }
232
-
233
- node.each_value.all? { |value| entirely_literal?(value) }
250
+ all_keys_entirely_literal?(node) && all_values_entirely_literal?(node)
251
+ when :send, :csend
252
+ node.method?(:freeze) && node.receiver && entirely_literal?(node.receiver)
234
253
  else
235
254
  node.literal?
236
255
  end
237
256
  end
257
+
258
+ def all_keys_entirely_literal?(node)
259
+ node.each_key.all? { |key| entirely_literal?(key) }
260
+ end
261
+
262
+ def all_values_entirely_literal?(node)
263
+ node.each_value.all? { |value| entirely_literal?(value) }
264
+ end
238
265
  end
239
266
  end
240
267
  end
@@ -9,8 +9,9 @@ module RuboCop
9
9
  # The cop can be configured to ignore blocks passed to certain methods.
10
10
  #
11
11
  # You can set constructs you want to fold with `CountAsOne`.
12
- # Available are: 'array', 'hash', 'heredoc', and 'method_call'. Each construct
13
- # will be counted as one line regardless of its actual size.
12
+ #
13
+ # Available are: 'array', 'hash', 'heredoc', and 'method_call'.
14
+ # Each construct will be counted as one line regardless of its actual size.
14
15
  #
15
16
  # NOTE: This cop does not apply for `Struct` definitions.
16
17
  #
@@ -18,7 +19,7 @@ module RuboCop
18
19
  # for backwards compatibility. Please use `AllowedMethods` and `AllowedPatterns`
19
20
  # instead. By default, there are no methods to allowed.
20
21
  #
21
- # @example CountAsOne: ['array', 'heredoc', 'method_call']
22
+ # @example CountAsOne: ['array', 'hash', 'heredoc', 'method_call']
22
23
  #
23
24
  # something do
24
25
  # array = [ # +1
@@ -26,7 +27,7 @@ module RuboCop
26
27
  # 2
27
28
  # ]
28
29
  #
29
- # hash = { # +3
30
+ # hash = { # +1
30
31
  # key: 'value'
31
32
  # }
32
33
  #
@@ -39,7 +40,7 @@ module RuboCop
39
40
  # 1,
40
41
  # 2
41
42
  # )
42
- # end # 6 points
43
+ # end # 4 points
43
44
  #
44
45
  class BlockLength < Base
45
46
  include CodeLength
@@ -3,12 +3,12 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Metrics
6
- # Checks for excessive nesting of conditional and looping
7
- # constructs.
6
+ # Checks for excessive nesting of conditional and looping constructs.
8
7
  #
9
- # You can configure if blocks are considered using the `CountBlocks`
10
- # option. When set to `false` (the default) blocks are not counted
11
- # towards the nesting level. Set to `true` to count blocks as well.
8
+ # You can configure if blocks are considered using the `CountBlocks` and `CountModifierForms`
9
+ # options. When both are set to `false` (the default) blocks and modifier forms are not
10
+ # counted towards the nesting level. Set them to `true` to include these in the nesting level
11
+ # calculation as well.
12
12
  #
13
13
  # The maximum level of nesting allowed is configurable.
14
14
  class BlockNesting < Base
@@ -27,7 +27,7 @@ module RuboCop
27
27
 
28
28
  def check_nesting_level(node, max, current_level)
29
29
  if consider_node?(node)
30
- current_level += 1 unless node.if_type? && node.elsif?
30
+ current_level += 1 if count_if_block?(node)
31
31
  if current_level > max
32
32
  self.max = current_level
33
33
  unless part_of_ignored_node?(node)
@@ -41,6 +41,14 @@ module RuboCop
41
41
  end
42
42
  end
43
43
 
44
+ def count_if_block?(node)
45
+ return true unless node.if_type?
46
+ return false if node.elsif?
47
+ return count_modifier_forms? if node.modifier_form?
48
+
49
+ true
50
+ end
51
+
44
52
  def consider_node?(node)
45
53
  return true if NESTING_BLOCKS.include?(node.type)
46
54
 
@@ -52,7 +60,11 @@ module RuboCop
52
60
  end
53
61
 
54
62
  def count_blocks?
55
- cop_config['CountBlocks']
63
+ cop_config.fetch('CountBlocks', false)
64
+ end
65
+
66
+ def count_modifier_forms?
67
+ cop_config.fetch('CountModifierForms', false)
56
68
  end
57
69
  end
58
70
  end
@@ -8,12 +8,13 @@ module RuboCop
8
8
  # The maximum allowed length is configurable.
9
9
  #
10
10
  # You can set constructs you want to fold with `CountAsOne`.
11
- # Available are: 'array', 'hash', 'heredoc', and 'method_call'. Each construct
12
- # will be counted as one line regardless of its actual size.
11
+ #
12
+ # Available are: 'array', 'hash', 'heredoc', and 'method_call'.
13
+ # Each construct will be counted as one line regardless of its actual size.
13
14
  #
14
15
  # NOTE: This cop also applies for `Struct` definitions.
15
16
  #
16
- # @example CountAsOne: ['array', 'heredoc', 'method_call']
17
+ # @example CountAsOne: ['array', 'hash', 'heredoc', 'method_call']
17
18
  #
18
19
  # class Foo
19
20
  # ARRAY = [ # +1
@@ -21,7 +22,7 @@ module RuboCop
21
22
  # 2
22
23
  # ]
23
24
  #
24
- # HASH = { # +3
25
+ # HASH = { # +1
25
26
  # key: 'value'
26
27
  # }
27
28
  #
@@ -34,7 +35,7 @@ module RuboCop
34
35
  # 1,
35
36
  # 2
36
37
  # )
37
- # end # 6 points
38
+ # end # 4 points
38
39
  #
39
40
  class ClassLength < Base
40
41
  include CodeLength
@@ -8,15 +8,16 @@ module RuboCop
8
8
  # The maximum allowed length is configurable.
9
9
  #
10
10
  # You can set constructs you want to fold with `CountAsOne`.
11
- # Available are: 'array', 'hash', 'heredoc', and 'method_call'. Each construct
12
- # will be counted as one line regardless of its actual size.
11
+ #
12
+ # Available are: 'array', 'hash', 'heredoc', and 'method_call'.
13
+ # Each construct will be counted as one line regardless of its actual size.
13
14
  #
14
15
  # NOTE: The `ExcludedMethods` and `IgnoredMethods` configuration is
15
16
  # deprecated and only kept for backwards compatibility.
16
17
  # Please use `AllowedMethods` and `AllowedPatterns` instead.
17
18
  # By default, there are no methods to allowed.
18
19
  #
19
- # @example CountAsOne: ['array', 'heredoc', 'method_call']
20
+ # @example CountAsOne: ['array', 'hash', 'heredoc', 'method_call']
20
21
  #
21
22
  # def m
22
23
  # array = [ # +1
@@ -24,7 +25,7 @@ module RuboCop
24
25
  # 2
25
26
  # ]
26
27
  #
27
- # hash = { # +3
28
+ # hash = { # +1
28
29
  # key: 'value'
29
30
  # }
30
31
  #
@@ -37,7 +38,7 @@ module RuboCop
37
38
  # 1,
38
39
  # 2
39
40
  # )
40
- # end # 6 points
41
+ # end # 4 points
41
42
  #
42
43
  class MethodLength < Base
43
44
  include CodeLength
@@ -8,10 +8,11 @@ module RuboCop
8
8
  # The maximum allowed length is configurable.
9
9
  #
10
10
  # You can set constructs you want to fold with `CountAsOne`.
11
- # Available are: 'array', 'hash', 'heredoc', and 'method_call'. Each construct
12
- # will be counted as one line regardless of its actual size.
13
11
  #
14
- # @example CountAsOne: ['array', 'heredoc', 'method_call']
12
+ # Available are: 'array', 'hash', 'heredoc', and 'method_call'.
13
+ # Each construct will be counted as one line regardless of its actual size.
14
+ #
15
+ # @example CountAsOne: ['array', 'hash', 'heredoc', 'method_call']
15
16
  #
16
17
  # module M
17
18
  # ARRAY = [ # +1
@@ -19,7 +20,7 @@ module RuboCop
19
20
  # 2
20
21
  # ]
21
22
  #
22
- # HASH = { # +3
23
+ # HASH = { # +1
23
24
  # key: 'value'
24
25
  # }
25
26
  #
@@ -32,7 +33,7 @@ module RuboCop
32
33
  # 1,
33
34
  # 2
34
35
  # )
35
- # end # 6 points
36
+ # end # 4 points
36
37
  #
37
38
  class ModuleLength < Base
38
39
  include CodeLength
@@ -43,16 +43,16 @@ module RuboCop
43
43
  types.map do |type|
44
44
  case type
45
45
  when :array
46
- ->(node) { node.array_type? }
46
+ lambda(&:array_type?)
47
47
  when :hash
48
- ->(node) { node.hash_type? }
48
+ lambda(&:hash_type?)
49
49
  when :heredoc
50
50
  ->(node) { heredoc_node?(node) }
51
51
  when :method_call
52
- ->(node) { node.call_type? }
52
+ lambda(&:call_type?)
53
53
  else
54
- raise ArgumentError, "Unknown foldable type: #{type.inspect}. " \
55
- "Valid foldable types are: #{FOLDABLE_TYPES.join(', ')}."
54
+ raise Warning, "Unknown foldable type: #{type.inspect}. " \
55
+ "Valid foldable types are: #{FOLDABLE_TYPES.join(', ')}."
56
56
  end
57
57
  end
58
58
  end
@@ -65,8 +65,12 @@ module RuboCop
65
65
  inner.begin_pos >= outer.begin_pos && inner.end_pos <= outer.end_pos
66
66
  end
67
67
 
68
- # @deprecated Use processed_source.comment_at_line(line)
68
+ # @deprecated Use processed_source.line_with_comment?(line)
69
69
  def end_of_line_comment(line)
70
+ warn Rainbow(<<~WARNING).yellow, uplevel: 1
71
+ `end_of_line_comment` is deprecated. Use `processed_source.line_with_comment?` instead.
72
+ WARNING
73
+
70
74
  processed_source.line_with_comment?(line)
71
75
  end
72
76
 
@@ -15,7 +15,13 @@ module RuboCop
15
15
  end
16
16
 
17
17
  # @deprecated Use allowed_method? instead
18
- alias ignored_method? allowed_method?
18
+ def ignored_method?
19
+ warn Rainbow(<<~WARNING).yellow, uplevel: 1
20
+ `ignored_method?` is deprecated. Use `allowed_method?` instead.
21
+ WARNING
22
+
23
+ allowed_method?
24
+ end
19
25
 
20
26
  # @api public
21
27
  def allowed_methods
@@ -18,14 +18,26 @@ module RuboCop
18
18
  end
19
19
 
20
20
  # @deprecated Use allowed_line? instead
21
- alias ignored_line? allowed_line?
21
+ def ignored_line?
22
+ warn Rainbow(<<~WARNING).yellow, uplevel: 1
23
+ `ignored_line?` is deprecated. Use `allowed_line?` instead.
24
+ WARNING
25
+
26
+ allowed_line?
27
+ end
22
28
 
23
29
  def matches_allowed_pattern?(line)
24
30
  allowed_patterns.any? { |pattern| Regexp.new(pattern).match?(line) }
25
31
  end
26
32
 
27
- # @deprecated Use matches_allowed_pattern?? instead
28
- alias matches_ignored_pattern? matches_allowed_pattern?
33
+ # @deprecated Use matches_allowed_pattern? instead
34
+ def matches_ignored_pattern?
35
+ warn Rainbow(<<~WARNING).yellow, uplevel: 1
36
+ `matches_ignored_pattern?` is deprecated. Use `matches_allowed_pattern?` instead.
37
+ WARNING
38
+
39
+ matches_allowed_pattern?
40
+ end
29
41
 
30
42
  def allowed_patterns
31
43
  # Since there could be a pattern specified in the default config, merge the two
@@ -4,8 +4,6 @@ module RuboCop
4
4
  module Cop
5
5
  # Representation of an annotation comment in source code (eg. `# TODO: blah blah blah`).
6
6
  class AnnotationComment
7
- extend Forwardable
8
-
9
7
  attr_reader :comment, :margin, :keyword, :colon, :space, :note
10
8
 
11
9
  # @param [Parser::Source::Comment] comment
@@ -36,7 +36,7 @@ module RuboCop
36
36
  length = calculator.calculate
37
37
  return if length <= max_length
38
38
 
39
- location = node.casgn_type? ? node.loc.name : node.source_range
39
+ location = location(node)
40
40
 
41
41
  add_offense(location, message: message(length, max_length)) { self.max = length }
42
42
  end
@@ -54,6 +54,17 @@ module RuboCop
54
54
  foldable_types: count_as_one
55
55
  )
56
56
  end
57
+
58
+ def location(node)
59
+ return node.loc.name if node.casgn_type?
60
+
61
+ if LSP.enabled?
62
+ end_range = node.loc.respond_to?(:name) ? node.loc.name : node.loc.begin
63
+ node.source_range.begin.join(end_range)
64
+ else
65
+ node.source_range
66
+ end
67
+ end
57
68
  end
58
69
  end
59
70
  end
@@ -4,11 +4,15 @@ module RuboCop
4
4
  module Cop
5
5
  # Handles `Max` configuration parameters, especially setting them to an
6
6
  # appropriate value with --auto-gen-config.
7
- # @deprecated Use `exclude_limit ParameterName` instead.
7
+ # @deprecated Use `exclude_limit <ParameterName>` instead.
8
8
  module ConfigurableMax
9
9
  private
10
10
 
11
11
  def max=(value)
12
+ warn Rainbow(<<~WARNING).yellow, uplevel: 1
13
+ `max=` is deprecated. Use `exclude_limit <ParameterName>` instead.
14
+ WARNING
15
+
12
16
  cfg = config_to_allow_offenses
13
17
  cfg[:exclude_limit] ||= {}
14
18
  current_max = cfg[:exclude_limit][max_parameter_name]
@@ -20,7 +20,7 @@ module RuboCop
20
20
 
21
21
  def frozen_string_literal?(node)
22
22
  frozen_string = if target_ruby_version >= 3.0
23
- uninterpolated_string?(node) || frozen_heredoc?(node)
23
+ uninterpolated_string?(node) || uninterpolated_heredoc?(node)
24
24
  else
25
25
  FROZEN_STRING_LITERAL_TYPES_RUBY27.include?(node.type)
26
26
  end
@@ -32,29 +32,39 @@ module RuboCop
32
32
  node.str_type? || (node.dstr_type? && node.each_descendant(:begin).none?)
33
33
  end
34
34
 
35
- def frozen_heredoc?(node)
35
+ def uninterpolated_heredoc?(node)
36
36
  return false unless node.dstr_type? && node.heredoc?
37
37
 
38
38
  node.children.all?(&:str_type?)
39
39
  end
40
+ alias frozen_heredoc? uninterpolated_heredoc?
40
41
 
41
42
  def frozen_string_literals_enabled?
42
43
  ruby_version = processed_source.ruby_version
43
44
  return false unless ruby_version
44
45
 
46
+ # Check if a magic string literal comment specifies what to do
47
+ magic_comments = leading_comment_lines.filter_map { |line| MagicComment.parse(line) }
48
+ if (literal_magic_comment = magic_comments.find(&:frozen_string_literal_specified?))
49
+ return literal_magic_comment.frozen_string_literal?
50
+ end
51
+
45
52
  # TODO: Ruby officially abandon making frozen string literals default
46
53
  # for Ruby 3.0.
47
54
  # https://bugs.ruby-lang.org/issues/11473#note-53
48
- # Whether frozen string literals will be the default after Ruby 3.0
49
- # or not is still unclear as of January 2019.
55
+ # Whether frozen string literals will be the default after Ruby 4.0
56
+ # or not is still unclear as of July 2024.
50
57
  # It may be necessary to add this code in the future.
51
58
  #
52
- # return true if ruby_version >= 3.1
59
+ # return ruby_version >= 4.0 if string_literals_frozen_by_default?.nil?
53
60
  #
54
- # And the above `ruby_version >= 3.1` is undecided whether it will be
55
- # Ruby 3.1, 3.2, 4.0 or others.
56
- # See https://bugs.ruby-lang.org/issues/8976#note-41 for details.
57
- leading_comment_lines.any? { |line| MagicComment.parse(line).frozen_string_literal? }
61
+ # And the above `ruby_version >= 4.0` is undecided whether it will be
62
+ # Ruby 4.0 or others.
63
+ # See https://bugs.ruby-lang.org/issues/20205 for details.
64
+ # For now, offer a configuration value to override behavior is using RUBYOPT.
65
+ return false if string_literals_frozen_by_default?.nil?
66
+
67
+ string_literals_frozen_by_default?
58
68
  end
59
69
 
60
70
  def frozen_string_literals_disabled?
@@ -67,13 +67,14 @@ module RuboCop
67
67
  end
68
68
 
69
69
  def ignore_mixed_hash_shorthand_syntax?(hash_node)
70
- target_ruby_version <= 3.0 || enforced_shorthand_syntax != 'consistent' ||
70
+ target_ruby_version <= 3.0 ||
71
+ !%w[consistent either_consistent].include?(enforced_shorthand_syntax) ||
71
72
  !hash_node.hash_type?
72
73
  end
73
74
 
74
75
  def ignore_hash_shorthand_syntax?(pair_node)
75
76
  target_ruby_version <= 3.0 || enforced_shorthand_syntax == 'either' ||
76
- enforced_shorthand_syntax == 'consistent' ||
77
+ %w[consistent either_consistent].include?(enforced_shorthand_syntax) ||
77
78
  !pair_node.parent.hash_type?
78
79
  end
79
80
 
@@ -172,6 +173,11 @@ module RuboCop
172
173
  hash_value_type_breakdown[:value_needed]&.any?
173
174
  end
174
175
 
176
+ def ignore_explicit_omissible_hash_shorthand_syntax?(hash_value_type_breakdown)
177
+ hash_value_type_breakdown.keys == [:value_omittable] &&
178
+ enforced_shorthand_syntax == 'either_consistent'
179
+ end
180
+
175
181
  def each_omitted_value_pair(hash_value_type_breakdown, &block)
176
182
  hash_value_type_breakdown[:value_omitted]&.each(&block)
177
183
  end
@@ -198,6 +204,7 @@ module RuboCop
198
204
 
199
205
  def no_mixed_shorthand_syntax_check(hash_value_type_breakdown)
200
206
  return if hash_with_values_that_cant_be_omitted?(hash_value_type_breakdown)
207
+ return if ignore_explicit_omissible_hash_shorthand_syntax?(hash_value_type_breakdown)
201
208
 
202
209
  each_omittable_value_pair(hash_value_type_breakdown) do |pair_node|
203
210
  hash_key_source = pair_node.key.source
@@ -91,8 +91,13 @@ module RuboCop
91
91
  end
92
92
 
93
93
  def uri_regexp
94
- @uri_regexp ||=
95
- URI::DEFAULT_PARSER.make_regexp(config.for_cop('Layout/LineLength')['URISchemes'])
94
+ @uri_regexp ||= begin
95
+ # Ruby 3.4 changes the default parser to RFC3986 which warns on make_regexp.
96
+ # Additionally, the RFC2396_PARSER alias is only available on 3.4 for now.
97
+ # Extra info at https://github.com/ruby/uri/issues/118
98
+ parser = defined?(URI::RFC2396_PARSER) ? URI::RFC2396_PARSER : URI::DEFAULT_PARSER
99
+ parser.make_regexp(config.for_cop('Layout/LineLength')['URISchemes'])
100
+ end
96
101
  end
97
102
 
98
103
  def valid_uri?(uri_ish_string)
@@ -49,13 +49,13 @@ module RuboCop
49
49
 
50
50
  return unless complexity > max
51
51
 
52
- msg = format(self.class::MSG,
53
- method: method_name,
54
- complexity: complexity,
55
- abc_vector: abc_vector,
56
- max: max)
52
+ msg = format(
53
+ self.class::MSG,
54
+ method: method_name, complexity: complexity, abc_vector: abc_vector, max: max
55
+ )
56
+ location = location(node)
57
57
 
58
- add_offense(node, message: msg) { self.max = complexity.ceil }
58
+ add_offense(location, message: msg) { self.max = complexity.ceil }
59
59
  end
60
60
 
61
61
  def complexity(body)
@@ -69,6 +69,15 @@ module RuboCop
69
69
  end
70
70
  score
71
71
  end
72
+
73
+ def location(node)
74
+ if LSP.enabled?
75
+ end_range = node.loc.respond_to?(:name) ? node.loc.name : node.loc.begin
76
+ node.source_range.begin.join(end_range)
77
+ else
78
+ node.source_range
79
+ end
80
+ end
72
81
  end
73
82
  end
74
83
  end
@@ -15,7 +15,7 @@ module RuboCop
15
15
  parent = node.parent
16
16
 
17
17
  parent&.send_type? && parent.arguments.include?(node) &&
18
- !parent.parenthesized? && parent&.block_literal?
18
+ !parent.parenthesized? && parent.block_literal?
19
19
  end
20
20
 
21
21
  # Override to determine values that are invalid in a percent array
@@ -18,6 +18,10 @@ module RuboCop
18
18
 
19
19
  # @deprecated Use ResbodyNode#exceptions instead
20
20
  def rescued_exceptions(resbody)
21
+ warn Rainbow(<<~WARNING).yellow, uplevel: 1
22
+ `rescued_exceptions` is deprecated. Use `ResbodyNode#exceptions` instead.
23
+ WARNING
24
+
21
25
  rescue_group, = *resbody
22
26
  if rescue_group
23
27
  rescue_group.values
@@ -14,7 +14,7 @@ module RuboCop
14
14
  def_node_matcher :empty_condition?, '(begin)'
15
15
 
16
16
  # @!method setter_method?(node)
17
- def_node_matcher :setter_method?, '[(send ...) setter_method?]'
17
+ def_node_matcher :setter_method?, '[(call ...) setter_method?]'
18
18
 
19
19
  # @!method safe_assignment?(node)
20
20
  def_node_matcher :safe_assignment?, '(begin {equals_asgn? #setter_method?})'
@@ -5,7 +5,6 @@ module RuboCop
5
5
  # Common functionality for modifier cops.
6
6
  module StatementModifier
7
7
  include LineLengthHelp
8
- include RangeHelp
9
8
 
10
9
  private
11
10
 
@@ -65,7 +64,9 @@ module RuboCop
65
64
  end
66
65
 
67
66
  def method_source(if_body)
68
- range_between(if_body.source_range.begin_pos, if_body.loc.selector.end_pos).source
67
+ end_range = if_body.implicit_call? ? if_body.loc.dot.end : if_body.loc.selector
68
+
69
+ if_body.source_range.begin.join(end_range).source
69
70
  end
70
71
 
71
72
  def first_line_comment(node)
@@ -16,6 +16,18 @@ module RuboCop
16
16
  !/" | \\[^'\\] | \#[@{$]/x.match?(src)
17
17
  end
18
18
  end
19
+
20
+ def preferred_string_literal
21
+ enforce_double_quotes? ? '""' : "''"
22
+ end
23
+
24
+ def enforce_double_quotes?
25
+ string_literals_config['EnforcedStyle'] == 'double_quotes'
26
+ end
27
+
28
+ def string_literals_config
29
+ config.for_cop('Style/StringLiterals')
30
+ end
19
31
  end
20
32
  end
21
33
  end