ronin_core/lib.rs
1//! `ronin-core` — a lossless, error-tolerant concrete-syntax-tree (CST) engine for
2//! RON (Rusty Object Notation).
3//!
4//! `ronin-core` parses RON source into a CST that preserves **every byte** of the
5//! input (comments, whitespace, trailing commas, struct/variant names, raw
6//! strings, extension attributes) and re-prints an unmodified tree
7//! byte-for-byte. It is the single, portable engine all RONin surfaces build on
8//! (project-instructions §II, "One Core, Many Surfaces").
9//!
10//! # Design invariants
11//!
12//! * **Lossless round-trip (INV-2):** concatenating every token's verbatim text
13//! reproduces the source exactly. See [`parse`] + [`print`].
14//! * **WASM-clean (INV-9):** the only runtime dependency is `rowan` (pure Rust);
15//! no filesystem / UI / async / native dependencies.
16//! * **Library-opaque surface (INV-7):** no `rowan` type appears in the public
17//! API; the CST is exposed through `ronin-core`'s own [`SyntaxNode`] /
18//! [`SyntaxToken`] / [`SyntaxKind`] newtypes so the backing library stays
19//! swappable.
20//! * **Never panics on input (TR-001):** non-UTF-8 input is rejected at the
21//! boundary with a clean [`LexError`]; malformed UTF-8 RON produces a tree
22//! that still covers all input.
23//!
24//! * **Error-tolerant (TR-005, INV-3):** malformed / incomplete input never
25//! panics and never drops bytes — unexpected tokens land in [`SyntaxKind::Error`]
26//! nodes and a structured [`Diagnostic`] (stable [`DiagnosticCode`] +
27//! [`Severity`]) is emitted per recovery point. A configurable nesting-depth
28//! guard ([`ParseOptions`], default [`DEFAULT_MAX_DEPTH`]) prevents stack
29//! overflow on deeply nested input (INV-5).
30//!
31//! # Public API surface (0.x shape-stable, TR-009)
32//!
33//! `ronin-core`'s public surface is **0.x shape-stable**: the *capability areas* —
34//! parse, navigate the CST, read diagnostics, print, and edit — are committed,
35//! while concrete signatures and types may still change in breaking ways within
36//! `0.x` until downstream epics validate the shape. The surface deliberately
37//! exposes **no `rowan` type and no I/O type** (INV-7 / TR-009): the CST is
38//! reachable only through `ronin-core`'s own opaque [`SyntaxNode`] / [`SyntaxToken`]
39//! / [`SyntaxElement`] / [`SyntaxKind`] / [`TextRange`] newtypes and the typed
40//! accessors in [`ast`], so the backing CST library stays swappable. The five
41//! capability areas:
42//!
43//! * **Parse** — [`parse`], [`parse_with_options`], [`parse_bytes`] →
44//! [`CstDocument`].
45//! * **Navigate** — untyped via [`CstDocument::root`] +
46//! [`SyntaxNode`] navigation; typed via [`ast::Document`] and the per-construct
47//! accessors ([`ast::Struct`], [`ast::Map`], [`ast::List`], …).
48//! * **Diagnostics** — [`CstDocument::diagnostics`] → `&[`[`Diagnostic`]`]`.
49//! * **Print** — [`print`] / [`print_node`] (byte-for-byte round-trip).
50//! * **Edit** — [`apply_edit`] with [`EditOperation`] / [`EditTarget`] /
51//! [`EditKind`] / [`TriviaPolicy`] (non-destructive; INV-8).
52//! * **Structural transform** — [`apply_structural`] with [`StructuralOp`] /
53//! [`TransformOutcome`] / [`BlockedReason`] (E008 / ADR-0007): pure CST→CST
54//! named structural ops (insert / remove / reorder / set-value / rename a
55//! field-or-element, enum-variant swap, add-field-across-rows) composed over
56//! [`apply_edit`] — byte-for-byte lossless on untouched regions (FR-013),
57//! WASM-clean and reusable by a future LSP/web surface.
58//! * **Undo/redo** — [`UndoStack`] / [`UndoEntry`] (E007): a bounded,
59//! WASM-clean CST + text + cursor history with exact-prior-byte restore;
60//! reusable across surfaces and adds no filesystem/native dependency (TR-014).
61//! This is the public undo surface the downstream editing epics import — E005
62//! (smart authoring) and E008 (structural / table editing) edit against it via
63//! this re-export (TR-013); see the [`undo`] module docs for the reuse contract.
64//!
65//! # Status
66//!
67//! This delivers the full E001 engine: OBJ1 (lossless parse + round-trip),
68//! OBJ2 (error-tolerant parsing + diagnostics), OBJ3 (WASM-clean 0.x
69//! shape-stable public API + wasm32 build gate), and OBJ4 (typed navigation +
70//! non-destructive edit primitives).
71//!
72//! # WASM-clean build gate (TR-007 / INV-9)
73//!
74//! `ronin-core`'s only runtime dependency is `rowan` (pure Rust); the crate carries
75//! no filesystem / UI / async-runtime / native dependency, so it builds for
76//! `wasm32-unknown-unknown`:
77//!
78//! ```text
79//! rustup target add wasm32-unknown-unknown
80//! cargo build -p ronin-core --target wasm32-unknown-unknown # MUST succeed
81//! ```
82//!
83//! This build is the proof of WASM-cleanliness; CI wires it as a mandatory gate
84//! (owned by E002).
85//!
86//! # Example
87//!
88//! ```
89//! let src = "Foo(x: 1, y: 2.0) // keep me\n";
90//! let doc = ronin_core::parse(src);
91//! assert_eq!(ronin_core::print(&doc), src); // byte-for-byte round-trip
92//! ```
93
94#![forbid(unsafe_code)]
95#![warn(missing_docs)]
96
97pub mod completion;
98pub mod diagnostics;
99pub mod edit;
100pub mod formatter;
101pub mod lexer;
102pub mod parser;
103pub mod printer;
104pub mod syntax;
105pub mod transform;
106pub mod undo;
107
108pub use completion::{
109 completion_context, completions, CompletionContext, CompletionItem, CompletionKind,
110 PositionKind,
111};
112pub use diagnostics::{Diagnostic, DiagnosticCode, Severity};
113pub use edit::{apply_edit, EditError, EditKind, EditOperation, EditTarget, TriviaPolicy};
114pub use formatter::{format, format_node, BlankLinePolicy, FormatConfig, FormatResult};
115pub use lexer::{validate_utf8, LexError};
116pub use parser::{
117 parse, parse_bytes, parse_with_options, CstDocument, ParseOptions, DEFAULT_MAX_DEPTH,
118};
119pub use printer::{print, print_node};
120pub use syntax::{SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange};
121pub use transform::{apply_structural, BlockedReason, ParentRef, StructuralOp, TransformOutcome};
122pub use undo::{UndoCap, UndoEntry, UndoStack};
123
124/// Typed accessors over the CST (TR-010): navigate RON constructs by name
125/// (`Struct::fields()`, `Map::entries()`, …) through `ronin-core` types only.
126pub use syntax::ast;