1use oxc_span::Span;
11
12use crate::ExportName;
13use fallow_types::extract::{NamespaceObjectAlias, VisibilityTag};
14
15use super::types::{
16 CachedDynamicImport, CachedDynamicImportPattern, CachedExport, CachedImport,
17 CachedLocalTypeDeclaration, CachedMember, CachedModule, CachedNamespaceObjectAlias,
18 CachedPublicSignatureTypeReference, CachedReExport, CachedRequireCall, CachedSuppression,
19 IMPORT_KIND_DEFAULT, IMPORT_KIND_NAMED, IMPORT_KIND_NAMESPACE, IMPORT_KIND_SIDE_EFFECT,
20};
21
22#[must_use]
24pub fn cached_to_module(
25 cached: &CachedModule,
26 file_id: fallow_types::discover::FileId,
27) -> crate::ModuleInfo {
28 cached_to_module_opts(cached, file_id, true)
29}
30
31#[must_use]
36#[expect(
37 clippy::too_many_lines,
38 reason = "single flat field-by-field deserialization; splitting it harms readability"
39)]
40pub fn cached_to_module_opts(
41 cached: &CachedModule,
42 file_id: fallow_types::discover::FileId,
43 need_complexity: bool,
44) -> crate::ModuleInfo {
45 use crate::{
46 DynamicImportInfo, ExportInfo, ImportInfo, ImportedName, LocalTypeDeclaration, MemberInfo,
47 ModuleInfo, PublicSignatureTypeReference, ReExportInfo, RequireCallInfo,
48 };
49
50 let exports = cached
51 .exports
52 .iter()
53 .map(|e| ExportInfo {
54 name: if e.is_default {
55 ExportName::Default
56 } else {
57 ExportName::Named(e.name.clone())
58 },
59 local_name: e.local_name.clone(),
60 is_type_only: e.is_type_only,
61 is_side_effect_used: e.is_side_effect_used,
62 visibility: match e.visibility {
63 1 => VisibilityTag::Public,
64 2 => VisibilityTag::Internal,
65 3 => VisibilityTag::Beta,
66 4 => VisibilityTag::Alpha,
67 5 => VisibilityTag::ExpectedUnused,
68 _ => VisibilityTag::None,
69 },
70 span: Span::new(e.span_start, e.span_end),
71 members: e
72 .members
73 .iter()
74 .map(|m| MemberInfo {
75 name: m.name.clone(),
76 kind: m.kind,
77 span: Span::new(m.span_start, m.span_end),
78 has_decorator: m.has_decorator,
79 is_instance_returning_static: m.is_instance_returning_static,
80 is_self_returning: m.is_self_returning,
81 })
82 .collect(),
83 super_class: e.super_class.clone(),
84 })
85 .collect();
86
87 let imports = cached
88 .imports
89 .iter()
90 .map(|i| ImportInfo {
91 source: i.source.clone(),
92 imported_name: match i.kind {
93 IMPORT_KIND_DEFAULT => ImportedName::Default,
94 IMPORT_KIND_NAMESPACE => ImportedName::Namespace,
95 IMPORT_KIND_SIDE_EFFECT => ImportedName::SideEffect,
96 _ => ImportedName::Named(i.imported_name.clone()),
98 },
99 local_name: i.local_name.clone(),
100 is_type_only: i.is_type_only,
101 from_style: i.from_style,
102 span: Span::new(i.span_start, i.span_end),
103 source_span: Span::new(i.source_span_start, i.source_span_end),
104 })
105 .collect();
106
107 let re_exports = cached
108 .re_exports
109 .iter()
110 .map(|r| ReExportInfo {
111 source: r.source.clone(),
112 imported_name: r.imported_name.clone(),
113 exported_name: r.exported_name.clone(),
114 is_type_only: r.is_type_only,
115 span: Span::new(r.span_start, r.span_end),
116 })
117 .collect();
118
119 let dynamic_imports = cached
120 .dynamic_imports
121 .iter()
122 .map(|d| DynamicImportInfo {
123 source: d.source.clone(),
124 span: Span::new(d.span_start, d.span_end),
125 destructured_names: d.destructured_names.clone(),
126 local_name: d.local_name.clone(),
127 is_speculative: d.is_speculative,
128 })
129 .collect();
130
131 let require_calls = cached
132 .require_calls
133 .iter()
134 .map(|r| RequireCallInfo {
135 source: r.source.clone(),
136 span: Span::new(r.span_start, r.span_end),
137 destructured_names: r.destructured_names.clone(),
138 local_name: r.local_name.clone(),
139 })
140 .collect();
141
142 let dynamic_import_patterns = cached
143 .dynamic_import_patterns
144 .iter()
145 .map(|p| crate::DynamicImportPattern {
146 prefix: p.prefix.clone(),
147 suffix: p.suffix.clone(),
148 span: Span::new(p.span_start, p.span_end),
149 })
150 .collect();
151
152 let suppressions = cached
153 .suppressions
154 .iter()
155 .map(|s| crate::suppress::Suppression {
156 line: s.line,
157 comment_line: s.comment_line,
158 kind: if s.kind == 0 {
159 None
160 } else {
161 crate::suppress::IssueKind::from_discriminant(s.kind)
162 },
163 })
164 .collect();
165
166 ModuleInfo {
167 file_id,
168 exports,
169 imports,
170 re_exports,
171 dynamic_imports,
172 dynamic_import_patterns,
173 require_calls,
174 member_accesses: cached.member_accesses.clone(),
175 whole_object_uses: cached.whole_object_uses.clone(),
176 has_cjs_exports: cached.has_cjs_exports,
177 has_angular_component_template_url: cached.has_angular_component_template_url,
178 content_hash: cached.content_hash,
179 suppressions,
180 unused_import_bindings: cached.unused_import_bindings.clone(),
181 type_referenced_import_bindings: cached.type_referenced_import_bindings.clone(),
182 value_referenced_import_bindings: cached.value_referenced_import_bindings.clone(),
183 line_offsets: cached.line_offsets.clone(),
184 complexity: if need_complexity {
185 cached.complexity.clone()
186 } else {
187 Vec::new()
188 },
189 flag_uses: cached.flag_uses.clone(),
190 class_heritage: cached.class_heritage.clone(),
191 local_type_declarations: cached
192 .local_type_declarations
193 .iter()
194 .map(|decl| LocalTypeDeclaration {
195 name: decl.name.clone(),
196 span: Span::new(decl.span_start, decl.span_end),
197 })
198 .collect(),
199 public_signature_type_references: cached
200 .public_signature_type_references
201 .iter()
202 .map(|reference| PublicSignatureTypeReference {
203 export_name: reference.export_name.clone(),
204 type_name: reference.type_name.clone(),
205 span: Span::new(reference.span_start, reference.span_end),
206 })
207 .collect(),
208 namespace_object_aliases: cached
209 .namespace_object_aliases
210 .iter()
211 .map(|alias| NamespaceObjectAlias {
212 via_export_name: alias.via_export_name.clone(),
213 suffix: alias.suffix.clone(),
214 namespace_local: alias.namespace_local.clone(),
215 })
216 .collect(),
217 }
218}
219
220#[must_use]
226#[expect(
227 clippy::too_many_lines,
228 reason = "single flat field-by-field serialization; splitting it harms readability"
229)]
230pub fn module_to_cached(
231 module: &crate::ModuleInfo,
232 mtime_secs: u64,
233 file_size: u64,
234) -> CachedModule {
235 CachedModule {
236 content_hash: module.content_hash,
237 mtime_secs,
238 file_size,
239 exports: module
240 .exports
241 .iter()
242 .map(|e| CachedExport {
243 name: match &e.name {
244 ExportName::Named(n) => n.clone(),
245 ExportName::Default => String::new(),
246 },
247 is_default: matches!(e.name, ExportName::Default),
248 is_type_only: e.is_type_only,
249 is_side_effect_used: e.is_side_effect_used,
250 visibility: e.visibility as u8,
251 local_name: e.local_name.clone(),
252 span_start: e.span.start,
253 span_end: e.span.end,
254 members: e
255 .members
256 .iter()
257 .map(|m| CachedMember {
258 name: m.name.clone(),
259 kind: m.kind,
260 span_start: m.span.start,
261 span_end: m.span.end,
262 has_decorator: m.has_decorator,
263 is_instance_returning_static: m.is_instance_returning_static,
264 is_self_returning: m.is_self_returning,
265 })
266 .collect(),
267 super_class: e.super_class.clone(),
268 })
269 .collect(),
270 imports: module
271 .imports
272 .iter()
273 .map(|i| {
274 let (kind, imported_name) = match &i.imported_name {
275 crate::ImportedName::Named(n) => (IMPORT_KIND_NAMED, n.clone()),
276 crate::ImportedName::Default => (IMPORT_KIND_DEFAULT, String::new()),
277 crate::ImportedName::Namespace => (IMPORT_KIND_NAMESPACE, String::new()),
278 crate::ImportedName::SideEffect => (IMPORT_KIND_SIDE_EFFECT, String::new()),
279 };
280 CachedImport {
281 source: i.source.clone(),
282 imported_name,
283 local_name: i.local_name.clone(),
284 is_type_only: i.is_type_only,
285 from_style: i.from_style,
286 kind,
287 span_start: i.span.start,
288 span_end: i.span.end,
289 source_span_start: i.source_span.start,
290 source_span_end: i.source_span.end,
291 }
292 })
293 .collect(),
294 re_exports: module
295 .re_exports
296 .iter()
297 .map(|r| CachedReExport {
298 source: r.source.clone(),
299 imported_name: r.imported_name.clone(),
300 exported_name: r.exported_name.clone(),
301 is_type_only: r.is_type_only,
302 span_start: r.span.start,
303 span_end: r.span.end,
304 })
305 .collect(),
306 dynamic_imports: module
307 .dynamic_imports
308 .iter()
309 .map(|d| CachedDynamicImport {
310 source: d.source.clone(),
311 span_start: d.span.start,
312 span_end: d.span.end,
313 destructured_names: d.destructured_names.clone(),
314 local_name: d.local_name.clone(),
315 is_speculative: d.is_speculative,
316 })
317 .collect(),
318 require_calls: module
319 .require_calls
320 .iter()
321 .map(|r| CachedRequireCall {
322 source: r.source.clone(),
323 span_start: r.span.start,
324 span_end: r.span.end,
325 destructured_names: r.destructured_names.clone(),
326 local_name: r.local_name.clone(),
327 })
328 .collect(),
329 member_accesses: module.member_accesses.clone(),
330 whole_object_uses: module.whole_object_uses.clone(),
331 dynamic_import_patterns: module
332 .dynamic_import_patterns
333 .iter()
334 .map(|p| CachedDynamicImportPattern {
335 prefix: p.prefix.clone(),
336 suffix: p.suffix.clone(),
337 span_start: p.span.start,
338 span_end: p.span.end,
339 })
340 .collect(),
341 has_cjs_exports: module.has_cjs_exports,
342 has_angular_component_template_url: module.has_angular_component_template_url,
343 unused_import_bindings: module.unused_import_bindings.clone(),
344 type_referenced_import_bindings: module.type_referenced_import_bindings.clone(),
345 value_referenced_import_bindings: module.value_referenced_import_bindings.clone(),
346 suppressions: module
347 .suppressions
348 .iter()
349 .map(|s| CachedSuppression {
350 line: s.line,
351 comment_line: s.comment_line,
352 kind: s
353 .kind
354 .map_or(0, crate::suppress::IssueKind::to_discriminant),
355 })
356 .collect(),
357 line_offsets: module.line_offsets.clone(),
358 complexity: module.complexity.clone(),
359 flag_uses: module.flag_uses.clone(),
360 class_heritage: module.class_heritage.clone(),
361 local_type_declarations: module
362 .local_type_declarations
363 .iter()
364 .map(|decl| CachedLocalTypeDeclaration {
365 name: decl.name.clone(),
366 span_start: decl.span.start,
367 span_end: decl.span.end,
368 })
369 .collect(),
370 public_signature_type_references: module
371 .public_signature_type_references
372 .iter()
373 .map(|reference| CachedPublicSignatureTypeReference {
374 export_name: reference.export_name.clone(),
375 type_name: reference.type_name.clone(),
376 span_start: reference.span.start,
377 span_end: reference.span.end,
378 })
379 .collect(),
380 namespace_object_aliases: module
381 .namespace_object_aliases
382 .iter()
383 .map(|alias| CachedNamespaceObjectAlias {
384 via_export_name: alias.via_export_name.clone(),
385 suffix: alias.suffix.clone(),
386 namespace_local: alias.namespace_local.clone(),
387 })
388 .collect(),
389 }
390}