rusty-javac 0.2.3

A Java compiler written in Rust.
Documentation
# Contributing to Rusty-JavaC

Rusty-JavaC is an early-stage Java compiler written in Rust. Treat every change as compiler work: keep it small, test the generated class files, and leave the code easier to understand than you found it.

## Setup

Required tools:

- Rust 1.85+ with Cargo
- Java 21+ for `javac`, `javap`, and JVM verification
- Git

Build and run the Rust tests:

```bash
cargo build --locked
cargo test --locked
```

For bytecode, lowering, or type changes, also compile at least one Java fixture and inspect the generated class:

```bash
cargo run --locked --example compiler-example -- --output-dir target/test-output tests/java/HelloWorld.java
javap -v -c target/test-output/HelloWorld.class
java -Xverify:all -cp target/test-output HelloWorld
```

## Project Layout

The project is a single Cargo package. Compiler stages are regular Rust modules under `src/`:

```text
src/
|- ast           # Syntax node wrappers over the parsed tree
|- lexer         # Tokenization and Unicode escape handling
|- parser        # Recursive-descent parser
|- hir           # High-level IR, lowering, and expression inference
|- ty            # Java type model, descriptors, and assignability
|- call_resolver # Class catalog and method/constructor lookup
|- bytecode      # JVM bytecode generation and bytecode validation
|- classfile     # .class reading and writing helpers
|- diagnostics   # User-facing diagnostic rendering
`- compiler      # Classpath, incremental state, and compile pipeline
```

The compile path is:

```text
Java source
  -> lexer
  -> parser
  -> ast
  -> hir lowering
  -> type and call resolution
  -> bytecode generation
  -> classfile writer
```

`src/lib.rs` should stay small. Add new implementation inside the stage that owns it, then expose only the API that other stages need.

## Change Guidelines

Keep compiler behavior and structure separate:

- Parser code should describe syntax, not Java semantics.
- Lowering should translate syntax into HIR and preserve useful source spans.
- Type inference and call resolution should avoid hardcoded one-off cases when the class catalog can answer the question.
- Bytecode generation should consume typed/resolved HIR instead of re-parsing syntax decisions.
- Diagnostics should report the real source span and explain the fix when the compiler knows one.

Prefer small modules with clear ownership. If a file grows because it handles several independent concepts, split by concept rather than by arbitrary line count.

Do not add tests that only assert exact pretty-printed diagnostic text unless the output is intentionally stable. Prefer Java fixtures, JVM verification, `javap` inspection, or snapshot tests for rendered diagnostics.

## Java Fixtures

Put integration fixtures under `tests/java/`. A good fixture:

- compiles with `javac`
- exercises one compiler capability or one known edge case
- can be verified with `java -Xverify:all` when it has a runnable `main`
- avoids unrelated language features that make failures harder to diagnose

When changing bytecode output, compare against `javac` when practical. Exact bytecode does not need to match, but verifier behavior and runtime behavior should.

## Checklist Before Commit

Run the narrowest useful checks first, then the full set before committing:

```bash
cargo fmt --all
cargo check --workspace --all-targets --locked
cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
cargo test --workspace --locked
```

For compiler changes, also compile the affected fixtures:

```bash
cargo run --locked --example compiler-example -- --output-dir target/java-fixtures-rusty tests/java/HelloWorld.java
javap -v -c target/java-fixtures-rusty/HelloWorld.class
```

## Commits

Use Conventional Commits:

```text
type(scope): short description
```

Common types are `feat`, `fix`, `refactor`, `docs`, `test`, `ci`, and `chore`. Useful scopes are module names such as `parser`, `hir`, `bytecode`, `compiler`, `diagnostics`, and `classfile`.

Keep commits focused. If a feature needs parser, lowering, bytecode, and tests, split it into reviewable commits when possible.

## Roadmap

Use [TODO.md](TODO.md) as the working backlog. If a PR finishes an item, update the checkbox in the same PR.

## License

By contributing, you agree that your contributions are licensed under the [MIT License](LICENSE).