sonicop 26.8.112 → 26.8.113

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 (343) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +11 -11
  3. data/Cargo.toml +4 -4
  4. data/README.ja.md +36 -23
  5. data/README.md +38 -26
  6. data/lib/sonicop/version.rb +1 -1
  7. data/src/config/inheritance.rs +45 -3
  8. data/src/engine.rs +11 -7
  9. data/src/lib.rs +1 -0
  10. data/src/nul_bytes.rs +2 -6
  11. data/src/parser.rs +37 -0
  12. data/src/profile.rs +13 -1
  13. data/src/rules/bundler/duplicated_group.rs +3 -2
  14. data/src/rules/bundler/gem_comment.rs +5 -4
  15. data/src/rules/gemspec/attribute_assignment.rs +4 -3
  16. data/src/rules/gemspec/deprecated_attribute_assignment.rs +7 -6
  17. data/src/rules/gemspec/duplicated_assignment.rs +4 -3
  18. data/src/rules/gemspec/require_mfa.rs +10 -9
  19. data/src/rules/gemspec/required_ruby_version.rs +3 -2
  20. data/src/rules/gemspec/support.rs +3 -2
  21. data/src/rules/layout/array_alignment.rs +1 -2
  22. data/src/rules/layout/block_end_newline.rs +5 -5
  23. data/src/rules/layout/class_structure.rs +5 -3
  24. data/src/rules/layout/closing_heredoc_indentation.rs +4 -3
  25. data/src/rules/layout/closing_parenthesis_indentation.rs +1 -2
  26. data/src/rules/layout/condition_position.rs +3 -2
  27. data/src/rules/layout/def_end_alignment.rs +2 -2
  28. data/src/rules/layout/dot_position.rs +1 -2
  29. data/src/rules/layout/empty_line_after_guard_clause.rs +3 -6
  30. data/src/rules/layout/empty_line_after_multiline_condition.rs +5 -5
  31. data/src/rules/layout/empty_lines_around_access_modifier.rs +2 -3
  32. data/src/rules/layout/empty_lines_around_arguments.rs +4 -4
  33. data/src/rules/layout/empty_lines_around_exception_handling_keywords.rs +1 -2
  34. data/src/rules/layout/empty_lines_around_method_body.rs +3 -2
  35. data/src/rules/layout/end_alignment.rs +2 -2
  36. data/src/rules/layout/extra_spacing.rs +7 -6
  37. data/src/rules/layout/first_array_element_indentation.rs +1 -2
  38. data/src/rules/layout/first_hash_element_indentation.rs +8 -6
  39. data/src/rules/layout/hash_alignment.rs +4 -4
  40. data/src/rules/layout/heredoc_argument_closing_parenthesis.rs +6 -5
  41. data/src/rules/layout/heredoc_indentation.rs +4 -3
  42. data/src/rules/layout/indentation_style.rs +4 -3
  43. data/src/rules/layout/indentation_width.rs +14 -13
  44. data/src/rules/layout/line_continuation_leading_space.rs +4 -3
  45. data/src/rules/layout/line_continuation_spacing.rs +2 -2
  46. data/src/rules/layout/line_length.rs +101 -57
  47. data/src/rules/layout/multiline_assignment_layout.rs +4 -3
  48. data/src/rules/layout/multiline_block_layout.rs +1 -2
  49. data/src/rules/layout/multiline_expression.rs +60 -31
  50. data/src/rules/layout/multiline_hash_brace_layout.rs +4 -3
  51. data/src/rules/layout/multiline_method_call_indentation.rs +1 -1
  52. data/src/rules/layout/multiline_operation_indentation.rs +3 -3
  53. data/src/rules/layout/redundant_line_break.rs +3 -2
  54. data/src/rules/layout/single_line_block_chain.rs +4 -3
  55. data/src/rules/layout/space_around_block_parameters.rs +1 -2
  56. data/src/rules/layout/space_around_equals_in_parameter_default.rs +1 -2
  57. data/src/rules/layout/space_around_operators.rs +1 -2
  58. data/src/rules/layout/space_before_brackets.rs +6 -5
  59. data/src/rules/layout/space_before_comma.rs +3 -2
  60. data/src/rules/layout/space_inside_range_literal.rs +8 -6
  61. data/src/rules/layout/support.rs +9 -7
  62. data/src/rules/layout/tokens.rs +15 -6
  63. data/src/rules/lint/access_modifier.rs +19 -10
  64. data/src/rules/lint/ambiguity.rs +2 -2
  65. data/src/rules/lint/ambiguous_block_association.rs +7 -10
  66. data/src/rules/lint/ambiguous_regexp_literal.rs +7 -5
  67. data/src/rules/lint/array_literal_in_regexp.rs +4 -3
  68. data/src/rules/lint/assignment_in_condition.rs +3 -2
  69. data/src/rules/lint/blocks.rs +2 -1
  70. data/src/rules/lint/boolean_symbol.rs +4 -4
  71. data/src/rules/lint/constant_definition_in_block.rs +1 -2
  72. data/src/rules/lint/constant_reassignment.rs +2 -1
  73. data/src/rules/lint/deprecated_open_ssl_constant.rs +1 -2
  74. data/src/rules/lint/disjunctive_assignment_in_constructor.rs +2 -2
  75. data/src/rules/lint/duplicate_branch.rs +6 -5
  76. data/src/rules/lint/duplicate_case_condition.rs +5 -5
  77. data/src/rules/lint/duplicate_hash_key.rs +4 -3
  78. data/src/rules/lint/duplicate_match_pattern.rs +7 -5
  79. data/src/rules/lint/duplicate_methods.rs +4 -3
  80. data/src/rules/lint/duplicate_require.rs +1 -2
  81. data/src/rules/lint/duplicate_set_element.rs +3 -2
  82. data/src/rules/lint/empty_conditional_body.rs +4 -3
  83. data/src/rules/lint/empty_in_pattern.rs +3 -2
  84. data/src/rules/lint/empty_when.rs +4 -4
  85. data/src/rules/lint/ensure_return.rs +3 -2
  86. data/src/rules/lint/float_comparison.rs +8 -6
  87. data/src/rules/lint/format_parameter_mismatch.rs +4 -3
  88. data/src/rules/lint/hash_compare_by_identity.rs +5 -4
  89. data/src/rules/lint/heredoc_method_call_position.rs +3 -2
  90. data/src/rules/lint/implicit_string_concatenation.rs +7 -5
  91. data/src/rules/lint/ineffective_access_modifier.rs +5 -4
  92. data/src/rules/lint/inherit_exception.rs +4 -3
  93. data/src/rules/lint/literal_as_condition.rs +5 -3
  94. data/src/rules/lint/literal_assignment_in_condition.rs +4 -3
  95. data/src/rules/lint/literal_in_interpolation.rs +5 -5
  96. data/src/rules/lint/literals.rs +10 -8
  97. data/src/rules/lint/no_return_in_begin_end_blocks.rs +2 -2
  98. data/src/rules/lint/node_equality.rs +8 -5
  99. data/src/rules/lint/non_atomic_file_operation.rs +1 -1
  100. data/src/rules/lint/non_deterministic_require_order.rs +5 -3
  101. data/src/rules/lint/non_local_exit_from_iterator.rs +3 -2
  102. data/src/rules/lint/number_conversion.rs +1 -1
  103. data/src/rules/lint/out_of_range_regexp_ref.rs +6 -4
  104. data/src/rules/lint/redundant_dir_glob_sort.rs +1 -2
  105. data/src/rules/lint/redundant_safe_navigation.rs +4 -3
  106. data/src/rules/lint/redundant_splat_expansion.rs +4 -2
  107. data/src/rules/lint/redundant_string_coercion.rs +3 -2
  108. data/src/rules/lint/regexp_source.rs +2 -2
  109. data/src/rules/lint/require_range_parentheses.rs +5 -5
  110. data/src/rules/lint/rescue_exception.rs +4 -3
  111. data/src/rules/lint/rescue_type.rs +3 -2
  112. data/src/rules/lint/return_in_void_context.rs +2 -2
  113. data/src/rules/lint/safe_navigation_chain.rs +3 -2
  114. data/src/rules/lint/self_assignment.rs +3 -2
  115. data/src/rules/lint/shadowed_argument.rs +2 -2
  116. data/src/rules/lint/shadowed_exception.rs +2 -2
  117. data/src/rules/lint/suppressed_exception_in_number_conversion.rs +4 -3
  118. data/src/rules/lint/symbol_conversion.rs +6 -5
  119. data/src/rules/lint/syntax.rs +4 -3
  120. data/src/rules/lint/triple_quotes.rs +3 -2
  121. data/src/rules/lint/unescaped_bracket_in_regexp.rs +1 -1
  122. data/src/rules/lint/unexpected_block_arity.rs +3 -2
  123. data/src/rules/lint/unmodified_reduce_accumulator.rs +7 -6
  124. data/src/rules/lint/unreachable_pattern_branch.rs +4 -4
  125. data/src/rules/lint/unused_block_argument.rs +2 -2
  126. data/src/rules/lint/unused_method_argument.rs +1 -2
  127. data/src/rules/lint/useless_assignment.rs +3 -2
  128. data/src/rules/lint/useless_constant_scoping.rs +3 -2
  129. data/src/rules/lint/useless_else_without_rescue.rs +4 -3
  130. data/src/rules/lint/useless_rescue.rs +5 -4
  131. data/src/rules/lint/useless_ruby2_keywords.rs +2 -1
  132. data/src/rules/lint/useless_setter_call.rs +5 -4
  133. data/src/rules/lint/useless_times.rs +4 -3
  134. data/src/rules/lint/variable_force.rs +146 -100
  135. data/src/rules/lint/void.rs +5 -4
  136. data/src/rules/metrics/block_nesting.rs +1 -2
  137. data/src/rules/metrics/collection_literal_length.rs +2 -1
  138. data/src/rules/metrics/complexity.rs +18 -13
  139. data/src/rules/metrics/fragments.rs +10 -14
  140. data/src/rules/metrics/locals.rs +23 -12
  141. data/src/rules/metrics/parameter_lists.rs +7 -6
  142. data/src/rules/metrics/support.rs +1 -1
  143. data/src/rules/mod.rs +464 -62
  144. data/src/rules/naming/ascii_identifiers.rs +3 -3
  145. data/src/rules/naming/block_forwarding.rs +9 -8
  146. data/src/rules/naming/constant_name.rs +1 -1
  147. data/src/rules/naming/predicate_method.rs +6 -5
  148. data/src/rules/naming/predicate_prefix.rs +10 -8
  149. data/src/rules/naming/rescued_exceptions_variable_name.rs +8 -6
  150. data/src/rules/naming/support.rs +7 -5
  151. data/src/rules/naming/variable_number.rs +4 -4
  152. data/src/rules/node_ext.rs +1 -1
  153. data/src/rules/ruby_literal.rs +3 -2
  154. data/src/rules/security/compound_hash.rs +3 -2
  155. data/src/rules/security/open.rs +5 -4
  156. data/src/rules/send_node.rs +134 -0
  157. data/src/rules/single_line.rs +4 -4
  158. data/src/rules/style/access_modifier_declarations.rs +1 -1
  159. data/src/rules/style/alias.rs +1 -2
  160. data/src/rules/style/and_or.rs +2 -2
  161. data/src/rules/style/arguments_forwarding.rs +5 -5
  162. data/src/rules/style/array_coercion.rs +5 -5
  163. data/src/rules/style/array_first_last.rs +3 -3
  164. data/src/rules/style/array_intersect.rs +2 -2
  165. data/src/rules/style/array_intersect_with_single_element.rs +1 -1
  166. data/src/rules/style/attr.rs +1 -1
  167. data/src/rules/style/auto_resource_cleanup.rs +1 -1
  168. data/src/rules/style/bitwise_predicate.rs +2 -2
  169. data/src/rules/style/block_args.rs +1 -1
  170. data/src/rules/style/block_delimiters.rs +7 -6
  171. data/src/rules/style/case_equality.rs +3 -2
  172. data/src/rules/style/case_like_if.rs +1 -1
  173. data/src/rules/style/class_and_module_children.rs +7 -5
  174. data/src/rules/style/class_methods.rs +1 -1
  175. data/src/rules/style/collection_compact.rs +4 -4
  176. data/src/rules/style/combinable_defined.rs +2 -2
  177. data/src/rules/style/combinable_loops.rs +1 -1
  178. data/src/rules/style/comparable_clamp.rs +2 -2
  179. data/src/rules/style/concat_array_literals.rs +3 -3
  180. data/src/rules/style/conditional.rs +8 -1
  181. data/src/rules/style/constant_visibility.rs +3 -3
  182. data/src/rules/style/copyright.rs +1 -1
  183. data/src/rules/style/data_inheritance.rs +1 -1
  184. data/src/rules/style/def_with_parentheses.rs +1 -1
  185. data/src/rules/style/document_dynamic_eval_definition.rs +1 -1
  186. data/src/rules/style/documentation.rs +1 -1
  187. data/src/rules/style/each_for_simple_loop.rs +1 -1
  188. data/src/rules/style/each_with_object.rs +4 -4
  189. data/src/rules/style/empty_block_parameter.rs +1 -1
  190. data/src/rules/style/empty_case_condition.rs +6 -6
  191. data/src/rules/style/empty_class_definition.rs +1 -1
  192. data/src/rules/style/empty_else.rs +1 -1
  193. data/src/rules/style/empty_heredoc.rs +1 -1
  194. data/src/rules/style/empty_lambda_parameter.rs +1 -1
  195. data/src/rules/style/empty_literal.rs +2 -2
  196. data/src/rules/style/empty_method.rs +1 -1
  197. data/src/rules/style/empty_string_inside_interpolation.rs +1 -1
  198. data/src/rules/style/endless.rs +1 -1
  199. data/src/rules/style/env_home.rs +1 -1
  200. data/src/rules/style/even_odd.rs +1 -1
  201. data/src/rules/style/exact_regexp_match.rs +1 -1
  202. data/src/rules/style/expand_path_arguments.rs +3 -3
  203. data/src/rules/style/explicit_block_argument.rs +3 -3
  204. data/src/rules/style/file_open_call.rs +3 -3
  205. data/src/rules/style/file_write.rs +1 -1
  206. data/src/rules/style/for.rs +1 -1
  207. data/src/rules/style/format_string.rs +2 -2
  208. data/src/rules/style/format_string_token.rs +6 -6
  209. data/src/rules/style/guard_clause.rs +8 -7
  210. data/src/rules/style/hash_as_last_array_item.rs +4 -4
  211. data/src/rules/style/hash_each_methods.rs +1 -1
  212. data/src/rules/style/hash_like_case.rs +8 -8
  213. data/src/rules/style/hash_lookup_method.rs +3 -3
  214. data/src/rules/style/hash_subset.rs +16 -10
  215. data/src/rules/style/hash_syntax.rs +4 -4
  216. data/src/rules/style/hash_transform.rs +20 -18
  217. data/src/rules/style/identical_conditional_branches.rs +4 -5
  218. data/src/rules/style/if_inside_else.rs +3 -3
  219. data/src/rules/style/if_unless_modifier.rs +13 -14
  220. data/src/rules/style/if_with_boolean_literal_branches.rs +1 -1
  221. data/src/rules/style/if_with_semicolon.rs +1 -1
  222. data/src/rules/style/in_pattern_then.rs +2 -2
  223. data/src/rules/style/inverse_methods.rs +2 -2
  224. data/src/rules/style/invertible_unless_condition.rs +3 -3
  225. data/src/rules/style/it_block_parameter.rs +1 -1
  226. data/src/rules/style/keyword_arguments_merging.rs +2 -2
  227. data/src/rules/style/keyword_parameters_order.rs +1 -1
  228. data/src/rules/style/magic_comment_format.rs +3 -2
  229. data/src/rules/style/map_chain.rs +1 -1
  230. data/src/rules/style/map_compact_with_conditional_block.rs +3 -3
  231. data/src/rules/style/map_into_array.rs +7 -7
  232. data/src/rules/style/map_join.rs +3 -3
  233. data/src/rules/style/method_call_with_args_parentheses.rs +7 -7
  234. data/src/rules/style/method_call_without_args_parentheses.rs +2 -2
  235. data/src/rules/style/method_def_parentheses.rs +2 -3
  236. data/src/rules/style/min_max.rs +3 -3
  237. data/src/rules/style/min_max_comparison.rs +2 -2
  238. data/src/rules/style/missing_else.rs +1 -1
  239. data/src/rules/style/missing_respond_to_missing.rs +1 -1
  240. data/src/rules/style/mixin_grouping.rs +1 -1
  241. data/src/rules/style/multiline_block_chain.rs +2 -2
  242. data/src/rules/style/multiline_if_then.rs +1 -1
  243. data/src/rules/style/multiline_in_pattern_then.rs +1 -1
  244. data/src/rules/style/multiline_method_signature.rs +1 -1
  245. data/src/rules/style/multiline_when_then.rs +2 -2
  246. data/src/rules/style/mutable_constant.rs +3 -3
  247. data/src/rules/style/negated_if.rs +2 -2
  248. data/src/rules/style/negated_if_else_condition.rs +2 -2
  249. data/src/rules/style/negated_while.rs +1 -1
  250. data/src/rules/style/negative_array_index.rs +2 -2
  251. data/src/rules/style/nested_modifier.rs +1 -1
  252. data/src/rules/style/nested_parenthesized_calls.rs +2 -2
  253. data/src/rules/style/nested_ternary_operator.rs +2 -2
  254. data/src/rules/style/next.rs +1 -1
  255. data/src/rules/style/nil_lambda.rs +2 -2
  256. data/src/rules/style/nodes.rs +21 -0
  257. data/src/rules/style/non_nil_check.rs +2 -2
  258. data/src/rules/style/numbered_parameters_limit.rs +2 -2
  259. data/src/rules/style/one_line_conditional.rs +4 -4
  260. data/src/rules/style/optional_arguments.rs +1 -1
  261. data/src/rules/style/or_assignment.rs +1 -1
  262. data/src/rules/style/parallel_assignment.rs +9 -10
  263. data/src/rules/style/parens.rs +1 -1
  264. data/src/rules/style/parentheses_around_condition.rs +3 -3
  265. data/src/rules/style/partition_instead_of_double_select.rs +3 -3
  266. data/src/rules/style/percent.rs +9 -7
  267. data/src/rules/style/percent_q_literals.rs +4 -3
  268. data/src/rules/style/preferred_hash_methods.rs +1 -1
  269. data/src/rules/style/random_with_offset.rs +1 -1
  270. data/src/rules/style/reduce_to_hash.rs +6 -6
  271. data/src/rules/style/redundant_argument.rs +1 -1
  272. data/src/rules/style/redundant_assignment.rs +5 -5
  273. data/src/rules/style/redundant_begin.rs +2 -2
  274. data/src/rules/style/redundant_capital_w.rs +3 -2
  275. data/src/rules/style/redundant_condition.rs +9 -7
  276. data/src/rules/style/redundant_current_directory_in_path.rs +2 -2
  277. data/src/rules/style/redundant_double_splat_hash_braces.rs +4 -4
  278. data/src/rules/style/redundant_file_extension_in_require.rs +2 -2
  279. data/src/rules/style/redundant_format.rs +16 -14
  280. data/src/rules/style/redundant_freeze.rs +1 -1
  281. data/src/rules/style/redundant_heredoc_delimiter_quotes.rs +1 -1
  282. data/src/rules/style/redundant_initialize.rs +2 -2
  283. data/src/rules/style/redundant_interpolation.rs +2 -2
  284. data/src/rules/style/redundant_interpolation_unfreeze.rs +2 -2
  285. data/src/rules/style/redundant_line_continuation.rs +5 -4
  286. data/src/rules/style/redundant_parentheses.rs +16 -15
  287. data/src/rules/style/redundant_regexp_argument.rs +1 -1
  288. data/src/rules/style/redundant_regexp_character_class.rs +4 -3
  289. data/src/rules/style/redundant_regexp_escape.rs +3 -2
  290. data/src/rules/style/redundant_return.rs +1 -2
  291. data/src/rules/style/redundant_self.rs +11 -11
  292. data/src/rules/style/redundant_sort.rs +1 -1
  293. data/src/rules/style/redundant_sort_by.rs +1 -1
  294. data/src/rules/style/redundant_string_escape.rs +6 -5
  295. data/src/rules/style/regexp_literal.rs +3 -2
  296. data/src/rules/style/require_order.rs +2 -2
  297. data/src/rules/style/rescue_modifier.rs +1 -1
  298. data/src/rules/style/rescue_standard_error.rs +1 -1
  299. data/src/rules/style/return_nil.rs +2 -2
  300. data/src/rules/style/return_nil_in_predicate_method_definition.rs +2 -2
  301. data/src/rules/style/safe_navigation.rs +2 -2
  302. data/src/rules/style/sample.rs +3 -3
  303. data/src/rules/style/select_by.rs +2 -2
  304. data/src/rules/style/select_by_range.rs +1 -1
  305. data/src/rules/style/semicolon.rs +5 -4
  306. data/src/rules/style/single_argument_dig.rs +1 -1
  307. data/src/rules/style/single_line_block_params.rs +7 -6
  308. data/src/rules/style/single_line_do_end_block.rs +13 -12
  309. data/src/rules/style/single_line_methods.rs +2 -2
  310. data/src/rules/style/slicing_with_range.rs +2 -2
  311. data/src/rules/style/sole_nested_conditional.rs +4 -4
  312. data/src/rules/style/special_global_vars.rs +2 -2
  313. data/src/rules/style/stabby_lambda_parentheses.rs +1 -1
  314. data/src/rules/style/statement_modifier.rs +3 -2
  315. data/src/rules/style/static_class.rs +1 -1
  316. data/src/rules/style/string_concatenation.rs +9 -7
  317. data/src/rules/style/string_hash_keys.rs +3 -2
  318. data/src/rules/style/string_literals.rs +3 -3
  319. data/src/rules/style/string_literals_in_interpolation.rs +1 -1
  320. data/src/rules/style/struct_inheritance.rs +3 -3
  321. data/src/rules/style/super_arguments.rs +2 -2
  322. data/src/rules/style/super_with_args_parentheses.rs +1 -1
  323. data/src/rules/style/swap_values.rs +1 -1
  324. data/src/rules/style/symbol_array.rs +1 -1
  325. data/src/rules/style/symbol_proc.rs +3 -3
  326. data/src/rules/style/tally_method.rs +4 -4
  327. data/src/rules/style/ternary_parentheses.rs +4 -4
  328. data/src/rules/style/top_level_method_definition.rs +1 -1
  329. data/src/rules/style/trailing_body.rs +1 -1
  330. data/src/rules/style/trailing_comma_in_array_literal.rs +1 -1
  331. data/src/rules/style/trailing_comma_in_hash_literal.rs +1 -1
  332. data/src/rules/style/trailing_method_end_statement.rs +1 -1
  333. data/src/rules/style/trailing_underscore_variable.rs +4 -5
  334. data/src/rules/style/trivial_accessors.rs +2 -2
  335. data/src/rules/style/unless_logical_operators.rs +1 -1
  336. data/src/rules/style/unpack_first.rs +1 -1
  337. data/src/rules/style/when_then.rs +4 -4
  338. data/src/rules/style/while_until_do.rs +1 -1
  339. data/src/rules/style/while_until_modifier.rs +3 -3
  340. data/src/rules/style/word_array.rs +3 -3
  341. data/src/rules/style/yoda_condition.rs +2 -2
  342. data/src/rules/support.rs +33 -8
  343. metadata +2 -1
@@ -10,6 +10,7 @@ use crate::diagnostic::{Edit, Offense};
10
10
  use crate::rules::RuleContext;
11
11
  use crate::rules::node_ext::NodeExt;
12
12
  use crate::rules::send_node::{Argument, arguments, heredoc_body, is_plain_send};
13
+ use crate::rules::send_node::named_children_iter;
13
14
 
14
15
  const MSG: &str = "Put the closing parenthesis for a method call with a HEREDOC parameter on the \
15
16
  same line as the HEREDOC opening.";
@@ -73,7 +74,7 @@ fn extract_heredoc_argument<'tree>(
73
74
  }
74
75
 
75
76
  /// `extract_heredoc`: the heredoc a value is, opens a chain with, or holds under a hash key.
76
- fn extract_heredoc<'tree>(node: Node<'tree>, context: &RuleContext<'_>) -> Option<Node<'tree>> {
77
+ fn extract_heredoc<'tree>(node: Node<'tree>, context: &'tree RuleContext<'_>) -> Option<Node<'tree>> {
77
78
  if node.kind_str() == "heredoc_beginning" {
78
79
  return Some(node);
79
80
  }
@@ -84,8 +85,8 @@ fn extract_heredoc<'tree>(node: Node<'tree>, context: &RuleContext<'_>) -> Optio
84
85
  // the brace-less form, whose `hash` upstream builds and the grammar does not.
85
86
  let values: Vec<Node<'tree>> = match node.kind_str() {
86
87
  "hash" => {
87
- let mut cursor = node.walk();
88
- node.named_children(&mut cursor)
88
+ let _cursor = node.walk();
89
+ named_children_iter(node, context)
89
90
  .filter(|child| child.kind_str() == "pair")
90
91
  .filter_map(|pair| pair.field("value"))
91
92
  .collect()
@@ -357,8 +358,8 @@ fn heredoc_terminator(node: Node<'_>, context: &RuleContext<'_>) -> Option<Range
357
358
  return None;
358
359
  }
359
360
  let body = heredoc_body(node, context)?;
360
- let mut cursor = body.walk();
361
- body.named_children(&mut cursor)
361
+ let _cursor = body.walk();
362
+ named_children_iter(body, context)
362
363
  .find(|child| child.kind_str() == "heredoc_end")
363
364
  .map(|child| child.byte_range())
364
365
  }
@@ -8,6 +8,7 @@ use crate::diagnostic::{Edit, Offense};
8
8
  use crate::ruby_version::RubyVersion;
9
9
  use crate::rules::RuleContext;
10
10
  use crate::rules::node_ext::NodeExt;
11
+ use crate::rules::send_node::named_children_of;
11
12
 
12
13
  pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
13
14
  // `minimum_target_ruby_version 2.3`: `<<~` is what the cop asks for, and it did not exist
@@ -101,9 +102,9 @@ fn heredocs<'ctx, 'tree>(
101
102
  .enumerate()
102
103
  .filter_map(|(index, node)| {
103
104
  let opener = *openers.get(index)?;
104
- let mut cursor = node.walk();
105
- let end = node
106
- .named_children(&mut cursor)
105
+ let _cursor = node.walk();
106
+ let end = named_children_of(node, context)
107
+ .into_iter()
107
108
  .find(|child| child.kind_str() == "heredoc_end")?;
108
109
  let first_body_line = context.source.line_column(node.start_byte()).0 + 1;
109
110
  let terminator_line = context.source.line_column(end.start_byte()).0;
@@ -5,6 +5,7 @@ use std::ops::Range;
5
5
  use crate::diagnostic::{Edit, Offense};
6
6
  use crate::rules::RuleContext;
7
7
  use crate::rules::node_ext::NodeExt;
8
+ use crate::rules::send_node::named_children_of;
8
9
 
9
10
  pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
10
11
  let tabs = context
@@ -77,11 +78,11 @@ fn string_literals(context: &RuleContext<'_>) -> Vec<Range<usize>> {
77
78
  .map(|node| node.byte_range())
78
79
  .collect();
79
80
  for body in context.nodes_of("heredoc_body") {
80
- let mut cursor = body.walk();
81
+ let _cursor = body.walk();
81
82
  // `loc.heredoc_body` stops at the start of the terminator's *line*, so the indentation a
82
83
  // squiggly heredoc's terminator was written with is code as far as this cop is concerned.
83
- let end = body
84
- .named_children(&mut cursor)
84
+ let end = named_children_of(body, context)
85
+ .into_iter()
85
86
  .find(|child| child.kind_str() == "heredoc_end")
86
87
  .map_or_else(
87
88
  || body.end_byte(),
@@ -11,7 +11,9 @@ use super::support::{
11
11
  };
12
12
  use crate::diagnostic::Offense;
13
13
  use crate::rules::node_ext::NodeExt;
14
- use crate::rules::{RuleContext, push_named_children};
14
+ use crate::rules::{RuleContext, push_named_children_in};
15
+ use crate::rules::send_node::named_children_of;
16
+ use crate::rules::send_node::all_children_of;
15
17
 
16
18
  pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
17
19
  let width: i64 = context
@@ -48,7 +50,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
48
50
  let mut stack = vec![context.root_node()];
49
51
  while let Some(node) = stack.pop() {
50
52
  checker.visit(node, offenses);
51
- push_named_children(node, &mut stack);
53
+ push_named_children_in(node, context, &mut stack);
52
54
  }
53
55
  }
54
56
 
@@ -203,9 +205,9 @@ impl Checker<'_, '_> {
203
205
  };
204
206
  let row = |byte: usize| self.context.source.line_column(byte).0;
205
207
  // `dot_on_new_line?`: the receiver stops on an earlier line than the dot.
206
- let mut cursor = call.walk();
207
- let dot = call
208
- .children(&mut cursor)
208
+ let _cursor = call.walk();
209
+ let dot = all_children_of(call, self.context)
210
+ .into_iter()
209
211
  .find(|child| !child.is_named() && matches!(child.kind_str(), "." | "&."));
210
212
  if let Some(dot) = dot
211
213
  && call
@@ -281,9 +283,9 @@ impl Checker<'_, '_> {
281
283
  }
282
284
 
283
285
  fn on_case(&mut self, node: Node<'_>, branch_kind: &str, offenses: &mut Vec<Offense>) {
284
- let mut cursor = node.walk();
285
- let branches: Vec<Node<'_>> = node
286
- .named_children(&mut cursor)
286
+ let _cursor = node.walk();
287
+ let branches: Vec<Node<'_>> = named_children_of(node, self.context)
288
+ .into_iter()
287
289
  .filter(|child| child.kind_str() == branch_kind)
288
290
  .collect();
289
291
  let mut last_keyword = None;
@@ -345,9 +347,9 @@ impl Checker<'_, '_> {
345
347
  if node.field("receiver").is_some() {
346
348
  return;
347
349
  }
348
- let mut cursor = node.walk();
349
- let Some(list) = node
350
- .children(&mut cursor)
350
+ let _cursor = node.walk();
351
+ let Some(list) = all_children_of(node, self.context)
352
+ .into_iter()
351
353
  .find(|child| child.kind_str() == "argument_list")
352
354
  else {
353
355
  return;
@@ -694,8 +696,7 @@ fn is_statement_container(node: Node<'_>) -> bool {
694
696
 
695
697
  fn body_container<'tree>(owner: Node<'tree>) -> Option<Node<'tree>> {
696
698
  let mut cursor = owner.walk();
697
- owner
698
- .named_children(&mut cursor)
699
+ owner.named_children(&mut cursor)
699
700
  .find(|child| matches!(child.kind_str(), "body_statement" | "block_body" | "do"))
700
701
  }
701
702
 
@@ -6,7 +6,8 @@ use tree_sitter::Node;
6
6
  use crate::diagnostic::{Edit, Offense};
7
7
  use crate::rules::RuleContext;
8
8
  use crate::rules::node_ext::NodeExt;
9
- use crate::rules::send_node::named_children;
9
+ use crate::rules::send_node::named_children_of;
10
+ use crate::rules::send_node::named_children_iter;
10
11
 
11
12
  /// Ruby's `\s`, which stays ASCII where this engine's would take in every Unicode blank.
12
13
  const BLANK: &str = r"[ \t\r\n\x0B\x0C]";
@@ -130,7 +131,7 @@ fn is_continuation(one: &str, line: usize, node: Node<'_>, context: &RuleContext
130
131
  if !one.ends_with("\\\n") {
131
132
  return false;
132
133
  }
133
- named_children(node).into_iter().all(|child| {
134
+ named_children_iter(node, context).all(|child| {
134
135
  let first = context.source.line_column(child.start_byte()).0;
135
136
  let last = context.source.line_column(child.end_byte()).0;
136
137
  !((first..last).contains(&line) && first != last)
@@ -145,7 +146,7 @@ fn is_dynamic_string(node: Node<'_>, context: &RuleContext<'_>) -> bool {
145
146
  return true;
146
147
  }
147
148
  context.source.line_column(node.start_byte()).0 != context.source.line_column(node.end_byte()).0
148
- || named_children(node)
149
+ || named_children_of(node, context)
149
150
  .iter()
150
151
  .any(|child| child.kind_str() == "interpolation")
151
152
  }
@@ -3,9 +3,9 @@ use std::ops::Range;
3
3
  use crate::diagnostic::{Edit, Offense};
4
4
  use crate::rules::RuleContext;
5
5
  use crate::rules::node_ext::NodeExt;
6
- use crate::rules::send_node::named_children;
7
6
 
8
7
  use super::tokens::tokens;
8
+ use crate::rules::send_node::named_children_of;
9
9
 
10
10
  pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
11
11
  if !context.source.text().contains('\\') {
@@ -118,7 +118,7 @@ fn ignored_ranges(context: &RuleContext<'_>) -> Vec<Range<usize>> {
118
118
  // interpolations one `str` node, where the grammar splits it at every escape.
119
119
  for literal in context.nodes_of_any(&["regex", "subshell"]) {
120
120
  let mut run: Option<Range<usize>> = None;
121
- for child in named_children(literal) {
121
+ for child in named_children_of(literal, context) {
122
122
  match child.kind_str() == "interpolation" {
123
123
  true => ranges.extend(run.take()),
124
124
  false => {
@@ -10,6 +10,7 @@ use crate::rules::node_ext::NodeExt;
10
10
  use crate::rules::support::Interpolations;
11
11
  use crate::rules::support::is_ruby_space_char;
12
12
  use crate::source::is_protected;
13
+ use crate::rules::send_node::named_children_iter;
13
14
 
14
15
  /// `Layout/IndentationStyle`'s `IndentationWidth` is unset by default, so RuboCop falls back to
15
16
  /// `Layout/IndentationWidth`'s `Width`, which is 2. A cop only ever sees its own configuration
@@ -35,16 +36,6 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
35
36
  true => rbs_annotation_lines(context),
36
37
  false => HashSet::new(),
37
38
  };
38
- let allow_uri: bool = context.setting("AllowURI").unwrap_or(true);
39
- let allow_qualified_name: bool = context.setting("AllowQualifiedName").unwrap_or(true);
40
- // `allowed_line?`: a line matching one of these is never long, whatever it holds.
41
- let allowed_patterns =
42
- crate::rules::naming::support::forbidden_patterns_named(context, "AllowedPatterns");
43
- let uri_pattern = match context.setting::<Vec<String>>("URISchemes") {
44
- Some(schemes) if !schemes.is_empty() => uri_regex(&schemes),
45
- _ => URI.clone(),
46
- };
47
-
48
39
  // RuboCop drops the `__END__` line and the data section behind it from the lines it walks, so
49
40
  // a long line down there is not a long line of code.
50
41
  let data_line = context
@@ -53,26 +44,39 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
53
44
  .map_or(usize::MAX, |node| node.start_position().row + 1);
54
45
  let last_line = context.source.line_count().min(data_line.saturating_sub(1));
55
46
 
56
- // Building autocorrections walks a large part of the AST. Most files have no line over the
57
- // limit, so first answer the one condition under which any of that work can be observed.
58
- let has_candidate = (1..=last_line).any(|line_number| {
59
- let raw = context.source.line(line_number);
60
- let line = crate::rules::support::chomp(raw);
61
- let length = line.chars().count() + indentation_difference(line);
62
- length > max
63
- && !(line_number == 1 && line.starts_with("#!"))
64
- && !rbs_lines.contains(&line_number)
65
- && !(context.in_heredoc(
66
- context.source.line_start(line_number)
67
- ..context.source.line_start(line_number) + line.len(),
68
- ) && (allow_all_heredocs || allowed_heredoc_lines.contains(&line_number)))
69
- });
70
- if !has_candidate {
47
+ // Building autocorrections walks a large part of the AST, and every break it finds is filed
48
+ // under a line. Only the lines that are over the limit are ever looked up again, so the lines
49
+ // are settled first and the walk below is held to them. Most files have none at all.
50
+ let candidate_lines: HashSet<usize> = (1..=last_line)
51
+ .filter(|line_number| {
52
+ let raw = context.source.line(*line_number);
53
+ let line = crate::rules::support::chomp(raw);
54
+ let length = line.chars().count() + indentation_difference(line);
55
+ length > max
56
+ && !(*line_number == 1 && line.starts_with("#!"))
57
+ && !rbs_lines.contains(line_number)
58
+ && !(context.in_heredoc(
59
+ context.source.line_start(*line_number)
60
+ ..context.source.line_start(*line_number) + line.len(),
61
+ ) && (allow_all_heredocs || allowed_heredoc_lines.contains(line_number)))
62
+ })
63
+ .collect();
64
+ if candidate_lines.is_empty() {
71
65
  return;
72
66
  }
73
67
 
68
+ let allow_uri: bool = context.setting("AllowURI").unwrap_or(true);
69
+ let allow_qualified_name: bool = context.setting("AllowQualifiedName").unwrap_or(true);
70
+ // `allowed_line?`: a line matching one of these is never long, whatever it holds.
71
+ let allowed_patterns =
72
+ crate::rules::naming::support::forbidden_patterns_named(context, "AllowedPatterns");
73
+ let uri_pattern = match context.setting::<Vec<String>>("URISchemes") {
74
+ Some(schemes) if !schemes.is_empty() => uri_regex(&schemes),
75
+ _ => &*URI,
76
+ };
77
+
74
78
  let allow_directives = allow_cop_directives(context);
75
- let break_edits = line_break_edits(context, max);
79
+ let break_edits = line_break_edits(context, max, &candidate_lines);
76
80
  let directive_lines = directive_lines(context);
77
81
  let endless_method_lines = endless_method_lines(context);
78
82
 
@@ -122,10 +126,10 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
122
126
  (max, without)
123
127
  } else if allow_uri || allow_qualified_name {
124
128
  let uri = allow_uri
125
- .then(|| excessive_range(line, MatchKind::Uri, max, indent, &uri_pattern))
129
+ .then(|| excessive_range(line, MatchKind::Uri, max, indent, uri_pattern))
126
130
  .flatten();
127
131
  let name = allow_qualified_name
128
- .then(|| excessive_range(line, MatchKind::QualifiedName, max, indent, &uri_pattern))
132
+ .then(|| excessive_range(line, MatchKind::QualifiedName, max, indent, uri_pattern))
129
133
  .flatten();
130
134
  if exempted(uri, name, length, max) {
131
135
  continue;
@@ -332,8 +336,7 @@ fn name_start(node: Node<'_>, object: Node<'_>) -> usize {
332
336
 
333
337
  fn is_endless_method(node: Node<'_>) -> bool {
334
338
  let mut cursor = node.walk();
335
- !node
336
- .children(&mut cursor)
339
+ !node.children(&mut cursor)
337
340
  .any(|child| child.kind_str() == "end")
338
341
  }
339
342
 
@@ -451,14 +454,23 @@ static QUALIFIED_NAME: LazyLock<Regex> = LazyLock::new(|| {
451
454
  /// a `//` and the negative lookahead was only ever reachable without one.
452
455
  /// `URISchemes`: the schemes `URI::DEFAULT_PARSER.make_regexp` is built from. Hard-coding
453
456
  /// `https?` made a line holding any other scheme -- the config exists to name one -- too long.
454
- fn uri_regex(schemes: &[String]) -> Regex {
457
+ /// The pattern is built from the configuration, so it cannot live in a `LazyLock` -- but the
458
+ /// configuration does not change between files, and `URISchemes` is set in the default
459
+ /// configuration, so this was compiling the RFC 2396 grammar once per file. It was the single
460
+ /// largest cop cost in a run over RuboCop's own tree.
461
+ fn uri_regex(schemes: &[String]) -> &'static Regex {
455
462
  let escaped: Vec<String> = schemes.iter().map(|scheme| regex::escape(scheme)).collect();
456
- build_uri_regex(&escaped.join("|"))
463
+ crate::rules::regex_cache::compiled(&uri_regex_pattern(&escaped.join("|")))
464
+ .unwrap_or_else(|| &URI)
457
465
  }
458
466
 
459
467
  static URI: LazyLock<Regex> = LazyLock::new(|| build_uri_regex("https?"));
460
468
 
461
469
  fn build_uri_regex(schemes: &str) -> Regex {
470
+ Regex::new(&uri_regex_pattern(schemes)).unwrap()
471
+ }
472
+
473
+ fn uri_regex_pattern(schemes: &str) -> String {
462
474
  const ESCAPED: &str = r"%[a-fA-F\d]{2}";
463
475
  let uric_no_slash = format!(r"(?:[\-_.!~*'()a-zA-Z\d;?:@&=+$,]|{ESCAPED})");
464
476
  let uric = format!(r"(?:[\-_.!~*'()a-zA-Z\d;/?:@&=+$,\[\]]|{ESCAPED})");
@@ -470,10 +482,9 @@ fn build_uri_regex(schemes: &str) -> Regex {
470
482
  let pchar = format!(r"(?:[\-_.!~*'()a-zA-Z\d:@&=+$,]|{ESCAPED})");
471
483
  let segment = format!(r"{pchar}*(?:;{pchar}*)*");
472
484
  let abs_path = format!(r"/{segment}(?:/{segment})*");
473
- Regex::new(&format!(
485
+ format!(
474
486
  r"(?:{schemes}):(?:{uric_no_slash}{uric}*|(?:(?://(?:(?:(?:{userinfo}@)?(?:{host}(?::(?-u:\d)*)?))?|{reg_name}))?(?:{abs_path})?)(?:\?{uric}*)?)(?:\#{uric}*)?"
475
- ))
476
- .unwrap()
487
+ )
477
488
  }
478
489
 
479
490
  /// Whether `URI.parse` accepts the string, which RuboCop uses to weed out RFC 2396 matches that
@@ -579,6 +590,7 @@ fn visit_order(node: Node<'_>, order: &HashMap<usize, u32>) -> (u32, u8) {
579
590
  fn line_break_edits(
580
591
  context: &RuleContext<'_>,
581
592
  max: usize,
593
+ lines: &HashSet<usize>,
582
594
  ) -> HashMap<usize, (Edit, std::ops::Range<usize>)> {
583
595
  let breaker = Breaker {
584
596
  context,
@@ -599,10 +611,10 @@ fn line_break_edits(
599
611
  // Reversed, so that the first semicolon on a line is the one whose position survives.
600
612
  if context.source.text().contains(';') {
601
613
  for offset in semicolon_break_positions(context).into_iter().rev() {
602
- positions.insert(
603
- context.source.line_column(offset).0,
604
- (offset..(offset + 1), "\n".to_owned()),
605
- );
614
+ let line = context.source.line_column(offset).0;
615
+ if lines.contains(&line) {
616
+ positions.insert(line, (offset..(offset + 1), "\n".to_owned()));
617
+ }
606
618
  }
607
619
  }
608
620
 
@@ -611,6 +623,9 @@ fn line_break_edits(
611
623
  // element a break would otherwise go in front of.
612
624
  if context.setting::<bool>("SplitStrings").unwrap_or(false) {
613
625
  for node in context.nodes_of_any(&["string", "bare_string"]) {
626
+ if !lines.contains(&(node.start_position().row + 1)) {
627
+ continue;
628
+ }
614
629
  let Some((offset, delimiter)) = breakable_string(context, node, max) else {
615
630
  continue;
616
631
  };
@@ -626,28 +641,58 @@ fn line_break_edits(
626
641
  }
627
642
  }
628
643
 
644
+ // A break is filed under the line of a node the break goes in front of, which lies inside
645
+ // `node` -- except for a block, whose break is filed under the line the call it hangs off
646
+ // begins on, and that call can start earlier. A node spanning no over-long line has nothing to
647
+ // contribute, and finding that out costs two integers rather than a search for the element.
648
+ let mut candidates: Vec<Node<'_>> = context
649
+ .nodes_of_any(BREAKABLE_KINDS)
650
+ .filter(|node| {
651
+ let first = match matches!(node.kind_str(), "block" | "do_block") {
652
+ true => node
653
+ .parent_of(context)
654
+ .unwrap_or(*node)
655
+ .start_position()
656
+ .row,
657
+ false => node.start_position().row,
658
+ };
659
+ (first + 1..=node.end_position().row + 1).any(|line| lines.contains(&line))
660
+ })
661
+ .collect();
662
+ if candidates.is_empty() {
663
+ return finish(positions);
664
+ }
629
665
  let order = upstream_order(context.root_node());
630
- let mut candidates: Vec<Node<'_>> = context.nodes_of_any(BREAKABLE_KINDS).collect();
631
666
  candidates.sort_by_key(|node| visit_order(*node, &order));
632
667
 
633
668
  for node in candidates {
634
669
  if matches!(node.kind_str(), "block" | "do_block") {
635
- if let Some(offset) = breaker.block_break_position(node) {
636
- // Upstream's block node starts at the receiver, not at the brace, so a call split
637
- // over two lines files its break under the line the receiver is on.
638
- let owner = node.parent_of(context).unwrap_or(node);
639
- positions.insert(
640
- owner.start_position().row + 1,
641
- (offset..(offset + 1), "\n".to_owned()),
642
- );
670
+ // Upstream's block node starts at the receiver, not at the brace, so a call split
671
+ // over two lines files its break under the line the receiver is on.
672
+ let owner = node.parent_of(context).unwrap_or(node);
673
+ let line = owner.start_position().row + 1;
674
+ if lines.contains(&line)
675
+ && let Some(offset) = breaker.block_break_position(node)
676
+ {
677
+ positions.insert(line, (offset..(offset + 1), "\n".to_owned()));
643
678
  }
644
679
  } else if let Some(element) = breaker.breakable_element(node) {
645
- positions
646
- .entry(element.start_position().row + 1)
647
- .or_insert_with(|| (element.byte_range(), "\n".to_owned()));
680
+ let line = element.start_position().row + 1;
681
+ if lines.contains(&line) {
682
+ positions
683
+ .entry(line)
684
+ .or_insert_with(|| (element.byte_range(), "\n".to_owned()));
685
+ }
648
686
  }
649
687
  }
650
688
 
689
+ finish(positions)
690
+ }
691
+
692
+ /// Turns each recorded break into the insertion it stands for.
693
+ fn finish(
694
+ positions: HashMap<usize, (std::ops::Range<usize>, String)>,
695
+ ) -> HashMap<usize, (Edit, std::ops::Range<usize>)> {
651
696
  positions
652
697
  .into_iter()
653
698
  .map(|(line, (anchor, replacement))| {
@@ -791,8 +836,7 @@ impl Breaker<'_, '_> {
791
836
  let mut cursor = container.walk();
792
837
  // A comment is a node of the tree but not of RuboCop's AST, and a heredoc's body hangs off
793
838
  // the argument list it was opened in rather than off the opener, so neither is an element.
794
- let children: Vec<Node<'t>> = container
795
- .named_children(&mut cursor)
839
+ let children: Vec<Node<'t>> = container.named_children(&mut cursor)
796
840
  .filter(|child| !matches!(child.kind_str(), "comment" | "heredoc_body"))
797
841
  .collect();
798
842
  // A literal hash's own pairs are its elements; only an argument list and an array literal
@@ -1200,8 +1244,8 @@ fn breakable_dstr(
1200
1244
  max: usize,
1201
1245
  delimiter: &'static str,
1202
1246
  ) -> Option<(usize, &'static str)> {
1203
- let mut cursor = node.walk();
1204
- for child in node.named_children(&mut cursor) {
1247
+ let _cursor = node.walk();
1248
+ for child in named_children_iter(node, context) {
1205
1249
  if child.kind_str() != "interpolation" {
1206
1250
  continue;
1207
1251
  }
@@ -1227,8 +1271,8 @@ fn breakable_string_part(
1227
1271
  delimiter: &'static str,
1228
1272
  ) -> Option<(usize, &'static str)> {
1229
1273
  let parent_column = context.source.line_column(node.start_byte()).1 - 1;
1230
- let mut cursor = node.walk();
1231
- for part in node.named_children(&mut cursor) {
1274
+ let _cursor = node.walk();
1275
+ for part in named_children_iter(node, context) {
1232
1276
  if part.kind_str() != "string_content" {
1233
1277
  continue;
1234
1278
  }
@@ -5,6 +5,7 @@ use crate::rules::RuleContext;
5
5
  use crate::rules::lint::blocks::BlockArgs;
6
6
  use crate::rules::lint::locals::LocalVariables;
7
7
  use crate::rules::node_ext::NodeExt;
8
+ use crate::rules::send_node::all_children_iter;
8
9
 
9
10
  const NEW_LINE_OFFENSE: &str = "Right hand side of multi-line assignment is on the same line as \
10
11
  the assignment operator `=`.";
@@ -157,10 +158,10 @@ fn block_of(
157
158
  }
158
159
 
159
160
  /// `node.loc.operator`: the `=` or `+=` the assignment was written with.
160
- fn operator<'tree>(node: Node<'tree>, context: &RuleContext<'_>) -> Option<Node<'tree>> {
161
+ fn operator<'tree>(node: Node<'tree>, context: &'tree RuleContext<'_>) -> Option<Node<'tree>> {
161
162
  let left = node.field("left")?;
162
- let mut cursor = node.walk();
163
- node.children(&mut cursor)
163
+ let _cursor = node.walk();
164
+ all_children_iter(node, context)
164
165
  .filter(|child| !child.is_named() && child.start_byte() >= left.end_byte())
165
166
  .find(|child| context.source.node_text(*child).ends_with('='))
166
167
  }
@@ -131,8 +131,7 @@ fn argument_string(context: &RuleContext<'_>, arguments: Node<'_>) -> String {
131
131
 
132
132
  fn parameter_nodes<'tree>(arguments: Node<'tree>) -> Vec<Node<'tree>> {
133
133
  let mut cursor = arguments.walk();
134
- arguments
135
- .named_children(&mut cursor)
134
+ arguments.named_children(&mut cursor)
136
135
  .filter(|child| !matches!(child.kind_str(), "comment" | "heredoc_body"))
137
136
  .collect()
138
137
  }