rubocop 1.39.0 → 1.57.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (448) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +6 -4
  4. data/config/default.yml +306 -54
  5. data/config/obsoletion.yml +5 -0
  6. data/exe/rubocop +1 -1
  7. data/lib/rubocop/cli/command/auto_generate_config.rb +7 -0
  8. data/lib/rubocop/cli/command/execute_runner.rb +7 -2
  9. data/lib/rubocop/cli/command/lsp.rb +19 -0
  10. data/lib/rubocop/cli.rb +59 -10
  11. data/lib/rubocop/comment_config.rb +24 -0
  12. data/lib/rubocop/config.rb +46 -18
  13. data/lib/rubocop/config_finder.rb +2 -2
  14. data/lib/rubocop/config_loader.rb +34 -28
  15. data/lib/rubocop/config_loader_resolver.rb +6 -2
  16. data/lib/rubocop/config_obsoletion/parameter_rule.rb +9 -1
  17. data/lib/rubocop/config_obsoletion.rb +2 -2
  18. data/lib/rubocop/config_validator.rb +1 -1
  19. data/lib/rubocop/cop/autocorrect_logic.rb +31 -13
  20. data/lib/rubocop/cop/badge.rb +9 -4
  21. data/lib/rubocop/cop/base.rb +116 -84
  22. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -0
  23. data/lib/rubocop/cop/bundler/duplicated_group.rb +127 -0
  24. data/lib/rubocop/cop/bundler/gem_comment.rb +2 -2
  25. data/lib/rubocop/cop/bundler/gem_version.rb +2 -2
  26. data/lib/rubocop/cop/bundler/ordered_gems.rb +9 -1
  27. data/lib/rubocop/cop/commissioner.rb +16 -5
  28. data/lib/rubocop/cop/cop.rb +53 -33
  29. data/lib/rubocop/cop/corrector.rb +31 -11
  30. data/lib/rubocop/cop/correctors/alignment_corrector.rb +3 -3
  31. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +3 -3
  32. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +3 -3
  33. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +7 -4
  34. data/lib/rubocop/cop/correctors/line_break_corrector.rb +1 -1
  35. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +23 -7
  36. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +2 -7
  37. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
  38. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  39. data/lib/rubocop/cop/gemspec/dependency_version.rb +19 -21
  40. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -1
  41. data/lib/rubocop/cop/gemspec/development_dependencies.rb +107 -0
  42. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +9 -1
  43. data/lib/rubocop/cop/generator/require_file_injector.rb +1 -1
  44. data/lib/rubocop/cop/internal_affairs/cop_description.rb +38 -12
  45. data/lib/rubocop/cop/internal_affairs/example_description.rb +42 -21
  46. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +3 -3
  47. data/lib/rubocop/cop/internal_affairs/inherit_deprecated_cop_class.rb +1 -1
  48. data/lib/rubocop/cop/internal_affairs/lambda_or_proc.rb +46 -0
  49. data/lib/rubocop/cop/internal_affairs/location_expression.rb +37 -0
  50. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -1
  51. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +6 -6
  52. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -1
  53. data/lib/rubocop/cop/internal_affairs/processed_source_buffer_name.rb +42 -0
  54. data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +11 -3
  55. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -1
  56. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +1 -1
  57. data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +11 -2
  58. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +66 -0
  59. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -0
  60. data/lib/rubocop/cop/internal_affairs.rb +4 -0
  61. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  62. data/lib/rubocop/cop/layout/block_end_newline.rb +7 -15
  63. data/lib/rubocop/cop/layout/class_structure.rb +44 -27
  64. data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +2 -3
  65. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +2 -6
  66. data/lib/rubocop/cop/layout/comment_indentation.rb +3 -1
  67. data/lib/rubocop/cop/layout/dot_position.rb +1 -5
  68. data/lib/rubocop/cop/layout/empty_comment.rb +3 -3
  69. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +42 -9
  70. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +28 -5
  71. data/lib/rubocop/cop/layout/empty_lines.rb +3 -1
  72. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +2 -0
  73. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +2 -0
  74. data/lib/rubocop/cop/layout/end_alignment.rb +9 -1
  75. data/lib/rubocop/cop/layout/extra_spacing.rb +15 -6
  76. data/lib/rubocop/cop/layout/first_argument_indentation.rb +8 -3
  77. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +35 -8
  78. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +36 -1
  79. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +57 -8
  80. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +52 -19
  81. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +10 -4
  82. data/lib/rubocop/cop/layout/heredoc_indentation.rb +11 -11
  83. data/lib/rubocop/cop/layout/indentation_style.rb +8 -3
  84. data/lib/rubocop/cop/layout/indentation_width.rb +3 -3
  85. data/lib/rubocop/cop/layout/initial_indentation.rb +1 -1
  86. data/lib/rubocop/cop/layout/leading_comment_space.rb +2 -2
  87. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +21 -10
  88. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +19 -9
  89. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -0
  90. data/lib/rubocop/cop/layout/line_length.rb +2 -0
  91. data/lib/rubocop/cop/layout/multiline_array_line_breaks.rb +31 -1
  92. data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -1
  93. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +29 -1
  94. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +35 -1
  95. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +18 -3
  96. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +33 -1
  97. data/lib/rubocop/cop/layout/redundant_line_break.rb +22 -13
  98. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +2 -2
  99. data/lib/rubocop/cop/layout/space_after_comma.rb +9 -1
  100. data/lib/rubocop/cop/layout/space_after_not.rb +1 -1
  101. data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -2
  102. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +2 -2
  103. data/lib/rubocop/cop/layout/space_around_operators.rb +4 -2
  104. data/lib/rubocop/cop/layout/space_before_first_arg.rb +1 -1
  105. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +2 -2
  106. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +11 -13
  107. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +3 -1
  108. data/lib/rubocop/cop/layout/space_inside_parens.rb +3 -3
  109. data/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb +1 -1
  110. data/lib/rubocop/cop/layout/space_inside_range_literal.rb +1 -1
  111. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +4 -4
  112. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +5 -4
  113. data/lib/rubocop/cop/layout/trailing_empty_lines.rb +6 -1
  114. data/lib/rubocop/cop/layout/trailing_whitespace.rb +12 -5
  115. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +14 -2
  116. data/lib/rubocop/cop/lint/ambiguous_operator.rb +4 -0
  117. data/lib/rubocop/cop/lint/assignment_in_condition.rb +11 -1
  118. data/lib/rubocop/cop/lint/constant_resolution.rb +5 -1
  119. data/lib/rubocop/cop/lint/debugger.rb +23 -24
  120. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +62 -112
  121. data/lib/rubocop/cop/lint/deprecated_constants.rb +8 -1
  122. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
  123. data/lib/rubocop/cop/lint/duplicate_branch.rb +0 -2
  124. data/lib/rubocop/cop/lint/duplicate_hash_key.rb +2 -1
  125. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +122 -0
  126. data/lib/rubocop/cop/lint/duplicate_methods.rb +20 -9
  127. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +47 -22
  128. data/lib/rubocop/cop/lint/else_layout.rb +3 -7
  129. data/lib/rubocop/cop/lint/empty_block.rb +3 -7
  130. data/lib/rubocop/cop/lint/empty_conditional_body.rb +5 -3
  131. data/lib/rubocop/cop/lint/empty_interpolation.rb +1 -1
  132. data/lib/rubocop/cop/lint/erb_new_arguments.rb +3 -4
  133. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +14 -7
  134. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +16 -18
  135. data/lib/rubocop/cop/lint/identity_comparison.rb +0 -1
  136. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  137. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -3
  138. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
  139. data/lib/rubocop/cop/lint/inherit_exception.rb +9 -0
  140. data/lib/rubocop/cop/lint/interpolation_check.rb +4 -3
  141. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  142. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +47 -5
  143. data/lib/rubocop/cop/lint/missing_super.rb +63 -5
  144. data/lib/rubocop/cop/lint/mixed_case_range.rb +111 -0
  145. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
  146. data/lib/rubocop/cop/lint/nested_method_definition.rb +4 -9
  147. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +20 -12
  148. data/lib/rubocop/cop/lint/number_conversion.rb +5 -0
  149. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +2 -2
  150. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +2 -0
  151. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +0 -1
  152. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +16 -1
  153. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +5 -0
  154. data/lib/rubocop/cop/lint/percent_string_array.rb +1 -1
  155. data/lib/rubocop/cop/lint/percent_symbol_array.rb +1 -1
  156. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +26 -8
  157. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +6 -6
  158. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +130 -0
  159. data/lib/rubocop/cop/lint/redundant_require_statement.rb +21 -2
  160. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +20 -4
  161. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
  162. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +35 -15
  163. data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -1
  164. data/lib/rubocop/cop/lint/redundant_with_object.rb +1 -1
  165. data/lib/rubocop/cop/lint/refinement_import_methods.rb +2 -1
  166. data/lib/rubocop/cop/lint/regexp_as_condition.rb +6 -0
  167. data/lib/rubocop/cop/lint/require_parentheses.rb +3 -1
  168. data/lib/rubocop/cop/lint/rescue_type.rb +3 -3
  169. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +21 -16
  170. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +1 -1
  171. data/lib/rubocop/cop/lint/script_permission.rb +1 -1
  172. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +6 -6
  173. data/lib/rubocop/cop/lint/shadowed_exception.rb +6 -12
  174. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +11 -4
  175. data/lib/rubocop/cop/lint/struct_new_override.rb +12 -12
  176. data/lib/rubocop/cop/lint/suppressed_exception.rb +2 -2
  177. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  178. data/lib/rubocop/cop/lint/syntax.rb +4 -0
  179. data/lib/rubocop/cop/lint/to_enum_arguments.rb +18 -6
  180. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +23 -9
  181. data/lib/rubocop/cop/lint/unreachable_loop.rb +3 -3
  182. data/lib/rubocop/cop/lint/unused_method_argument.rb +2 -1
  183. data/lib/rubocop/cop/lint/useless_access_modifier.rb +10 -7
  184. data/lib/rubocop/cop/lint/useless_assignment.rb +94 -10
  185. data/lib/rubocop/cop/lint/useless_method_definition.rb +12 -4
  186. data/lib/rubocop/cop/lint/useless_rescue.rb +89 -0
  187. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +14 -4
  188. data/lib/rubocop/cop/lint/useless_times.rb +1 -1
  189. data/lib/rubocop/cop/lint/void.rb +84 -21
  190. data/lib/rubocop/cop/metrics/block_length.rb +11 -6
  191. data/lib/rubocop/cop/metrics/block_nesting.rb +2 -2
  192. data/lib/rubocop/cop/metrics/class_length.rb +12 -6
  193. data/lib/rubocop/cop/metrics/collection_literal_length.rb +76 -0
  194. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
  195. data/lib/rubocop/cop/metrics/method_length.rb +10 -5
  196. data/lib/rubocop/cop/metrics/module_length.rb +10 -5
  197. data/lib/rubocop/cop/metrics/parameter_lists.rb +27 -0
  198. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  199. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -8
  200. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +39 -8
  201. data/lib/rubocop/cop/migration/department_name.rb +3 -3
  202. data/lib/rubocop/cop/mixin/alignment.rb +2 -2
  203. data/lib/rubocop/cop/mixin/allowed_identifiers.rb +2 -2
  204. data/lib/rubocop/cop/mixin/allowed_methods.rb +3 -1
  205. data/lib/rubocop/cop/mixin/allowed_receivers.rb +34 -0
  206. data/lib/rubocop/cop/mixin/annotation_comment.rb +14 -7
  207. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  208. data/lib/rubocop/cop/mixin/comments_help.rb +13 -7
  209. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +21 -9
  210. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  211. data/lib/rubocop/cop/mixin/documentation_comment.rb +1 -1
  212. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -1
  213. data/lib/rubocop/cop/mixin/first_element_line_break.rb +11 -7
  214. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +1 -1
  215. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +75 -13
  216. data/lib/rubocop/cop/mixin/hash_transform_method.rb +3 -3
  217. data/lib/rubocop/cop/mixin/heredoc.rb +6 -2
  218. data/lib/rubocop/cop/mixin/line_length_help.rb +11 -2
  219. data/lib/rubocop/cop/mixin/method_complexity.rb +5 -3
  220. data/lib/rubocop/cop/mixin/min_branches_count.rb +40 -0
  221. data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +5 -6
  222. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -2
  223. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
  224. data/lib/rubocop/cop/mixin/percent_array.rb +3 -5
  225. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  226. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +6 -8
  227. data/lib/rubocop/cop/mixin/range_help.rb +1 -6
  228. data/lib/rubocop/cop/mixin/require_library.rb +2 -0
  229. data/lib/rubocop/cop/mixin/rescue_node.rb +3 -3
  230. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  231. data/lib/rubocop/cop/mixin/statement_modifier.rb +18 -3
  232. data/lib/rubocop/cop/mixin/string_help.rb +4 -2
  233. data/lib/rubocop/cop/mixin/surrounding_space.rb +3 -3
  234. data/lib/rubocop/cop/mixin/trailing_comma.rb +3 -3
  235. data/lib/rubocop/cop/naming/ascii_identifiers.rb +1 -1
  236. data/lib/rubocop/cop/naming/block_forwarding.rb +6 -2
  237. data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +3 -1
  238. data/lib/rubocop/cop/naming/constant_name.rb +1 -1
  239. data/lib/rubocop/cop/naming/file_name.rb +1 -1
  240. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +1 -1
  241. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +3 -1
  242. data/lib/rubocop/cop/naming/inclusive_language.rb +27 -5
  243. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +25 -10
  244. data/lib/rubocop/cop/naming/method_name.rb +3 -3
  245. data/lib/rubocop/cop/naming/predicate_name.rb +1 -1
  246. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +12 -4
  247. data/lib/rubocop/cop/naming/variable_name.rb +6 -1
  248. data/lib/rubocop/cop/registry.rb +66 -44
  249. data/lib/rubocop/cop/security/compound_hash.rb +2 -1
  250. data/lib/rubocop/cop/style/access_modifier_declarations.rb +26 -11
  251. data/lib/rubocop/cop/style/accessor_grouping.rb +43 -17
  252. data/lib/rubocop/cop/style/alias.rb +18 -9
  253. data/lib/rubocop/cop/style/arguments_forwarding.rb +280 -62
  254. data/lib/rubocop/cop/style/array_intersect.rb +119 -0
  255. data/lib/rubocop/cop/style/ascii_comments.rb +1 -1
  256. data/lib/rubocop/cop/style/attr.rb +11 -1
  257. data/lib/rubocop/cop/style/begin_block.rb +1 -2
  258. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +1 -1
  259. data/lib/rubocop/cop/style/block_comments.rb +3 -3
  260. data/lib/rubocop/cop/style/block_delimiters.rb +22 -6
  261. data/lib/rubocop/cop/style/case_like_if.rb +20 -3
  262. data/lib/rubocop/cop/style/class_and_module_children.rb +5 -12
  263. data/lib/rubocop/cop/style/class_equality_comparison.rb +58 -40
  264. data/lib/rubocop/cop/style/collection_compact.rb +20 -7
  265. data/lib/rubocop/cop/style/collection_methods.rb +2 -0
  266. data/lib/rubocop/cop/style/colon_method_call.rb +2 -2
  267. data/lib/rubocop/cop/style/combinable_loops.rb +30 -8
  268. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  269. data/lib/rubocop/cop/style/comment_annotation.rb +1 -1
  270. data/lib/rubocop/cop/style/commented_keyword.rb +2 -2
  271. data/lib/rubocop/cop/style/comparable_clamp.rb +125 -0
  272. data/lib/rubocop/cop/style/concat_array_literals.rb +94 -0
  273. data/lib/rubocop/cop/style/conditional_assignment.rb +11 -15
  274. data/lib/rubocop/cop/style/copyright.rb +6 -3
  275. data/lib/rubocop/cop/style/data_inheritance.rb +75 -0
  276. data/lib/rubocop/cop/style/dir.rb +1 -1
  277. data/lib/rubocop/cop/style/dir_empty.rb +54 -0
  278. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +2 -2
  279. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +3 -3
  280. data/lib/rubocop/cop/style/documentation.rb +22 -10
  281. data/lib/rubocop/cop/style/documentation_method.rb +10 -4
  282. data/lib/rubocop/cop/style/double_negation.rb +2 -2
  283. data/lib/rubocop/cop/style/each_with_object.rb +1 -1
  284. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  285. data/lib/rubocop/cop/style/empty_case_condition.rb +6 -1
  286. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  287. data/lib/rubocop/cop/style/eval_with_location.rb +8 -8
  288. data/lib/rubocop/cop/style/exact_regexp_match.rb +68 -0
  289. data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
  290. data/lib/rubocop/cop/style/file_empty.rb +71 -0
  291. data/lib/rubocop/cop/style/file_read.rb +3 -3
  292. data/lib/rubocop/cop/style/file_write.rb +1 -1
  293. data/lib/rubocop/cop/style/for.rb +1 -1
  294. data/lib/rubocop/cop/style/format_string.rb +24 -3
  295. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +4 -2
  296. data/lib/rubocop/cop/style/guard_clause.rb +73 -10
  297. data/lib/rubocop/cop/style/hash_conversion.rb +10 -0
  298. data/lib/rubocop/cop/style/hash_each_methods.rb +1 -10
  299. data/lib/rubocop/cop/style/hash_except.rb +23 -12
  300. data/lib/rubocop/cop/style/hash_like_case.rb +3 -9
  301. data/lib/rubocop/cop/style/hash_syntax.rb +16 -9
  302. data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
  303. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
  304. data/lib/rubocop/cop/style/identical_conditional_branches.rb +36 -3
  305. data/lib/rubocop/cop/style/if_inside_else.rb +6 -0
  306. data/lib/rubocop/cop/style/if_unless_modifier.rb +111 -15
  307. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +2 -0
  308. data/lib/rubocop/cop/style/if_with_semicolon.rb +6 -6
  309. data/lib/rubocop/cop/style/infinite_loop.rb +2 -5
  310. data/lib/rubocop/cop/style/inverse_methods.rb +7 -5
  311. data/lib/rubocop/cop/style/invertible_unless_condition.rb +118 -0
  312. data/lib/rubocop/cop/style/lambda.rb +3 -3
  313. data/lib/rubocop/cop/style/lambda_call.rb +5 -0
  314. data/lib/rubocop/cop/style/line_end_concatenation.rb +4 -1
  315. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +2 -2
  316. data/lib/rubocop/cop/style/map_to_hash.rb +4 -1
  317. data/lib/rubocop/cop/style/map_to_set.rb +64 -0
  318. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +35 -24
  319. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +44 -37
  320. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -0
  321. data/lib/rubocop/cop/style/method_def_parentheses.rb +11 -4
  322. data/lib/rubocop/cop/style/min_max.rb +3 -3
  323. data/lib/rubocop/cop/style/min_max_comparison.rb +83 -0
  324. data/lib/rubocop/cop/style/missing_else.rb +13 -1
  325. data/lib/rubocop/cop/style/mixin_grouping.rb +5 -5
  326. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
  327. data/lib/rubocop/cop/style/multiline_if_modifier.rb +0 -4
  328. data/lib/rubocop/cop/style/multiline_memoization.rb +2 -2
  329. data/lib/rubocop/cop/style/multiline_method_signature.rb +7 -4
  330. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +19 -4
  331. data/lib/rubocop/cop/style/multiple_comparison.rb +14 -0
  332. data/lib/rubocop/cop/style/negated_if_else_condition.rb +13 -12
  333. data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -11
  334. data/lib/rubocop/cop/style/nil_lambda.rb +3 -3
  335. data/lib/rubocop/cop/style/numbered_parameters_limit.rb +11 -3
  336. data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
  337. data/lib/rubocop/cop/style/one_line_conditional.rb +3 -6
  338. data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
  339. data/lib/rubocop/cop/style/operator_method_call.rb +22 -2
  340. data/lib/rubocop/cop/style/parallel_assignment.rb +29 -19
  341. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -3
  342. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  343. data/lib/rubocop/cop/style/preferred_hash_methods.rb +1 -1
  344. data/lib/rubocop/cop/style/redundant_argument.rb +9 -1
  345. data/lib/rubocop/cop/style/redundant_array_constructor.rb +77 -0
  346. data/lib/rubocop/cop/style/redundant_begin.rb +10 -2
  347. data/lib/rubocop/cop/style/redundant_condition.rb +18 -3
  348. data/lib/rubocop/cop/style/redundant_conditional.rb +2 -14
  349. data/lib/rubocop/cop/style/redundant_constant_base.rb +85 -0
  350. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +38 -0
  351. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +126 -0
  352. data/lib/rubocop/cop/style/redundant_exception.rb +32 -12
  353. data/lib/rubocop/cop/style/redundant_fetch_block.rb +6 -4
  354. data/lib/rubocop/cop/style/redundant_filter_chain.rb +117 -0
  355. data/lib/rubocop/cop/style/redundant_heredoc_delimiter_quotes.rb +58 -0
  356. data/lib/rubocop/cop/style/redundant_interpolation.rb +2 -2
  357. data/lib/rubocop/cop/style/redundant_line_continuation.rb +183 -0
  358. data/lib/rubocop/cop/style/redundant_parentheses.rb +26 -8
  359. data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
  360. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +100 -0
  361. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +7 -8
  362. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +46 -0
  363. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +13 -4
  364. data/lib/rubocop/cop/style/redundant_return.rb +14 -2
  365. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +8 -1
  366. data/lib/rubocop/cop/style/redundant_sort.rb +5 -5
  367. data/lib/rubocop/cop/style/redundant_string_escape.rb +11 -7
  368. data/lib/rubocop/cop/style/regexp_literal.rb +11 -2
  369. data/lib/rubocop/cop/style/require_order.rb +139 -0
  370. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -3
  371. data/lib/rubocop/cop/style/rescue_standard_error.rb +2 -2
  372. data/lib/rubocop/cop/style/return_nil.rb +6 -2
  373. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +95 -0
  374. data/lib/rubocop/cop/style/safe_navigation.rb +37 -8
  375. data/lib/rubocop/cop/style/select_by_regexp.rb +23 -5
  376. data/lib/rubocop/cop/style/self_assignment.rb +2 -2
  377. data/lib/rubocop/cop/style/semicolon.rb +37 -6
  378. data/lib/rubocop/cop/style/signal_exception.rb +9 -7
  379. data/lib/rubocop/cop/style/single_line_do_end_block.rb +65 -0
  380. data/lib/rubocop/cop/style/single_line_methods.rb +1 -1
  381. data/lib/rubocop/cop/style/slicing_with_range.rb +1 -1
  382. data/lib/rubocop/cop/style/sole_nested_conditional.rb +9 -5
  383. data/lib/rubocop/cop/style/special_global_vars.rb +3 -4
  384. data/lib/rubocop/cop/style/stderr_puts.rb +1 -1
  385. data/lib/rubocop/cop/style/string_hash_keys.rb +4 -1
  386. data/lib/rubocop/cop/style/string_literals.rb +1 -5
  387. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +30 -5
  388. data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
  389. data/lib/rubocop/cop/style/symbol_array.rb +35 -15
  390. data/lib/rubocop/cop/style/symbol_proc.rb +2 -4
  391. data/lib/rubocop/cop/style/trailing_body_on_class.rb +1 -0
  392. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -4
  393. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +1 -1
  394. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  395. data/lib/rubocop/cop/style/unless_logical_operators.rb +1 -0
  396. data/lib/rubocop/cop/style/unpack_first.rb +3 -3
  397. data/lib/rubocop/cop/style/word_array.rb +54 -1
  398. data/lib/rubocop/cop/style/yaml_file_read.rb +66 -0
  399. data/lib/rubocop/cop/style/yoda_condition.rb +17 -8
  400. data/lib/rubocop/cop/style/yoda_expression.rb +91 -0
  401. data/lib/rubocop/cop/style/zero_length_predicate.rb +40 -19
  402. data/lib/rubocop/cop/team.rb +61 -53
  403. data/lib/rubocop/cop/util.rb +43 -7
  404. data/lib/rubocop/cop/utils/regexp_ranges.rb +113 -0
  405. data/lib/rubocop/cop/variable_force/assignment.rb +45 -4
  406. data/lib/rubocop/cop/variable_force/scope.rb +3 -3
  407. data/lib/rubocop/cop/variable_force/variable.rb +5 -3
  408. data/lib/rubocop/cop/variable_force/variable_table.rb +5 -3
  409. data/lib/rubocop/cop/variable_force.rb +19 -30
  410. data/lib/rubocop/cops_documentation_generator.rb +44 -15
  411. data/lib/rubocop/directive_comment.rb +4 -4
  412. data/lib/rubocop/ext/comment.rb +18 -0
  413. data/lib/rubocop/ext/regexp_node.rb +1 -1
  414. data/lib/rubocop/ext/regexp_parser.rb +5 -2
  415. data/lib/rubocop/file_finder.rb +4 -7
  416. data/lib/rubocop/file_patterns.rb +43 -0
  417. data/lib/rubocop/formatter/disabled_config_formatter.rb +17 -6
  418. data/lib/rubocop/formatter/html_formatter.rb +1 -1
  419. data/lib/rubocop/formatter/junit_formatter.rb +4 -1
  420. data/lib/rubocop/formatter/simple_text_formatter.rb +1 -1
  421. data/lib/rubocop/formatter.rb +4 -1
  422. data/lib/rubocop/lsp/logger.rb +22 -0
  423. data/lib/rubocop/lsp/routes.rb +246 -0
  424. data/lib/rubocop/lsp/runtime.rb +99 -0
  425. data/lib/rubocop/lsp/server.rb +68 -0
  426. data/lib/rubocop/lsp/severity.rb +27 -0
  427. data/lib/rubocop/magic_comment.rb +12 -10
  428. data/lib/rubocop/options.rb +45 -3
  429. data/lib/rubocop/path_util.rb +50 -22
  430. data/lib/rubocop/result_cache.rb +8 -4
  431. data/lib/rubocop/rspec/cop_helper.rb +6 -3
  432. data/lib/rubocop/rspec/expect_offense.rb +6 -4
  433. data/lib/rubocop/rspec/shared_contexts.rb +6 -3
  434. data/lib/rubocop/rspec/support.rb +3 -2
  435. data/lib/rubocop/runner.rb +55 -10
  436. data/lib/rubocop/server/cache.rb +12 -4
  437. data/lib/rubocop/server/cli.rb +37 -18
  438. data/lib/rubocop/server/client_command/exec.rb +4 -3
  439. data/lib/rubocop/server/client_command/start.rb +6 -1
  440. data/lib/rubocop/server/core.rb +25 -10
  441. data/lib/rubocop/server/helper.rb +1 -1
  442. data/lib/rubocop/server/server_command/exec.rb +1 -1
  443. data/lib/rubocop/string_interpreter.rb +3 -3
  444. data/lib/rubocop/target_finder.rb +8 -4
  445. data/lib/rubocop/target_ruby.rb +14 -10
  446. data/lib/rubocop/version.rb +10 -6
  447. data/lib/rubocop.rb +47 -6
  448. metadata +91 -37
@@ -28,6 +28,7 @@ module RuboCop
28
28
  # execute(sql).keys.each { |v| p v }
29
29
  # execute(sql).values.each { |v| p v }
30
30
  class HashEachMethods < Base
31
+ include AllowedReceivers
31
32
  include Lint::UnusedArgument
32
33
  extend AutoCorrector
33
34
 
@@ -116,16 +117,6 @@ module RuboCop
116
117
  def kv_range(outer_node)
117
118
  outer_node.receiver.loc.selector.join(outer_node.loc.selector)
118
119
  end
119
-
120
- def allowed_receiver?(receiver)
121
- receiver_name = receiver.send_type? ? receiver.method_name.to_s : receiver.source
122
-
123
- allowed_receivers.include?(receiver_name)
124
- end
125
-
126
- def allowed_receivers
127
- cop_config.fetch('AllowedReceivers', [])
128
- end
129
120
  end
130
121
  end
131
122
  end
@@ -45,13 +45,13 @@ module RuboCop
45
45
  (block
46
46
  (send _ _)
47
47
  (args
48
- (arg _)
48
+ $(arg _)
49
49
  (arg _))
50
50
  {
51
- (send
51
+ $(send
52
52
  _ {:== :!= :eql? :include?} _)
53
53
  (send
54
- (send
54
+ $(send
55
55
  _ {:== :!= :eql? :include?} _) :!)
56
56
  })
57
57
  PATTERN
@@ -61,13 +61,13 @@ module RuboCop
61
61
  (block
62
62
  (send _ _)
63
63
  (args
64
- (arg _)
64
+ $(arg _)
65
65
  (arg _))
66
66
  {
67
- (send
67
+ $(send
68
68
  _ {:== :!= :eql? :in? :include? :exclude?} _)
69
69
  (send
70
- (send
70
+ $(send
71
71
  _ {:== :!= :eql? :in? :include? :exclude?} _) :!)
72
72
  })
73
73
  PATTERN
@@ -89,13 +89,24 @@ module RuboCop
89
89
 
90
90
  private
91
91
 
92
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
92
93
  def bad_method?(block)
93
94
  if active_support_extensions_enabled?
94
- bad_method_with_active_support?(block)
95
+ bad_method_with_active_support?(block) do |key_arg, send_node|
96
+ if send_node.method?(:in?) && send_node.receiver&.source != key_arg.source
97
+ return false
98
+ end
99
+ return true if !send_node.method?(:include?) && !send_node.method?(:exclude?)
100
+
101
+ send_node.first_argument&.source == key_arg.source
102
+ end
95
103
  else
96
- bad_method_with_poro?(block)
104
+ bad_method_with_poro?(block) do |key_arg, send_node|
105
+ !send_node.method?(:include?) || send_node.first_argument&.source == key_arg.source
106
+ end
97
107
  end
98
108
  end
109
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
99
110
 
100
111
  def semantically_except_method?(send, block)
101
112
  body = block.body
@@ -122,8 +133,8 @@ module RuboCop
122
133
  end
123
134
 
124
135
  def safe_to_register_offense?(block, except_key)
125
- extracted = extract_body_if_nagated(block.body)
126
- if extracted.method?('in?') || extracted.method?('include?') || \
136
+ extracted = extract_body_if_negated(block.body)
137
+ if extracted.method?('in?') || extracted.method?('include?') ||
127
138
  extracted.method?('exclude?')
128
139
  return true
129
140
  end
@@ -132,7 +143,7 @@ module RuboCop
132
143
  except_key.sym_type? || except_key.str_type?
133
144
  end
134
145
 
135
- def extract_body_if_nagated(body)
146
+ def extract_body_if_negated(body)
136
147
  return body unless body.method?('!')
137
148
 
138
149
  body.receiver
@@ -161,7 +172,7 @@ module RuboCop
161
172
 
162
173
  def except_key(node)
163
174
  key_argument = node.argument_list.first.source
164
- body = extract_body_if_nagated(node.body)
175
+ body = extract_body_if_negated(node.body)
165
176
  lhs, _method_name, rhs = *body
166
177
  return if [lhs, rhs].map(&:source).none?(key_argument)
167
178
 
@@ -37,6 +37,8 @@ module RuboCop
37
37
  # end
38
38
  #
39
39
  class HashLikeCase < Base
40
+ include MinBranchesCount
41
+
40
42
  MSG = 'Consider replacing `case-when` with a hash lookup.'
41
43
 
42
44
  # @!method hash_like_case?(node)
@@ -49,7 +51,7 @@ module RuboCop
49
51
  PATTERN
50
52
 
51
53
  def on_case(node)
52
- return if node.when_branches.size < min_branches_count
54
+ return unless min_branches_count?(node)
53
55
 
54
56
  hash_like_case?(node) do |condition_nodes, body_nodes|
55
57
  if nodes_of_same_type?(condition_nodes) && nodes_of_same_type?(body_nodes)
@@ -63,14 +65,6 @@ module RuboCop
63
65
  def nodes_of_same_type?(nodes)
64
66
  nodes.all? { |node| node.type == nodes.first.type }
65
67
  end
66
-
67
- def min_branches_count
68
- length = cop_config['MinBranchesCount'] || 3
69
- return length if length.is_a?(Integer) && length.positive?
70
-
71
- warn Rainbow('`MinBranchesCount` needs to be a positive integer!').red
72
- exit!
73
- end
74
68
  end
75
69
  end
76
70
  end
@@ -28,7 +28,7 @@ module RuboCop
28
28
  # * always - forces use of the 3.1 syntax (e.g. {foo:})
29
29
  # * never - forces use of explicit hash literal value
30
30
  # * either - accepts both shorthand and explicit use of hash literal value
31
- # * consistent - like "either", but will avoid mixing styles in a single hash
31
+ # * consistent - forces use of the 3.1 syntax only if all values can be omitted in the hash
32
32
  #
33
33
  # @example EnforcedStyle: ruby19 (default)
34
34
  # # bad
@@ -88,20 +88,26 @@ module RuboCop
88
88
  # {foo: foo, bar: bar}
89
89
  #
90
90
  # # good
91
+ # {foo: foo, bar:}
92
+ #
93
+ # # good
91
94
  # {foo:, bar:}
92
95
  #
93
96
  # @example EnforcedShorthandSyntax: consistent
94
97
  #
95
- # # bad
96
- # {foo: , bar: bar}
98
+ # # bad - `foo` and `bar` values can be omitted
99
+ # {foo: foo, bar: bar}
97
100
  #
98
- # # good
99
- # {foo:, bar:}
101
+ # # bad - `bar` value can be omitted
102
+ # {foo:, bar: bar}
100
103
  #
101
- # # bad
102
- # {foo: , bar: baz}
104
+ # # bad - mixed syntaxes
105
+ # {foo:, bar: baz}
103
106
  #
104
107
  # # good
108
+ # {foo:, bar:}
109
+ #
110
+ # # good - can't omit `baz`
105
111
  # {foo: foo, bar: baz}
106
112
  #
107
113
  class HashSyntax < Base
@@ -204,7 +210,7 @@ module RuboCop
204
210
  return true if /\A[_a-z]\w*[?!]?\z/i.match?(sym_name)
205
211
 
206
212
  # For more complicated hash keys, let the parser validate the syntax.
207
- ProcessedSource.new("{ #{sym_name}: :foo }", target_ruby_version).valid_syntax?
213
+ parse("{ #{sym_name}: :foo }").valid_syntax?
208
214
  end
209
215
 
210
216
  def check(pairs, delim, msg)
@@ -244,13 +250,14 @@ module RuboCop
244
250
  end
245
251
 
246
252
  def argument_without_space?(node)
247
- node.argument? && node.loc.expression.begin_pos == node.parent.loc.selector.end_pos
253
+ node.argument? && node.source_range.begin_pos == node.parent.loc.selector.end_pos
248
254
  end
249
255
 
250
256
  def autocorrect_hash_rockets(corrector, pair_node)
251
257
  op = pair_node.loc.operator
252
258
 
253
259
  key_with_hash_rocket = ":#{pair_node.key.source}#{pair_node.inverse_delimiter(true)}"
260
+ key_with_hash_rocket += pair_node.key.source if pair_node.value_omission?
254
261
  corrector.replace(pair_node.key, key_with_hash_rocket)
255
262
  corrector.remove(range_with_surrounding_space(op))
256
263
  end
@@ -3,8 +3,8 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Looks for uses of `_.each_with_object({}) {...}`,
7
- # `_.map {...}.to_h`, and `Hash[_.map {...}]` that are actually just
6
+ # Looks for uses of `\_.each_with_object({}) {...}`,
7
+ # `\_.map {...}.to_h`, and `Hash[\_.map {...}]` that are actually just
8
8
  # transforming the keys of a hash, and tries to use a simpler & faster
9
9
  # call to `transform_keys` instead.
10
10
  # It should only be enabled on Ruby version 2.5 or newer.
@@ -3,8 +3,8 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Looks for uses of `_.each_with_object({}) {...}`,
7
- # `_.map {...}.to_h`, and `Hash[_.map {...}]` that are actually just
6
+ # Looks for uses of `\_.each_with_object({}) {...}`,
7
+ # `\_.map {...}.to_h`, and `Hash[\_.map {...}]` that are actually just
8
8
  # transforming the values of a hash, and tries to use a simpler & faster
9
9
  # call to `transform_values` instead.
10
10
  #
@@ -136,6 +136,7 @@ module RuboCop
136
136
 
137
137
  private
138
138
 
139
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
139
140
  def check_branches(node, branches)
140
141
  # return if any branch is empty. An empty branch can be an `if`
141
142
  # without an `else` or a branch that contains only comments.
@@ -144,22 +145,43 @@ module RuboCop
144
145
  tails = branches.map { |branch| tail(branch) }
145
146
  check_expressions(node, tails, :after_condition) if duplicated_expressions?(node, tails)
146
147
 
148
+ return if last_child_of_parent?(node) &&
149
+ branches.any? { |branch| single_child_branch?(branch) }
150
+
147
151
  heads = branches.map { |branch| head(branch) }
148
- check_expressions(node, heads, :before_condition) if duplicated_expressions?(node, heads)
152
+
153
+ return unless duplicated_expressions?(node, heads)
154
+
155
+ condition_variable = assignable_condition_value(node)
156
+ return if heads.first.assignment? && condition_variable == heads.first.name.to_s
157
+
158
+ check_expressions(node, heads, :before_condition)
149
159
  end
160
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
150
161
 
151
162
  def duplicated_expressions?(node, expressions)
152
163
  unique_expressions = expressions.uniq
153
164
  return false unless expressions.size >= 1 && unique_expressions.one?
154
165
 
155
166
  unique_expression = unique_expressions.first
156
- return true unless unique_expression.assignment?
167
+ return true unless unique_expression&.assignment?
157
168
 
158
169
  lhs = unique_expression.child_nodes.first
159
170
  node.condition.child_nodes.none? { |n| n.source == lhs.source if n.variable? }
160
171
  end
161
172
 
162
- def check_expressions(node, expressions, insert_position) # rubocop:disable Metrics/MethodLength
173
+ def assignable_condition_value(node)
174
+ if node.condition.call_type?
175
+ (receiver = node.condition.receiver) ? receiver.source : node.condition.source
176
+ elsif node.condition.variable?
177
+ node.condition.source
178
+ end
179
+ end
180
+
181
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
182
+ def check_expressions(node, expressions, insert_position)
183
+ return if expressions.any?(&:nil?)
184
+
163
185
  inserted_expression = false
164
186
 
165
187
  expressions.each do |expression|
@@ -179,6 +201,17 @@ module RuboCop
179
201
  end
180
202
  end
181
203
  end
204
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
205
+
206
+ def last_child_of_parent?(node)
207
+ return true unless (parent = node.parent)
208
+
209
+ parent.child_nodes.last == node
210
+ end
211
+
212
+ def single_child_branch?(branch_node)
213
+ !branch_node.begin_type? || branch_node.children.size == 1
214
+ end
182
215
 
183
216
  def message(node)
184
217
  format(MSG, source: node.source)
@@ -59,11 +59,13 @@ module RuboCop
59
59
  # end
60
60
  #
61
61
  class IfInsideElse < Base
62
+ include IgnoredNode
62
63
  include RangeHelp
63
64
  extend AutoCorrector
64
65
 
65
66
  MSG = 'Convert `if` nested inside `else` to `elsif`.'
66
67
 
68
+ # rubocop:disable Metrics/CyclomaticComplexity
67
69
  def on_if(node)
68
70
  return if node.ternary? || node.unless?
69
71
 
@@ -73,9 +75,13 @@ module RuboCop
73
75
  return if allow_if_modifier_in_else_branch?(else_branch)
74
76
 
75
77
  add_offense(else_branch.loc.keyword) do |corrector|
78
+ next if part_of_ignored_node?(node)
79
+
76
80
  autocorrect(corrector, else_branch)
81
+ ignore_node(node)
77
82
  end
78
83
  end
84
+ # rubocop:enable Metrics/CyclomaticComplexity
79
85
 
80
86
  private
81
87
 
@@ -11,6 +11,32 @@ module RuboCop
11
11
  # cop. The tab size is configured in the `IndentationWidth` of the
12
12
  # `Layout/IndentationStyle` cop.
13
13
  #
14
+ # One-line pattern matching is always allowed. To ensure that there are few cases
15
+ # where the match variable is not used, and to prevent oversights. The variable `x`
16
+ # becomes undefined and raises `NameError` when the following example is changed to
17
+ # the modifier form:
18
+ #
19
+ # [source,ruby]
20
+ # ----
21
+ # if [42] in [x]
22
+ # x # `x` is undefined when using modifier form.
23
+ # end
24
+ # ----
25
+ #
26
+ # NOTE: It is allowed when `defined?` argument has an undefined value,
27
+ # because using the modifier form causes the following incompatibility:
28
+ #
29
+ # [source,ruby]
30
+ # ----
31
+ # unless defined?(undefined_foo)
32
+ # undefined_foo = 'default_value'
33
+ # end
34
+ # undefined_foo # => 'default_value'
35
+ #
36
+ # undefined_bar = 'default_value' unless defined?(undefined_bar)
37
+ # undefined_bar # => nil
38
+ # ----
39
+ #
14
40
  # @example
15
41
  # # bad
16
42
  # if condition
@@ -39,6 +65,7 @@ module RuboCop
39
65
  include LineLengthHelp
40
66
  include AllowedPattern
41
67
  include RangeHelp
68
+ include CommentsHelp
42
69
  extend AutoCorrector
43
70
 
44
71
  MSG_USE_MODIFIER = 'Favor modifier `%<keyword>s` usage when having a ' \
@@ -51,42 +78,96 @@ module RuboCop
51
78
  end
52
79
 
53
80
  def on_if(node)
54
- msg = if single_line_as_modifier?(node) && !named_capture_in_condition?(node)
55
- MSG_USE_MODIFIER
56
- elsif too_long_due_to_modifier?(node)
57
- MSG_USE_NORMAL
58
- end
59
- return unless msg
81
+ condition = node.condition
82
+ return if defined_nodes(condition).any? { |n| defined_argument_is_undefined?(node, n) } ||
83
+ pattern_matching_nodes(condition).any?
84
+ return unless (msg = message(node))
60
85
 
61
86
  add_offense(node.loc.keyword, message: format(msg, keyword: node.keyword)) do |corrector|
87
+ next if part_of_ignored_node?(node)
88
+
62
89
  autocorrect(corrector, node)
90
+ ignore_node(node)
63
91
  end
64
92
  end
65
93
 
66
94
  private
67
95
 
96
+ def defined_nodes(condition)
97
+ if condition.defined_type?
98
+ [condition]
99
+ else
100
+ condition.each_descendant.select(&:defined_type?)
101
+ end
102
+ end
103
+
104
+ def defined_argument_is_undefined?(if_node, defined_node)
105
+ defined_argument = defined_node.first_argument
106
+ return false unless defined_argument.lvar_type? || defined_argument.send_type?
107
+
108
+ if_node.left_siblings.none? do |sibling|
109
+ sibling.respond_to?(:lvasgn_type?) && sibling.lvasgn_type? &&
110
+ sibling.name == defined_argument.node_parts[0]
111
+ end
112
+ end
113
+
114
+ def pattern_matching_nodes(condition)
115
+ if condition.match_pattern_type? || condition.match_pattern_p_type?
116
+ [condition]
117
+ else
118
+ condition.each_descendant.select do |node|
119
+ node.match_pattern_type? || node.match_pattern_p_type?
120
+ end
121
+ end
122
+ end
123
+
124
+ def message(node)
125
+ if single_line_as_modifier?(node) && !named_capture_in_condition?(node)
126
+ MSG_USE_MODIFIER
127
+ elsif too_long_due_to_modifier?(node)
128
+ MSG_USE_NORMAL
129
+ end
130
+ end
131
+
68
132
  def autocorrect(corrector, node)
69
133
  replacement = if node.modifier_form?
70
- last_argument = node.if_branch.last_argument if node.if_branch.send_type?
71
-
72
- if last_argument.respond_to?(:heredoc?) && last_argument.heredoc?
73
- heredoc = extract_heredoc_from(last_argument)
74
- remove_heredoc(corrector, heredoc)
75
- to_normal_form_with_heredoc(node, indent(node), heredoc)
76
- else
77
- to_normal_form(node, indent(node))
78
- end
134
+ replacement_for_modifier_form(corrector, node)
79
135
  else
80
136
  to_modifier_form(node)
81
137
  end
82
138
  corrector.replace(node, replacement)
83
139
  end
84
140
 
141
+ def replacement_for_modifier_form(corrector, node) # rubocop:disable Metrics/AbcSize
142
+ comment = comment_on_node_line(node)
143
+ if comment && too_long_due_to_comment_after_modifier?(node, comment)
144
+ remove_comment(corrector, node, comment)
145
+
146
+ return to_modifier_form_with_move_comment(node, indent(node), comment)
147
+ end
148
+
149
+ last_argument = node.if_branch.last_argument if node.if_branch.send_type?
150
+ if last_argument.respond_to?(:heredoc?) && last_argument.heredoc?
151
+ heredoc = extract_heredoc_from(last_argument)
152
+ remove_heredoc(corrector, heredoc)
153
+
154
+ return to_normal_form_with_heredoc(node, indent(node), heredoc)
155
+ end
156
+
157
+ to_normal_form(node, indent(node))
158
+ end
159
+
85
160
  def too_long_due_to_modifier?(node)
86
161
  node.modifier_form? && too_long_single_line?(node) &&
87
162
  !another_statement_on_same_line?(node)
88
163
  end
89
164
 
165
+ def too_long_due_to_comment_after_modifier?(node, comment)
166
+ source_length = processed_source.lines[node.first_line - 1].length
167
+ source_length >= max_line_length &&
168
+ source_length - comment.source_range.length <= max_line_length
169
+ end
170
+
90
171
  def allowed_patterns
91
172
  line_length_config = config.for_cop('Layout/LineLength')
92
173
  line_length_config['AllowedPatterns'] || line_length_config['IgnoredPatterns'] || []
@@ -181,6 +262,13 @@ module RuboCop
181
262
  RUBY
182
263
  end
183
264
 
265
+ def to_modifier_form_with_move_comment(node, indentation, comment)
266
+ <<~RUBY.chomp
267
+ #{comment.source}
268
+ #{indentation}#{node.body.source} #{node.keyword} #{node.condition.source}
269
+ RUBY
270
+ end
271
+
184
272
  def extract_heredoc_from(last_argument)
185
273
  heredoc_body = last_argument.loc.heredoc_body
186
274
  heredoc_end = last_argument.loc.heredoc_end
@@ -193,6 +281,14 @@ module RuboCop
193
281
  corrector.remove(range_by_whole_lines(range, include_final_newline: true))
194
282
  end
195
283
  end
284
+
285
+ def comment_on_node_line(node)
286
+ processed_source.comments.find { |c| same_line?(c, node) }
287
+ end
288
+
289
+ def remove_comment(corrector, _node, comment)
290
+ corrector.remove(range_with_surrounding_space(range: comment.source_range, side: :left))
291
+ end
196
292
  end
197
293
  end
198
294
  end
@@ -118,6 +118,8 @@ module RuboCop
118
118
  end
119
119
 
120
120
  def return_boolean_value?(condition)
121
+ return false unless condition
122
+
121
123
  if condition.begin_type?
122
124
  return_boolean_value?(condition.children.first)
123
125
  elsif condition.or_type?
@@ -21,13 +21,12 @@ module RuboCop
21
21
  MSG_TERNARY = 'Do not use `if %<expr>s;` - use a ternary operator instead.'
22
22
 
23
23
  def on_normal_if_unless(node)
24
- return unless node.else_branch
25
24
  return if node.parent&.if_type?
26
25
 
27
26
  beginning = node.loc.begin
28
27
  return unless beginning&.is?(';')
29
28
 
30
- message = node.else_branch.if_type? ? MSG_IF_ELSE : MSG_TERNARY
29
+ message = node.else_branch&.if_type? ? MSG_IF_ELSE : MSG_TERNARY
31
30
 
32
31
  add_offense(node, message: format(message, expr: node.condition.source)) do |corrector|
33
32
  corrector.replace(node, autocorrect(node))
@@ -37,17 +36,18 @@ module RuboCop
37
36
  private
38
37
 
39
38
  def autocorrect(node)
40
- return correct_elsif(node) if node.else_branch.if_type?
39
+ return correct_elsif(node) if node.else_branch&.if_type?
41
40
 
41
+ then_code = node.if_branch ? node.if_branch.source : 'nil'
42
42
  else_code = node.else_branch ? node.else_branch.source : 'nil'
43
43
 
44
- "#{node.condition.source} ? #{node.if_branch.source} : #{else_code}"
44
+ "#{node.condition.source} ? #{then_code} : #{else_code}"
45
45
  end
46
46
 
47
47
  def correct_elsif(node)
48
48
  <<~RUBY.chop
49
49
  if #{node.condition.source}
50
- #{node.if_branch.source}
50
+ #{node.if_branch&.source}
51
51
  #{build_else_branch(node.else_branch).chop}
52
52
  end
53
53
  RUBY
@@ -56,7 +56,7 @@ module RuboCop
56
56
  def build_else_branch(second_condition)
57
57
  result = <<~RUBY
58
58
  elsif #{second_condition.condition.source}
59
- #{second_condition.if_branch.source}
59
+ #{second_condition.if_branch&.source}
60
60
  RUBY
61
61
 
62
62
  if second_condition.else_branch
@@ -21,6 +21,7 @@ module RuboCop
21
21
  # work
22
22
  # end
23
23
  class InfiniteLoop < Base
24
+ include Alignment
24
25
  extend AutoCorrector
25
26
 
26
27
  LEADING_SPACE = /\A(\s*)/.freeze
@@ -106,7 +107,7 @@ module RuboCop
106
107
  else
107
108
  indentation = body.source_range.source_line[LEADING_SPACE]
108
109
 
109
- ['loop do', body.source.gsub(/^/, configured_indent), 'end'].join("\n#{indentation}")
110
+ ['loop do', body.source.gsub(/^/, indentation(node)), 'end'].join("\n#{indentation}")
110
111
  end
111
112
  end
112
113
 
@@ -120,10 +121,6 @@ module RuboCop
120
121
 
121
122
  start_range.join(end_range)
122
123
  end
123
-
124
- def configured_indent
125
- ' ' * config.for_cop('Layout/IndentationWidth')['Width']
126
- end
127
124
  end
128
125
  end
129
126
  end
@@ -51,6 +51,8 @@ module RuboCop
51
51
  NEGATED_EQUALITY_METHODS = %i[!= !~].freeze
52
52
  CAMEL_CASE = /[A-Z]+[a-z]+/.freeze
53
53
 
54
+ RESTRICT_ON_SEND = [:!].freeze
55
+
54
56
  def self.autocorrect_incompatible_with
55
57
  [Style::Not, Style::SymbolProc]
56
58
  end
@@ -153,15 +155,15 @@ module RuboCop
153
155
  end
154
156
 
155
157
  def not_to_receiver(node, method_call)
156
- Parser::Source::Range.new(node.loc.expression.source_buffer,
158
+ Parser::Source::Range.new(node.source_range.source_buffer,
157
159
  node.loc.selector.begin_pos,
158
- method_call.loc.expression.begin_pos)
160
+ method_call.source_range.begin_pos)
159
161
  end
160
162
 
161
163
  def end_parentheses(node, method_call)
162
- Parser::Source::Range.new(node.loc.expression.source_buffer,
163
- method_call.loc.expression.end_pos,
164
- node.loc.expression.end_pos)
164
+ Parser::Source::Range.new(node.source_range.source_buffer,
165
+ method_call.source_range.end_pos,
166
+ node.source_range.end_pos)
165
167
  end
166
168
 
167
169
  # When comparing classes, `!(Integer < Numeric)` is not the same as