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
@@ -17,7 +17,7 @@ use tree_sitter::Node;
17
17
  use crate::diagnostic::Edit;
18
18
  use crate::rules::RuleContext;
19
19
  use crate::rules::node_ext::NodeExt;
20
- use crate::rules::send_node::named_children;
20
+ use crate::rules::send_node::named_children_iter;
21
21
 
22
22
  /// One ambiguity the lexer would have warned about.
23
23
  pub(super) struct Ambiguity<'tree> {
@@ -70,7 +70,7 @@ pub(super) fn scan<'tree>(
70
70
  continue;
71
71
  }
72
72
 
73
- let Some(first) = named_children(list).into_iter().next() else {
73
+ let Some(first) = named_children_iter(list, context).next() else {
74
74
  continue;
75
75
  };
76
76
  let text = context.source.node_text(first);
@@ -4,6 +4,8 @@ use tree_sitter::Node;
4
4
  use crate::diagnostic::{Edit, Offense};
5
5
  use crate::rules::RuleContext;
6
6
  use crate::rules::node_ext::NodeExt;
7
+ use crate::rules::send_node::named_children_of;
8
+ use crate::rules::send_node::named_children_iter;
7
9
 
8
10
  /// The enumerable methods a trailing `do` block was probably meant for.
9
11
  const BLOCK_METHODS: &[&str] = &[
@@ -84,7 +86,7 @@ fn check_brace_block_argument(
84
86
  let Some(arguments) = node.field("arguments") else {
85
87
  return;
86
88
  };
87
- let list = named_children(arguments);
89
+ let list = named_children_of(arguments, context);
88
90
  let (Some(&first), Some(&last)) = (list.first(), list.last()) else {
89
91
  return;
90
92
  };
@@ -173,7 +175,7 @@ fn check_do_block(
173
175
  let Some(arguments) = call.field("arguments") else {
174
176
  return;
175
177
  };
176
- let Some(&last) = named_children(arguments).last() else {
178
+ let Some(&last) = named_children_of(arguments, context).last() else {
177
179
  return;
178
180
  };
179
181
  if parenthesized(call, arguments, context) {
@@ -202,7 +204,7 @@ fn check_do_block(
202
204
  fn trailing_block_method<'tree>(
203
205
  node: Node<'tree>,
204
206
  end: usize,
205
- context: &RuleContext<'_>,
207
+ context: &'tree RuleContext<'_>,
206
208
  ) -> Option<Node<'tree>> {
207
209
  let mut stack = vec![node];
208
210
  while let Some(current) = stack.pop() {
@@ -214,18 +216,13 @@ fn trailing_block_method<'tree>(
214
216
  return Some(current);
215
217
  }
216
218
  let start = stack.len();
217
- let mut cursor = current.walk();
218
- stack.extend(current.named_children(&mut cursor));
219
+ let _cursor = current.walk();
220
+ stack.extend(named_children_iter(current, context));
219
221
  stack[start..].reverse();
220
222
  }
221
223
  None
222
224
  }
223
225
 
224
- fn named_children<'tree>(node: Node<'tree>) -> Vec<Node<'tree>> {
225
- let mut cursor = node.walk();
226
- node.named_children(&mut cursor).collect()
227
- }
228
-
229
226
  /// The block written on a call, which upstream holds one level above the call instead.
230
227
  fn block_of(node: Node<'_>) -> Option<Node<'_>> {
231
228
  (node.kind_str() == "call")
@@ -5,6 +5,8 @@ use crate::rules::RuleContext;
5
5
  use crate::rules::node_ext::NodeExt;
6
6
 
7
7
  use super::ambiguity::scan;
8
+ use crate::rules::send_node::named_children_of;
9
+ use crate::rules::send_node::named_children_iter;
8
10
 
9
11
  const MSG: &str = "Ambiguous regexp literal. Parenthesize the method arguments if it's surely a \
10
12
  regexp literal, or add a whitespace to the right of the `/` if it should be a division.";
@@ -31,8 +33,8 @@ fn matches_a_static_regexp(owner: Node<'_>, context: &RuleContext<'_>) -> bool {
31
33
  let Some(arguments) = owner.field("arguments") else {
32
34
  return false;
33
35
  };
34
- let mut cursor = arguments.walk();
35
- let Some(first) = arguments.named_children(&mut cursor).next() else {
36
+ let _cursor = arguments.walk();
37
+ let Some(first) = named_children_iter(arguments, context).next() else {
36
38
  return false;
37
39
  };
38
40
  if first.kind_str() != "binary"
@@ -47,9 +49,9 @@ fn matches_a_static_regexp(owner: Node<'_>, context: &RuleContext<'_>) -> bool {
47
49
  .field("left")
48
50
  .filter(|left| left.kind_str() == "regex")
49
51
  .is_some_and(|left| {
50
- let mut cursor = left.walk();
51
- !left
52
- .named_children(&mut cursor)
52
+ let _cursor = left.walk();
53
+ !named_children_of(left, context)
54
+ .into_iter()
53
55
  .any(|part| part.kind_str() == "interpolation")
54
56
  })
55
57
  }
@@ -3,9 +3,10 @@ use tree_sitter::Node;
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::{has_interpolation, named_children, string_text, symbol_name};
6
+ use crate::rules::send_node::{has_interpolation, string_text, symbol_name};
7
7
 
8
8
  use super::node_equality::numeric_value;
9
+ use crate::rules::send_node::named_children_of;
9
10
 
10
11
  const MSG_CHARACTER_CLASS: &str =
11
12
  "Use a character class instead of interpolating an array in a regexp.";
@@ -21,7 +22,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
21
22
  {
22
23
  continue;
23
24
  }
24
- let Some(array) = named_children(node)
25
+ let Some(array) = named_children_of(node, context)
25
26
  .into_iter()
26
27
  .rfind(|child| child.kind_str() != "comment")
27
28
  // `%w[…]` and `%i[…]` are `array` nodes upstream. The grammar gives each percent form
@@ -30,7 +31,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
30
31
  else {
31
32
  continue;
32
33
  };
33
- let elements: Vec<Node<'_>> = named_children(array)
34
+ let elements: Vec<Node<'_>> = named_children_of(array, context)
34
35
  .into_iter()
35
36
  .filter(|child| child.kind_str() != "comment")
36
37
  .collect();
@@ -6,6 +6,7 @@ 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_iter;
9
10
 
10
11
  const MSG_WITH_SAFE_ASSIGNMENT_ALLOWED: &str = "Use `==` if you meant to do a comparison or wrap the expression in parentheses to \
11
12
  indicate you meant to assign in a condition.";
@@ -191,8 +192,8 @@ fn traverse(
191
192
  }
192
193
  Shape::Other => {}
193
194
  }
194
- let mut cursor = node.walk();
195
- let children: Vec<Node<'_>> = node.named_children(&mut cursor).collect();
195
+ let _cursor = node.walk();
196
+ let children: Vec<Node<'_>> = named_children_iter(node, context).collect();
196
197
  for child in children {
197
198
  traverse(child, context, allow_safe, reported, offenses);
198
199
  }
@@ -14,6 +14,7 @@ use crate::rules::send_node::named_children;
14
14
 
15
15
  use super::locals::LocalVariables;
16
16
  use crate::rules::node_ext::NodeExt;
17
+ use crate::rules::send_node::named_children_of;
17
18
 
18
19
  /// The kinds tree-sitter writes a block as. A `lambda` is `-> { }`, which upstream also reaches
19
20
  /// through `on_block`.
@@ -87,7 +88,7 @@ fn scan(
87
88
  highest: &mut usize,
88
89
  it: &mut bool,
89
90
  ) {
90
- for child in named_children(node) {
91
+ for child in named_children_of(node, context) {
91
92
  if BLOCK_KINDS.contains(&child.kind_str()) || child.kind_str() == "lambda" {
92
93
  continue;
93
94
  }
@@ -3,6 +3,7 @@ use tree_sitter::Node;
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_iter;
6
7
 
7
8
  /// The node kinds a `sym` reaches tree-sitter as. A `%i[]` element is a `bare_symbol` instead,
8
9
  /// which is how the percent literal upstream exempts stays exempt.
@@ -53,8 +54,8 @@ fn boolean_name<'a>(node: Node<'_>, context: &'a RuleContext<'_>) -> Option<&'a
53
54
 
54
55
  /// The text between the quotes, when that is all there is between them.
55
56
  fn quoted_content<'a>(node: Node<'_>, context: &'a RuleContext<'_>) -> Option<&'a str> {
56
- let mut cursor = node.walk();
57
- let parts: Vec<Node<'_>> = node.named_children(&mut cursor).collect();
57
+ let _cursor = node.walk();
58
+ let parts: Vec<Node<'_>> = named_children_iter(node, context).collect();
58
59
  match parts.as_slice() {
59
60
  [content] if content.kind_str() == "string_content" => Some(context.source.node_text(*content)),
60
61
  _ => None,
@@ -68,8 +69,7 @@ fn colon_pair(pair: Node<'_>) -> bool {
68
69
 
69
70
  fn separator(pair: Node<'_>) -> Option<Node<'_>> {
70
71
  let mut cursor = pair.walk();
71
- let separator = pair
72
- .children(&mut cursor)
72
+ let separator = pair.children(&mut cursor)
73
73
  .find(|child| !child.is_named() && matches!(child.kind_str(), ":" | "=>"))?;
74
74
  Some(separator)
75
75
  }
@@ -43,8 +43,7 @@ fn enclosing_block(node: Node<'_>) -> Option<Node<'_>> {
43
43
  // statements one level further down again -- so nothing in such a block is written directly in
44
44
  // it any more.
45
45
  let mut cursor = body.walk();
46
- if body
47
- .named_children(&mut cursor)
46
+ if body.named_children(&mut cursor)
48
47
  .any(|child| matches!(child.kind_str(), "rescue" | "else" | "ensure"))
49
48
  {
50
49
  return None;
@@ -7,6 +7,7 @@ use crate::rules::RuleContext;
7
7
  use crate::rules::node_ext::NodeExt;
8
8
  use crate::rules::send_node::{arguments, named_children, string_text, symbol_name};
9
9
  use crate::rules::support::spurious_assignment_list;
10
+ use crate::rules::send_node::named_children_of;
10
11
 
11
12
  /// The parts of a constant path, as `each_path` walks them.
12
13
  struct ConstantPath {
@@ -45,7 +46,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
45
46
  },
46
47
  _ => namespaces.clone(),
47
48
  };
48
- let mut children = named_children(node);
49
+ let mut children = named_children_of(node, context);
49
50
  children.reverse();
50
51
  for child in children {
51
52
  stack.push((child, inner.clone()));
@@ -223,7 +223,6 @@ fn sanitize_arguments(
223
223
  /// `loc.double_colon`: the `::` the name was written after.
224
224
  fn separator<'tree>(receiver: Node<'tree>, name: Node<'_>) -> Option<Node<'tree>> {
225
225
  let mut cursor = receiver.walk();
226
- receiver
227
- .children(&mut cursor)
226
+ receiver.children(&mut cursor)
228
227
  .find(|child| !child.is_named() && child.end_byte() <= name.start_byte())
229
228
  }
@@ -2,8 +2,8 @@ use tree_sitter::Node;
2
2
 
3
3
  use crate::diagnostic::{Edit, Offense};
4
4
  use crate::rules::RuleContext;
5
- use crate::rules::send_node::named_children;
6
5
  use crate::rules::node_ext::NodeExt;
6
+ use crate::rules::send_node::named_children_of;
7
7
 
8
8
  const MSG: &str = "Unnecessary disjunctive assignment. Use plain assignment.";
9
9
 
@@ -20,7 +20,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
20
20
  };
21
21
  // A body with a `rescue` or an `ensure` is one node of that type upstream rather than the
22
22
  // `begin` this walks, so the very first line already fails the `or_asgn` test.
23
- let lines = named_children(body);
23
+ let lines = named_children_of(body, context);
24
24
  if lines
25
25
  .iter()
26
26
  .any(|line| matches!(line.kind_str(), "rescue" | "ensure" | "else"))
@@ -5,10 +5,11 @@ use tree_sitter::Node;
5
5
  use crate::diagnostic::Offense;
6
6
  use crate::rules::RuleContext;
7
7
  use crate::rules::node_ext::NodeExt;
8
- use crate::rules::send_node::named_children;
9
8
 
10
9
  use super::node_equality::identical;
11
10
  use super::statements::{body_children, statements};
11
+ use crate::rules::send_node::named_children_of;
12
+ use crate::rules::send_node::named_children_iter;
12
13
 
13
14
  /// One branch, with what upstream would report it at.
14
15
  struct Branch<'tree> {
@@ -53,7 +54,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
53
54
  // `on_rescue`: the clauses of one body, which the grammar keeps as siblings rather than under
54
55
  // a node of their own.
55
56
  for container in context.nodes_of_any(&["begin", "body_statement", "block_body", "do"]) {
56
- let clauses: Vec<Node<'_>> = named_children(container)
57
+ let clauses: Vec<Node<'_>> = named_children_of(container, context)
57
58
  .into_iter()
58
59
  .filter(|child| matches!(child.kind_str(), "rescue" | "else"))
59
60
  .collect();
@@ -135,8 +136,8 @@ fn branches<'tree>(node: Node<'tree>, context: &'tree RuleContext<'_>) -> Vec<Br
135
136
  let mut collected = Vec::new();
136
137
  match node.kind_str() {
137
138
  "case" | "case_match" => {
138
- let mut cursor = node.walk();
139
- for clause in node.named_children(&mut cursor) {
139
+ let _cursor = node.walk();
140
+ for clause in named_children_iter(node, context) {
140
141
  match clause.kind_str() {
141
142
  "when" | "in_clause" => collected.push(Branch {
142
143
  nodes: clause.field("body").map(statements).unwrap_or_default(),
@@ -235,7 +236,7 @@ fn is_literal_branch(
235
236
  return true;
236
237
  }
237
238
  let mut all = true;
238
- crate::rules::walk_named(only, &mut |node| {
239
+ crate::rules::walk_named(only, context, &mut |node| {
239
240
  if node.id() == only.id() || !all {
240
241
  return;
241
242
  }
@@ -5,15 +5,16 @@ use crate::rules::RuleContext;
5
5
 
6
6
  use super::node_equality::identical;
7
7
  use crate::rules::node_ext::NodeExt;
8
+ use crate::rules::send_node::named_children_of;
8
9
 
9
10
  const MSG: &str = "Duplicate `when` condition detected.";
10
11
 
11
12
  pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
12
13
  for case in context.nodes_of("case") {
13
14
  let mut seen: Vec<Node<'_>> = Vec::new();
14
- let mut cursor = case.walk();
15
- let branches: Vec<Node<'_>> = case
16
- .named_children(&mut cursor)
15
+ let _cursor = case.walk();
16
+ let branches: Vec<Node<'_>> = named_children_of(case, context)
17
+ .into_iter()
17
18
  .filter(|child| child.kind_str() == "when")
18
19
  .collect();
19
20
  for branch in branches {
@@ -35,8 +36,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
35
36
  /// condition, so what upstream reports is the node inside it.
36
37
  fn conditions<'tree>(branch: Node<'tree>) -> Vec<Node<'tree>> {
37
38
  let mut cursor = branch.walk();
38
- branch
39
- .named_children(&mut cursor)
39
+ branch.named_children(&mut cursor)
40
40
  .filter(|child| child.kind_str() == "pattern")
41
41
  .filter_map(|pattern| pattern.named_child(0))
42
42
  .collect()
@@ -6,6 +6,7 @@ use crate::rules::RuleContext;
6
6
  use super::literals::{is_constant, recursive_basic_literal};
7
7
  use super::node_equality::equality_key;
8
8
  use crate::rules::node_ext::NodeExt;
9
+ use crate::rules::send_node::named_children_of;
9
10
 
10
11
  const MSG: &str = "Duplicated key in hash literal.";
11
12
 
@@ -14,10 +15,10 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
14
15
  // the argument list, so a call's keyword arguments are no hash node here -- and every duplicate
15
16
  // written that way went unreported.
16
17
  for hash in context.nodes_of_any(&["hash", "argument_list"]) {
17
- let mut cursor = hash.walk();
18
+ let _cursor = hash.walk();
18
19
  // `HashNode#keys`: a `**splat` entry is no pair and contributes no key.
19
- let keys: Vec<_> = hash
20
- .named_children(&mut cursor)
20
+ let keys: Vec<_> = named_children_of(hash, context)
21
+ .into_iter()
21
22
  .filter(|child| child.kind_str() == "pair")
22
23
  .filter_map(|pair| pair.field("key"))
23
24
  .filter(|key| recursive_basic_literal(*key, context) || is_constant(*key, context))
@@ -6,15 +6,17 @@ use crate::diagnostic::Offense;
6
6
  use crate::rules::RuleContext;
7
7
  use crate::rules::node_ext::NodeExt;
8
8
  use crate::ruby_version::RubyVersion;
9
+ use crate::rules::send_node::named_children_of;
10
+ use crate::rules::send_node::named_children_iter;
9
11
 
10
12
  pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
11
13
  if context.target_ruby_version() < RubyVersion::new(2, 7) {
12
14
  return;
13
15
  }
14
16
  for case in context.nodes_of("case_match") {
15
- let mut cursor = case.walk();
17
+ let _cursor = case.walk();
16
18
  let mut seen: HashSet<String> = HashSet::new();
17
- for branch in case.named_children(&mut cursor) {
19
+ for branch in named_children_iter(case, context) {
18
20
  if branch.kind_str() != "in_clause" {
19
21
  continue;
20
22
  }
@@ -52,9 +54,9 @@ fn pattern_identity(branch: Node<'_>, pattern: Node<'_>, context: &RuleContext<'
52
54
  /// Upstream builds an alternation of three from an alternation of two, so its children are the run
53
55
  /// up to the last alternative and that last one -- not the flat list the grammar keeps.
54
56
  fn sorted_parts(pattern: Node<'_>, context: &RuleContext<'_>) -> Vec<String> {
55
- let mut cursor = pattern.walk();
56
- let parts: Vec<Node<'_>> = pattern
57
- .named_children(&mut cursor)
57
+ let _cursor = pattern.walk();
58
+ let parts: Vec<Node<'_>> = named_children_of(pattern, context)
59
+ .into_iter()
58
60
  .filter(|child| child.kind_str() != "comment")
59
61
  .collect();
60
62
  let mut sources: Vec<String> = if pattern.kind_str() == "alternative_pattern" && parts.len() > 2
@@ -8,6 +8,7 @@ use crate::rules::node_ext::NodeExt;
8
8
 
9
9
  use super::blocks::BlockArgs;
10
10
  use super::locals::LocalVariables;
11
+ use crate::rules::send_node::named_children_iter;
11
12
 
12
13
  pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
13
14
  let mut tracker = Tracker {
@@ -821,9 +822,9 @@ fn literal_arguments(context: &RuleContext<'_>, node: Node<'_>) -> Vec<String> {
821
822
  let Some(arguments) = node.field("arguments") else {
822
823
  return Vec::new();
823
824
  };
824
- let mut cursor = arguments.walk();
825
+ let _cursor = arguments.walk();
825
826
  let mut names = Vec::new();
826
- for argument in arguments.named_children(&mut cursor) {
827
+ for argument in named_children_iter(arguments, context) {
827
828
  match symbol_name(context.source.node_text(argument)) {
828
829
  Some(name) if matches!(argument.kind_str(), "simple_symbol" | "string") => {
829
830
  names.push(name.to_owned());
@@ -861,7 +862,7 @@ fn attr_with_writer(node: Node<'_>) -> bool {
861
862
  /// `literal_arguments` from answering.
862
863
  fn attr_first_name(context: &RuleContext<'_>, node: Node<'_>) -> Option<String> {
863
864
  let list = node.field("arguments")?;
864
- let first = *crate::rules::send_node::named_children(list).first()?;
865
+ let first = *crate::rules::send_node::named_children_of(list, context).first()?;
865
866
  if !matches!(first.kind_str(), "simple_symbol" | "string") {
866
867
  return None;
867
868
  }
@@ -156,7 +156,6 @@ fn body_parent(container: Node<'_>) -> Parent {
156
156
  /// statements it holds.
157
157
  fn split_body(container: Node<'_>) -> bool {
158
158
  let mut cursor = container.walk();
159
- container
160
- .named_children(&mut cursor)
159
+ container.named_children(&mut cursor)
161
160
  .any(|child| matches!(child.kind_str(), "rescue" | "else" | "ensure"))
162
161
  }
@@ -6,6 +6,7 @@ use crate::rules::node_ext::NodeExt;
6
6
  use crate::rules::send_node::{arguments, named_children};
7
7
 
8
8
  use super::node_equality::identical;
9
+ use crate::rules::send_node::named_children_of;
9
10
 
10
11
  pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
11
12
  for node in context.nodes_of_any(&["call", "element_reference"]) {
@@ -41,12 +42,12 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
41
42
  /// `set_init_elements`, paired with the name the message calls the class by.
42
43
  fn set_init_elements<'tree>(
43
44
  node: Node<'tree>,
44
- context: &RuleContext<'_>,
45
+ context: &'tree RuleContext<'_>,
45
46
  ) -> Option<(String, Vec<Node<'tree>>)> {
46
47
  if node.kind_str() == "element_reference" {
47
48
  let object = node.field("object")?;
48
49
  let name = set_class_name(object, context)?;
49
- let elements = named_children(node)
50
+ let elements = named_children_of(node, context)
50
51
  .into_iter()
51
52
  .filter(|child| child.kind_str() != "comment" && child.id() != object.id())
52
53
  .collect();
@@ -5,6 +5,7 @@ use crate::rules::RuleContext;
5
5
 
6
6
  use super::statements::statements;
7
7
  use crate::rules::node_ext::NodeExt;
8
+ use crate::rules::send_node::all_children_iter;
8
9
 
9
10
  /// The three conditionals whose branch can be written empty. A modifier form always has a body.
10
11
  const CONDITIONALS: &[&str] = &["if", "unless", "elsif"];
@@ -181,7 +182,7 @@ fn enclosing_end<'tree>(node: Node<'tree>, context: &RuleContext<'_>) -> Option<
181
182
  /// `node.loc.begin`: the `then` or `;` the branch was introduced with. The grammar puts a `then`
182
183
  /// inside the branch it opens, but a `;` stays beside the condition -- and a branch holding nothing
183
184
  /// is no node at all, which leaves the `;` as the only trace of it.
184
- fn then_keyword<'tree>(node: Node<'tree>, context: &RuleContext<'_>) -> Option<Node<'tree>> {
185
+ fn then_keyword<'tree>(node: Node<'tree>, context: &'tree RuleContext<'_>) -> Option<Node<'tree>> {
185
186
  if let Some(first) = node
186
187
  .field("consequence")
187
188
  .and_then(|branch| branch.child(0))
@@ -190,8 +191,8 @@ fn then_keyword<'tree>(node: Node<'tree>, context: &RuleContext<'_>) -> Option<N
190
191
  return Some(first);
191
192
  }
192
193
  let condition = node.field("condition")?;
193
- let mut cursor = node.walk();
194
- node.children(&mut cursor).find(|child| {
194
+ let _cursor = node.walk();
195
+ all_children_iter(node, context).find(|child| {
195
196
  child.start_byte() >= condition.end_byte()
196
197
  && matches!(context.source.node_text(*child), "then" | ";")
197
198
  })
@@ -11,6 +11,7 @@ use super::comments_help::comment_search_lines;
11
11
  use crate::ruby_version::RubyVersion;
12
12
 
13
13
  use super::statements::statements;
14
+ use crate::rules::send_node::named_children_iter;
14
15
 
15
16
  const MSG: &str = "Avoid `in` branches without a body.";
16
17
 
@@ -20,8 +21,8 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
20
21
  }
21
22
  let allow_comments: bool = context.setting("AllowComments").unwrap_or(true);
22
23
  for case in context.nodes_of("case_match") {
23
- let mut cursor = case.walk();
24
- let children: Vec<Node<'_>> = case.named_children(&mut cursor).collect();
24
+ let _cursor = case.walk();
25
+ let children: Vec<Node<'_>> = named_children_iter(case, context).collect();
25
26
  for (index, &branch) in children.iter().enumerate() {
26
27
  if branch.kind_str() != "in_clause" || has_body(branch) {
27
28
  continue;
@@ -8,14 +8,15 @@ use crate::rules::RuleContext;
8
8
  use crate::rules::node_ext::NodeExt;
9
9
 
10
10
  use super::comments_help::comment_search_lines;
11
+ use crate::rules::send_node::named_children_iter;
11
12
 
12
13
  const MSG: &str = "Avoid `when` branches without a body.";
13
14
 
14
15
  pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
15
16
  let allow_comments: bool = context.setting("AllowComments").unwrap_or(true);
16
17
  for case in context.nodes_of("case") {
17
- let mut cursor = case.walk();
18
- let children: Vec<Node<'_>> = case.named_children(&mut cursor).collect();
18
+ let _cursor = case.walk();
19
+ let children: Vec<Node<'_>> = named_children_iter(case, context).collect();
19
20
  for (index, &branch) in children.iter().enumerate() {
20
21
  if branch.kind_str() != "when" || has_body(branch) {
21
22
  continue;
@@ -32,8 +33,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
32
33
  /// the `;` or `then` that separates it from the body it does not have is no part of it.
33
34
  fn reported_range(branch: Node<'_>) -> std::ops::Range<usize> {
34
35
  let mut cursor = branch.walk();
35
- let last = branch
36
- .named_children(&mut cursor)
36
+ let last = branch.named_children(&mut cursor)
37
37
  .filter(|child| child.kind_str() == "pattern")
38
38
  .last();
39
39
  branch.start_byte()..last.map_or_else(|| branch.end_byte(), |last| last.end_byte())
@@ -5,6 +5,7 @@ use crate::rules::RuleContext;
5
5
 
6
6
  use super::statements::statements;
7
7
  use crate::rules::node_ext::NodeExt;
8
+ use crate::rules::send_node::named_children_iter;
8
9
 
9
10
  const MSG: &str = "Do not return from an `ensure` block.";
10
11
 
@@ -26,8 +27,8 @@ fn collect(
26
27
  if node.kind_str() == "return" && !returns_from_inner_scope(node, ensure_node, context) {
27
28
  offenses.push(context.offense(MSG, node.byte_range()));
28
29
  }
29
- let mut cursor = node.walk();
30
- let children: Vec<Node<'_>> = node.named_children(&mut cursor).collect();
30
+ let _cursor = node.walk();
31
+ let children: Vec<Node<'_>> = named_children_iter(node, context).collect();
31
32
  for child in children {
32
33
  collect(child, ensure_node, context, offenses);
33
34
  }
@@ -2,8 +2,10 @@ use tree_sitter::Node;
2
2
 
3
3
  use crate::diagnostic::Offense;
4
4
  use crate::rules::RuleContext;
5
- use crate::rules::send_node::{Argument, arguments, named_children, send_range};
5
+ use crate::rules::send_node::{Argument, arguments, send_range};
6
6
  use crate::rules::node_ext::NodeExt;
7
+ use crate::rules::send_node::named_children_of;
8
+ use crate::rules::send_node::named_children_iter;
7
9
 
8
10
  const MSG_EQUALITY: &str = "Avoid equality comparisons of floats as they are unreliable.";
9
11
  const MSG_INEQUALITY: &str = "Avoid inequality comparisons of floats as they are unreliable.";
@@ -52,15 +54,15 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
52
54
 
53
55
  /// `on_case`: every condition of every `when` branch, taken on its own.
54
56
  fn case_conditions(node: Node<'_>, context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
55
- for branch in named_children(node) {
57
+ for branch in named_children_of(node, context) {
56
58
  if branch.kind_str() != "when" {
57
59
  continue;
58
60
  }
59
- for pattern in named_children(branch) {
61
+ for pattern in named_children_of(branch, context) {
60
62
  if pattern.kind_str() != "pattern" {
61
63
  continue;
62
64
  }
63
- let Some(condition) = named_children(pattern).into_iter().next() else {
65
+ let Some(condition) = named_children_iter(pattern, context).next() else {
64
66
  continue;
65
67
  };
66
68
  if is_float(condition, context) && !literal_safe(condition, context) {
@@ -110,7 +112,7 @@ fn is_float(node: Node<'_>, context: &RuleContext<'_>) -> bool {
110
112
  // The parser folds a sign into the numeric literal it stands before.
111
113
  "unary" => signed_numeric(node, context).is_some_and(|operand| operand.kind_str() == "float"),
112
114
  "binary" | "call" => float_send(node, context),
113
- "parenthesized_statements" => named_children(node)
115
+ "parenthesized_statements" => named_children_of(node, context)
114
116
  .into_iter()
115
117
  .next()
116
118
  .is_some_and(|first| is_float(first, context)),
@@ -167,7 +169,7 @@ fn literal_safe(node: Node<'_>, context: &RuleContext<'_>) -> bool {
167
169
  "nil" => true,
168
170
  "integer" | "float" | "rational" | "complex" => is_zero(node, context),
169
171
  "unary" => signed_numeric(node, context).is_some_and(|operand| is_zero(operand, context)),
170
- "parenthesized_statements" => named_children(node)
172
+ "parenthesized_statements" => named_children_of(node, context)
171
173
  .into_iter()
172
174
  .next()
173
175
  .is_some_and(|first| literal_safe(first, context)),
@@ -9,6 +9,7 @@ use crate::rules::send_node::{arguments, is_plain_send};
9
9
  use super::format_string::{is_valid, parse};
10
10
  use super::literals::literal_type;
11
11
  use crate::rules::node_ext::NodeExt;
12
+ use crate::rules::send_node::named_children_of;
12
13
 
13
14
  const MSG_INVALID: &str = "Format string is invalid because formatting sequence types \
14
15
  (numbered, named or unnumbered) are mixed.";
@@ -222,9 +223,9 @@ fn count_matches(call: &Call<'_>, context: &RuleContext<'_>) -> Count {
222
223
  .is_some_and(|first| first.first.kind_str() == "array")
223
224
  {
224
225
  let list = call.given[0].first;
225
- let mut cursor = list.walk();
226
- let passed = list
227
- .named_children(&mut cursor)
226
+ let _cursor = list.walk();
227
+ let passed = named_children_of(list, context)
228
+ .into_iter()
228
229
  .filter(|child| child.kind_str() != "comment")
229
230
  .count();
230
231
  let Some(receiver) = call.receiver else {