rubocop 1.46.0 → 1.52.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/config/default.yml +83 -11
  4. data/lib/rubocop/cli/command/auto_generate_config.rb +7 -0
  5. data/lib/rubocop/cli/command/execute_runner.rb +7 -2
  6. data/lib/rubocop/cli.rb +6 -6
  7. data/lib/rubocop/comment_config.rb +2 -0
  8. data/lib/rubocop/config.rb +7 -3
  9. data/lib/rubocop/config_loader.rb +8 -8
  10. data/lib/rubocop/config_obsoletion.rb +2 -2
  11. data/lib/rubocop/cop/autocorrect_logic.rb +29 -13
  12. data/lib/rubocop/cop/base.rb +6 -2
  13. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  14. data/lib/rubocop/cop/cop.rb +2 -2
  15. data/lib/rubocop/cop/corrector.rb +1 -1
  16. data/lib/rubocop/cop/correctors/alignment_corrector.rb +3 -3
  17. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +3 -3
  18. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +3 -3
  19. data/lib/rubocop/cop/correctors/line_break_corrector.rb +1 -1
  20. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +2 -2
  21. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +1 -1
  22. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
  23. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  24. data/lib/rubocop/cop/gemspec/dependency_version.rb +1 -1
  25. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -1
  26. data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
  27. data/lib/rubocop/cop/internal_affairs/cop_description.rb +37 -13
  28. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +3 -3
  29. data/lib/rubocop/cop/internal_affairs/inherit_deprecated_cop_class.rb +1 -1
  30. data/lib/rubocop/cop/internal_affairs/location_expression.rb +37 -0
  31. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +3 -3
  32. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -1
  33. data/lib/rubocop/cop/internal_affairs/processed_source_buffer_name.rb +1 -1
  34. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -1
  35. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +1 -1
  36. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +66 -0
  37. data/lib/rubocop/cop/internal_affairs.rb +2 -0
  38. data/lib/rubocop/cop/layout/block_end_newline.rb +7 -21
  39. data/lib/rubocop/cop/layout/class_structure.rb +6 -3
  40. data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +1 -2
  41. data/lib/rubocop/cop/layout/empty_comment.rb +3 -3
  42. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +1 -1
  43. data/lib/rubocop/cop/layout/empty_lines.rb +1 -1
  44. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +2 -0
  45. data/lib/rubocop/cop/layout/end_alignment.rb +5 -1
  46. data/lib/rubocop/cop/layout/extra_spacing.rb +6 -1
  47. data/lib/rubocop/cop/layout/first_argument_indentation.rb +7 -2
  48. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +25 -34
  49. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +7 -19
  50. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +42 -52
  51. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +38 -55
  52. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +4 -4
  53. data/lib/rubocop/cop/layout/heredoc_indentation.rb +2 -2
  54. data/lib/rubocop/cop/layout/initial_indentation.rb +1 -1
  55. data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
  56. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +1 -3
  57. data/lib/rubocop/cop/layout/multiline_array_line_breaks.rb +8 -27
  58. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +7 -26
  59. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +4 -21
  60. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +6 -30
  61. data/lib/rubocop/cop/layout/redundant_line_break.rb +6 -7
  62. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +2 -2
  63. data/lib/rubocop/cop/layout/space_before_first_arg.rb +1 -1
  64. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +2 -2
  65. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +3 -1
  66. data/lib/rubocop/cop/layout/space_inside_parens.rb +2 -2
  67. data/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb +1 -1
  68. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  69. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +13 -1
  70. data/lib/rubocop/cop/lint/constant_resolution.rb +1 -1
  71. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +4 -4
  72. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
  73. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +122 -0
  74. data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -2
  75. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -3
  76. data/lib/rubocop/cop/lint/else_layout.rb +1 -1
  77. data/lib/rubocop/cop/lint/empty_block.rb +1 -1
  78. data/lib/rubocop/cop/lint/empty_conditional_body.rb +4 -2
  79. data/lib/rubocop/cop/lint/empty_interpolation.rb +1 -1
  80. data/lib/rubocop/cop/lint/erb_new_arguments.rb +3 -4
  81. data/lib/rubocop/cop/lint/identity_comparison.rb +0 -1
  82. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -3
  83. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
  84. data/lib/rubocop/cop/lint/inherit_exception.rb +9 -0
  85. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  86. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +46 -4
  87. data/lib/rubocop/cop/lint/missing_super.rb +34 -2
  88. data/lib/rubocop/cop/lint/nested_method_definition.rb +2 -2
  89. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +2 -2
  90. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +2 -0
  91. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +0 -1
  92. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -2
  93. data/lib/rubocop/cop/lint/percent_string_array.rb +1 -1
  94. data/lib/rubocop/cop/lint/percent_symbol_array.rb +1 -1
  95. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +4 -4
  96. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +5 -5
  97. data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -1
  98. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
  99. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +35 -15
  100. data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -1
  101. data/lib/rubocop/cop/lint/redundant_with_object.rb +1 -1
  102. data/lib/rubocop/cop/lint/rescue_type.rb +3 -3
  103. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +1 -1
  104. data/lib/rubocop/cop/lint/script_permission.rb +1 -1
  105. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -2
  106. data/lib/rubocop/cop/lint/shadowed_exception.rb +6 -12
  107. data/lib/rubocop/cop/lint/syntax.rb +4 -0
  108. data/lib/rubocop/cop/lint/to_enum_arguments.rb +7 -1
  109. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +23 -9
  110. data/lib/rubocop/cop/lint/unreachable_loop.rb +3 -3
  111. data/lib/rubocop/cop/lint/useless_access_modifier.rb +9 -1
  112. data/lib/rubocop/cop/lint/useless_assignment.rb +59 -1
  113. data/lib/rubocop/cop/lint/useless_method_definition.rb +10 -2
  114. data/lib/rubocop/cop/lint/useless_rescue.rb +4 -1
  115. data/lib/rubocop/cop/lint/useless_times.rb +1 -1
  116. data/lib/rubocop/cop/lint/void.rb +69 -9
  117. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  118. data/lib/rubocop/cop/metrics/class_length.rb +1 -0
  119. data/lib/rubocop/cop/metrics/collection_literal_length.rb +76 -0
  120. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -2
  121. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +3 -3
  122. data/lib/rubocop/cop/migration/department_name.rb +1 -1
  123. data/lib/rubocop/cop/mixin/allowed_receivers.rb +34 -0
  124. data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
  125. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  126. data/lib/rubocop/cop/mixin/comments_help.rb +9 -5
  127. data/lib/rubocop/cop/mixin/documentation_comment.rb +1 -1
  128. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +1 -1
  129. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +4 -2
  130. data/lib/rubocop/cop/mixin/hash_transform_method.rb +3 -3
  131. data/lib/rubocop/cop/mixin/min_branches_count.rb +40 -0
  132. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
  133. data/lib/rubocop/cop/mixin/range_help.rb +1 -6
  134. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  135. data/lib/rubocop/cop/mixin/statement_modifier.rb +3 -3
  136. data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
  137. data/lib/rubocop/cop/naming/ascii_identifiers.rb +1 -1
  138. data/lib/rubocop/cop/naming/constant_name.rb +1 -1
  139. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +1 -1
  140. data/lib/rubocop/cop/naming/inclusive_language.rb +23 -4
  141. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +22 -7
  142. data/lib/rubocop/cop/naming/method_name.rb +3 -3
  143. data/lib/rubocop/cop/naming/predicate_name.rb +1 -1
  144. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +12 -4
  145. data/lib/rubocop/cop/naming/variable_name.rb +6 -1
  146. data/lib/rubocop/cop/registry.rb +3 -1
  147. data/lib/rubocop/cop/style/accessor_grouping.rb +32 -7
  148. data/lib/rubocop/cop/style/arguments_forwarding.rb +3 -3
  149. data/lib/rubocop/cop/style/ascii_comments.rb +1 -1
  150. data/lib/rubocop/cop/style/attr.rb +11 -1
  151. data/lib/rubocop/cop/style/begin_block.rb +1 -2
  152. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +1 -1
  153. data/lib/rubocop/cop/style/block_comments.rb +1 -1
  154. data/lib/rubocop/cop/style/block_delimiters.rb +11 -2
  155. data/lib/rubocop/cop/style/case_like_if.rb +20 -3
  156. data/lib/rubocop/cop/style/class_and_module_children.rb +2 -2
  157. data/lib/rubocop/cop/style/class_equality_comparison.rb +51 -40
  158. data/lib/rubocop/cop/style/collection_compact.rb +20 -7
  159. data/lib/rubocop/cop/style/colon_method_call.rb +2 -2
  160. data/lib/rubocop/cop/style/combinable_loops.rb +26 -6
  161. data/lib/rubocop/cop/style/comment_annotation.rb +1 -1
  162. data/lib/rubocop/cop/style/commented_keyword.rb +2 -2
  163. data/lib/rubocop/cop/style/concat_array_literals.rb +10 -2
  164. data/lib/rubocop/cop/style/conditional_assignment.rb +8 -8
  165. data/lib/rubocop/cop/style/copyright.rb +6 -3
  166. data/lib/rubocop/cop/style/data_inheritance.rb +75 -0
  167. data/lib/rubocop/cop/style/dir.rb +1 -1
  168. data/lib/rubocop/cop/style/dir_empty.rb +54 -0
  169. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +2 -2
  170. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +2 -2
  171. data/lib/rubocop/cop/style/documentation.rb +11 -5
  172. data/lib/rubocop/cop/style/double_negation.rb +2 -2
  173. data/lib/rubocop/cop/style/each_with_object.rb +1 -1
  174. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  175. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  176. data/lib/rubocop/cop/style/eval_with_location.rb +8 -8
  177. data/lib/rubocop/cop/style/exact_regexp_match.rb +68 -0
  178. data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
  179. data/lib/rubocop/cop/style/file_empty.rb +71 -0
  180. data/lib/rubocop/cop/style/file_read.rb +3 -3
  181. data/lib/rubocop/cop/style/file_write.rb +1 -1
  182. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  183. data/lib/rubocop/cop/style/guard_clause.rb +3 -1
  184. data/lib/rubocop/cop/style/hash_each_methods.rb +1 -22
  185. data/lib/rubocop/cop/style/hash_except.rb +23 -12
  186. data/lib/rubocop/cop/style/hash_like_case.rb +3 -9
  187. data/lib/rubocop/cop/style/hash_syntax.rb +5 -2
  188. data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
  189. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
  190. data/lib/rubocop/cop/style/if_inside_else.rb +6 -0
  191. data/lib/rubocop/cop/style/if_unless_modifier.rb +111 -15
  192. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +2 -0
  193. data/lib/rubocop/cop/style/inverse_methods.rb +5 -5
  194. data/lib/rubocop/cop/style/invertible_unless_condition.rb +9 -5
  195. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +2 -2
  196. data/lib/rubocop/cop/style/map_to_hash.rb +4 -1
  197. data/lib/rubocop/cop/style/map_to_set.rb +4 -1
  198. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +4 -9
  199. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +44 -37
  200. data/lib/rubocop/cop/style/min_max.rb +3 -3
  201. data/lib/rubocop/cop/style/mixin_grouping.rb +4 -4
  202. data/lib/rubocop/cop/style/multiline_method_signature.rb +7 -4
  203. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -1
  204. data/lib/rubocop/cop/style/multiple_comparison.rb +14 -0
  205. data/lib/rubocop/cop/style/negated_if_else_condition.rb +12 -7
  206. data/lib/rubocop/cop/style/nil_lambda.rb +2 -2
  207. data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
  208. data/lib/rubocop/cop/style/parallel_assignment.rb +26 -18
  209. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -3
  210. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  211. data/lib/rubocop/cop/style/redundant_array_constructor.rb +77 -0
  212. data/lib/rubocop/cop/style/redundant_condition.rb +2 -2
  213. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +2 -2
  214. data/lib/rubocop/cop/style/redundant_fetch_block.rb +6 -4
  215. data/lib/rubocop/cop/style/redundant_filter_chain.rb +101 -0
  216. data/lib/rubocop/cop/style/redundant_interpolation.rb +2 -2
  217. data/lib/rubocop/cop/style/redundant_line_continuation.rb +183 -0
  218. data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -1
  219. data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
  220. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +2 -2
  221. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +46 -0
  222. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +11 -4
  223. data/lib/rubocop/cop/style/redundant_sort.rb +3 -3
  224. data/lib/rubocop/cop/style/redundant_string_escape.rb +3 -4
  225. data/lib/rubocop/cop/style/regexp_literal.rb +11 -2
  226. data/lib/rubocop/cop/style/require_order.rb +12 -8
  227. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -3
  228. data/lib/rubocop/cop/style/rescue_standard_error.rb +2 -2
  229. data/lib/rubocop/cop/style/safe_navigation.rb +2 -2
  230. data/lib/rubocop/cop/style/select_by_regexp.rb +15 -5
  231. data/lib/rubocop/cop/style/semicolon.rb +12 -1
  232. data/lib/rubocop/cop/style/single_line_methods.rb +1 -1
  233. data/lib/rubocop/cop/style/sole_nested_conditional.rb +6 -4
  234. data/lib/rubocop/cop/style/special_global_vars.rb +3 -4
  235. data/lib/rubocop/cop/style/stderr_puts.rb +1 -1
  236. data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
  237. data/lib/rubocop/cop/style/trailing_body_on_class.rb +1 -0
  238. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +1 -1
  239. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  240. data/lib/rubocop/cop/style/unless_logical_operators.rb +1 -0
  241. data/lib/rubocop/cop/style/unpack_first.rb +3 -3
  242. data/lib/rubocop/cop/style/yoda_condition.rb +1 -1
  243. data/lib/rubocop/cop/style/zero_length_predicate.rb +9 -5
  244. data/lib/rubocop/cop/team.rb +2 -2
  245. data/lib/rubocop/cop/util.rb +1 -1
  246. data/lib/rubocop/cop/variable_force/assignment.rb +33 -1
  247. data/lib/rubocop/cop/variable_force/variable.rb +5 -3
  248. data/lib/rubocop/cop/variable_force/variable_table.rb +2 -2
  249. data/lib/rubocop/cop/variable_force.rb +1 -0
  250. data/lib/rubocop/cops_documentation_generator.rb +10 -3
  251. data/lib/rubocop/directive_comment.rb +3 -3
  252. data/lib/rubocop/ext/comment.rb +18 -0
  253. data/lib/rubocop/ext/regexp_node.rb +1 -1
  254. data/lib/rubocop/ext/regexp_parser.rb +1 -1
  255. data/lib/rubocop/formatter/junit_formatter.rb +4 -1
  256. data/lib/rubocop/formatter/simple_text_formatter.rb +1 -1
  257. data/lib/rubocop/options.rb +4 -1
  258. data/lib/rubocop/result_cache.rb +2 -2
  259. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  260. data/lib/rubocop/rspec/support.rb +1 -0
  261. data/lib/rubocop/server/cache.rb +1 -1
  262. data/lib/rubocop/server/client_command/exec.rb +2 -1
  263. data/lib/rubocop/server/core.rb +1 -1
  264. data/lib/rubocop/server/helper.rb +1 -1
  265. data/lib/rubocop/server/server_command/exec.rb +1 -1
  266. data/lib/rubocop/target_ruby.rb +3 -2
  267. data/lib/rubocop/version.rb +10 -6
  268. data/lib/rubocop.rb +13 -0
  269. metadata +23 -8
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module Style
6
6
  # Enforces the use of `Object#instance_of?` instead of class comparison
7
7
  # for equality.
8
- # `==`, `equal?`, and `eql?` methods are allowed by default.
8
+ # `==`, `equal?`, and `eql?` custom method definitions are allowed by default.
9
9
  # These are customizable with `AllowedMethods` option.
10
10
  #
11
11
  # @example
@@ -18,45 +18,31 @@ module RuboCop
18
18
  # # good
19
19
  # var.instance_of?(Date)
20
20
  #
21
- # @example AllowedMethods: [] (default)
21
+ # @example AllowedMethods: ['==', 'equal?', 'eql?'] (default)
22
22
  # # good
23
- # var.instance_of?(Date)
23
+ # def ==(other)
24
+ # self.class == other.class && name == other.name
25
+ # end
24
26
  #
25
- # # bad
26
- # var.class == Date
27
- # var.class.equal?(Date)
28
- # var.class.eql?(Date)
29
- # var.class.name == 'Date'
27
+ # def equal?(other)
28
+ # self.class.equal?(other.class) && name.equal?(other.name)
29
+ # end
30
30
  #
31
- # @example AllowedMethods: [`==`]
32
- # # good
33
- # var.instance_of?(Date)
34
- # var.class == Date
35
- # var.class.name == 'Date'
36
- #
37
- # # bad
38
- # var.class.equal?(Date)
39
- # var.class.eql?(Date)
31
+ # def eql?(other)
32
+ # self.class.eql?(other.class) && name.eql?(other.name)
33
+ # end
40
34
  #
41
35
  # @example AllowedPatterns: [] (default)
42
- # # good
43
- # var.instance_of?(Date)
44
- #
45
36
  # # bad
46
- # var.class == Date
47
- # var.class.equal?(Date)
48
- # var.class.eql?(Date)
49
- # var.class.name == 'Date'
37
+ # def eq(other)
38
+ # self.class.eq(other.class) && name.eq(other.name)
39
+ # end
50
40
  #
51
41
  # @example AllowedPatterns: ['eq']
52
42
  # # good
53
- # var.instance_of?(Date)
54
- # var.class.equal?(Date)
55
- # var.class.eql?(Date)
56
- #
57
- # # bad
58
- # var.class == Date
59
- # var.class.name == 'Date'
43
+ # def eq(other)
44
+ # self.class.eq(other.class) && name.eq(other.name)
45
+ # end
60
46
  #
61
47
  class ClassEqualityComparison < Base
62
48
  include RangeHelp
@@ -64,14 +50,15 @@ module RuboCop
64
50
  include AllowedPattern
65
51
  extend AutoCorrector
66
52
 
67
- MSG = 'Use `instance_of?(%<class_name>s)` instead of comparing classes.'
53
+ MSG = 'Use `instance_of?%<class_argument>s` instead of comparing classes.'
68
54
 
69
55
  RESTRICT_ON_SEND = %i[== equal? eql?].freeze
56
+ CLASS_NAME_METHODS = %i[name to_s inspect].freeze
70
57
 
71
58
  # @!method class_comparison_candidate?(node)
72
59
  def_node_matcher :class_comparison_candidate?, <<~PATTERN
73
60
  (send
74
- {$(send _ :class) (send $(send _ :class) :name)}
61
+ {$(send _ :class) (send $(send _ :class) #class_name_method?)}
75
62
  {:== :equal? :eql?} $_)
76
63
  PATTERN
77
64
 
@@ -83,10 +70,12 @@ module RuboCop
83
70
 
84
71
  class_comparison_candidate?(node) do |receiver_node, class_node|
85
72
  range = offense_range(receiver_node, node)
86
- class_name = class_name(class_node, node)
73
+ class_argument = (class_name = class_name(class_node, node)) ? "(#{class_name})" : ''
74
+
75
+ add_offense(range, message: format(MSG, class_argument: class_argument)) do |corrector|
76
+ next unless class_name
87
77
 
88
- add_offense(range, message: format(MSG, class_name: class_name)) do |corrector|
89
- corrector.replace(range, "instance_of?(#{class_name})")
78
+ corrector.replace(range, "instance_of?#{class_argument}")
90
79
  end
91
80
  end
92
81
  end
@@ -94,19 +83,41 @@ module RuboCop
94
83
  private
95
84
 
96
85
  def class_name(class_node, node)
97
- if node.children.first.method?(:name)
98
- return class_node.receiver.source if class_node.receiver
86
+ if class_name_method?(node.children.first.method_name)
87
+ if (receiver = class_node.receiver) && class_name_method?(class_node.method_name)
88
+ return receiver.source
89
+ end
99
90
 
100
91
  if class_node.str_type?
101
- value = class_node.source.delete('"').delete("'")
102
- value.prepend('::') if class_node.each_ancestor(:class, :module).any?
92
+ value = trim_string_quotes(class_node)
93
+ value.prepend('::') if require_cbase?(class_node)
103
94
  return value
95
+ elsif unable_to_determine_type?(class_node)
96
+ # When a variable or return value of a method is used, it returns nil
97
+ # because the type is not known and cannot be suggested.
98
+ return
104
99
  end
105
100
  end
106
101
 
107
102
  class_node.source
108
103
  end
109
104
 
105
+ def class_name_method?(method_name)
106
+ CLASS_NAME_METHODS.include?(method_name)
107
+ end
108
+
109
+ def require_cbase?(class_node)
110
+ class_node.each_ancestor(:class, :module).any?
111
+ end
112
+
113
+ def unable_to_determine_type?(class_node)
114
+ class_node.variable? || class_node.call_type?
115
+ end
116
+
117
+ def trim_string_quotes(class_node)
118
+ class_node.source.delete('"').delete("'")
119
+ end
120
+
110
121
  def offense_range(receiver_node, node)
111
122
  range_between(receiver_node.loc.selector.begin_pos, node.source_range.end_pos)
112
123
  end
@@ -9,8 +9,8 @@ module RuboCop
9
9
  # @safety
10
10
  # It is unsafe by default because false positives may occur in the
11
11
  # `nil` check of block arguments to the receiver object. Additionally,
12
- # we can't know the type of the receiver object for sure, which may
13
- # result in false positives as well.
12
+ # we can't know the type of the receiver object for sure, which may
13
+ # result in false positives as well.
14
14
  #
15
15
  # For example, `[[1, 2], [3, nil]].reject { |first, second| second.nil? }`
16
16
  # and `[[1, 2], [3, nil]].compact` are not compatible. This will work fine
@@ -19,7 +19,9 @@ module RuboCop
19
19
  # @example
20
20
  # # bad
21
21
  # array.reject(&:nil?)
22
+ # array.delete_if(&:nil?)
22
23
  # array.reject { |e| e.nil? }
24
+ # array.delete_if { |e| e.nil? }
23
25
  # array.select { |e| !e.nil? }
24
26
  #
25
27
  # # good
@@ -33,17 +35,25 @@ module RuboCop
33
35
  # # good
34
36
  # hash.compact!
35
37
  #
38
+ # @example AllowedReceivers: ['params']
39
+ # # good
40
+ # params.reject(&:nil?)
41
+ #
36
42
  class CollectionCompact < Base
43
+ include AllowedReceivers
37
44
  include RangeHelp
38
45
  extend AutoCorrector
46
+ extend TargetRubyVersion
39
47
 
40
48
  MSG = 'Use `%<good>s` instead of `%<bad>s`.'
41
- RESTRICT_ON_SEND = %i[reject reject! select select!].freeze
49
+ RESTRICT_ON_SEND = %i[reject delete_if reject! select select!].freeze
42
50
  TO_ENUM_METHODS = %i[to_enum lazy].freeze
43
51
 
52
+ minimum_target_ruby_version 2.4
53
+
44
54
  # @!method reject_method_with_block_pass?(node)
45
55
  def_node_matcher :reject_method_with_block_pass?, <<~PATTERN
46
- (send !nil? {:reject :reject!}
56
+ (send !nil? {:reject :delete_if :reject!}
47
57
  (block_pass
48
58
  (sym :nil?)))
49
59
  PATTERN
@@ -52,7 +62,7 @@ module RuboCop
52
62
  def_node_matcher :reject_method?, <<~PATTERN
53
63
  (block
54
64
  (send
55
- !nil? {:reject :reject!})
65
+ !nil? {:reject :delete_if :reject!})
56
66
  $(args ...)
57
67
  (send
58
68
  $(lvar _) :nil?))
@@ -71,7 +81,10 @@ module RuboCop
71
81
 
72
82
  def on_send(node)
73
83
  return unless (range = offense_range(node))
74
- return if target_ruby_version <= 3.0 && to_enum_method?(node)
84
+ return if allowed_receiver?(node.receiver)
85
+ if (target_ruby_version <= 3.0 || node.method?(:delete_if)) && to_enum_method?(node)
86
+ return
87
+ end
75
88
 
76
89
  good = good_method_name(node)
77
90
  message = format(MSG, good: good, bad: range.source)
@@ -112,7 +125,7 @@ module RuboCop
112
125
  end
113
126
 
114
127
  def range(begin_pos_node, end_pos_node)
115
- range_between(begin_pos_node.loc.selector.begin_pos, end_pos_node.loc.expression.end_pos)
128
+ range_between(begin_pos_node.loc.selector.begin_pos, end_pos_node.source_range.end_pos)
116
129
  end
117
130
  end
118
131
  end
@@ -3,8 +3,8 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for methods invoked via the :: operator instead
7
- # of the . operator (like FileUtils::rmdir instead of FileUtils.rmdir).
6
+ # Checks for methods invoked via the `::` operator instead
7
+ # of the `.` operator (like `FileUtils::rmdir` instead of `FileUtils.rmdir`).
8
8
  #
9
9
  # @example
10
10
  # # bad
@@ -57,38 +57,58 @@ module RuboCop
57
57
  # end
58
58
  #
59
59
  class CombinableLoops < Base
60
+ extend AutoCorrector
61
+
62
+ include RangeHelp
63
+
60
64
  MSG = 'Combine this loop with the previous loop.'
61
65
 
62
66
  def on_block(node)
63
67
  return unless node.parent&.begin_type?
64
68
  return unless collection_looping_method?(node)
69
+ return unless same_collection_looping_block?(node, node.left_sibling)
65
70
 
66
- add_offense(node) if same_collection_looping?(node, node.left_sibling)
71
+ add_offense(node) do |corrector|
72
+ combine_with_left_sibling(corrector, node)
73
+ end
67
74
  end
68
75
 
69
76
  alias on_numblock on_block
70
77
 
71
78
  def on_for(node)
72
79
  return unless node.parent&.begin_type?
80
+ return unless same_collection_looping_for?(node, node.left_sibling)
73
81
 
74
- sibling = node.left_sibling
75
- add_offense(node) if sibling&.for_type? && node.collection == sibling.collection
82
+ add_offense(node) do |corrector|
83
+ combine_with_left_sibling(corrector, node)
84
+ end
76
85
  end
77
86
 
78
87
  private
79
88
 
80
89
  def collection_looping_method?(node)
81
- # TODO: Remove `Symbol#to_s` after supporting only Ruby >= 2.7.
82
- method_name = node.method_name.to_s
90
+ method_name = node.method_name
83
91
  method_name.start_with?('each') || method_name.end_with?('_each')
84
92
  end
85
93
 
86
- def same_collection_looping?(node, sibling)
94
+ def same_collection_looping_block?(node, sibling)
87
95
  (sibling&.block_type? || sibling&.numblock_type?) &&
88
96
  sibling.send_node.method?(node.method_name) &&
89
97
  sibling.receiver == node.receiver &&
90
98
  sibling.send_node.arguments == node.send_node.arguments
91
99
  end
100
+
101
+ def same_collection_looping_for?(node, sibling)
102
+ sibling&.for_type? && node.collection == sibling.collection
103
+ end
104
+
105
+ def combine_with_left_sibling(corrector, node)
106
+ corrector.replace(
107
+ node.left_sibling.body,
108
+ "#{node.left_sibling.body.source}\n#{node.body.source}"
109
+ )
110
+ corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
111
+ end
92
112
  end
93
113
  end
94
114
  end
@@ -104,7 +104,7 @@ module RuboCop
104
104
  end
105
105
 
106
106
  def inline_comment?(comment)
107
- !comment_line?(comment.loc.expression.source_line)
107
+ !comment_line?(comment.source_range.source_line)
108
108
  end
109
109
 
110
110
  def annotation_range(annotation)
@@ -66,7 +66,7 @@ module RuboCop
66
66
 
67
67
  def register_offense(comment, matched_keyword)
68
68
  add_offense(comment, message: format(MSG, keyword: matched_keyword)) do |corrector|
69
- range = range_with_surrounding_space(comment.loc.expression, newlines: false)
69
+ range = range_with_surrounding_space(comment.source_range, newlines: false)
70
70
  corrector.remove(range)
71
71
 
72
72
  unless matched_keyword == 'end'
@@ -84,7 +84,7 @@ module RuboCop
84
84
  end
85
85
 
86
86
  def source_line(comment)
87
- comment.location.expression.source_line
87
+ comment.source_range.source_line
88
88
  end
89
89
  end
90
90
  end
@@ -38,7 +38,7 @@ module RuboCop
38
38
  offense = offense_range(node)
39
39
  current = offense.source
40
40
 
41
- if node.arguments.any?(&:percent_literal?)
41
+ if (use_percent_literal = node.arguments.any?(&:percent_literal?))
42
42
  if percent_literals_includes_only_basic_literals?(node)
43
43
  prefer = preferred_method(node)
44
44
  message = format(MSG, prefer: prefer, current: current)
@@ -51,7 +51,15 @@ module RuboCop
51
51
  end
52
52
 
53
53
  add_offense(offense, message: message) do |corrector|
54
- corrector.replace(offense, prefer)
54
+ if use_percent_literal
55
+ corrector.replace(offense, prefer)
56
+ else
57
+ corrector.replace(node.loc.selector, 'push')
58
+ node.arguments.each do |argument|
59
+ corrector.remove(argument.loc.begin)
60
+ corrector.remove(argument.loc.end)
61
+ end
62
+ end
55
63
  end
56
64
  end
57
65
  # rubocop:enable Metrics
@@ -350,7 +350,7 @@ module RuboCop
350
350
  end
351
351
 
352
352
  def ternary_condition?(node)
353
- [node, node.children.first].any? { |n| n.if_type? && n.ternary? }
353
+ [node, node.children.first].compact.any? { |n| n.if_type? && n.ternary? }
354
354
  end
355
355
 
356
356
  def lhs_all_match?(branches)
@@ -386,7 +386,7 @@ module RuboCop
386
386
  def allowed_statements?(branches)
387
387
  return false unless branches.all?
388
388
 
389
- statements = branches.map { |branch| tail(branch) }.compact
389
+ statements = branches.filter_map { |branch| tail(branch) }
390
390
 
391
391
  lhs_all_match?(statements) && statements.none?(&:masgn_type?) &&
392
392
  assignment_types_match?(*statements)
@@ -450,7 +450,7 @@ module RuboCop
450
450
  end
451
451
 
452
452
  def white_space_range(node, column)
453
- expression = node.loc.expression
453
+ expression = node.source_range
454
454
  begin_pos = expression.begin_pos - (expression.column - column - 2)
455
455
 
456
456
  Parser::Source::Range.new(expression.source_buffer, begin_pos, expression.begin_pos)
@@ -458,9 +458,9 @@ module RuboCop
458
458
 
459
459
  def assignment(node)
460
460
  *_, condition = *node
461
- Parser::Source::Range.new(node.loc.expression.source_buffer,
462
- node.loc.expression.begin_pos,
463
- condition.loc.expression.begin_pos)
461
+ Parser::Source::Range.new(node.source_range.source_buffer,
462
+ node.source_range.begin_pos,
463
+ condition.source_range.begin_pos)
464
464
  end
465
465
 
466
466
  def correct_if_branches(corrector, cop, node)
@@ -565,7 +565,7 @@ module RuboCop
565
565
  end
566
566
 
567
567
  def move_assignment_inside_condition(corrector, node)
568
- column = node.loc.expression.column
568
+ column = node.source_range.column
569
569
  *_var, condition = *node
570
570
  assignment = assignment(node)
571
571
 
@@ -616,7 +616,7 @@ module RuboCop
616
616
  end
617
617
 
618
618
  def move_assignment_inside_condition(corrector, node)
619
- column = node.loc.expression.column
619
+ column = node.source_range.column
620
620
  *_var, condition = *node
621
621
  assignment = assignment(node)
622
622
 
@@ -8,8 +8,11 @@ module RuboCop
8
8
  # The default regexp for an acceptable copyright notice can be found in
9
9
  # config/default.yml. The default can be changed as follows:
10
10
  #
11
- # Style/Copyright:
12
- # Notice: '^Copyright (\(c\) )?2\d{3} Acme Inc'
11
+ # [source,yaml]
12
+ # ----
13
+ # Style/Copyright:
14
+ # Notice: '^Copyright (\(c\) )?2\d{3} Acme Inc'
15
+ # ----
13
16
  #
14
17
  # This regex string is treated as an unanchored regex. For each file
15
18
  # that RuboCop scans, a comment that matches this regex must be found or
@@ -82,7 +85,7 @@ module RuboCop
82
85
  def notice_found?(processed_source)
83
86
  notice_found = false
84
87
  notice_regexp = Regexp.new(notice)
85
- processed_source.each_token do |token|
88
+ processed_source.tokens.each do |token|
86
89
  break unless token.comment?
87
90
 
88
91
  notice_found = notice_regexp.match?(token.text)
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Checks for inheritance from `Data.define` to avoid creating the anonymous parent class.
7
+ #
8
+ # @safety
9
+ # Autocorrection is unsafe because it will change the inheritance
10
+ # tree (e.g. return value of `Module#ancestors`) of the constant.
11
+ #
12
+ # @example
13
+ # # bad
14
+ # class Person < Data.define(:first_name, :last_name)
15
+ # def age
16
+ # 42
17
+ # end
18
+ # end
19
+ #
20
+ # # good
21
+ # Person = Data.define(:first_name, :last_name) do
22
+ # def age
23
+ # 42
24
+ # end
25
+ # end
26
+ class DataInheritance < Base
27
+ include RangeHelp
28
+ extend AutoCorrector
29
+ extend TargetRubyVersion
30
+
31
+ MSG = "Don't extend an instance initialized by `Data.define`. " \
32
+ 'Use a block to customize the class.'
33
+
34
+ minimum_target_ruby_version 3.2
35
+
36
+ def on_class(node)
37
+ return unless data_define?(node.parent_class)
38
+
39
+ add_offense(node.parent_class.source_range) do |corrector|
40
+ corrector.remove(range_with_surrounding_space(node.loc.keyword, newlines: false))
41
+ corrector.replace(node.loc.operator, '=')
42
+
43
+ correct_parent(node.parent_class, corrector)
44
+ end
45
+ end
46
+
47
+ # @!method data_define?(node)
48
+ def_node_matcher :data_define?, <<~PATTERN
49
+ {(send (const {nil? cbase} :Data) :define ...)
50
+ (block (send (const {nil? cbase} :Data) :define ...) ...)}
51
+ PATTERN
52
+
53
+ private
54
+
55
+ def correct_parent(parent, corrector)
56
+ if parent.block_type?
57
+ corrector.remove(range_with_surrounding_space(parent.loc.end, newlines: false))
58
+ elsif (class_node = parent.parent).body.nil?
59
+ corrector.remove(range_for_empty_class_body(class_node, parent))
60
+ else
61
+ corrector.insert_after(parent, ' do')
62
+ end
63
+ end
64
+
65
+ def range_for_empty_class_body(class_node, data_define)
66
+ if class_node.single_line?
67
+ range_between(data_define.source_range.end_pos, class_node.source_range.end_pos)
68
+ else
69
+ range_by_whole_lines(class_node.loc.end, include_final_newline: true)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for places where the `#__dir__` method can replace more
6
+ # Checks for places where the `#\_\_dir\_\_` method can replace more
7
7
  # complex constructs to retrieve a canonicalized absolute path to the
8
8
  # current file.
9
9
  #
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Prefer to use `Dir.empty?('path/to/dir')` when checking if a directory is empty.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # Dir.entries('path/to/dir').size == 2
11
+ # Dir.children('path/to/dir').empty?
12
+ # Dir.children('path/to/dir').size == 0
13
+ # Dir.each_child('path/to/dir').none?
14
+ #
15
+ # # good
16
+ # Dir.empty?('path/to/dir')
17
+ #
18
+ class DirEmpty < Base
19
+ extend AutoCorrector
20
+ extend TargetRubyVersion
21
+
22
+ MSG = 'Use `%<replacement>s` instead.'
23
+ RESTRICT_ON_SEND = %i[== != > empty? none?].freeze
24
+
25
+ minimum_target_ruby_version 2.4
26
+
27
+ # @!method offensive?(node)
28
+ def_node_matcher :offensive?, <<~PATTERN
29
+ {
30
+ (send (send (send $(const {nil? cbase} :Dir) :entries $_) :size) {:== :!= :>} (int 2))
31
+ (send (send (send $(const {nil? cbase} :Dir) :children $_) :size) {:== :!= :>} (int 0))
32
+ (send (send $(const {nil? cbase} :Dir) :children $_) :empty?)
33
+ (send (send $(const {nil? cbase} :Dir) :each_child $_) :none?)
34
+ }
35
+ PATTERN
36
+
37
+ def on_send(node)
38
+ offensive?(node) do |const_node, arg_node|
39
+ replacement = "#{bang(node)}#{const_node.source}.empty?(#{arg_node.source})"
40
+ add_offense(node, message: format(MSG, replacement: replacement)) do |corrector|
41
+ corrector.replace(node, replacement)
42
+ end
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def bang(node)
49
+ '!' if %i[!= >].include? node.method_name
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -34,8 +34,8 @@ module RuboCop
34
34
  extend AutoCorrector
35
35
 
36
36
  # rubocop:enable Lint/RedundantCopDisableDirective
37
- MSG = 'Rubocop disable/enable directives are not permitted.'
38
- MSG_FOR_COPS = 'Rubocop disable/enable directives for %<cops>s are not permitted.'
37
+ MSG = 'RuboCop disable/enable directives are not permitted.'
38
+ MSG_FOR_COPS = 'RuboCop disable/enable directives for %<cops>s are not permitted.'
39
39
 
40
40
  def on_new_investigation
41
41
  processed_source.comments.each do |comment|
@@ -111,12 +111,12 @@ module RuboCop
111
111
  return if comments.none?
112
112
 
113
113
  regexp = comment_regexp(arg_node)
114
- comments.any? { |comment| regexp.match?(comment) } || regexp.match?(comments.join)
114
+ comments.any?(regexp) || regexp.match?(comments.join)
115
115
  end
116
116
 
117
117
  def preceding_comment_blocks(node)
118
118
  # Collect comments in the method call, but outside the heredoc
119
- comments = processed_source.each_comment_in_lines(node.loc.expression.line_span)
119
+ comments = processed_source.each_comment_in_lines(node.source_range.line_span)
120
120
 
121
121
  comments.each_with_object({}) do |comment, hash|
122
122
  merge_adjacent_comments(comment.text, comment.loc.line, hash)
@@ -10,7 +10,7 @@ module RuboCop
10
10
  # declarations.
11
11
  #
12
12
  # The documentation requirement is annulled if the class or module has
13
- # a "#:nodoc:" comment next to it. Likewise, "#:nodoc: all" does the
13
+ # a `#:nodoc:` comment next to it. Likewise, `#:nodoc: all` does the
14
14
  # same for all its children.
15
15
  #
16
16
  # @example
@@ -110,7 +110,7 @@ module RuboCop
110
110
  return if nodoc_self_or_outer_module?(node)
111
111
  return if include_statement_only?(body)
112
112
 
113
- range = range_between(node.loc.expression.begin_pos, node.loc.name.end_pos)
113
+ range = range_between(node.source_range.begin_pos, node.loc.name.end_pos)
114
114
  message = format(MSG, type: node.type, identifier: identifier(node))
115
115
  add_offense(range, message: message)
116
116
  end
@@ -178,13 +178,19 @@ module RuboCop
178
178
  def identifier(node)
179
179
  # Get the fully qualified identifier for a class/module
180
180
  nodes = [node, *node.each_ancestor(:class, :module)]
181
- nodes.reverse_each.flat_map { |n| qualify_const(n.identifier) }.join('::')
181
+ identifier = nodes.reverse_each.flat_map { |n| qualify_const(n.identifier) }.join('::')
182
+
183
+ identifier.sub('::::', '::')
182
184
  end
183
185
 
184
186
  def qualify_const(node)
185
- return if node.nil? || node.cbase_type? || node.self_type? || node.send_type?
187
+ return if node.nil?
186
188
 
187
- [qualify_const(node.namespace), node.short_name].compact
189
+ if node.cbase_type? || node.self_type? || node.call_type? || node.variable?
190
+ node.source
191
+ else
192
+ [qualify_const(node.namespace), node.short_name].compact
193
+ end
188
194
  end
189
195
  end
190
196
  end
@@ -103,12 +103,12 @@ module RuboCop
103
103
  def find_def_node_from_ascendant(node)
104
104
  return unless (parent = node.parent)
105
105
  return parent if parent.def_type? || parent.defs_type?
106
- return node.parent.child_nodes.first if define_mehod?(parent)
106
+ return node.parent.child_nodes.first if define_method?(parent)
107
107
 
108
108
  find_def_node_from_ascendant(node.parent)
109
109
  end
110
110
 
111
- def define_mehod?(node)
111
+ def define_method?(node)
112
112
  return false unless node.block_type?
113
113
 
114
114
  child = node.child_nodes.first