jvへの貢献¶
English | 日本語
jvへの貢献に関心をお持ちいただき、ありがとうございます!このガイドは、開発と貢献ワークフローの開始に役立ちます。
目次¶
はじめに¶
前提条件¶
- Rust 1.70+: rustup経由でインストール
- Java 25+: 生成されたコードのテストに必要
- Git: バージョン管理用
- IDE: rust-analyzer付きVS CodeまたはRustプラグイン付きIntelliJ
クイックセットアップ¶
# リポジトリをクローン
git clone https://github.com/project-jvlang/jv-lang.git
cd jv-lang
# プロジェクトをビルド
cargo build
# テストを実行
cargo test
# pre-commitフックをインストール(オプションですが推奨)
cargo install --git https://github.com/project-jvlang/jv-tools pre-commit
pre-commit install
開発環境セットアップ¶
開発依存関係¶
# 追加の開発ツールをインストール
cargo install cargo-watch # 変更時の自動再ビルド
cargo install cargo-audit # セキュリティ監査
cargo install cargo-tarpaulin # コードカバレッジ
cargo install cargo-deny # 依存関係チェック
IDE設定¶
VS Code¶
これらの拡張機能をインストール: - rust-analyzer: Rust言語サポート - Error Lens: インラインエラー表示 - GitLens: Git統合 - Better TOML: TOMLファイルサポート
推奨設定(.vscode/settings.json):
{
"rust-analyzer.checkOnSave.command": "clippy",
"rust-analyzer.cargo.features": "all",
"editor.formatOnSave": true,
"files.trimTrailingWhitespace": true
}
IntelliJ IDEA¶
- Rustプラグインをインストール
- コードフォーマット用にRustfmtを設定
- リンティング用にClippyを有効化
環境変数¶
export RUST_LOG=debug # デバッグログを有効化
export JV_TEST_DATA=/path/to/test # カスタムテストデータディレクトリ
export JAVA_HOME=/path/to/java25 # Java 25インストール
プロジェクト構造¶
jv/
├── crates/ # Rustワークスペースクレート
│ ├── jv_lexer/ # 字句解析
│ ├── jv_parser/ # 構文解析
│ ├── jv_ast/ # AST定義
│ ├── jv_ir/ # 中間表現
│ ├── jv_codegen_java/ # Javaコード生成
│ ├── jv_checker/ # 静的解析
│ ├── jv_fmt/ # コードフォーマット
│ ├── jv_build/ # ビルドシステム
│ ├── jv_mapper/ # ソースマッピング
│ ├── jv_pm/ # パッケージマネージャー
│ ├── jv_lsp/ # 言語サーバー
│ └── jv_cli/ # コマンドラインインターフェース
├── docs/ # ドキュメント
├── examples/ # jvプログラム例
├── tests/ # 統合テスト
├── tools/ # 開発ツール
├── Cargo.toml # ワークスペース設定
└── README.md
クレートの責任¶
- jv_lexer: jvソースコードのトークン化
- jv_parser: トークンを抽象構文木(AST)に解析
- jv_ast: ASTノード定義とユーティリティ
- jv_ir: 中間表現と変換
- jv_codegen_java: IRからJavaソースコード生成
- jv_checker: 型チェックと静的解析
- jv_fmt: ソースコードフォーマット
- jv_build: ビルドシステム統合とjavac相互作用
- jv_mapper: デバッグ用ソースマップ生成
- jv_pm: パッケージ管理と依存関係解決
- jv_lsp: 言語サーバープロトコル実装
- jv_cli: コマンドラインインターフェースとメインエントリーポイント
開発ワークフロー¶
ブランチ戦略¶
シンプルなGit Flowを使用:
- main: 安定リリースブランチ
- develop: フィーチャー統合ブランチ
- feature/: フィーチャー開発ブランチ
- bugfix/: バグ修正ブランチ
- hotfix/: mainに対する重要な修正
フィーチャー開発¶
-
フィーチャーブランチを作成:
-
頻繁なコミットで変更を実施:
-
ブランチを最新に保つ:
-
プッシュしてプルリクエストを作成:
言語フィーチャーの追加¶
新しいjv言語フィーチャーを追加する際は、この順序に従ってください:
- lexerを更新 (
jv_lexer): - 必要に応じて新しいトークンタイプを追加
-
トークン化ロジックを更新
-
parserを更新 (
jv_parser): - 新しい構文を処理するため文法を拡張
-
新しい構造のASTノードを追加
-
AST定義を更新 (
jv_ast): - 新しいノードタイプとビジターを追加
-
シリアライゼーション/デシリアライゼーションを更新
-
型チェッカーを更新 (
jv_checker): - セマンティック検証を追加
-
新しい型ルールを処理
-
IR変換を更新 (
jv_ir): - 新しい構造の脱糖方法を定義
-
変換パスを追加
-
コードジェネレーターを更新 (
jv_codegen_java): - Javaコード生成を実装
-
慣用的な出力を保証
-
フォーマッターを更新 (
jv_fmt): -
新しい構文のフォーマットルールを追加
-
包括的なテストを追加:
- 各コンポーネントの単体テスト
- 完全パイプラインの統合テスト
-
エラーケーステスト
-
ドキュメントを更新:
- 言語ガイドの例
- 仕様の更新
デバッグ¶
コンパイラデバッグ¶
詳細ログを有効化:
中間表現を表示:
# 生成されたASTを表示
cargo run -- build --debug-ast test.jv
# 生成されたIRを表示
cargo run -- build --debug-ir test.jv
# 生成されたJava(コンパイル前)を表示
cargo run -- build --preview test.jv
テストデバッグ¶
特定のテストを実行:
# 特定のクレートのテストを実行
cargo test -p jv_parser
# 特定のテストを実行
cargo test test_string_interpolation
# 出力付きで実行
cargo test -- --nocapture
テスト¶
テストカテゴリ¶
単体テスト¶
各クレートはsrc/ディレクトリに単体テストを持ちます:
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_lexer_string_literal() {
let input = r#""Hello, world!""#;
let mut lexer = Lexer::new(input);
let token = lexer.next_token();
assert_eq!(token.kind, TokenKind::StringLiteral("Hello, world!".to_string()));
}
}
統合テスト¶
tests/の完全コンパイルパイプラインテスト:
#[test]
fn test_compile_hello_world() {
let jv_source = r#"
fun main() {
println("Hello, world!")
}
"#;
let result = compile_jv_to_java(jv_source);
assert!(result.is_ok());
let java_code = result.unwrap();
assert!(java_code.contains("System.out.println"));
}
ゴールデンテスト¶
生成出力を期待ファイルと比較:
#[test]
fn test_codegen_golden() {
let jv_file = "tests/golden/input.jv";
let expected_java = "tests/golden/expected.java";
let actual_java = compile_file(jv_file).unwrap();
let expected = fs::read_to_string(expected_java).unwrap();
assert_eq!(normalize_whitespace(&actual_java), normalize_whitespace(&expected));
}
テストの実行¶
# すべてのテストを実行
cargo test
# カバレッジ付きテスト実行
cargo tarpaulin --out html
# 特定のクレートのテストを実行
cargo test -p jv_parser
# 統合テストのみ実行
cargo test --test integration
# 詳細出力付き実行
cargo test -- --nocapture
# パターンマッチングテスト実行
cargo test string_interpolation
テストデータ¶
テストファイルはtests/data/に整理されています:
tests/data/
├── valid/ # 有効なjvプログラム
│ ├── basic/ # 基本言語フィーチャー
│ ├── advanced/ # 高度なフィーチャー
│ └── edge_cases/ # エッジケースとコーナーケース
├── invalid/ # 無効なプログラム(エラーテスト用)
├── golden/ # ゴールデンテストファイル
│ ├── input.jv
│ └── expected.java
└── performance/ # パフォーマンスベンチマーク
良いテストの書き方¶
-
テスト命名: 説明的な名前を使用
-
Arrange-Act-Assertパターン:
#[test] fn test_parser_function_declaration() { // Arrange let input = "fun add(a: Int, b: Int): Int = a + b"; let mut parser = Parser::new(input); // Act let result = parser.parse_function(); // Assert assert!(result.is_ok()); let func = result.unwrap(); assert_eq!(func.name, "add"); assert_eq!(func.parameters.len(), 2); } -
エラーケースのテスト:
コードスタイル¶
Rustコードスタイル¶
標準Rust規約に従う:
フォーマット¶
リンティング¶
命名規則¶
- 型:
PascalCase - 関数:
snake_case - 変数:
snake_case - 定数:
SCREAMING_SNAKE_CASE - モジュール:
snake_case
ドキュメント¶
Rustドキュメントコメントを使用:
/// jv式をASTノードに解析します。
///
/// # 引数
///
/// * `input` - 解析するjvソースコード
/// * `options` - 解析オプションと設定
///
/// # 戻り値
///
/// 解析が成功すれば`Ok(Expression)`、失敗すれば`Err(ParseError)`を返します。
///
/// # 例
///
/// ```
/// use jv_parser::Parser;
///
/// let expr = Parser::new("1 + 2").parse_expression().unwrap();
/// assert_eq!(expr.kind, ExpressionKind::BinaryOperation);
/// ```
pub fn parse_expression(input: &str, options: ParseOptions) -> Result<Expression, ParseError> {
// 実装...
}
エラーハンドリング¶
Result型を一貫して使用:
use anyhow::{Result, Context};
pub fn compile_file(path: &Path) -> Result<String> {
let source = fs::read_to_string(path)
.with_context(|| format!("Failed to read file: {}", path.display()))?;
let ast = parse(&source)
.context("Failed to parse jv source")?;
let java_code = generate_java(&ast)
.context("Failed to generate Java code")?;
Ok(java_code)
}
Gitコミットメッセージ¶
慣用的コミット形式に従う:
タイプ:
- feat: 新機能
- fix: バグ修正
- docs: ドキュメント変更
- style: コードスタイル変更
- refactor: コードリファクタリング
- test: テストの追加または更新
- chore: ビルドプロセスまたは補助ツール変更
例:
fix(codegen): メソッドチェーンでのnull安全性を処理
以前は、nullable型でのチェーンメソッド呼び出しが不正な
Javaコードを生成していました。今はnull安全な呼び出し
チェーンを適切に生成します。
Fixes #456
プルリクエストプロセス¶
提出前¶
-
テストが通ることを確認:
-
必要に応じてドキュメントを更新
-
新機能にテストを追加
-
統合テストを実行:
プルリクエストテンプレート¶
PRを作成する際は、以下を含めてください:
## 説明
変更の簡潔な説明
## 変更の種類
- [ ] バグ修正(既存機能を壊さない問題修正)
- [ ] 新機能(既存機能を壊さない機能追加)
- [ ] 破壊的変更(既存機能が期待通りに動作しなくなる修正や機能)
- [ ] ドキュメント更新
## テスト
- [ ] 単体テストを追加/更新
- [ ] 統合テストを追加/更新
- [ ] すべてのテストがローカルで通る
## チェックリスト
- [ ] コードがスタイルガイドラインに従っている
- [ ] セルフレビューを完了
- [ ] ドキュメントを更新
- [ ] 破壊的変更なし(または明確に文書化)
レビュープロセス¶
- 自動チェックが通る必要がある(CI/CD)
- メンテナーによるコードレビュー
- 議論とフィードバック
- 承認とマージ
フィードバックへの対応¶
# フィードバックに基づいて変更
git add .
git commit -m "Address PR feedback: improve error messages"
git push origin feature/my-feature
イシューガイドライン¶
バグ報告¶
バグ報告テンプレートを使用:
## バグの説明
バグの明確な説明
## 再現手順
1. 内容でファイル`test.jv`を作成: ...
2. `jv build test.jv`を実行
3. エラーを観察: ...
## 期待される動作
何が起こるべきか
## 実際の動作
実際に何が起こるか
## 環境
- jvバージョン: `jv version`
- OS: Linux/macOS/Windows
- Javaバージョン: `java -version`
## 追加コンテキスト
その他の情報
機能リクエスト¶
## 機能の説明
提案する機能の明確な説明
## 使用例
なぜこの機能が必要か?
## 提案する解決策
この機能はどのように動作すべきか?
## 検討した代替案
他にどのような解決策を検討したか?
## 追加コンテキスト
例、モックアップなど
ラベル¶
bug: 何かが動作していないenhancement: 新機能またはリクエストdocumentation: ドキュメントの改善または追加good-first-issue: 新人に適しているhelp-wanted: 特別な注意が必要priority-high: 高優先度の問題component-parser: パーサー関連の問題component-codegen: コード生成の問題
コミュニティ¶
コミュニケーションチャンネル¶
- GitHub Issues: バグ報告と機能リクエスト
- GitHub Discussions: 一般的な質問と議論
- Discord: リアルタイムチャット(READMEの招待)
- Reddit: r/jv_langコミュニティ議論
行動規範¶
私たちはContributor Covenantに従います:
- 敬意を持ち包括的である
- フィードバックは建設的である
- 協力的で助けになる
- 人ではなくコードに焦点を当てる
ヘルプの取得¶
- ドキュメント: まずドキュメントをチェック
- イシューを検索: 同じ問題を抱えた人がいるかもしれません
- 質問する: GitHub Discussionsを質問に使用
- Discordに参加: コミュニティからのリアルタイムヘルプ
認識¶
貢献者は以下で認識されます: - CONTRIBUTORS.mdファイル - 重要な貢献に対するリリースノート - GitHub contributorsページ - Discord contributorロール
jvへの貢献をありがとうございます!🎉