sonicop 26.8.101-aarch64-linux

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b1298b2be973ee50f74c784c1d35d4f0b6a7fdb015bd8ac9d8677d07fb88ba0c
4
+ data.tar.gz: 3baadbdd3a5d6f10099820bc6b4d0cd890080b119b634b3c8dda391edb509e6d
5
+ SHA512:
6
+ metadata.gz: 39960db7a2d0ef1d1f30e0687a5a0f0a1c58333f1ed2516339b866c43beb5b62c82928e3fd47fcdd971648bcef5dbe00c248a4003ff5bb0114f504b6c3bbdf55
7
+ data.tar.gz: 3cdd38531491001e03abb895f4af8600999c9f267031c59d21a7b113c762adfd2ff5c997377dc16579898dc0b51dc0684f418a1f8c1fd01dc8099b66aaf705e0
data/CONFORMANCE.md ADDED
@@ -0,0 +1,109 @@
1
+ # RuboCop conformance
2
+
3
+ Snapshot date: 2026-08-10
4
+ Reference: RuboCop 1.89.0
5
+ Corpus: the complete 1,759-file RuboCop source tree
6
+ Configuration: RuboCop 1.89.0 built-in defaults (`--force-default-config`)
7
+
8
+ The bundled `config/default.yml` records the upstream version it was vendored from in its header.
9
+ Re-fetch it with `scripts/sync_default_yml.sh <rubocop-version>`.
10
+
11
+ The comparison covers every cop Sonicop implemented at the snapshot date, listed verbatim in the
12
+ `cops` variable of the command below. Each JSON offense is normalized by path, cop, line, column,
13
+ length, severity, correctability, and message. Run `sonicop --show-cops` for the current set.
14
+
15
+ | Result | Count |
16
+ |---|---:|
17
+ | Reference offense locations | 4,052 |
18
+ | Sonicop offense locations | 4,052 |
19
+ | Matching locations | 4,052 |
20
+ | False positives | **0** |
21
+ | False negatives | **0** |
22
+ | Location recall | **100%** |
23
+ | Message/severity/correctability differences at matching locations | **0** |
24
+
25
+ All offenses from the implemented cops match RuboCop by location, message, severity, and
26
+ correctability. This includes RuboCop's source-line indexing for metric cops, line-length
27
+ correctability and exemptions, directive lexing around heredocs, and target-version syntax errors.
28
+
29
+ Run the harness against a local RuboCop and corpus. It defaults to `rubocop` on `PATH`
30
+ (`gem install rubocop`) as the reference and `./target/release/sonicop` (`make release`) as the
31
+ candidate, so both only need `--reference` / `--candidate` when they live elsewhere — for example
32
+ `--reference "bundle exec rubocop"` inside a bundled project:
33
+
34
+ ```bash
35
+ cops="Layout/EmptyLineAfterMagicComment,Layout/EndOfLine,Layout/LineLength,Layout/SpaceAfterComma,Layout/SpaceAroundOperators,Layout/SpaceInsideParens,Layout/TrailingEmptyLines,Layout/TrailingWhitespace,Lint/DuplicateMethods,Lint/Syntax,Lint/UnusedBlockArgument,Lint/UselessAssignment,Metrics/BlockLength,Metrics/ClassLength,Metrics/MethodLength,Metrics/ModuleLength,Metrics/ParameterLists,Naming/AsciiIdentifiers,Naming/ConstantName,Naming/MethodName,Naming/VariableName,Security/Eval,Style/FrozenStringLiteralComment,Style/HashSyntax,Style/NumericLiterals,Style/RedundantReturn,Style/Semicolon,Style/StringLiterals"
36
+
37
+ scripts/conformance_diff.sh \
38
+ --force-default-config \
39
+ --cop "${cops}" \
40
+ -- /path/to/rubocop
41
+ ```
42
+
43
+ `Lint/Syntax` is also run independently over the corpus. The latest owayo tree-sitter grammar
44
+ accepts the modern syntax in all 1,759 files, while Sonicop resolves Ruby 2.6 from the corpus
45
+ gemspec and applies a post-parse syntax feature gate. Its four fatal offenses, including the legacy
46
+ parser recovery diagnostics, exactly match RuboCop.
47
+
48
+ ## Limits of this measurement
49
+
50
+ The 100% above is a property of *this corpus*, not a general accuracy claim. RuboCop's own source
51
+ tree is RuboCop-clean and stylistically uniform, so entire classes of input never occur in it and
52
+ the comparison cannot exercise them. A cop that is never triggered contributes nothing to the
53
+ match count, and its absence is indistinguishable from agreement.
54
+
55
+ Two implemented cops are confirmed to produce **zero offenses on both sides** over this corpus, so
56
+ this run says nothing about them:
57
+
58
+ | Cop | Offenses in this corpus | Verified elsewhere |
59
+ |---|---:|---|
60
+ | `Layout/TrailingEmptyLines` | 0 | Diverges on line, column, length, and message for a file ending in a blank line |
61
+ | `Naming/AsciiIdentifiers` | 0 | Rails contains exactly two occurrences; both diverge on message casing |
62
+
63
+ Running the same harness over application code rather than linter source surfaces divergences this
64
+ corpus does not. Treat a clean run on any single corpus as evidence about that corpus.
65
+
66
+ Two properties of the harness itself also bound what a run can tell you:
67
+
68
+ - Only the cops passed to `--cop` are compared. Cops that RuboCop reports and Sonicop has not
69
+ implemented show up as false negatives, which is expected rather than a defect.
70
+ - RuboCop emits **only** `Lint/Syntax` for a file it considers fatally unparseable and suppresses
71
+ every other cop for that file, while Sonicop keeps inspecting it. Whenever the two disagree
72
+ about syntax validity — most easily triggered by a `TargetRubyVersion` the source does not
73
+ satisfy — the false-positive count is dominated by that single behaviour rather than by cop
74
+ logic. Check the reference output for `"severity": "fatal"` before reading a large false-positive
75
+ count as a cop problem.
76
+
77
+ Closing these gaps properly means migrating RuboCop's own spec suite, which exercises each cop
78
+ against inputs written to break it. Until that lands, this document records what was measured, not
79
+ an upper bound on what could differ.
80
+
81
+ ## Rails configuration and scale
82
+
83
+ Rails source snapshot: `adf307b03b4241cbc0ed3821faf3b153ca6cd5cd` (Rails 8.2.0.alpha).
84
+ The reference process uses RuboCop 1.89.0 with the five plugins declared by Rails:
85
+ rubocop-minitest 0.40.0, rubocop-packaging 0.6.0, rubocop-performance 1.26.1,
86
+ rubocop-rails 2.36.0, and rubocop-md 2.0.4.
87
+
88
+ This corpus exercises `AllCops/DisabledByDefault`, external plugin cops, recursive excludes,
89
+ hidden paths, and the inherited `guides/.rubocop.yml` configuration.
90
+
91
+ | Compatibility check | RuboCop | Sonicop | Result |
92
+ |---|---:|---:|---|
93
+ | Ruby target files from repository root | 3,453 | 3,453 | Exact paths and order |
94
+ | Enabled cops for `activerecord/lib/active_record.rb` | 107 | 107 | Exact names and order |
95
+ | Enabled cops for a file under `guides/` | 102 | 102 | Exact names and order |
96
+ | Full-tree false positives | — | 0 | Pass |
97
+
98
+ RuboCop also discovers 75 Markdown targets through rubocop-md. Markdown extraction is outside
99
+ Sonicop's current parser scope, so those files are removed before comparing `-L` output.
100
+
101
+ The full 3,453-Ruby-file offense comparison reports 10 reference locations and no Sonicop
102
+ locations: zero false positives and 10 visible false negatives. The missing locations are three
103
+ `Style/RedundantPercentQ`, two `Lint/RedundantCopDisableDirective`, two
104
+ `Layout/IndentationWidth`, two unsupported `Lint/DuplicateMethods` cases, and one
105
+ `Lint/Debugger`. Artifacts: `/tmp/sonicop-conformance-rails-full-2`.
106
+
107
+ On the 402-file `activerecord/lib` subset, a warmed single run with cache and color disabled took
108
+ 4.37 seconds for RuboCop and 0.35 seconds for Sonicop (`/usr/bin/time -p`): approximately
109
+ **12.5x faster** on the validation machine.
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/).