feat: ck_playground — render .cktest fixtures via cktest parser #1
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/001-feat-ck-playground-render-cktest-fixtures-via"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
feat: ck_playground — render .cktest fixtures via cktest parser
Along the way:
Touches 42 files:
docs/impl/02-lexer.md,docs/impl/03-parser.md,scripts/run.sh,scripts/test.sh,src/rust/crates/ck_driver/tests/architecture.rs,src/rust/crates/ck_lex/src/lib.rsand 36 more.Happy with this. I ran the suite against the branch and it is green,
src/rust/crates/ck_lex/src/tests.rsincluded.@ -0,0 +49,4 @@}#[test]fn long_decimal() {long_decimalreads, decides and writes in one function. The deciding part is the piece I would want to test on its own. Worth splitting?@ -0,0 +377,4 @@"unexpected diagnostics: {:?}",out.diagnostics);let f = find_first(&out.tree, SyntaxKind::FnDecl).expect("FnDecl");The expect message on
fis the only thing a user sees if this fires. Does it say what they should do, or only what we assumed?Split. The decision in
long_decimalis a pure function now, with its own tests insrc/rust/crates/ck_lex/src/tests.rs.It said what I assumed. Reworded in
src/rust/crates/ck_parser/src/tests.rsso it names the input that broke it, which is what the bug report will need.Feeding a raw .cktest file to the lexer flooded the diagnostics pane with E0001 on every `# page:` / `# expected:` marker. Route .cktest through ck_cktest::parse and load the first page's source; show a muted status line ("page 1/N — path") so it's clear which slice is in the buffer. Multi-page fixtures lose pages 2..N for now — a page selector can wait until something needs it.Why: slice 3 landed `mod Name` end-to-end but parse_source_file then drained tokens unparsed. Records are the smallest locked declaration that doesn't drag in expressions, so this slice builds the scaffolding (top-level loop, brace-balanced sync) plus one real vertical (record). Changes: - `ck_parser`: top-level item loop after parse_module_header; placeholder parsers for every locked-but-unimplemented decl keyword (`fn`, `data`, `const`, `effect`, `trait`, `test`, `actor`, `impl`, nested `mod`) that recognize the keyword and brace-balance to the next sync point. - `ck_parser`: full record-decl production — `record Name <Generics>? <Traits>? { Field* }`, with `Field = Ident : TypeExpr ,?` and minimal `TypeExpr = TypePath GenericArgs?` over `Ident (:: Ident)*` paths. Recovery for missing name / `{` / `}` / `:`. - `ck_lex`: new `Traits` keyword (plural, distinct from singular `Trait` per docs/records.md). 7 new SyntaxKind node variants. - Diagnostic codes E0012..E0022 added to the stable contract; both the parser doc-comment and docs/impl/03-parser.md updated. - 11 new parser unit tests + 9 new `.cktest` fixtures under tests/parse/. Existing `tests/lex/program_*.cktest` re-blessed (CST now shows record structure rather than a flat token list). - Trivia attribution refined: node spans end at their last significant token, so trailing whitespace consistently belongs to the parent regardless of trailing-comma presence. Quality gates: cargo fmt --check clean, cargo clippy --all-targets -D warnings clean, all 127 workspace tests green.Lock the front end's discipline before the next parser slice grows it past the point where backfilling these gates becomes expensive. Architectural gates (ck_driver/tests/architecture.rs): - R3 caps any .rs under crates/*/src or crates/*/tests at 1000 lines. - R4 caps any function body at 80 lines; 2-entry allow-list with justifications (ck_cktest::parse state machine, panes/module_header render egui chain). Stale-allow-list-entry check included. - R1 now also verifies the set of directories under crates/ matches EXPECTED_GRAPH — previously a missing crate (ck_playground) was invisible to R1 and skipped silently by every other rule. - Adds ck_playground to EXPECTED_GRAPH with its 6 workspace deps. ck_lex refactor (lib.rs: 1736 → 984 LoC): - Move the #[cfg(test)] mod tests block into a sibling tests.rs. - Extract consume_one_logical_char and sweep_to_char_close from scan_char_lit (84 → 47 LoC); now under the R4 cap. - Unify push_unterminated and a near-duplicate new push_lit_diag into one widened helper; collapse two more inline span+diag sites (E0001 unknown byte, E0002 unterminated block comment). Lossless-CST contract: - ck_syntax::cst_to_source walks the tree concatenating each token's source slice; round-trip test feeds real lexer output through a synthetic SourceFile node across 8 sources. - ck_parser test runs the same round-trip against the actual parser on 7 sources including error-recovery paths. Pane-state fixes (ck_playground): - CktestRegistry::discover surfaces IO failures as parsed: Err("io: ...") instead of unwrap_or_default → confusing empty parse. - load_into_buffer doc rewritten to match impl (primary page only, matching what analysis runs on). - Buffer::mark_dirty doc rewritten to permit per-keystroke calls; the existing edit loop already does that. 131/131 tests pass (was 127). 0 clippy warnings under all+pedantic with -D warnings.Slice 6 adds `DataDecl` with three variant shapes (bare, positional payload, named-field payload). Named-variant fields reuse `RecordField` so a record body and a named-variant payload project to the same AST. Diagnostics E0023–E0028. Slice 7 adds `FnDecl` covering the signature (generics, params, return, effect clause) plus a brace-balanced `Block` placeholder for the body that the expression slice will refine. Diagnostics E0029–E0036. The production lives in `ck_parser/src/fn_decl.rs` to keep `lib.rs` under the R3 cap. R3 ratchets from 1000 → 850 after extracting `SyntaxKind`/`Token` into `ck_lex/src/syntax_kind.rs` and the parser test module into `ck_parser/src/tests.rs`. New worst case: `ck_lex/src/lib.rs` at 819 lines. Existing `.cktest` fixtures that previously matched the placeholder `fn` parser are updated to the real `FnDecl` shape; `tests/parse/placeholder_decl` switches to `const` (still a placeholder) so the recovery path is exercised without depending on the now-implemented `fn`. New `tests/parser/{data,fn}/` fixtures cover the happy paths and each new error code.