pub struct AnalysisContext {
pub workspace_root: Arc<Path>,
pub registry: SymbolRegistry,
pub code_graph: CodeGraphV2,
pub typeflow_graph: TypeFlowGraphV2,
pub dataflow_graph: DataFlowGraphV2,
pub detail_store: DetailStore,
pub ast_registry: ASTRegistry,
pub files: ImHashMap<WorkspaceFilePath, Arc<PureFile>>,
pub original: HashMap<WorkspaceFilePath, String>,
pub use_resolver: UseResolver,
pub derive_index: DeriveIndex,
}Expand description
Unified context containing all analysis structures.
This is the recommended way to initialize code analysis from source files. Executor receives this context and works with SymbolId-based Intent.
§Fork-on-Write Pattern
AnalysisContext supports fork-on-write for speculative execution:
let forked = ctx.fork(); // O(log n) structural sharing
// Mutations on forked don't affect originalUses im::HashMap<FileId, Arc<PureFile>> for efficient cloning:
- Clone is O(log n) via structural sharing
- Modifications only copy affected nodes
- Arc ensures PureFile is shared until modified
See docs/parallel-execution-design.md for design details.
Fields§
§workspace_root: Arc<Path>Workspace root path (shared via Arc for efficient cloning).
registry: SymbolRegistrySymbol registry for path ↔ SymbolId mapping.
code_graph: CodeGraphV2Code graph for symbol relationships.
typeflow_graph: TypeFlowGraphV2Type flow graph for type relationships.
dataflow_graph: DataFlowGraphV2Data flow graph for variable-level flow analysis.
detail_store: DetailStoreCached symbol details for O(1) access.
ast_registry: ASTRegistryComplete AST storage for v2 mutation engine.
Stores full PureItem per symbol, replacing file-based mutation approach. Used by ASTMutationEngine for registry-only execution.
files: ImHashMap<WorkspaceFilePath, Arc<PureFile>>Source files with structural sharing for O(log n) fork. Key: WorkspaceFilePath (self-contained, no external registry needed)
original: HashMap<WorkspaceFilePath, String>Original source strings for diff generation.
use_resolver: UseResolverUse statement resolver for cross-crate symbol resolution.
derive_index: DeriveIndexDerive index for fast derive trait validation (O(1) lookup).
Implementations§
Source§impl AnalysisContext
impl AnalysisContext
Sourcepub fn from_workspace_root(path: impl AsRef<Path>) -> Result<Self, ContextError>
pub fn from_workspace_root(path: impl AsRef<Path>) -> Result<Self, ContextError>
Create context from workspace root path.
This is the recommended API for workspace-aware analysis.
Automatically discovers and loads all Rust files in the workspace,
using CargoMetadataProvider for accurate crate name resolution.
Also loads UUID mappings from .ryo/uuid-mapping.json if present.
§Example
use ryo_analysis::AnalysisContext;
let ctx = AnalysisContext::from_workspace_root("/path/to/project")?;
let symbol = ctx.registry.lookup(&path);Sourcepub fn from_workspace_root_parallel(
path: impl AsRef<Path>,
) -> Result<Self, ContextError>
pub fn from_workspace_root_parallel( path: impl AsRef<Path>, ) -> Result<Self, ContextError>
Create context from workspace root with parallel processing.
Sourcepub fn from_im_files(files: ImHashMap<WorkspaceFilePath, Arc<PureFile>>) -> Self
pub fn from_im_files(files: ImHashMap<WorkspaceFilePath, Arc<PureFile>>) -> Self
Create a minimal context from WorkspaceFilePath-keyed files.
This is useful for speculative execution where you want to work with a snapshot of files without full re-analysis.
Note: This creates a partial context with empty symbol registry and code graph. Suitable for mutation execution but not for symbol-based queries.
§Panics
Panics if files is empty (cannot infer workspace_root).
Sourcepub fn registry(&self) -> &SymbolRegistry
pub fn registry(&self) -> &SymbolRegistry
Get the registry.
Sourcepub fn registry_mut(&mut self) -> &mut SymbolRegistry
pub fn registry_mut(&mut self) -> &mut SymbolRegistry
Get mutable registry.
Sourcepub fn code_graph(&self) -> &CodeGraphV2
pub fn code_graph(&self) -> &CodeGraphV2
Get the code graph.
Sourcepub fn code_graph_mut(&mut self) -> &mut CodeGraphV2
pub fn code_graph_mut(&mut self) -> &mut CodeGraphV2
Get mutable code graph.
Sourcepub fn typeflow_graph(&self) -> &TypeFlowGraphV2
pub fn typeflow_graph(&self) -> &TypeFlowGraphV2
Get the TypeFlow graph.
Sourcepub fn workspace_root(&self) -> &Path
pub fn workspace_root(&self) -> &Path
Get the workspace root path.
Sourcepub fn file(&self, path: &WorkspaceFilePath) -> Option<&PureFile>
pub fn file(&self, path: &WorkspaceFilePath) -> Option<&PureFile>
Get a file by path.
Sourcepub fn file_mut(&mut self, path: &WorkspaceFilePath) -> Option<&mut PureFile>
pub fn file_mut(&mut self, path: &WorkspaceFilePath) -> Option<&mut PureFile>
Get mutable file by path (copy-on-write).
Uses Arc::make_mut for copy-on-write semantics:
- If Arc is uniquely owned, returns mutable reference directly
- If Arc is shared, clones the PureFile first
Sourcepub fn files_mut(&mut self) -> &mut ImHashMap<WorkspaceFilePath, Arc<PureFile>>
pub fn files_mut(&mut self) -> &mut ImHashMap<WorkspaceFilePath, Arc<PureFile>>
Get mutable files map.
Sourcepub fn original(&self, path: &WorkspaceFilePath) -> Option<&String>
pub fn original(&self, path: &WorkspaceFilePath) -> Option<&String>
Get original source for a file (for diff generation).
Sourcepub fn file_count(&self) -> usize
pub fn file_count(&self) -> usize
Get file count.
Sourcepub fn detail_store(&self) -> &DetailStore
pub fn detail_store(&self) -> &DetailStore
Get the detail store.
Sourcepub fn detail_store_mut(&mut self) -> &mut DetailStore
pub fn detail_store_mut(&mut self) -> &mut DetailStore
Get mutable detail store.
Sourcepub fn commit_changes(&mut self, updates: &RegistryUpdateBatch)
pub fn commit_changes(&mut self, updates: &RegistryUpdateBatch)
Commit changes at Tick boundary.
Applies registry updates and incrementally updates CodeGraphV2 indices. This is O(k) where k is the number of updates, not O(n) for full rebuild.
§Arguments
updates- Registry updates collected during this Tick
§Performance
| Operation | Before (rebuild_indices) | After (incremental) |
|---|---|---|
| 10 updates, 10k symbols | O(10k) | O(10) |
| 100 updates, 10k symbols | O(10k) | O(100) |
Sourcepub fn rebuild_edges_for_files(&mut self, file_paths: &[WorkspaceFilePath])
pub fn rebuild_edges_for_files(&mut self, file_paths: &[WorkspaceFilePath])
Rebuild edges for symbols in the specified files.
This is used for incremental updates after mutation:
- Clear outgoing edges for all symbols in the files
- Rebuild edges from the updated AST
§Performance
O(k * m) where k is the number of files and m is symbols per file. Much faster than full rebuild for small changes.
Sourcepub fn rebuild_edges_for_symbols(&mut self, affected_ids: &[SymbolId])
pub fn rebuild_edges_for_symbols(&mut self, affected_ids: &[SymbolId])
Rebuild code_graph edges for the given symbol IDs (Phase 2: Symbol-based).
This method rebuilds edges directly from ASTRegistry without file I/O:
- Clear outgoing edges for affected symbols
- Get AST from ASTRegistry for each symbol
- Rebuild edges from the AST
§Performance
O(S) where S is the number of affected symbols. Much faster than file-based updates for targeted changes.
Sourcepub fn get_symbols_in_files(
&self,
file_paths: &[WorkspaceFilePath],
) -> Vec<SymbolId>
pub fn get_symbols_in_files( &self, file_paths: &[WorkspaceFilePath], ) -> Vec<SymbolId>
Get all symbols defined in the specified files.
Uses registry.span() to determine which file each symbol belongs to.
§Returns
Vector of SymbolIds for symbols defined in the given files.
Sourcepub fn rebuild_after_mutation(&mut self, modified_files: &[WorkspaceFilePath])
pub fn rebuild_after_mutation(&mut self, modified_files: &[WorkspaceFilePath])
Rebuild all analysis graphs after mutation execution.
Converts file paths to symbol IDs and delegates to the Symbol-based rebuild path. All graphs are rebuilt from ASTRegistry (no file I/O).
Note: ast_registry and files are already updated by execute_v2.
Sourcepub fn rebuild_after_mutation_by_symbols(&mut self, affected_ids: &[SymbolId])
pub fn rebuild_after_mutation_by_symbols(&mut self, affected_ids: &[SymbolId])
Rebuild analysis graphs for the given affected symbol IDs.
This is the Symbol-based update path (Phase 2) that rebuilds all graphs directly from ASTRegistry, avoiding file reconstruction overhead.
All graphs are now built from ASTRegistry (no file I/O):
- code_graph: Incremental edge rebuild for affected symbols
- typeflow_graph: Full rebuild from ASTRegistry
- dataflow_graph: Incremental rebuild for affected symbols
- detail_store: Incremental rebuild for affected symbols
§Performance
- code_graph: O(S) where S is affected symbols
- typeflow_graph: O(N) where N is total symbols (full rebuild, but no file I/O)
- dataflow_graph: O(S) incremental
- detail_store: O(S) incremental
Sourcepub fn fork(&self) -> ExecutionContext<'_>
pub fn fork(&self) -> ExecutionContext<'_>
Create an ExecutionContext for parallel Mutation execution.
Registry and Graph are shared as read-only references.
Files use O(log n) structural sharing via im::HashMap.
§Design
During parallel Mutation execution:
- Registry: Read-only, shared across all Mutations
- Graph: Read-only, shared across all Mutations
- Files: O(log n) clone via structural sharing, copy-on-write
- Changes to Registry are collected as
RegistryUpdatedeltas
§Performance
Clone is O(log n) due to im::HashMap structural sharing.
Modifications use copy-on-write via Arc::make_mut.
§Example
let ctx = AnalysisContext::from_path_files(files, "my_crate");
let mut exec_ctx = ctx.fork(); // O(log n) clone
// Modify files in exec_ctx - original is unchanged
exec_ctx.file_mut(&path).unwrap().modify(...); // Copy-on-write
// Registry is read-only
let symbol = exec_ctx.registry.lookup(&path);Sourcepub fn fork_rebuild(&self) -> Self
pub fn fork_rebuild(&self) -> Self
Create a new AnalysisContext with files cloned.
Registry, graph, and detail store are rebuilt from the cloned files. Use this when you need a completely independent context with mutable Registry access.
§Note
This is more expensive than fork() as it rebuilds all indices.
Prefer fork() for parallel Mutation execution.
§Panics
Panics if the current context has zero files (cannot infer crate_name during rebuild) or if any file fails source generation during rebuild. Either situation indicates a corrupted internal state that should not occur in normal use.
Sourcepub fn fork_clone(&self) -> Self
pub fn fork_clone(&self) -> Self
Create an owned clone of AnalysisContext without rebuilding.
This is much faster than fork_rebuild() because it clones the
existing graph structures directly instead of rebuilding from files.
§Performance
- Files: O(log n) structural sharing via
im::HashMap - All other fields: Direct Clone (no rebuild)
Expected: < 1ms vs ~100ms for fork_rebuild()
§Use Case
Use this for precheck scenarios where you need a mutable owned context but don’t need to rebuild graphs from scratch.
Sourcepub fn symbol_count(&self) -> usize
pub fn symbol_count(&self) -> usize
Get the number of registered symbols.
Sourcepub fn snapshot_symbols(&self, symbols: &[SymbolId]) -> ContextSnapshot
pub fn snapshot_symbols(&self, symbols: &[SymbolId]) -> ContextSnapshot
Take a snapshot of specified symbols before mutation.
This enables efficient speculative execution by only saving the symbols that will be modified, rather than cloning the entire context.
§Usage
let snapshot = ctx.snapshot_symbols(&affected_ids);
// ... apply mutation ...
ctx.rollback(snapshot, &affected_ids);Sourcepub fn rollback(&mut self, snapshot: ContextSnapshot, affected_ids: &[SymbolId])
pub fn rollback(&mut self, snapshot: ContextSnapshot, affected_ids: &[SymbolId])
Rollback to a previous snapshot.
Restores AST items and rebuilds analysis graphs for affected symbols. This is more efficient than fork_clone when processing many mutations sequentially on the same context.
Auto Trait Implementations§
impl Freeze for AnalysisContext
impl RefUnwindSafe for AnalysisContext
impl Send for AnalysisContext
impl Sync for AnalysisContext
impl Unpin for AnalysisContext
impl UnsafeUnpin for AnalysisContext
impl UnwindSafe for AnalysisContext
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more