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
@@ -41,15 +41,23 @@ module RuboCop
41
41
  MSG = 'Useless method definition detected.'
42
42
 
43
43
  def on_def(node)
44
- return if use_rest_or_optional_args?(node)
44
+ return if method_definition_with_modifier?(node) || use_rest_or_optional_args?(node)
45
45
  return unless delegating?(node.body, node)
46
46
 
47
- add_offense(node) { |corrector| corrector.remove(node) }
47
+ add_offense(node) do |corrector|
48
+ range = node.parent&.send_type? ? node.parent : node
49
+
50
+ corrector.remove(range)
51
+ end
48
52
  end
49
53
  alias on_defs on_def
50
54
 
51
55
  private
52
56
 
57
+ def method_definition_with_modifier?(node)
58
+ node.parent&.send_type? && !node.parent&.non_bare_access_modifier?
59
+ end
60
+
53
61
  def use_rest_or_optional_args?(node)
54
62
  node.arguments.any? { |arg| arg.restarg_type? || arg.optarg_type? || arg.kwoptarg_type? }
55
63
  end
@@ -56,11 +56,13 @@ module RuboCop
56
56
 
57
57
  private
58
58
 
59
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
59
60
  def only_reraising?(resbody_node)
60
61
  return false if use_exception_variable_in_ensure?(resbody_node)
61
62
 
62
63
  body = resbody_node.body
63
- return false if body.nil? || !body.send_type? || !body.method?(:raise)
64
+
65
+ return false if body.nil? || !body.send_type? || !body.method?(:raise) || body.receiver
64
66
  return true unless body.arguments?
65
67
  return false if body.arguments.size > 1
66
68
 
@@ -68,6 +70,7 @@ module RuboCop
68
70
 
69
71
  exception_objects(resbody_node).include?(exception_name)
70
72
  end
73
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
71
74
 
72
75
  def use_exception_variable_in_ensure?(resbody_node)
73
76
  return false unless (exception_variable = resbody_node.exception_variable)
@@ -74,7 +74,7 @@ module RuboCop
74
74
  end
75
75
 
76
76
  def remove_node(corrector, node)
77
- corrector.remove(range_by_whole_lines(node.loc.expression, include_final_newline: true))
77
+ corrector.remove(range_by_whole_lines(node.source_range, include_final_newline: true))
78
78
  end
79
79
 
80
80
  def autocorrect_block_pass(corrector, node, proc_name)
@@ -41,6 +41,10 @@ module RuboCop
41
41
  # do_something(some_array)
42
42
  # end
43
43
  class Void < Base
44
+ extend AutoCorrector
45
+
46
+ include RangeHelp
47
+
44
48
  OP_MSG = 'Operator `%<op>s` used in void context.'
45
49
  VAR_MSG = 'Variable `%<var>s` used in void context.'
46
50
  LIT_MSG = 'Literal `%<lit>s` used in void context.'
@@ -59,10 +63,10 @@ module RuboCop
59
63
  shuffle slice sort sort_by squeeze strip sub
60
64
  succ swapcase tr tr_s transform_values
61
65
  unicode_normalize uniq upcase].freeze
62
- METHODS_REPLACABLE_BY_EACH = %i[collect map].freeze
66
+ METHODS_REPLACEABLE_BY_EACH = %i[collect map].freeze
63
67
 
64
68
  NONMUTATING_METHODS = (NONMUTATING_METHODS_WITH_BANG_VERSION +
65
- METHODS_REPLACABLE_BY_EACH).freeze
69
+ METHODS_REPLACEABLE_BY_EACH).freeze
66
70
 
67
71
  def on_block(node)
68
72
  return unless node.body && !node.body.begin_type?
@@ -100,31 +104,43 @@ module RuboCop
100
104
  def check_void_op(node)
101
105
  return unless node.send_type? && OPERATORS.include?(node.method_name)
102
106
 
103
- add_offense(node.loc.selector, message: format(OP_MSG, op: node.method_name))
107
+ add_offense(node.loc.selector,
108
+ message: format(OP_MSG, op: node.method_name)) do |corrector|
109
+ autocorrect_void_op(corrector, node)
110
+ end
104
111
  end
105
112
 
106
113
  def check_var(node)
107
114
  return unless node.variable? || node.const_type?
108
115
 
109
- add_offense(node.loc.name, message: format(VAR_MSG, var: node.loc.name.source))
116
+ add_offense(node.loc.name,
117
+ message: format(VAR_MSG, var: node.loc.name.source)) do |corrector|
118
+ autocorrect_void_var(corrector, node)
119
+ end
110
120
  end
111
121
 
112
122
  def check_literal(node)
113
123
  return if !node.literal? || node.xstr_type? || node.range_type?
114
124
 
115
- add_offense(node, message: format(LIT_MSG, lit: node.source))
125
+ add_offense(node, message: format(LIT_MSG, lit: node.source)) do |corrector|
126
+ autocorrect_void_literal(corrector, node)
127
+ end
116
128
  end
117
129
 
118
130
  def check_self(node)
119
131
  return unless node.self_type?
120
132
 
121
- add_offense(node, message: SELF_MSG)
133
+ add_offense(node, message: SELF_MSG) do |corrector|
134
+ autocorrect_void_self(corrector, node)
135
+ end
122
136
  end
123
137
 
124
138
  def check_void_expression(node)
125
139
  return unless node.defined_type? || node.lambda_or_proc?
126
140
 
127
- add_offense(node, message: format(EXPRESSION_MSG, expression: node.source))
141
+ add_offense(node, message: format(EXPRESSION_MSG, expression: node.source)) do |corrector|
142
+ autocorrect_void_expression(corrector, node)
143
+ end
128
144
  end
129
145
 
130
146
  def check_nonmutating(node)
@@ -133,9 +149,16 @@ module RuboCop
133
149
  method_name = node.method_name
134
150
  return unless NONMUTATING_METHODS.include?(method_name)
135
151
 
136
- suggestion = METHODS_REPLACABLE_BY_EACH.include?(method_name) ? 'each' : "#{method_name}!"
152
+ suggestion = if METHODS_REPLACEABLE_BY_EACH.include?(method_name)
153
+ 'each'
154
+ else
155
+ "#{method_name}!"
156
+ end
137
157
  add_offense(node,
138
- message: format(NONMUTATING_MSG, method: method_name, suggest: suggestion))
158
+ message: format(NONMUTATING_MSG, method: method_name,
159
+ suggest: suggestion)) do |corrector|
160
+ autocorrect_nonmutating_send(corrector, node, suggestion)
161
+ end
139
162
  end
140
163
 
141
164
  def in_void_context?(node)
@@ -145,6 +168,43 @@ module RuboCop
145
168
 
146
169
  VOID_CONTEXT_TYPES.include?(parent.type) && parent.void_context?
147
170
  end
171
+
172
+ def autocorrect_void_op(corrector, node)
173
+ if node.arguments.empty?
174
+ corrector.replace(node, node.receiver.source)
175
+ else
176
+ corrector.replace(
177
+ range_with_surrounding_space(range: node.loc.selector, side: :both,
178
+ newlines: false),
179
+ "\n"
180
+ )
181
+ end
182
+ end
183
+
184
+ def autocorrect_void_var(corrector, node)
185
+ corrector.remove(range_with_surrounding_space(range: node.loc.name, side: :left))
186
+ end
187
+
188
+ def autocorrect_void_literal(corrector, node)
189
+ corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
190
+ end
191
+
192
+ def autocorrect_void_self(corrector, node)
193
+ corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
194
+ end
195
+
196
+ def autocorrect_void_expression(corrector, node)
197
+ corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
198
+ end
199
+
200
+ def autocorrect_nonmutating_send(corrector, node, suggestion)
201
+ send_node = if node.send_type?
202
+ node
203
+ else
204
+ node.send_node
205
+ end
206
+ corrector.replace(send_node.loc.selector, suggestion)
207
+ end
148
208
  end
149
209
  end
150
210
  end
@@ -44,7 +44,7 @@ module RuboCop
44
44
  def consider_node?(node)
45
45
  return true if NESTING_BLOCKS.include?(node.type)
46
46
 
47
- count_blocks? && node.block_type?
47
+ count_blocks? && (node.block_type? || node.numblock_type?)
48
48
  end
49
49
 
50
50
  def message(max)
@@ -42,6 +42,7 @@ module RuboCop
42
42
  def on_class(node)
43
43
  check_code_length(node)
44
44
  end
45
+ alias on_sclass on_class
45
46
 
46
47
  def on_casgn(node)
47
48
  parent = node.parent
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Metrics
6
+ # Checks for literals with extremely many entries. This is indicative of
7
+ # configuration or data that may be better extracted somewhere else, like
8
+ # a database, fetched from an API, or read from a non-code file (CSV,
9
+ # JSON, YAML, etc.).
10
+ #
11
+ # @example
12
+ # # bad
13
+ # # Huge Array literal
14
+ # [1, 2, '...', 999_999_999]
15
+ #
16
+ # # bad
17
+ # # Huge Hash literal
18
+ # { 1 => 1, 2 => 2, '...' => '...', 999_999_999 => 999_999_999}
19
+ #
20
+ # # bad
21
+ # # Huge Set "literal"
22
+ # Set[1, 2, '...', 999_999_999]
23
+ #
24
+ # # good
25
+ # # Reasonably sized Array literal
26
+ # [1, 2, '...', 10]
27
+ #
28
+ # # good
29
+ # # Reading huge Array from external data source
30
+ # # File.readlines('numbers.txt', chomp: true).map!(&:to_i)
31
+ #
32
+ # # good
33
+ # # Reasonably sized Hash literal
34
+ # { 1 => 1, 2 => 2, '...' => '...', 10 => 10}
35
+ #
36
+ # # good
37
+ # # Reading huge Hash from external data source
38
+ # CSV.foreach('numbers.csv', headers: true).each_with_object({}) do |row, hash|
39
+ # hash[row["key"].to_i] = row["value"].to_i
40
+ # end
41
+ #
42
+ # # good
43
+ # # Reasonably sized Set "literal"
44
+ # Set[1, 2, '...', 10]
45
+ #
46
+ # # good
47
+ # # Reading huge Set from external data source
48
+ # SomeFramework.config_for(:something)[:numbers].to_set
49
+ #
50
+ class CollectionLiteralLength < Base
51
+ MSG = 'Avoid hard coding large quantities of data in code. ' \
52
+ 'Prefer reading the data from an external source.'
53
+ RESTRICT_ON_SEND = [:[]].freeze
54
+
55
+ def on_array(node)
56
+ add_offense(node) if node.children.length >= collection_threshold
57
+ end
58
+ alias on_hash on_array
59
+
60
+ def on_index(node)
61
+ add_offense(node) if node.arguments.length >= collection_threshold
62
+ end
63
+
64
+ def on_send(node)
65
+ on_index(node) if node.method?(:[])
66
+ end
67
+
68
+ private
69
+
70
+ def collection_threshold
71
+ cop_config.fetch('LengthThreshold', Float::INFINITY)
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -117,8 +117,7 @@ module RuboCop
117
117
  end
118
118
 
119
119
  def capturing_variable?(name)
120
- # TODO: Remove `Symbol#to_s` after supporting only Ruby >= 2.7.
121
- name && !name.to_s.start_with?('_')
120
+ name && !name.start_with?('_')
122
121
  end
123
122
 
124
123
  def branch?(node)
@@ -10,7 +10,7 @@ module RuboCop
10
10
  include Util
11
11
 
12
12
  FOLDABLE_TYPES = %i[array hash heredoc send csend].freeze
13
- CLASSLIKE_TYPES = %i[class module].freeze
13
+ CLASSLIKE_TYPES = %i[class module sclass].freeze
14
14
  private_constant :FOLDABLE_TYPES, :CLASSLIKE_TYPES
15
15
 
16
16
  def initialize(node, processed_source, count_comments: false, foldable_types: [])
@@ -163,8 +163,8 @@ module RuboCop
163
163
  return 0 unless parenthesized?(parent)
164
164
 
165
165
  [
166
- parent.loc.begin.end_pos != descendant.loc.expression.begin_pos,
167
- parent.loc.end.begin_pos != descendant.loc.expression.end_pos
166
+ parent.loc.begin.end_pos != descendant.source_range.begin_pos,
167
+ parent.loc.end.begin_pos != descendant.source_range.end_pos
168
168
  ].count(true)
169
169
  end
170
170
 
@@ -45,7 +45,7 @@ module RuboCop
45
45
  end
46
46
 
47
47
  def check_cop_name(name, comment, offset)
48
- start = comment.location.expression.begin_pos + offset
48
+ start = comment.source_range.begin_pos + offset
49
49
  range = range_between(start, start + name.length)
50
50
 
51
51
  add_offense(range) do |corrector|
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # This module encapsulates the ability to allow certain receivers in a cop.
6
+ module AllowedReceivers
7
+ def allowed_receiver?(receiver)
8
+ receiver_name = receiver_name(receiver)
9
+
10
+ allowed_receivers.include?(receiver_name)
11
+ end
12
+
13
+ def receiver_name(receiver)
14
+ if receiver.receiver && !receiver.receiver.const_type?
15
+ return receiver_name(receiver.receiver)
16
+ end
17
+
18
+ if receiver.send_type?
19
+ if receiver.receiver
20
+ "#{receiver_name(receiver.receiver)}.#{receiver.method_name}"
21
+ else
22
+ receiver.method_name.to_s
23
+ end
24
+ else
25
+ receiver.source
26
+ end
27
+ end
28
+
29
+ def allowed_receivers
30
+ cop_config.fetch('AllowedReceivers', [])
31
+ end
32
+ end
33
+ end
34
+ end
@@ -29,7 +29,7 @@ module RuboCop
29
29
 
30
30
  # Returns the range bounds for just the annotation
31
31
  def bounds
32
- start = comment.loc.expression.begin_pos + margin.length
32
+ start = comment.source_range.begin_pos + margin.length
33
33
  length = [keyword, colon, space].reduce(0) { |len, elem| len + elem.to_s.length }
34
34
  [start, start + length]
35
35
  end
@@ -36,7 +36,7 @@ module RuboCop
36
36
  length = calculator.calculate
37
37
  return if length <= max_length
38
38
 
39
- location = node.casgn_type? ? node.loc.name : node.loc.expression
39
+ location = node.casgn_type? ? node.loc.name : node.source_range
40
40
 
41
41
  add_offense(location, message: message(length, max_length)) { self.max = length }
42
42
  end
@@ -37,7 +37,7 @@ module RuboCop
37
37
  private
38
38
 
39
39
  def end_position_for(node)
40
- end_line = buffer.line_for_position(node.loc.expression.end_pos)
40
+ end_line = buffer.line_for_position(node.source_range.end_pos)
41
41
  buffer.line_range(end_line).end_pos
42
42
  end
43
43
 
@@ -62,21 +62,25 @@ module RuboCop
62
62
  # Returns the end line of a node, which might be a comment and not part of the AST
63
63
  # End line is considered either the line at which another node starts, or
64
64
  # the line at which the parent node ends.
65
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
65
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity, Lint/DuplicateBranch
66
66
  def find_end_line(node)
67
67
  if node.if_type? && node.else?
68
68
  node.loc.else.line
69
69
  elsif node.if_type? && node.ternary?
70
70
  node.else_branch.loc.line
71
- elsif (next_sibling = node.right_sibling)
71
+ elsif node.if_type? && node.elsif?
72
+ node.each_ancestor(:if).find(&:if?).loc.end.line
73
+ elsif node.block_type? || node.numblock_type?
74
+ node.loc.end.line
75
+ elsif (next_sibling = node.right_sibling) && next_sibling.is_a?(AST::Node)
72
76
  next_sibling.loc.line
73
77
  elsif (parent = node.parent)
74
- parent.loc.end ? parent.loc.end.line : parent.loc.line
78
+ parent.loc.respond_to?(:end) && parent.loc.end ? parent.loc.end.line : parent.loc.line
75
79
  else
76
80
  node.loc.end.line
77
81
  end
78
82
  end
79
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
83
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity, Lint/DuplicateBranch
80
84
  end
81
85
  end
82
86
  end
@@ -23,7 +23,7 @@ module RuboCop
23
23
  # The args node1 & node2 may represent a RuboCop::AST::Node
24
24
  # or a Parser::Source::Comment. Both respond to #loc.
25
25
  def preceding_comment?(node1, node2)
26
- node1 && node2 && precede?(node2, node1) && comment_line?(node2.loc.expression.source)
26
+ node1 && node2 && precede?(node2, node1) && comment_line?(node2.source)
27
27
  end
28
28
 
29
29
  # The args node1 & node2 may represent a RuboCop::AST::Node
@@ -33,7 +33,7 @@ module RuboCop
33
33
 
34
34
  def separator_delta(pair)
35
35
  if pair.hash_rocket?
36
- correct_separator_column = pair.key.loc.expression.end.column + 1
36
+ correct_separator_column = pair.key.source_range.end.column + 1
37
37
  actual_separator_column = pair.loc.operator.column
38
38
 
39
39
  correct_separator_column - actual_separator_column
@@ -95,19 +95,21 @@ module RuboCop
95
95
  use_modifier_form_without_parenthesized_method_call?(method_dispatch_node)
96
96
  end
97
97
 
98
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
98
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
99
99
  def def_node_that_require_parentheses(node)
100
100
  last_pair = node.parent.pairs.last
101
101
  return unless last_pair.key.source == last_pair.value.source
102
102
  return unless (dispatch_node = find_ancestor_method_dispatch_node(node))
103
+ return if dispatch_node.assignment_method?
103
104
  return if dispatch_node.parenthesized?
105
+ return if dispatch_node.parent && parentheses?(dispatch_node.parent)
104
106
  return if last_expression?(dispatch_node) && !method_dispatch_as_argument?(dispatch_node)
105
107
 
106
108
  def_node = node.each_ancestor(:send, :csend, :super, :yield).first
107
109
 
108
110
  DefNode.new(def_node) unless def_node && def_node.arguments.empty?
109
111
  end
110
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
112
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
111
113
 
112
114
  def find_ancestor_method_dispatch_node(node)
113
115
  return unless (ancestor = node.parent.parent)
@@ -159,7 +159,7 @@ module RuboCop
159
159
  end
160
160
 
161
161
  def strip_prefix_and_suffix(node, corrector)
162
- expression = node.loc.expression
162
+ expression = node.source_range
163
163
  corrector.remove_leading(expression, leading)
164
164
  corrector.remove_trailing(expression, trailing)
165
165
  end
@@ -175,11 +175,11 @@ module RuboCop
175
175
  end
176
176
 
177
177
  def set_new_arg_name(transformed_argname, corrector)
178
- corrector.replace(block_node.arguments.loc.expression, "|#{transformed_argname}|")
178
+ corrector.replace(block_node.arguments, "|#{transformed_argname}|")
179
179
  end
180
180
 
181
181
  def set_new_body_expression(transforming_body_expr, corrector)
182
- body_source = transforming_body_expr.loc.expression.source
182
+ body_source = transforming_body_expr.source
183
183
  if transforming_body_expr.hash_type? && !transforming_body_expr.braces?
184
184
  body_source = "{ #{body_source} }"
185
185
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # Common functionality for checking minimum branches count.
6
+ module MinBranchesCount
7
+ private
8
+
9
+ def min_branches_count?(node)
10
+ branches =
11
+ if node.case_type?
12
+ node.when_branches
13
+ elsif node.if_type?
14
+ if_conditional_branches(node)
15
+ else
16
+ raise ArgumentError, "Unsupported #{node.type.inspect} node type"
17
+ end
18
+
19
+ branches.size >= min_branches_count
20
+ end
21
+
22
+ def min_branches_count
23
+ length = cop_config['MinBranchesCount'] || 3
24
+ return length if length.is_a?(Integer) && length.positive?
25
+
26
+ raise 'MinBranchesCount needs to be a positive integer!'
27
+ end
28
+
29
+ def if_conditional_branches(node, branches = [])
30
+ return [] if node.nil? || !node.if_type?
31
+
32
+ branches << node.if_branch
33
+
34
+ else_branch = node.else_branch
35
+ if_conditional_branches(else_branch, branches) if else_branch&.if_type?
36
+ branches
37
+ end
38
+ end
39
+ end
40
+ end
@@ -10,7 +10,7 @@ module RuboCop
10
10
  def get_source_range(node, comments_as_separators)
11
11
  unless comments_as_separators
12
12
  first_comment = processed_source.ast_with_comments[node].first
13
- return first_comment.loc.expression unless first_comment.nil?
13
+ return first_comment.source_range unless first_comment.nil?
14
14
  end
15
15
  node.source_range
16
16
  end
@@ -132,12 +132,7 @@ module RuboCop
132
132
  end
133
133
 
134
134
  def range_with_comments(node)
135
- ranges = [
136
- node,
137
- *@processed_source.ast_with_comments[node]
138
- ].map do |element|
139
- element.location.expression
140
- end
135
+ ranges = [node, *@processed_source.ast_with_comments[node]].map(&:source_range)
141
136
  ranges.reduce do |result, range|
142
137
  add_range(result, range)
143
138
  end
@@ -36,7 +36,7 @@ module RuboCop
36
36
  end
37
37
 
38
38
  def allowed_type?(token)
39
- %i[tRPAREN tRBRACK tPIPE].include?(token.type)
39
+ %i[tRPAREN tRBRACK tPIPE tSTRING_DEND].include?(token.type)
40
40
  end
41
41
 
42
42
  def space_forbidden_before_rcurly?
@@ -65,14 +65,14 @@ module RuboCop
65
65
  end
66
66
 
67
67
  def method_source(if_body)
68
- range_between(if_body.loc.expression.begin_pos, if_body.loc.selector.end_pos).source
68
+ range_between(if_body.source_range.begin_pos, if_body.loc.selector.end_pos).source
69
69
  end
70
70
 
71
71
  def first_line_comment(node)
72
- comment = processed_source.find_comment { |c| same_line?(c, node) }
72
+ comment = processed_source.comments.find { |c| same_line?(c, node) }
73
73
  return unless comment
74
74
 
75
- comment_source = comment.loc.expression.source
75
+ comment_source = comment.source
76
76
  comment_source unless comment_disables_cop?(comment_source)
77
77
  end
78
78
 
@@ -75,7 +75,7 @@ module RuboCop
75
75
 
76
76
  def inside_comment?(range, comma_offset)
77
77
  comment = processed_source.comment_at_line(range.line)
78
- comment && comment.loc.expression.begin_pos < range.begin_pos + comma_offset
78
+ comment && comment.source_range.begin_pos < range.begin_pos + comma_offset
79
79
  end
80
80
 
81
81
  # Returns true if the node has round/square/curly brackets.
@@ -57,7 +57,7 @@ module RuboCop
57
57
  CONSTANT_MSG = 'Use only ascii symbols in constants.'
58
58
 
59
59
  def on_new_investigation
60
- processed_source.each_token do |token|
60
+ processed_source.tokens.each do |token|
61
61
  next if !should_check?(token) || token.text.ascii_only?
62
62
 
63
63
  message = token.type == :tIDENTIFIER ? IDENTIFIER_MSG : CONSTANT_MSG
@@ -76,7 +76,7 @@ module RuboCop
76
76
  end
77
77
 
78
78
  def contains_constant?(node)
79
- node.branches.any?(&:const_type?)
79
+ node.branches.compact.any?(&:const_type?)
80
80
  end
81
81
  end
82
82
  end
@@ -38,7 +38,7 @@ module RuboCop
38
38
  return if correct_case_delimiters?(node)
39
39
 
40
40
  add_offense(node.loc.heredoc_end) do |corrector|
41
- expr = node.loc.expression
41
+ expr = node.source_range
42
42
 
43
43
  corrector.replace(expr, correct_delimiters(expr.source))
44
44
  corrector.replace(node.loc.heredoc_end, correct_delimiters(delimiter_string(expr)))