rubocop 1.80.2 → 1.86.1

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 (310) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +2 -2
  4. data/config/default.yml +170 -19
  5. data/config/obsoletion.yml +9 -0
  6. data/lib/rubocop/cache_config.rb +29 -0
  7. data/lib/rubocop/cli/command/auto_generate_config.rb +3 -3
  8. data/lib/rubocop/cli/command/lsp.rb +1 -1
  9. data/lib/rubocop/cli/command/mcp.rb +19 -0
  10. data/lib/rubocop/cli/command/show_cops.rb +2 -2
  11. data/lib/rubocop/cli/command/show_docs_url.rb +1 -1
  12. data/lib/rubocop/cli.rb +28 -6
  13. data/lib/rubocop/comment_config.rb +62 -17
  14. data/lib/rubocop/config.rb +14 -10
  15. data/lib/rubocop/config_finder.rb +1 -1
  16. data/lib/rubocop/config_loader.rb +20 -21
  17. data/lib/rubocop/config_loader_resolver.rb +9 -7
  18. data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -2
  19. data/lib/rubocop/config_store.rb +6 -1
  20. data/lib/rubocop/config_validator.rb +1 -1
  21. data/lib/rubocop/cop/autocorrect_logic.rb +8 -4
  22. data/lib/rubocop/cop/bundler/gem_version.rb +28 -28
  23. data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -2
  24. data/lib/rubocop/cop/correctors/alignment_corrector.rb +22 -6
  25. data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -1
  26. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  27. data/lib/rubocop/cop/documentation.rb +2 -3
  28. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -2
  29. data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
  30. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +10 -5
  31. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +8 -8
  32. data/lib/rubocop/cop/internal_affairs/itblock_handler.rb +69 -0
  33. data/lib/rubocop/cop/internal_affairs/location_exists.rb +28 -2
  34. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +9 -9
  35. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
  36. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +3 -1
  37. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
  38. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +4 -4
  39. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  40. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -2
  41. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  42. data/lib/rubocop/cop/layout/case_indentation.rb +3 -1
  43. data/lib/rubocop/cop/layout/class_structure.rb +13 -6
  44. data/lib/rubocop/cop/layout/dot_position.rb +2 -2
  45. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +12 -2
  46. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +31 -13
  47. data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +1 -1
  48. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
  49. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +12 -2
  50. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +16 -2
  51. data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +16 -2
  52. data/lib/rubocop/cop/layout/end_alignment.rb +8 -1
  53. data/lib/rubocop/cop/layout/first_argument_indentation.rb +34 -1
  54. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +26 -0
  55. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +7 -1
  56. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +25 -25
  57. data/lib/rubocop/cop/layout/hash_alignment.rb +3 -6
  58. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
  59. data/lib/rubocop/cop/layout/heredoc_indentation.rb +33 -3
  60. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  61. data/lib/rubocop/cop/layout/indentation_width.rb +111 -7
  62. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  63. data/lib/rubocop/cop/layout/line_length.rb +26 -9
  64. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +57 -57
  65. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +9 -2
  66. data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
  67. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +56 -56
  68. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +204 -39
  69. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +6 -4
  70. data/lib/rubocop/cop/layout/parameter_alignment.rb +1 -1
  71. data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -1
  72. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +13 -3
  73. data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
  74. data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
  75. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
  76. data/lib/rubocop/cop/layout/space_around_keyword.rb +4 -2
  77. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +9 -8
  78. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  79. data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -3
  80. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +3 -2
  81. data/lib/rubocop/cop/lint/constant_reassignment.rb +59 -9
  82. data/lib/rubocop/cop/lint/constant_resolution.rb +1 -1
  83. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +14 -8
  84. data/lib/rubocop/cop/lint/data_define_override.rb +63 -0
  85. data/lib/rubocop/cop/lint/debugger.rb +0 -2
  86. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +4 -1
  87. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
  88. data/lib/rubocop/cop/lint/duplicate_methods.rb +111 -12
  89. data/lib/rubocop/cop/lint/else_layout.rb +19 -0
  90. data/lib/rubocop/cop/lint/empty_block.rb +1 -1
  91. data/lib/rubocop/cop/lint/empty_conditional_body.rb +6 -1
  92. data/lib/rubocop/cop/lint/empty_in_pattern.rb +8 -1
  93. data/lib/rubocop/cop/lint/empty_interpolation.rb +11 -0
  94. data/lib/rubocop/cop/lint/empty_when.rb +8 -1
  95. data/lib/rubocop/cop/lint/float_comparison.rb +1 -1
  96. data/lib/rubocop/cop/lint/interpolation_check.rb +7 -2
  97. data/lib/rubocop/cop/lint/literal_as_condition.rb +5 -1
  98. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  99. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +16 -6
  100. data/lib/rubocop/cop/lint/next_without_accumulator.rb +2 -0
  101. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +4 -0
  102. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -1
  103. data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
  104. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +23 -9
  105. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +0 -9
  106. data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -2
  107. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +23 -6
  108. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -2
  109. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
  110. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -0
  111. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +7 -1
  112. data/lib/rubocop/cop/lint/self_assignment.rb +10 -2
  113. data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
  114. data/lib/rubocop/cop/lint/struct_new_override.rb +17 -1
  115. data/lib/rubocop/cop/lint/syntax.rb +25 -1
  116. data/lib/rubocop/cop/lint/to_json.rb +12 -16
  117. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -0
  118. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -0
  119. data/lib/rubocop/cop/lint/unreachable_code.rb +5 -3
  120. data/lib/rubocop/cop/lint/unreachable_pattern_branch.rb +113 -0
  121. data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
  122. data/lib/rubocop/cop/lint/useless_assignment.rb +45 -17
  123. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +4 -4
  124. data/lib/rubocop/cop/lint/useless_default_value_argument.rb +2 -0
  125. data/lib/rubocop/cop/lint/useless_or.rb +15 -2
  126. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +24 -9
  127. data/lib/rubocop/cop/lint/void.rb +39 -12
  128. data/lib/rubocop/cop/message_annotator.rb +1 -1
  129. data/lib/rubocop/cop/metrics/block_nesting.rb +23 -0
  130. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
  131. data/lib/rubocop/cop/migration/department_name.rb +12 -1
  132. data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
  133. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +4 -6
  134. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  135. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +5 -5
  136. data/lib/rubocop/cop/mixin/hash_transform_method/autocorrection.rb +63 -0
  137. data/lib/rubocop/cop/mixin/hash_transform_method.rb +10 -60
  138. data/lib/rubocop/cop/mixin/line_length_help.rb +21 -2
  139. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  140. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
  141. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
  142. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
  143. data/lib/rubocop/cop/mixin/statement_modifier.rb +0 -6
  144. data/lib/rubocop/cop/mixin/trailing_comma.rb +8 -5
  145. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  146. data/lib/rubocop/cop/naming/method_name.rb +4 -2
  147. data/lib/rubocop/cop/naming/predicate_method.rb +27 -4
  148. data/lib/rubocop/cop/naming/predicate_prefix.rb +11 -11
  149. data/lib/rubocop/cop/offense.rb +9 -1
  150. data/lib/rubocop/cop/registry.rb +20 -13
  151. data/lib/rubocop/cop/security/eval.rb +15 -2
  152. data/lib/rubocop/cop/security/json_load.rb +33 -11
  153. data/lib/rubocop/cop/style/access_modifier_declarations.rb +15 -4
  154. data/lib/rubocop/cop/style/accessor_grouping.rb +4 -2
  155. data/lib/rubocop/cop/style/alias.rb +4 -1
  156. data/lib/rubocop/cop/style/and_or.rb +1 -0
  157. data/lib/rubocop/cop/style/arguments_forwarding.rb +25 -7
  158. data/lib/rubocop/cop/style/array_intersect.rb +2 -2
  159. data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +47 -0
  160. data/lib/rubocop/cop/style/array_join.rb +4 -2
  161. data/lib/rubocop/cop/style/ascii_comments.rb +6 -3
  162. data/lib/rubocop/cop/style/attr.rb +5 -2
  163. data/lib/rubocop/cop/style/bare_percent_literals.rb +4 -3
  164. data/lib/rubocop/cop/style/begin_block.rb +3 -1
  165. data/lib/rubocop/cop/style/block_delimiters.rb +27 -34
  166. data/lib/rubocop/cop/style/case_equality.rb +15 -13
  167. data/lib/rubocop/cop/style/class_and_module_children.rb +11 -2
  168. data/lib/rubocop/cop/style/collection_compact.rb +36 -16
  169. data/lib/rubocop/cop/style/colon_method_call.rb +3 -1
  170. data/lib/rubocop/cop/style/concat_array_literals.rb +2 -0
  171. data/lib/rubocop/cop/style/conditional_assignment.rb +8 -18
  172. data/lib/rubocop/cop/style/constant_visibility.rb +17 -12
  173. data/lib/rubocop/cop/style/copyright.rb +1 -1
  174. data/lib/rubocop/cop/style/documentation.rb +6 -6
  175. data/lib/rubocop/cop/style/documentation_method.rb +8 -8
  176. data/lib/rubocop/cop/style/double_negation.rb +1 -1
  177. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  178. data/lib/rubocop/cop/style/each_with_object.rb +2 -0
  179. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  180. data/lib/rubocop/cop/style/empty_class_definition.rb +119 -0
  181. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  182. data/lib/rubocop/cop/style/empty_method.rb +0 -6
  183. data/lib/rubocop/cop/style/encoding.rb +7 -1
  184. data/lib/rubocop/cop/style/end_block.rb +3 -1
  185. data/lib/rubocop/cop/style/endless_method.rb +23 -5
  186. data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
  187. data/lib/rubocop/cop/style/file_open.rb +84 -0
  188. data/lib/rubocop/cop/style/float_division.rb +15 -1
  189. data/lib/rubocop/cop/style/for.rb +3 -0
  190. data/lib/rubocop/cop/style/format_string_token.rb +49 -5
  191. data/lib/rubocop/cop/style/global_vars.rb +5 -2
  192. data/lib/rubocop/cop/style/guard_clause.rb +27 -22
  193. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +27 -9
  194. data/lib/rubocop/cop/style/hash_lookup_method.rb +101 -0
  195. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  196. data/lib/rubocop/cop/style/hash_transform_keys.rb +17 -7
  197. data/lib/rubocop/cop/style/hash_transform_values.rb +17 -7
  198. data/lib/rubocop/cop/style/if_inside_else.rb +1 -5
  199. data/lib/rubocop/cop/style/if_unless_modifier.rb +57 -17
  200. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +12 -12
  201. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +4 -1
  202. data/lib/rubocop/cop/style/if_with_semicolon.rb +7 -5
  203. data/lib/rubocop/cop/style/inline_comment.rb +4 -1
  204. data/lib/rubocop/cop/style/ip_addresses.rb +1 -2
  205. data/lib/rubocop/cop/style/lambda_call.rb +8 -8
  206. data/lib/rubocop/cop/style/magic_comment_format.rb +2 -2
  207. data/lib/rubocop/cop/style/map_join.rb +123 -0
  208. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +15 -2
  209. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +17 -4
  210. data/lib/rubocop/cop/style/method_def_parentheses.rb +2 -4
  211. data/lib/rubocop/cop/style/module_member_existence_check.rb +107 -0
  212. data/lib/rubocop/cop/style/multiline_if_then.rb +4 -4
  213. data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -4
  214. data/lib/rubocop/cop/style/mutable_constant.rb +1 -1
  215. data/lib/rubocop/cop/style/negative_array_index.rb +220 -0
  216. data/lib/rubocop/cop/style/nil_comparison.rb +11 -10
  217. data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
  218. data/lib/rubocop/cop/style/non_nil_check.rb +5 -11
  219. data/lib/rubocop/cop/style/not.rb +2 -0
  220. data/lib/rubocop/cop/style/numeric_literals.rb +3 -2
  221. data/lib/rubocop/cop/style/one_class_per_file.rb +115 -0
  222. data/lib/rubocop/cop/style/one_line_conditional.rb +21 -12
  223. data/lib/rubocop/cop/style/operator_method_call.rb +11 -2
  224. data/lib/rubocop/cop/style/parallel_assignment.rb +6 -2
  225. data/lib/rubocop/cop/style/partition_instead_of_double_select.rb +270 -0
  226. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -0
  227. data/lib/rubocop/cop/style/predicate_with_kind.rb +84 -0
  228. data/lib/rubocop/cop/style/preferred_hash_methods.rb +12 -12
  229. data/lib/rubocop/cop/style/proc.rb +3 -2
  230. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  231. data/lib/rubocop/cop/style/reduce_to_hash.rb +184 -0
  232. data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
  233. data/lib/rubocop/cop/style/redundant_begin.rb +3 -3
  234. data/lib/rubocop/cop/style/redundant_condition.rb +5 -2
  235. data/lib/rubocop/cop/style/redundant_each.rb +3 -3
  236. data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
  237. data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
  238. data/lib/rubocop/cop/style/redundant_format.rb +26 -5
  239. data/lib/rubocop/cop/style/redundant_interpolation.rb +11 -2
  240. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +26 -10
  241. data/lib/rubocop/cop/style/redundant_line_continuation.rb +16 -0
  242. data/lib/rubocop/cop/style/redundant_min_max_by.rb +93 -0
  243. data/lib/rubocop/cop/style/redundant_parentheses.rb +26 -22
  244. data/lib/rubocop/cop/style/redundant_percent_q.rb +5 -3
  245. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +9 -0
  246. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
  247. data/lib/rubocop/cop/style/redundant_return.rb +3 -1
  248. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +0 -5
  249. data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
  250. data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +114 -0
  251. data/lib/rubocop/cop/style/reverse_find.rb +51 -0
  252. data/lib/rubocop/cop/style/safe_navigation.rb +7 -7
  253. data/lib/rubocop/cop/style/select_by_kind.rb +158 -0
  254. data/lib/rubocop/cop/style/select_by_range.rb +197 -0
  255. data/lib/rubocop/cop/style/select_by_regexp.rb +51 -21
  256. data/lib/rubocop/cop/style/semicolon.rb +25 -7
  257. data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
  258. data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -1
  259. data/lib/rubocop/cop/style/single_line_methods.rb +3 -1
  260. data/lib/rubocop/cop/style/sole_nested_conditional.rb +8 -1
  261. data/lib/rubocop/cop/style/special_global_vars.rb +6 -1
  262. data/lib/rubocop/cop/style/super_arguments.rb +2 -2
  263. data/lib/rubocop/cop/style/symbol_proc.rb +4 -3
  264. data/lib/rubocop/cop/style/tally_method.rb +181 -0
  265. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
  266. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
  267. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -0
  268. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +11 -11
  269. data/lib/rubocop/cop/style/unless_else.rb +10 -9
  270. data/lib/rubocop/cop/style/yoda_expression.rb +1 -1
  271. data/lib/rubocop/cop/team.rb +4 -4
  272. data/lib/rubocop/cop/util.rb +2 -3
  273. data/lib/rubocop/cop/utils/format_string.rb +10 -0
  274. data/lib/rubocop/cop/variable_force/branch.rb +30 -6
  275. data/lib/rubocop/cops_documentation_generator.rb +4 -4
  276. data/lib/rubocop/directive_comment.rb +48 -4
  277. data/lib/rubocop/formatter/clang_style_formatter.rb +5 -2
  278. data/lib/rubocop/formatter/disabled_config_formatter.rb +2 -1
  279. data/lib/rubocop/formatter/formatter_set.rb +2 -2
  280. data/lib/rubocop/formatter/junit_formatter.rb +1 -1
  281. data/lib/rubocop/formatter/simple_text_formatter.rb +0 -2
  282. data/lib/rubocop/formatter/tap_formatter.rb +5 -2
  283. data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
  284. data/lib/rubocop/formatter.rb +22 -21
  285. data/lib/rubocop/lsp/diagnostic.rb +18 -33
  286. data/lib/rubocop/lsp/disable_comment_edits.rb +135 -0
  287. data/lib/rubocop/lsp/routes.rb +12 -5
  288. data/lib/rubocop/lsp/runtime.rb +13 -3
  289. data/lib/rubocop/lsp/stdin_runner.rb +8 -17
  290. data/lib/rubocop/magic_comment.rb +20 -0
  291. data/lib/rubocop/mcp/server.rb +200 -0
  292. data/lib/rubocop/options.rb +10 -1
  293. data/lib/rubocop/path_util.rb +14 -2
  294. data/lib/rubocop/plugin/loader.rb +1 -1
  295. data/lib/rubocop/rake_task.rb +1 -1
  296. data/lib/rubocop/remote_config.rb +10 -8
  297. data/lib/rubocop/result_cache.rb +60 -37
  298. data/lib/rubocop/rspec/cop_helper.rb +8 -0
  299. data/lib/rubocop/rspec/shared_contexts.rb +18 -5
  300. data/lib/rubocop/rspec/support.rb +2 -1
  301. data/lib/rubocop/runner.rb +12 -3
  302. data/lib/rubocop/server/cache.rb +6 -29
  303. data/lib/rubocop/server/core.rb +2 -0
  304. data/lib/rubocop/target_finder.rb +1 -1
  305. data/lib/rubocop/target_ruby.rb +31 -14
  306. data/lib/rubocop/version.rb +2 -2
  307. data/lib/rubocop.rb +20 -0
  308. data/lib/ruby_lsp/rubocop/addon.rb +23 -8
  309. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +49 -15
  310. metadata +33 -9
@@ -45,17 +45,6 @@ module RuboCop
45
45
  # ok
46
46
  #
47
47
  # # bad
48
- # if something
49
- # foo || raise('exception')
50
- # else
51
- # ok
52
- # end
53
- #
54
- # # good
55
- # foo || raise('exception') if something
56
- # ok
57
- #
58
- # # bad
59
48
  # define_method(:test) do
60
49
  # if something
61
50
  # work
@@ -207,7 +196,7 @@ module RuboCop
207
196
  end
208
197
  end
209
198
 
210
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
199
+ # rubocop:disable Metrics/AbcSize
211
200
  def autocorrect(corrector, node, condition, replacement, guard)
212
201
  corrector.replace(node.loc.keyword.join(condition.source_range), replacement)
213
202
 
@@ -216,10 +205,10 @@ module RuboCop
216
205
 
217
206
  corrector.replace(node.loc.begin, "\n") if node.then?
218
207
 
219
- if if_branch&.send_type? && heredoc?(if_branch.last_argument)
220
- autocorrect_heredoc_argument(corrector, node, if_branch, else_branch, guard)
221
- elsif else_branch&.send_type? && heredoc?(else_branch.last_argument)
222
- autocorrect_heredoc_argument(corrector, node, else_branch, if_branch, guard)
208
+ if (if_heredoc = find_heredoc_argument(if_branch))
209
+ autocorrect_heredoc_argument(corrector, node, if_heredoc, else_branch, guard)
210
+ elsif (else_heredoc = find_heredoc_argument(else_branch))
211
+ autocorrect_heredoc_argument(corrector, node, else_heredoc, if_branch, guard)
223
212
  else
224
213
  corrector.remove(node.loc.end)
225
214
  return unless node.else?
@@ -228,22 +217,38 @@ module RuboCop
228
217
  corrector.remove(range_of_branch_to_remove(node, guard))
229
218
  end
230
219
  end
231
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
220
+ # rubocop:enable Metrics/AbcSize
232
221
 
233
222
  def heredoc?(argument)
234
223
  argument.respond_to?(:heredoc?) && argument.heredoc?
235
224
  end
236
225
 
237
- def autocorrect_heredoc_argument(corrector, node, heredoc_branch, leave_branch, guard)
226
+ def find_heredoc_argument(node)
227
+ return unless node
228
+
229
+ node = node.children.first while node.begin_type?
230
+ return node if heredoc?(node)
231
+ return unless node.call_type?
232
+
233
+ node.arguments.reverse_each do |argument|
234
+ heredoc_argument = find_heredoc_argument(argument)
235
+ return heredoc_argument if heredoc_argument
236
+ end
237
+
238
+ find_heredoc_argument(node.receiver)
239
+ end
240
+
241
+ def autocorrect_heredoc_argument(corrector, node, heredoc_node, leave_branch, guard)
238
242
  remove_whole_lines(corrector, node.loc.end)
239
243
  return unless node.else?
240
244
 
241
- remove_whole_lines(corrector, leave_branch.source_range)
245
+ if leave_branch
246
+ remove_whole_lines(corrector, leave_branch.source_range)
247
+ corrector.insert_after(heredoc_node.loc.heredoc_end, "\n#{leave_branch.source}")
248
+ end
249
+
242
250
  remove_whole_lines(corrector, node.loc.else)
243
251
  remove_whole_lines(corrector, range_of_branch_to_remove(node, guard))
244
- corrector.insert_after(
245
- heredoc_branch.last_argument.loc.heredoc_end, "\n#{leave_branch.source}"
246
- )
247
252
  end
248
253
 
249
254
  def range_of_branch_to_remove(node, guard)
@@ -6,8 +6,13 @@ module RuboCop
6
6
  # Checks for presence or absence of braces around hash literal as a last
7
7
  # array item depending on configuration.
8
8
  #
9
- # NOTE: This cop will ignore arrays where all items are hashes, regardless of
10
- # EnforcedStyle.
9
+ # NOTE: This cop will ignore arrays where multiple items are all hashes,
10
+ # regardless of `EnforcedStyle`.
11
+ #
12
+ # [source,ruby]
13
+ # ----
14
+ # [{ one: 1 }, { two: 2 }]
15
+ # ----
11
16
  #
12
17
  # @example EnforcedStyle: braces (default)
13
18
  # # bad
@@ -16,8 +21,11 @@ module RuboCop
16
21
  # # good
17
22
  # [1, 2, { one: 1, two: 2 }]
18
23
  #
24
+ # # bad
25
+ # [one: 1, two: 2]
26
+ #
19
27
  # # good
20
- # [{ one: 1 }, { two: 2 }]
28
+ # [{ one: 1, two: 2 }]
21
29
  #
22
30
  # @example EnforcedStyle: no_braces
23
31
  # # bad
@@ -26,8 +34,11 @@ module RuboCop
26
34
  # # good
27
35
  # [1, 2, one: 1, two: 2]
28
36
  #
37
+ # # bad
38
+ # [{ one: 1, two: 2 }]
39
+ #
29
40
  # # good
30
- # [{ one: 1 }, { two: 2 }]
41
+ # [one: 1, two: 2]
31
42
  class HashAsLastArrayItem < Base
32
43
  include RangeHelp
33
44
  include ConfigurableEnforcedStyle
@@ -36,7 +47,7 @@ module RuboCop
36
47
  def on_hash(node)
37
48
  return if node.children.first&.kwsplat_type?
38
49
  return unless (array = containing_array(node))
39
- return unless last_array_item?(array, node) && explicit_array?(array)
50
+ return unless expected_braced_last_array_item?(array, node) && explicit_array?(array)
40
51
 
41
52
  if braces_style?
42
53
  check_braces(node)
@@ -52,10 +63,12 @@ module RuboCop
52
63
  parent if parent&.array_type?
53
64
  end
54
65
 
55
- def last_array_item?(array, node)
56
- return false if array.child_nodes.all?(&:hash_type?)
66
+ def expected_braced_last_array_item?(array, node)
67
+ return false if array.each_value.all? do |node|
68
+ node.hash_type? && (braces_style? ? node.braces? : !node.braces?)
69
+ end
57
70
 
58
- array.children.last.equal?(node)
71
+ !array.values[-2]&.hash_type? && array.values.last.equal?(node)
59
72
  end
60
73
 
61
74
  def explicit_array?(array)
@@ -67,7 +80,12 @@ module RuboCop
67
80
  return if node.braces?
68
81
 
69
82
  add_offense(node, message: 'Wrap hash in `{` and `}`.') do |corrector|
70
- corrector.wrap(node, '{', '}')
83
+ if node.single_line? || same_line?(node, node.parent)
84
+ corrector.wrap(node, '{', '}')
85
+ else
86
+ indent = indent(node)
87
+ corrector.wrap(node, "{\n#{indent}", "\n#{indent}}")
88
+ end
71
89
  end
72
90
  end
73
91
 
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Enforces the use of either `Hash#[]` or `Hash#fetch` for hash lookup.
7
+ #
8
+ # This cop can be configured to prefer either bracket-style (`[]`)
9
+ # or fetch-style lookup. It is disabled by default.
10
+ #
11
+ # When enforcing `fetch` style, only single-argument bracket access is flagged.
12
+ # When enforcing `brackets` style, only `fetch` calls with a single key
13
+ # argument are flagged (not those with default values or blocks).
14
+ #
15
+ # @safety
16
+ # This cop is unsafe because `Hash#[]` and `Hash#fetch` have different
17
+ # semantics. `Hash#[]` returns `nil` for missing keys, while `Hash#fetch`
18
+ # raises a `KeyError`. Replacing one with the other can change program
19
+ # behavior in cases where the key is missing.
20
+ #
21
+ # Additionally, it cannot be guaranteed that the receiver is a `Hash`
22
+ # or responds to the replacement method.
23
+ #
24
+ # @example EnforcedStyle: brackets (default)
25
+ # # bad
26
+ # hash.fetch(key)
27
+ #
28
+ # # good
29
+ # hash[key]
30
+ #
31
+ # # good - fetch with default value is allowed
32
+ # hash.fetch(key, default)
33
+ #
34
+ # # good - fetch with block is allowed
35
+ # hash.fetch(key) { default }
36
+ #
37
+ # @example EnforcedStyle: fetch
38
+ # # bad
39
+ # hash[key]
40
+ #
41
+ # # good
42
+ # hash.fetch(key)
43
+ #
44
+ # @example AllowedReceivers: ['Rails.cache']
45
+ # # good
46
+ # Rails.cache.fetch(name, options) { block }
47
+ #
48
+ class HashLookupMethod < Base
49
+ include ConfigurableEnforcedStyle
50
+ include AllowedReceivers
51
+ extend AutoCorrector
52
+
53
+ BRACKET_MSG = 'Use `Hash#[]` instead of `Hash#fetch`.'
54
+ FETCH_MSG = 'Use `Hash#fetch` instead of `Hash#[]`.'
55
+
56
+ RESTRICT_ON_SEND = %i[[] fetch].freeze
57
+
58
+ def on_send(node)
59
+ return if (receiver = node.receiver) && allowed_receiver?(receiver)
60
+
61
+ if offense_for_brackets?(node)
62
+ add_offense(node.loc.selector, message: BRACKET_MSG) do |corrector|
63
+ correct_fetch_to_brackets(corrector, node)
64
+ end
65
+ elsif offense_for_fetch?(node)
66
+ add_offense(node, message: FETCH_MSG) do |corrector|
67
+ correct_brackets_to_fetch(corrector, node)
68
+ end
69
+ end
70
+ end
71
+ alias on_csend on_send
72
+
73
+ private
74
+
75
+ def offense_for_brackets?(node)
76
+ style == :brackets && node.receiver && node.method?(:fetch) && node.arguments.one? &&
77
+ !node.block_literal?
78
+ end
79
+
80
+ def offense_for_fetch?(node)
81
+ style == :fetch && node.method?(:[]) && node.arguments.one?
82
+ end
83
+
84
+ def correct_fetch_to_brackets(corrector, node)
85
+ receiver = node.receiver.source
86
+ key = node.first_argument.source
87
+ replacement = "#{receiver}[#{key}]"
88
+ replacement = "(#{replacement})" if node.csend_type?
89
+ corrector.replace(node, replacement)
90
+ end
91
+
92
+ def correct_brackets_to_fetch(corrector, node)
93
+ receiver = node.receiver.source
94
+ key = node.first_argument.source
95
+ operator = node.csend_type? ? '&.' : '.'
96
+ corrector.replace(node, "#{receiver}#{operator}fetch(#{key})")
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -212,7 +212,7 @@ module RuboCop
212
212
  end
213
213
 
214
214
  def word_symbol_pair?(pair)
215
- return false unless pair.key.type?(:sym, :dsym)
215
+ return false unless pair.key.any_sym_type?
216
216
 
217
217
  acceptable_19_syntax_symbol?(pair.key.source)
218
218
  end
@@ -11,9 +11,11 @@ module RuboCop
11
11
  # (`transform_keys` was added in Ruby 2.5.)
12
12
  #
13
13
  # @safety
14
- # This cop is unsafe, as it can produce false positives if we are
15
- # transforming an enumerable of key-value-like pairs that isn't actually
16
- # a hash, e.g.: `[[k1, v1], [k2, v2], ...]`
14
+ # This cop identifies the receiver as a hash by checking for literal hash
15
+ # syntax and common methods that are known to return hashes (e.g. `to_h`,
16
+ # `merge`, `invert`, `group_by`, etc.). However, it is unsafe because it
17
+ # is possible for a custom class to define one of these methods and return
18
+ # something other than a hash.
17
19
  #
18
20
  # @example
19
21
  # # bad
@@ -21,10 +23,18 @@ module RuboCop
21
23
  # Hash[{a: 1, b: 2}.collect { |k, v| [foo(k), v] }]
22
24
  # {a: 1, b: 2}.map { |k, v| [k.to_s, v] }.to_h
23
25
  # {a: 1, b: 2}.to_h { |k, v| [k.to_s, v] }
26
+ # foo.to_h.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
27
+ # foo.merge(bar).map { |k, v| [k.to_s, v] }.to_h
24
28
  #
25
29
  # # good
26
30
  # {a: 1, b: 2}.transform_keys { |k| foo(k) }
27
31
  # {a: 1, b: 2}.transform_keys { |k| k.to_s }
32
+ # foo.to_h.transform_keys { |k| k.to_sym }
33
+ # foo.merge(bar).transform_keys { |k| k.to_s }
34
+ #
35
+ # # Won't register an offense - receiver is not known to be a hash
36
+ # foo.bar.each_with_object({}) { |(k, v), h| h[k.to_s] = v }
37
+ # baz.map { |k, v| [k.to_s, v] }.to_h
28
38
  class HashTransformKeys < Base
29
39
  include HashTransformMethod
30
40
  extend AutoCorrector
@@ -35,7 +45,7 @@ module RuboCop
35
45
  # @!method on_bad_each_with_object(node)
36
46
  def_node_matcher :on_bad_each_with_object, <<~PATTERN
37
47
  (block
38
- (call !#array_receiver? :each_with_object (hash))
48
+ (call #hash_receiver? :each_with_object (hash))
39
49
  (args
40
50
  (mlhs
41
51
  (arg $_)
@@ -50,7 +60,7 @@ module RuboCop
50
60
  (const _ :Hash)
51
61
  :[]
52
62
  (block
53
- (call !#array_receiver? {:map :collect})
63
+ (call #hash_receiver? {:map :collect})
54
64
  (args
55
65
  (arg $_)
56
66
  (arg _val))
@@ -61,7 +71,7 @@ module RuboCop
61
71
  def_node_matcher :on_bad_map_to_h, <<~PATTERN
62
72
  (call
63
73
  (block
64
- (call !#array_receiver? {:map :collect})
74
+ (call #hash_receiver? {:map :collect})
65
75
  (args
66
76
  (arg $_)
67
77
  (arg _val))
@@ -72,7 +82,7 @@ module RuboCop
72
82
  # @!method on_bad_to_h(node)
73
83
  def_node_matcher :on_bad_to_h, <<~PATTERN
74
84
  (block
75
- (call !#array_receiver? :to_h)
85
+ (call #hash_receiver? :to_h)
76
86
  (args
77
87
  (arg $_)
78
88
  (arg _val))
@@ -9,9 +9,11 @@ module RuboCop
9
9
  # call to `transform_values` instead.
10
10
  #
11
11
  # @safety
12
- # This cop is unsafe, as it can produce false positives if we are
13
- # transforming an enumerable of key-value-like pairs that isn't actually
14
- # a hash, e.g.: `[[k1, v1], [k2, v2], ...]`
12
+ # This cop identifies the receiver as a hash by checking for literal hash
13
+ # syntax and common methods that are known to return hashes (e.g. `to_h`,
14
+ # `merge`, `invert`, `group_by`, etc.). However, it is unsafe because it
15
+ # is possible for a custom class to define one of these methods and return
16
+ # something other than a hash.
15
17
  #
16
18
  # @example
17
19
  # # bad
@@ -19,10 +21,18 @@ module RuboCop
19
21
  # Hash[{a: 1, b: 2}.collect { |k, v| [k, foo(v)] }]
20
22
  # {a: 1, b: 2}.map { |k, v| [k, v * v] }.to_h
21
23
  # {a: 1, b: 2}.to_h { |k, v| [k, v * v] }
24
+ # foo.to_h.each_with_object({}) { |(k, v), h| h[k] = foo(v) }
25
+ # foo.merge(bar).map { |k, v| [k, v.to_s] }.to_h
22
26
  #
23
27
  # # good
24
28
  # {a: 1, b: 2}.transform_values { |v| foo(v) }
25
29
  # {a: 1, b: 2}.transform_values { |v| v * v }
30
+ # foo.to_h.transform_values { |v| foo(v) }
31
+ # foo.merge(bar).transform_values { |v| v.to_s }
32
+ #
33
+ # # Won't register an offense - receiver is not known to be a hash
34
+ # foo.bar.each_with_object({}) { |(k, v), h| h[k] = v.to_s }
35
+ # baz.map { |k, v| [k, v.to_s] }.to_h
26
36
  class HashTransformValues < Base
27
37
  include HashTransformMethod
28
38
  extend AutoCorrector
@@ -33,7 +43,7 @@ module RuboCop
33
43
  # @!method on_bad_each_with_object(node)
34
44
  def_node_matcher :on_bad_each_with_object, <<~PATTERN
35
45
  (block
36
- (call !#array_receiver? :each_with_object (hash))
46
+ (call #hash_receiver? :each_with_object (hash))
37
47
  (args
38
48
  (mlhs
39
49
  (arg _key)
@@ -48,7 +58,7 @@ module RuboCop
48
58
  (const _ :Hash)
49
59
  :[]
50
60
  (block
51
- (call !#array_receiver? {:map :collect})
61
+ (call #hash_receiver? {:map :collect})
52
62
  (args
53
63
  (arg _key)
54
64
  (arg $_))
@@ -59,7 +69,7 @@ module RuboCop
59
69
  def_node_matcher :on_bad_map_to_h, <<~PATTERN
60
70
  (call
61
71
  (block
62
- (call !#array_receiver? {:map :collect})
72
+ (call #hash_receiver? {:map :collect})
63
73
  (args
64
74
  (arg _key)
65
75
  (arg $_))
@@ -70,7 +80,7 @@ module RuboCop
70
80
  # @!method on_bad_to_h(node)
71
81
  def_node_matcher :on_bad_to_h, <<~PATTERN
72
82
  (block
73
- (call !#array_receiver? :to_h)
83
+ (call #hash_receiver? :to_h)
74
84
  (args
75
85
  (arg _key)
76
86
  (arg $_))
@@ -85,7 +85,7 @@ module RuboCop
85
85
  private
86
86
 
87
87
  def autocorrect(corrector, node)
88
- if then?(node)
88
+ if node.then?
89
89
  # If the nested `if` is a then node, correct it first,
90
90
  # then the next pass will use `correct_to_elsif_from_if_inside_else_form`
91
91
  IfThenCorrector.new(node, indentation: 0).call(corrector)
@@ -124,10 +124,6 @@ module RuboCop
124
124
  corrector.remove(range_by_whole_lines(find_end_range(node), include_final_newline: true))
125
125
  end
126
126
 
127
- def then?(node)
128
- node.loc.begin&.source == 'then'
129
- end
130
-
131
127
  def find_end_range(node)
132
128
  end_range = node.loc.end
133
129
  return end_range if end_range
@@ -71,7 +71,8 @@ module RuboCop
71
71
  # if short_condition # a long comment that makes it too long if it were just a single line
72
72
  # do_something
73
73
  # end
74
- class IfUnlessModifier < Base
74
+ #
75
+ class IfUnlessModifier < Base # rubocop:disable Metrics/ClassLength
75
76
  include StatementModifier
76
77
  include LineLengthHelp
77
78
  include AllowedPattern
@@ -88,9 +89,9 @@ module RuboCop
88
89
  [Style::SoleNestedConditional]
89
90
  end
90
91
 
91
- # rubocop:disable Metrics/AbcSize
92
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
92
93
  def on_if(node)
93
- return if endless_method?(node.body)
94
+ return if endless_method?(node.body) || node.ancestors.any?(&:dstr_type?)
94
95
 
95
96
  condition = node.condition
96
97
  return if defined_nodes(condition).any? { |n| defined_argument_is_undefined?(node, n) } ||
@@ -100,12 +101,13 @@ module RuboCop
100
101
 
101
102
  add_offense(node.loc.keyword, message: format(msg, keyword: node.keyword)) do |corrector|
102
103
  next if part_of_ignored_node?(node)
104
+ next if another_modifier_if_on_same_line?(node)
103
105
 
104
106
  autocorrect(corrector, node)
105
107
  ignore_node(node)
106
108
  end
107
109
  end
108
- # rubocop:enable Metrics/AbcSize
110
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
109
111
 
110
112
  private
111
113
 
@@ -207,14 +209,14 @@ module RuboCop
207
209
  def too_long_line_based_on_config?(range, line)
208
210
  return false if matches_allowed_pattern?(line)
209
211
 
210
- too_long = too_long_line_based_on_ignore_cop_directives?(range, line)
212
+ too_long = too_long_line_based_on_allow_cop_directives?(range, line)
211
213
  return too_long unless too_long == :undetermined
212
214
 
213
215
  too_long_line_based_on_allow_uri?(line)
214
216
  end
215
217
 
216
- def too_long_line_based_on_ignore_cop_directives?(range, line)
217
- if ignore_cop_directives? && directive_on_source_line?(range.line - 1)
218
+ def too_long_line_based_on_allow_cop_directives?(range, line)
219
+ if allow_cop_directives? && directive_on_source_line?(range.line - 1)
218
220
  return line_length_without_directive(line) > max_line_length
219
221
  end
220
222
 
@@ -230,15 +232,6 @@ module RuboCop
230
232
  true
231
233
  end
232
234
 
233
- def too_long_line_based_on_allow_qualified_name?(line)
234
- if allow_qualified_name?
235
- namespace_range = find_excessive_range(line, :namespace)
236
- return false if namespace_range && allowed_position?(line, namespace_range)
237
- end
238
-
239
- true
240
- end
241
-
242
235
  def line_length_enabled_at_line?(line)
243
236
  processed_source.comment_config.cop_enabled_at_line?('Layout/LineLength', line)
244
237
  end
@@ -248,7 +241,54 @@ module RuboCop
248
241
  end
249
242
 
250
243
  def non_eligible_node?(node)
251
- non_simple_if_unless?(node) || node.chained? || node.nested_conditional? || super
244
+ non_simple_if_unless?(node) || node.chained? || node.nested_conditional? ||
245
+ multiline_inside_collection?(node) || super
246
+ end
247
+
248
+ def multiline_inside_collection?(node)
249
+ return false if node.modifier_form?
250
+ return false unless (collection = find_containing_collection(node))
251
+
252
+ collection.children.any? { |child| sibling_if_shares_line?(child, node) }
253
+ end
254
+
255
+ def sibling_if_shares_line?(child, node)
256
+ inner = unwrap_begin(child)
257
+ inner&.if_type? && !inner.ternary? && shares_line_with?(inner, node)
258
+ end
259
+
260
+ def unwrap_begin(node)
261
+ return unless node.is_a?(RuboCop::AST::Node)
262
+
263
+ node = node.value if node.pair_type?
264
+ node.begin_type? ? node.children.first : node
265
+ end
266
+
267
+ def shares_line_with?(inner, node)
268
+ same_line?(inner, node.loc.end) || same_line?(inner.loc.end, node)
269
+ end
270
+
271
+ def find_containing_collection(node)
272
+ parent = node.parent
273
+ return collection_from_ancestor(parent) unless parent&.begin_type?
274
+
275
+ collection_from_ancestor(parent.parent)
276
+ end
277
+
278
+ def collection_from_ancestor(node)
279
+ return node if node&.type?(:array, :call)
280
+
281
+ node.parent if node&.type?(:pair)
282
+ end
283
+
284
+ def another_modifier_if_on_same_line?(node)
285
+ collection = find_containing_collection(node)
286
+ return false unless collection
287
+
288
+ line = node.source_range.line
289
+ collection.each_descendant(:if).any? do |sibling|
290
+ sibling != node && sibling.modifier_form? && sibling.source_range.line == line
291
+ end
252
292
  end
253
293
 
254
294
  def non_simple_if_unless?(node)
@@ -8,20 +8,20 @@ module RuboCop
8
8
  #
9
9
  # @example
10
10
  #
11
- # # bad
12
- # tired? ? 'stop' : 'go faster' if running?
11
+ # # bad
12
+ # tired? ? 'stop' : 'go faster' if running?
13
13
  #
14
- # # bad
15
- # if tired?
16
- # "please stop"
17
- # else
18
- # "keep going"
19
- # end if running?
14
+ # # bad
15
+ # if tired?
16
+ # "please stop"
17
+ # else
18
+ # "keep going"
19
+ # end if running?
20
20
  #
21
- # # good
22
- # if running?
23
- # tired? ? 'stop' : 'go faster'
24
- # end
21
+ # # good
22
+ # if running?
23
+ # tired? ? 'stop' : 'go faster'
24
+ # end
25
25
  class IfUnlessModifierOfIfUnless < Base
26
26
  include StatementModifier
27
27
  extend AutoCorrector
@@ -54,7 +54,10 @@ module RuboCop
54
54
  # # good (but potentially an unsafe correction)
55
55
  # foo.do_something?
56
56
  #
57
- # @example AllowedMethods: ['nonzero?'] (default)
57
+ # @example AllowedMethods: ['infinite?', 'nonzero?'] (default)
58
+ # # good
59
+ # num.infinite? ? true : false
60
+ #
58
61
  # # good
59
62
  # num.nonzero? ? true : false
60
63
  #
@@ -17,9 +17,9 @@ module RuboCop
17
17
  include OnNormalIfUnless
18
18
  extend AutoCorrector
19
19
 
20
- MSG_IF_ELSE = 'Do not use `if %<expr>s;` - use `if/else` instead.'
21
- MSG_NEWLINE = 'Do not use `if %<expr>s;` - use a newline instead.'
22
- MSG_TERNARY = 'Do not use `if %<expr>s;` - use a ternary operator instead.'
20
+ MSG_IF_ELSE = 'Do not use `%<keyword>s %<expr>s;` - use `if/else` instead.'
21
+ MSG_NEWLINE = 'Do not use `%<keyword>s %<expr>s;` - use a newline instead.'
22
+ MSG_TERNARY = 'Do not use `%<keyword>s %<expr>s;` - use a ternary operator instead.'
23
23
 
24
24
  def on_normal_if_unless(node)
25
25
  return if node.parent&.if_type?
@@ -49,7 +49,7 @@ module RuboCop
49
49
  MSG_TERNARY
50
50
  end
51
51
 
52
- format(template, expr: node.condition.source)
52
+ format(template, keyword: node.keyword, expr: node.condition.source)
53
53
  end
54
54
 
55
55
  def autocorrect(corrector, node)
@@ -71,7 +71,7 @@ module RuboCop
71
71
  end
72
72
 
73
73
  def use_return_with_argument?(node)
74
- node.if_branch&.return_type? && node.if_branch&.arguments&.any?
74
+ node.branches.compact.any? { |branch| branch.return_type? && branch.arguments.any? }
75
75
  end
76
76
 
77
77
  def replacement(node)
@@ -80,6 +80,8 @@ module RuboCop
80
80
  then_code = node.if_branch ? build_expression(node.if_branch) : 'nil'
81
81
  else_code = node.else_branch ? build_expression(node.else_branch) : 'nil'
82
82
 
83
+ then_code, else_code = else_code, then_code if node.unless?
84
+
83
85
  "#{node.condition.source} ? #{then_code} : #{else_code}"
84
86
  end
85
87
 
@@ -3,7 +3,10 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for trailing inline comments.
6
+ # Checks for trailing inline comments. Inline comments can
7
+ # make lines harder to read, especially when they are long.
8
+ # Placing comments on their own line above the code they
9
+ # describe is often clearer.
7
10
  #
8
11
  # @example
9
12
  #
@@ -48,8 +48,7 @@ module RuboCop
48
48
  private
49
49
 
50
50
  def allowed_addresses
51
- allowed_addresses = cop_config['AllowedAddresses']
52
- Array(allowed_addresses).map(&:downcase)
51
+ @allowed_addresses ||= Array(cop_config['AllowedAddresses']).map(&:downcase).freeze
53
52
  end
54
53
 
55
54
  def potential_ip?(str)