pub struct Graph { /* private fields */ }Expand description
Main call graph structure containing nodes and edges
Implementations§
Source§impl CallGraph
impl CallGraph
Sourcepub fn entry_point_criticality_factor(is_entry_point: bool) -> f64
pub fn entry_point_criticality_factor(is_entry_point: bool) -> f64
Pure function to calculate entry point criticality factor
Sourcepub fn dependency_count_criticality_factor(dependency_count: usize) -> f64
pub fn dependency_count_criticality_factor(dependency_count: usize) -> f64
Pure function to calculate dependency count criticality factor
Sourcepub fn has_entry_point_caller<F>(
callers: &[FunctionId],
is_entry_point_fn: F,
) -> bool
pub fn has_entry_point_caller<F>( callers: &[FunctionId], is_entry_point_fn: F, ) -> bool
Pure function to check if any caller is an entry point
Sourcepub fn entry_point_caller_criticality_factor(
has_entry_point_caller: bool,
) -> f64
pub fn entry_point_caller_criticality_factor( has_entry_point_caller: bool, ) -> f64
Pure function to calculate entry point caller criticality factor
pub fn calculate_criticality(&self, func_id: &FunctionId) -> f64
Source§impl CallGraph
impl CallGraph
Sourcepub fn resolve_cross_file_calls(&mut self)
pub fn resolve_cross_file_calls(&mut self)
Resolve cross-file function calls using parallel processing
This method processes unresolved calls in two phases:
- Parallel Resolution: Uses Rayon to resolve calls concurrently across multiple CPU cores, leveraging the pure functional nature of the resolution logic.
- Sequential Updates: Applies all resolutions to the graph sequentially to maintain data structure consistency.
§Performance
Expected speedup: 10-15% on multi-core systems (4-8 cores). Scales linearly with number of unresolved calls and available cores.
§Memory Usage
Memory overhead is minimal and predictable:
- Stores resolved call pairs in a
Vec<(FunctionCall, FunctionId)> - For typical codebases with 1000-2000 unresolved calls:
- Each tuple: ~200-300 bytes (two FunctionId + one FunctionCall)
- Total overhead: ~200KB-600KB for 1000-2000 resolutions
- Peak memory during phase 1 (parallel resolution)
- Memory freed after phase 2 (sequential updates)
- Well under the 10MB budget specified in requirements
§Thread Safety
The resolution phase is thread-safe because:
- Resolution logic is pure (no side effects)
- All input data is immutable during resolution
- No shared mutable state between threads
Sourcepub fn resolve_cross_file_calls_sequential(&mut self)
pub fn resolve_cross_file_calls_sequential(&mut self)
Sequential resolution for testing and benchmarking
This method provides a non-parallel baseline for comparison with the
parallel resolve_cross_file_calls() method. It’s primarily used for:
- Verifying correctness of parallel implementation (determinism tests)
- Performance benchmarking and comparison
- Debugging and development
In production, prefer resolve_cross_file_calls() for better performance.
Source§impl CallGraph
impl CallGraph
pub fn merge(&mut self, other: CallGraph)
pub fn add_function( &mut self, id: FunctionId, is_entry_point: bool, is_test: bool, complexity: u32, lines: usize, )
pub fn add_call(&mut self, call: FunctionCall)
pub fn add_call_parts( &mut self, caller: FunctionId, callee: FunctionId, call_type: CallType, )
pub fn get_callees(&self, func_id: &FunctionId) -> Vec<FunctionId>
pub fn get_callees_exact(&self, func_id: &FunctionId) -> Vec<FunctionId>
pub fn node_count(&self) -> usize
pub fn get_callers(&self, func_id: &FunctionId) -> Vec<FunctionId>
pub fn get_callers_exact(&self, func_id: &FunctionId) -> Vec<FunctionId>
pub fn get_dependency_count(&self, func_id: &FunctionId) -> usize
Sourcepub fn get_all_functions(&self) -> impl Iterator<Item = &FunctionId>
pub fn get_all_functions(&self) -> impl Iterator<Item = &FunctionId>
Get all functions in the graph
Sourcepub fn get_function_info(
&self,
func_id: &FunctionId,
) -> Option<(bool, bool, u32, usize)>
pub fn get_function_info( &self, func_id: &FunctionId, ) -> Option<(bool, bool, u32, usize)>
Get function info
Sourcepub fn mark_as_trait_dispatch(&mut self, func_id: FunctionId)
pub fn mark_as_trait_dispatch(&mut self, func_id: FunctionId)
Mark a function as being reachable through trait dispatch This helps reduce false positives in dead code detection
pub fn is_entry_point(&self, func_id: &FunctionId) -> bool
pub fn is_test_function(&self, func_id: &FunctionId) -> bool
pub fn has_test_function_named(&self, name: &str) -> bool
Sourcepub fn add_edge_by_name(&mut self, from: String, to: String, file: PathBuf)
pub fn add_edge_by_name(&mut self, from: String, to: String, file: PathBuf)
Add an edge between two functions by name (used by critical path analyzer)
Sourcepub fn get_callees_by_name(&self, function: &str) -> Vec<String>
pub fn get_callees_by_name(&self, function: &str) -> Vec<String>
Get callees by function name (returns function names)
Sourcepub fn get_callers_by_name(&self, function: &str) -> Vec<String>
pub fn get_callers_by_name(&self, function: &str) -> Vec<String>
Get callers by function name (returns function names)
pub fn get_transitive_callees( &self, func_id: &FunctionId, max_depth: usize, ) -> HashSet<FunctionId>
pub fn get_transitive_callers( &self, func_id: &FunctionId, max_depth: usize, ) -> HashSet<FunctionId>
pub fn find_entry_points(&self) -> Vec<FunctionId>
pub fn find_all_functions(&self) -> Vec<FunctionId>
Sourcepub fn get_functions_by_file(&self, file: &PathBuf) -> Vec<FunctionId>
pub fn get_functions_by_file(&self, file: &PathBuf) -> Vec<FunctionId>
Get all functions in a specific file
Sourcepub fn get_functions_by_name(&self, name: &str) -> Vec<FunctionId>
pub fn get_functions_by_name(&self, name: &str) -> Vec<FunctionId>
Get all functions with a specific name
Sourcepub fn get_functions_with_no_callers(&self) -> Vec<FunctionId>
pub fn get_functions_with_no_callers(&self) -> Vec<FunctionId>
Get all functions that have no callers
pub fn get_function_calls(&self, func_id: &FunctionId) -> Vec<FunctionCall>
Sourcepub fn get_all_calls(&self) -> Vec<FunctionCall>
pub fn get_all_calls(&self) -> Vec<FunctionCall>
Get all function calls in the graph (for testing and debugging)
pub fn is_empty(&self) -> bool
Sourcepub fn find_function(&self, query: &FunctionId) -> Option<FunctionId>
pub fn find_function(&self, query: &FunctionId) -> Option<FunctionId>
Find a function using fallback matching strategies Tries exact match first, then fuzzy match, then name-only match
Sourcepub fn find_function_at_location(
&self,
file: &PathBuf,
line: usize,
) -> Option<FunctionId>
pub fn find_function_at_location( &self, file: &PathBuf, line: usize, ) -> Option<FunctionId>
Find a function at a specific file and line location Returns the function that contains the given line
Sourcepub fn functions_in_file<'a>(
nodes: &'a HashMap<FunctionId, FunctionNode>,
file: &PathBuf,
) -> Vec<&'a FunctionId>
pub fn functions_in_file<'a>( nodes: &'a HashMap<FunctionId, FunctionNode>, file: &PathBuf, ) -> Vec<&'a FunctionId>
Pure function to filter functions by file
Sourcepub fn find_best_line_match(
functions: &[&FunctionId],
target_line: usize,
) -> Option<FunctionId>
pub fn find_best_line_match( functions: &[&FunctionId], target_line: usize, ) -> Option<FunctionId>
Pure function to find the best matching function by line proximity
Sourcepub fn is_recursive(&self, func_id: &FunctionId) -> bool
pub fn is_recursive(&self, func_id: &FunctionId) -> bool
Check if a function is recursive (calls itself directly or through a cycle)
Uses iterative DFS with explicit stack to avoid stack overflow on large graphs.
Sourcepub fn topological_sort(&self) -> Result<Vec<FunctionId>, String>
pub fn topological_sort(&self) -> Result<Vec<FunctionId>, String>
Topological sort of functions for bottom-up analysis Returns functions in dependency order (leaves first, roots last)
Uses iterative DFS with explicit stack to avoid stack overflow on large graphs.
Source§impl CallGraph
impl CallGraph
Sourcepub fn meets_delegation_criteria(
orchestrator_complexity: u32,
callee_count: usize,
) -> bool
pub fn meets_delegation_criteria( orchestrator_complexity: u32, callee_count: usize, ) -> bool
Pure function to check if delegation pattern criteria are met
Sourcepub fn calculate_average_callee_complexity(
callees: &[FunctionId],
nodes: &HashMap<FunctionId, FunctionNode>,
) -> f64
pub fn calculate_average_callee_complexity( callees: &[FunctionId], nodes: &HashMap<FunctionId, FunctionNode>, ) -> f64
Pure function to calculate average complexity of callees
Sourcepub fn indicates_delegation(
orchestrator_complexity: u32,
avg_callee_complexity: f64,
) -> bool
pub fn indicates_delegation( orchestrator_complexity: u32, avg_callee_complexity: f64, ) -> bool
Pure function to determine if complexity indicates delegation
pub fn detect_delegation_pattern(&self, func_id: &FunctionId) -> bool
Source§impl CallGraph
impl CallGraph
pub fn find_test_functions(&self) -> Vec<FunctionId>
Sourcepub fn is_test_helper(&self, func_id: &FunctionId) -> bool
pub fn is_test_helper(&self, func_id: &FunctionId) -> bool
Check if a function is only called by test functions (test helper) Returns true if:
- The function has at least one caller
- All callers are test functions
Sourcepub fn is_production_entry_point(
node: &FunctionNode,
callers: &[FunctionId],
) -> bool
pub fn is_production_entry_point( node: &FunctionNode, callers: &[FunctionId], ) -> bool
Pure function to check if a node is a production entry point
Sourcepub fn find_test_only_functions(&self) -> HashSet<FunctionId>
pub fn find_test_only_functions(&self) -> HashSet<FunctionId>
Identify functions that are only reachable from test functions These are test infrastructure functions (mocks, helpers, fixtures, etc.)
Trait Implementations§
Source§impl<'de> Deserialize<'de> for CallGraph
impl<'de> Deserialize<'de> for CallGraph
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl Freeze for CallGraph
impl RefUnwindSafe for CallGraph
impl Send for CallGraph
impl Sync for CallGraph
impl Unpin for CallGraph
impl UnsafeUnpin for CallGraph
impl UnwindSafe for CallGraph
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> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> EnsureExt<T> for T
impl<T> EnsureExt<T> for T
Source§fn ensure<P, E>(self, predicate: P, error: E) -> Validation<T, NonEmptyVec<E>>where
P: Predicate<T>,
fn ensure<P, E>(self, predicate: P, error: E) -> Validation<T, NonEmptyVec<E>>where
P: Predicate<T>,
Source§fn ensure_with<P, E, F>(
self,
predicate: P,
error_fn: F,
) -> Validation<T, NonEmptyVec<E>>
fn ensure_with<P, E, F>( self, predicate: P, error_fn: F, ) -> Validation<T, NonEmptyVec<E>>
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
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