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