sonicop 26.8.112 → 26.9.100

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 (369) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +39 -47
  3. data/Cargo.toml +7 -7
  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 +11 -10
  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/access_modifier_indentation.rs +1 -1
  22. data/src/rules/layout/array_alignment.rs +1 -2
  23. data/src/rules/layout/block_alignment.rs +1 -1
  24. data/src/rules/layout/block_end_newline.rs +6 -6
  25. data/src/rules/layout/class_structure.rs +5 -3
  26. data/src/rules/layout/closing_heredoc_indentation.rs +4 -3
  27. data/src/rules/layout/closing_parenthesis_indentation.rs +1 -2
  28. data/src/rules/layout/condition_position.rs +3 -2
  29. data/src/rules/layout/def_end_alignment.rs +2 -2
  30. data/src/rules/layout/dot_position.rs +1 -2
  31. data/src/rules/layout/empty_line_after_guard_clause.rs +3 -6
  32. data/src/rules/layout/empty_line_after_multiline_condition.rs +5 -5
  33. data/src/rules/layout/empty_lines_around_access_modifier.rs +2 -3
  34. data/src/rules/layout/empty_lines_around_arguments.rs +5 -5
  35. data/src/rules/layout/empty_lines_around_exception_handling_keywords.rs +2 -3
  36. data/src/rules/layout/empty_lines_around_method_body.rs +3 -2
  37. data/src/rules/layout/end_alignment.rs +2 -2
  38. data/src/rules/layout/extra_spacing.rs +7 -6
  39. data/src/rules/layout/first_argument_indentation.rs +1 -1
  40. data/src/rules/layout/first_array_element_indentation.rs +2 -3
  41. data/src/rules/layout/first_hash_element_indentation.rs +9 -7
  42. data/src/rules/layout/hash_alignment.rs +4 -4
  43. data/src/rules/layout/heredoc_argument_closing_parenthesis.rs +7 -6
  44. data/src/rules/layout/heredoc_indentation.rs +4 -3
  45. data/src/rules/layout/indentation_style.rs +4 -3
  46. data/src/rules/layout/indentation_width.rs +15 -14
  47. data/src/rules/layout/line_continuation_leading_space.rs +4 -3
  48. data/src/rules/layout/line_continuation_spacing.rs +2 -2
  49. data/src/rules/layout/line_length.rs +101 -57
  50. data/src/rules/layout/multiline_assignment_layout.rs +4 -3
  51. data/src/rules/layout/multiline_block_layout.rs +1 -2
  52. data/src/rules/layout/multiline_brace.rs +1 -1
  53. data/src/rules/layout/multiline_expression.rs +62 -33
  54. data/src/rules/layout/multiline_hash_brace_layout.rs +4 -3
  55. data/src/rules/layout/multiline_method_call_indentation.rs +1 -1
  56. data/src/rules/layout/multiline_operation_indentation.rs +3 -3
  57. data/src/rules/layout/redundant_line_break.rs +3 -2
  58. data/src/rules/layout/single_line_block_chain.rs +4 -3
  59. data/src/rules/layout/space_around_block_parameters.rs +1 -2
  60. data/src/rules/layout/space_around_equals_in_parameter_default.rs +1 -2
  61. data/src/rules/layout/space_around_operators.rs +1 -2
  62. data/src/rules/layout/space_before_brackets.rs +6 -5
  63. data/src/rules/layout/space_before_comma.rs +3 -2
  64. data/src/rules/layout/space_inside_array_percent_literal.rs +1 -1
  65. data/src/rules/layout/space_inside_block_braces.rs +1 -1
  66. data/src/rules/layout/space_inside_hash_literal_braces.rs +1 -1
  67. data/src/rules/layout/space_inside_percent_literal_delimiters.rs +1 -1
  68. data/src/rules/layout/space_inside_range_literal.rs +8 -6
  69. data/src/rules/layout/space_inside_string_interpolation.rs +1 -1
  70. data/src/rules/layout/support.rs +11 -12
  71. data/src/rules/layout/tokens.rs +16 -9
  72. data/src/rules/lint/access_modifier.rs +20 -11
  73. data/src/rules/lint/ambiguity.rs +2 -2
  74. data/src/rules/lint/ambiguous_block_association.rs +7 -10
  75. data/src/rules/lint/ambiguous_regexp_literal.rs +7 -5
  76. data/src/rules/lint/array_literal_in_regexp.rs +4 -3
  77. data/src/rules/lint/assignment_in_condition.rs +3 -2
  78. data/src/rules/lint/blocks.rs +2 -1
  79. data/src/rules/lint/boolean_symbol.rs +4 -4
  80. data/src/rules/lint/constant_definition_in_block.rs +1 -2
  81. data/src/rules/lint/constant_reassignment.rs +2 -1
  82. data/src/rules/lint/deprecated_open_ssl_constant.rs +1 -2
  83. data/src/rules/lint/disjunctive_assignment_in_constructor.rs +2 -2
  84. data/src/rules/lint/duplicate_branch.rs +6 -5
  85. data/src/rules/lint/duplicate_case_condition.rs +5 -5
  86. data/src/rules/lint/duplicate_hash_key.rs +4 -3
  87. data/src/rules/lint/duplicate_match_pattern.rs +7 -5
  88. data/src/rules/lint/duplicate_methods.rs +4 -3
  89. data/src/rules/lint/duplicate_require.rs +1 -2
  90. data/src/rules/lint/duplicate_set_element.rs +3 -2
  91. data/src/rules/lint/empty_conditional_body.rs +5 -4
  92. data/src/rules/lint/empty_in_pattern.rs +3 -2
  93. data/src/rules/lint/empty_when.rs +4 -4
  94. data/src/rules/lint/ensure_return.rs +3 -2
  95. data/src/rules/lint/float_comparison.rs +8 -6
  96. data/src/rules/lint/format_parameter_mismatch.rs +4 -3
  97. data/src/rules/lint/hash_compare_by_identity.rs +5 -4
  98. data/src/rules/lint/heredoc_method_call_position.rs +3 -2
  99. data/src/rules/lint/implicit_string_concatenation.rs +7 -5
  100. data/src/rules/lint/ineffective_access_modifier.rs +5 -4
  101. data/src/rules/lint/inherit_exception.rs +4 -3
  102. data/src/rules/lint/literal_as_condition.rs +5 -3
  103. data/src/rules/lint/literal_assignment_in_condition.rs +4 -3
  104. data/src/rules/lint/literal_in_interpolation.rs +7 -7
  105. data/src/rules/lint/literals.rs +96 -53
  106. data/src/rules/lint/loop.rs +1 -2
  107. data/src/rules/lint/nil_receiver.rs +1 -1
  108. data/src/rules/lint/no_return_in_begin_end_blocks.rs +2 -2
  109. data/src/rules/lint/node_equality.rs +13 -7
  110. data/src/rules/lint/non_atomic_file_operation.rs +2 -2
  111. data/src/rules/lint/non_deterministic_require_order.rs +5 -3
  112. data/src/rules/lint/non_local_exit_from_iterator.rs +3 -2
  113. data/src/rules/lint/number_conversion.rs +1 -1
  114. data/src/rules/lint/out_of_range_regexp_ref.rs +6 -4
  115. data/src/rules/lint/redundant_dir_glob_sort.rs +1 -2
  116. data/src/rules/lint/redundant_safe_navigation.rs +4 -3
  117. data/src/rules/lint/redundant_splat_expansion.rs +4 -2
  118. data/src/rules/lint/redundant_string_coercion.rs +3 -2
  119. data/src/rules/lint/regexp.rs +1 -1
  120. data/src/rules/lint/regexp_source.rs +2 -2
  121. data/src/rules/lint/require_range_parentheses.rs +5 -5
  122. data/src/rules/lint/rescue_exception.rs +4 -3
  123. data/src/rules/lint/rescue_type.rs +3 -2
  124. data/src/rules/lint/return_in_void_context.rs +2 -2
  125. data/src/rules/lint/safe_navigation_chain.rs +3 -2
  126. data/src/rules/lint/self_assignment.rs +3 -2
  127. data/src/rules/lint/shadowed_argument.rs +2 -2
  128. data/src/rules/lint/shadowed_exception.rs +2 -2
  129. data/src/rules/lint/suppressed_exception.rs +1 -1
  130. data/src/rules/lint/suppressed_exception_in_number_conversion.rs +4 -3
  131. data/src/rules/lint/symbol_conversion.rs +6 -5
  132. data/src/rules/lint/syntax.rs +5 -4
  133. data/src/rules/lint/triple_quotes.rs +3 -2
  134. data/src/rules/lint/unescaped_bracket_in_regexp.rs +1 -1
  135. data/src/rules/lint/unexpected_block_arity.rs +3 -2
  136. data/src/rules/lint/unmodified_reduce_accumulator.rs +7 -6
  137. data/src/rules/lint/unreachable_loop.rs +27 -11
  138. data/src/rules/lint/unreachable_pattern_branch.rs +4 -4
  139. data/src/rules/lint/unused_block_argument.rs +2 -2
  140. data/src/rules/lint/unused_method_argument.rs +1 -2
  141. data/src/rules/lint/useless_assignment.rs +3 -2
  142. data/src/rules/lint/useless_constant_scoping.rs +3 -2
  143. data/src/rules/lint/useless_else_without_rescue.rs +4 -3
  144. data/src/rules/lint/useless_rescue.rs +5 -4
  145. data/src/rules/lint/useless_ruby2_keywords.rs +2 -1
  146. data/src/rules/lint/useless_setter_call.rs +5 -4
  147. data/src/rules/lint/useless_times.rs +4 -3
  148. data/src/rules/lint/variable_force.rs +147 -101
  149. data/src/rules/lint/void.rs +5 -4
  150. data/src/rules/metrics/block_nesting.rs +1 -2
  151. data/src/rules/metrics/collection_literal_length.rs +2 -1
  152. data/src/rules/metrics/complexity.rs +18 -13
  153. data/src/rules/metrics/fragments.rs +10 -14
  154. data/src/rules/metrics/locals.rs +24 -13
  155. data/src/rules/metrics/parameter_lists.rs +7 -6
  156. data/src/rules/metrics/support.rs +1 -1
  157. data/src/rules/mod.rs +543 -62
  158. data/src/rules/naming/ascii_identifiers.rs +3 -3
  159. data/src/rules/naming/block_forwarding.rs +9 -8
  160. data/src/rules/naming/constant_name.rs +1 -1
  161. data/src/rules/naming/predicate_method.rs +6 -5
  162. data/src/rules/naming/predicate_prefix.rs +10 -8
  163. data/src/rules/naming/rescued_exceptions_variable_name.rs +8 -6
  164. data/src/rules/naming/support.rs +8 -6
  165. data/src/rules/naming/variable_number.rs +4 -4
  166. data/src/rules/node_ext.rs +45 -14
  167. data/src/rules/ruby_literal.rs +3 -2
  168. data/src/rules/security/compound_hash.rs +3 -2
  169. data/src/rules/security/open.rs +5 -4
  170. data/src/rules/send_node.rs +135 -1
  171. data/src/rules/single_line.rs +4 -4
  172. data/src/rules/style/access_modifier_declarations.rs +11 -4
  173. data/src/rules/style/alias.rs +1 -2
  174. data/src/rules/style/and_or.rs +2 -2
  175. data/src/rules/style/arguments_forwarding.rs +5 -5
  176. data/src/rules/style/array_coercion.rs +5 -5
  177. data/src/rules/style/array_first_last.rs +3 -3
  178. data/src/rules/style/array_intersect.rs +2 -2
  179. data/src/rules/style/array_intersect_with_single_element.rs +1 -1
  180. data/src/rules/style/attr.rs +1 -1
  181. data/src/rules/style/auto_resource_cleanup.rs +1 -1
  182. data/src/rules/style/bitwise_predicate.rs +2 -2
  183. data/src/rules/style/block_args.rs +1 -1
  184. data/src/rules/style/block_delimiters.rs +7 -6
  185. data/src/rules/style/case_equality.rs +3 -2
  186. data/src/rules/style/case_like_if.rs +1 -1
  187. data/src/rules/style/class_and_module_children.rs +9 -7
  188. data/src/rules/style/class_methods.rs +1 -1
  189. data/src/rules/style/collection_compact.rs +4 -4
  190. data/src/rules/style/combinable_defined.rs +2 -2
  191. data/src/rules/style/combinable_loops.rs +1 -1
  192. data/src/rules/style/command_literal.rs +1 -1
  193. data/src/rules/style/comparable_clamp.rs +2 -2
  194. data/src/rules/style/concat_array_literals.rs +4 -4
  195. data/src/rules/style/conditional.rs +8 -1
  196. data/src/rules/style/conditional_assignment.rs +1 -1
  197. data/src/rules/style/constant_visibility.rs +3 -3
  198. data/src/rules/style/copyright.rs +1 -1
  199. data/src/rules/style/data_inheritance.rs +1 -1
  200. data/src/rules/style/def_with_parentheses.rs +2 -2
  201. data/src/rules/style/document_dynamic_eval_definition.rs +1 -1
  202. data/src/rules/style/documentation.rs +1 -1
  203. data/src/rules/style/each_for_simple_loop.rs +1 -1
  204. data/src/rules/style/each_with_object.rs +4 -4
  205. data/src/rules/style/empty_block_parameter.rs +1 -1
  206. data/src/rules/style/empty_case_condition.rs +6 -6
  207. data/src/rules/style/empty_class_definition.rs +1 -1
  208. data/src/rules/style/empty_else.rs +2 -2
  209. data/src/rules/style/empty_heredoc.rs +1 -1
  210. data/src/rules/style/empty_lambda_parameter.rs +1 -1
  211. data/src/rules/style/empty_literal.rs +2 -2
  212. data/src/rules/style/empty_method.rs +1 -1
  213. data/src/rules/style/empty_string_inside_interpolation.rs +1 -1
  214. data/src/rules/style/endless.rs +1 -1
  215. data/src/rules/style/env_home.rs +1 -1
  216. data/src/rules/style/even_odd.rs +1 -1
  217. data/src/rules/style/exact_regexp_match.rs +1 -1
  218. data/src/rules/style/expand_path_arguments.rs +3 -3
  219. data/src/rules/style/explicit_block_argument.rs +3 -3
  220. data/src/rules/style/file_open_call.rs +3 -3
  221. data/src/rules/style/file_write.rs +1 -1
  222. data/src/rules/style/for.rs +1 -1
  223. data/src/rules/style/format_string.rs +2 -2
  224. data/src/rules/style/format_string_token.rs +8 -8
  225. data/src/rules/style/guard_clause.rs +8 -7
  226. data/src/rules/style/hash_as_last_array_item.rs +5 -5
  227. data/src/rules/style/hash_conversion.rs +1 -1
  228. data/src/rules/style/hash_each_methods.rs +1 -1
  229. data/src/rules/style/hash_fetch_chain.rs +1 -1
  230. data/src/rules/style/hash_like_case.rs +8 -8
  231. data/src/rules/style/hash_lookup_method.rs +3 -3
  232. data/src/rules/style/hash_subset.rs +16 -10
  233. data/src/rules/style/hash_syntax.rs +4 -4
  234. data/src/rules/style/hash_transform.rs +20 -18
  235. data/src/rules/style/identical_conditional_branches.rs +4 -5
  236. data/src/rules/style/if_inside_else.rs +3 -3
  237. data/src/rules/style/if_unless_modifier.rs +13 -14
  238. data/src/rules/style/if_with_boolean_literal_branches.rs +1 -1
  239. data/src/rules/style/if_with_semicolon.rs +1 -1
  240. data/src/rules/style/in_pattern_then.rs +2 -2
  241. data/src/rules/style/infinite_loop.rs +1 -1
  242. data/src/rules/style/inverse_methods.rs +2 -2
  243. data/src/rules/style/invertible_unless_condition.rs +3 -3
  244. data/src/rules/style/it_block_parameter.rs +1 -1
  245. data/src/rules/style/keyword_arguments_merging.rs +2 -2
  246. data/src/rules/style/keyword_parameters_order.rs +1 -1
  247. data/src/rules/style/lambda.rs +1 -1
  248. data/src/rules/style/literal.rs +2 -2
  249. data/src/rules/style/magic_comment_format.rs +3 -2
  250. data/src/rules/style/map_chain.rs +1 -1
  251. data/src/rules/style/map_compact_with_conditional_block.rs +3 -3
  252. data/src/rules/style/map_into_array.rs +7 -7
  253. data/src/rules/style/map_join.rs +3 -3
  254. data/src/rules/style/method_call_with_args_parentheses.rs +7 -7
  255. data/src/rules/style/method_call_without_args_parentheses.rs +2 -2
  256. data/src/rules/style/method_def_parentheses.rs +2 -3
  257. data/src/rules/style/min_max.rs +3 -3
  258. data/src/rules/style/min_max_comparison.rs +2 -2
  259. data/src/rules/style/missing_else.rs +4 -4
  260. data/src/rules/style/missing_respond_to_missing.rs +1 -1
  261. data/src/rules/style/mixin_grouping.rs +1 -1
  262. data/src/rules/style/multiline_block_chain.rs +3 -3
  263. data/src/rules/style/multiline_if_then.rs +1 -1
  264. data/src/rules/style/multiline_in_pattern_then.rs +1 -1
  265. data/src/rules/style/multiline_memoization.rs +1 -1
  266. data/src/rules/style/multiline_method_signature.rs +1 -1
  267. data/src/rules/style/multiline_when_then.rs +2 -2
  268. data/src/rules/style/mutable_constant.rs +3 -3
  269. data/src/rules/style/negated_if.rs +2 -2
  270. data/src/rules/style/negated_if_else_condition.rs +2 -2
  271. data/src/rules/style/negated_while.rs +1 -1
  272. data/src/rules/style/negative_array_index.rs +2 -2
  273. data/src/rules/style/nested_modifier.rs +1 -1
  274. data/src/rules/style/nested_parenthesized_calls.rs +2 -2
  275. data/src/rules/style/nested_ternary_operator.rs +2 -2
  276. data/src/rules/style/next.rs +1 -1
  277. data/src/rules/style/nil_lambda.rs +2 -2
  278. data/src/rules/style/nodes.rs +21 -0
  279. data/src/rules/style/non_nil_check.rs +3 -3
  280. data/src/rules/style/numbered_parameters_limit.rs +2 -2
  281. data/src/rules/style/one_line_conditional.rs +4 -4
  282. data/src/rules/style/optional_arguments.rs +1 -1
  283. data/src/rules/style/or_assignment.rs +1 -1
  284. data/src/rules/style/parallel_assignment.rs +9 -10
  285. data/src/rules/style/parens.rs +1 -1
  286. data/src/rules/style/parentheses_around_condition.rs +3 -3
  287. data/src/rules/style/partition_instead_of_double_select.rs +3 -3
  288. data/src/rules/style/percent.rs +10 -8
  289. data/src/rules/style/percent_array.rs +3 -3
  290. data/src/rules/style/percent_q_literals.rs +4 -3
  291. data/src/rules/style/preferred_hash_methods.rs +1 -1
  292. data/src/rules/style/random_with_offset.rs +1 -1
  293. data/src/rules/style/reduce_to_hash.rs +6 -6
  294. data/src/rules/style/redundant_argument.rs +1 -1
  295. data/src/rules/style/redundant_assignment.rs +5 -5
  296. data/src/rules/style/redundant_begin.rs +2 -2
  297. data/src/rules/style/redundant_capital_w.rs +3 -2
  298. data/src/rules/style/redundant_condition.rs +9 -7
  299. data/src/rules/style/redundant_current_directory_in_path.rs +2 -2
  300. data/src/rules/style/redundant_double_splat_hash_braces.rs +4 -4
  301. data/src/rules/style/redundant_file_extension_in_require.rs +2 -2
  302. data/src/rules/style/redundant_format.rs +16 -14
  303. data/src/rules/style/redundant_freeze.rs +1 -1
  304. data/src/rules/style/redundant_heredoc_delimiter_quotes.rs +1 -1
  305. data/src/rules/style/redundant_initialize.rs +2 -2
  306. data/src/rules/style/redundant_interpolation.rs +2 -2
  307. data/src/rules/style/redundant_interpolation_unfreeze.rs +2 -2
  308. data/src/rules/style/redundant_line_continuation.rs +5 -4
  309. data/src/rules/style/redundant_parentheses.rs +16 -15
  310. data/src/rules/style/redundant_regexp_argument.rs +1 -1
  311. data/src/rules/style/redundant_regexp_character_class.rs +5 -4
  312. data/src/rules/style/redundant_regexp_constructor.rs +1 -1
  313. data/src/rules/style/redundant_regexp_escape.rs +4 -3
  314. data/src/rules/style/redundant_return.rs +1 -2
  315. data/src/rules/style/redundant_self.rs +11 -11
  316. data/src/rules/style/redundant_sort.rs +1 -1
  317. data/src/rules/style/redundant_sort_by.rs +1 -1
  318. data/src/rules/style/redundant_string_escape.rs +6 -5
  319. data/src/rules/style/regexp_literal.rs +4 -3
  320. data/src/rules/style/require_order.rs +8 -4
  321. data/src/rules/style/rescue_modifier.rs +1 -1
  322. data/src/rules/style/rescue_standard_error.rs +1 -1
  323. data/src/rules/style/return_nil.rs +2 -2
  324. data/src/rules/style/return_nil_in_predicate_method_definition.rs +2 -2
  325. data/src/rules/style/safe_navigation.rs +2 -2
  326. data/src/rules/style/sample.rs +3 -3
  327. data/src/rules/style/select_by.rs +2 -2
  328. data/src/rules/style/select_by_range.rs +1 -1
  329. data/src/rules/style/semicolon.rs +5 -4
  330. data/src/rules/style/single_argument_dig.rs +1 -1
  331. data/src/rules/style/single_line_block_params.rs +7 -6
  332. data/src/rules/style/single_line_do_end_block.rs +13 -12
  333. data/src/rules/style/single_line_methods.rs +3 -3
  334. data/src/rules/style/slicing_with_range.rs +2 -2
  335. data/src/rules/style/sole_nested_conditional.rs +4 -4
  336. data/src/rules/style/special_global_vars.rs +2 -2
  337. data/src/rules/style/stabby_lambda_parentheses.rs +1 -1
  338. data/src/rules/style/statement_modifier.rs +3 -2
  339. data/src/rules/style/static_class.rs +1 -1
  340. data/src/rules/style/string_concatenation.rs +11 -9
  341. data/src/rules/style/string_hash_keys.rs +3 -2
  342. data/src/rules/style/string_literals.rs +3 -3
  343. data/src/rules/style/string_literals_in_interpolation.rs +1 -1
  344. data/src/rules/style/struct_inheritance.rs +4 -4
  345. data/src/rules/style/super_arguments.rs +2 -2
  346. data/src/rules/style/super_with_args_parentheses.rs +1 -1
  347. data/src/rules/style/swap_values.rs +1 -1
  348. data/src/rules/style/symbol_array.rs +1 -1
  349. data/src/rules/style/symbol_proc.rs +3 -3
  350. data/src/rules/style/tally_method.rs +4 -4
  351. data/src/rules/style/ternary_parentheses.rs +4 -4
  352. data/src/rules/style/top_level_method_definition.rs +1 -1
  353. data/src/rules/style/trailing_body.rs +1 -1
  354. data/src/rules/style/trailing_body_on_method_definition.rs +1 -1
  355. data/src/rules/style/trailing_comma.rs +1 -1
  356. data/src/rules/style/trailing_comma_in_array_literal.rs +1 -1
  357. data/src/rules/style/trailing_comma_in_hash_literal.rs +1 -1
  358. data/src/rules/style/trailing_method_end_statement.rs +2 -2
  359. data/src/rules/style/trailing_underscore_variable.rs +4 -5
  360. data/src/rules/style/trivial_accessors.rs +2 -2
  361. data/src/rules/style/unless_logical_operators.rs +1 -1
  362. data/src/rules/style/unpack_first.rs +1 -1
  363. data/src/rules/style/when_then.rs +4 -4
  364. data/src/rules/style/while_until_do.rs +1 -1
  365. data/src/rules/style/while_until_modifier.rs +3 -3
  366. data/src/rules/style/word_array.rs +3 -3
  367. data/src/rules/style/yoda_condition.rs +2 -2
  368. data/src/rules/support.rs +33 -8
  369. metadata +2 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd4ccd5169f98c0ac8c5aedbe9dd4662344c27da16b2a4ea009a5f95b77a0cff
4
- data.tar.gz: d516055ea9785026bda48a405d49ad97fc0e0851469bafa7d71cb341b663bda3
3
+ metadata.gz: a163c5bd6a8d400159bd4ba0f973dffb08ec9a588554d11ba4d1240962b7f4ed
4
+ data.tar.gz: 23e90583b4aafc8fbe66ecee0202d0fedddf45ed75d90e6060a7d5fb77345343
5
5
  SHA512:
6
- metadata.gz: a28ead40c6fd72e5e79ea4c69e3d6dabeeb1a5af3004110548ae02cbad6310bbdaf6fe7f5765afc3014d77dd640dcad02821465be4d6d866808f080bc697f822
7
- data.tar.gz: f422f7e53c4e4a7535ac1910ca2bbf50a0e7fae1851fcb94621a0dcec388bf4bdd0164962b140187085e15eabb5e31351f0e4c0a04ae6cb050fa8b1f7834e009
6
+ metadata.gz: 0cb9a7320c8bbbe4b3fa3d773486cf66460bc5f29eb43161226dd195566210ec7cab52757c4543a01a6d9f127e0508bcb3ccb9c1ddcd95dbc6908678a202115a
7
+ data.tar.gz: faa62e145f9d96b10db86cf60a9a565a3c6033b8a4b28c994ecb76d99a1a4e8e79ed30775a85e1b512988117901f7b9ddb3ff19e9a8e9d116e34125a0eed03f2
data/Cargo.lock CHANGED
@@ -67,12 +67,6 @@ version = "1.0.104"
67
67
  source = "registry+https://github.com/rust-lang/crates.io-index"
68
68
  checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470"
69
69
 
70
- [[package]]
71
- name = "arrayref"
72
- version = "0.3.9"
73
- source = "registry+https://github.com/rust-lang/crates.io-index"
74
- checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
75
-
76
70
  [[package]]
77
71
  name = "arrayvec"
78
72
  version = "0.7.8"
@@ -114,11 +108,10 @@ checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
114
108
 
115
109
  [[package]]
116
110
  name = "blake3"
117
- version = "1.8.6"
111
+ version = "1.8.7"
118
112
  source = "registry+https://github.com/rust-lang/crates.io-index"
119
- checksum = "76ae7bad254120e9e4c63bafc385310756f90c484eac0e36b8317cf09cb92a77"
113
+ checksum = "6d9e454fc11f76977dc803893aff6304ed33d6a26efae8696573bea74baa27ae"
120
114
  dependencies = [
121
- "arrayref",
122
115
  "arrayvec",
123
116
  "cc",
124
117
  "cfg-if",
@@ -128,9 +121,9 @@ dependencies = [
128
121
 
129
122
  [[package]]
130
123
  name = "bstr"
131
- version = "1.13.0"
124
+ version = "1.13.1"
132
125
  source = "registry+https://github.com/rust-lang/crates.io-index"
133
- checksum = "1f7dc094d718f2e1c1559ad110e27eeaae14a5465d3d56dd6dbd793079fbd530"
126
+ checksum = "6bb31b46c14244e20ee9984b11bf5c992b91fb6939fea616e3512c8baecdbe5f"
134
127
  dependencies = [
135
128
  "memchr",
136
129
  "regex-automata",
@@ -145,9 +138,9 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
145
138
 
146
139
  [[package]]
147
140
  name = "cc"
148
- version = "1.4.0"
141
+ version = "1.4.5"
149
142
  source = "registry+https://github.com/rust-lang/crates.io-index"
150
- checksum = "5add81bb678e6cb321aff7fa0dc7689ad82b112dbc032cea19f91d6b8e3582b9"
143
+ checksum = "005ec2760ca554fae18df7a11195552ec576cd665632a881bc011d5bb2fd4d80"
151
144
  dependencies = [
152
145
  "find-msvc-tools",
153
146
  "shlex",
@@ -191,7 +184,7 @@ dependencies = [
191
184
  "heck",
192
185
  "proc-macro2",
193
186
  "quote",
194
- "syn 3.0.3",
187
+ "syn 3.0.5",
195
188
  ]
196
189
 
197
190
  [[package]]
@@ -230,18 +223,18 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
230
223
 
231
224
  [[package]]
232
225
  name = "cpufeatures"
233
- version = "0.3.0"
226
+ version = "0.3.1"
234
227
  source = "registry+https://github.com/rust-lang/crates.io-index"
235
- checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
228
+ checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566"
236
229
  dependencies = [
237
230
  "libc",
238
231
  ]
239
232
 
240
233
  [[package]]
241
234
  name = "crossbeam-deque"
242
- version = "0.8.7"
235
+ version = "0.8.8"
243
236
  source = "registry+https://github.com/rust-lang/crates.io-index"
244
- checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb"
237
+ checksum = "622f3fc73690be383c7214310406f28a90e6edeadc3cea882f9d71e495b9711a"
245
238
  dependencies = [
246
239
  "crossbeam-epoch",
247
240
  "crossbeam-utils",
@@ -249,24 +242,24 @@ dependencies = [
249
242
 
250
243
  [[package]]
251
244
  name = "crossbeam-epoch"
252
- version = "0.9.20"
245
+ version = "0.9.21"
253
246
  source = "registry+https://github.com/rust-lang/crates.io-index"
254
- checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f"
247
+ checksum = "dc74980687109a3b14c72fd458107bf0baa1da1a1a805e178d15501ba9b86d9d"
255
248
  dependencies = [
256
249
  "crossbeam-utils",
257
250
  ]
258
251
 
259
252
  [[package]]
260
253
  name = "crossbeam-utils"
261
- version = "0.8.22"
254
+ version = "0.8.23"
262
255
  source = "registry+https://github.com/rust-lang/crates.io-index"
263
- checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17"
256
+ checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6"
264
257
 
265
258
  [[package]]
266
259
  name = "der"
267
- version = "0.8.1"
260
+ version = "0.8.2"
268
261
  source = "registry+https://github.com/rust-lang/crates.io-index"
269
- checksum = "a69dedd701da44b0536442edf09c81a64b0ab97a7a4a5e3d1971f00027cbc63d"
262
+ checksum = "a878c850e9e421b20262e9b41f9c860e4785fa07541c266b62ff9d1ef998a80a"
270
263
  dependencies = [
271
264
  "pem-rfc7468",
272
265
  "zeroize",
@@ -280,9 +273,9 @@ checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
280
273
 
281
274
  [[package]]
282
275
  name = "either"
283
- version = "1.17.0"
276
+ version = "1.18.0"
284
277
  source = "registry+https://github.com/rust-lang/crates.io-index"
285
- checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d"
278
+ checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34"
286
279
 
287
280
  [[package]]
288
281
  name = "encoding_rs"
@@ -317,9 +310,9 @@ checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223"
317
310
 
318
311
  [[package]]
319
312
  name = "find-msvc-tools"
320
- version = "0.1.9"
313
+ version = "0.1.12"
321
314
  source = "registry+https://github.com/rust-lang/crates.io-index"
322
- checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
315
+ checksum = "3e0f1c7c3a72c66fd80abe965175f7523475c0489a87d3ff9d6e8c87d87a9d2d"
323
316
 
324
317
  [[package]]
325
318
  name = "foreign-types"
@@ -416,9 +409,9 @@ dependencies = [
416
409
 
417
410
  [[package]]
418
411
  name = "indexmap"
419
- version = "2.14.0"
412
+ version = "2.14.2"
420
413
  source = "registry+https://github.com/rust-lang/crates.io-index"
421
- checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
414
+ checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855"
422
415
  dependencies = [
423
416
  "equivalent",
424
417
  "hashbrown",
@@ -450,9 +443,9 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
450
443
 
451
444
  [[package]]
452
445
  name = "log"
453
- version = "0.4.33"
446
+ version = "0.4.34"
454
447
  source = "registry+https://github.com/rust-lang/crates.io-index"
455
- checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
448
+ checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
456
449
 
457
450
  [[package]]
458
451
  name = "memchr"
@@ -549,9 +542,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
549
542
 
550
543
  [[package]]
551
544
  name = "pkg-config"
552
- version = "0.3.33"
545
+ version = "0.3.34"
553
546
  source = "registry+https://github.com/rust-lang/crates.io-index"
554
- checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e"
547
+ checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548"
555
548
 
556
549
  [[package]]
557
550
  name = "predicates"
@@ -749,7 +742,7 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
749
742
  dependencies = [
750
743
  "proc-macro2",
751
744
  "quote",
752
- "syn 3.0.3",
745
+ "syn 3.0.5",
753
746
  ]
754
747
 
755
748
  [[package]]
@@ -793,7 +786,7 @@ checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
793
786
 
794
787
  [[package]]
795
788
  name = "sonicop"
796
- version = "26.8.112"
789
+ version = "26.9.100"
797
790
  dependencies = [
798
791
  "anyhow",
799
792
  "assert_cmd",
@@ -840,9 +833,9 @@ dependencies = [
840
833
 
841
834
  [[package]]
842
835
  name = "syn"
843
- version = "3.0.3"
836
+ version = "3.0.5"
844
837
  source = "registry+https://github.com/rust-lang/crates.io-index"
845
- checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
838
+ checksum = "12df2e0110f65b775f769bb17ef989067a1d931b2eb822bd4346631eeada89f9"
846
839
  dependencies = [
847
840
  "proc-macro2",
848
841
  "quote",
@@ -880,13 +873,12 @@ checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683"
880
873
 
881
874
  [[package]]
882
875
  name = "tree-sitter"
883
- version = "0.26.11"
876
+ version = "0.27.0"
884
877
  source = "registry+https://github.com/rust-lang/crates.io-index"
885
- checksum = "af1c71c1c4cc0920b20d6b0f6572e7682cd07a6a2faec71067a31fa394c586df"
878
+ checksum = "2038684e0058edba0d17302619f62eabce4a8e11c6ac59506996a8d79848851d"
886
879
  dependencies = [
887
880
  "cc",
888
881
  "regex",
889
- "regex-syntax",
890
882
  "serde_json",
891
883
  "streaming-iterator",
892
884
  "tree-sitter-language",
@@ -894,9 +886,9 @@ dependencies = [
894
886
 
895
887
  [[package]]
896
888
  name = "tree-sitter-language"
897
- version = "0.1.7"
889
+ version = "0.1.8"
898
890
  source = "registry+https://github.com/rust-lang/crates.io-index"
899
- checksum = "009994f150cc0cd50ff54917d5bc8bffe8cad10ca10d81c34da2ec421ae61782"
891
+ checksum = "ca0d1bf6fdd806e43ae5198f82f527056d359def39e54e67a0f478ac09dac081"
900
892
 
901
893
  [[package]]
902
894
  name = "tree-sitter-ruby"
@@ -921,9 +913,9 @@ checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
921
913
 
922
914
  [[package]]
923
915
  name = "ureq"
924
- version = "3.4.0"
916
+ version = "3.4.1"
925
917
  source = "registry+https://github.com/rust-lang/crates.io-index"
926
- checksum = "972d7902c8735f2695410b8aed7df6ed12a47394aa1c8d7af49f0497b731a94d"
918
+ checksum = "af5546be8f5378d5414f83733f5c9a2526f4645829edbc1c41790aeef1b38e8b"
927
919
  dependencies = [
928
920
  "base64",
929
921
  "der",
@@ -938,9 +930,9 @@ dependencies = [
938
930
 
939
931
  [[package]]
940
932
  name = "ureq-proto"
941
- version = "0.6.1"
933
+ version = "0.6.2"
942
934
  source = "registry+https://github.com/rust-lang/crates.io-index"
943
- checksum = "da5f78b09e6941e1a0f2e30e695e4b120377b54d5e0aec11b594bb57b3971613"
935
+ checksum = "fabc3e92916c89c95b20eef7b06b00b066bc217ef9ea3a4ac9bf1a7e35261e10"
944
936
  dependencies = [
945
937
  "base64",
946
938
  "http",
data/Cargo.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "sonicop"
3
- version = "26.8.112"
3
+ version = "26.9.100"
4
4
  edition = "2024"
5
5
  rust-version = "1.85"
6
6
  description = "A fast, native RuboCop-compatible Ruby linter and formatter"
@@ -16,7 +16,7 @@ path = "src/main.rs"
16
16
 
17
17
  [dependencies]
18
18
  anyhow = "1.0.104"
19
- blake3 = "1.8.6"
19
+ blake3 = "1.8.7"
20
20
  clap = { version = "4.6.6", features = ["derive", "wrap_help"] }
21
21
  encoding_rs = "0.8.35"
22
22
  fs2 = "0.4.3"
@@ -29,23 +29,23 @@ serde_json = "1.0.151"
29
29
  serde_yaml_ng = "0.10"
30
30
  shell-words = "1.1.1"
31
31
  tempfile = "3.27.0"
32
- tree-sitter = "0.26.11"
32
+ tree-sitter = "0.27.0"
33
33
  tree-sitter-ruby = { git = "https://github.com/owayo/tree-sitter-ruby.git", tag = "v26.8.103" }
34
- ureq = { version = "3.4", default-features = false, features = ["native-tls"] }
34
+ ureq = { version = "3.4.1", default-features = false, features = ["native-tls"] }
35
35
 
36
36
  [dev-dependencies]
37
37
  assert_cmd = "2.2.2"
38
38
 
39
39
  [build-dependencies]
40
- blake3 = "1.8.6"
40
+ blake3 = "1.8.7"
41
41
 
42
42
  [profile.release]
43
43
  lto = "thin"
44
44
  codegen-units = 1
45
45
  strip = true
46
46
 
47
- # `cargo build --profile profiling` keeps the symbols a sampling profiler needs while
48
- # generating exactly the code `--release` does.
47
+ # `cargo build --profile profiling` はサンプリングプロファイラ用のシンボルを残しつつ、
48
+ # `--release` と同じ最適化コードを生成する。
49
49
  [profile.profiling]
50
50
  inherits = "release"
51
51
  debug = 1
data/README.ja.md CHANGED
@@ -153,6 +153,8 @@ sonicop --show-cops
153
153
  `AllCops/DisabledByDefault`、`Include`/`Exclude`、Cop ごとの `Enabled`、`Exclude`、
154
154
  `Severity`、`Safe`、`SafeAutoCorrect` と設定値に対応します。宣言されたプラグイン由来の
155
155
  Cop は「認識済み・未実装」として受理し、Ruby プラグインコード自体は実行しません。
156
+ リモート設定のリクエストには 30 秒のネットワークタイムアウトを設け、応答は 1 件あたり
157
+ 5 MiB に制限します。
156
158
 
157
159
  ```yaml
158
160
  inherit_from: .rubocop_todo.yml
@@ -229,52 +231,63 @@ autocorrect は RuboCop 自身のツリーと Mastodon でバイト単位に一
229
231
  既定の実行はどちらの群にも届きません。)
230
232
  各値は暖機後 2 回の最速値です。
231
233
 
232
- | コーパス | ファイル | RuboCop 並列 | Sonicop 並列 | RuboCop 単一 | Sonicop 単一 |
233
- |---|---:|---:|---:|---:|---:|
234
- | rubocop/rubocop | 1,765 | 12.71 秒 | **4.59 秒** | 42.74 秒 | **13.75 秒** |
235
- | mastodon/mastodon | 3,290 | 29.95 秒 | **6.48 秒** | 37.60 秒 | **15.88 秒** |
236
- | Homebrew/brew | 2,179 | 18.20 秒 | **4.31 秒** | 38.72 秒 | **11.67 秒** |
237
- | rails/rails | 3,551 | 52.55 秒 | **16.88 秒** | 162.55 秒 | **63.97 秒** |
238
- | ruby/ruby | 7,466 | 132.17 秒 | **43.10 秒** | 199.78 秒 | **76.07 秒** |
234
+ | コーパス | ファイル | offense | RuboCop 並列 | Sonicop 並列 | RuboCop 単一 | Sonicop 単一 |
235
+ |---|---:|---:|---:|---:|---:|---:|
236
+ | rubocop/rubocop | 1,780 | 5,826 | 10.85 秒 | **1.53 秒** | 41.44 秒 | **8.96 秒** |
237
+ | mastodon/mastodon | 3,292 | 15,293 | 22.59 秒 | **3.04 秒** | 34.74 秒 | **6.86 秒** |
238
+ | Homebrew/brew | 2,296 | 51,527 | 13.56 秒 | **2.21 秒** | 40.36 秒 | **6.51 秒** |
239
+ | rails/rails | 3,562 | 168,615 | 32.90 秒 | **8.84 秒** | 85.71 秒 | **19.17 秒** |
240
+ | ruby/ruby | 7,477 | 765,975 | 86.89 秒 | **15.59 秒** | 193.59 秒 | **37.98 秒** |
239
241
 
240
- 差は並列で 2.8〜4.6 倍、単一プロセスで 2.4〜3.3 倍と幅があり、1 コーパスでは代表できません。
242
+ 差は並列で 3.7〜7.4 倍、単一プロセスで 4.5〜6.2 倍と幅があり、1 コーパスでは代表できません。
241
243
  **単一プロセスの列を読み、並列は目安として扱ってください。** 同じ 2 つのバイナリを 1 日に
242
244
  3 回測ったところ、単一プロセスの値は毎回 16% 以内に収まったのに対し、RuboCop 自身のツリーでの
243
245
  並列の倍率は、マシンが他に何をしていたかだけで 3.3 倍から 9.2 倍まで動きました。単一プロセスは
244
246
  エンジンを測っていますが、並列はエンジンに加えて「その実行でスケジューリングがそのツリーに
245
247
  どれだけ噛み合ったか」を測っています。
246
248
 
247
- 仕事を省いて速いわけではありません。この同じ 394 Cop について、RuboCop 自身のツリー・
248
- Rails・Mastodon の 3 つで**すべての offense が一致**します(計 188,812 件、どちらの側にも
249
- 残りません)。autocorrect は前者と後者でバイト単位に一致します。
249
+ 仕事を省いて速いわけではありません。この同じ 394 Cop について、表のどのコーパスでも
250
+ **offense の総数が一致**し、RuboCop 自身のツリーと Mastodon ではその 1 件ずつが同じ位置・
251
+ 同じメッセージ・同じ severity です。Rails は 168,615 件のうち 2 件だけ食い違います
252
+ (Sonicop が出す `Style/CaseLikeIf` 1 件と、出さない `Metrics/AbcSize` 1 件)。
253
+ RuboCop 自身のツリーでは 1 件の `correctable` フラグが違います。
254
+ autocorrect は前者と後者でバイト単位に一致します。
250
255
 
251
- 再現時に注意が必要な点が 3 つあります。RuboCop は **`--cache false` と併用すると
256
+ 再現時に注意が必要な点が 4 つあります。RuboCop は **`--cache false` と併用すると
252
257
  `--parallel` を黙って無効化します**。そのためここでの並列実行はキャッシュを有効にしたうえで
253
258
  実行ごとにキャッシュディレクトリを消しており、`--cache false --parallel` で計測すると
254
259
  単一プロセスを測ることになり差が過大に出ます。また RuboCop の既定は単一プロセス、
255
260
  Sonicop は `--no-parallel` を渡さない限り並列です。そして**両方ともキャッシュを空にする**
256
261
  必要があります。Sonicop も既定でキャッシュするため、同じツリーを 2 回目に流すと自分の
257
262
  キャッシュが答えてしまい、エンジンについては何も測れません。どちらにも使い捨ての
258
- キャッシュディレクトリを渡してください。
263
+ キャッシュディレクトリを渡してください。最後に、そのキャッシュディレクトリは**実パス**である
264
+ 必要があります。macOS の `mktemp -d` は `/var/folders/…` を返し、その `/var` は symlink なので
265
+ RuboCop はそこを拒み、キャッシュ無しで走ってしまいます。
259
266
 
260
267
  ```bash
261
268
  # RuboCop(並列・キャッシュは毎回空・既定の全 394 Cop)
262
- rubocop --force-default-config --cache true --cache-root "$(mktemp -d)" \
269
+ root=$(mktemp -d /private/tmp/bench.XXXXXX)
270
+ rubocop --force-default-config --cache true --cache-root "$root" \
263
271
  --no-color --parallel -f quiet
264
272
 
265
273
  # Sonicop(キャッシュは毎回空)
266
- sonicop --force-default-config --cache-root "$(mktemp -d)" --format quiet
274
+ sonicop --force-default-config --cache-root "$root" --format quiet
267
275
  ```
268
276
 
277
+ キャッシュの書き込みもこの数値に含まれており、無料ではありません。索引は全 offense を
278
+ 「見つかった行のテキスト」付きで保持するため、`ruby/ruby` では 336 MB になります。
279
+ 2 回目の実行(キャッシュ命中)は `ruby/ruby` で 1.59 秒、Rails で 0.42 秒です。
280
+
269
281
  測定機は Apple M2(8 コア)、Ruby 4.0.6(YJIT 利用可)、RubyGems 導入の RuboCop 1.89.0。
270
- 1 分平均のロードアベレージは、計測開始時が 4.0、終了時が 3.1 でした。**アイドル状態ではありません**。
271
- RuboCop 自身のツリーだけは後から単独で測り直しています(負荷 3.7 → 4.0)。1 回目はリリース
272
- ビルドの終わりがけに走ってしまい、値が 60% ほど高く出たためです。**負荷の違う 1 行を同じ表に
273
- 並べることはできません**。
274
- 両者を同じ条件で測っているため倍率は保たれますが、秒数そのものは下限ではなく、静かなマシンなら
275
- より速く出ます。コアを奪い合うものが動いていると両者とも膨らみ、その度合いは一致しません。それが
276
- 並列の列があれだけ動く理由です。秒数そのものが重要なときは、他に負荷のない状態で測り、**実行の
277
- 前後でロードアベレージを記録してください** — その情報が無い数値は、別の数値と比べられません。
282
+ 2026-08-31 に、`rubocop_rubocop` 2693129 / `mastodon_mastodon` b59ddc7 / `Homebrew_brew` b42173b /
283
+ `rails_rails` a19f07f / `ruby_ruby` 22e4a75 の各リビジョンに対して測定しました。
284
+ 1 分平均のロードアベレージは各行の測定時点で 4.5〜7.1 で、その大半は RuboCop 自身の並列
285
+ ワーカーです(計測する以上避けられません)。**アイドル状態ではありません。**
286
+ 各コーパスで両者を連続して同じ条件で測っているため倍率は保たれますが、秒数そのものは下限ではなく、
287
+ 静かなマシンならより速く出ます。コアを奪い合うものが動いていると両者とも膨らみ、その度合いは
288
+ 一致しません。それが並列の列があれだけ動く理由です。秒数そのものが重要なときは、他に負荷のない
289
+ 状態で測り、**実行の前後でロードアベレージを記録してください** — その情報が無い数値は、
290
+ 別の数値と比べられません。
278
291
 
279
292
  ## 開発
280
293
 
data/README.md CHANGED
@@ -160,6 +160,8 @@ run. Local and HTTPS `inherit_from`, `inherit_gem`, `inherit_mode`,
160
160
  `AllCops/DisabledByDefault`, `Include`, and `Exclude`, plus per-cop `Enabled`, `Exclude`,
161
161
  `Severity`, `Safe`, `SafeAutoCorrect`, and cop settings are supported. Cops supplied by declared
162
162
  plugins are accepted as recognized-but-unimplemented without executing Ruby plugin code.
163
+ Remote configuration requests use 30-second network timeouts, and each response is limited to
164
+ 5 MiB.
163
165
 
164
166
  ```yaml
165
167
  inherit_from: .rubocop_todo.yml
@@ -240,52 +242,62 @@ once the 159 RuboCop ships as `Enabled: pending` and the 56 it ships as `Enabled
240
242
  aside; a default run reaches neither group on either side.) Times are the fastest of two
241
243
  warmed runs.
242
244
 
243
- | Corpus | Files | RuboCop parallel | Sonicop parallel | RuboCop single | Sonicop single |
244
- |---|---:|---:|---:|---:|---:|
245
- | rubocop/rubocop | 1,765 | 12.71 s | **4.59 s** | 42.74 s | **13.75 s** |
246
- | mastodon/mastodon | 3,290 | 29.95 s | **6.48 s** | 37.60 s | **15.88 s** |
247
- | Homebrew/brew | 2,179 | 18.20 s | **4.31 s** | 38.72 s | **11.67 s** |
248
- | rails/rails | 3,551 | 52.55 s | **16.88 s** | 162.55 s | **63.97 s** |
249
- | ruby/ruby | 7,466 | 132.17 s | **43.10 s** | 199.78 s | **76.07 s** |
245
+ | Corpus | Files | Offenses | RuboCop parallel | Sonicop parallel | RuboCop single | Sonicop single |
246
+ |---|---:|---:|---:|---:|---:|---:|
247
+ | rubocop/rubocop | 1,780 | 5,826 | 10.85 s | **1.53 s** | 41.44 s | **8.96 s** |
248
+ | mastodon/mastodon | 3,292 | 15,293 | 22.59 s | **3.04 s** | 34.74 s | **6.86 s** |
249
+ | Homebrew/brew | 2,296 | 51,527 | 13.56 s | **2.21 s** | 40.36 s | **6.51 s** |
250
+ | rails/rails | 3,562 | 168,615 | 32.90 s | **8.84 s** | 85.71 s | **19.17 s** |
251
+ | ruby/ruby | 7,477 | 765,975 | 86.89 s | **15.59 s** | 193.59 s | **37.98 s** |
250
252
 
251
- The gap is 2.8x to 4.6x in parallel and 2.4x to 3.3x single-process, so no single corpus summarizes
253
+ The gap is 3.7x to 7.4x in parallel and 4.5x to 6.2x single-process, so no single corpus summarizes
252
254
  it. **Read the single-process column and treat the parallel one as indicative.** Measuring the same
253
255
  two binaries three times over a day put the single-process figures within 16% of each other every
254
256
  time, while the parallel ratio on RuboCop's own tree moved between 3.3x and 9.2x purely with what
255
257
  else the machine was doing. Single-process measures the engines; parallel measures the engines plus
256
258
  how well each one's scheduling happens to fit that tree on that run.
257
259
 
258
- The speed is not bought by skipping work: over those same 394 cops the two agree on **every offense**
259
- on RuboCop's own tree, on Rails and on Mastodon — 188,812 offenses with nothing on either side of the
260
- ledger — and autocorrect is byte-identical on the first and the last.
260
+ The speed is not bought by skipping work. Over those same 394 cops the two find the **same number of
261
+ offenses** on every corpus in the table, and on RuboCop's own tree and on Mastodon every one of them
262
+ is at the same position with the same message and severity. Rails, at 168,615 offenses, differs in
263
+ two of them — one `Style/CaseLikeIf` Sonicop reports and one `Metrics/AbcSize` it does not — and
264
+ RuboCop's own tree differs in one offense's `correctable` flag. Autocorrect is byte-identical on the
265
+ first and the last.
261
266
 
262
- Three details matter for reproducing this. RuboCop **silently turns `--parallel` off when combined
267
+ Four details matter for reproducing this. RuboCop **silently turns `--parallel` off when combined
263
268
  with `--cache false`**, so its parallel runs here use a cache directory that is deleted before each
264
269
  run rather than disabled; timing it with `--cache false --parallel` measures a single process and
265
270
  overstates the difference. RuboCop's default is a single process, while Sonicop is parallel unless
266
- `--no-parallel` is passed. And both sides need a **cold** cache: Sonicop caches by default too, so a
267
- second run over the same tree answers from its own cache and measures nothing about the engine.
268
- Give each tool a throwaway cache root.
271
+ `--no-parallel` is passed. Both sides need a **cold** cache: Sonicop caches by default too, so a
272
+ second run over the same tree answers from its own cache and measures nothing about the engine —
273
+ give each tool a throwaway cache root. And the cache root must be a **real path**: macOS `mktemp -d`
274
+ returns `/var/folders/…`, whose `/var` is a symlink, and RuboCop refuses such a location and runs
275
+ with no cache at all.
269
276
 
270
277
  ```bash
271
278
  # RuboCop, parallel, cold cache, its full default set of 394 cops
272
- rubocop --force-default-config --cache true --cache-root "$(mktemp -d)" \
279
+ root=$(mktemp -d /private/tmp/bench.XXXXXX)
280
+ rubocop --force-default-config --cache true --cache-root "$root" \
273
281
  --no-color --parallel -f quiet
274
282
 
275
283
  # Sonicop, cold cache
276
- sonicop --force-default-config --cache-root "$(mktemp -d)" --format quiet
284
+ sonicop --force-default-config --cache-root "$root" --format quiet
277
285
  ```
278
286
 
287
+ Writing the cache is part of these numbers, and it is not free: the index holds every offense with
288
+ the source line it was found on, which is 336 MB over `ruby/ruby`. A second run against a warm cache
289
+ answers in 1.59 s there, and in 0.42 s over Rails.
290
+
279
291
  Machine: Apple M2 (8 cores), Ruby 4.0.6 with YJIT available, RubyGems-installed RuboCop 1.89.0.
280
- The one-minute load average was 4.0 when the run started and 3.1 when it finished — the machine was
281
- in use, not idle. RuboCop's own tree was re-measured on its own afterwards, at load 3.7 rising to 4.0,
282
- because the first pass over it ran while a release build was still finishing and its numbers came out
283
- 60% high; a row measured under a different load cannot sit in the same table as the others. Both tools
284
- ran under the same conditions, so the ratios hold, but the absolute
285
- seconds are not a floor: expect better on a quiet machine. Anything competing for cores inflates
286
- both sides, and not by the same factor on each, which is what makes the parallel column move as much
287
- as it does. If the absolute numbers matter to you, measure on an idle machine and record the load
288
- either side of the run — a figure without that context cannot be compared with another one.
292
+ Measured on 2026-08-31 against the corpora at `rubocop_rubocop` 2693129, `mastodon_mastodon` b59ddc7,
293
+ `Homebrew_brew` b42173b, `rails_rails` a19f07f and `ruby_ruby` 22e4a75. The one-minute load average
294
+ was between 4.5 and 7.1 as each row was taken — most of it RuboCop's own parallel workers, which is
295
+ inherent to measuring them. **The machine was in use, not idle.** Both tools ran back to back under
296
+ the same conditions on each corpus, so the ratios hold, but the absolute seconds are not a floor:
297
+ expect better on a quiet machine. Anything competing for cores inflates both sides, and not by the
298
+ same factor on each, which is what makes the parallel column move as much as it does. If the
299
+ absolute numbers matter to you, measure on an idle machine and record the load either side of the
300
+ run — a figure without that context cannot be compared with another one.
289
301
 
290
302
  ## Development
291
303
 
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Generated from Cargo.toml by `rake version:sync`. Do not edit by hand.
4
4
  module Sonicop
5
- VERSION = '26.8.112'
5
+ VERSION = '26.9.100'
6
6
  end
@@ -8,6 +8,8 @@ use std::time::Duration;
8
8
  use anyhow::{Context, Result, bail};
9
9
  use serde_yaml_ng::{Mapping, Value};
10
10
 
11
+ const MAX_REMOTE_CONFIG_BYTES: u64 = 5 * 1024 * 1024;
12
+
11
13
  /// Configuration files whose inheritance has already been resolved, keyed by canonical path for
12
14
  /// local files and by URL for remote ones.
13
15
  ///
@@ -164,7 +166,8 @@ fn fetch_remote_config(url: &str) -> Result<String> {
164
166
  response
165
167
  .body_mut()
166
168
  .with_config()
167
- .limit(5 * 1024 * 1024)
169
+ // ureq は指定値と同じ長さでも上限超過にするため、論理上限を含む 1 バイト先を渡す。
170
+ .limit(MAX_REMOTE_CONFIG_BYTES + 1)
168
171
  .read_to_string()
169
172
  .with_context(|| format!("failed to read remote configuration: {url}"))
170
173
  }
@@ -459,14 +462,17 @@ fn mode_keys(mode: &Value, name: &str) -> HashSet<String> {
459
462
  mod tests {
460
463
  use std::collections::HashSet;
461
464
  use std::fs;
465
+ use std::io::{Read, Write};
466
+ use std::net::TcpListener;
462
467
  use std::path::Path;
468
+ use std::thread;
463
469
 
464
470
  use serde_yaml_ng::Value;
465
471
  use tempfile::tempdir;
466
472
 
467
473
  use super::{
468
- InheritMode, PARSED_CONFIG_COUNT, deep_merge, join_remote_url, load_with_inheritance,
469
- merge_config, merge_inherited_config,
474
+ InheritMode, MAX_REMOTE_CONFIG_BYTES, PARSED_CONFIG_COUNT, deep_merge, fetch_remote_config,
475
+ join_remote_url, load_with_inheritance, merge_config, merge_inherited_config,
470
476
  };
471
477
  use crate::config::Config;
472
478
 
@@ -483,6 +489,24 @@ mod tests {
483
489
  load_with_inheritance(path, &mut HashSet::new())
484
490
  }
485
491
 
492
+ fn serve_once(body: Vec<u8>) -> (String, thread::JoinHandle<()>) {
493
+ let listener = TcpListener::bind(("127.0.0.1", 0)).unwrap();
494
+ let address = listener.local_addr().unwrap();
495
+ let server = thread::spawn(move || {
496
+ let (mut stream, _) = listener.accept().unwrap();
497
+ let mut request = [0; 1024];
498
+ assert_ne!(stream.read(&mut request).unwrap(), 0);
499
+ write!(
500
+ stream,
501
+ "HTTP/1.1 200 OK\r\nContent-Length: {}\r\nConnection: close\r\n\r\n",
502
+ body.len()
503
+ )
504
+ .unwrap();
505
+ stream.write_all(&body).unwrap();
506
+ });
507
+ (format!("http://{address}/config.yml"), server)
508
+ }
509
+
486
510
  fn cop_exclude(merged: &Value, cop: &str) -> Value {
487
511
  merged
488
512
  .as_mapping()
@@ -577,6 +601,24 @@ mod tests {
577
601
  assert!(join_remote_url("no-directory", "shared.yml").is_err());
578
602
  }
579
603
 
604
+ #[test]
605
+ fn remote_configuration_enforces_the_response_size_limit() {
606
+ let limit = MAX_REMOTE_CONFIG_BYTES as usize;
607
+
608
+ let (url, server) = serve_once(vec![b'a'; limit]);
609
+ let accepted = fetch_remote_config(&url).unwrap();
610
+ server.join().unwrap();
611
+ assert_eq!(accepted.len(), limit);
612
+
613
+ let (url, server) = serve_once(vec![b'a'; limit + 1]);
614
+ let error = fetch_remote_config(&url).unwrap_err().to_string();
615
+ server.join().unwrap();
616
+ assert!(
617
+ error.starts_with("failed to read remote configuration:"),
618
+ "unexpected error: {error}"
619
+ );
620
+ }
621
+
580
622
  #[test]
581
623
  fn merges_configurations_without_losing_untouched_keys() {
582
624
  let merged = merge_config(
data/src/engine.rs CHANGED
@@ -10,7 +10,6 @@ use ignore::WalkBuilder;
10
10
  use rayon::prelude::*;
11
11
  use serde::{Deserialize, Serialize};
12
12
  use tempfile::NamedTempFile;
13
- use tree_sitter::Parser;
14
13
 
15
14
  use crate::config::{Config, ConfigStore};
16
15
  use crate::cop_name::selector_matches;
@@ -554,7 +553,16 @@ fn persist_cache_index(path: &Path, index: &CacheIndex) -> bool {
554
553
  let Ok(mut temporary) = NamedTempFile::new_in(parent) else {
555
554
  return false;
556
555
  };
557
- if serde_json::to_writer(temporary.as_file_mut(), index).is_err()
556
+ // **Buffered.** `serde_json::to_writer` hands the writer each token as it produces it, so an
557
+ // unbuffered `File` turns one index into millions of `write` calls. The index holds every
558
+ // offense of every file with the source line it was found on, which is 336 MB over `ruby/ruby`:
559
+ // writing it a token at a time cost 115 seconds of a 135-second run, nearly all of it blocked
560
+ // in the kernel rather than serializing.
561
+ let written = {
562
+ let mut writer = std::io::BufWriter::with_capacity(1 << 20, temporary.as_file_mut());
563
+ serde_json::to_writer(&mut writer, index).is_ok() && writer.flush().is_ok()
564
+ };
565
+ if !written
558
566
  || temporary.as_file_mut().flush().is_err()
559
567
  || temporary.as_file().sync_all().is_err()
560
568
  {
@@ -992,12 +1000,8 @@ fn inspect_planned(
992
1000
  let length_as_read = text.len();
993
1001
  let text = crate::nul_bytes::as_ruby_reads_it(&text).unwrap_or(text);
994
1002
  let source = SourceFile::new(path, text).read_as_long_as(length_as_read);
995
- let mut parser = Parser::new();
996
- parser
997
- .set_language(&tree_sitter_ruby::LANGUAGE.into())
998
- .context("failed to initialize the Ruby parser")?;
999
1003
  let tree = crate::profile::phase(crate::profile::Phase::Parse, || {
1000
- parser.parse(source.text(), None)
1004
+ crate::parser::parse(source.text())
1001
1005
  })
1002
1006
  .context("Ruby parser returned no syntax tree")?;
1003
1007
  let ast = crate::profile::phase(crate::profile::Phase::Index, || {