1use std::path::Path;
4
5use rustc_hash::FxHashSet;
6
7use crate::duplicates::DuplicationReport;
8use crate::module_graph::RetainedModuleGraph;
9
10#[path = "trace_impl.rs"]
11pub(crate) mod trace_impl;
12
13pub use fallow_types::trace::{
14 ClassMemberTrace, CloneTrace, DependencyTrace, ExportReference, ExportTrace, FileTrace,
15 ImpactClosureGap, ImpactClosureTrace, ImportPathHop, ImportPathTrace, PipelineTimings,
16 ReExportChain, TraceProvenance, TraceSource, TracedCloneGroup, TracedExport, TracedReExport,
17};
18pub use trace_impl::{ImportPathEndpoint, SemanticClassMethodResolutionError};
19
20#[must_use]
22pub fn trace_export(
23 graph: &RetainedModuleGraph,
24 root: &Path,
25 file_path: &str,
26 export_name: &str,
27) -> Option<ExportTrace> {
28 trace_impl::trace_export(graph.as_graph(), root, file_path, export_name)
29}
30
31pub fn reconcile_semantic_trace_reachability(
34 graph: &RetainedModuleGraph,
35 root: &Path,
36 target_reachable: bool,
37 trace: &mut fallow_types::semantic::SemanticSymbolTrace,
38) {
39 trace_impl::reconcile_semantic_trace_reachability(
40 graph.as_graph(),
41 root,
42 target_reachable,
43 trace,
44 );
45}
46
47#[must_use]
49pub fn semantic_symbol_for_export(
50 graph: &RetainedModuleGraph,
51 root: &Path,
52 file_path: &str,
53 export_name: &str,
54) -> Option<fallow_types::semantic::SemanticSymbol> {
55 trace_impl::semantic_symbol_for_export(graph.as_graph(), root, file_path, export_name)
56}
57
58#[must_use]
60pub fn semantic_symbol_for_class_member(
61 graph: &RetainedModuleGraph,
62 root: &Path,
63 file_path: &str,
64 member_name: &str,
65) -> Option<fallow_types::semantic::SemanticSymbol> {
66 trace_impl::semantic_symbol_for_class_member(graph.as_graph(), root, file_path, member_name)
67}
68
69pub fn semantic_symbol_for_exact_class_method(
71 graph: &RetainedModuleGraph,
72 root: &Path,
73 file_path: &str,
74 owner_name: &str,
75 member_name: &str,
76) -> Result<fallow_types::semantic::SemanticSymbol, SemanticClassMethodResolutionError> {
77 trace_impl::semantic_symbol_for_exact_class_method(
78 graph.as_graph(),
79 root,
80 file_path,
81 owner_name,
82 member_name,
83 )
84}
85
86#[must_use]
89pub fn trace_class_member(
90 graph: &RetainedModuleGraph,
91 root: &Path,
92 file_path: &str,
93 member_name: &str,
94) -> Option<ClassMemberTrace> {
95 trace_impl::trace_class_member(graph.as_graph(), root, file_path, member_name)
96}
97
98#[must_use]
100pub fn trace_file(graph: &RetainedModuleGraph, root: &Path, file_path: &str) -> Option<FileTrace> {
101 trace_impl::trace_file(graph.as_graph(), root, file_path)
102}
103
104#[must_use]
112#[expect(
113 clippy::implicit_hasher,
114 reason = "fallow standardizes on FxHashSet across the workspace"
115)]
116pub fn trace_dependency(
117 graph: &RetainedModuleGraph,
118 root: &Path,
119 workspace_roots: &[&Path],
120 ignore_patterns: &fallow_config::IgnorePatternSet,
121 package_name: &str,
122 script_used_packages: &FxHashSet<String>,
123) -> DependencyTrace {
124 trace_impl::trace_dependency(
125 graph.as_graph(),
126 root,
127 workspace_roots,
128 ignore_patterns,
129 package_name,
130 script_used_packages,
131 )
132}
133
134#[must_use]
136pub fn trace_clone(
137 report: &DuplicationReport,
138 root: &Path,
139 file_path: &str,
140 line: usize,
141) -> CloneTrace {
142 trace_impl::trace_clone(report, root, file_path, line)
143}
144
145#[must_use]
147pub fn trace_clone_by_fingerprint(
148 report: &DuplicationReport,
149 root: &Path,
150 fingerprint: &str,
151) -> CloneTrace {
152 trace_impl::trace_clone_by_fingerprint(report, root, fingerprint)
153}
154
155#[must_use]
157pub fn trace_impact_closure(
158 graph: &RetainedModuleGraph,
159 root: &Path,
160 file_path: &str,
161) -> Option<ImpactClosureTrace> {
162 trace_impl::trace_impact_closure(graph.as_graph(), root, file_path)
163}
164
165pub fn trace_import_path(
171 graph: &RetainedModuleGraph,
172 root: &Path,
173 from_path: &str,
174 to_path: &str,
175) -> Result<ImportPathTrace, ImportPathEndpoint> {
176 trace_impl::trace_import_path(graph.as_graph(), root, from_path, to_path, false)
177}
178
179pub fn trace_eager_import_path(
187 graph: &RetainedModuleGraph,
188 root: &Path,
189 from_path: &str,
190 to_path: &str,
191) -> Result<ImportPathTrace, ImportPathEndpoint> {
192 trace_impl::trace_import_path(graph.as_graph(), root, from_path, to_path, true)
193}
194
195pub fn trace_import_path_with_session(
204 session: &crate::session::AnalysisSession,
205 from_path: &str,
206 to_path: &str,
207 eager_only: bool,
208) -> crate::EngineResult<Result<ImportPathTrace, ImportPathEndpoint>> {
209 let output = session.analyze_dead_code_with_shared_artifacts(false, true)?;
210 let graph = output
211 .graph
212 .as_ref()
213 .ok_or_else(|| crate::EngineError::new("trace --path requires a retained module graph"))?;
214 Ok(trace_impl::trace_import_path(
215 graph.as_graph(),
216 session.root(),
217 from_path,
218 to_path,
219 eager_only,
220 ))
221}