sonicop 26.8.111 → 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 (436) hide show
  1. checksums.yaml +4 -4
  2. data/CONFORMANCE.md +64 -31
  3. data/Cargo.lock +94 -19
  4. data/Cargo.toml +13 -8
  5. data/NOTICE +15 -3
  6. data/README.ja.md +145 -57
  7. data/README.md +140 -48
  8. data/build.rs +155 -0
  9. data/lib/sonicop/runner.rb +7 -1
  10. data/lib/sonicop/version.rb +1 -1
  11. data/src/cli.rs +216 -45
  12. data/src/config/inheritance.rs +637 -64
  13. data/src/config/mod.rs +130 -1
  14. data/src/config/paths.rs +550 -48
  15. data/src/cop_name.rs +18 -1
  16. data/src/diagnostic.rs +168 -3
  17. data/src/directives.rs +398 -77
  18. data/src/display_width.rs +82 -42
  19. data/src/display_width_table.rs +506 -0
  20. data/src/engine.rs +1532 -51
  21. data/src/formatter.rs +10 -1
  22. data/src/lib.rs +2 -0
  23. data/src/main.rs +112 -1
  24. data/src/nul_bytes.rs +245 -47
  25. data/src/parser.rs +37 -0
  26. data/src/profile.rs +174 -24
  27. data/src/ruby_version.rs +167 -21
  28. data/src/rules/bundler/duplicated_group.rs +3 -2
  29. data/src/rules/bundler/gem_comment.rs +5 -4
  30. data/src/rules/gemspec/attribute_assignment.rs +4 -3
  31. data/src/rules/gemspec/deprecated_attribute_assignment.rs +7 -6
  32. data/src/rules/gemspec/duplicated_assignment.rs +4 -3
  33. data/src/rules/gemspec/require_mfa.rs +10 -9
  34. data/src/rules/gemspec/required_ruby_version.rs +3 -2
  35. data/src/rules/gemspec/support.rs +28 -8
  36. data/src/rules/layout/access_modifier_indentation.rs +13 -6
  37. data/src/rules/layout/argument_alignment.rs +19 -7
  38. data/src/rules/layout/array_alignment.rs +1 -2
  39. data/src/rules/layout/block_alignment.rs +74 -30
  40. data/src/rules/layout/block_end_newline.rs +5 -5
  41. data/src/rules/layout/class_structure.rs +13 -4
  42. data/src/rules/layout/closing_heredoc_indentation.rs +24 -5
  43. data/src/rules/layout/closing_parenthesis_indentation.rs +3 -3
  44. data/src/rules/layout/comment_indentation.rs +2 -1
  45. data/src/rules/layout/condition_position.rs +3 -2
  46. data/src/rules/layout/def_end_alignment.rs +10 -6
  47. data/src/rules/layout/dot_position.rs +1 -2
  48. data/src/rules/layout/else_alignment.rs +24 -14
  49. data/src/rules/layout/empty_line_after_guard_clause.rs +8 -7
  50. data/src/rules/layout/empty_line_after_multiline_condition.rs +5 -5
  51. data/src/rules/layout/empty_line_between_defs.rs +8 -6
  52. data/src/rules/layout/empty_lines_around_access_modifier.rs +22 -10
  53. data/src/rules/layout/empty_lines_around_arguments.rs +4 -4
  54. data/src/rules/layout/empty_lines_around_body.rs +8 -2
  55. data/src/rules/layout/empty_lines_around_exception_handling_keywords.rs +1 -2
  56. data/src/rules/layout/empty_lines_around_method_body.rs +3 -2
  57. data/src/rules/layout/end_alignment.rs +32 -7
  58. data/src/rules/layout/end_of_line.rs +14 -1
  59. data/src/rules/layout/extra_spacing.rs +9 -11
  60. data/src/rules/layout/first_array_element_indentation.rs +1 -2
  61. data/src/rules/layout/first_hash_element_indentation.rs +8 -6
  62. data/src/rules/layout/hash_alignment.rs +113 -19
  63. data/src/rules/layout/heredoc_argument_closing_parenthesis.rs +6 -5
  64. data/src/rules/layout/heredoc_indentation.rs +4 -3
  65. data/src/rules/layout/indentation_style.rs +6 -4
  66. data/src/rules/layout/indentation_width.rs +76 -16
  67. data/src/rules/layout/initial_indentation.rs +18 -5
  68. data/src/rules/layout/line_continuation_leading_space.rs +4 -3
  69. data/src/rules/layout/line_continuation_spacing.rs +4 -3
  70. data/src/rules/layout/line_length.rs +417 -43
  71. data/src/rules/layout/mod.rs +1 -1
  72. data/src/rules/layout/multiline_assignment_layout.rs +20 -3
  73. data/src/rules/layout/multiline_block_layout.rs +1 -2
  74. data/src/rules/layout/multiline_expression.rs +60 -31
  75. data/src/rules/layout/multiline_hash_brace_layout.rs +4 -3
  76. data/src/rules/layout/multiline_method_call_indentation.rs +1 -1
  77. data/src/rules/layout/multiline_operation_indentation.rs +3 -3
  78. data/src/rules/layout/redundant_line_break.rs +16 -5
  79. data/src/rules/layout/rescue_ensure_alignment.rs +20 -12
  80. data/src/rules/layout/single_line_block_chain.rs +13 -4
  81. data/src/rules/layout/space_around_block_parameters.rs +16 -2
  82. data/src/rules/layout/space_around_equals_in_parameter_default.rs +1 -2
  83. data/src/rules/layout/space_around_keyword.rs +22 -4
  84. data/src/rules/layout/space_around_operators.rs +34 -2
  85. data/src/rules/layout/space_before_brackets.rs +13 -6
  86. data/src/rules/layout/space_before_comma.rs +3 -2
  87. data/src/rules/layout/space_inside_array_literal_brackets.rs +25 -10
  88. data/src/rules/layout/space_inside_array_percent_literal.rs +7 -1
  89. data/src/rules/layout/space_inside_parens.rs +170 -87
  90. data/src/rules/layout/space_inside_range_literal.rs +53 -19
  91. data/src/rules/layout/space_inside_reference_brackets.rs +65 -3
  92. data/src/rules/layout/space_inside_string_interpolation.rs +147 -48
  93. data/src/rules/layout/support.rs +172 -26
  94. data/src/rules/layout/tokens.rs +47 -7
  95. data/src/rules/layout/trailing_whitespace.rs +5 -2
  96. data/src/rules/lint/access_modifier.rs +50 -5
  97. data/src/rules/lint/ambiguity.rs +97 -7
  98. data/src/rules/lint/ambiguous_block_association.rs +29 -12
  99. data/src/rules/lint/ambiguous_operator.rs +8 -0
  100. data/src/rules/lint/ambiguous_operator_precedence.rs +18 -1
  101. data/src/rules/lint/ambiguous_range.rs +15 -1
  102. data/src/rules/lint/ambiguous_regexp_literal.rs +40 -1
  103. data/src/rules/lint/array_literal_in_regexp.rs +13 -5
  104. data/src/rules/lint/assignment_in_condition.rs +3 -2
  105. data/src/rules/lint/blocks.rs +2 -1
  106. data/src/rules/lint/boolean_symbol.rs +4 -4
  107. data/src/rules/lint/constant_definition_in_block.rs +1 -2
  108. data/src/rules/lint/constant_reassignment.rs +9 -13
  109. data/src/rules/lint/constant_resolution.rs +8 -0
  110. data/src/rules/lint/cop_directives.rs +28 -4
  111. data/src/rules/lint/debugger.rs +59 -9
  112. data/src/rules/lint/deprecated_open_ssl_constant.rs +1 -2
  113. data/src/rules/lint/disjunctive_assignment_in_constructor.rs +2 -2
  114. data/src/rules/lint/duplicate_branch.rs +16 -6
  115. data/src/rules/lint/duplicate_case_condition.rs +5 -5
  116. data/src/rules/lint/duplicate_hash_key.rs +8 -4
  117. data/src/rules/lint/duplicate_match_pattern.rs +7 -5
  118. data/src/rules/lint/duplicate_methods.rs +133 -54
  119. data/src/rules/lint/duplicate_require.rs +1 -2
  120. data/src/rules/lint/duplicate_set_element.rs +19 -5
  121. data/src/rules/lint/empty_conditional_body.rs +19 -3
  122. data/src/rules/lint/empty_expression.rs +16 -1
  123. data/src/rules/lint/empty_in_pattern.rs +3 -2
  124. data/src/rules/lint/empty_when.rs +4 -4
  125. data/src/rules/lint/ensure_return.rs +3 -2
  126. data/src/rules/lint/float_comparison.rs +8 -6
  127. data/src/rules/lint/flow.rs +8 -5
  128. data/src/rules/lint/format_parameter_mismatch.rs +4 -3
  129. data/src/rules/lint/hash_compare_by_identity.rs +5 -4
  130. data/src/rules/lint/heredoc_method_call_position.rs +3 -2
  131. data/src/rules/lint/implicit_string_concatenation.rs +33 -3
  132. data/src/rules/lint/ineffective_access_modifier.rs +5 -4
  133. data/src/rules/lint/inherit_exception.rs +4 -3
  134. data/src/rules/lint/literal_as_condition.rs +51 -31
  135. data/src/rules/lint/literal_assignment_in_condition.rs +4 -3
  136. data/src/rules/lint/literal_in_interpolation.rs +66 -5
  137. data/src/rules/lint/literals.rs +10 -8
  138. data/src/rules/lint/missing_cop_enable_directive.rs +95 -18
  139. data/src/rules/lint/mod.rs +1 -0
  140. data/src/rules/lint/nested_method_definition.rs +36 -11
  141. data/src/rules/lint/nil_receiver.rs +420 -0
  142. data/src/rules/lint/no_return_in_begin_end_blocks.rs +2 -2
  143. data/src/rules/lint/node_equality.rs +8 -5
  144. data/src/rules/lint/non_atomic_file_operation.rs +9 -3
  145. data/src/rules/lint/non_deterministic_require_order.rs +5 -3
  146. data/src/rules/lint/non_local_exit_from_iterator.rs +22 -9
  147. data/src/rules/lint/number_conversion.rs +1 -1
  148. data/src/rules/lint/out_of_range_regexp_ref.rs +6 -4
  149. data/src/rules/lint/parentheses_as_grouped_expression.rs +5 -0
  150. data/src/rules/lint/redundant_cop_enable_directive.rs +3 -1
  151. data/src/rules/lint/redundant_dir_glob_sort.rs +1 -2
  152. data/src/rules/lint/redundant_safe_navigation.rs +47 -22
  153. data/src/rules/lint/redundant_splat_expansion.rs +4 -2
  154. data/src/rules/lint/redundant_string_coercion.rs +3 -2
  155. data/src/rules/lint/redundant_type_conversion.rs +16 -4
  156. data/src/rules/lint/regexp.rs +1 -3
  157. data/src/rules/lint/regexp_source.rs +2 -2
  158. data/src/rules/lint/regexp_tree.rs +38 -5
  159. data/src/rules/lint/require_range_parentheses.rs +5 -5
  160. data/src/rules/lint/rescue_exception.rs +4 -3
  161. data/src/rules/lint/rescue_type.rs +3 -2
  162. data/src/rules/lint/return_in_void_context.rs +8 -3
  163. data/src/rules/lint/safe_navigation_chain.rs +47 -11
  164. data/src/rules/lint/self_assignment.rs +20 -2
  165. data/src/rules/lint/shadowed_argument.rs +2 -2
  166. data/src/rules/lint/shadowed_exception.rs +2 -2
  167. data/src/rules/lint/suppressed_exception.rs +21 -3
  168. data/src/rules/lint/suppressed_exception_in_number_conversion.rs +4 -3
  169. data/src/rules/lint/symbol_conversion.rs +56 -8
  170. data/src/rules/lint/syntax.rs +195 -5
  171. data/src/rules/lint/top_level_return_with_argument.rs +11 -1
  172. data/src/rules/lint/triple_quotes.rs +3 -2
  173. data/src/rules/lint/unescaped_bracket_in_regexp.rs +1 -1
  174. data/src/rules/lint/unexpected_block_arity.rs +23 -5
  175. data/src/rules/lint/unified_integer.rs +18 -12
  176. data/src/rules/lint/unmodified_reduce_accumulator.rs +36 -7
  177. data/src/rules/lint/unreachable_code.rs +4 -4
  178. data/src/rules/lint/unreachable_loop.rs +26 -10
  179. data/src/rules/lint/unreachable_pattern_branch.rs +7 -5
  180. data/src/rules/lint/unused_block_argument.rs +2 -2
  181. data/src/rules/lint/unused_method_argument.rs +1 -2
  182. data/src/rules/lint/useless_assignment.rs +3 -2
  183. data/src/rules/lint/useless_constant_scoping.rs +3 -2
  184. data/src/rules/lint/useless_else_without_rescue.rs +4 -3
  185. data/src/rules/lint/useless_rescue.rs +5 -4
  186. data/src/rules/lint/useless_ruby2_keywords.rs +2 -1
  187. data/src/rules/lint/useless_setter_call.rs +5 -4
  188. data/src/rules/lint/useless_times.rs +4 -3
  189. data/src/rules/lint/variable_force.rs +307 -79
  190. data/src/rules/lint/void.rs +32 -20
  191. data/src/rules/metrics/abc_size.rs +197 -7
  192. data/src/rules/metrics/block_length.rs +19 -10
  193. data/src/rules/metrics/block_nesting.rs +1 -2
  194. data/src/rules/metrics/class_length.rs +16 -4
  195. data/src/rules/metrics/collection_literal_length.rs +2 -1
  196. data/src/rules/metrics/complexity.rs +52 -14
  197. data/src/rules/metrics/fragments.rs +10 -14
  198. data/src/rules/metrics/locals.rs +35 -14
  199. data/src/rules/metrics/method_length.rs +14 -6
  200. data/src/rules/metrics/parameter_lists.rs +7 -6
  201. data/src/rules/metrics/perceived_complexity.rs +1 -3
  202. data/src/rules/metrics/support.rs +94 -4
  203. data/src/rules/mod.rs +525 -80
  204. data/src/rules/naming/ascii_identifiers.rs +3 -3
  205. data/src/rules/naming/binary_operator_parameter_name.rs +5 -4
  206. data/src/rules/naming/block_forwarding.rs +9 -8
  207. data/src/rules/naming/constant_name.rs +56 -18
  208. data/src/rules/naming/file_name.rs +174 -43
  209. data/src/rules/naming/method_name.rs +8 -1
  210. data/src/rules/naming/predicate_method.rs +42 -14
  211. data/src/rules/naming/predicate_prefix.rs +70 -4
  212. data/src/rules/naming/rescued_exceptions_variable_name.rs +14 -11
  213. data/src/rules/naming/support.rs +54 -295
  214. data/src/rules/naming/variable_name.rs +17 -4
  215. data/src/rules/naming/variable_number.rs +9 -10
  216. data/src/rules/node_ext.rs +1 -1
  217. data/src/rules/ruby_literal.rs +8 -3
  218. data/src/rules/security/compound_hash.rs +3 -2
  219. data/src/rules/security/open.rs +5 -4
  220. data/src/rules/send_node.rs +134 -0
  221. data/src/rules/single_line.rs +4 -4
  222. data/src/rules/style/access_modifier_declarations.rs +76 -22
  223. data/src/rules/style/accessor_grouping.rs +44 -6
  224. data/src/rules/style/alias.rs +4 -3
  225. data/src/rules/style/and_or.rs +2 -2
  226. data/src/rules/style/arguments_forwarding.rs +5 -5
  227. data/src/rules/style/array_coercion.rs +5 -5
  228. data/src/rules/style/array_first_last.rs +19 -4
  229. data/src/rules/style/array_intersect.rs +26 -8
  230. data/src/rules/style/array_intersect_with_single_element.rs +1 -1
  231. data/src/rules/style/ascii_comments.rs +2 -0
  232. data/src/rules/style/attr.rs +1 -1
  233. data/src/rules/style/auto_resource_cleanup.rs +1 -1
  234. data/src/rules/style/bitwise_predicate.rs +2 -2
  235. data/src/rules/style/block_args.rs +1 -1
  236. data/src/rules/style/block_comments.rs +11 -2
  237. data/src/rules/style/block_delimiters.rs +154 -10
  238. data/src/rules/style/case_equality.rs +7 -2
  239. data/src/rules/style/case_like_if.rs +26 -2
  240. data/src/rules/style/class_and_module_children.rs +162 -10
  241. data/src/rules/style/class_methods.rs +1 -1
  242. data/src/rules/style/class_methods_definitions.rs +9 -0
  243. data/src/rules/style/collection_compact.rs +4 -4
  244. data/src/rules/style/combinable_defined.rs +2 -2
  245. data/src/rules/style/combinable_loops.rs +9 -11
  246. data/src/rules/style/comments.rs +6 -3
  247. data/src/rules/style/comparable_clamp.rs +2 -2
  248. data/src/rules/style/concat_array_literals.rs +3 -3
  249. data/src/rules/style/conditional.rs +12 -1
  250. data/src/rules/style/conditional_assignment.rs +133 -4
  251. data/src/rules/style/constant_visibility.rs +3 -3
  252. data/src/rules/style/copyright.rs +64 -3
  253. data/src/rules/style/data_inheritance.rs +1 -1
  254. data/src/rules/style/def_with_parentheses.rs +1 -1
  255. data/src/rules/style/document_dynamic_eval_definition.rs +50 -12
  256. data/src/rules/style/documentation.rs +1 -1
  257. data/src/rules/style/each_for_simple_loop.rs +1 -1
  258. data/src/rules/style/each_with_object.rs +4 -4
  259. data/src/rules/style/empty_block_parameter.rs +1 -1
  260. data/src/rules/style/empty_case_condition.rs +6 -6
  261. data/src/rules/style/empty_class_definition.rs +1 -1
  262. data/src/rules/style/empty_else.rs +1 -1
  263. data/src/rules/style/empty_heredoc.rs +14 -1
  264. data/src/rules/style/empty_lambda_parameter.rs +1 -1
  265. data/src/rules/style/empty_literal.rs +34 -2
  266. data/src/rules/style/empty_method.rs +1 -1
  267. data/src/rules/style/empty_string_inside_interpolation.rs +1 -1
  268. data/src/rules/style/endless.rs +11 -3
  269. data/src/rules/style/env_home.rs +1 -1
  270. data/src/rules/style/eval_with_location.rs +6 -0
  271. data/src/rules/style/even_odd.rs +1 -1
  272. data/src/rules/style/exact_regexp_match.rs +1 -1
  273. data/src/rules/style/expand_path_arguments.rs +3 -3
  274. data/src/rules/style/explicit_block_argument.rs +3 -3
  275. data/src/rules/style/file_open.rs +5 -0
  276. data/src/rules/style/file_open_call.rs +3 -3
  277. data/src/rules/style/file_write.rs +1 -1
  278. data/src/rules/style/for.rs +1 -1
  279. data/src/rules/style/format_sequences.rs +6 -0
  280. data/src/rules/style/format_string.rs +75 -11
  281. data/src/rules/style/format_string_token.rs +61 -12
  282. data/src/rules/style/frozen_string_literal_comment.rs +62 -4
  283. data/src/rules/style/guard_clause.rs +8 -7
  284. data/src/rules/style/hash_as_last_array_item.rs +4 -4
  285. data/src/rules/style/hash_each_methods.rs +1 -1
  286. data/src/rules/style/hash_like_case.rs +8 -8
  287. data/src/rules/style/hash_lookup_method.rs +43 -3
  288. data/src/rules/style/hash_subset.rs +16 -10
  289. data/src/rules/style/hash_syntax.rs +609 -71
  290. data/src/rules/style/hash_transform.rs +20 -18
  291. data/src/rules/style/hash_transform_keys.rs +7 -0
  292. data/src/rules/style/hash_transform_values.rs +7 -0
  293. data/src/rules/style/identical_conditional_branches.rs +54 -5
  294. data/src/rules/style/if_inside_else.rs +19 -3
  295. data/src/rules/style/if_unless_modifier.rs +13 -14
  296. data/src/rules/style/if_with_boolean_literal_branches.rs +1 -1
  297. data/src/rules/style/if_with_semicolon.rs +7 -1
  298. data/src/rules/style/implicit_runtime_error.rs +7 -0
  299. data/src/rules/style/in_pattern_then.rs +2 -2
  300. data/src/rules/style/infinite_loop.rs +6 -0
  301. data/src/rules/style/inline_comment.rs +4 -1
  302. data/src/rules/style/inverse_methods.rs +12 -2
  303. data/src/rules/style/invertible_unless_condition.rs +12 -12
  304. data/src/rules/style/it_block_parameter.rs +5 -2
  305. data/src/rules/style/keyword_arguments_merging.rs +8 -2
  306. data/src/rules/style/keyword_parameters_order.rs +1 -1
  307. data/src/rules/style/line_end_concatenation.rs +1 -1
  308. data/src/rules/style/magic_comment_format.rs +14 -6
  309. data/src/rules/style/map_chain.rs +1 -1
  310. data/src/rules/style/map_compact_with_conditional_block.rs +3 -3
  311. data/src/rules/style/map_into_array.rs +7 -7
  312. data/src/rules/style/map_join.rs +3 -3
  313. data/src/rules/style/method_call_with_args_parentheses.rs +7 -7
  314. data/src/rules/style/method_call_without_args_parentheses.rs +2 -2
  315. data/src/rules/style/method_def_parentheses.rs +2 -3
  316. data/src/rules/style/min_max.rs +3 -3
  317. data/src/rules/style/min_max_comparison.rs +2 -2
  318. data/src/rules/style/missing_else.rs +1 -1
  319. data/src/rules/style/missing_respond_to_missing.rs +1 -1
  320. data/src/rules/style/mixin_grouping.rs +6 -7
  321. data/src/rules/style/multiline_block_chain.rs +6 -8
  322. data/src/rules/style/multiline_if_then.rs +1 -1
  323. data/src/rules/style/multiline_in_pattern_then.rs +16 -3
  324. data/src/rules/style/multiline_method_signature.rs +1 -1
  325. data/src/rules/style/multiline_when_then.rs +2 -2
  326. data/src/rules/style/mutable_constant.rs +31 -35
  327. data/src/rules/style/negated_if.rs +2 -2
  328. data/src/rules/style/negated_if_else_condition.rs +5 -3
  329. data/src/rules/style/negated_while.rs +1 -1
  330. data/src/rules/style/negative_array_index.rs +25 -3
  331. data/src/rules/style/nested_modifier.rs +1 -1
  332. data/src/rules/style/nested_parenthesized_calls.rs +2 -2
  333. data/src/rules/style/nested_ternary_operator.rs +2 -2
  334. data/src/rules/style/next.rs +12 -12
  335. data/src/rules/style/nil_lambda.rs +2 -2
  336. data/src/rules/style/nodes.rs +21 -0
  337. data/src/rules/style/non_nil_check.rs +82 -2
  338. data/src/rules/style/numbered_parameters.rs +4 -1
  339. data/src/rules/style/numbered_parameters_limit.rs +2 -2
  340. data/src/rules/style/numeric_literals.rs +17 -1
  341. data/src/rules/style/numeric_predicate.rs +25 -6
  342. data/src/rules/style/one_line_conditional.rs +24 -7
  343. data/src/rules/style/operator_method_call.rs +5 -0
  344. data/src/rules/style/optional_arguments.rs +1 -1
  345. data/src/rules/style/or_assignment.rs +1 -1
  346. data/src/rules/style/parallel_assignment.rs +20 -9
  347. data/src/rules/style/parens.rs +1 -1
  348. data/src/rules/style/parentheses_around_condition.rs +3 -3
  349. data/src/rules/style/partition_instead_of_double_select.rs +3 -3
  350. data/src/rules/style/percent.rs +18 -9
  351. data/src/rules/style/percent_q_literals.rs +40 -7
  352. data/src/rules/style/preferred_hash_methods.rs +1 -1
  353. data/src/rules/style/quoted_symbols.rs +6 -0
  354. data/src/rules/style/raise_args.rs +26 -20
  355. data/src/rules/style/random_with_offset.rs +1 -1
  356. data/src/rules/style/reduce_to_hash.rs +6 -6
  357. data/src/rules/style/redundant_argument.rs +1 -1
  358. data/src/rules/style/redundant_assignment.rs +5 -5
  359. data/src/rules/style/redundant_begin.rs +5 -3
  360. data/src/rules/style/redundant_capital_w.rs +3 -2
  361. data/src/rules/style/redundant_condition.rs +17 -8
  362. data/src/rules/style/redundant_current_directory_in_path.rs +2 -2
  363. data/src/rules/style/redundant_double_splat_hash_braces.rs +15 -5
  364. data/src/rules/style/redundant_exception.rs +3 -1
  365. data/src/rules/style/redundant_file_extension_in_require.rs +2 -2
  366. data/src/rules/style/redundant_format.rs +98 -20
  367. data/src/rules/style/redundant_freeze.rs +1 -1
  368. data/src/rules/style/redundant_heredoc_delimiter_quotes.rs +1 -1
  369. data/src/rules/style/redundant_initialize.rs +6 -3
  370. data/src/rules/style/redundant_interpolation.rs +8 -8
  371. data/src/rules/style/redundant_interpolation_unfreeze.rs +10 -3
  372. data/src/rules/style/redundant_line_continuation.rs +10 -7
  373. data/src/rules/style/redundant_parentheses.rs +96 -19
  374. data/src/rules/style/redundant_regexp_argument.rs +1 -1
  375. data/src/rules/style/redundant_regexp_character_class.rs +4 -3
  376. data/src/rules/style/redundant_regexp_escape.rs +3 -2
  377. data/src/rules/style/redundant_return.rs +1 -2
  378. data/src/rules/style/redundant_self.rs +28 -16
  379. data/src/rules/style/redundant_sort.rs +1 -1
  380. data/src/rules/style/redundant_sort_by.rs +1 -1
  381. data/src/rules/style/redundant_string_escape.rs +6 -5
  382. data/src/rules/style/regexp_literal.rs +3 -2
  383. data/src/rules/style/require_order.rs +2 -2
  384. data/src/rules/style/rescue_modifier.rs +9 -4
  385. data/src/rules/style/rescue_standard_error.rs +1 -1
  386. data/src/rules/style/return_nil.rs +2 -2
  387. data/src/rules/style/return_nil_in_predicate_method_definition.rs +2 -2
  388. data/src/rules/style/safe_navigation.rs +2 -2
  389. data/src/rules/style/safe_navigation_chain_length.rs +8 -1
  390. data/src/rules/style/sample.rs +3 -3
  391. data/src/rules/style/select_by.rs +6 -2
  392. data/src/rules/style/select_by_range.rs +1 -1
  393. data/src/rules/style/semicolon.rs +77 -4
  394. data/src/rules/style/signal_exception.rs +60 -3
  395. data/src/rules/style/single_argument_dig.rs +10 -2
  396. data/src/rules/style/single_line_block_params.rs +14 -4
  397. data/src/rules/style/single_line_do_end_block.rs +13 -12
  398. data/src/rules/style/single_line_methods.rs +2 -2
  399. data/src/rules/style/slicing_with_range.rs +2 -2
  400. data/src/rules/style/sole_nested_conditional.rs +4 -4
  401. data/src/rules/style/special_global_vars.rs +2 -2
  402. data/src/rules/style/stabby_lambda_parentheses.rs +1 -1
  403. data/src/rules/style/statement_modifier.rs +3 -2
  404. data/src/rules/style/static_class.rs +7 -1
  405. data/src/rules/style/string_concatenation.rs +12 -7
  406. data/src/rules/style/string_hash_keys.rs +3 -2
  407. data/src/rules/style/string_literals.rs +3 -3
  408. data/src/rules/style/string_literals_in_interpolation.rs +4 -1
  409. data/src/rules/style/struct_inheritance.rs +3 -3
  410. data/src/rules/style/super_arguments.rs +15 -7
  411. data/src/rules/style/super_with_args_parentheses.rs +49 -12
  412. data/src/rules/style/swap_values.rs +1 -1
  413. data/src/rules/style/symbol_array.rs +9 -2
  414. data/src/rules/style/symbol_proc.rs +3 -3
  415. data/src/rules/style/tally_method.rs +4 -4
  416. data/src/rules/style/ternary_parentheses.rs +30 -15
  417. data/src/rules/style/top_level_method_definition.rs +10 -5
  418. data/src/rules/style/trailing_body.rs +1 -1
  419. data/src/rules/style/trailing_comma.rs +206 -10
  420. data/src/rules/style/trailing_comma_in_arguments.rs +9 -10
  421. data/src/rules/style/trailing_comma_in_array_literal.rs +2 -1
  422. data/src/rules/style/trailing_comma_in_hash_literal.rs +2 -1
  423. data/src/rules/style/trailing_method_end_statement.rs +6 -1
  424. data/src/rules/style/trailing_underscore_variable.rs +4 -5
  425. data/src/rules/style/trivial_accessors.rs +2 -2
  426. data/src/rules/style/unless_logical_operators.rs +1 -1
  427. data/src/rules/style/unpack_first.rs +11 -2
  428. data/src/rules/style/when_then.rs +4 -4
  429. data/src/rules/style/while_until_do.rs +1 -1
  430. data/src/rules/style/while_until_modifier.rs +3 -3
  431. data/src/rules/style/word_array.rs +9 -7
  432. data/src/rules/style/yoda_condition.rs +2 -2
  433. data/src/rules/style/zero_length_predicate.rs +5 -0
  434. data/src/rules/support.rs +128 -11
  435. data/src/source.rs +18 -15
  436. metadata +5 -1
@@ -84,7 +84,7 @@ fn skipped(node: Node<'_>, context: &RuleContext<'_>) -> bool {
84
84
  if is_dstr(source) {
85
85
  return true;
86
86
  }
87
- inside_interpolation(node) || quoted_label_key(node, context)
87
+ inside_interpolation(node, context) || quoted_label_key(node, context)
88
88
  }
89
89
 
90
90
  /// RuboCop's `on_dstr`, which only reports under `ConsistentQuotesInMultiline`: a literal the
@@ -286,10 +286,10 @@ pub(super) fn has_interpolation(node: Node<'_>) -> bool {
286
286
  /// RuboCop's `StringHelp#inside_interpolation?`: from the innermost interpolation outwards, is the
287
287
  /// literal owned by a `dstr`, `dsym` or `regexp`? The walk continues past the first interpolation
288
288
  /// because a command literal nested in a string -- `"#{`cmd #{'x'}`}"` -- is still inside one.
289
- pub(super) fn inside_interpolation(node: Node<'_>) -> bool {
289
+ pub(super) fn inside_interpolation(node: Node<'_>, context: &RuleContext<'_>) -> bool {
290
290
  let mut current = node;
291
291
  let mut interpolated = false;
292
- while let Some(parent) = current.parent() {
292
+ while let Some(parent) = context.parent(current) {
293
293
  if parent.kind_str() == "interpolation" {
294
294
  interpolated = true;
295
295
  } else if interpolated && INTERPOLATION_OWNERS.contains(&parent.kind_str()) {
@@ -7,6 +7,9 @@ use super::string_literals::{
7
7
  };
8
8
 
9
9
  pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
10
+ if context.nodes_of("interpolation").next().is_none() {
11
+ return;
12
+ }
10
13
  let style: String = context
11
14
  .setting("EnforcedStyle")
12
15
  .unwrap_or_else(|| "single_quotes".to_owned());
@@ -26,7 +29,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
26
29
  || has_interpolation(node)
27
30
  || is_dstr(source)
28
31
  || quoted_label_key(node, context)
29
- || !inside_interpolation(node)
32
+ || !inside_interpolation(node, context)
30
33
  || !wrong_quotes(source, single_quotes)
31
34
  {
32
35
  continue;
@@ -13,7 +13,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
13
13
  let Some(superclass) = node.field("superclass") else {
14
14
  continue;
15
15
  };
16
- let Some(parent) = super::nodes::children(superclass).into_iter().next() else {
16
+ let Some(parent) = super::nodes::children_in(superclass, context).into_iter().next() else {
17
17
  continue;
18
18
  };
19
19
  if !is_struct_constructor(context, parent) {
@@ -94,7 +94,7 @@ fn correct_parent(
94
94
  // `class_node.body.nil?`: a body holding nothing but comments is no body upstream.
95
95
  if class_node
96
96
  .field("body")
97
- .is_none_or(|body| super::nodes::children(body).is_empty())
97
+ .is_none_or(|body| super::nodes::children_in(body, context).is_empty())
98
98
  {
99
99
  edits.push(empty_body_removal(context, class_node, parent));
100
100
  return;
@@ -150,7 +150,7 @@ fn unparenthesized_arguments(context: &RuleContext<'_>, parent: Node<'_>) -> Opt
150
150
  if arguments.child(0).is_some_and(|open| open.kind_str() == "(") {
151
151
  return None;
152
152
  }
153
- let joined = super::nodes::children(arguments)
153
+ let joined = super::nodes::children_in(arguments, context)
154
154
  .into_iter()
155
155
  .map(|argument| context.source.node_text(argument))
156
156
  .collect::<Vec<_>>()
@@ -78,7 +78,7 @@ fn definition_parameters(definition: Node<'_>, context: &RuleContext<'_>) -> Vec
78
78
  return Vec::new();
79
79
  };
80
80
  let mut found = Vec::new();
81
- for child in super::nodes::children(list) {
81
+ for child in super::nodes::children_in(list, context) {
82
82
  match unfolded_defaults(child) {
83
83
  Some(names) => found.extend(names.into_iter().map(|name| Parameter {
84
84
  kind: "optional_parameter".to_owned(),
@@ -205,13 +205,21 @@ fn same_argument(
205
205
  if argument.kind_str() != "pair" {
206
206
  return false;
207
207
  }
208
- let (Some(key), Some(value)) = (argument.field("key"), argument.field("value")) else {
208
+ let Some(key) = argument.field("key") else {
209
209
  return false;
210
210
  };
211
- // `sym_node.source == lvar_node.source`: only the `name:` shorthand spelling.
212
- context.source.node_text(key) == context.source.node_text(value)
213
- && symbol_name(key, context) == parameter.name.as_deref()
214
- && value.kind_str() == "identifier"
211
+ match argument.field("value") {
212
+ // `sym_node.source == lvar_node.source`: only the `name:` shorthand spelling.
213
+ Some(value) => {
214
+ context.source.node_text(key) == context.source.node_text(value)
215
+ && symbol_name(key, context) == parameter.name.as_deref()
216
+ && value.kind_str() == "identifier"
217
+ }
218
+ // **`a:` with no value is the same pair spelled shorter.** The parser fills the
219
+ // omitted value in with the variable of that name, so `super(a:)` passes `a` --
220
+ // the grammar leaves the field empty instead.
221
+ None => symbol_name(key, context) == parameter.name.as_deref(),
222
+ }
215
223
  }
216
224
  // `keyword_rest_arg_same?`.
217
225
  "hash_splat_parameter" => match &parameter.name {
@@ -272,7 +280,7 @@ fn block_reassigned(context: &RuleContext<'_>, definition: Node<'_>, name: &str)
272
280
  {
273
281
  return true;
274
282
  }
275
- crate::rules::push_named_children(node, &mut stack);
283
+ crate::rules::push_named_children_in(node, context, &mut stack);
276
284
  }
277
285
  false
278
286
  }
@@ -8,22 +8,59 @@ const MSG: &str = "Use parentheses for `super` with arguments.";
8
8
  /// upstream and never reaches this cop, which is why only the calls that carry an argument list
9
9
  /// are walked here.
10
10
  pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
11
- for node in context.nodes_of("call") {
12
- let Some(keyword) = node.field("method") else {
13
- continue;
11
+ // **`super \\\n +bar` is a `super` with one argument upstream.** The parser reads the sign as
12
+ // belonging to the operand; the grammar reads the whole line as a binary expression whose left
13
+ // operand is the keyword, so the call never appears and the offense went unreported.
14
+ for node in context.nodes_of_any(&["call", "binary"]) {
15
+ let (keyword, arguments) = match node.kind_str() {
16
+ "binary" => {
17
+ let (Some(left), Some(right), Some(operator)) =
18
+ (node.field("left"), node.field("right"), node.field("operator"))
19
+ else {
20
+ continue;
21
+ };
22
+ if left.kind_str() != "super" {
23
+ continue;
24
+ }
25
+ // Only a sign the parser folds into the operand makes the line an argument:
26
+ // `super == bar` is a comparison, and `super + 1` an addition, wherever the
27
+ // spacing puts them. The sign has to hug its operand and stand apart from the
28
+ // keyword, which is the spelling `super \` + `-1` has after the continuation.
29
+ let text = context.source.node_text(operator);
30
+ let source = context.source.text();
31
+ let hugs = !source[operator.end_byte()..].starts_with([' ', '\t']);
32
+ if !matches!(text, "+" | "-") || !hugs {
33
+ continue;
34
+ }
35
+ (left, right)
36
+ }
37
+ _ => {
38
+ let Some(keyword) = node.field("method") else {
39
+ continue;
40
+ };
41
+ if keyword.kind_str() != "super" {
42
+ continue;
43
+ }
44
+ let Some(arguments) = node.field("arguments") else {
45
+ continue;
46
+ };
47
+ (keyword, arguments)
48
+ }
14
49
  };
15
- if keyword.kind_str() != "super" {
50
+ // `node.parenthesized?`: the parser reads a `(` written apart from the keyword as the
51
+ // argument's own grouping rather than as the call's parentheses, so `super (x)` has no
52
+ // `loc.begin` and is an offense. The grammar puts that `(` inside the argument list either
53
+ // way, which leaves the space between the two as what tells them apart.
54
+ if arguments.start_byte() == keyword.end_byte()
55
+ && context.source.node_text(arguments).starts_with('(')
56
+ {
16
57
  continue;
17
58
  }
18
- let Some(arguments) = node.field("arguments") else {
19
- continue;
59
+ // A binary's right operand is the single argument; a list holds them all.
60
+ let written = match node.kind_str() {
61
+ "binary" => vec![arguments],
62
+ _ => super::nodes::children_in(arguments, context),
20
63
  };
21
- // `node.parenthesized?`: the argument list starts at the paren when there is one, so its
22
- // first byte is what decides.
23
- if context.source.node_text(arguments).starts_with('(') {
24
- continue;
25
- }
26
- let written = super::nodes::children(arguments);
27
64
  let (Some(first), Some(last)) = (written.first(), written.last()) else {
28
65
  continue;
29
66
  };
@@ -26,7 +26,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
26
26
  let Some(parent) = node.parent() else {
27
27
  continue;
28
28
  };
29
- let statements: Vec<Node<'_>> = super::nodes::children(parent)
29
+ let statements: Vec<Node<'_>> = super::nodes::children_in(parent, context)
30
30
  .into_iter()
31
31
  .filter(|child| child.kind_str() != "comment")
32
32
  .collect();
@@ -1,6 +1,7 @@
1
1
  use tree_sitter::Node;
2
2
 
3
3
  use crate::diagnostic::{Edit, Offense};
4
+ use crate::ruby_version::RubyVersion;
4
5
  use crate::rules::RuleContext;
5
6
 
6
7
  use super::literal::{node_value, to_string_literal, to_symbol_literal, trim_interpolation_escape};
@@ -17,13 +18,19 @@ const ARRAY_MSG: &str = "Use %<prefer>s for an array of symbols.";
17
18
  /// The characters `complex_content?` refuses to leave inside a percent literal.
18
19
  const DELIMITERS: [char; 4] = ['[', ']', '(', ')'];
19
20
 
21
+ /// `minimum_target_ruby_version 2.0`: `%i[…]` arrived in 2.0.
22
+ const MINIMUM: RubyVersion = RubyVersion::new(2, 0);
23
+
20
24
  pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
25
+ if context.target_ruby_version() < MINIMUM {
26
+ return;
27
+ }
21
28
  let style: String = context
22
29
  .setting("EnforcedStyle")
23
30
  .unwrap_or_else(|| "percent".to_owned());
24
31
 
25
32
  for node in context.nodes_of("array") {
26
- let items = nodes::children(node);
33
+ let items = nodes::children_in(node, context);
27
34
  if items.is_empty() || !items.iter().all(|item| is_symbol(context, *item)) {
28
35
  continue;
29
36
  }
@@ -82,7 +89,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
82
89
  fn is_symbol(context: &RuleContext<'_>, node: Node<'_>) -> bool {
83
90
  matches!(node.kind_str(), "simple_symbol" | "delimited_symbol")
84
91
  && !interpolated(node)
85
- && !context.source.node_text(node).contains('\n')
92
+ && !crate::rules::support::quoted_spans_lines(context.source.node_text(node))
86
93
  }
87
94
 
88
95
  fn interpolated(node: Node<'_>) -> bool {
@@ -144,7 +144,7 @@ fn block_parameter(
144
144
  let Some(parameters) = parameters else {
145
145
  return implicit_parameter(context, locals, block);
146
146
  };
147
- let written = super::nodes::children(parameters);
147
+ let written = super::nodes::children_in(parameters, context);
148
148
  let [only] = written.as_slice() else {
149
149
  return None;
150
150
  };
@@ -183,7 +183,7 @@ fn scan_implicit(
183
183
  uses_it: &mut bool,
184
184
  locals: &LocalVariables<'_, '_>,
185
185
  ) {
186
- for child in super::nodes::children(node) {
186
+ for child in super::nodes::children_in(node, context) {
187
187
  // A nested block's implicit parameters are its own.
188
188
  if matches!(child.kind_str(), "block" | "do_block" | "lambda") {
189
189
  continue;
@@ -207,7 +207,7 @@ fn scan_implicit(
207
207
  /// passed to it.
208
208
  fn single_call(context: &RuleContext<'_>, block: Node<'_>, parameter: &str) -> Option<String> {
209
209
  let body = block.field("body")?;
210
- let statements = super::nodes::children(body);
210
+ let statements = super::nodes::children_in(body, context);
211
211
  let [only] = statements.as_slice() else {
212
212
  return None;
213
213
  };
@@ -124,14 +124,14 @@ fn counts_into_hash(context: &RuleContext<'_>, block: Node<'_>) -> bool {
124
124
  && left
125
125
  .field("object")
126
126
  .is_some_and(|object| names(object, &hash, context))
127
- && matches!(super::nodes::children(left).as_slice(),
127
+ && matches!(super::nodes::children_in(left, context).as_slice(),
128
128
  [_, index] if names(*index, &element, context))
129
129
  }
130
130
 
131
131
  /// The element and hash names a block takes, whether declared or numbered.
132
132
  fn two_parameters(context: &RuleContext<'_>, block: Node<'_>) -> Option<(String, String)> {
133
133
  match block.field("parameters") {
134
- Some(parameters) => match super::nodes::children(parameters).as_slice() {
134
+ Some(parameters) => match super::nodes::children_in(parameters, context).as_slice() {
135
135
  [element, hash]
136
136
  if element.kind_str() == "identifier" && hash.kind_str() == "identifier" =>
137
137
  {
@@ -223,7 +223,7 @@ fn counts_block_value(context: &RuleContext<'_>, block: Node<'_>) -> bool {
223
223
  /// The one name a block reads its value by, declared or implicit.
224
224
  fn single_parameter(context: &RuleContext<'_>, block: Node<'_>) -> Option<String> {
225
225
  match block.field("parameters") {
226
- Some(parameters) => match super::nodes::children(parameters).as_slice() {
226
+ Some(parameters) => match super::nodes::children_in(parameters, context).as_slice() {
227
227
  [only] if only.kind_str() == "identifier" => {
228
228
  Some(context.source.node_text(*only).to_owned())
229
229
  }
@@ -244,7 +244,7 @@ fn implicit_name(context: &RuleContext<'_>, block: Node<'_>) -> String {
244
244
  if node.kind_str() == "identifier" && context.source.node_text(node) == "it" {
245
245
  return "it".to_owned();
246
246
  }
247
- crate::rules::push_named_children(node, &mut stack);
247
+ crate::rules::push_named_children_in(node, context, &mut stack);
248
248
  }
249
249
  "_1".to_owned()
250
250
  }
@@ -19,6 +19,14 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
19
19
  let Some(condition) = node.field("condition") else {
20
20
  continue;
21
21
  };
22
+ // `not x ? a : b` is `not(x ? a : b)` upstream whatever the parentheses around `x`: the
23
+ // keyword binds looser than `?:`. The grammar agrees only while `x` is bare -- once it is
24
+ // parenthesized it hoists the conditional above the `not`, which would make the cop wrap
25
+ // `not (x)` and grow another pair of parentheses on every pass.
26
+ let condition = match keyword_not(condition, context) {
27
+ Some(operand) => operand,
28
+ None => condition,
29
+ };
22
30
  if only_closing_parenthesis_is_last_line(context, condition)
23
31
  || condition_as_parenthesized_one_line_pattern_matching(condition)
24
32
  {
@@ -68,6 +76,16 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
68
76
  }
69
77
  }
70
78
 
79
+ /// The operand of a `not` written as the condition, which upstream reads as standing outside the
80
+ /// conditional entirely. `!` is not one of these -- it binds tighter than `?:` and stays inside.
81
+ fn keyword_not<'tree>(node: Node<'tree>, context: &RuleContext<'_>) -> Option<Node<'tree>> {
82
+ if node.kind_str() != "unary" {
83
+ return None;
84
+ }
85
+ let operator = node.child(0)?;
86
+ (context.source.node_text(operator) == "not").then(|| node.field("operand"))?
87
+ }
88
+
71
89
  /// `only_closing_parenthesis_is_last_line?`: a condition whose last line is nothing but `)` is
72
90
  /// spread over lines on purpose, and pulling the parentheses off it would run the lines together.
73
91
  fn only_closing_parenthesis_is_last_line(context: &RuleContext<'_>, condition: Node<'_>) -> bool {
@@ -105,17 +123,18 @@ fn parenthesized_modifier_condition(condition: Node<'_>) -> bool {
105
123
  /// `safe_assignment?`: `(begin {equals_asgn? #setter_method?})`, the parenthesized assignment that
106
124
  /// says the assignment was meant.
107
125
  fn is_safe_assignment(context: &RuleContext<'_>, condition: Node<'_>) -> bool {
108
- let children = super::nodes::children(condition);
126
+ let children = super::nodes::children_in(condition, context);
109
127
  let [only] = children.as_slice() else {
110
128
  return false;
111
129
  };
112
- only.kind_str() == "assignment" && !super::nodes::is_match_assignment(*only, context.source.text())
130
+ only.kind_str() == "assignment"
131
+ && !super::nodes::is_match_assignment(*only, context.source.text())
113
132
  }
114
133
 
115
134
  /// `complex_condition?`: a parenthesized condition is complex when anything written inside it is.
116
135
  fn complex_condition(context: &RuleContext<'_>, condition: Node<'_>) -> bool {
117
136
  if condition.kind_str() == "parenthesized_statements" {
118
- return super::nodes::children(condition)
137
+ return super::nodes::children_in(condition, context)
119
138
  .into_iter()
120
139
  .any(|child| complex_condition(context, child));
121
140
  }
@@ -137,11 +156,9 @@ fn non_complex_expression(context: &RuleContext<'_>, node: Node<'_>) -> bool {
137
156
  .is_some_and(|operator| context.source.node_text(operator) == "defined?"),
138
157
  // A call carrying a block is a `block` node upstream rather than a `send`, and no `block`
139
158
  // is ever simple.
140
- "call" if node.field("block").is_none() => {
141
- node.field("method").is_some_and(|method| {
142
- !super::nodes::is_operator_method(context.source.node_text(method))
143
- })
144
- }
159
+ "call" if node.field("block").is_none() => node.field("method").is_some_and(|method| {
160
+ !super::nodes::is_operator_method(context.source.node_text(method))
161
+ }),
145
162
  // `a.b = 1` is a `send` named `b=`, which is no operator; `a[0] = 1` is `:[]=`, which is.
146
163
  "assignment" => node
147
164
  .field("left")
@@ -153,14 +170,12 @@ fn non_complex_expression(context: &RuleContext<'_>, node: Node<'_>) -> bool {
153
170
  /// `unsafe_autocorrect?`: `and`, `or` and `not` all bind looser than the ternary, so the
154
171
  /// parentheses are what make the condition one.
155
172
  fn unsafe_autocorrect(context: &RuleContext<'_>, condition: Node<'_>) -> bool {
156
- super::nodes::children(condition)
173
+ super::nodes::children_in(condition, context)
157
174
  .into_iter()
158
175
  .any(|child| match child.kind_str() {
159
- "binary" | "unary" => child
160
- .field("operator")
161
- .is_some_and(|operator| {
162
- matches!(context.source.node_text(operator), "and" | "or" | "not")
163
- }),
176
+ "binary" | "unary" => child.field("operator").is_some_and(|operator| {
177
+ matches!(context.source.node_text(operator), "and" | "or" | "not")
178
+ }),
164
179
  _ => false,
165
180
  })
166
181
  }
@@ -218,7 +233,7 @@ fn correct_parenthesized(context: &RuleContext<'_>, condition: Node<'_>) -> Vec<
218
233
  safe: true,
219
234
  });
220
235
  }
221
- if let Some(call) = super::nodes::children(condition).last().copied() {
236
+ if let Some(call) = super::nodes::children_in(condition, context).last().copied() {
222
237
  edits.extend(parenthesize_condition_arguments(context, call));
223
238
  }
224
239
  edits
@@ -12,10 +12,15 @@ const MSG: &str = "Do not define methods at the top-level.";
12
12
  /// statement list, which is the same as having `program` for a parent here.
13
13
  pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
14
14
  for node in context.nodes_of_any(&["method", "singleton_method", "call"]) {
15
- if !node
16
- .parent()
17
- .is_some_and(|parent| parent.kind_str() == "program")
18
- {
15
+ // `node.parent&.begin_type? ? node.parent.root? : node.root?`: a definition wrapped in
16
+ // parentheses is a `begin` at the top level upstream, and counts as written there.
17
+ if !node.parent().is_some_and(|parent| match parent.kind_str() {
18
+ "program" => true,
19
+ "parenthesized_statements" => parent
20
+ .parent()
21
+ .is_some_and(|outer| outer.kind_str() == "program"),
22
+ _ => false,
23
+ }) {
19
24
  continue;
20
25
  }
21
26
  if node.kind_str() == "call" && !defines_a_method(node, context) {
@@ -40,5 +45,5 @@ fn defines_a_method(node: Node<'_>, context: &RuleContext<'_>) -> bool {
40
45
  return true;
41
46
  }
42
47
  node.field("arguments")
43
- .is_some_and(|arguments| super::nodes::children(arguments).len() == 1)
48
+ .is_some_and(|arguments| super::nodes::children_in(arguments, context).len() == 1)
44
49
  }
@@ -18,7 +18,7 @@ pub(super) fn check(
18
18
  let Some(body) = node.field("body") else {
19
19
  return;
20
20
  };
21
- let statements = super::nodes::children(body);
21
+ let statements = super::nodes::children_in(body, context);
22
22
  let (Some(first), Some(last)) = (statements.first(), statements.last()) else {
23
23
  return;
24
24
  };