sonicop 26.8.106 → 26.8.108

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 (126) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +3 -3
  3. data/Cargo.toml +2 -2
  4. data/lib/sonicop/version.rb +1 -1
  5. data/src/cli.rs +29 -2
  6. data/src/directives.rs +2 -2
  7. data/src/engine.rs +444 -71
  8. data/src/magic_comment.rs +15 -9
  9. data/src/ruby_version.rs +1 -1
  10. data/src/rules/bundler/gem_comment.rs +3 -3
  11. data/src/rules/layout/block_end_newline.rs +14 -6
  12. data/src/rules/layout/closing_parenthesis_indentation.rs +7 -0
  13. data/src/rules/layout/condition_position.rs +6 -4
  14. data/src/rules/layout/element_line_breaks.rs +1 -1
  15. data/src/rules/layout/empty_line_after_magic_comment.rs +11 -1
  16. data/src/rules/layout/empty_line_after_multiline_condition.rs +2 -13
  17. data/src/rules/layout/empty_lines_after_module_inclusion.rs +2 -12
  18. data/src/rules/layout/empty_lines_around_arguments.rs +7 -6
  19. data/src/rules/layout/first_array_element_indentation.rs +17 -1
  20. data/src/rules/layout/first_hash_element_indentation.rs +7 -4
  21. data/src/rules/layout/indentation_width.rs +61 -20
  22. data/src/rules/layout/line_length.rs +7 -12
  23. data/src/rules/layout/multiline_brace.rs +12 -21
  24. data/src/rules/layout/multiline_method_call_brace_layout.rs +3 -6
  25. data/src/rules/layout/space_around_block_parameters.rs +45 -14
  26. data/src/rules/layout/space_around_operators.rs +9 -18
  27. data/src/rules/layout/space_inside_array_percent_literal.rs +4 -2
  28. data/src/rules/layout/space_inside_block_braces.rs +14 -27
  29. data/src/rules/layout/trailing_empty_lines.rs +19 -1
  30. data/src/rules/lint/ambiguous_assignment.rs +1 -1
  31. data/src/rules/lint/comments_help.rs +39 -0
  32. data/src/rules/lint/constant_reassignment.rs +4 -1
  33. data/src/rules/lint/cop_directives.rs +75 -26
  34. data/src/rules/lint/data_define_override.rs +5 -0
  35. data/src/rules/lint/duplicate_methods.rs +10 -0
  36. data/src/rules/lint/empty_conditional_body.rs +23 -0
  37. data/src/rules/lint/empty_in_pattern.rs +2 -25
  38. data/src/rules/lint/empty_when.rs +2 -27
  39. data/src/rules/lint/hash_new_with_keyword_arguments_as_default.rs +5 -0
  40. data/src/rules/lint/incompatible_io_select_with_fiber_scheduler.rs +5 -0
  41. data/src/rules/lint/inherit_exception.rs +5 -0
  42. data/src/rules/lint/interpolation_check.rs +45 -0
  43. data/src/rules/lint/missing_super.rs +1 -15
  44. data/src/rules/lint/mod.rs +2 -0
  45. data/src/rules/lint/non_atomic_file_operation.rs +5 -0
  46. data/src/rules/lint/ranges.rs +8 -6
  47. data/src/rules/lint/redundant_cop_enable_directive.rs +69 -75
  48. data/src/rules/lint/safe_navigation_consistency.rs +14 -0
  49. data/src/rules/lint/shared_mutable_default.rs +5 -0
  50. data/src/rules/lint/to_enum_arguments.rs +5 -0
  51. data/src/rules/lint/unused_arg_corrector.rs +55 -0
  52. data/src/rules/lint/unused_block_argument.rs +3 -45
  53. data/src/rules/lint/unused_method_argument.rs +4 -61
  54. data/src/rules/lint/useless_assignment.rs +2 -1
  55. data/src/rules/lint/useless_times.rs +24 -4
  56. data/src/rules/lint/variable_force.rs +1 -45
  57. data/src/rules/lint/void.rs +9 -7
  58. data/src/rules/metrics/complexity.rs +2 -1
  59. data/src/rules/metrics/locals.rs +1 -46
  60. data/src/rules/mod.rs +19 -16
  61. data/src/rules/naming/constant_name.rs +3 -2
  62. data/src/rules/naming/file_name.rs +1 -1
  63. data/src/rules/naming/rescued_exceptions_variable_name.rs +2 -1
  64. data/src/rules/naming/support.rs +3 -37
  65. data/src/rules/send_node.rs +12 -0
  66. data/src/rules/single_line.rs +1 -1
  67. data/src/rules/style/attr.rs +22 -12
  68. data/src/rules/style/auto_resource_cleanup.rs +6 -0
  69. data/src/rules/style/block_delimiters.rs +34 -16
  70. data/src/rules/style/class_vars.rs +6 -1
  71. data/src/rules/style/collection_compact.rs +7 -1
  72. data/src/rules/style/collection_querying.rs +15 -6
  73. data/src/rules/style/commented_keyword.rs +5 -5
  74. data/src/rules/style/comments.rs +4 -3
  75. data/src/rules/style/copyright.rs +1 -1
  76. data/src/rules/style/dir.rs +6 -0
  77. data/src/rules/style/document_dynamic_eval_definition.rs +6 -1
  78. data/src/rules/style/documentation.rs +3 -3
  79. data/src/rules/style/empty_literal.rs +6 -1
  80. data/src/rules/style/env_home.rs +6 -0
  81. data/src/rules/style/expand_path_arguments.rs +6 -0
  82. data/src/rules/style/frozen_string_literal_comment.rs +1 -1
  83. data/src/rules/style/hash_syntax.rs +80 -18
  84. data/src/rules/style/hash_transform.rs +38 -18
  85. data/src/rules/style/identical_conditional_branches.rs +56 -18
  86. data/src/rules/style/if_inside_else.rs +4 -10
  87. data/src/rules/style/if_unless_modifier.rs +11 -31
  88. data/src/rules/style/in_pattern_then.rs +9 -0
  89. data/src/rules/style/keyword_parameters_order.rs +9 -22
  90. data/src/rules/style/lambda.rs +2 -4
  91. data/src/rules/style/line_length_help.rs +6 -10
  92. data/src/rules/style/magic_comment_format.rs +1 -1
  93. data/src/rules/style/map_compact_with_conditional_block.rs +36 -12
  94. data/src/rules/style/mod.rs +1 -0
  95. data/src/rules/style/multiline_method_signature.rs +1 -13
  96. data/src/rules/style/negated_if_else_condition.rs +22 -19
  97. data/src/rules/style/nested_parenthesized_calls.rs +30 -4
  98. data/src/rules/style/nested_ternary_operator.rs +13 -11
  99. data/src/rules/style/nil_lambda.rs +1 -12
  100. data/src/rules/style/numeric_literals.rs +3 -3
  101. data/src/rules/style/one_line_conditional.rs +15 -3
  102. data/src/rules/style/or_assignment.rs +68 -44
  103. data/src/rules/style/parallel_assignment.rs +113 -28
  104. data/src/rules/style/parens.rs +107 -25
  105. data/src/rules/style/partition_instead_of_double_select.rs +2 -12
  106. data/src/rules/style/percent_array.rs +2 -6
  107. data/src/rules/style/random_with_offset.rs +6 -0
  108. data/src/rules/style/ranges.rs +4 -22
  109. data/src/rules/style/redundant_array_constructor.rs +6 -0
  110. data/src/rules/style/redundant_begin.rs +9 -16
  111. data/src/rules/style/redundant_line_continuation.rs +23 -4
  112. data/src/rules/style/redundant_parentheses.rs +62 -28
  113. data/src/rules/style/redundant_regexp_constructor.rs +6 -0
  114. data/src/rules/style/rescue_modifier.rs +32 -7
  115. data/src/rules/style/safe_navigation.rs +9 -9
  116. data/src/rules/style/semicolon.rs +38 -2
  117. data/src/rules/style/signal_exception.rs +6 -1
  118. data/src/rules/style/sole_nested_conditional.rs +13 -2
  119. data/src/rules/style/statement_modifier.rs +31 -0
  120. data/src/rules/style/struct_inheritance.rs +3 -12
  121. data/src/rules/style/trailing_underscore_variable.rs +12 -0
  122. data/src/rules/style/while_until_modifier.rs +3 -23
  123. data/src/rules/style/word_array.rs +16 -1
  124. data/src/rules/support.rs +298 -19
  125. data/src/rules/visibility.rs +23 -2
  126. metadata +4 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c90ed3a9d03214ba6922d2aecd35c70b28e09791c870f06c22848ef05b336054
4
- data.tar.gz: 0557036a886b2023e5151d8b18b1df8bdd66725faf957d19013412a0bc62c6ef
3
+ metadata.gz: bbee17a19e72bf5b5dad03303c42be9905e5dfeef68faf8f1155b5f9910f3fac
4
+ data.tar.gz: d756a00e368f91dcf8c3ca4d2e0e9df85c0315638d1aaa0d653e6cfbb4d68648
5
5
  SHA512:
6
- metadata.gz: 63191904f82e06d89200c5b81a22a9ad6a4ebcbf07ed86039966605a2d87225d7984a2dfd7a3b0a7b38ca54aaebc1b36518fdb1eeb5dead16318168e3441d692
7
- data.tar.gz: deb43652b8dfd0c2c9fac7ed27a1a33fb1097e76bd2d455851ba04d30d2fc6751025fadfdc4012d06f6a45140a983a5686b7bdfc3e5436e5d9ea0e238da26ddd
6
+ metadata.gz: cdbfc78cb9c5f22948032627bd4dbcb6f28f9b044c69d2ee139cb16b598e928113e64d3d0267505d58160b000a9a66193456cd6943fb1f95b86f8c7d1699061d
7
+ data.tar.gz: 6d7cf795e8e02782a81c4f16a9e2805cbd93dc88daf25d175944aefeb3b1a06af405b64c1c720129bf8945a8eee7873882968d5649efa43670d0029094e991ae
data/Cargo.lock CHANGED
@@ -742,7 +742,7 @@ checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
742
742
 
743
743
  [[package]]
744
744
  name = "sonicop"
745
- version = "26.8.106"
745
+ version = "26.8.108"
746
746
  dependencies = [
747
747
  "anyhow",
748
748
  "assert_cmd",
@@ -847,8 +847,8 @@ checksum = "009994f150cc0cd50ff54917d5bc8bffe8cad10ca10d81c34da2ec421ae61782"
847
847
 
848
848
  [[package]]
849
849
  name = "tree-sitter-ruby"
850
- version = "26.8.100"
851
- source = "git+https://github.com/owayo/tree-sitter-ruby.git?rev=6408d8b7adff44f0b346517b56071460efd323b6#6408d8b7adff44f0b346517b56071460efd323b6"
850
+ version = "26.8.101"
851
+ source = "git+https://github.com/owayo/tree-sitter-ruby.git?rev=f1a19bb27ba64300d1032b813c51437a5a76ea33#f1a19bb27ba64300d1032b813c51437a5a76ea33"
852
852
  dependencies = [
853
853
  "cc",
854
854
  "tree-sitter-language",
data/Cargo.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "sonicop"
3
- version = "26.8.106"
3
+ version = "26.8.108"
4
4
  edition = "2024"
5
5
  rust-version = "1.85"
6
6
  description = "A fast, native RuboCop-compatible Ruby linter and formatter"
@@ -28,7 +28,7 @@ serde_yaml_ng = "0.10"
28
28
  shell-words = "1.1.1"
29
29
  tempfile = "3.27.0"
30
30
  tree-sitter = "0.26.11"
31
- tree-sitter-ruby = { git = "https://github.com/owayo/tree-sitter-ruby.git", rev = "6408d8b7adff44f0b346517b56071460efd323b6" }
31
+ tree-sitter-ruby = { git = "https://github.com/owayo/tree-sitter-ruby.git", rev = "f1a19bb27ba64300d1032b813c51437a5a76ea33" }
32
32
  ureq = { version = "3.4", default-features = false, features = ["native-tls"] }
33
33
 
34
34
  [dev-dependencies]
@@ -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.106'
5
+ VERSION = '26.8.108'
6
6
  end
data/src/cli.rs CHANGED
@@ -11,8 +11,8 @@ use crate::config::{Config, ConfigStore};
11
11
  use crate::cop_name::{self, selector_matches};
12
12
  use crate::diagnostic::{FileReport, Offense, Severity};
13
13
  use crate::engine::{
14
- CorrectMode, Selection, correct_file, discover_targets_with_store, inspect_files_with_store,
15
- inspect_source, is_mandatory_cop, offense_count, write_corrected,
14
+ CorrectMode, NO_SYNTAX_GUARD, Selection, correct_file, discover_targets_with_store,
15
+ inspect_files_with_store, inspect_source, is_mandatory_cop, offense_count, write_corrected,
16
16
  };
17
17
  use crate::formatter::{
18
18
  Format, FormatOptions, offenses_by_cop, render, smart_path, yaml_single_quoted,
@@ -359,6 +359,7 @@ fn try_run(cli: Cli, outputs: &[Option<PathBuf>]) -> Result<i32> {
359
359
  validate_compatibility(&cli)?;
360
360
  let fail_level = FailLevel::parse(&cli.fail_level)?;
361
361
  print_deprecation_warnings(&cli);
362
+ warn_if_syntax_guard_disabled();
362
363
 
363
364
  let cwd = std::env::current_dir().context("failed to determine current directory")?;
364
365
  if cli.init {
@@ -410,6 +411,9 @@ fn try_run(cli: Cli, outputs: &[Option<PathBuf>]) -> Result<i32> {
410
411
  ignore_disable_comments: cli.ignore_disable_comments,
411
412
  display_suppressed: cli.display_suppressed,
412
413
  correcting: cli.correct_mode() != CorrectMode::None,
414
+ // **No flag turns this on from the command line.** The guard is switched off for tests
415
+ // only, and even then per case; a run reaches the environment variable or nothing.
416
+ skip_syntax_guard: false,
413
417
  };
414
418
  let correct_mode = cli.correct_mode();
415
419
  if !cli.list_target_files {
@@ -489,6 +493,13 @@ fn try_run(cli: Cli, outputs: &[Option<PathBuf>]) -> Result<i32> {
489
493
  eprintln!("{message}");
490
494
  run_errors += 1;
491
495
  }
496
+ // Not an offense: the file on disk parses, so a reader told to look for a syntax error
497
+ // would find none. It is an autocorrect failure, and it has to reach the exit code --
498
+ // a `-A` run that silently declined to correct must not look like a clean one to CI.
499
+ if let Some(message) = outcome.rollback {
500
+ eprintln!("{message}");
501
+ run_errors += 1;
502
+ }
492
503
  if outcome.rewritten {
493
504
  if cli.stdin.is_some() {
494
505
  stdin_corrected = Some(outcome.text);
@@ -609,6 +620,22 @@ fn validate_compatibility(cli: &Cli) -> Result<()> {
609
620
  Ok(())
610
621
  }
611
622
 
623
+ /// Says out loud that the guard against writing unparsable corrections has been switched off.
624
+ ///
625
+ /// The switch exists so the guard's error rate can be measured -- with it on, the text needed to
626
+ /// measure it never reaches disk. **A measurement hatch must not be a silent one:** left set in a
627
+ /// shell profile or a CI job it turns a refusal to write into a destructive write, and nothing
628
+ /// else in the output would say so.
629
+ fn warn_if_syntax_guard_disabled() {
630
+ if std::env::var_os(NO_SYNTAX_GUARD).is_some() {
631
+ eprintln!(
632
+ "Sonicop: {} is set. The guard against writing corrections that do not parse is off, \
633
+ so autocorrection will overwrite files even when the result is a syntax error.",
634
+ NO_SYNTAX_GUARD
635
+ );
636
+ }
637
+ }
638
+
612
639
  fn print_deprecation_warnings(cli: &Cli) {
613
640
  if cli.deprecated_auto_correct {
614
641
  eprintln!("--auto-correct is deprecated; use --autocorrect instead.");
data/src/directives.rs CHANGED
@@ -334,7 +334,7 @@ fn cop_list(arguments: &str) -> Vec<String> {
334
334
 
335
335
  /// The length of the cop name `text` starts with, following `COP_NAME_PATTERN`: one or more
336
336
  /// `[A-Za-z]\w+` segments separated by slashes.
337
- fn cop_name_length(text: &str) -> Option<usize> {
337
+ pub(crate) fn cop_name_length(text: &str) -> Option<usize> {
338
338
  let bytes = text.as_bytes();
339
339
  let mut index = 0;
340
340
  loop {
@@ -619,7 +619,7 @@ fn commented_out(prefix: &str) -> bool {
619
619
  prefix.starts_with('#')
620
620
  && prefix[1..]
621
621
  .bytes()
622
- .all(|byte| matches!(byte, b' ' | b'\t' | b'\r' | b'\n' | 0x0b | 0x0c))
622
+ .all(crate::rules::support::is_ruby_space)
623
623
  }
624
624
 
625
625
  /// A `# rubocop:` comment, parsed the way `RuboCop::DirectiveComment` parses one.