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]
106#[expect(
107 clippy::implicit_hasher,
108 reason = "fallow standardizes on FxHashSet across the workspace"
109)]
110pub fn trace_dependency(
111 graph: &RetainedModuleGraph,
112 root: &Path,
113 package_name: &str,
114 script_used_packages: &FxHashSet<String>,
115) -> DependencyTrace {
116 trace_impl::trace_dependency(graph.as_graph(), root, package_name, script_used_packages)
117}
118
119#[must_use]
121pub fn trace_clone(
122 report: &DuplicationReport,
123 root: &Path,
124 file_path: &str,
125 line: usize,
126) -> CloneTrace {
127 trace_impl::trace_clone(report, root, file_path, line)
128}
129
130#[must_use]
132pub fn trace_clone_by_fingerprint(
133 report: &DuplicationReport,
134 root: &Path,
135 fingerprint: &str,
136) -> CloneTrace {
137 trace_impl::trace_clone_by_fingerprint(report, root, fingerprint)
138}
139
140#[must_use]
142pub fn trace_impact_closure(
143 graph: &RetainedModuleGraph,
144 root: &Path,
145 file_path: &str,
146) -> Option<ImpactClosureTrace> {
147 trace_impl::trace_impact_closure(graph.as_graph(), root, file_path)
148}
149
150pub fn trace_import_path(
156 graph: &RetainedModuleGraph,
157 root: &Path,
158 from_path: &str,
159 to_path: &str,
160) -> Result<ImportPathTrace, ImportPathEndpoint> {
161 trace_impl::trace_import_path(graph.as_graph(), root, from_path, to_path, false)
162}
163
164pub fn trace_eager_import_path(
172 graph: &RetainedModuleGraph,
173 root: &Path,
174 from_path: &str,
175 to_path: &str,
176) -> Result<ImportPathTrace, ImportPathEndpoint> {
177 trace_impl::trace_import_path(graph.as_graph(), root, from_path, to_path, true)
178}
179
180pub fn trace_import_path_with_session(
189 session: &crate::session::AnalysisSession,
190 from_path: &str,
191 to_path: &str,
192 eager_only: bool,
193) -> crate::EngineResult<Result<ImportPathTrace, ImportPathEndpoint>> {
194 let output = session.analyze_dead_code_with_shared_artifacts(false, true)?;
195 let graph = output
196 .graph
197 .as_ref()
198 .ok_or_else(|| crate::EngineError::new("trace --path requires a retained module graph"))?;
199 Ok(trace_impl::trace_import_path(
200 graph.as_graph(),
201 session.root(),
202 from_path,
203 to_path,
204 eager_only,
205 ))
206}