sonicop 26.8.101

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 (72) hide show
  1. checksums.yaml +7 -0
  2. data/CONFORMANCE.md +109 -0
  3. data/Cargo.lock +975 -0
  4. data/Cargo.toml +40 -0
  5. data/LICENSE +21 -0
  6. data/NOTICE +7 -0
  7. data/README.ja.md +161 -0
  8. data/README.md +173 -0
  9. data/config/default.yml +6305 -0
  10. data/exe/sonicop +7 -0
  11. data/ext/sonicop/extconf.rb +38 -0
  12. data/lib/sonicop/runner.rb +67 -0
  13. data/lib/sonicop/version.rb +6 -0
  14. data/lib/sonicop.rb +8 -0
  15. data/licenses/RUBOCOP.txt +20 -0
  16. data/licenses/TREE_SITTER_RUBY.txt +21 -0
  17. data/src/cli.rs +940 -0
  18. data/src/config/inheritance.rs +332 -0
  19. data/src/config/loader.rs +117 -0
  20. data/src/config/mod.rs +461 -0
  21. data/src/config/paths.rs +436 -0
  22. data/src/config/plugin.rs +247 -0
  23. data/src/config/store.rs +141 -0
  24. data/src/cop_name.rs +71 -0
  25. data/src/diagnostic.rs +205 -0
  26. data/src/directives.rs +305 -0
  27. data/src/engine.rs +734 -0
  28. data/src/formatter.rs +684 -0
  29. data/src/lib.rs +42 -0
  30. data/src/main.rs +3 -0
  31. data/src/ruby_version.rs +393 -0
  32. data/src/rules/layout/empty_line_after_magic_comment.rs +49 -0
  33. data/src/rules/layout/end_of_line.rs +35 -0
  34. data/src/rules/layout/line_length.rs +167 -0
  35. data/src/rules/layout/mod.rs +13 -0
  36. data/src/rules/layout/space_after_comma.rs +32 -0
  37. data/src/rules/layout/space_around_operators.rs +104 -0
  38. data/src/rules/layout/space_inside_parens.rs +100 -0
  39. data/src/rules/layout/support.rs +23 -0
  40. data/src/rules/layout/trailing_empty_lines.rs +38 -0
  41. data/src/rules/layout/trailing_whitespace.rs +26 -0
  42. data/src/rules/lint/duplicate_methods.rs +72 -0
  43. data/src/rules/lint/mod.rs +7 -0
  44. data/src/rules/lint/syntax.rs +200 -0
  45. data/src/rules/lint/unused_block_argument.rs +74 -0
  46. data/src/rules/lint/useless_assignment.rs +104 -0
  47. data/src/rules/metrics/block_length.rs +39 -0
  48. data/src/rules/metrics/class_length.rs +34 -0
  49. data/src/rules/metrics/method_length.rs +10 -0
  50. data/src/rules/metrics/mod.rs +10 -0
  51. data/src/rules/metrics/module_length.rs +17 -0
  52. data/src/rules/metrics/parameter_lists.rs +21 -0
  53. data/src/rules/metrics/support.rs +105 -0
  54. data/src/rules/mod.rs +380 -0
  55. data/src/rules/naming/ascii_identifiers.rs +17 -0
  56. data/src/rules/naming/constant_name.rs +49 -0
  57. data/src/rules/naming/method_name.rs +51 -0
  58. data/src/rules/naming/mod.rs +9 -0
  59. data/src/rules/naming/support.rs +22 -0
  60. data/src/rules/naming/variable_name.rs +50 -0
  61. data/src/rules/security/eval.rs +170 -0
  62. data/src/rules/security/mod.rs +6 -0
  63. data/src/rules/style/frozen_string_literal_comment.rs +56 -0
  64. data/src/rules/style/hash_syntax.rs +63 -0
  65. data/src/rules/style/mod.rs +9 -0
  66. data/src/rules/style/numeric_literals.rs +59 -0
  67. data/src/rules/style/redundant_return.rs +143 -0
  68. data/src/rules/style/semicolon.rs +48 -0
  69. data/src/rules/style/string_literals.rs +74 -0
  70. data/src/rules/support.rs +31 -0
  71. data/src/source.rs +118 -0
  72. metadata +117 -0
data/Cargo.toml ADDED
@@ -0,0 +1,40 @@
1
+ [package]
2
+ name = "sonicop"
3
+ version = "26.8.101"
4
+ edition = "2024"
5
+ rust-version = "1.85"
6
+ description = "A fast, native RuboCop-compatible Ruby linter and formatter"
7
+ license = "MIT"
8
+ repository = "https://github.com/owayo/sonicop"
9
+ readme = "README.md"
10
+ keywords = ["ruby", "rubocop", "linter", "formatter"]
11
+ categories = ["command-line-utilities", "development-tools"]
12
+
13
+ [[bin]]
14
+ name = "sonicop"
15
+ path = "src/main.rs"
16
+
17
+ [dependencies]
18
+ anyhow = "1.0.104"
19
+ clap = { version = "4.6.4", features = ["derive", "wrap_help"] }
20
+ globset = "0.4.19"
21
+ ignore = "0.4.31"
22
+ rayon = "1.12.0"
23
+ regex = "1.13.1"
24
+ serde = { version = "1.0.229", features = ["derive"] }
25
+ serde_json = "1.0.151"
26
+ serde_yaml_ng = "0.10"
27
+ shell-words = "1.1.1"
28
+ tempfile = "3.27.0"
29
+ tree-sitter = "0.26.11"
30
+ tree-sitter-ruby = { git = "https://github.com/owayo/tree-sitter-ruby.git", rev = "88a64c6c37c4c23d8d4d804c4ef9c4eca3c88b96" }
31
+ unicode-width = "0.2.2"
32
+ ureq = { version = "3.4", default-features = false, features = ["native-tls"] }
33
+
34
+ [dev-dependencies]
35
+ assert_cmd = "2.2.2"
36
+
37
+ [profile.release]
38
+ lto = "thin"
39
+ codegen-units = 1
40
+ strip = true
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yohei
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/NOTICE ADDED
@@ -0,0 +1,7 @@
1
+ Sonicop includes and adapts configuration data from RuboCop 1.89.0.
2
+ RuboCop is Copyright (c) 2012-26 Bozhidar Batsov and contributors,
3
+ licensed under the MIT License. See licenses/RUBOCOP.txt.
4
+
5
+ Sonicop links to owayo/tree-sitter-ruby, derived from tree-sitter-ruby.
6
+ tree-sitter-ruby is Copyright (c) 2016 Rob Rix and contributors,
7
+ licensed under the MIT License. See licenses/TREE_SITTER_RUBY.txt.
data/README.ja.md ADDED
@@ -0,0 +1,161 @@
1
+ <h1 align="center">
2
+ <img src="docs/images/sonicop_logo_header.png" width="600" alt="Sonicop">
3
+ </h1>
4
+
5
+ <p align="center">
6
+ <strong>Rust で実装した高速なネイティブ RuboCop 互換 Ruby リンター/フォーマッター。</strong>
7
+ </p>
8
+
9
+ <p align="center">
10
+ <a href="https://github.com/owayo/sonicop/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/owayo/sonicop/actions/workflows/ci.yml/badge.svg?branch=main"></a>
11
+ <a href="https://rubygems.org/gems/sonicop"><img alt="Gem Version" src="https://img.shields.io/gem/v/sonicop"></a>
12
+ <a href="LICENSE"><img alt="License" src="https://img.shields.io/github/license/owayo/sonicop"></a>
13
+ </p>
14
+
15
+ <p align="center">
16
+ <a href="README.md">English</a> |
17
+ <a href="README.ja.md">日本語</a>
18
+ </p>
19
+
20
+ ---
21
+
22
+ ## 概要
23
+
24
+ Sonicop は、Ruby プロセスを起動せずに動作する高速な Rust 製 Ruby リンター/フォーマッターです。
25
+ 既存の `.rubocop.yml` をそのまま利用でき、サブディレクトリごとの設定、設定の継承、対象ファイルの
26
+ Include/Exclude、severity、自動修正設定にも対応しています。
27
+
28
+ 最新の Ruby 構文へ追従する
29
+ [owayo/tree-sitter-ruby](https://github.com/owayo/tree-sitter-ruby) を使い、ファイルを並列に検査して
30
+ 修正をアトミックに適用します。RuboCop 1.89 互換の CLI と JSON 出力により、既存のエディタや
31
+ CI へ最小限の変更で導入できます。
32
+
33
+ ## 主な機能
34
+
35
+ Layout、Lint、Metrics、Naming、Security、Style の各部門の Cop を実装しています。
36
+ 実装済みの Cop はリリースごとに増えるため、一覧はバイナリ自身が正本です。
37
+
38
+ ```bash
39
+ # 認識済み Cop と実装状況の一覧
40
+ sonicop --show-cops
41
+ ```
42
+
43
+ RuboCop 1.89 の全 609 Cop を同梱設定として認識します。実装済み Cop は検査を実行し、
44
+ 認識済みで未実装の Cop は既存設定を壊さず `--debug` で一覧表示します。本家にも存在しない
45
+ Cop 名だけをエラーにし、必要なら `--ignore-unrecognized-cops` で続行できます。
46
+
47
+ ## インストール
48
+
49
+ ```bash
50
+ gem install sonicop
51
+ ```
52
+
53
+ Linux、macOS、Windows 向けの platform gem にはネイティブ実行ファイルが含まれます。
54
+ 対応する platform gem がない環境では、source gem がインストール時に Cargo でビルドします。
55
+
56
+ 最新版のソースから直接インストールすることもできます。
57
+
58
+ ```bash
59
+ cargo install --git https://github.com/owayo/sonicop
60
+ ```
61
+
62
+ ## 使い方
63
+
64
+ ```bash
65
+ # 現在のプロジェクトを検査
66
+ sonicop
67
+
68
+ # Cop/部門を選択
69
+ sonicop --only Layout,Style/StringLiterals app spec
70
+
71
+ # 安全な自動修正/全自動修正
72
+ sonicop -a
73
+ sonicop -A
74
+
75
+ # RuboCop 互換形状の JSON
76
+ sonicop --format json
77
+
78
+ # 認識済み Cop と実装状況
79
+ sonicop --show-cops
80
+ ```
81
+
82
+ 主な互換オプションは `-l`、`-x`、`--only`、`--except`、`-s/--stdin`、
83
+ `-P/--parallel`、`-f/--format`、`-a/--autocorrect`、`-A/--autocorrect-all`、
84
+ `-L/--list-target-files`、`-c/--config`、`-v/--version`、`-V/--verbose-version` です。
85
+
86
+ ### 設定
87
+
88
+ 対象ファイルごとに `.rubocop.yml` を解決するため、1 回の実行でもサブディレクトリ設定が
89
+ 適用されます。ローカル/HTTPS の `inherit_from`、`inherit_gem`、`inherit_mode`、
90
+ `AllCops/DisabledByDefault`、`Include`/`Exclude`、Cop ごとの `Enabled`、`Exclude`、
91
+ `Severity`、`Safe`、`SafeAutoCorrect` と設定値に対応します。宣言されたプラグイン由来の
92
+ Cop は「認識済み・未実装」として受理し、Ruby プラグインコード自体は実行しません。
93
+
94
+ ```yaml
95
+ inherit_from: .rubocop_todo.yml
96
+
97
+ Layout/LineLength:
98
+ Max: 100
99
+
100
+ Style/StringLiterals:
101
+ EnforcedStyle: single_quotes
102
+ ```
103
+
104
+ 既存コマンドとの互換性を保つため、server/LSP/MCP、plugin、cache 系の引数も受理します。
105
+ 未対応の機能を要求する引数は互換 no-op として stderr に明示します。現在、サーバートランスポート、
106
+ Ruby プラグイン実行、キャッシュ再利用、カスタム Cop、実装済み以外の Cop は実行しません。
107
+
108
+ ### 適合性
109
+
110
+ 実装済み Cop は、正規化した JSON offense を使って RuboCop 1.89 との一致を検証済みです。
111
+ 本家の全 1,759 ファイルを本家既定設定で検査した現在のスナップショットは、参照 4,052 件中
112
+ 4,052 件すべての位置が一致(**recall 100%**)し、**誤検出とメタデータ差もともに 0 件**です。コマンド、比較範囲、測定結果は
113
+ [CONFORMANCE.md](CONFORMANCE.md) にまとめています。Rails では Ruby 対象 3,453 ファイルと
114
+ ルート/`guides/` の有効 Cop 一覧が完全一致し、全体の誤検出は 0 件です。Active Record
115
+ 402 ファイルの無キャッシュ実行は本家比で約 12.5 倍高速でした。
116
+
117
+ ## 開発
118
+
119
+ 入口は `make` に一本化しています。`make help` で全ターゲットを確認できます。gem 配布の
120
+ タスクは Rakefile 側にあり、`make` から呼び出します。
121
+
122
+ ```bash
123
+ make build # デバッグビルド
124
+ make check # fmt、clippy、Rust テスト、Ruby ラッパーテスト、バージョン整合
125
+ make gem # source gem
126
+ ```
127
+
128
+ ### Cop の追加
129
+
130
+ Cop は `src/rules/<部門>/<cop>.rs` の 1 ファイルで、公開するのは `check(context, offenses)` の
131
+ 1 関数だけです。登録は部門の `mod.rs` に 1 行を足します。
132
+
133
+ ```rust
134
+ department_rules! {
135
+ "Layout";
136
+ line_length => ("LineLength", Convention),
137
+ }
138
+ ```
139
+
140
+ Cop 名と既定 severity を書くのはこの 1 行だけです。Cop 本体では名前は暗黙で、
141
+ `context.setting("Max")` が `Layout/LineLength: Max` を読み、`context.offense(message, range)` が
142
+ その Cop の名前と設定済み severity で報告します。Cop が自分の名前を 2 度書ける設計では、
143
+ レジストリと食い違っても型検査では捕まりません。
144
+
145
+ 全ノード走査より `context.nodes_of("kind")` を優先してください。Cop は全ファイルに対して走るため、
146
+ Cop ごとの全走査はファイル規模ではなく Cop 数に比例して重くなります。
147
+
148
+ バージョンの正本は `Cargo.toml` です。`lib/sonicop/version.rb` は `make version-sync` で
149
+ 生成してコミットします(gemspec がパッケージ時に読むため)。両者が食い違うと CI が落ちます。
150
+
151
+ `config/default.yml` は上流 RuboCop から取り込んだものです。再取得は
152
+ `scripts/sync_default_yml.sh <rubocop-version>` で行い、由来のバージョンがファイル先頭に
153
+ 記録されます。
154
+
155
+ 依存更新には `depup --install` を使います。Ruby grammar は再現可能性のため `Cargo.toml` で
156
+ fork のコミットを固定しています。
157
+
158
+ ## ライセンス
159
+
160
+ [MIT](LICENSE)。同梱する RuboCop 既定設定とパーサー依存の著作権表示は
161
+ [NOTICE](NOTICE) および [`licenses/`](licenses/) に収録しています。
data/README.md ADDED
@@ -0,0 +1,173 @@
1
+ <h1 align="center">
2
+ <img src="docs/images/sonicop_logo_header.png" width="600" alt="Sonicop">
3
+ </h1>
4
+
5
+ <p align="center">
6
+ <strong>A fast, native RuboCop-compatible Ruby linter and formatter written in Rust.</strong>
7
+ </p>
8
+
9
+ <p align="center">
10
+ <a href="https://github.com/owayo/sonicop/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/owayo/sonicop/actions/workflows/ci.yml/badge.svg?branch=main"></a>
11
+ <a href="https://rubygems.org/gems/sonicop"><img alt="Gem Version" src="https://img.shields.io/gem/v/sonicop"></a>
12
+ <a href="LICENSE"><img alt="License" src="https://img.shields.io/github/license/owayo/sonicop"></a>
13
+ </p>
14
+
15
+ <p align="center">
16
+ <a href="README.md">English</a> |
17
+ <a href="README.ja.md">日本語</a>
18
+ </p>
19
+
20
+ ---
21
+
22
+ ## Overview
23
+
24
+ Sonicop is a fast Ruby linter and formatter that runs as a native executable without starting a
25
+ Ruby process. Existing `.rubocop.yml` files work as-is, including nested configuration,
26
+ inheritance, file inclusion and exclusion, severity, and autocorrect settings.
27
+
28
+ It uses the actively maintained
29
+ [owayo/tree-sitter-ruby](https://github.com/owayo/tree-sitter-ruby) grammar, inspects files in
30
+ parallel, and applies corrections atomically. Its RuboCop 1.89-compatible CLI and JSON output fit
31
+ existing editor and CI integrations with minimal changes.
32
+
33
+ ## Features
34
+
35
+ Sonicop implements cops in the Layout, Lint, Metrics, Naming, Security, and Style departments.
36
+ The implemented set grows with each release, so the binary itself is the authoritative list:
37
+
38
+ ```bash
39
+ # Every recognized cop and its implementation status
40
+ sonicop --show-cops
41
+ ```
42
+
43
+ The bundled upstream configuration recognizes all 609 RuboCop 1.89 cops. Implemented cops run
44
+ normally; recognized but not-yet-implemented cops remain configuration-compatible and are
45
+ reported by `--debug`. Truly unknown cop names still fail validation unless
46
+ `--ignore-unrecognized-cops` is supplied.
47
+
48
+ ## Installation
49
+
50
+ ```bash
51
+ gem install sonicop
52
+ ```
53
+
54
+ Platform gems include native executables for Linux, macOS, and Windows. When a prebuilt platform
55
+ gem is unavailable, the source gem builds the executable with Cargo during installation.
56
+
57
+ You can also install the latest source directly:
58
+
59
+ ```bash
60
+ cargo install --git https://github.com/owayo/sonicop
61
+ ```
62
+
63
+ ## Usage
64
+
65
+ ```bash
66
+ # Inspect the current project
67
+ sonicop
68
+
69
+ # Select cops or departments
70
+ sonicop --only Layout,Style/StringLiterals app spec
71
+
72
+ # Safe correction / all correction
73
+ sonicop -a
74
+ sonicop -A
75
+
76
+ # RuboCop-shaped JSON
77
+ sonicop --format json
78
+
79
+ # Editor input
80
+ printf '%s\n' 'value=10000' | sonicop --stdin example.rb --format json
81
+
82
+ # List recognized cops and their implementation status
83
+ sonicop --show-cops
84
+ ```
85
+
86
+ Key compatibility flags include `-l`, `-x`, `--only`, `--except`, `-s/--stdin`, `-P/--parallel`,
87
+ `-f/--format`, `-a/--autocorrect`, `-A/--autocorrect-all`, `-L/--list-target-files`,
88
+ `-c/--config`, `-v/--version`, and `-V/--verbose-version`.
89
+
90
+ ### Configuration
91
+
92
+ Sonicop resolves `.rubocop.yml` from each target file, so nested configurations apply within one
93
+ run. Local and HTTPS `inherit_from`, `inherit_gem`, `inherit_mode`,
94
+ `AllCops/DisabledByDefault`, `Include`, and `Exclude`, plus per-cop `Enabled`, `Exclude`,
95
+ `Severity`, `Safe`, `SafeAutoCorrect`, and cop settings are supported. Cops supplied by declared
96
+ plugins are accepted as recognized-but-unimplemented without executing Ruby plugin code.
97
+
98
+ ```yaml
99
+ inherit_from: .rubocop_todo.yml
100
+
101
+ AllCops:
102
+ Exclude:
103
+ - "vendor/**/*"
104
+
105
+ Layout/LineLength:
106
+ Max: 100
107
+
108
+ Style/StringLiterals:
109
+ EnforcedStyle: single_quotes
110
+ ```
111
+
112
+ The CLI accepts RuboCop's server/LSP/MCP, plugin, and cache flags to keep existing command lines
113
+ parse-compatible. These flags are reported as compatibility no-ops when they request unsupported
114
+ functionality. Sonicop does not currently provide server transports, Ruby plugin execution, cache
115
+ reuse, custom Ruby cops, or cops outside the implemented set.
116
+
117
+ ### Conformance
118
+
119
+ The implemented cops are verified against RuboCop 1.89 using normalized JSON offenses.
120
+ On RuboCop's complete 1,759-file source tree with the upstream default configuration, the current
121
+ snapshot matches all 4,052 reference offense locations (**100% recall**) with **zero false
122
+ positives and zero metadata differences**. On Rails, all 3,453 Ruby target paths and the root/nested enabled-cop lists match
123
+ exactly, the full tree has zero false positives, and the 402-file Active Record subset runs about
124
+ 12.5x faster without cache. See [CONFORMANCE.md](CONFORMANCE.md) for the commands, scope, and
125
+ measurements.
126
+
127
+ ## Development
128
+
129
+ `make` is the single entry point; `make help` lists every target. The Rakefile holds the gem
130
+ packaging tasks that `make` delegates to.
131
+
132
+ ```bash
133
+ make build # debug build
134
+ make check # fmt, clippy, Rust tests, Ruby wrapper tests, version consistency
135
+ make gem # source gem
136
+ ```
137
+
138
+ ### Adding a cop
139
+
140
+ A cop is one file under `src/rules/<department>/<cop>.rs` exposing a single
141
+ `check(context, offenses)`, plus one line in that department's `mod.rs`:
142
+
143
+ ```rust
144
+ department_rules! {
145
+ "Layout";
146
+ line_length => ("LineLength", Convention),
147
+ }
148
+ ```
149
+
150
+ That line is the only place the cop's name and default severity are written. Inside the cop the
151
+ name stays implicit: `context.setting("Max")` reads `Layout/LineLength: Max`, and
152
+ `context.offense(message, range)` reports under the cop's own name at its configured severity. A
153
+ cop that spelled its name a second time could disagree with the registry, and nothing in the type
154
+ system would catch it.
155
+
156
+ Prefer `context.nodes_of("kind")` over walking every node: each cop runs on every file, so a full
157
+ walk per cop is what makes inspection scale with the registry rather than with the file.
158
+
159
+ `Cargo.toml` is the single source of truth for the version. `lib/sonicop/version.rb` is generated
160
+ from it by `make version-sync` and committed, because the gemspec reads it at package time. CI
161
+ fails when the two disagree.
162
+
163
+ `config/default.yml` is vendored from upstream RuboCop; re-fetch it with
164
+ `scripts/sync_default_yml.sh <rubocop-version>`, which records the source version in the file
165
+ header.
166
+
167
+ Dependencies are updated with `depup --install`. The Ruby grammar dependency is pinned to an exact
168
+ fork commit in `Cargo.toml` for reproducible builds.
169
+
170
+ ## License
171
+
172
+ [MIT](LICENSE). The bundled RuboCop default configuration and parser dependency retain their
173
+ upstream notices in [NOTICE](NOTICE) and [`licenses/`](licenses/).