Skip to main content

aft/inspect/oxc_engine/
types.rs

1use std::collections::BTreeSet;
2use std::fmt;
3use std::path::PathBuf;
4
5use serde::{Deserialize, Serialize};
6
7pub const OXC_PROVENANCE: &str = "oxc";
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
10pub struct FileId(pub usize);
11
12#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
13#[serde(tag = "kind", content = "name", rename_all = "snake_case")]
14pub enum ExportName {
15    Named(String),
16    Default,
17}
18
19impl ExportName {
20    pub fn matches_str(&self, name: &str) -> bool {
21        match self {
22            Self::Named(value) => value == name,
23            Self::Default => name == "default",
24        }
25    }
26
27    pub fn as_symbol(&self) -> String {
28        match self {
29            Self::Named(value) => value.clone(),
30            Self::Default => "default".to_string(),
31        }
32    }
33}
34
35impl fmt::Display for ExportName {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        match self {
38            Self::Named(name) => f.write_str(name),
39            Self::Default => f.write_str("default"),
40        }
41    }
42}
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
45#[serde(rename_all = "snake_case")]
46pub enum ImportKind {
47    Named,
48    Default,
49    Namespace,
50    SideEffect,
51}
52
53#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
54#[serde(rename_all = "snake_case")]
55pub enum ReExportKind {
56    Named,
57    Star,
58    Namespace,
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct ExportFact {
63    pub name: ExportName,
64    pub local_name: Option<String>,
65    pub kind: String,
66    pub is_type_only: bool,
67    pub line: u32,
68    pub declared: bool,
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct ImportFact {
73    pub source: String,
74    pub kind: ImportKind,
75    pub imported_name: Option<String>,
76    pub local_name: Option<String>,
77    pub is_type_only: bool,
78    pub line: u32,
79}
80
81#[derive(Debug, Clone, Serialize, Deserialize)]
82pub struct ReExportFact {
83    pub source: String,
84    pub kind: ReExportKind,
85    pub imported_name: Option<String>,
86    pub exported_name: Option<String>,
87    pub is_type_only: bool,
88    pub line: u32,
89}
90
91#[derive(Debug, Clone, Serialize, Deserialize)]
92pub struct DynamicImportFact {
93    pub source: Option<String>,
94    pub is_literal: bool,
95    pub line: u32,
96}
97
98#[derive(Debug, Clone, Serialize, Deserialize)]
99pub struct FileFacts {
100    pub file_id: FileId,
101    pub path: PathBuf,
102    pub content_hash: String,
103    pub exports: Vec<ExportFact>,
104    pub imports: Vec<ImportFact>,
105    pub re_exports: Vec<ReExportFact>,
106    pub dynamic_imports: Vec<DynamicImportFact>,
107    pub same_file_value_references: BTreeSet<String>,
108    pub used_import_bindings: BTreeSet<String>,
109    pub type_referenced_import_bindings: BTreeSet<String>,
110    pub value_referenced_import_bindings: BTreeSet<String>,
111    pub parse_error: Option<String>,
112}
113
114impl FileFacts {
115    pub fn empty(
116        file_id: FileId,
117        path: PathBuf,
118        content_hash: String,
119        parse_error: String,
120    ) -> Self {
121        Self {
122            file_id,
123            path,
124            content_hash,
125            exports: Vec::new(),
126            imports: Vec::new(),
127            re_exports: Vec::new(),
128            dynamic_imports: Vec::new(),
129            same_file_value_references: BTreeSet::new(),
130            used_import_bindings: BTreeSet::new(),
131            type_referenced_import_bindings: BTreeSet::new(),
132            value_referenced_import_bindings: BTreeSet::new(),
133            parse_error: Some(parse_error),
134        }
135    }
136}
137
138#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
139#[serde(rename_all = "snake_case")]
140pub enum LivenessVerdict {
141    Used,
142    Unused,
143    Uncertain,
144}
145
146#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct OxcExportVerdict {
148    pub symbol: String,
149    pub kind: String,
150    pub line: u32,
151    pub verdict: LivenessVerdict,
152    pub reason: String,
153    pub provenance: String,
154}
155
156#[derive(Debug, Clone, Serialize, Deserialize)]
157pub struct OxcFileVerdicts {
158    pub file: PathBuf,
159    pub relative_file: String,
160    pub exports: Vec<OxcExportVerdict>,
161}
162
163impl OxcFileVerdicts {
164    pub fn contribution_payload(&self) -> serde_json::Value {
165        serde_json::json!({
166            "file": self.relative_file,
167            "exports": self.exports,
168            "provenance": OXC_PROVENANCE,
169        })
170    }
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct ResolverConfigInput {
175    pub path: PathBuf,
176    pub content_hash: String,
177}
178
179#[derive(Debug, Clone, Serialize, Deserialize)]
180pub struct OxcResolvedEdge {
181    pub from_file: PathBuf,
182    pub specifier: String,
183    pub resolved_file: Option<PathBuf>,
184    pub kind: String,
185}
186
187#[derive(Debug, Clone, Default, Serialize, Deserialize)]
188pub struct OxcEngineStats {
189    pub files: usize,
190    pub cache_hits: usize,
191    pub cache_misses: usize,
192    pub resolved_edges: usize,
193    pub unresolved_edges: usize,
194}
195
196#[derive(Debug, Clone, Serialize, Deserialize)]
197pub struct OxcEngineError {
198    pub file: PathBuf,
199    pub message: String,
200}
201
202#[derive(Debug, Clone, Serialize, Deserialize)]
203pub struct OxcEngineResult {
204    pub files: Vec<OxcFileVerdicts>,
205    pub resolver_config_inputs: Vec<ResolverConfigInput>,
206    pub resolver_config_fingerprint: String,
207    pub edges: Vec<OxcResolvedEdge>,
208    pub stats: OxcEngineStats,
209    pub errors: Vec<OxcEngineError>,
210    #[serde(default)]
211    pub skipped_outside_root: Vec<PathBuf>,
212}
213
214impl OxcEngineResult {
215    pub fn resolver_config_fingerprint(&self) -> &str {
216        &self.resolver_config_fingerprint
217    }
218}