Skip to content

Commit 33b13ad

Browse files
makinzmclaude
andauthored
feat: C language support (#70)
* [fix] C 言語サポートを追加 because of C プロジェクトのアーキテクチャチェックが必要 - infrastructure/parser/c.rs: #include パース、Symbol/Variable/Comment 抽出(ParsedNames 対応) - infrastructure/resolver/c.rs: "..." → Internal, <stdlib> → Stdlib, <other> → External - DispatchingParser / DispatchingResolver に .c/.h 拡張子を登録 - SOURCE_EXTENSIONS に c, h を追加 - ext_to_language に c/h を追加(mille init 対応) - violation_detector に C の external crate_name 抽出(/ 区切り)を追加 - E2E テスト 9 ケース全通過(valid, dep opt-in/out, naming) - CI dogfooding ステップ追加(ci.yml) - CLAUDE.md / .claude/rules/new-language.md に言語追加チェックリスト追加 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [refactor] README / TODO.md / Website ドキュメント更新 — C 言語サポート追加 - README.md: フィーチャーマトリックスに C 列追加、C 設定例追加 - docs/TODO.md: C 言語サポート完了を記載 - website: C 言語ガイド(ja + en)、index.mdx サポート表更新、sidebar 追加 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 05fd111 commit 33b13ad

File tree

30 files changed

+1299
-23
lines changed

30 files changed

+1299
-23
lines changed

.claude/rules/new-language.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# 言語追加時のルール
2+
3+
## E2E fixture と CI dogfooding はセットで1タスク
4+
5+
E2E fixture を書いたら、それを CI で走らせるステップも同時に追加する。分離して考えない。
6+
7+
### 必須成果物(parser/resolver 以外)
8+
9+
1. **CI dogfooding**(最初に意識する)
10+
- `.github/workflows/ci.yml``dogfood-rust` ジョブに追加
11+
- `mille check` が新 fixture に対して正常終了すること
12+
- **これは E2E テストとは別物** — CI 上で実際のバイナリが fixture を検証する
13+
14+
2. **E2E テスト**
15+
- `tests/e2e_<lang>.rs` + `tests/fixtures/<lang>_sample/`
16+
- `docs/e2e_checklist.md` の全項目をカバー(dep opt-in/out, external opt-in/out, naming)
17+
- 正常系だけでなく、**意図的に壊したときに失敗するテスト** を含める
18+
19+
3. **Website ドキュメント**
20+
- `website/src/content/docs/guides/languages/<lang>.md`(ja)
21+
- `website/src/content/docs/en/guides/languages/<lang>.md`(en)
22+
- `website/src/content/docs/index.mdx` + `en/index.mdx` のサポート表
23+
- `website/astro.config.mjs` のサイドバー
24+
25+
4. **README.md フィーチャーマトリックス**
26+
- 全チェック行に新言語の列を追加
27+
28+
### TODO.md の書き方
29+
30+
言語追加の TODO.md を書くとき、以下の順序でタスクを列挙する:
31+
32+
```markdown
33+
- [ ] CI dogfooding ステップ追加(ci.yml) ← 最初に書く
34+
- [ ] E2E fixture 作成
35+
- [ ] E2E テスト作成
36+
- [ ] Parser 実装
37+
- [ ] Resolver 実装
38+
- [ ] DispatchingParser / DispatchingResolver 登録
39+
- [ ] Website ドキュメント(ja + en + sidebar + index)
40+
- [ ] README.md フィーチャーマトリックス更新
41+
- [ ] docs/TODO.md 更新
42+
```

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ jobs:
144144
- name: Self-check — PHP fixture (tests/fixtures/php_sample)
145145
working-directory: tests/fixtures/php_sample
146146
run: ${{ github.workspace }}/target/release/mille check
147+
- name: Self-check — C fixture (tests/fixtures/c_sample)
148+
working-directory: tests/fixtures/c_sample
149+
run: ${{ github.workspace }}/target/release/mille check
147150

148151
# ------------------------------------------------------------------ #
149152
# 3b. Dogfooding-python — maturin build → pytest + mille check #

AGENTS.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@
2222
- `external_allow=[]` を安易に使うと serde 等で他レイヤーが誤検知する
2323
- 設定項目の追加・変更時は `docs/e2e_checklist.md` を確認し、**意図的に壊したとき失敗する**テストが揃っているか検証する(正常系のみは無価値)
2424

25+
## 言語追加チェックリスト
26+
27+
新しい言語サポートを追加するとき、以下を **すべて** 完了する。parser/resolver だけでは未完成。
28+
29+
1. **CI dogfooding**: `.github/workflows/ci.yml``dogfood-rust` ジョブに新 fixture の `mille check` ステップ追加 ← **最初にやる**
30+
2. **E2E fixture テスト**: `tests/fixtures/<lang>_sample/` + `tests/e2e_<lang>.rs``docs/e2e_checklist.md` の全項目をカバー
31+
3. **Website ドキュメント**: `website/src/content/docs/guides/languages/<lang>.md`(ja + en)、`index.mdx` のサポート表更新、`astro.config.mjs` のサイドバー追加
32+
4. **README.md**: フィーチャーマトリックスに言語列追加
33+
34+
TODO.md を書く段階でこの 4 点を明示的にタスクとして含める。
35+
2536
## PR 作成前チェックリスト(順序厳守)
2637

2738
1. `docs/TODO.md` 更新(完了チェック・実装状況サマリー)

Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ clap = { version = "4", features = ["derive"] }
3636
serde_json = "1"
3737
tree-sitter-kotlin = "0.3"
3838
tree-sitter-php = "0.22"
39+
tree-sitter-c = "0.21"
3940

4041
[dev-dependencies]
4142
tempfile = "3"

README.md

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ One TOML config. Rust-powered. CI-ready. Supports multiple languages from a sing
1818

1919
## What it checks
2020

21-
| Check | Rust | Go | TypeScript | JavaScript | Python | Java | Kotlin | PHP |
22-
|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
23-
| Layer dependency rules (`dependency_mode`) |||||||||
24-
| External library rules (`external_mode`) |||||||||
25-
| DI method call rules (`allow_call_patterns`) |||||||||
26-
| Naming convention rules (`name_deny`) |||||||||
21+
| Check | Rust | Go | TypeScript | JavaScript | Python | Java | Kotlin | PHP | C |
22+
|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
23+
| Layer dependency rules (`dependency_mode`) ||||||||||
24+
| External library rules (`external_mode`) ||||||||||
25+
| DI method call rules (`allow_call_patterns`) ||||||||||
26+
| Naming convention rules (`name_deny`) ||||||||||
2727

2828
## Install
2929

@@ -419,7 +419,7 @@ Exit codes:
419419
|---|---|
420420
| `name` | Project name |
421421
| `root` | Root directory for analysis |
422-
| `languages` | Languages to check: `"rust"`, `"go"`, `"typescript"`, `"javascript"`, `"python"`, `"java"`, `"kotlin"`, `"php"` |
422+
| `languages` | Languages to check: `"rust"`, `"go"`, `"typescript"`, `"javascript"`, `"python"`, `"java"`, `"kotlin"`, `"php"`, `"c"` |
423423

424424
### `[[layers]]`
425425

@@ -626,6 +626,35 @@ allow = ["domain", "application"]
626626
composer_json = "composer.json" # auto-detects "App\\" from autoload.psr-4
627627
```
628628

629+
### C
630+
631+
> `#include "..."` is classified as Internal (project header). `#include <...>` is classified as Stdlib (standard/POSIX headers) or External (third-party libraries).
632+
633+
**Example `mille.toml` for a C project:**
634+
635+
```toml
636+
[project]
637+
name = "my-c-app"
638+
root = "."
639+
languages = ["c"]
640+
641+
[[layers]]
642+
name = "domain"
643+
paths = ["src/domain/**"]
644+
645+
[[layers]]
646+
name = "usecase"
647+
paths = ["src/usecase/**"]
648+
dependency_mode = "opt-in"
649+
allow = ["domain"]
650+
651+
[[layers]]
652+
name = "infrastructure"
653+
paths = ["src/infrastructure/**"]
654+
dependency_mode = "opt-in"
655+
allow = ["domain"]
656+
```
657+
629658
## How it Works
630659

631660
mille uses [tree-sitter](https://tree-sitter.github.io/) for AST-based import extraction — no regex heuristics.

docs/TODO.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
-`mille init` Python namespace インポートスキャン修正 — `from src.domain.entity import X` がレイヤー内部依存として正しく検出されるよう修正(`classify_py_import` フルパス返し + `resolve_to_known_dir` プレフィックス照合)、`src/main.py` 等の浅い階層ファイルがスキップされずレイヤーとして登録されるよう修正(PR #62
3131
- ✅ ネーミング規則チェック (`name_deny` / `name_targets` / `name_allow` / `name_deny_ignore`) — レイヤーごとに禁止キーワードを設定し、ファイル名・シンボル名・変数名・コメントに禁止キーワードが含まれる場合に `NamingViolation` を報告(大文字小文字区別なし・部分一致)。`name_allow` で false positive を抑制、`name_deny_ignore` でグロブパターンにマッチするファイルを除外可能。対応言語: Rust/TypeScript/Python/Go/Java/Kotlin/PHP。`severity.naming_violation` で重大度設定可(PR #65
3232
-`ParsedNames` 構造体によるコンパイルタイムガード — `Parser::parse_names` の戻り値を `ParsedNames` に変更し、新しい `NameKind` 追加時に全パーサーでコンパイルエラーが発生するよう保証。PHP/Python に Variable 抽出を追加(PR #68
33+
- ✅ C 言語サポート — `.c`/`.h` ファイルの `#include` パース、`"..."` → Internal / `<stdlib>` → Stdlib / `<other>` → External 分類、Symbol/Variable/Comment naming 抽出、E2E テスト追加(PR #69
3334
- ✅ PHP 言語サポート — `.php` ファイルの `use` 文パース(simple/aliased/grouped/function/const)・Internal/External/Stdlib 分類、`[resolve.php] namespace` 設定、`composer.json` `autoload.psr-4` 自動検出、PHP stdlib クラス(DateTime/PDO/Exception 等)の Stdlib 自動分類
3435

3536
以下は **設定ファイルにフィールドが存在しても、まだ動作していない** 項目です(README に掲載しないよう修正済み):

src/domain/service/violation_detector.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,14 @@ impl<'a> ViolationDetector<'a> {
9797
{
9898
// Slash-separated imports: "vitest/config" -> "vitest", "@scope/pkg/sub" -> "@scope/pkg"
9999
extract_ts_package_name(&import.raw.path)
100+
} else if import.raw.file.ends_with(".c") || import.raw.file.ends_with(".h") {
101+
// Slash-separated includes: "curl/curl.h" -> "curl", "sqlite3.h" -> "sqlite3.h"
102+
import
103+
.raw
104+
.path
105+
.split('/')
106+
.next()
107+
.unwrap_or(&import.raw.path)
100108
} else if import.raw.file.ends_with(".php") {
101109
// Backslash-separated imports: "Illuminate\Http\Request" -> "Illuminate"
102110
import

0 commit comments

Comments
 (0)