Skip to content

Latest commit

 

History

History
72 lines (55 loc) · 4.53 KB

File metadata and controls

72 lines (55 loc) · 4.53 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Plz read README.md.

Build & Test Commands

cargo build --release        # Build
cargo test                   # Run all tests
cargo clippy                 # Lint
cargo fmt --check            # Format check
cargo bench                  # Run all benchmarks (Criterion)
cargo bench --bench ui_rendering
cargo bench --bench diff_parsing
cargo bench --bench symbol_search

Principles

This project is Building/Development for 5 Principles.

1. Always Integration/Snapshot/Scenario based TDD

  • Write tests before implementation. No feature is complete without passing tests.
  • Use insta for snapshot testing. always use inline-snapshot.
  • Use assert_cmd + predicates for integration tests that exercise the binary end-to-end.
  • Prefer scenario-based tests that simulate real user workflows (e.g., "load PR → navigate to file → jump to comment") over isolated unit tests of internal helpers.
  • Snapshot tests are the primary regression safety net. When changing rendering or API response parsing, always update or add snapshots.
  • Use serial_test (#[serial]) when tests share mutable global state or filesystem resources.

2. Always without exception needs recover Clippy,Test,Check Errors

  • Every change must pass all three gates before being considered complete:
    1. cargo clippy -- -D warnings — zero warnings, treated as errors
    2. cargo test — all tests green
    3. cargo check — no compilation errors
  • If a change introduces a Clippy warning, fix it immediately in the same change — never suppress with #[allow(...)] unless there is a documented, unavoidable reason.
  • CI failures are blocking. Do not proceed with further work until all three gates pass locally.
  • When refactoring, run all three gates after each logical step, not just at the end.

3. Focus on performance for Rust code

  • This app handles PRs with 6,000+ files and 300,000+ lines. Performance is a user-facing feature.
  • Use string interning (lasso::Rodeo) for repeated diff line strings to reduce allocations.
  • Use smallvec for stack-allocated small collections where heap allocation is avoidable.
  • Use compile-time perfect hash maps (phf) for static lookup tables (e.g., language detection, capture-to-scope mapping).
  • Pre-compute and cache syntax-highlighted diffs in DiffCache — never re-highlight on every render.
  • Benchmark before and after performance-sensitive changes using Criterion (benches/). The CI alerts on 150%+ regression.
  • Prefer &str borrows over String clones. Avoid unnecessary .clone() and .to_string().
  • Use tokio async tasks with cancellation tokens for background data loading — never block the UI thread.

4. Use a state machine for consistency instead of individual conditional branches.

  • All screen/mode transitions go through AppState enum (17 states). Never use ad-hoc boolean flags to track "which screen am I on."
  • Data loading lifecycle is modeled as DataState enum (LoadingLoadedError). Never use Option<Data> + is_loading: bool separately.
  • AI Rally transitions flow through RallyState enum with RallyEvent-driven transitions. Each state has explicit allowed transitions — invalid transitions are compile-time or runtime errors.
  • Input modes are modeled as InputMode enum variants with associated data (context, original code, etc.).
  • When adding a new feature that introduces a new mode or screen, add a variant to the appropriate state enum and handle it exhaustively in match arms. The compiler enforces completeness.
  • Pause/resume is PauseState enum (RunningPauseRequestedPausedRunning), not a boolean toggle.

5. Consider all edge cases as use cases

  • Empty states are first-class: no PRs, no files, no comments, no diff content — all must render gracefully.
  • Unicode and CJK text: use unicode-width for display width calculation. Never assume 1 byte = 1 character = 1 column.
  • Large inputs: test with 1,000+ line diffs and 5,000+ line patches. Benchmark suites cover 100/500/1000/5000 line scenarios.
  • Network failures: DataState::Error must display actionable messages. Retry mechanism uses atomic flags.
  • Concurrent state: file watcher events can arrive during any state. AI Rally commands can arrive while rendering. Handle via channels with non-blocking receives.
  • Platform differences: binary runs on Linux, macOS, Windows. Terminal behavior varies — use crossterm abstractions, never raw ANSI escapes.