rubocop 1.31.1 → 1.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (462) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +5 -5
  4. data/config/default.yml +342 -52
  5. data/config/obsoletion.yml +23 -1
  6. data/exe/rubocop +1 -1
  7. data/lib/rubocop/arguments_env.rb +17 -0
  8. data/lib/rubocop/arguments_file.rb +17 -0
  9. data/lib/rubocop/cache_config.rb +29 -0
  10. data/lib/rubocop/cli/command/{auto_genenerate_config.rb → auto_generate_config.rb} +9 -2
  11. data/lib/rubocop/cli/command/execute_runner.rb +14 -9
  12. data/lib/rubocop/cli/command/init_dotfile.rb +1 -1
  13. data/lib/rubocop/cli/command/suggest_extensions.rb +61 -16
  14. data/lib/rubocop/cli.rb +56 -9
  15. data/lib/rubocop/comment_config.rb +60 -1
  16. data/lib/rubocop/config.rb +48 -20
  17. data/lib/rubocop/config_finder.rb +68 -0
  18. data/lib/rubocop/config_loader.rb +46 -68
  19. data/lib/rubocop/config_loader_resolver.rb +11 -12
  20. data/lib/rubocop/config_obsoletion/changed_parameter.rb +5 -0
  21. data/lib/rubocop/config_obsoletion/parameter_rule.rb +4 -0
  22. data/lib/rubocop/config_obsoletion.rb +9 -4
  23. data/lib/rubocop/config_validator.rb +1 -1
  24. data/lib/rubocop/cop/autocorrect_logic.rb +29 -13
  25. data/lib/rubocop/cop/badge.rb +9 -4
  26. data/lib/rubocop/cop/base.rb +115 -83
  27. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  28. data/lib/rubocop/cop/commissioner.rb +19 -6
  29. data/lib/rubocop/cop/cop.rb +54 -34
  30. data/lib/rubocop/cop/corrector.rb +31 -11
  31. data/lib/rubocop/cop/correctors/alignment_corrector.rb +3 -3
  32. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +3 -3
  33. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +3 -3
  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 +58 -0
  38. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  39. data/lib/rubocop/cop/gemspec/dependency_version.rb +17 -19
  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/require_mfa.rb +1 -1
  43. data/lib/rubocop/cop/generator/require_file_injector.rb +2 -2
  44. data/lib/rubocop/cop/generator.rb +5 -2
  45. data/lib/rubocop/cop/internal_affairs/cop_description.rb +8 -6
  46. data/lib/rubocop/cop/internal_affairs/create_empty_file.rb +37 -0
  47. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +111 -0
  48. data/lib/rubocop/cop/internal_affairs/inherit_deprecated_cop_class.rb +1 -1
  49. data/lib/rubocop/cop/internal_affairs/lambda_or_proc.rb +46 -0
  50. data/lib/rubocop/cop/internal_affairs/location_expression.rb +37 -0
  51. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +3 -3
  52. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -1
  53. data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +69 -0
  54. data/lib/rubocop/cop/internal_affairs/processed_source_buffer_name.rb +42 -0
  55. data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +11 -3
  56. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -1
  57. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +1 -1
  58. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +66 -0
  59. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +62 -0
  60. data/lib/rubocop/cop/internal_affairs/useless_restrict_on_send.rb +60 -0
  61. data/lib/rubocop/cop/internal_affairs.rb +9 -0
  62. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  63. data/lib/rubocop/cop/layout/block_alignment.rb +16 -12
  64. data/lib/rubocop/cop/layout/block_end_newline.rb +31 -9
  65. data/lib/rubocop/cop/layout/class_structure.rb +37 -27
  66. data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +1 -1
  67. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +2 -6
  68. data/lib/rubocop/cop/layout/comment_indentation.rb +3 -1
  69. data/lib/rubocop/cop/layout/empty_comment.rb +3 -3
  70. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +1 -1
  71. data/lib/rubocop/cop/layout/empty_lines.rb +3 -1
  72. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +7 -2
  73. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +2 -0
  74. data/lib/rubocop/cop/layout/end_alignment.rb +9 -1
  75. data/lib/rubocop/cop/layout/end_of_line.rb +4 -4
  76. data/lib/rubocop/cop/layout/extra_spacing.rb +15 -6
  77. data/lib/rubocop/cop/layout/first_argument_indentation.rb +15 -4
  78. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +6 -5
  79. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +35 -8
  80. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +5 -5
  81. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +36 -1
  82. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +57 -8
  83. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +52 -19
  84. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +10 -4
  85. data/lib/rubocop/cop/layout/heredoc_indentation.rb +8 -11
  86. data/lib/rubocop/cop/layout/indentation_style.rb +7 -2
  87. data/lib/rubocop/cop/layout/indentation_width.rb +6 -2
  88. data/lib/rubocop/cop/layout/initial_indentation.rb +1 -1
  89. data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
  90. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +80 -12
  91. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +18 -8
  92. data/lib/rubocop/cop/layout/line_length.rb +8 -1
  93. data/lib/rubocop/cop/layout/multiline_array_line_breaks.rb +31 -1
  94. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
  95. data/lib/rubocop/cop/layout/multiline_block_layout.rb +3 -1
  96. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +29 -1
  97. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +39 -2
  98. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +77 -0
  99. data/lib/rubocop/cop/layout/redundant_line_break.rb +9 -10
  100. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +2 -2
  101. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
  102. data/lib/rubocop/cop/layout/space_around_keyword.rb +3 -3
  103. data/lib/rubocop/cop/layout/space_around_operators.rb +1 -1
  104. data/lib/rubocop/cop/layout/space_before_block_braces.rb +2 -0
  105. data/lib/rubocop/cop/layout/space_before_first_arg.rb +1 -1
  106. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +2 -2
  107. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +22 -20
  108. data/lib/rubocop/cop/layout/space_inside_array_percent_literal.rb +3 -0
  109. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +27 -9
  110. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +30 -3
  111. data/lib/rubocop/cop/layout/space_inside_parens.rb +2 -2
  112. data/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb +34 -0
  113. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +10 -6
  114. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +5 -4
  115. data/lib/rubocop/cop/layout/trailing_empty_lines.rb +1 -1
  116. data/lib/rubocop/cop/layout/trailing_whitespace.rb +12 -5
  117. data/lib/rubocop/cop/legacy/corrections_proxy.rb +1 -1
  118. data/lib/rubocop/cop/legacy/corrector.rb +1 -1
  119. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +39 -8
  120. data/lib/rubocop/cop/lint/ambiguous_operator.rb +4 -0
  121. data/lib/rubocop/cop/lint/assignment_in_condition.rb +11 -1
  122. data/lib/rubocop/cop/lint/constant_resolution.rb +5 -1
  123. data/lib/rubocop/cop/lint/debugger.rb +27 -31
  124. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +66 -110
  125. data/lib/rubocop/cop/lint/deprecated_constants.rb +8 -1
  126. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
  127. data/lib/rubocop/cop/lint/duplicate_branch.rb +0 -2
  128. data/lib/rubocop/cop/lint/duplicate_magic_comment.rb +73 -0
  129. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +122 -0
  130. data/lib/rubocop/cop/lint/duplicate_methods.rb +48 -18
  131. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +26 -9
  132. data/lib/rubocop/cop/lint/duplicate_require.rb +1 -1
  133. data/lib/rubocop/cop/lint/else_layout.rb +3 -7
  134. data/lib/rubocop/cop/lint/empty_block.rb +3 -7
  135. data/lib/rubocop/cop/lint/empty_class.rb +3 -1
  136. data/lib/rubocop/cop/lint/empty_conditional_body.rb +110 -2
  137. data/lib/rubocop/cop/lint/empty_interpolation.rb +1 -1
  138. data/lib/rubocop/cop/lint/erb_new_arguments.rb +11 -11
  139. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +14 -7
  140. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +15 -17
  141. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  142. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -2
  143. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
  144. data/lib/rubocop/cop/lint/interpolation_check.rb +4 -3
  145. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  146. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +48 -2
  147. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +18 -3
  148. data/lib/rubocop/cop/lint/missing_super.rb +31 -2
  149. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
  150. data/lib/rubocop/cop/lint/nested_method_definition.rb +53 -9
  151. data/lib/rubocop/cop/lint/next_without_accumulator.rb +25 -6
  152. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +68 -28
  153. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +12 -0
  154. data/lib/rubocop/cop/lint/number_conversion.rb +28 -6
  155. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +2 -2
  156. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +2 -0
  157. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +4 -5
  158. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +17 -2
  159. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +5 -0
  160. data/lib/rubocop/cop/lint/percent_string_array.rb +1 -1
  161. data/lib/rubocop/cop/lint/percent_symbol_array.rb +1 -1
  162. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +49 -9
  163. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +6 -6
  164. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +7 -0
  165. data/lib/rubocop/cop/lint/redundant_require_statement.rb +48 -10
  166. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +13 -0
  167. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
  168. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +35 -15
  169. data/lib/rubocop/cop/lint/redundant_with_index.rb +14 -11
  170. data/lib/rubocop/cop/lint/redundant_with_object.rb +13 -12
  171. data/lib/rubocop/cop/lint/refinement_import_methods.rb +2 -1
  172. data/lib/rubocop/cop/lint/regexp_as_condition.rb +6 -0
  173. data/lib/rubocop/cop/lint/require_parentheses.rb +3 -1
  174. data/lib/rubocop/cop/lint/require_range_parentheses.rb +57 -0
  175. data/lib/rubocop/cop/lint/rescue_type.rb +3 -3
  176. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +41 -8
  177. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +1 -1
  178. data/lib/rubocop/cop/lint/script_permission.rb +1 -1
  179. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +5 -4
  180. data/lib/rubocop/cop/lint/shadowed_exception.rb +16 -11
  181. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +28 -3
  182. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  183. data/lib/rubocop/cop/lint/syntax.rb +4 -0
  184. data/lib/rubocop/cop/lint/to_enum_arguments.rb +13 -3
  185. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +23 -9
  186. data/lib/rubocop/cop/lint/unreachable_loop.rb +12 -6
  187. data/lib/rubocop/cop/lint/unused_method_argument.rb +6 -1
  188. data/lib/rubocop/cop/lint/useless_access_modifier.rb +17 -12
  189. data/lib/rubocop/cop/lint/useless_assignment.rb +56 -1
  190. data/lib/rubocop/cop/lint/useless_method_definition.rb +12 -4
  191. data/lib/rubocop/cop/lint/useless_rescue.rb +89 -0
  192. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +15 -5
  193. data/lib/rubocop/cop/lint/useless_times.rb +1 -1
  194. data/lib/rubocop/cop/lint/void.rb +92 -21
  195. data/lib/rubocop/cop/metrics/abc_size.rb +4 -2
  196. data/lib/rubocop/cop/metrics/block_length.rb +16 -11
  197. data/lib/rubocop/cop/metrics/block_nesting.rb +2 -2
  198. data/lib/rubocop/cop/metrics/class_length.rb +11 -5
  199. data/lib/rubocop/cop/metrics/collection_literal_length.rb +76 -0
  200. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
  201. data/lib/rubocop/cop/metrics/method_length.rb +17 -11
  202. data/lib/rubocop/cop/metrics/module_length.rb +10 -5
  203. data/lib/rubocop/cop/metrics/parameter_lists.rb +27 -0
  204. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  205. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +3 -6
  206. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +9 -6
  207. data/lib/rubocop/cop/migration/department_name.rb +1 -1
  208. data/lib/rubocop/cop/mixin/alignment.rb +2 -2
  209. data/lib/rubocop/cop/mixin/allowed_identifiers.rb +2 -2
  210. data/lib/rubocop/cop/mixin/allowed_methods.rb +23 -2
  211. data/lib/rubocop/cop/mixin/allowed_pattern.rb +17 -1
  212. data/lib/rubocop/cop/mixin/annotation_comment.rb +14 -7
  213. data/lib/rubocop/cop/mixin/check_line_breakable.rb +5 -1
  214. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  215. data/lib/rubocop/cop/mixin/comments_help.rb +29 -7
  216. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +21 -9
  217. data/lib/rubocop/cop/mixin/def_node.rb +2 -7
  218. data/lib/rubocop/cop/mixin/documentation_comment.rb +1 -1
  219. data/lib/rubocop/cop/mixin/enforce_superclass.rb +2 -1
  220. data/lib/rubocop/cop/mixin/first_element_line_break.rb +11 -7
  221. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -0
  222. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +1 -1
  223. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +152 -12
  224. data/lib/rubocop/cop/mixin/hash_transform_method.rb +13 -9
  225. data/lib/rubocop/cop/mixin/line_length_help.rb +11 -2
  226. data/lib/rubocop/cop/mixin/method_complexity.rb +13 -16
  227. data/lib/rubocop/cop/mixin/min_branches_count.rb +40 -0
  228. data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +7 -14
  229. data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +5 -6
  230. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
  231. data/lib/rubocop/cop/mixin/percent_array.rb +58 -1
  232. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +1 -1
  233. data/lib/rubocop/cop/mixin/range_help.rb +22 -5
  234. data/lib/rubocop/cop/mixin/require_library.rb +2 -0
  235. data/lib/rubocop/cop/mixin/rescue_node.rb +5 -3
  236. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  237. data/lib/rubocop/cop/mixin/statement_modifier.rb +18 -3
  238. data/lib/rubocop/cop/mixin/surrounding_space.rb +13 -11
  239. data/lib/rubocop/cop/mixin/trailing_comma.rb +2 -2
  240. data/lib/rubocop/cop/mixin/visibility_help.rb +40 -5
  241. data/lib/rubocop/cop/naming/ascii_identifiers.rb +1 -1
  242. data/lib/rubocop/cop/naming/block_forwarding.rb +5 -1
  243. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  244. data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +3 -1
  245. data/lib/rubocop/cop/naming/constant_name.rb +3 -3
  246. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +1 -1
  247. data/lib/rubocop/cop/naming/inclusive_language.rb +28 -6
  248. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +22 -7
  249. data/lib/rubocop/cop/naming/method_name.rb +3 -3
  250. data/lib/rubocop/cop/naming/predicate_name.rb +31 -2
  251. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +12 -4
  252. data/lib/rubocop/cop/registry.rb +73 -45
  253. data/lib/rubocop/cop/security/compound_hash.rb +2 -1
  254. data/lib/rubocop/cop/style/access_modifier_declarations.rb +92 -3
  255. data/lib/rubocop/cop/style/accessor_grouping.rb +46 -20
  256. data/lib/rubocop/cop/style/alias.rb +9 -1
  257. data/lib/rubocop/cop/style/arguments_forwarding.rb +6 -5
  258. data/lib/rubocop/cop/style/array_intersect.rb +111 -0
  259. data/lib/rubocop/cop/style/ascii_comments.rb +1 -1
  260. data/lib/rubocop/cop/style/attr.rb +11 -1
  261. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +1 -1
  262. data/lib/rubocop/cop/style/block_comments.rb +2 -2
  263. data/lib/rubocop/cop/style/block_delimiters.rb +44 -10
  264. data/lib/rubocop/cop/style/case_equality.rb +40 -10
  265. data/lib/rubocop/cop/style/case_like_if.rb +20 -3
  266. data/lib/rubocop/cop/style/character_literal.rb +1 -1
  267. data/lib/rubocop/cop/style/class_and_module_children.rb +8 -15
  268. data/lib/rubocop/cop/style/class_equality_comparison.rb +94 -12
  269. data/lib/rubocop/cop/style/class_methods_definitions.rb +2 -1
  270. data/lib/rubocop/cop/style/collection_compact.rb +21 -5
  271. data/lib/rubocop/cop/style/collection_methods.rb +2 -0
  272. data/lib/rubocop/cop/style/colon_method_call.rb +2 -2
  273. data/lib/rubocop/cop/style/combinable_loops.rb +29 -7
  274. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  275. data/lib/rubocop/cop/style/comment_annotation.rb +1 -1
  276. data/lib/rubocop/cop/style/commented_keyword.rb +2 -2
  277. data/lib/rubocop/cop/style/comparable_clamp.rb +125 -0
  278. data/lib/rubocop/cop/style/concat_array_literals.rb +94 -0
  279. data/lib/rubocop/cop/style/conditional_assignment.rb +8 -14
  280. data/lib/rubocop/cop/style/copyright.rb +6 -3
  281. data/lib/rubocop/cop/style/data_inheritance.rb +75 -0
  282. data/lib/rubocop/cop/style/dir_empty.rb +60 -0
  283. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +2 -2
  284. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +2 -2
  285. data/lib/rubocop/cop/style/documentation.rb +22 -10
  286. data/lib/rubocop/cop/style/documentation_method.rb +10 -4
  287. data/lib/rubocop/cop/style/double_negation.rb +4 -2
  288. data/lib/rubocop/cop/style/each_for_simple_loop.rb +41 -6
  289. data/lib/rubocop/cop/style/each_with_object.rb +40 -9
  290. data/lib/rubocop/cop/style/empty_block_parameter.rb +2 -2
  291. data/lib/rubocop/cop/style/empty_else.rb +37 -0
  292. data/lib/rubocop/cop/style/empty_heredoc.rb +73 -0
  293. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +2 -2
  294. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  295. data/lib/rubocop/cop/style/endless_method.rb +1 -1
  296. data/lib/rubocop/cop/style/eval_with_location.rb +4 -4
  297. data/lib/rubocop/cop/style/exact_regexp_match.rb +62 -0
  298. data/lib/rubocop/cop/style/explicit_block_argument.rb +5 -1
  299. data/lib/rubocop/cop/style/fetch_env_var.rb +10 -177
  300. data/lib/rubocop/cop/style/file_empty.rb +71 -0
  301. data/lib/rubocop/cop/style/file_read.rb +1 -1
  302. data/lib/rubocop/cop/style/file_write.rb +1 -1
  303. data/lib/rubocop/cop/style/for.rb +2 -0
  304. data/lib/rubocop/cop/style/format_string_token.rb +25 -6
  305. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  306. data/lib/rubocop/cop/style/guard_clause.rb +127 -38
  307. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +1 -0
  308. data/lib/rubocop/cop/style/hash_each_methods.rb +48 -12
  309. data/lib/rubocop/cop/style/hash_except.rb +27 -16
  310. data/lib/rubocop/cop/style/hash_like_case.rb +3 -9
  311. data/lib/rubocop/cop/style/hash_syntax.rb +26 -2
  312. data/lib/rubocop/cop/style/identical_conditional_branches.rb +15 -0
  313. data/lib/rubocop/cop/style/if_inside_else.rb +6 -0
  314. data/lib/rubocop/cop/style/if_unless_modifier.rb +112 -16
  315. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +29 -2
  316. data/lib/rubocop/cop/style/if_with_semicolon.rb +4 -4
  317. data/lib/rubocop/cop/style/infinite_loop.rb +2 -5
  318. data/lib/rubocop/cop/style/inverse_methods.rb +15 -11
  319. data/lib/rubocop/cop/style/invertible_unless_condition.rb +118 -0
  320. data/lib/rubocop/cop/style/line_end_concatenation.rb +4 -1
  321. data/lib/rubocop/cop/style/magic_comment_format.rb +307 -0
  322. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +2 -2
  323. data/lib/rubocop/cop/style/map_to_hash.rb +4 -1
  324. data/lib/rubocop/cop/style/map_to_set.rb +64 -0
  325. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +40 -24
  326. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +5 -1
  327. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +48 -41
  328. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +21 -2
  329. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +4 -1
  330. data/lib/rubocop/cop/style/method_def_parentheses.rb +11 -4
  331. data/lib/rubocop/cop/style/min_max.rb +3 -3
  332. data/lib/rubocop/cop/style/min_max_comparison.rb +83 -0
  333. data/lib/rubocop/cop/style/missing_else.rb +13 -1
  334. data/lib/rubocop/cop/style/mixin_grouping.rb +4 -4
  335. data/lib/rubocop/cop/style/module_function.rb +30 -8
  336. data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -1
  337. data/lib/rubocop/cop/style/multiline_if_modifier.rb +0 -4
  338. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -1
  339. data/lib/rubocop/cop/style/multiline_memoization.rb +2 -2
  340. data/lib/rubocop/cop/style/multiline_method_signature.rb +7 -4
  341. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +18 -3
  342. data/lib/rubocop/cop/style/negated_if_else_condition.rb +17 -10
  343. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +9 -0
  344. data/lib/rubocop/cop/style/next.rb +3 -5
  345. data/lib/rubocop/cop/style/nil_lambda.rb +4 -4
  346. data/lib/rubocop/cop/style/numbered_parameters_limit.rb +11 -3
  347. data/lib/rubocop/cop/style/numeric_literals.rb +16 -1
  348. data/lib/rubocop/cop/style/numeric_predicate.rb +43 -9
  349. data/lib/rubocop/cop/style/object_then.rb +5 -0
  350. data/lib/rubocop/cop/style/one_line_conditional.rb +3 -6
  351. data/lib/rubocop/cop/style/operator_method_call.rb +67 -0
  352. data/lib/rubocop/cop/style/parallel_assignment.rb +29 -19
  353. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -3
  354. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  355. data/lib/rubocop/cop/style/perl_backrefs.rb +22 -1
  356. data/lib/rubocop/cop/style/proc.rb +4 -1
  357. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  358. data/lib/rubocop/cop/style/redundant_argument.rb +3 -0
  359. data/lib/rubocop/cop/style/redundant_begin.rb +3 -0
  360. data/lib/rubocop/cop/style/redundant_condition.rb +41 -8
  361. data/lib/rubocop/cop/style/redundant_conditional.rb +0 -4
  362. data/lib/rubocop/cop/style/redundant_constant_base.rb +85 -0
  363. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +45 -0
  364. data/lib/rubocop/cop/style/redundant_each.rb +116 -0
  365. data/lib/rubocop/cop/style/redundant_fetch_block.rb +7 -5
  366. data/lib/rubocop/cop/style/redundant_heredoc_delimiter_quotes.rb +58 -0
  367. data/lib/rubocop/cop/style/redundant_initialize.rb +3 -1
  368. data/lib/rubocop/cop/style/redundant_interpolation.rb +2 -2
  369. data/lib/rubocop/cop/style/redundant_line_continuation.rb +183 -0
  370. data/lib/rubocop/cop/style/redundant_parentheses.rb +22 -24
  371. data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
  372. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +9 -3
  373. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +21 -4
  374. data/lib/rubocop/cop/style/redundant_return.rb +7 -0
  375. data/lib/rubocop/cop/style/redundant_self.rb +2 -0
  376. data/lib/rubocop/cop/style/redundant_sort.rb +24 -9
  377. data/lib/rubocop/cop/style/redundant_sort_by.rb +24 -8
  378. data/lib/rubocop/cop/style/redundant_string_escape.rb +183 -0
  379. data/lib/rubocop/cop/style/regexp_literal.rb +11 -2
  380. data/lib/rubocop/cop/style/require_order.rb +138 -0
  381. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
  382. data/lib/rubocop/cop/style/rescue_standard_error.rb +2 -2
  383. data/lib/rubocop/cop/style/safe_navigation.rb +41 -10
  384. data/lib/rubocop/cop/style/select_by_regexp.rb +13 -5
  385. data/lib/rubocop/cop/style/self_assignment.rb +2 -2
  386. data/lib/rubocop/cop/style/semicolon.rb +63 -5
  387. data/lib/rubocop/cop/style/signal_exception.rb +8 -6
  388. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  389. data/lib/rubocop/cop/style/slicing_with_range.rb +1 -1
  390. data/lib/rubocop/cop/style/sole_nested_conditional.rb +17 -8
  391. data/lib/rubocop/cop/style/special_global_vars.rb +2 -2
  392. data/lib/rubocop/cop/style/static_class.rb +32 -1
  393. data/lib/rubocop/cop/style/stderr_puts.rb +1 -1
  394. data/lib/rubocop/cop/style/string_hash_keys.rb +4 -1
  395. data/lib/rubocop/cop/style/string_literals.rb +1 -5
  396. data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
  397. data/lib/rubocop/cop/style/symbol_array.rb +6 -5
  398. data/lib/rubocop/cop/style/symbol_proc.rb +42 -10
  399. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -13
  400. data/lib/rubocop/cop/style/top_level_method_definition.rb +3 -1
  401. data/lib/rubocop/cop/style/trailing_body_on_class.rb +1 -0
  402. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -4
  403. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
  404. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +1 -1
  405. data/lib/rubocop/cop/style/trivial_accessors.rb +4 -1
  406. data/lib/rubocop/cop/style/unless_logical_operators.rb +1 -0
  407. data/lib/rubocop/cop/style/unpack_first.rb +3 -3
  408. data/lib/rubocop/cop/style/word_array.rb +59 -5
  409. data/lib/rubocop/cop/style/yoda_condition.rb +13 -6
  410. data/lib/rubocop/cop/style/yoda_expression.rb +90 -0
  411. data/lib/rubocop/cop/style/zero_length_predicate.rb +40 -19
  412. data/lib/rubocop/cop/team.rb +63 -56
  413. data/lib/rubocop/cop/util.rb +44 -8
  414. data/lib/rubocop/cop/variable_force/assignment.rb +5 -1
  415. data/lib/rubocop/cop/variable_force/scope.rb +3 -3
  416. data/lib/rubocop/cop/variable_force/variable.rb +5 -3
  417. data/lib/rubocop/cop/variable_force/variable_table.rb +6 -4
  418. data/lib/rubocop/cop/variable_force.rb +18 -30
  419. data/lib/rubocop/cops_documentation_generator.rb +45 -15
  420. data/lib/rubocop/directive_comment.rb +4 -4
  421. data/lib/rubocop/ext/comment.rb +18 -0
  422. data/lib/rubocop/ext/processed_source.rb +2 -0
  423. data/lib/rubocop/ext/range.rb +15 -0
  424. data/lib/rubocop/ext/regexp_node.rb +1 -1
  425. data/lib/rubocop/ext/regexp_parser.rb +1 -1
  426. data/lib/rubocop/feature_loader.rb +94 -0
  427. data/lib/rubocop/file_patterns.rb +43 -0
  428. data/lib/rubocop/formatter/clang_style_formatter.rb +1 -1
  429. data/lib/rubocop/formatter/disabled_config_formatter.rb +26 -9
  430. data/lib/rubocop/formatter/html_formatter.rb +4 -4
  431. data/lib/rubocop/formatter/junit_formatter.rb +4 -1
  432. data/lib/rubocop/formatter/markdown_formatter.rb +1 -1
  433. data/lib/rubocop/formatter/offense_count_formatter.rb +8 -5
  434. data/lib/rubocop/formatter/simple_text_formatter.rb +1 -1
  435. data/lib/rubocop/formatter/tap_formatter.rb +1 -1
  436. data/lib/rubocop/formatter/worst_offenders_formatter.rb +6 -3
  437. data/lib/rubocop/formatter.rb +4 -1
  438. data/lib/rubocop/options.rb +55 -22
  439. data/lib/rubocop/path_util.rb +50 -22
  440. data/lib/rubocop/rake_task.rb +5 -1
  441. data/lib/rubocop/result_cache.rb +26 -24
  442. data/lib/rubocop/rspec/cop_helper.rb +26 -3
  443. data/lib/rubocop/rspec/expect_offense.rb +6 -4
  444. data/lib/rubocop/rspec/shared_contexts.rb +31 -14
  445. data/lib/rubocop/rspec/support.rb +17 -2
  446. data/lib/rubocop/runner.rb +73 -18
  447. data/lib/rubocop/server/cache.rb +48 -2
  448. data/lib/rubocop/server/cli.rb +62 -19
  449. data/lib/rubocop/server/client_command/base.rb +1 -1
  450. data/lib/rubocop/server/client_command/exec.rb +6 -1
  451. data/lib/rubocop/server/client_command/start.rb +6 -1
  452. data/lib/rubocop/server/core.rb +42 -10
  453. data/lib/rubocop/server/helper.rb +1 -1
  454. data/lib/rubocop/server/server_command/exec.rb +1 -1
  455. data/lib/rubocop/server/socket_reader.rb +5 -1
  456. data/lib/rubocop/server.rb +1 -1
  457. data/lib/rubocop/target_finder.rb +1 -1
  458. data/lib/rubocop/target_ruby.rb +5 -5
  459. data/lib/rubocop/version.rb +10 -4
  460. data/lib/rubocop.rb +45 -9
  461. metadata +58 -33
  462. data/lib/rubocop/cop/mixin/ignored_methods.rb +0 -52
@@ -7,12 +7,15 @@ module RuboCop
7
7
  #
8
8
  # If you prefer a style that allows block for method with arguments,
9
9
  # please set `true` to `AllowMethodsWithArguments`.
10
+ # `define_method?` methods are allowed by default.
11
+ # These are customizable with `AllowedMethods` option.
10
12
  #
11
13
  # @safety
12
- # This cop is unsafe because `proc`s and blocks work differently
13
- # when additional arguments are passed in. A block will silently
14
- # ignore additional arguments, but a `proc` will raise
15
- # an `ArgumentError`.
14
+ # This cop is unsafe because there is a difference that a `Proc`
15
+ # generated from `Symbol#to_proc` behaves as a lambda, while
16
+ # a `Proc` generated from a block does not.
17
+ # For example, a lambda will raise an `ArgumentError` if the
18
+ # number of arguments is wrong, but a non-lambda `Proc` will not.
16
19
  #
17
20
  # For example:
18
21
  #
@@ -68,10 +71,24 @@ module RuboCop
68
71
  # s.upcase # some comment
69
72
  # # some comment
70
73
  # end
74
+ #
75
+ # @example AllowedMethods: [define_method] (default)
76
+ # # good
77
+ # define_method(:foo) { |foo| foo.bar }
78
+ #
79
+ # @example AllowedPatterns: [] (default)
80
+ # # bad
81
+ # something.map { |s| s.upcase }
82
+ #
83
+ # @example AllowedPatterns: ['map'] (default)
84
+ # # good
85
+ # something.map { |s| s.upcase }
86
+ #
71
87
  class SymbolProc < Base
72
88
  include CommentsHelp
73
89
  include RangeHelp
74
- include IgnoredMethods
90
+ include AllowedMethods
91
+ include AllowedPattern
75
92
  extend AutoCorrector
76
93
 
77
94
  MSG = 'Pass `&:%<method>s` as an argument to `%<block_method>s` instead of a block.'
@@ -81,7 +98,7 @@ module RuboCop
81
98
  def_node_matcher :proc_node?, '(send (const {nil? cbase} :Proc) :new)'
82
99
 
83
100
  # @!method symbol_proc_receiver?(node)
84
- def_node_matcher :symbol_proc_receiver?, '{(send ...) (super ...) zsuper}'
101
+ def_node_matcher :symbol_proc_receiver?, '{(call ...) (super ...) zsuper}'
85
102
 
86
103
  # @!method symbol_proc?(node)
87
104
  def_node_matcher :symbol_proc?, <<~PATTERN
@@ -95,15 +112,17 @@ module RuboCop
95
112
  [Layout::SpaceBeforeBlockBraces]
96
113
  end
97
114
 
98
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
115
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
99
116
  def on_block(node)
100
117
  symbol_proc?(node) do |dispatch_node, arguments_node, method_name|
101
118
  # TODO: Rails-specific handling that we should probably make
102
119
  # configurable - https://github.com/rubocop/rubocop/issues/1485
103
- # we should ignore lambdas & procs
120
+ # we should allow lambdas & procs
104
121
  return if proc_node?(dispatch_node)
122
+ return if unsafe_hash_usage?(dispatch_node)
123
+ return if unsafe_array_usage?(dispatch_node)
105
124
  return if %i[lambda proc].include?(dispatch_node.method_name)
106
- return if ignored_method?(dispatch_node.method_name)
125
+ return if allowed_method_name?(dispatch_node.method_name)
107
126
  return if allow_if_method_has_argument?(node.send_node)
108
127
  return if node.block_type? && destructuring_block_argument?(arguments_node)
109
128
  return if allow_comments? && contains_comments?(node)
@@ -111,7 +130,7 @@ module RuboCop
111
130
  register_offense(node, method_name, dispatch_node.method_name)
112
131
  end
113
132
  end
114
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
133
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
115
134
  alias on_numblock on_block
116
135
 
117
136
  def destructuring_block_argument?(argument_node)
@@ -120,6 +139,19 @@ module RuboCop
120
139
 
121
140
  private
122
141
 
142
+ # See: https://github.com/rubocop/rubocop/issues/10864
143
+ def unsafe_hash_usage?(node)
144
+ node.receiver&.hash_type? && %i[reject select].include?(node.method_name)
145
+ end
146
+
147
+ def unsafe_array_usage?(node)
148
+ node.receiver&.array_type? && %i[min max].include?(node.method_name)
149
+ end
150
+
151
+ def allowed_method_name?(name)
152
+ allowed_method?(name) || matches_allowed_pattern?(name)
153
+ end
154
+
123
155
  def register_offense(node, method_name, block_method_name)
124
156
  block_start = node.loc.begin.begin_pos
125
157
  block_end = node.loc.end.end_pos
@@ -71,7 +71,7 @@ module RuboCop
71
71
 
72
72
  return if only_closing_parenthesis_is_last_line?(condition)
73
73
  return if condition_as_parenthesized_one_line_pattern_matching?(condition)
74
- return unless node.ternary? && !infinite_loop? && offense?(node)
74
+ return unless node.ternary? && offense?(node)
75
75
 
76
76
  message = message(node)
77
77
 
@@ -166,22 +166,10 @@ module RuboCop
166
166
  style == :require_parentheses_when_complex
167
167
  end
168
168
 
169
- def redundant_parentheses_enabled?
170
- @config.for_cop('Style/RedundantParentheses').fetch('Enabled')
171
- end
172
-
173
169
  def parenthesized?(node)
174
170
  node.begin_type?
175
171
  end
176
172
 
177
- # When this cop is configured to enforce parentheses and the
178
- # `RedundantParentheses` cop is enabled, it will cause an infinite loop
179
- # as they compete to add and remove the parentheses respectively.
180
- def infinite_loop?
181
- (require_parentheses? || require_parentheses_when_complex?) &&
182
- redundant_parentheses_enabled?
183
- end
184
-
185
173
  def unsafe_autocorrect?(condition)
186
174
  condition.children.any? do |child|
187
175
  unparenthesized_method_call?(child) || below_ternary_precedence?(child)
@@ -63,6 +63,8 @@ module RuboCop
63
63
  add_offense(node)
64
64
  end
65
65
 
66
+ alias on_numblock on_block
67
+
66
68
  private
67
69
 
68
70
  def top_level_method_definition?(node)
@@ -75,7 +77,7 @@ module RuboCop
75
77
 
76
78
  # @!method define_method_block?(node)
77
79
  def_node_matcher :define_method_block?, <<~PATTERN
78
- (block (send _ {:define_method} _) ...)
80
+ ({block numblock} (send _ {:define_method} _) ...)
79
81
  PATTERN
80
82
  end
81
83
  end
@@ -34,6 +34,7 @@ module RuboCop
34
34
  )
35
35
  end
36
36
  end
37
+ alias on_sclass on_class
37
38
  end
38
39
  end
39
40
  end
@@ -88,6 +88,10 @@ module RuboCop
88
88
  include TrailingComma
89
89
  extend AutoCorrector
90
90
 
91
+ def self.autocorrect_incompatible_with
92
+ [Layout::HeredocArgumentClosingParenthesis]
93
+ end
94
+
91
95
  def on_send(node)
92
96
  return unless node.arguments? && node.parenthesized?
93
97
 
@@ -96,10 +100,6 @@ module RuboCop
96
100
  node.source_range.end_pos)
97
101
  end
98
102
  alias on_csend on_send
99
-
100
- def self.autocorrect_incompatible_with
101
- [Layout::HeredocArgumentClosingParenthesis]
102
- end
103
103
  end
104
104
  end
105
105
  end
@@ -64,7 +64,7 @@ module RuboCop
64
64
 
65
65
  MSG = 'Useless trailing comma present in block arguments.'
66
66
 
67
- def on_block(node)
67
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
68
68
  # lambda literal (`->`) never has block arguments.
69
69
  return if node.send_node.lambda_literal?
70
70
  return unless useless_trailing_comma?(node)
@@ -144,7 +144,7 @@ module RuboCop
144
144
  end
145
145
 
146
146
  def range_for_parentheses(offense, left)
147
- range_between(offense.source_range.begin_pos - 1, left.loc.expression.end_pos - 1)
147
+ range_between(offense.source_range.begin_pos - 1, left.source_range.end_pos - 1)
148
148
  end
149
149
  end
150
150
  end
@@ -5,6 +5,9 @@ module RuboCop
5
5
  module Style
6
6
  # Looks for trivial reader/writer methods, that could
7
7
  # have been created with the attr_* family of functions automatically.
8
+ # `to_ary`, `to_a`, `to_c`, `to_enum`, `to_h`, `to_hash`, `to_i`, `to_int`, `to_io`,
9
+ # `to_open`, `to_path`, `to_proc`, `to_r`, `to_regexp`, `to_str`, `to_s`, and `to_sym` methods
10
+ # are allowed by default. These are customizable with `AllowedMethods` option.
8
11
  #
9
12
  # @example
10
13
  # # bad
@@ -235,7 +238,7 @@ module RuboCop
235
238
 
236
239
  indent = ' ' * node.loc.column
237
240
  corrector.replace(
238
- node.source_range,
241
+ node,
239
242
  ['class << self',
240
243
  "#{indent} #{accessor(kind, node.method_name)}",
241
244
  "#{indent}end"].join("\n")
@@ -8,6 +8,7 @@ module RuboCop
8
8
  # to read and understand.
9
9
  #
10
10
  # This cop supports two styles:
11
+ #
11
12
  # - `forbid_mixed_logical_operators` (default)
12
13
  # - `forbid_logical_operators`
13
14
  #
@@ -52,9 +52,9 @@ module RuboCop
52
52
  private
53
53
 
54
54
  def first_element_range(node, unpack_call)
55
- Parser::Source::Range.new(node.loc.expression.source_buffer,
56
- unpack_call.loc.expression.end_pos,
57
- node.loc.expression.end_pos)
55
+ Parser::Source::Range.new(node.source_range.source_buffer,
56
+ unpack_call.source_range.end_pos,
57
+ node.source_range.end_pos)
58
58
  end
59
59
  end
60
60
  end
@@ -27,6 +27,25 @@ module RuboCop
27
27
  # # bad (contains spaces)
28
28
  # %w[foo\ bar baz\ quux]
29
29
  #
30
+ # # bad
31
+ # [
32
+ # ['one', 'One'],
33
+ # ['two', 'Two']
34
+ # ]
35
+ #
36
+ # # good
37
+ # [
38
+ # %w[one One],
39
+ # %w[two Two]
40
+ # ]
41
+ #
42
+ # # good (2d array containing spaces)
43
+ # [
44
+ # ['one', 'One'],
45
+ # ['two', 'Two'],
46
+ # ['forty two', 'Forty Two']
47
+ # ]
48
+ #
30
49
  # @example EnforcedStyle: brackets
31
50
  # # good
32
51
  # ['foo', 'bar', 'baz']
@@ -36,6 +55,19 @@ module RuboCop
36
55
  #
37
56
  # # good (contains spaces)
38
57
  # ['foo bar', 'baz quux']
58
+ #
59
+ # # good
60
+ # [
61
+ # ['one', 'One'],
62
+ # ['two', 'Two']
63
+ # ]
64
+ #
65
+ # # bad
66
+ # [
67
+ # %w[one One],
68
+ # %w[two Two]
69
+ # ]
70
+ #
39
71
  class WordArray < Base
40
72
  include ArrayMinSize
41
73
  include ArraySyntax
@@ -44,15 +76,25 @@ module RuboCop
44
76
  extend AutoCorrector
45
77
 
46
78
  PERCENT_MSG = 'Use `%w` or `%W` for an array of words.'
47
- ARRAY_MSG = 'Use `%<prefer>s` for an array of words.'
79
+ ARRAY_MSG = 'Use %<prefer>s for an array of words.'
48
80
 
49
81
  class << self
50
82
  attr_accessor :largest_brackets
51
83
  end
52
84
 
85
+ def on_new_investigation
86
+ super
87
+
88
+ # Prevent O(n2) checks (checking the entire matrix once for each child array) by caching
89
+ @matrix_of_complex_content_cache = Hash.new do |cache, node|
90
+ cache[node] = matrix_of_complex_content?(node)
91
+ end
92
+ end
93
+
53
94
  def on_array(node)
54
95
  if bracketed_array_of?(:str, node)
55
96
  return if complex_content?(node.values)
97
+ return if within_matrix_of_complex_content?(node)
56
98
 
57
99
  check_bracketed_array(node, 'w')
58
100
  elsif node.percent_literal?(:string)
@@ -62,6 +104,17 @@ module RuboCop
62
104
 
63
105
  private
64
106
 
107
+ def within_matrix_of_complex_content?(node)
108
+ return false unless (parent = node.parent)
109
+
110
+ parent.array_type? && @matrix_of_complex_content_cache[parent]
111
+ end
112
+
113
+ def matrix_of_complex_content?(array)
114
+ array.values.all?(&:array_type?) &&
115
+ array.values.any? { |subarray| complex_content?(subarray.values) }
116
+ end
117
+
65
118
  def complex_content?(strings, complex_regex: word_regex)
66
119
  strings.any? do |s|
67
120
  next unless s.str_content
@@ -69,7 +122,7 @@ module RuboCop
69
122
  string = s.str_content.dup.force_encoding(::Encoding::UTF_8)
70
123
  !string.valid_encoding? ||
71
124
  (complex_regex && !complex_regex.match?(string)) ||
72
- / /.match?(string)
125
+ string.include?(' ')
73
126
  end
74
127
  end
75
128
 
@@ -83,17 +136,18 @@ module RuboCop
83
136
  end
84
137
 
85
138
  def build_bracketed_array(node)
139
+ return '[]' if node.children.empty?
140
+
86
141
  words = node.children.map do |word|
87
142
  if word.dstr_type?
88
143
  string_literal = to_string_literal(word.source)
89
144
 
90
- trim_string_interporation_escape_character(string_literal)
145
+ trim_string_interpolation_escape_character(string_literal)
91
146
  else
92
147
  to_string_literal(word.children[0])
93
148
  end
94
149
  end
95
-
96
- "[#{words.join(', ')}]"
150
+ build_bracketed_array_with_appropriate_whitespace(elements: words, node: node)
97
151
  end
98
152
  end
99
153
  end
@@ -33,12 +33,14 @@ module RuboCop
33
33
  # "bar" != foo
34
34
  # 42 >= foo
35
35
  # 10 < bar
36
+ # 99 == CONST
36
37
  #
37
38
  # # good
38
39
  # foo == 99
39
40
  # foo == "bar"
40
41
  # foo <= 42
41
42
  # bar > 10
43
+ # CONST == 99
42
44
  # "#{interpolation}" == foo
43
45
  # /#{interpolation}/ == foo
44
46
  #
@@ -92,9 +94,10 @@ module RuboCop
92
94
  def on_send(node)
93
95
  return unless yoda_compatible_condition?(node)
94
96
  return if (equality_only? && non_equality_operator?(node)) ||
95
- file_constant_equal_program_name?(node)
97
+ file_constant_equal_program_name?(node) ||
98
+ valid_yoda?(node)
96
99
 
97
- valid_yoda?(node) || add_offense(node) do |corrector|
100
+ add_offense(node) do |corrector|
98
101
  corrector.replace(actual_code_range(node), corrected_code(node))
99
102
  end
100
103
  end
@@ -119,11 +122,11 @@ module RuboCop
119
122
  lhs = node.receiver
120
123
  rhs = node.first_argument
121
124
 
122
- return true if (lhs.literal? && rhs.literal?) ||
123
- (!lhs.literal? && !rhs.literal?) ||
125
+ return true if (constant_portion?(lhs) && constant_portion?(rhs)) ||
126
+ (!constant_portion?(lhs) && !constant_portion?(rhs)) ||
124
127
  interpolation?(lhs)
125
128
 
126
- enforce_yoda? ? lhs.literal? : rhs.literal?
129
+ enforce_yoda? ? constant_portion?(lhs) : constant_portion?(rhs)
127
130
  end
128
131
 
129
132
  def message(node)
@@ -137,8 +140,12 @@ module RuboCop
137
140
  "#{rhs.source} #{reverse_comparison(node.method_name)} #{lhs.source}"
138
141
  end
139
142
 
143
+ def constant_portion?(node)
144
+ node.literal? || node.const_type?
145
+ end
146
+
140
147
  def actual_code_range(node)
141
- range_between(node.loc.expression.begin_pos, node.loc.expression.end_pos)
148
+ range_between(node.source_range.begin_pos, node.source_range.end_pos)
142
149
  end
143
150
 
144
151
  def reverse_comparison(operator)
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Forbids Yoda expressions, i.e. binary operations (using `*`, `+`, `&`, `|`,
7
+ # and `^` operators) where the order of expression is reversed, eg. `1 + x`.
8
+ # This cop complements `Style/YodaCondition` cop, which has a similar purpose.
9
+ #
10
+ # This cop is disabled by default to respect user intentions such as:
11
+ #
12
+ # [source,ruby]
13
+ # ----
14
+ # config.server_port = 9000 + ENV["TEST_ENV_NUMBER"].to_i
15
+ # ----
16
+ #
17
+ # @safety
18
+ # This cop is unsafe because binary operators can be defined
19
+ # differently on different classes, and are not guaranteed to
20
+ # have the same result if reversed.
21
+ #
22
+ # @example SupportedOperators: ['*', '+', '&'']
23
+ # # bad
24
+ # 1 + x
25
+ # 10 * y
26
+ # 1 & z
27
+ # 1 + CONST
28
+ #
29
+ # # good
30
+ # 60 * 24
31
+ # x + 1
32
+ # y * 10
33
+ # z & 1
34
+ # CONST + 1
35
+ #
36
+ # # good
37
+ # 1 | x
38
+ #
39
+ class YodaExpression < Base
40
+ extend AutoCorrector
41
+
42
+ MSG = 'Non-literal operand (`%<source>s`) should be first.'
43
+
44
+ RESTRICT_ON_SEND = %i[* + & | ^].freeze
45
+
46
+ def on_new_investigation
47
+ @offended_nodes = nil
48
+ end
49
+
50
+ def on_send(node)
51
+ return unless supported_operators.include?(node.method_name.to_s)
52
+
53
+ lhs = node.receiver
54
+ rhs = node.first_argument
55
+ return unless yoda_expression_constant?(lhs, rhs)
56
+ return if offended_ancestor?(node)
57
+
58
+ message = format(MSG, source: rhs.source)
59
+ add_offense(node, message: message) do |corrector|
60
+ corrector.swap(lhs, rhs)
61
+ end
62
+
63
+ offended_nodes.add(node)
64
+ end
65
+
66
+ private
67
+
68
+ def yoda_expression_constant?(lhs, rhs)
69
+ constant_portion?(lhs) && !constant_portion?(rhs)
70
+ end
71
+
72
+ def constant_portion?(node)
73
+ node.numeric_type? || node.const_type?
74
+ end
75
+
76
+ def supported_operators
77
+ Array(cop_config['SupportedOperators'])
78
+ end
79
+
80
+ def offended_ancestor?(node)
81
+ node.each_ancestor(:send).any? { |ancestor| @offended_nodes&.include?(ancestor) }
82
+ end
83
+
84
+ def offended_nodes
85
+ @offended_nodes ||= Set.new.compare_by_identity
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -4,10 +4,13 @@ module RuboCop
4
4
  module Cop
5
5
  module Style
6
6
  # Checks for numeric comparisons that can be replaced
7
- # by a predicate method, such as receiver.length == 0,
8
- # receiver.length > 0, receiver.length != 0,
9
- # receiver.length < 1 and receiver.size == 0 that can be
10
- # replaced by receiver.empty? and !receiver.empty?.
7
+ # by a predicate method, such as `receiver.length == 0`,
8
+ # `receiver.length > 0`, and `receiver.length != 0`,
9
+ # `receiver.length < 1` and `receiver.size == 0` that can be
10
+ # replaced by `receiver.empty?` and `!receiver.empty?`.
11
+ #
12
+ # NOTE: `File`, `Tempfile`, and `StringIO` do not have `empty?`
13
+ # so allow `size == 0` and `size.zero?`.
11
14
  #
12
15
  # @safety
13
16
  # This cop is unsafe because it cannot be guaranteed that the receiver
@@ -34,43 +37,56 @@ module RuboCop
34
37
  class ZeroLengthPredicate < Base
35
38
  extend AutoCorrector
36
39
 
37
- ZERO_MSG = 'Use `empty?` instead of `%<lhs>s %<opr>s %<rhs>s`.'
38
- NONZERO_MSG = 'Use `!empty?` instead of `%<lhs>s %<opr>s %<rhs>s`.'
40
+ ZERO_MSG = 'Use `empty?` instead of `%<current>s`.'
41
+ NONZERO_MSG = 'Use `!empty?` instead of `%<current>s`.'
39
42
 
40
43
  RESTRICT_ON_SEND = %i[size length].freeze
41
44
 
42
45
  def on_send(node)
43
46
  check_zero_length_predicate(node)
44
- check_nonzero_length_predicate(node)
47
+ check_zero_length_comparison(node)
48
+ check_nonzero_length_comparison(node)
45
49
  end
46
50
 
47
51
  private
48
52
 
49
53
  def check_zero_length_predicate(node)
50
- zero_length_predicate = zero_length_predicate(node.parent)
51
- return unless zero_length_predicate
54
+ return unless (length_method = zero_length_predicate(node.parent))
55
+ return if non_polymorphic_collection?(node.parent)
56
+
57
+ offense = node.loc.selector.join(node.parent.source_range.end)
58
+ message = format(ZERO_MSG, current: "#{length_method}.zero?")
52
59
 
53
- lhs, opr, rhs = zero_length_predicate
60
+ add_offense(offense, message: message) do |corrector|
61
+ corrector.replace(offense, 'empty?')
62
+ end
63
+ end
64
+
65
+ def check_zero_length_comparison(node)
66
+ zero_length_comparison = zero_length_comparison(node.parent)
67
+ return unless zero_length_comparison
68
+
69
+ lhs, opr, rhs = zero_length_comparison
54
70
 
55
71
  return if non_polymorphic_collection?(node.parent)
56
72
 
57
73
  add_offense(
58
- node.parent, message: format(ZERO_MSG, lhs: lhs, opr: opr, rhs: rhs)
74
+ node.parent, message: format(ZERO_MSG, current: "#{lhs} #{opr} #{rhs}")
59
75
  ) do |corrector|
60
76
  corrector.replace(node.parent, replacement(node.parent))
61
77
  end
62
78
  end
63
79
 
64
- def check_nonzero_length_predicate(node)
65
- nonzero_length_predicate = nonzero_length_predicate(node.parent)
66
- return unless nonzero_length_predicate
80
+ def check_nonzero_length_comparison(node)
81
+ nonzero_length_comparison = nonzero_length_comparison(node.parent)
82
+ return unless nonzero_length_comparison
67
83
 
68
- lhs, opr, rhs = nonzero_length_predicate
84
+ lhs, opr, rhs = nonzero_length_comparison
69
85
 
70
86
  return if non_polymorphic_collection?(node.parent)
71
87
 
72
88
  add_offense(
73
- node.parent, message: format(NONZERO_MSG, lhs: lhs, opr: opr, rhs: rhs)
89
+ node.parent, message: format(NONZERO_MSG, current: "#{lhs} #{opr} #{rhs}")
74
90
  ) do |corrector|
75
91
  corrector.replace(node.parent, replacement(node.parent))
76
92
  end
@@ -78,14 +94,19 @@ module RuboCop
78
94
 
79
95
  # @!method zero_length_predicate(node)
80
96
  def_node_matcher :zero_length_predicate, <<~PATTERN
97
+ (send (send (...) ${:length :size}) :zero?)
98
+ PATTERN
99
+
100
+ # @!method zero_length_comparison(node)
101
+ def_node_matcher :zero_length_comparison, <<~PATTERN
81
102
  {(send (send (...) ${:length :size}) $:== (int $0))
82
103
  (send (int $0) $:== (send (...) ${:length :size}))
83
104
  (send (send (...) ${:length :size}) $:< (int $1))
84
105
  (send (int $1) $:> (send (...) ${:length :size}))}
85
106
  PATTERN
86
107
 
87
- # @!method nonzero_length_predicate(node)
88
- def_node_matcher :nonzero_length_predicate, <<~PATTERN
108
+ # @!method nonzero_length_comparison(node)
109
+ def_node_matcher :nonzero_length_comparison, <<~PATTERN
89
110
  {(send (send (...) ${:length :size}) ${:> :!=} (int $0))
90
111
  (send (int $0) ${:< :!=} (send (...) ${:length :size}))}
91
112
  PATTERN
@@ -117,7 +138,7 @@ module RuboCop
117
138
  # @!method non_polymorphic_collection?(node)
118
139
  def_node_matcher :non_polymorphic_collection?, <<~PATTERN
119
140
  {(send (send (send (const {nil? cbase} :File) :stat _) ...) ...)
120
- (send (send (send (const {nil? cbase} {:Tempfile :StringIO}) {:new :open} ...) ...) ...)}
141
+ (send (send (send (const {nil? cbase} {:File :Tempfile :StringIO}) {:new :open} ...) ...) ...)}
121
142
  PATTERN
122
143
  end
123
144
  end