1use std::collections::HashSet;
4use std::collections::VecDeque;
5
6use deno_ast::SourceRange;
7use indexmap::IndexMap;
8
9use crate::ModuleGraph;
10use crate::ModuleSpecifier;
11
12use super::FileDep;
13use super::FileDepName;
14use super::ModuleInfoRef;
15use super::Symbol;
16use super::SymbolDecl;
17use super::SymbolId;
18use super::SymbolNodeDep;
19use super::UniqueSymbolId;
20use super::analyzer::SymbolDeclKind;
21
22#[derive(Debug, Clone)]
23pub enum DefinitionOrUnresolved<'a> {
24 Definition(Definition<'a>),
25 Unresolved(DefinitionUnresolved<'a>),
26}
27
28impl<'a> DefinitionOrUnresolved<'a> {
29 pub fn module(&self) -> ModuleInfoRef<'a> {
30 match self {
31 DefinitionOrUnresolved::Definition(def) => def.module,
32 DefinitionOrUnresolved::Unresolved(unresolved) => unresolved.module,
33 }
34 }
35
36 pub fn symbol(&self) -> Option<&'a Symbol> {
37 match self {
38 DefinitionOrUnresolved::Definition(def) => Some(def.symbol),
39 DefinitionOrUnresolved::Unresolved(_) => None,
40 }
41 }
42}
43
44#[derive(Debug, Clone, PartialEq, Eq, Hash)]
45pub enum DefinitionKind<'a> {
46 ExportStar(&'a FileDep),
47 Definition,
48}
49
50#[derive(Debug, Clone)]
51pub struct Definition<'a> {
52 pub kind: DefinitionKind<'a>,
53 pub module: ModuleInfoRef<'a>,
54 pub symbol: &'a Symbol,
55 pub symbol_decl: &'a SymbolDecl,
56}
57
58impl Definition<'_> {
59 pub fn range(&self) -> &SourceRange {
60 &self.symbol_decl.range
61 }
62
63 pub fn byte_range(&self) -> std::ops::Range<usize> {
64 self
65 .range()
66 .as_byte_range(self.module.text_info().range().start)
67 }
68
69 pub fn text(&self) -> &str {
70 self.module.text_info().range_text(self.range())
71 }
72}
73
74#[derive(Debug, Clone)]
75pub enum DefinitionUnresolvedKind {
76 Id(deno_ast::swc::ast::Id),
78 Specifier(String),
80 Part(String),
82}
83
84#[derive(Debug, Clone)]
86pub struct DefinitionUnresolved<'a> {
87 pub module: ModuleInfoRef<'a>,
88 pub kind: DefinitionUnresolvedKind,
89 pub parts: Vec<String>,
90}
91
92#[derive(Debug, Clone)]
93pub struct DefinitionPathLink<'a> {
94 pub module: ModuleInfoRef<'a>,
95 pub symbol: &'a Symbol,
96 pub symbol_decl: &'a SymbolDecl,
97 pub parts: Vec<String>,
98 pub next: Vec<DefinitionPathNode<'a>>,
99}
100
101#[derive(Debug, Clone)]
102pub enum DefinitionPathNodeResolved<'a> {
103 Link(DefinitionPathLink<'a>),
104 Definition(Definition<'a>),
105}
106
107impl<'a> DefinitionPathNodeResolved<'a> {
108 pub fn symbol(&self) -> Option<&'a Symbol> {
109 match self {
110 Self::Link(link) => Some(link.symbol),
111 Self::Definition(def) => Some(def.symbol),
112 }
113 }
114
115 pub fn module(&self) -> ModuleInfoRef<'a> {
116 match self {
117 Self::Link(link) => link.module,
118 Self::Definition(def) => def.module,
119 }
120 }
121}
122
123#[derive(Debug, Clone)]
125pub enum DefinitionPathNode<'a> {
126 Resolved(DefinitionPathNodeResolved<'a>),
127 Unresolved(DefinitionUnresolved<'a>),
128}
129
130impl<'a> DefinitionPathNode<'a> {
131 fn definition(definition: Definition<'a>) -> Self {
132 Self::Resolved(DefinitionPathNodeResolved::Definition(definition))
133 }
134
135 fn link(link: DefinitionPathLink<'a>) -> Self {
136 Self::Resolved(DefinitionPathNodeResolved::Link(link))
137 }
138
139 pub fn module(&self) -> ModuleInfoRef<'a> {
140 match self {
141 Self::Resolved(resolved) => resolved.module(),
142 Self::Unresolved(unresolved) => unresolved.module,
143 }
144 }
145
146 pub fn into_definitions(self) -> impl Iterator<Item = Definition<'a>> {
147 self
148 .into_definitions_or_unresolveds()
149 .filter_map(|d| match d {
150 DefinitionOrUnresolved::Definition(d) => Some(d),
151 DefinitionOrUnresolved::Unresolved(_) => None,
152 })
153 }
154
155 pub fn into_definitions_or_unresolveds(
156 self,
157 ) -> impl Iterator<Item = DefinitionOrUnresolved<'a>> {
158 struct IntoIterator<'a> {
159 queue: VecDeque<DefinitionPathNode<'a>>,
160 }
161
162 impl<'a> Iterator for IntoIterator<'a> {
163 type Item = DefinitionOrUnresolved<'a>;
164
165 fn next(&mut self) -> Option<Self::Item> {
166 while let Some(path) = self.queue.pop_front() {
167 match path {
168 DefinitionPathNode::Resolved(DefinitionPathNodeResolved::Link(
169 link,
170 )) => {
171 for child_path in link.next.into_iter().rev() {
172 self.queue.push_front(child_path);
173 }
174 }
175 DefinitionPathNode::Resolved(
176 DefinitionPathNodeResolved::Definition(def),
177 ) => {
178 return Some(DefinitionOrUnresolved::Definition(def));
179 }
180 DefinitionPathNode::Unresolved(unresolved) => {
181 return Some(DefinitionOrUnresolved::Unresolved(unresolved));
182 }
183 }
184 }
185
186 None
187 }
188 }
189
190 IntoIterator {
191 queue: VecDeque::from([self]),
192 }
193 }
194}
195
196pub fn find_definition_paths<'a>(
198 module_graph: &'a ModuleGraph,
199 module: ModuleInfoRef<'a>,
200 symbol: &'a Symbol,
201 specifier_to_module: &impl Fn(&ModuleSpecifier) -> Option<ModuleInfoRef<'a>>,
202) -> Vec<DefinitionPathNode<'a>> {
203 find_definition_paths_internal(
204 module_graph,
205 module,
206 symbol,
207 &mut Default::default(),
208 specifier_to_module,
209 )
210}
211
212fn find_definition_paths_internal<'a>(
213 module_graph: &'a ModuleGraph,
214 module: ModuleInfoRef<'a>,
215 symbol: &'a Symbol,
216 visited_symbols: &mut HashSet<UniqueSymbolId>,
217 specifier_to_module: &impl Fn(&ModuleSpecifier) -> Option<ModuleInfoRef<'a>>,
218) -> Vec<DefinitionPathNode<'a>> {
219 debug_assert_eq!(module.module_id(), symbol.module_id());
220 if !visited_symbols.insert(symbol.unique_id()) {
221 return Vec::new();
222 }
223 let mut paths = Vec::with_capacity(symbol.decls().len());
224 for decl in symbol.decls() {
225 match &decl.kind {
226 SymbolDeclKind::Definition(_) => {
227 paths.push(DefinitionPathNode::definition(Definition {
228 module,
229 symbol,
230 symbol_decl: decl,
231 kind: DefinitionKind::Definition,
232 }));
233 }
234 SymbolDeclKind::Target(target_id) => {
235 if let Some(symbol) = module
236 .esm()
237 .unwrap()
238 .symbol_id_from_swc(target_id)
239 .and_then(|id| module.symbol(id))
240 {
241 let inner_paths = find_definition_paths_internal(
242 module_graph,
243 module,
244 symbol,
245 visited_symbols,
246 specifier_to_module,
247 );
248 if !inner_paths.is_empty() {
249 paths.push(DefinitionPathNode::link(DefinitionPathLink {
250 module,
251 symbol,
252 symbol_decl: decl,
253 parts: Vec::new(),
254 next: inner_paths,
255 }));
256 }
257 }
258 }
259 SymbolDeclKind::QualifiedTarget(target_id, parts) => {
260 let inner_paths = go_to_id_and_parts_definition_paths(
261 module_graph,
262 module,
263 target_id,
264 parts,
265 specifier_to_module,
266 );
267 if !inner_paths.is_empty() {
268 paths.push(DefinitionPathNode::link(DefinitionPathLink {
269 module,
270 symbol,
271 symbol_decl: decl,
272 parts: parts.clone(),
273 next: inner_paths,
274 }));
275 }
276 }
277 SymbolDeclKind::FileRef(file_ref) => match &file_ref.name {
278 FileDepName::Star => {
279 paths.push(DefinitionPathNode::definition(Definition {
280 module,
281 symbol,
282 kind: DefinitionKind::ExportStar(file_ref),
283 symbol_decl: decl,
284 }));
285 }
286 FileDepName::Name(export_name) => {
287 let inner_paths = go_to_file_export(
288 module_graph,
289 module,
290 file_ref,
291 export_name,
292 specifier_to_module,
293 visited_symbols,
294 );
295 if !inner_paths.is_empty() {
296 paths.push(DefinitionPathNode::link(DefinitionPathLink {
297 module,
298 symbol,
299 symbol_decl: decl,
300 parts: Vec::new(),
301 next: inner_paths,
302 }));
303 }
304 }
305 },
306 }
307 }
308 paths
309}
310
311fn go_to_file_export<'a>(
312 module_graph: &'a ModuleGraph,
313 referrer_module: ModuleInfoRef<'a>,
314 file_ref: &'a FileDep,
315 export_name: &'a str,
316 specifier_to_module: &impl Fn(&ModuleSpecifier) -> Option<ModuleInfoRef<'a>>,
317 visited_symbols: &mut HashSet<UniqueSymbolId>,
318) -> Vec<DefinitionPathNode<'a>> {
319 let maybe_dep_module = module_graph
320 .resolve_dependency(
321 &file_ref.specifier,
322 referrer_module.specifier(),
323 true,
324 )
325 .and_then(specifier_to_module);
326
327 let Some(dep_module) = maybe_dep_module else {
328 return vec![DefinitionPathNode::Unresolved(DefinitionUnresolved {
329 module: referrer_module,
330 kind: DefinitionUnresolvedKind::Specifier(file_ref.specifier.clone()),
331 parts: Vec::new(),
332 })];
333 };
334 let maybe_export_symbol = dep_module
335 .module_symbol()
336 .exports()
337 .get(export_name)
338 .and_then(|symbol_id| dep_module.symbol(*symbol_id));
339 match maybe_export_symbol {
340 Some(export_symbol) => find_definition_paths_internal(
341 module_graph,
342 dep_module,
343 export_symbol,
344 visited_symbols,
345 specifier_to_module,
346 ),
347 None => {
348 if let Some(re_export_all_specifiers) =
350 dep_module.re_export_all_specifiers()
351 {
352 for re_export_specifier in re_export_all_specifiers {
353 let maybe_specifier = module_graph.resolve_dependency(
354 re_export_specifier,
355 dep_module.specifier(),
356 true,
357 );
358 let maybe_module = maybe_specifier.and_then(specifier_to_module);
359 let mut visited = HashSet::new();
360 if let Some(module) = maybe_module {
361 let inner = exports_and_re_exports_inner(
363 module_graph,
364 module,
365 specifier_to_module,
366 &mut visited,
367 );
368 for (name, item) in inner.resolved {
369 if name == export_name {
370 let resolved_rexport = item.as_resolved_export();
371 let paths = find_definition_paths_internal(
372 module_graph,
373 resolved_rexport.module,
374 resolved_rexport.symbol(),
375 visited_symbols,
376 specifier_to_module,
377 );
378 if !paths.is_empty() {
379 return paths;
380 }
381 break;
382 }
383 }
384 }
385 }
386 }
387 vec![DefinitionPathNode::Unresolved(DefinitionUnresolved {
388 module: dep_module,
389 kind: DefinitionUnresolvedKind::Part(export_name.to_string()),
390 parts: Vec::new(),
391 })]
392 }
393 }
394}
395
396#[derive(Debug)]
398pub enum ResolvedSymbolDepEntry<'a> {
399 Path(DefinitionPathNode<'a>),
401 ImportType(ModuleInfoRef<'a>),
405}
406
407pub fn resolve_symbol_dep<'a>(
408 module_graph: &'a ModuleGraph,
409 module: ModuleInfoRef<'a>,
410 dep: &SymbolNodeDep,
411 specifier_to_module: &impl Fn(&ModuleSpecifier) -> Option<ModuleInfoRef<'a>>,
412) -> Vec<ResolvedSymbolDepEntry<'a>> {
413 match dep {
414 SymbolNodeDep::Id(id) => {
415 if let Some(dep_symbol) = module.esm().and_then(|m| m.symbol_from_swc(id))
416 {
417 find_definition_paths(
418 module_graph,
419 module,
420 dep_symbol,
421 specifier_to_module,
422 )
423 .into_iter()
424 .map(ResolvedSymbolDepEntry::Path)
425 .collect()
426 } else {
427 vec![ResolvedSymbolDepEntry::Path(
428 DefinitionPathNode::Unresolved(DefinitionUnresolved {
429 module,
430 kind: DefinitionUnresolvedKind::Id(id.clone()),
431 parts: Vec::new(),
432 }),
433 )]
434 }
435 }
436 SymbolNodeDep::QualifiedId(id, parts) => {
437 go_to_id_and_parts_definition_paths(
438 module_graph,
439 module,
440 id,
441 parts,
442 specifier_to_module,
443 )
444 .into_iter()
445 .map(ResolvedSymbolDepEntry::Path)
446 .collect()
447 }
448 SymbolNodeDep::ImportType(import_specifier, parts) => {
449 let maybe_dep_specifier = module_graph.resolve_dependency(
450 import_specifier,
451 module.specifier(),
452 true,
453 );
454 let maybe_module = maybe_dep_specifier.and_then(specifier_to_module);
455 let Some(module) = maybe_module else {
456 return vec![ResolvedSymbolDepEntry::Path(
457 DefinitionPathNode::Unresolved(DefinitionUnresolved {
458 module,
459 kind: DefinitionUnresolvedKind::Specifier(import_specifier.clone()),
460 parts: parts.clone(),
461 }),
462 )];
463 };
464 if parts.is_empty() {
465 vec![ResolvedSymbolDepEntry::ImportType(module)]
467 } else {
468 resolve_qualified_export_name(
469 module_graph,
470 module,
471 parts,
472 specifier_to_module,
473 )
474 .into_iter()
475 .map(ResolvedSymbolDepEntry::Path)
476 .collect()
477 }
478 }
479 }
480}
481
482fn go_to_id_and_parts_definition_paths<'a>(
483 module_graph: &'a ModuleGraph,
484 module: ModuleInfoRef<'a>,
485 target_id: &deno_ast::swc::ast::Id,
486 parts: &[String],
487 specifier_to_module: &impl Fn(&ModuleSpecifier) -> Option<ModuleInfoRef<'a>>,
488) -> Vec<DefinitionPathNode<'a>> {
489 if let Some(symbol_id) =
490 module.esm().and_then(|m| m.symbol_id_from_swc(target_id))
491 {
492 resolve_qualified_name(
493 module_graph,
494 module,
495 module.symbol(symbol_id).unwrap(),
496 parts,
497 specifier_to_module,
498 )
499 } else {
500 vec![DefinitionPathNode::Unresolved(DefinitionUnresolved {
501 module,
502 kind: DefinitionUnresolvedKind::Id(target_id.clone()),
503 parts: parts.to_vec(),
504 })]
505 }
506}
507
508fn resolve_qualified_export_name<'a>(
509 graph: &'a ModuleGraph,
510 module: ModuleInfoRef<'a>,
511 parts: &[String],
512 specifier_to_module: &impl Fn(&ModuleSpecifier) -> Option<ModuleInfoRef<'a>>,
513) -> Vec<DefinitionPathNode<'a>> {
514 debug_assert!(!parts.is_empty());
515 resolve_qualified_export_name_internal(
516 graph,
517 module,
518 parts,
519 &mut HashSet::new(),
520 specifier_to_module,
521 )
522}
523
524fn resolve_qualified_export_name_internal<'a>(
525 graph: &'a ModuleGraph,
526 module: ModuleInfoRef<'a>,
527 parts: &[String],
528 visited_symbols: &mut HashSet<UniqueSymbolId>,
529 specifier_to_module: &impl Fn(&ModuleSpecifier) -> Option<ModuleInfoRef<'a>>,
530) -> Vec<DefinitionPathNode<'a>> {
531 debug_assert!(!parts.is_empty());
532 let exports = exports_and_re_exports(graph, module, specifier_to_module);
533 let export_name = &parts[0];
534 if let Some(resolved) = exports.resolved.get(export_name) {
535 let resolved = resolved.as_resolved_export();
536 resolve_qualified_name_internal(
537 graph,
538 resolved.module,
539 resolved.symbol(),
540 &parts[1..],
541 visited_symbols,
542 specifier_to_module,
543 )
544 } else {
545 vec![DefinitionPathNode::Unresolved(DefinitionUnresolved {
546 module,
547 kind: DefinitionUnresolvedKind::Part(export_name.to_string()),
548 parts: parts.to_vec(),
549 })]
550 }
551}
552
553pub fn resolve_qualified_name<'a>(
554 graph: &'a ModuleGraph,
555 module: ModuleInfoRef<'a>,
556 symbol: &'a Symbol,
557 parts: &[String],
558 specifier_to_module: &impl Fn(&ModuleSpecifier) -> Option<ModuleInfoRef<'a>>,
559) -> Vec<DefinitionPathNode<'a>> {
560 resolve_qualified_name_internal(
561 graph,
562 module,
563 symbol,
564 parts,
565 &mut HashSet::new(),
566 specifier_to_module,
567 )
568}
569
570fn resolve_qualified_name_internal<'a>(
571 graph: &'a ModuleGraph,
572 module: ModuleInfoRef<'a>,
573 symbol: &'a Symbol,
574 parts: &[String],
575 visited_symbols: &mut HashSet<UniqueSymbolId>,
576 specifier_to_module: &impl Fn(&ModuleSpecifier) -> Option<ModuleInfoRef<'a>>,
577) -> Vec<DefinitionPathNode<'a>> {
578 fn resolve_paths_with_parts<'a>(
579 paths: Vec<DefinitionPathNode<'a>>,
580 parts: &[String],
581 graph: &'a ModuleGraph,
582 visited_symbols: &mut HashSet<UniqueSymbolId>,
583 specifier_to_module: &impl Fn(&url::Url) -> Option<ModuleInfoRef<'a>>,
584 ) -> Vec<DefinitionPathNode<'a>> {
585 debug_assert!(!parts.is_empty());
586 paths
587 .into_iter()
588 .flat_map(|path| {
589 resolve_path_with_parts(
590 path,
591 parts,
592 graph,
593 visited_symbols,
594 specifier_to_module,
595 )
596 })
597 .collect()
598 }
599
600 fn resolve_path_with_parts<'a>(
601 path: DefinitionPathNode<'a>,
602 parts: &[String],
603 graph: &'a ModuleGraph,
604 visited_symbols: &mut HashSet<UniqueSymbolId>,
605 specifier_to_module: &impl Fn(&url::Url) -> Option<ModuleInfoRef<'a>>,
606 ) -> Option<DefinitionPathNode<'a>> {
607 match path {
608 DefinitionPathNode::Resolved(DefinitionPathNodeResolved::Link(link)) => {
609 let next = resolve_paths_with_parts(
610 link.next,
611 parts,
612 graph,
613 visited_symbols,
614 specifier_to_module,
615 );
616 if next.is_empty() {
617 None
618 } else {
619 Some(DefinitionPathNode::link(DefinitionPathLink {
620 module: link.module,
621 symbol: link.symbol,
622 symbol_decl: link.symbol_decl,
623 parts: parts.to_vec(),
624 next,
625 }))
626 }
627 }
628 DefinitionPathNode::Resolved(DefinitionPathNodeResolved::Definition(
629 definition,
630 )) => {
631 let next_part = &parts[0];
632 let mut next = Vec::new();
633 match definition.kind {
634 DefinitionKind::Definition => {
635 if let Some(export_symbol_id) = definition.symbol.export(next_part)
636 {
637 next.extend(resolve_qualified_name_internal(
638 graph,
639 definition.module,
640 definition.module.symbol(export_symbol_id).unwrap(),
641 &parts[1..],
642 visited_symbols,
643 specifier_to_module,
644 ));
645 } else if next_part == "prototype"
646 && definition.symbol_decl.is_class()
647 {
648 debug_assert!(next.is_empty());
650 return Some(DefinitionPathNode::definition(definition.clone()));
651 } else {
652 next.push(DefinitionPathNode::Unresolved(DefinitionUnresolved {
653 module: definition.module,
654 kind: DefinitionUnresolvedKind::Part(next_part.to_string()),
655 parts: parts.to_vec(),
656 }))
657 }
658 }
659 DefinitionKind::ExportStar(file_dep) => {
660 let maybe_dep_specifier = graph.resolve_dependency(
661 &file_dep.specifier,
662 definition.module.specifier(),
663 true,
664 );
665 let specifier_module =
666 maybe_dep_specifier.and_then(specifier_to_module);
667 if let Some(module) = specifier_module {
668 next.extend(resolve_qualified_export_name_internal(
669 graph,
670 module,
671 parts,
672 visited_symbols,
673 specifier_to_module,
674 ));
675 } else {
676 next.push(DefinitionPathNode::Unresolved(DefinitionUnresolved {
677 module: definition.module,
678 kind: DefinitionUnresolvedKind::Specifier(
679 file_dep.specifier.to_string(),
680 ),
681 parts: parts.to_vec(),
682 }))
683 }
684 }
685 }
686
687 if next.is_empty() {
688 None
689 } else {
690 Some(DefinitionPathNode::link(DefinitionPathLink {
692 module: definition.module,
693 symbol: definition.symbol,
694 symbol_decl: definition.symbol_decl,
695 parts: parts.to_vec(),
696 next,
697 }))
698 }
699 }
700 DefinitionPathNode::Unresolved(unresolved) => {
701 Some(DefinitionPathNode::Unresolved(unresolved))
702 }
703 }
704 }
705
706 let paths = find_definition_paths_internal(
707 graph,
708 module,
709 symbol,
710 visited_symbols,
711 specifier_to_module,
712 );
713 if !parts.is_empty() {
714 resolve_paths_with_parts(
715 paths,
716 parts,
717 graph,
718 visited_symbols,
719 specifier_to_module,
720 )
721 } else {
722 paths
723 }
724}
725
726#[derive(Debug, Default, Clone)]
727pub struct ModuleExports<'a> {
728 pub resolved: IndexMap<String, ResolvedExportOrReExportAllPath<'a>>,
729 pub unresolved_specifiers: Vec<UnresolvedSpecifier<'a>>,
730}
731
732#[derive(Debug, Clone)]
736pub struct ResolvedExport<'a> {
737 pub module: ModuleInfoRef<'a>,
738 pub symbol_id: SymbolId,
739}
740
741impl<'a> ResolvedExport<'a> {
742 pub fn symbol(&self) -> &'a Symbol {
743 self.module.symbol(self.symbol_id).unwrap()
744 }
745}
746
747#[derive(Debug, Clone)]
748pub struct ResolvedReExportAllPath<'a> {
749 pub referrer_module: ModuleInfoRef<'a>,
751 pub specifier: &'a str,
753 pub next: Box<ResolvedExportOrReExportAllPath<'a>>,
755}
756
757impl ResolvedReExportAllPath<'_> {
758 pub fn resolved_module(&self) -> ModuleInfoRef<'_> {
759 match &*self.next {
760 ResolvedExportOrReExportAllPath::Export(e) => e.module,
761 ResolvedExportOrReExportAllPath::ReExportAllPath(e) => e.referrer_module,
762 }
763 }
764}
765
766#[derive(Debug, Clone)]
767pub enum ResolvedExportOrReExportAllPath<'a> {
768 Export(ResolvedExport<'a>),
769 ReExportAllPath(ResolvedReExportAllPath<'a>),
770}
771
772impl<'a> ResolvedExportOrReExportAllPath<'a> {
773 pub fn as_resolved_export(&self) -> &ResolvedExport<'a> {
774 match self {
775 ResolvedExportOrReExportAllPath::Export(export) => export,
776 ResolvedExportOrReExportAllPath::ReExportAllPath(re_export) => {
777 re_export.next.as_resolved_export()
778 }
779 }
780 }
781
782 pub fn iter(
783 &self,
784 ) -> impl Iterator<Item = &ResolvedExportOrReExportAllPath<'a>> {
785 std::iter::successors(Some(self), |last| match last {
786 ResolvedExportOrReExportAllPath::Export(_) => None,
787 ResolvedExportOrReExportAllPath::ReExportAllPath(re_export) => {
788 Some(&re_export.next)
789 }
790 })
791 }
792}
793
794#[derive(Debug, Clone)]
795pub struct UnresolvedSpecifier<'a> {
796 pub referrer: ModuleInfoRef<'a>,
797 pub specifier: &'a str,
798}
799
800pub fn exports_and_re_exports<'a>(
801 module_graph: &'a ModuleGraph,
802 module: ModuleInfoRef<'a>,
803 specifier_to_module: &impl Fn(&ModuleSpecifier) -> Option<ModuleInfoRef<'a>>,
804) -> ModuleExports<'a> {
805 exports_and_re_exports_inner(
806 module_graph,
807 module,
808 specifier_to_module,
809 &mut Default::default(),
810 )
811}
812
813fn exports_and_re_exports_inner<'a>(
814 module_graph: &'a ModuleGraph,
815 module: ModuleInfoRef<'a>,
816 specifier_to_module: &impl Fn(&ModuleSpecifier) -> Option<ModuleInfoRef<'a>>,
817 visited: &mut HashSet<&'a ModuleSpecifier>,
818) -> ModuleExports<'a> {
819 if !visited.insert(module.specifier()) {
820 return ModuleExports::default();
821 }
822
823 let mut unresolved_specifiers = Vec::new();
824 let mut resolved = IndexMap::new();
825 for (name, symbol_id) in module.module_symbol().exports() {
826 resolved.insert(
827 name.clone(),
828 ResolvedExportOrReExportAllPath::Export(ResolvedExport {
829 module,
830 symbol_id: *symbol_id,
831 }),
832 );
833 }
834 if let Some(re_export_all_specifier) = module.re_export_all_specifiers() {
835 let referrer_module = module;
836 for re_export_specifier in re_export_all_specifier {
837 let maybe_specifier = module_graph.resolve_dependency(
838 re_export_specifier,
839 module.specifier(),
840 true,
841 );
842 let maybe_module = maybe_specifier.and_then(specifier_to_module);
843 if let Some(module) = maybe_module {
844 let inner = exports_and_re_exports_inner(
845 module_graph,
846 module,
847 specifier_to_module,
848 visited,
849 );
850 for (name, item) in inner.resolved {
851 if name != "default" && !resolved.contains_key(&name) {
852 resolved.insert(
853 name,
854 ResolvedExportOrReExportAllPath::ReExportAllPath(
855 ResolvedReExportAllPath {
856 referrer_module,
857 specifier: re_export_specifier,
858 next: Box::new(item),
859 },
860 ),
861 );
862 }
863 }
864 unresolved_specifiers.extend(inner.unresolved_specifiers);
865 } else {
866 unresolved_specifiers.push(UnresolvedSpecifier {
867 referrer: module,
868 specifier: re_export_specifier,
869 });
870 }
871 }
872 }
873 ModuleExports {
874 resolved,
875 unresolved_specifiers,
876 }
877}