1use std::path::Path;
4
5use rustc_hash::FxHashSet;
6
7use crate::duplicates::DuplicationReport;
8use crate::module_graph::RetainedModuleGraph;
9
10#[expect(
11 unused_imports,
12 reason = "engine owns a copied trace implementation whose internal pub uses serve its tests"
13)]
14#[path = "trace_impl.rs"]
15pub(crate) mod trace_impl;
16
17pub type ClassMemberTrace = fallow_types::trace::ClassMemberTrace;
19pub type CloneTrace = fallow_types::trace::CloneTrace;
21pub type DependencyTrace = fallow_types::trace::DependencyTrace;
23pub type ExportReference = fallow_types::trace::ExportReference;
25pub type ExportTrace = fallow_types::trace::ExportTrace;
27pub type FileTrace = fallow_types::trace::FileTrace;
29pub type ImpactClosureGap = fallow_types::trace::ImpactClosureGap;
31pub type ImpactClosureTrace = fallow_types::trace::ImpactClosureTrace;
33pub type ImportPathHop = fallow_types::trace::ImportPathHop;
35pub type ImportPathTrace = fallow_types::trace::ImportPathTrace;
37pub use trace_impl::ImportPathEndpoint;
38pub type PipelineTimings = fallow_types::trace::PipelineTimings;
40pub type ReExportChain = fallow_types::trace::ReExportChain;
42pub use trace_impl::SemanticClassMethodResolutionError;
43pub type TracedCloneGroup = fallow_types::trace::TracedCloneGroup;
45pub type TracedExport = fallow_types::trace::TracedExport;
47pub type TracedReExport = fallow_types::trace::TracedReExport;
49
50#[must_use]
52pub fn trace_export(
53 graph: &RetainedModuleGraph,
54 root: &Path,
55 file_path: &str,
56 export_name: &str,
57) -> Option<ExportTrace> {
58 trace_impl::trace_export(graph.as_graph(), root, file_path, export_name)
59}
60
61pub fn reconcile_semantic_trace_reachability(
64 graph: &RetainedModuleGraph,
65 root: &Path,
66 target_reachable: bool,
67 trace: &mut fallow_types::semantic::SemanticSymbolTrace,
68) {
69 trace_impl::reconcile_semantic_trace_reachability(
70 graph.as_graph(),
71 root,
72 target_reachable,
73 trace,
74 );
75}
76
77#[must_use]
79pub fn semantic_symbol_for_export(
80 graph: &RetainedModuleGraph,
81 root: &Path,
82 file_path: &str,
83 export_name: &str,
84) -> Option<fallow_types::semantic::SemanticSymbol> {
85 trace_impl::semantic_symbol_for_export(graph.as_graph(), root, file_path, export_name)
86}
87
88#[must_use]
90pub fn semantic_symbol_for_class_member(
91 graph: &RetainedModuleGraph,
92 root: &Path,
93 file_path: &str,
94 member_name: &str,
95) -> Option<fallow_types::semantic::SemanticSymbol> {
96 trace_impl::semantic_symbol_for_class_member(graph.as_graph(), root, file_path, member_name)
97}
98
99pub fn semantic_symbol_for_exact_class_method(
101 graph: &RetainedModuleGraph,
102 root: &Path,
103 file_path: &str,
104 owner_name: &str,
105 member_name: &str,
106) -> Result<fallow_types::semantic::SemanticSymbol, SemanticClassMethodResolutionError> {
107 trace_impl::semantic_symbol_for_exact_class_method(
108 graph.as_graph(),
109 root,
110 file_path,
111 owner_name,
112 member_name,
113 )
114}
115
116#[must_use]
119pub fn trace_class_member(
120 graph: &RetainedModuleGraph,
121 root: &Path,
122 file_path: &str,
123 member_name: &str,
124) -> Option<ClassMemberTrace> {
125 trace_impl::trace_class_member(graph.as_graph(), root, file_path, member_name)
126}
127
128#[must_use]
130pub fn trace_file(graph: &RetainedModuleGraph, root: &Path, file_path: &str) -> Option<FileTrace> {
131 trace_impl::trace_file(graph.as_graph(), root, file_path)
132}
133
134#[must_use]
136#[expect(
137 clippy::implicit_hasher,
138 reason = "fallow standardizes on FxHashSet across the workspace"
139)]
140pub fn trace_dependency(
141 graph: &RetainedModuleGraph,
142 root: &Path,
143 package_name: &str,
144 script_used_packages: &FxHashSet<String>,
145) -> DependencyTrace {
146 trace_impl::trace_dependency(graph.as_graph(), root, package_name, script_used_packages)
147}
148
149#[must_use]
151pub fn trace_clone(
152 report: &DuplicationReport,
153 root: &Path,
154 file_path: &str,
155 line: usize,
156) -> CloneTrace {
157 trace_impl::trace_clone(report, root, file_path, line)
158}
159
160#[must_use]
162pub fn trace_clone_by_fingerprint(
163 report: &DuplicationReport,
164 root: &Path,
165 fingerprint: &str,
166) -> CloneTrace {
167 trace_impl::trace_clone_by_fingerprint(report, root, fingerprint)
168}
169
170#[must_use]
172pub fn trace_impact_closure(
173 graph: &RetainedModuleGraph,
174 root: &Path,
175 file_path: &str,
176) -> Option<ImpactClosureTrace> {
177 trace_impl::trace_impact_closure(graph.as_graph(), root, file_path)
178}
179
180pub fn trace_import_path(
186 graph: &RetainedModuleGraph,
187 root: &Path,
188 from_path: &str,
189 to_path: &str,
190) -> Result<ImportPathTrace, ImportPathEndpoint> {
191 trace_impl::trace_import_path(graph.as_graph(), root, from_path, to_path)
192}
193
194pub fn trace_import_path_with_session(
202 session: &crate::session::AnalysisSession,
203 from_path: &str,
204 to_path: &str,
205) -> crate::EngineResult<Result<ImportPathTrace, ImportPathEndpoint>> {
206 let output = session.analyze_dead_code_with_shared_artifacts(false, true)?;
207 let graph = output
208 .graph
209 .as_ref()
210 .ok_or_else(|| crate::EngineError::new("trace --path requires a retained module graph"))?;
211 Ok(trace_import_path(graph, session.root(), from_path, to_path))
212}