fallow_types/trace.rs
1//! Shared trace output contracts for analysis and integration surfaces.
2
3use std::path::PathBuf;
4
5use serde::Serialize;
6
7use crate::duplicates::{CloneInstance, RefactoringSuggestion};
8use crate::serde_path;
9
10/// Result of tracing an export: why it is considered used or unused.
11#[derive(Debug, Serialize)]
12pub struct ExportTrace {
13 /// The file containing the export.
14 #[serde(serialize_with = "serde_path::serialize")]
15 pub file: PathBuf,
16 /// The export name being traced.
17 pub export_name: String,
18 /// Whether the file is reachable from an entry point.
19 pub file_reachable: bool,
20 /// Whether the file is an entry point.
21 pub is_entry_point: bool,
22 /// Whether the export is considered used.
23 pub is_used: bool,
24 /// Files that reference this export directly.
25 pub direct_references: Vec<ExportReference>,
26 /// Re-export chains that pass through this export.
27 pub re_export_chains: Vec<ReExportChain>,
28 /// Human-readable reason summary.
29 pub reason: String,
30}
31
32/// A direct reference to an export.
33#[derive(Debug, Serialize)]
34pub struct ExportReference {
35 /// File that contains the reference.
36 #[serde(serialize_with = "serde_path::serialize")]
37 pub from_file: PathBuf,
38 /// Reference kind, such as named import, default import, or re-export.
39 pub kind: String,
40}
41
42/// A re-export chain showing how an export is propagated.
43#[derive(Debug, Serialize)]
44pub struct ReExportChain {
45 /// The barrel file that re-exports this symbol.
46 #[serde(serialize_with = "serde_path::serialize")]
47 pub barrel_file: PathBuf,
48 /// The name it is re-exported as.
49 pub exported_as: String,
50 /// Number of references on the barrel's re-exported symbol.
51 pub reference_count: usize,
52}
53
54/// Result of tracing all edges for a file.
55#[derive(Debug, Serialize)]
56pub struct FileTrace {
57 /// The traced file.
58 #[serde(serialize_with = "serde_path::serialize")]
59 pub file: PathBuf,
60 /// Whether this file is reachable from entry points.
61 pub is_reachable: bool,
62 /// Whether this file is an entry point.
63 pub is_entry_point: bool,
64 /// Exports declared by this file.
65 pub exports: Vec<TracedExport>,
66 /// Files that this file imports from.
67 #[serde(serialize_with = "serde_path::serialize_vec")]
68 pub imports_from: Vec<PathBuf>,
69 /// Files that import from this file.
70 #[serde(serialize_with = "serde_path::serialize_vec")]
71 pub imported_by: Vec<PathBuf>,
72 /// Re-exports declared by this file.
73 pub re_exports: Vec<TracedReExport>,
74}
75
76/// An export with usage information.
77#[derive(Debug, Serialize)]
78pub struct TracedExport {
79 /// Export name.
80 pub name: String,
81 /// Whether the export is type-only.
82 pub is_type_only: bool,
83 /// Number of references to this export.
84 pub reference_count: usize,
85 /// Files that reference this export.
86 pub referenced_by: Vec<ExportReference>,
87}
88
89/// A re-export with source information.
90#[derive(Debug, Serialize)]
91pub struct TracedReExport {
92 /// Source file being re-exported from.
93 #[serde(serialize_with = "serde_path::serialize")]
94 pub source_file: PathBuf,
95 /// Imported symbol name.
96 pub imported_name: String,
97 /// Exported symbol name.
98 pub exported_name: String,
99}
100
101/// Result of tracing a dependency: where it is used.
102#[derive(Debug, Serialize)]
103pub struct DependencyTrace {
104 /// The dependency name being traced.
105 pub package_name: String,
106 /// Files that import this dependency.
107 #[serde(serialize_with = "serde_path::serialize_vec")]
108 pub imported_by: Vec<PathBuf>,
109 /// Files that import this dependency with type-only imports.
110 #[serde(serialize_with = "serde_path::serialize_vec")]
111 pub type_only_imported_by: Vec<PathBuf>,
112 /// Whether the dependency is invoked from package.json scripts or CI configs.
113 pub used_in_scripts: bool,
114 /// Whether the dependency is used at all.
115 pub is_used: bool,
116 /// Total import count.
117 pub import_count: usize,
118}
119
120/// Pipeline performance timings.
121#[derive(Debug, Clone, Serialize)]
122pub struct PipelineTimings {
123 /// Time spent discovering files.
124 pub discover_files_ms: f64,
125 /// Number of discovered files.
126 pub file_count: usize,
127 /// Time spent discovering workspaces.
128 pub workspaces_ms: f64,
129 /// Number of discovered workspaces.
130 pub workspace_count: usize,
131 /// Time spent running plugin discovery.
132 pub plugins_ms: f64,
133 /// Time spent analyzing package scripts and CI configuration.
134 pub script_analysis_ms: f64,
135 /// Wall-clock time spent parsing and extracting modules.
136 pub parse_extract_ms: f64,
137 /// Summed parser CPU time across workers.
138 pub parse_cpu_ms: f64,
139 /// Number of extracted modules.
140 pub module_count: usize,
141 /// Number of files loaded from the parse cache.
142 pub cache_hits: usize,
143 /// Number of files parsed without a cache hit.
144 pub cache_misses: usize,
145 /// Time spent updating the parse cache.
146 pub cache_update_ms: f64,
147 /// Time spent categorizing entry points.
148 pub entry_points_ms: f64,
149 /// Number of entry points considered.
150 pub entry_point_count: usize,
151 /// Time spent resolving imports.
152 pub resolve_imports_ms: f64,
153 /// Time spent building the module graph.
154 pub build_graph_ms: f64,
155 /// Time spent running analysis.
156 pub analyze_ms: f64,
157 /// Time spent running duplicate-code analysis, when included.
158 #[serde(skip_serializing_if = "Option::is_none")]
159 pub duplication_ms: Option<f64>,
160 /// Total pipeline time.
161 pub total_ms: f64,
162}
163
164/// Result of computing the impact closure for a single file as the seed.
165#[derive(Debug, Serialize)]
166pub struct ImpactClosureTrace {
167 /// The seed file, root-relative.
168 pub seed: String,
169 /// Root-relative paths transitively affected by the seed.
170 pub affected_not_shown: Vec<String>,
171 /// Coordination gaps between the seed and consumers.
172 pub coordination_gap: Vec<ImpactClosureGap>,
173}
174
175/// One coordination-gap entry in an [`ImpactClosureTrace`].
176#[derive(Debug, Serialize)]
177pub struct ImpactClosureGap {
178 /// Root-relative path of the consumer module.
179 pub consumer_file: String,
180 /// Exported symbol names the consumer references.
181 pub consumed_symbols: Vec<String>,
182 /// Scope note for the syntactic trace.
183 pub note: String,
184}
185
186/// Result of tracing a clone: all groups containing the code at a source
187/// location or addressed by a stable clone fingerprint.
188#[derive(Debug, Serialize)]
189pub struct CloneTrace {
190 /// File passed to the trace request, root-relative when a group matches.
191 #[serde(serialize_with = "serde_path::serialize")]
192 pub file: PathBuf,
193 /// 1-based line passed to the trace request or representative group line.
194 pub line: usize,
195 /// The matched clone instance, if one exists.
196 pub matched_instance: Option<CloneInstance>,
197 /// Clone groups matched by the trace request.
198 pub clone_groups: Vec<TracedCloneGroup>,
199}
200
201/// One clone group returned from a clone trace request.
202#[derive(Debug, Serialize)]
203pub struct TracedCloneGroup {
204 /// Stable content fingerprint, usually `dup:<8hex>` and widened on rare
205 /// report collisions.
206 pub fingerprint: String,
207 /// Number of tokens in the duplicated block.
208 pub token_count: usize,
209 /// Number of lines in the duplicated block.
210 pub line_count: usize,
211 /// Root-relative clone instances in this group.
212 pub instances: Vec<CloneInstance>,
213 /// Group-level refactoring suggestion.
214 pub suggestion: RefactoringSuggestion,
215 /// Best-effort name for the extracted function. Advisory only.
216 #[serde(skip_serializing_if = "Option::is_none")]
217 pub suggested_name: Option<String>,
218}