Skip to main content

ryo_source/
lib.rs

1#![warn(missing_docs)]
2//! # ryo-source
3//!
4//! High-speed Rust AST manipulation engine for the RYO (流) project's "Fluid Code" paradigm.
5//!
6//! This crate provides two complementary AST representations optimized for different use cases:
7//! [`RustAST`] for full-fidelity manipulation and [`PureFile`] for thread-safe parallel processing.
8//!
9//! # Core Philosophy: Fluid Code
10//!
11//! Code is not static text—it's a living, flowing structure that can be manipulated,
12//! analyzed, and transformed at high speed. The AST is the "shadow" of source code,
13//! a pure representation that enables:
14//!
15//! - **Instant Analysis**: Query definitions, references, and dependencies in nanoseconds
16//! - **Safe Mutation**: Transform code with type-safe operations
17//! - **Parallel Processing**: Share and analyze code across threads via [`PureFile`]
18//!
19//! # Dual AST Architecture
20//!
21//! ```text
22//!                          Source Code
23//!                      "fn main() { ... }"
24//!                              │
25//!                              ▼
26//!                          syn::parse
27//!                              │
28//!              ┌───────────────┴───────────────┐
29//!              ▼                               ▼
30//!     ┌─────────────────┐           ┌─────────────────┐
31//!     │     RustAST     │           │    PureFile     │
32//!     │  (Full-fidelity)│           │  (Thread-safe)  │
33//!     ├─────────────────┤           ├─────────────────┤
34//!     │ • syn::File     │           │ • Span-free     │
35//!     │ • Complete info │  ToPure   │ • Send + Sync   │
36//!     │ • Span preserve │ ───────▶  │ • Arc-shareable │
37//!     │ • Code gen      │  (~10%)   │ • Serializable  │
38//!     │ • NOT Send/Sync │           │ • Lightweight   │
39//!     └─────────────────┘           └─────────────────┘
40//! ```
41//!
42//! # RustAST: Full-Fidelity AST
43//!
44//! [`RustAST`] wraps `syn::File` to provide high-level operations while preserving
45//! complete syntactic information including spans (source locations).
46//!
47//! ```
48//! use ryo_source::RustAST;
49//!
50//! // Parse source code
51//! let mut ast = RustAST::parse("use std::io;\nfn main() {}").unwrap();
52//!
53//! // Remove unused imports
54//! let removed = ast.remove_unused_imports();
55//! assert_eq!(removed.len(), 1);
56//!
57//! // Generate cleaned code
58//! let code = ast.to_string_pretty();
59//! assert!(!code.contains("use std::io"));
60//! ```
61//!
62//! # PureFile: Thread-Safe AST
63//!
64//! [`PureFile`] strips all `Span` information, creating a pure data structure
65//! that can be safely shared across threads with `Arc`.
66//!
67//! ```
68//! use std::sync::Arc;
69//! use std::thread;
70//! use ryo_source::PureFile;
71//!
72//! // Parse directly to PureFile
73//! let pure = PureFile::from_source("fn foo() {} fn bar() {}").unwrap();
74//!
75//! // Share across threads
76//! let shared = Arc::new(pure);
77//!
78//! let s1 = Arc::clone(&shared);
79//! let h1 = thread::spawn(move || s1.functions().len());
80//!
81//! let s2 = Arc::clone(&shared);
82//! let h2 = thread::spawn(move || s2.find_fn("foo").is_some());
83//!
84//! assert_eq!(h1.join().unwrap(), 2);
85//! assert!(h2.join().unwrap());
86//! ```
87//!
88//! # Operations
89//!
90//! ## Query Operations (Read-only)
91//!
92//! | Operation | Description |
93//! |-----------|-------------|
94//! | [`DefRefs::analyze`] | Find all symbol definitions and references |
95//! | [`DefRefs::find_definition`] | Locate where a symbol is defined |
96//! | [`DefRefs::find_references`] | Find all uses of a symbol |
97//! | [`PureFile::functions`] | Get all functions (thread-safe) |
98//! | [`PureFile::find_fn`] | Find function by name (thread-safe) |
99//!
100//! ## Mutation Operations
101//!
102//! | Operation | Description | Pattern |
103//! |-----------|-------------|---------|
104//! | [`Rename::apply`] | Rename symbols globally | In-place |
105//! | [`Rename::rename_local_in_fn`] | Rename within specific function | In-place |
106//! | [`RemoveUnusedImports::apply`] | Remove unused imports | In-place |
107//! | [`CowMut::rename`] | Copy-on-write rename | Returns new AST |
108//! | [`CowMut::chain_renames`] | Sequential renames | Returns new AST |
109//!
110//! # Copy-on-Write Mutation
111//!
112//! For scenarios requiring multiple independent mutations:
113//!
114//! ```
115//! use ryo_source::{RustAST, CowMut};
116//!
117//! let ast = RustAST::parse("fn foo() { fn bar() {} }").unwrap();
118//!
119//! // Each rename produces an independent copy
120//! let results = CowMut::multi_rename(&ast, &[
121//!     ("foo", "alpha"),
122//!     ("bar", "beta"),
123//! ]);
124//!
125//! // results[0].ast has foo→alpha, bar unchanged
126//! // results[1].ast has bar→beta, foo unchanged
127//! // Original ast is unchanged
128//! assert!(ast.to_string().contains("foo"));
129//! ```
130//!
131//! # Why syn over tree-sitter?
132//!
133//! We chose `syn` for Rust because:
134//!
135//! 1. **Semantic Awareness**: syn understands Rust's semantics, not just syntax
136//! 2. **Type Safety**: Operations are checked at compile time
137//! 3. **Ecosystem Integration**: Works with `quote`, `proc-macro2`, and Rust tooling
138//! 4. **Rust-First Philosophy**: Optimized for Rust's unique features
139//!
140//! [`RustAST`]: crate::RustAST
141//! [`PureFile`]: crate::PureFile
142//! [`DefRefs::analyze`]: crate::DefRefs::analyze
143//! [`DefRefs::find_definition`]: crate::DefRefs::find_definition
144//! [`DefRefs::find_references`]: crate::DefRefs::find_references
145//! [`PureFile::functions`]: crate::pure::PureFile::functions
146//! [`PureFile::find_fn`]: crate::pure::PureFile::find_fn
147//! [`Rename::apply`]: crate::Rename::apply
148//! [`Rename::rename_local_in_fn`]: crate::Rename::rename_local_in_fn
149//! [`RemoveUnusedImports::apply`]: crate::RemoveUnusedImports::apply
150//! [`CowMut::rename`]: crate::CowMut::rename
151//! [`CowMut::chain_renames`]: crate::CowMut::chain_renames
152
153mod ast;
154mod error;
155pub mod generator;
156pub mod ops;
157pub mod parallel;
158pub mod pure;
159mod visitor;
160
161// Test utilities (available with `test-utils` feature or in test builds)
162#[cfg(any(test, feature = "test-utils"))]
163pub mod test_utils;
164
165pub use ast::RustAST;
166pub use error::{SourceError, SourceResult};
167pub use generator::{
168    GeneratedFiles, GeneratedSource, ModuleTree, MultiFileGenerator, SingleFileGenerator,
169    SourceGenerator,
170};
171pub use ops::{
172    DefRefs, Location, RemoveUnusedImports, Rename, RenameResult, Symbol, SymbolKind, SymbolTable,
173};
174pub use parallel::{CowMut, MutResult, SourceParallel};
175pub use pure::{ItemKind, PureFile, ToPure, ToSyn};