1use std::sync::Arc;
11use std::time::{SystemTime, UNIX_EPOCH};
12
13use oxc_span::Span;
14
15use crate::ExportName;
16use fallow_types::extract::{NamespaceObjectAlias, VisibilityTag};
17use fallow_types::suppress::{PolicyRuleSuppression, SuppressionTarget};
18
19#[must_use]
25pub fn current_unix_seconds() -> u64 {
26 SystemTime::now()
27 .duration_since(UNIX_EPOCH)
28 .map_or(0, |d| d.as_secs())
29}
30
31use super::types::{
32 CachedDynamicImport, CachedDynamicImportPattern, CachedExport, CachedImport,
33 CachedLocalTypeDeclaration, CachedMember, CachedModule, CachedNamespaceObjectAlias,
34 CachedPublicSignatureTypeReference, CachedReExport, CachedRequireCall, CachedSuppression,
35 CachedUnknownSuppressionKind, IMPORT_KIND_DEFAULT, IMPORT_KIND_NAMED, IMPORT_KIND_NAMESPACE,
36 IMPORT_KIND_SIDE_EFFECT,
37};
38
39#[must_use]
41pub fn cached_to_module(
42 cached: &CachedModule,
43 file_id: fallow_types::discover::FileId,
44) -> crate::ModuleInfo {
45 cached_to_module_opts(cached, file_id, true)
46}
47
48fn cached_exports_to_module(exports: &[CachedExport]) -> Vec<crate::ExportInfo> {
49 exports
50 .iter()
51 .map(|export| crate::ExportInfo {
52 name: if export.is_default {
53 ExportName::Default
54 } else {
55 ExportName::Named(export.name.clone())
56 },
57 local_name: export.local_name.clone(),
58 is_type_only: export.is_type_only,
59 is_side_effect_used: export.is_side_effect_used,
60 visibility: match export.visibility {
61 1 => VisibilityTag::Public,
62 2 => VisibilityTag::Internal,
63 3 => VisibilityTag::Beta,
64 4 => VisibilityTag::Alpha,
65 5 => VisibilityTag::ExpectedUnused,
66 _ => VisibilityTag::None,
67 },
68 expected_unused_reason: export.expected_unused_reason.clone(),
69 deprecated: export.deprecated,
70 deprecated_reason: export.deprecated_reason.clone(),
71 span: Span::new(export.span_start, export.span_end),
72 members: export
73 .members
74 .iter()
75 .map(|member| crate::MemberInfo {
76 name: member.name.clone(),
77 kind: member.kind,
78 span: Span::new(member.span_start, member.span_end),
79 has_decorator: member.has_decorator,
80 decorator_names: member.decorator_names.clone(),
81 is_instance_returning_static: member.is_instance_returning_static,
82 is_self_returning: member.is_self_returning,
83 })
84 .collect(),
85 super_class: export.super_class.clone(),
86 })
87 .collect()
88}
89
90fn cached_imports_to_module(imports: &[CachedImport]) -> Vec<crate::ImportInfo> {
91 imports
92 .iter()
93 .map(|import| crate::ImportInfo {
94 source: import.source.clone(),
95 imported_name: match import.kind {
96 IMPORT_KIND_DEFAULT => crate::ImportedName::Default,
97 IMPORT_KIND_NAMESPACE => crate::ImportedName::Namespace,
98 IMPORT_KIND_SIDE_EFFECT => crate::ImportedName::SideEffect,
99 _ => crate::ImportedName::Named(import.imported_name.clone()),
100 },
101 local_name: import.local_name.clone(),
102 is_type_only: import.is_type_only,
103 is_type_only_star: import.is_type_only_star,
104 from_style: import.from_style,
105 span: Span::new(import.span_start, import.span_end),
106 source_span: Span::new(import.source_span_start, import.source_span_end),
107 })
108 .collect()
109}
110
111fn cached_re_exports_to_module(re_exports: &[CachedReExport]) -> Vec<crate::ReExportInfo> {
112 re_exports
113 .iter()
114 .map(|re_export| crate::ReExportInfo {
115 source: re_export.source.clone(),
116 imported_name: re_export.imported_name.clone(),
117 exported_name: re_export.exported_name.clone(),
118 is_type_only: re_export.is_type_only,
119 span: Span::new(re_export.span_start, re_export.span_end),
120 statement_span: Span::new(re_export.statement_span_start, re_export.statement_span_end),
121 source_span: Span::new(re_export.source_span_start, re_export.source_span_end),
122 })
123 .collect()
124}
125
126fn cached_dynamic_imports_to_module(
127 dynamic_imports: &[CachedDynamicImport],
128) -> Vec<crate::DynamicImportInfo> {
129 dynamic_imports
130 .iter()
131 .map(|dynamic_import| crate::DynamicImportInfo {
132 source: dynamic_import.source.clone(),
133 span: Span::new(dynamic_import.span_start, dynamic_import.span_end),
134 destructured_names: dynamic_import.destructured_names.clone(),
135 local_name: dynamic_import.local_name.clone(),
136 is_speculative: dynamic_import.is_speculative,
137 })
138 .collect()
139}
140
141fn cached_require_calls_to_module(
142 require_calls: &[CachedRequireCall],
143) -> Vec<crate::RequireCallInfo> {
144 require_calls
145 .iter()
146 .map(|require_call| crate::RequireCallInfo {
147 source: require_call.source.clone(),
148 span: Span::new(require_call.span_start, require_call.span_end),
149 source_span: Span::new(require_call.source_span_start, require_call.source_span_end),
150 destructured_names: require_call.destructured_names.clone(),
151 local_name: require_call.local_name.clone(),
152 is_type_only: require_call.is_type_only,
153 })
154 .collect()
155}
156
157fn cached_dynamic_patterns_to_module(
158 dynamic_import_patterns: &[CachedDynamicImportPattern],
159) -> Vec<crate::DynamicImportPattern> {
160 dynamic_import_patterns
161 .iter()
162 .map(|pattern| crate::DynamicImportPattern {
163 prefix: pattern.prefix.clone(),
164 suffix: pattern.suffix.clone(),
165 span: Span::new(pattern.span_start, pattern.span_end),
166 mechanism: pattern.mechanism,
167 })
168 .collect()
169}
170
171fn cached_suppressions_to_module(
172 suppressions: &[CachedSuppression],
173) -> Vec<crate::suppress::Suppression> {
174 suppressions
175 .iter()
176 .map(|suppression| {
177 let target = if suppression.kind == 0 {
178 None
179 } else if suppression.kind
180 == crate::suppress::IssueKind::PolicyViolation.to_discriminant()
181 && !suppression.policy_pack.is_empty()
182 && !suppression.policy_rule_id.is_empty()
183 {
184 Some(SuppressionTarget::PolicyRule(PolicyRuleSuppression::new(
185 suppression.policy_pack.clone(),
186 suppression.policy_rule_id.clone(),
187 )))
188 } else {
189 crate::suppress::IssueKind::from_discriminant(suppression.kind)
190 .map(SuppressionTarget::Issue)
191 };
192 crate::suppress::Suppression {
193 line: suppression.line,
194 comment_line: suppression.comment_line,
195 target,
196 reason: suppression.reason.clone(),
197 }
198 })
199 .collect()
200}
201
202fn cached_unknown_suppressions_to_module(
203 unknown_suppression_kinds: &[CachedUnknownSuppressionKind],
204) -> Vec<fallow_types::suppress::UnknownSuppressionKind> {
205 unknown_suppression_kinds
206 .iter()
207 .map(|unknown| fallow_types::suppress::UnknownSuppressionKind {
208 comment_line: unknown.comment_line,
209 is_file_level: unknown.is_file_level,
210 token: unknown.token.clone(),
211 reason: unknown.reason.clone(),
212 })
213 .collect()
214}
215
216fn cached_local_types_to_module(
217 local_type_declarations: &[CachedLocalTypeDeclaration],
218) -> Vec<crate::LocalTypeDeclaration> {
219 local_type_declarations
220 .iter()
221 .map(|declaration| crate::LocalTypeDeclaration {
222 name: declaration.name.clone(),
223 span: Span::new(declaration.span_start, declaration.span_end),
224 })
225 .collect()
226}
227
228fn cached_signature_refs_to_module(
229 public_signature_type_references: &[CachedPublicSignatureTypeReference],
230) -> Vec<crate::PublicSignatureTypeReference> {
231 public_signature_type_references
232 .iter()
233 .map(|reference| crate::PublicSignatureTypeReference {
234 export_name: reference.export_name.clone(),
235 type_name: reference.type_name.clone(),
236 span: Span::new(reference.span_start, reference.span_end),
237 from_satisfies: reference.from_satisfies,
238 })
239 .collect()
240}
241
242fn cached_namespace_aliases_to_module(
243 namespace_object_aliases: &[CachedNamespaceObjectAlias],
244) -> Vec<NamespaceObjectAlias> {
245 namespace_object_aliases
246 .iter()
247 .map(|alias| NamespaceObjectAlias {
248 via_export_name: alias.via_export_name.clone(),
249 suffix: alias.suffix.clone(),
250 namespace_local: alias.namespace_local.clone(),
251 })
252 .collect()
253}
254
255fn module_exports_to_cached(exports: &[crate::ExportInfo]) -> Vec<CachedExport> {
256 exports
257 .iter()
258 .map(|export| CachedExport {
259 name: match &export.name {
260 ExportName::Named(name) => name.clone(),
261 ExportName::Default => String::new(),
262 },
263 is_default: matches!(export.name, ExportName::Default),
264 is_type_only: export.is_type_only,
265 is_side_effect_used: export.is_side_effect_used,
266 visibility: export.visibility as u8,
267 expected_unused_reason: export.expected_unused_reason.clone(),
268 deprecated: export.deprecated,
269 deprecated_reason: export.deprecated_reason.clone(),
270 local_name: export.local_name.clone(),
271 span_start: export.span.start,
272 span_end: export.span.end,
273 members: export
274 .members
275 .iter()
276 .map(|member| CachedMember {
277 name: member.name.clone(),
278 kind: member.kind,
279 span_start: member.span.start,
280 span_end: member.span.end,
281 has_decorator: member.has_decorator,
282 decorator_names: member.decorator_names.clone(),
283 is_instance_returning_static: member.is_instance_returning_static,
284 is_self_returning: member.is_self_returning,
285 })
286 .collect(),
287 super_class: export.super_class.clone(),
288 })
289 .collect()
290}
291
292fn module_imports_to_cached(imports: &[crate::ImportInfo]) -> Vec<CachedImport> {
293 imports
294 .iter()
295 .map(|import| {
296 let (kind, imported_name) = match &import.imported_name {
297 crate::ImportedName::Named(name) => (IMPORT_KIND_NAMED, name.clone()),
298 crate::ImportedName::Default => (IMPORT_KIND_DEFAULT, String::new()),
299 crate::ImportedName::Namespace => (IMPORT_KIND_NAMESPACE, String::new()),
300 crate::ImportedName::SideEffect => (IMPORT_KIND_SIDE_EFFECT, String::new()),
301 };
302 CachedImport {
303 source: import.source.clone(),
304 imported_name,
305 local_name: import.local_name.clone(),
306 is_type_only: import.is_type_only,
307 is_type_only_star: import.is_type_only_star,
308 from_style: import.from_style,
309 kind,
310 span_start: import.span.start,
311 span_end: import.span.end,
312 source_span_start: import.source_span.start,
313 source_span_end: import.source_span.end,
314 }
315 })
316 .collect()
317}
318
319fn module_re_exports_to_cached(re_exports: &[crate::ReExportInfo]) -> Vec<CachedReExport> {
320 re_exports
321 .iter()
322 .map(|re_export| CachedReExport {
323 source: re_export.source.clone(),
324 imported_name: re_export.imported_name.clone(),
325 exported_name: re_export.exported_name.clone(),
326 is_type_only: re_export.is_type_only,
327 span_start: re_export.span.start,
328 span_end: re_export.span.end,
329 statement_span_start: re_export.statement_span.start,
330 statement_span_end: re_export.statement_span.end,
331 source_span_start: re_export.source_span.start,
332 source_span_end: re_export.source_span.end,
333 })
334 .collect()
335}
336
337fn module_dynamic_imports_to_cached(
338 dynamic_imports: &[crate::DynamicImportInfo],
339) -> Vec<CachedDynamicImport> {
340 dynamic_imports
341 .iter()
342 .map(|dynamic_import| CachedDynamicImport {
343 source: dynamic_import.source.clone(),
344 span_start: dynamic_import.span.start,
345 span_end: dynamic_import.span.end,
346 destructured_names: dynamic_import.destructured_names.clone(),
347 local_name: dynamic_import.local_name.clone(),
348 is_speculative: dynamic_import.is_speculative,
349 })
350 .collect()
351}
352
353fn module_require_calls_to_cached(
354 require_calls: &[crate::RequireCallInfo],
355) -> Vec<CachedRequireCall> {
356 require_calls
357 .iter()
358 .map(|require_call| CachedRequireCall {
359 source: require_call.source.clone(),
360 span_start: require_call.span.start,
361 span_end: require_call.span.end,
362 source_span_start: require_call.source_span.start,
363 source_span_end: require_call.source_span.end,
364 destructured_names: require_call.destructured_names.clone(),
365 local_name: require_call.local_name.clone(),
366 is_type_only: require_call.is_type_only,
367 })
368 .collect()
369}
370
371fn module_dynamic_patterns_to_cached(
372 dynamic_import_patterns: &[crate::DynamicImportPattern],
373) -> Vec<CachedDynamicImportPattern> {
374 dynamic_import_patterns
375 .iter()
376 .map(|pattern| CachedDynamicImportPattern {
377 prefix: pattern.prefix.clone(),
378 suffix: pattern.suffix.clone(),
379 span_start: pattern.span.start,
380 span_end: pattern.span.end,
381 mechanism: pattern.mechanism,
382 })
383 .collect()
384}
385
386fn module_suppressions_to_cached(
387 suppressions: &[crate::suppress::Suppression],
388) -> Vec<CachedSuppression> {
389 suppressions
390 .iter()
391 .map(|suppression| {
392 let (kind, policy_pack, policy_rule_id) = match &suppression.target {
393 None => (0, String::new(), String::new()),
394 Some(SuppressionTarget::Issue(kind)) => {
395 (kind.to_discriminant(), String::new(), String::new())
396 }
397 Some(SuppressionTarget::PolicyRule(target)) => (
398 crate::suppress::IssueKind::PolicyViolation.to_discriminant(),
399 target.pack.clone(),
400 target.rule_id.clone(),
401 ),
402 };
403 CachedSuppression {
404 line: suppression.line,
405 comment_line: suppression.comment_line,
406 kind,
407 policy_pack,
408 policy_rule_id,
409 reason: suppression.reason.clone(),
410 }
411 })
412 .collect()
413}
414
415fn module_unknown_suppressions_to_cached(
416 unknown_suppression_kinds: &[fallow_types::suppress::UnknownSuppressionKind],
417) -> Vec<CachedUnknownSuppressionKind> {
418 unknown_suppression_kinds
419 .iter()
420 .map(|unknown| CachedUnknownSuppressionKind {
421 comment_line: unknown.comment_line,
422 is_file_level: unknown.is_file_level,
423 token: unknown.token.clone(),
424 reason: unknown.reason.clone(),
425 })
426 .collect()
427}
428
429fn module_local_types_to_cached(
430 local_type_declarations: &[crate::LocalTypeDeclaration],
431) -> Vec<CachedLocalTypeDeclaration> {
432 local_type_declarations
433 .iter()
434 .map(|declaration| CachedLocalTypeDeclaration {
435 name: declaration.name.clone(),
436 span_start: declaration.span.start,
437 span_end: declaration.span.end,
438 })
439 .collect()
440}
441
442fn module_signature_refs_to_cached(
443 public_signature_type_references: &[crate::PublicSignatureTypeReference],
444) -> Vec<CachedPublicSignatureTypeReference> {
445 public_signature_type_references
446 .iter()
447 .map(|reference| CachedPublicSignatureTypeReference {
448 export_name: reference.export_name.clone(),
449 type_name: reference.type_name.clone(),
450 span_start: reference.span.start,
451 span_end: reference.span.end,
452 from_satisfies: reference.from_satisfies,
453 })
454 .collect()
455}
456
457fn module_namespace_aliases_to_cached(
458 namespace_object_aliases: &[NamespaceObjectAlias],
459) -> Vec<CachedNamespaceObjectAlias> {
460 namespace_object_aliases
461 .iter()
462 .map(|alias| CachedNamespaceObjectAlias {
463 via_export_name: alias.via_export_name.clone(),
464 suffix: alias.suffix.clone(),
465 namespace_local: alias.namespace_local.clone(),
466 })
467 .collect()
468}
469
470fn cached_opt_to_arc<T: Clone>(cached: Option<&[T]>) -> Arc<[T]> {
472 cached.map(Arc::from).unwrap_or_default()
473}
474
475#[must_use]
480#[expect(
481 clippy::too_many_lines,
482 reason = "flat field projection preserves the complete extraction cache contract"
483)]
484pub fn cached_to_module_opts(
485 cached: &CachedModule,
486 file_id: fallow_types::discover::FileId,
487 need_complexity: bool,
488) -> crate::ModuleInfo {
489 crate::ModuleInfo {
490 file_id,
491 exports: cached_exports_to_module(&cached.exports).into(),
492 imports: cached_imports_to_module(&cached.imports),
493 re_exports: cached_re_exports_to_module(&cached.re_exports),
494 dynamic_imports: cached_dynamic_imports_to_module(&cached.dynamic_imports),
495 dynamic_import_patterns: cached_dynamic_patterns_to_module(&cached.dynamic_import_patterns),
496 require_calls: cached_require_calls_to_module(&cached.require_calls),
497 package_path_references: cached.package_path_references.clone(),
498 type_package_references: cached.type_package_references.clone(),
499 bin_path_references: cached.bin_path_references.clone(),
500 package_resolve_sites: cached.package_resolve_sites.clone(),
501 member_accesses: cached.member_accesses.clone().into(),
502 semantic_facts: cached_opt_to_arc(cached.semantic_facts.as_deref()),
503 whole_object_uses: Arc::from(&*cached.whole_object_uses),
504 has_cjs_exports: cached.has_cjs_exports,
505 has_angular_component_template_url: cached.has_angular_component_template_url,
506 content_hash: cached.content_hash,
507 parse_error_count: cached.parse_error_count,
508 parse_panicked: cached.parse_panicked,
509 suppressions: cached_suppressions_to_module(&cached.suppressions),
510 unknown_suppression_kinds: cached_unknown_suppressions_to_module(
511 &cached.unknown_suppression_kinds,
512 ),
513 unused_import_bindings: cached.unused_import_bindings.clone(),
514 type_referenced_import_bindings: cached.type_referenced_import_bindings.clone(),
515 value_referenced_import_bindings: cached.value_referenced_import_bindings.clone(),
516 line_offsets: cached.line_offsets.clone(),
517 complexity: if need_complexity {
518 cached.complexity.clone()
519 } else {
520 Vec::new()
521 },
522 flag_uses: cached.flag_uses.clone(),
523 flag_registry_facts: cached.flag_registry_facts.clone(),
524 class_heritage: cached.class_heritage.clone(),
525 exported_factory_returns: cached_opt_to_arc(cached.exported_factory_returns.as_deref()),
526 exported_factory_return_object_shapes: cached_opt_to_arc(
527 cached.exported_factory_return_object_shapes.as_deref(),
528 ),
529 type_member_types: cached_opt_to_arc(cached.type_member_types.as_deref()),
530 injection_tokens: cached.injection_tokens.clone(),
531 local_type_declarations: cached_local_types_to_module(&cached.local_type_declarations),
532 public_signature_type_references: cached_signature_refs_to_module(
533 &cached.public_signature_type_references,
534 ),
535 namespace_object_aliases: cached_namespace_aliases_to_module(
536 &cached.namespace_object_aliases,
537 ),
538 iconify_prefixes: cached.iconify_prefixes.clone(),
539 iconify_icon_names: cached.iconify_icon_names.clone(),
540 auto_import_candidates: cached.auto_import_candidates.clone(),
541 directives: cached.directives.clone(),
542 client_only_dynamic_import_spans: cached.client_only_dynamic_import_spans.clone(),
543 security_sinks: cached.security_sinks.clone(),
544 security_sinks_skipped: cached.security_sinks_skipped,
545 security_unresolved_callee_sites: cached.security_unresolved_callee_sites.clone(),
546 tainted_bindings: cached.tainted_bindings.clone(),
547 sanitized_sink_args: cached.sanitized_sink_args.clone(),
548 security_control_sites: cached.security_control_sites.clone(),
549 callee_uses: cached.callee_uses.clone(),
550 imported_call_sites: cached.imported_call_sites.clone().into(),
551 import_binding_references: cached.import_binding_references.clone().into(),
552 misplaced_directives: cached.misplaced_directives.clone(),
553 inline_server_action_exports: cached.inline_server_action_exports.clone(),
554 di_key_sites: cached.di_key_sites.clone(),
555 has_dynamic_provide: cached.has_dynamic_provide,
556 is_server_action_module: cached.is_server_action_module,
557 has_global_declarations: cached.has_global_declarations,
558 triple_slash_reference_paths: cached.triple_slash_reference_paths.clone(),
559 jsx_runtime_from_config: cached.jsx_runtime_from_config,
560 referenced_import_bindings: Vec::new(),
563 component_props: cached.component_props.clone(),
564 component_contracts: cached.component_contracts.clone(),
565 has_props_attrs_fallthrough: cached.has_props_attrs_fallthrough,
566 has_define_expose: cached.has_define_expose,
567 has_define_model: cached.has_define_model,
568 has_unharvestable_props: cached.has_unharvestable_props,
569 component_emits: cached.component_emits.clone(),
570 angular_inputs: cached.angular_inputs.clone(),
571 angular_outputs: cached.angular_outputs.clone(),
572 angular_component_selectors: cached.angular_component_selectors.clone(),
573 registered_custom_elements: cached.registered_custom_elements.clone(),
574 used_custom_element_tags: cached.used_custom_element_tags.clone(),
575 angular_used_selectors: cached.angular_used_selectors.clone(),
576 angular_entry_component_refs: cached.angular_entry_component_refs.clone(),
577 has_dynamic_component_render: cached.has_dynamic_component_render,
578 has_unharvestable_emits: cached.has_unharvestable_emits,
579 has_dynamic_emit: cached.has_dynamic_emit,
580 has_emit_whole_object_use: cached.has_emit_whole_object_use,
581 load_return_keys: cached.load_return_keys.clone(),
582 has_unharvestable_load: cached.has_unharvestable_load,
583 has_load_data_whole_use: cached.has_load_data_whole_use,
584 has_page_data_store_whole_use: false,
586 has_route_loader_data_whole_use: false,
588 component_functions: cached.component_functions.clone(),
589 react_props: cached.react_props.clone(),
590 hook_uses: cached.hook_uses.clone(),
591 render_edges: cached.render_edges.clone(),
592 svelte_dispatched_events: cached.svelte_dispatched_events.clone(),
593 svelte_listened_events: cached.svelte_listened_events.clone(),
594 has_dynamic_dispatch: cached.has_dynamic_dispatch,
595 }
596}
597
598#[must_use]
604pub fn module_to_cached(
605 module: &crate::ModuleInfo,
606 fingerprint: fallow_types::source_fingerprint::SourceFingerprint,
607 complexity_extracted: bool,
608) -> CachedModule {
609 let mut cached = module_to_cached_payload(module);
610 cached.mtime_ns = fingerprint.mtime_ns;
611 cached.ctime_ns = fingerprint.ctime_ns;
612 cached.file_size = fingerprint.file_size;
613 cached.complexity_extracted = complexity_extracted;
614 cached
615}
616
617#[expect(
618 clippy::too_many_lines,
619 reason = "flat field projection preserves the complete extraction cache contract"
620)]
621fn module_to_cached_payload(module: &crate::ModuleInfo) -> CachedModule {
622 CachedModule {
623 content_hash: module.content_hash,
624 mtime_ns: 0,
625 ctime_ns: 0,
626 file_size: 0,
627 last_access_secs: current_unix_seconds(),
628 exports: module_exports_to_cached(&module.exports),
629 imports: module_imports_to_cached(&module.imports),
630 re_exports: module_re_exports_to_cached(&module.re_exports),
631 dynamic_imports: module_dynamic_imports_to_cached(&module.dynamic_imports),
632 require_calls: module_require_calls_to_cached(&module.require_calls),
633 package_path_references: module.package_path_references.clone(),
634 type_package_references: module.type_package_references.clone(),
635 bin_path_references: module.bin_path_references.clone(),
636 package_resolve_sites: module.package_resolve_sites.clone(),
637 member_accesses: module.member_accesses.to_vec(),
638 semantic_facts: cached_semantic_facts(&module.semantic_facts),
639 whole_object_uses: Box::from(&*module.whole_object_uses),
640 dynamic_import_patterns: module_dynamic_patterns_to_cached(&module.dynamic_import_patterns),
641 parse_error_count: module.parse_error_count,
642 parse_panicked: module.parse_panicked,
643 has_cjs_exports: module.has_cjs_exports,
644 has_angular_component_template_url: module.has_angular_component_template_url,
645 unused_import_bindings: module.unused_import_bindings.clone(),
646 type_referenced_import_bindings: module.type_referenced_import_bindings.clone(),
647 value_referenced_import_bindings: module.value_referenced_import_bindings.clone(),
648 suppressions: module_suppressions_to_cached(&module.suppressions),
649 unknown_suppression_kinds: module_unknown_suppressions_to_cached(
650 &module.unknown_suppression_kinds,
651 ),
652 line_offsets: module.line_offsets.clone(),
653 complexity: module.complexity.clone(),
654 complexity_extracted: false,
655 flag_uses: module.flag_uses.clone(),
656 flag_registry_facts: module.flag_registry_facts.clone(),
657 class_heritage: module.class_heritage.clone(),
658 exported_factory_returns: (!module.exported_factory_returns.is_empty())
659 .then(|| Box::from(&*module.exported_factory_returns)),
660 exported_factory_return_object_shapes: (!module
661 .exported_factory_return_object_shapes
662 .is_empty())
663 .then(|| Box::from(&*module.exported_factory_return_object_shapes)),
664 type_member_types: (!module.type_member_types.is_empty())
665 .then(|| Box::from(&*module.type_member_types)),
666 injection_tokens: module.injection_tokens.clone(),
667 local_type_declarations: module_local_types_to_cached(&module.local_type_declarations),
668 public_signature_type_references: module_signature_refs_to_cached(
669 &module.public_signature_type_references,
670 ),
671 namespace_object_aliases: module_namespace_aliases_to_cached(
672 &module.namespace_object_aliases,
673 ),
674 iconify_prefixes: module.iconify_prefixes.clone(),
675 iconify_icon_names: module.iconify_icon_names.clone(),
676 auto_import_candidates: module.auto_import_candidates.clone(),
677 directives: module.directives.clone(),
678 client_only_dynamic_import_spans: module.client_only_dynamic_import_spans.clone(),
679 security_sinks: module.security_sinks.clone(),
680 security_sinks_skipped: module.security_sinks_skipped,
681 security_unresolved_callee_sites: module.security_unresolved_callee_sites.clone(),
682 tainted_bindings: module.tainted_bindings.clone(),
683 sanitized_sink_args: module.sanitized_sink_args.clone(),
684 security_control_sites: module.security_control_sites.clone(),
685 callee_uses: module.callee_uses.clone(),
686 imported_call_sites: module.imported_call_sites.to_vec(),
687 import_binding_references: module.import_binding_references.to_vec(),
688 misplaced_directives: module.misplaced_directives.clone(),
689 inline_server_action_exports: module.inline_server_action_exports.clone(),
690 di_key_sites: module.di_key_sites.clone(),
691 has_dynamic_provide: module.has_dynamic_provide,
692 is_server_action_module: module.is_server_action_module,
693 has_global_declarations: module.has_global_declarations,
694 triple_slash_reference_paths: module.triple_slash_reference_paths.clone(),
695 jsx_runtime_from_config: module.jsx_runtime_from_config,
696 component_props: module.component_props.clone(),
697 component_contracts: module.component_contracts.clone(),
698 has_props_attrs_fallthrough: module.has_props_attrs_fallthrough,
699 has_define_expose: module.has_define_expose,
700 has_define_model: module.has_define_model,
701 has_unharvestable_props: module.has_unharvestable_props,
702 component_emits: module.component_emits.clone(),
703 angular_inputs: module.angular_inputs.clone(),
704 angular_outputs: module.angular_outputs.clone(),
705 angular_component_selectors: module.angular_component_selectors.clone(),
706 registered_custom_elements: module.registered_custom_elements.clone(),
707 used_custom_element_tags: module.used_custom_element_tags.clone(),
708 angular_used_selectors: module.angular_used_selectors.clone(),
709 angular_entry_component_refs: module.angular_entry_component_refs.clone(),
710 has_dynamic_component_render: module.has_dynamic_component_render,
711 has_unharvestable_emits: module.has_unharvestable_emits,
712 has_dynamic_emit: module.has_dynamic_emit,
713 has_emit_whole_object_use: module.has_emit_whole_object_use,
714 load_return_keys: module.load_return_keys.clone(),
715 has_unharvestable_load: module.has_unharvestable_load,
716 has_load_data_whole_use: module.has_load_data_whole_use,
717 component_functions: module.component_functions.clone(),
718 react_props: module.react_props.clone(),
719 hook_uses: module.hook_uses.clone(),
720 render_edges: module.render_edges.clone(),
721 svelte_dispatched_events: module.svelte_dispatched_events.clone(),
722 svelte_listened_events: module.svelte_listened_events.clone(),
723 has_dynamic_dispatch: module.has_dynamic_dispatch,
724 }
725}
726
727#[cfg(test)]
732#[must_use]
733pub fn module_to_cached_from_parts(
734 module: &crate::ModuleInfo,
735 mtime_ns: u64,
736 file_size: u64,
737) -> CachedModule {
738 module_to_cached(
739 module,
740 fallow_types::source_fingerprint::SourceFingerprint::new(mtime_ns, file_size),
741 !module.complexity.is_empty(),
742 )
743}
744
745fn cached_semantic_facts(
746 facts: &[fallow_types::extract::SemanticFact],
747) -> Option<Box<[fallow_types::extract::SemanticFact]>> {
748 (!facts.is_empty()).then(|| Box::from(facts))
749}