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
@@ -31,22 +31,26 @@ module RuboCop
31
31
  def on_masgn(node)
32
32
  lhs, rhs = *node
33
33
  lhs_elements = *lhs
34
+ rhs = rhs.body if rhs.rescue_type?
34
35
  rhs_elements = Array(rhs).compact # edge case for one constant
35
36
 
36
37
  return if allowed_lhs?(lhs) || allowed_rhs?(rhs) ||
37
38
  allowed_masign?(lhs_elements, rhs_elements)
38
39
 
39
- add_offense(node) { |corrector| autocorrect(corrector, node) }
40
+ range = node.source_range.begin.join(rhs.source_range.end)
41
+
42
+ add_offense(range) do |corrector|
43
+ autocorrect(corrector, node, lhs, rhs)
44
+ end
40
45
  end
41
46
 
42
47
  private
43
48
 
44
- def autocorrect(corrector, node)
45
- left, right = *node
46
- left_elements = *left
47
- right_elements = Array(right).compact
49
+ def autocorrect(corrector, node, lhs, rhs)
50
+ left_elements = *lhs
51
+ right_elements = Array(rhs).compact
48
52
  order = find_valid_order(left_elements, right_elements)
49
- correction = assignment_corrector(node, order)
53
+ correction = assignment_corrector(node, rhs, order)
50
54
 
51
55
  corrector.replace(correction.correction_range, correction.correction)
52
56
  end
@@ -77,14 +81,19 @@ module RuboCop
77
81
  node.block_type? || node.send_type?
78
82
  end
79
83
 
80
- def assignment_corrector(node, order)
81
- _assignment, modifier = *node.parent
84
+ def assignment_corrector(node, rhs, order)
85
+ if node.parent&.rescue_type?
86
+ _assignment, modifier = *node.parent
87
+ else
88
+ _assignment, modifier = *rhs.parent
89
+ end
90
+
82
91
  if modifier_statement?(node.parent)
83
- ModifierCorrector.new(node, config, order)
92
+ ModifierCorrector.new(node, rhs, modifier, config, order)
84
93
  elsif rescue_modifier?(modifier)
85
- RescueCorrector.new(node, config, order)
94
+ RescueCorrector.new(node, rhs, modifier, config, order)
86
95
  else
87
- GenericCorrector.new(node, config, order)
96
+ GenericCorrector.new(node, rhs, modifier, config, order)
88
97
  end
89
98
  end
90
99
 
@@ -181,10 +190,12 @@ module RuboCop
181
190
  class GenericCorrector
182
191
  include Alignment
183
192
 
184
- attr_reader :config, :node
193
+ attr_reader :node, :rhs, :rescue_result, :config
185
194
 
186
- def initialize(node, config, new_elements)
195
+ def initialize(node, rhs, modifier, config, new_elements)
187
196
  @node = node
197
+ @rhs = rhs
198
+ _, _, @rescue_result = *modifier
188
199
  @config = config
189
200
  @new_elements = new_elements
190
201
  end
@@ -228,13 +239,10 @@ module RuboCop
228
239
  # protected by rescue
229
240
  class RescueCorrector < GenericCorrector
230
241
  def correction
231
- _node, rescue_clause = *node.parent
232
- _, _, rescue_result = *rescue_clause
233
-
234
242
  # If the parallel assignment uses a rescue modifier and it is the
235
243
  # only contents of a method, then we want to make use of the
236
244
  # implicit begin
237
- if node.parent.parent&.def_type?
245
+ if rhs.parent.parent.parent&.def_type?
238
246
  super + def_correction(rescue_result)
239
247
  else
240
248
  begin_correction(rescue_result)
@@ -242,7 +250,7 @@ module RuboCop
242
250
  end
243
251
 
244
252
  def correction_range
245
- node.parent.source_range
253
+ rhs.parent.parent.source_range
246
254
  end
247
255
 
248
256
  private
@@ -92,9 +92,8 @@ module RuboCop
92
92
 
93
93
  def contains_delimiter?(node, delimiters)
94
94
  delimiters_regexp = Regexp.union(delimiters)
95
- node
96
- .children.map { |n| string_source(n) }.compact
97
- .any? { |s| delimiters_regexp.match?(s) }
95
+
96
+ node.children.filter_map { |n| string_source(n) }.any?(delimiters_regexp)
98
97
  end
99
98
 
100
99
  def string_source(node)
@@ -44,7 +44,7 @@ module RuboCop
44
44
 
45
45
  # Report offense only if changing case doesn't change semantics,
46
46
  # i.e., if the string would become dynamic or has special characters.
47
- ast = ProcessedSource.new(corrected(node.source), target_ruby_version).ast
47
+ ast = parse(corrected(node.source)).ast
48
48
  return if node.children != ast.children
49
49
 
50
50
  add_offense(node.loc.begin) do |corrector|
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Checks for the instantiation of array using redundant `Array` constructor.
7
+ # Autocorrect replaces to array literal which is the simplest and fastest.
8
+ #
9
+ # @example
10
+ #
11
+ # # bad
12
+ # Array.new([])
13
+ # Array[]
14
+ # Array([])
15
+ # Array.new(['foo', 'foo', 'foo'])
16
+ # Array['foo', 'foo', 'foo']
17
+ # Array(['foo', 'foo', 'foo'])
18
+ #
19
+ # # good
20
+ # []
21
+ # ['foo', 'foo', 'foo']
22
+ # Array.new(3, 'foo')
23
+ # Array.new(3) { 'foo' }
24
+ #
25
+ class RedundantArrayConstructor < Base
26
+ extend AutoCorrector
27
+
28
+ MSG = 'Remove the redundant `Array` constructor.'
29
+
30
+ RESTRICT_ON_SEND = %i[new [] Array].freeze
31
+
32
+ # @!method redundant_array_constructor(node)
33
+ def_node_matcher :redundant_array_constructor, <<~PATTERN
34
+ {
35
+ (send
36
+ (const {nil? cbase} :Array) :new
37
+ $(array ...))
38
+ (send
39
+ (const {nil? cbase} :Array) :[]
40
+ $...)
41
+ (send
42
+ nil? :Array
43
+ $(array ...))
44
+ }
45
+ PATTERN
46
+
47
+ def on_send(node)
48
+ return unless (array_literal = redundant_array_constructor(node))
49
+
50
+ receiver = node.receiver
51
+ selector = node.loc.selector
52
+
53
+ if node.method?(:new)
54
+ range = receiver.source_range.join(selector)
55
+ replacement = array_literal
56
+ elsif node.method?(:Array)
57
+ range = selector
58
+ replacement = array_literal
59
+ else
60
+ range = receiver
61
+ replacement = selector.begin.join(node.source_range.end)
62
+ end
63
+
64
+ register_offense(range, node, replacement)
65
+ end
66
+
67
+ private
68
+
69
+ def register_offense(range, node, replacement)
70
+ add_offense(range) do |corrector|
71
+ corrector.replace(node, replacement.source)
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -70,8 +70,8 @@ module RuboCop
70
70
  end
71
71
 
72
72
  def range_of_offense(node)
73
- return node.loc.expression unless node.ternary?
74
- return node.loc.expression if node.ternary? && branches_have_method?(node)
73
+ return node.source_range unless node.ternary?
74
+ return node.source_range if node.ternary? && branches_have_method?(node)
75
75
 
76
76
  range_between(node.loc.question.begin_pos, node.loc.colon.end_pos)
77
77
  end
@@ -33,11 +33,11 @@ module RuboCop
33
33
  private
34
34
 
35
35
  def opening_brace(node)
36
- node.loc.begin.join(node.children.first.loc.expression.begin)
36
+ node.loc.begin.join(node.children.first.source_range.begin)
37
37
  end
38
38
 
39
39
  def closing_brace(node)
40
- node.children.last.loc.expression.end.join(node.loc.end)
40
+ node.children.last.source_range.end.join(node.loc.end)
41
41
  end
42
42
  end
43
43
  end
@@ -3,11 +3,13 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Identifies places where `fetch(key) { value }`
7
- # can be replaced by `fetch(key, value)`.
6
+ # Identifies places where `fetch(key) { value }` can be replaced by `fetch(key, value)`.
8
7
  #
9
- # In such cases `fetch(key, value)` method is faster
10
- # than `fetch(key) { value }`.
8
+ # In such cases `fetch(key, value)` method is faster than `fetch(key) { value }`.
9
+ #
10
+ # NOTE: The block string `'value'` in `hash.fetch(:key) { 'value' }` is detected
11
+ # when frozen string literal magic comment is enabled (i.e. `# frozen_string_literal: true`),
12
+ # but not when disabled.
11
13
  #
12
14
  # @safety
13
15
  # This cop is unsafe because it cannot be guaranteed that the receiver
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Identifies usages of `any?`, `empty?` or `none?` predicate methods
7
+ # chained to `select`/`filter`/`find_all` and change them to use predicate method instead.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # arr.select { |x| x > 1 }.any?
12
+ #
13
+ # # good
14
+ # arr.any? { |x| x > 1 }
15
+ #
16
+ # # bad
17
+ # arr.select { |x| x > 1 }.empty?
18
+ # arr.select { |x| x > 1 }.none?
19
+ #
20
+ # # good
21
+ # arr.none? { |x| x > 1 }
22
+ #
23
+ # # good
24
+ # relation.select(:name).any?
25
+ # arr.select { |x| x > 1 }.any?(&:odd?)
26
+ #
27
+ # @example AllCops:ActiveSupportExtensionsEnabled: false (default)
28
+ # # good
29
+ # arr.select { |x| x > 1 }.many?
30
+ #
31
+ # @example AllCops:ActiveSupportExtensionsEnabled: true
32
+ # # bad
33
+ # arr.select { |x| x > 1 }.many?
34
+ #
35
+ # # good
36
+ # arr.many? { |x| x > 1 }
37
+ #
38
+ class RedundantFilterChain < Base
39
+ extend AutoCorrector
40
+
41
+ MSG = 'Use `%<prefer>s` instead of `%<first_method>s.%<second_method>s`.'
42
+
43
+ RAILS_METHODS = %i[many?].freeze
44
+ RESTRICT_ON_SEND = (%i[any? empty? none? one?] + RAILS_METHODS).freeze
45
+
46
+ # @!method select_predicate?(node)
47
+ def_node_matcher :select_predicate?, <<~PATTERN
48
+ (send
49
+ {
50
+ (block $(send _ {:select :filter :find_all}) ...)
51
+ $(send _ {:select :filter :find_all} block_pass_type?)
52
+ }
53
+ ${:#{RESTRICT_ON_SEND.join(' :')}})
54
+ PATTERN
55
+
56
+ REPLACEMENT_METHODS = {
57
+ any?: :any?,
58
+ empty?: :none?,
59
+ none?: :none?,
60
+ one?: :one?,
61
+ many?: :many?
62
+ }.freeze
63
+ private_constant :REPLACEMENT_METHODS
64
+
65
+ def on_send(node)
66
+ return if node.arguments? || node.block_node
67
+
68
+ select_predicate?(node) do |select_node, filter_method|
69
+ return if RAILS_METHODS.include?(filter_method) && !active_support_extensions_enabled?
70
+
71
+ register_offense(select_node, node)
72
+ end
73
+ end
74
+
75
+ private
76
+
77
+ def register_offense(select_node, predicate_node)
78
+ replacement = REPLACEMENT_METHODS[predicate_node.method_name]
79
+ message = format(MSG, prefer: replacement,
80
+ first_method: select_node.method_name,
81
+ second_method: predicate_node.method_name)
82
+
83
+ offense_range = offense_range(select_node, predicate_node)
84
+
85
+ add_offense(offense_range, message: message) do |corrector|
86
+ corrector.remove(predicate_range(predicate_node))
87
+ corrector.replace(select_node.loc.selector, replacement)
88
+ end
89
+ end
90
+
91
+ def offense_range(select_node, predicate_node)
92
+ select_node.loc.selector.join(predicate_node.loc.selector)
93
+ end
94
+
95
+ def predicate_range(predicate_node)
96
+ predicate_node.receiver.source_range.end.join(predicate_node.loc.selector)
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -97,7 +97,7 @@ module RuboCop
97
97
  end
98
98
 
99
99
  def autocorrect_variable_interpolation(corrector, embedded_node, node)
100
- replacement = "#{embedded_node.loc.expression.source}.to_s"
100
+ replacement = "#{embedded_node.source}.to_s"
101
101
 
102
102
  corrector.replace(node, replacement)
103
103
  end
@@ -107,7 +107,7 @@ module RuboCop
107
107
 
108
108
  source = if require_parentheses?(embedded_var)
109
109
  receiver = range_between(
110
- embedded_var.loc.expression.begin_pos, embedded_var.loc.selector.end_pos
110
+ embedded_var.source_range.begin_pos, embedded_var.loc.selector.end_pos
111
111
  )
112
112
  arguments = embedded_var.arguments.map(&:source).join(', ')
113
113
 
@@ -0,0 +1,183 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Check for redundant line continuation.
7
+ #
8
+ # This cop marks a line continuation as redundant if removing the backslash
9
+ # does not result in a syntax error.
10
+ # However, a backslash at the end of a comment or
11
+ # for string concatenation is not redundant and is not considered an offense.
12
+ #
13
+ # @example
14
+ # # bad
15
+ # foo. \
16
+ # bar
17
+ # foo \
18
+ # &.bar \
19
+ # .baz
20
+ #
21
+ # # good
22
+ # foo.
23
+ # bar
24
+ # foo
25
+ # &.bar
26
+ # .baz
27
+ #
28
+ # # bad
29
+ # [foo, \
30
+ # bar]
31
+ # {foo: \
32
+ # bar}
33
+ #
34
+ # # good
35
+ # [foo,
36
+ # bar]
37
+ # {foo:
38
+ # bar}
39
+ #
40
+ # # bad
41
+ # foo(bar, \
42
+ # baz)
43
+ #
44
+ # # good
45
+ # foo(bar,
46
+ # baz)
47
+ #
48
+ # # also good - backslash in string concatenation is not redundant
49
+ # foo('bar' \
50
+ # 'baz')
51
+ #
52
+ # # also good - backslash at the end of a comment is not redundant
53
+ # foo(bar, # \
54
+ # baz)
55
+ #
56
+ # # also good - backslash at the line following the newline begins with a + or -,
57
+ # # it is not redundant
58
+ # 1 \
59
+ # + 2 \
60
+ # - 3
61
+ #
62
+ # # also good - backslash with newline between the method name and its arguments,
63
+ # # it is not redundant.
64
+ # some_method \
65
+ # (argument)
66
+ #
67
+ class RedundantLineContinuation < Base
68
+ include MatchRange
69
+ extend AutoCorrector
70
+
71
+ MSG = 'Redundant line continuation.'
72
+ ALLOWED_STRING_TOKENS = %i[tSTRING tSTRING_CONTENT].freeze
73
+ ARGUMENT_TYPES = %i[
74
+ kFALSE kNIL kSELF kTRUE tCONSTANT tCVAR tFLOAT tGVAR tIDENTIFIER tINTEGER tIVAR
75
+ tLBRACK tLCURLY tLPAREN_ARG tSTRING tSTRING_BEG tSYMBOL tXSTRING_BEG
76
+ ].freeze
77
+
78
+ def on_new_investigation
79
+ return unless processed_source.ast
80
+
81
+ each_match_range(processed_source.ast.source_range, /(\\\n)/) do |range|
82
+ next if require_line_continuation?(range)
83
+ next unless redundant_line_continuation?(range)
84
+
85
+ add_offense(range) do |corrector|
86
+ corrector.remove_leading(range, 1)
87
+ end
88
+ end
89
+ end
90
+
91
+ private
92
+
93
+ def require_line_continuation?(range)
94
+ !ends_with_backslash_without_comment?(range.source_line) ||
95
+ string_concatenation?(range.source_line) ||
96
+ start_with_arithmetic_operator?(processed_source[range.line]) ||
97
+ inside_string_literal_or_method_with_argument?(range)
98
+ end
99
+
100
+ def ends_with_backslash_without_comment?(source_line)
101
+ source_line.gsub(/#.+/, '').end_with?('\\')
102
+ end
103
+
104
+ def string_concatenation?(source_line)
105
+ /["']\s*\\\z/.match?(source_line)
106
+ end
107
+
108
+ def inside_string_literal_or_method_with_argument?(range)
109
+ processed_source.tokens.each_cons(2).any? do |token, next_token|
110
+ inside_string_literal?(range, token) || method_with_argument?(token, next_token)
111
+ end
112
+ end
113
+
114
+ def redundant_line_continuation?(range)
115
+ return true unless (node = find_node_for_line(range.line))
116
+ return false if argument_newline?(node)
117
+
118
+ source = node.parent ? node.parent.source : node.source
119
+ parse(source.gsub(/\\\n/, "\n")).valid_syntax?
120
+ end
121
+
122
+ def inside_string_literal?(range, token)
123
+ ALLOWED_STRING_TOKENS.include?(token.type) && token.pos.overlaps?(range)
124
+ end
125
+
126
+ # A method call without parentheses such as the following cannot remove `\`:
127
+ #
128
+ # do_something \
129
+ # argument
130
+ def method_with_argument?(current_token, next_token)
131
+ current_token.type == :tIDENTIFIER && ARGUMENT_TYPES.include?(next_token.type)
132
+ end
133
+
134
+ def argument_newline?(node)
135
+ node = node.children.first if node.root? && node.begin_type?
136
+
137
+ if argument_is_method?(node)
138
+ argument_newline?(node.first_argument)
139
+ else
140
+ return false unless method_call_with_arguments?(node)
141
+
142
+ node.loc.selector.line != node.first_argument.loc.line
143
+ end
144
+ end
145
+
146
+ def find_node_for_line(line)
147
+ processed_source.ast.each_node do |node|
148
+ return node if same_line?(node, line)
149
+ end
150
+ end
151
+
152
+ def same_line?(node, line)
153
+ return unless (source_range = node.source_range)
154
+
155
+ if node.is_a?(AST::StrNode)
156
+ if node.heredoc?
157
+ (node.loc.heredoc_body.line..node.loc.heredoc_body.last_line).cover?(line)
158
+ else
159
+ (source_range.line..source_range.last_line).cover?(line)
160
+ end
161
+ else
162
+ source_range.line == line
163
+ end
164
+ end
165
+
166
+ def argument_is_method?(node)
167
+ return false unless node.send_type?
168
+ return false unless (first_argument = node.first_argument)
169
+
170
+ method_call_with_arguments?(first_argument)
171
+ end
172
+
173
+ def method_call_with_arguments?(node)
174
+ node.call_type? && !node.arguments.empty?
175
+ end
176
+
177
+ def start_with_arithmetic_operator?(source_line)
178
+ %r{\A\s*[+\-*/%]}.match?(source_line)
179
+ end
180
+ end
181
+ end
182
+ end
183
+ end
@@ -98,7 +98,7 @@ module RuboCop
98
98
  end
99
99
 
100
100
  def like_method_argument_parentheses?(node)
101
- node.send_type? && node.arguments.one? &&
101
+ node.send_type? && node.arguments.one? && !node.parenthesized? &&
102
102
  !node.arithmetic_operation? && node.first_argument.begin_type?
103
103
  end
104
104
 
@@ -93,7 +93,7 @@ module RuboCop
93
93
 
94
94
  return true if STRING_INTERPOLATION_REGEXP.match?(src)
95
95
 
96
- src.scan(/\\./).any? { |s| ESCAPED_NON_BACKSLASH.match?(s) }
96
+ src.scan(/\\./).any?(ESCAPED_NON_BACKSLASH)
97
97
  end
98
98
 
99
99
  def acceptable_capital_q?(node)
@@ -63,7 +63,7 @@ module RuboCop
63
63
  next if expr.type != :set || expr.expressions.size != 1
64
64
  next if expr.negative?
65
65
  next if %i[set posixclass nonposixclass].include?(expr.expressions.first.type)
66
- next if multiple_codepoins?(expr.expressions.first)
66
+ next if multiple_codepoints?(expr.expressions.first)
67
67
 
68
68
  yield expr
69
69
  end
@@ -80,7 +80,7 @@ module RuboCop
80
80
  !non_redundant
81
81
  end
82
82
 
83
- def multiple_codepoins?(expression)
83
+ def multiple_codepoints?(expression)
84
84
  expression.respond_to?(:codepoints) && expression.codepoints.count >= 2
85
85
  end
86
86
 
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Checks for the instantiation of regexp using redundant `Regexp.new` or `Regexp.compile`.
7
+ # Autocorrect replaces to regexp literal which is the simplest and fastest.
8
+ #
9
+ # @example
10
+ #
11
+ # # bad
12
+ # Regexp.new(/regexp/)
13
+ # Regexp.compile(/regexp/)
14
+ #
15
+ # # good
16
+ # /regexp/
17
+ # Regexp.new('regexp')
18
+ # Regexp.compile('regexp')
19
+ #
20
+ class RedundantRegexpConstructor < Base
21
+ extend AutoCorrector
22
+
23
+ MSG = 'Remove the redundant `Regexp.%<method>s`.'
24
+ RESTRICT_ON_SEND = %i[new compile].freeze
25
+
26
+ # @!method redundant_regexp_constructor(node)
27
+ def_node_matcher :redundant_regexp_constructor, <<~PATTERN
28
+ (send
29
+ (const {nil? cbase} :Regexp) {:new :compile}
30
+ (regexp $... (regopt $...)))
31
+ PATTERN
32
+
33
+ def on_send(node)
34
+ return unless (regexp, regopt = redundant_regexp_constructor(node))
35
+
36
+ add_offense(node, message: format(MSG, method: node.method_name)) do |corrector|
37
+ pattern = regexp.map(&:source).join
38
+ regopt = regopt.join
39
+
40
+ corrector.replace(node, "/#{pattern}/#{regopt}")
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -74,11 +74,18 @@ module RuboCop
74
74
 
75
75
  def char_class_begins_or_ends_with_escaped_hyphen?(node, index)
76
76
  # The hyphen character is allowed to be escaped within a character class
77
- # but it's not necessry to escape hyphen if it's the first or last character
77
+ # but it's not necessary to escape hyphen if it's the first or last character
78
78
  # within the character class. This method checks if that's the case.
79
79
  # e.g. "[0-9\\-]" or "[\\-0-9]" would return true
80
- contents_range(node).source[index - 1] == '[' ||
81
- contents_range(node).source[index + 2] == ']'
80
+ content = contents_range(node).source
81
+
82
+ if content[index + 2] == ']'
83
+ true
84
+ elsif content[index - 1] == '['
85
+ index < 2 || content[index - 2] != '\\'
86
+ else
87
+ false
88
+ end
82
89
  end
83
90
 
84
91
  def delimiter?(node, char)
@@ -100,7 +107,7 @@ module RuboCop
100
107
  end
101
108
  end
102
109
  # Please remove this `else` branch when support for regexp_parser 1.8 will be dropped.
103
- # It's for compatibility with regexp_arser 1.8 and will never be maintained.
110
+ # It's for compatibility with regexp_parser 1.8 and will never be maintained.
104
111
  else
105
112
  def each_escape(node)
106
113
  node.parsed_tree&.traverse&.reduce(0) do |char_class_depth, (event, expr)|
@@ -129,13 +129,13 @@ module RuboCop
129
129
  end
130
130
 
131
131
  def offense_range(sort_node, node)
132
- range_between(sort_node.loc.selector.begin_pos, node.loc.expression.end_pos)
132
+ range_between(sort_node.loc.selector.begin_pos, node.source_range.end_pos)
133
133
  end
134
134
 
135
135
  def message(node, sorter, accessor)
136
136
  accessor_source = range_between(
137
137
  node.loc.selector.begin_pos,
138
- node.loc.expression.end_pos
138
+ node.source_range.end_pos
139
139
  ).source
140
140
 
141
141
  format(MSG,
@@ -146,7 +146,7 @@ module RuboCop
146
146
 
147
147
  def autocorrect(corrector, node, sort_node, sorter, accessor)
148
148
  # Remove accessor, e.g. `first` or `[-1]`.
149
- corrector.remove(range_between(accessor_start(node), node.loc.expression.end_pos))
149
+ corrector.remove(range_between(accessor_start(node), node.source_range.end_pos))
150
150
  # Replace "sort" or "sort_by" with the appropriate min/max method.
151
151
  corrector.replace(sort_node.loc.selector, suggestion(sorter, accessor, arg_value(node)))
152
152
  # Replace to avoid syntax errors when followed by a logical operator.