use std::path::PathBuf;
use serde::Serialize;
use crate::cache_rejection::CacheRejection;
use crate::duplicates::{CloneInstance, RefactoringSuggestion};
use crate::semantic::SemanticNamespace;
use crate::serde_path;
use crate::trace_chain::StarExportAmbiguity;
#[derive(Debug, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ExportTrace {
#[serde(serialize_with = "serde_path::serialize")]
pub file: PathBuf,
pub export_name: String,
#[cfg_attr(feature = "schema", schemars(default))]
pub namespace: crate::semantic::SemanticNamespace,
pub file_reachable: bool,
pub is_entry_point: bool,
pub is_used: bool,
pub direct_references: Vec<ExportReference>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub direct_references_by_namespace: Vec<NamespacedExportReferences>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub star_export_ambiguity: Option<StarExportAmbiguity>,
pub re_export_chains: Vec<ReExportChain>,
pub reason: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub semantic: Option<crate::semantic::SemanticSymbolTrace>,
}
#[derive(Debug, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ClassMemberTrace {
#[serde(serialize_with = "serde_path::serialize")]
pub file: PathBuf,
pub member_name: String,
pub member_kind: String,
pub owner_export: String,
#[cfg_attr(feature = "schema", schemars(default))]
pub owner_namespace: crate::semantic::SemanticNamespace,
pub owner_is_used: bool,
pub owner_file_reachable: bool,
pub owner_is_entry_point: bool,
pub owner_direct_references: Vec<ExportReference>,
pub owner_re_export_chains: Vec<ReExportChain>,
pub reason: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub semantic: Option<crate::semantic::SemanticSymbolTrace>,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ExportReference {
#[serde(serialize_with = "serde_path::serialize")]
pub from_file: PathBuf,
pub kind: String,
}
#[derive(Debug, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct NamespacedExportReferences {
pub namespace: SemanticNamespace,
pub reference_count: usize,
pub references: Vec<ExportReference>,
}
#[derive(Debug, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ReExportChain {
#[serde(serialize_with = "serde_path::serialize")]
pub barrel_file: PathBuf,
pub exported_as: String,
pub reference_count: usize,
}
#[derive(Debug, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct FileTrace {
#[serde(serialize_with = "serde_path::serialize")]
pub file: PathBuf,
pub is_reachable: bool,
pub is_entry_point: bool,
pub exports: Vec<TracedExport>,
#[serde(serialize_with = "serde_path::serialize_vec")]
pub imports_from: Vec<PathBuf>,
#[serde(serialize_with = "serde_path::serialize_vec")]
pub imported_by: Vec<PathBuf>,
pub re_exports: Vec<TracedReExport>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub sources: Vec<TraceSource>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct TraceProvenance {
files: Vec<(PathBuf, TraceSource)>,
dependencies: Vec<(String, TraceSource)>,
}
impl TraceProvenance {
pub fn push_file(&mut self, file: PathBuf, source: TraceSource) {
if !self
.files
.iter()
.any(|(known, known_source)| *known == file && *known_source == source)
{
self.files.push((file, source));
}
}
pub fn push_dependency(&mut self, name: String, source: TraceSource) {
if !self
.dependencies
.iter()
.any(|(known, known_source)| *known == name && *known_source == source)
{
self.dependencies.push((name, source));
}
}
#[must_use]
pub fn file_sources(&self, file: &std::path::Path) -> Vec<TraceSource> {
self.files
.iter()
.filter(|(known, _)| known == file)
.map(|(_, source)| source.clone())
.collect()
}
#[must_use]
pub fn dependency_sources(&self, name: &str) -> Vec<TraceSource> {
self.dependencies
.iter()
.filter(|(known, _)| known == name)
.map(|(_, source)| source.clone())
.collect()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct TraceSource {
pub kind: String,
pub plugin: String,
#[serde(serialize_with = "serde_path::serialize")]
pub config: PathBuf,
pub key: String,
}
#[derive(Debug, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct TracedExport {
pub name: String,
pub is_type_only: bool,
pub reference_count: usize,
pub referenced_by: Vec<ExportReference>,
}
#[derive(Debug, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct TracedReExport {
#[serde(serialize_with = "serde_path::serialize")]
pub source_file: PathBuf,
pub imported_name: String,
pub exported_name: String,
}
#[derive(Debug, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct DependencyTrace {
pub package_name: String,
#[serde(serialize_with = "serde_path::serialize_vec")]
pub imported_by: Vec<PathBuf>,
#[serde(serialize_with = "serde_path::serialize_vec")]
pub type_only_imported_by: Vec<PathBuf>,
pub used_in_scripts: bool,
pub is_used: bool,
pub import_count: usize,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub sources: Vec<TraceSource>,
}
#[derive(Debug, Clone, Copy, Default, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct EntryPointSpans {
pub root_ms: f64,
pub workspaces_ms: f64,
pub plugins_ms: f64,
pub plugin_glob_build_ms: f64,
pub plugin_glob_match_ms: f64,
pub infrastructure_ms: f64,
pub dynamic_ms: f64,
pub dedup_ms: f64,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct PipelineCounters {
pub files_read: u64,
pub source_bytes_read: u64,
pub parse_cache_bytes_read: u64,
pub css_masked_bytes: u64,
pub resolve_specifier_calls: u64,
pub unique_specifiers: u64,
pub oxc_resolve_calls: u64,
pub canonicalize_calls: u64,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct PipelineTimings {
pub discover_files_ms: f64,
pub file_count: usize,
pub workspaces_ms: f64,
pub workspace_count: usize,
pub plugins_ms: f64,
pub script_analysis_ms: f64,
pub parse_extract_ms: f64,
pub parse_cpu_ms: f64,
pub parse_cache_load_ms: f64,
pub module_count: usize,
pub cache_hits: usize,
pub cache_misses: usize,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cache_rejection: Option<CacheRejection>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub graph_cache_rejection: Option<CacheRejection>,
pub cache_update_ms: f64,
pub entry_points_ms: f64,
pub entry_point_spans: EntryPointSpans,
pub entry_point_count: usize,
pub resolve_imports_ms: f64,
pub build_graph_ms: f64,
pub analyze_ms: f64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub duplication_ms: Option<f64>,
pub total_ms: f64,
pub counters: PipelineCounters,
}
#[derive(Debug, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ImpactClosureTrace {
pub seed: String,
pub affected_not_shown: Vec<String>,
pub coordination_gap: Vec<ImpactClosureGap>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum ImportPathTraceSchemaVersion {
#[serde(rename = "1")]
V1,
}
#[derive(Debug, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "schema", schemars(title = "fallow trace --path"))]
pub struct ImportPathTrace {
pub schema_version: ImportPathTraceSchemaVersion,
pub from: String,
pub to: String,
pub reachable: bool,
pub hops: usize,
pub path: Vec<ImportPathHop>,
pub reason: String,
}
#[derive(Debug, Serialize, PartialEq, Eq)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ImportPathHop {
pub from: String,
pub to: String,
pub type_only: bool,
pub dynamic: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub import_line: Option<u32>,
}
#[derive(Debug, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ImpactClosureGap {
pub consumer_file: String,
pub consumed_symbols: Vec<String>,
pub note: String,
}
#[derive(Debug, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct CloneTrace {
#[serde(serialize_with = "serde_path::serialize")]
pub file: PathBuf,
pub line: usize,
pub matched_instance: Option<CloneInstance>,
pub clone_groups: Vec<TracedCloneGroup>,
}
#[derive(Debug, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct TracedCloneGroup {
pub fingerprint: String,
pub token_count: usize,
pub line_count: usize,
pub spread: usize,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "schema", schemars(with = "f64"))]
pub similarity: Option<f64>,
pub instances: Vec<CloneInstance>,
pub suggestion: RefactoringSuggestion,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub suggested_name: Option<String>,
}