1use alloc::vec::Vec;
10
11use hir_lang::{
12 BinderId, BinderKind, Def, DefId, ExpnId, Hir, IdKind, ItemId, ItemKind, Name, NodeRef, Origin,
13 PathId, Span, Symbol, UnitId, VariantId,
14};
15
16use crate::model::{NONE, ix};
17
18#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
28#[non_exhaustive]
29pub enum SymbolKind {
30 Module,
32 Function,
34 Record,
36 Sum,
38 Variant,
40 Class,
42 Mixin,
44 Interface,
46 Impl,
48 Alias,
50 AssocType,
52 Const,
54 Global,
56 Import,
58 Local,
60 Param,
62 Capture,
64 TypeParam,
66 ConstParam,
68 Region,
70 Label,
72 Place,
75 External,
78}
79
80impl SymbolKind {
81 #[must_use]
91 pub const fn name(self) -> &'static str {
92 match self {
93 Self::Module => "module",
94 Self::Function => "function",
95 Self::Record => "record",
96 Self::Sum => "sum",
97 Self::Variant => "variant",
98 Self::Class => "class",
99 Self::Mixin => "mixin",
100 Self::Interface => "interface",
101 Self::Impl => "impl",
102 Self::Alias => "alias",
103 Self::AssocType => "associated type",
104 Self::Const => "constant",
105 Self::Global => "global",
106 Self::Import => "import",
107 Self::Local => "local",
108 Self::Param => "parameter",
109 Self::Capture => "capture",
110 Self::TypeParam => "type parameter",
111 Self::ConstParam => "const parameter",
112 Self::Region => "region",
113 Self::Label => "label",
114 Self::Place => "place alias",
115 Self::External => "external",
116 }
117 }
118
119 const fn of_item(kind: &ItemKind) -> Self {
120 match kind {
121 ItemKind::Fn(_) => Self::Function,
122 ItemKind::Record(_) => Self::Record,
123 ItemKind::Sum(_) => Self::Sum,
124 ItemKind::Class(c) if c.mixin => Self::Mixin,
125 ItemKind::Class(_) => Self::Class,
126 ItemKind::Interface(_) => Self::Interface,
127 ItemKind::Impl(_) => Self::Impl,
128 ItemKind::Alias { .. } => Self::Alias,
129 ItemKind::AssocType { .. } => Self::AssocType,
130 ItemKind::Const { .. } => Self::Const,
131 ItemKind::Global { .. } => Self::Global,
132 ItemKind::Module { .. } | ItemKind::Err => Self::Module,
133 ItemKind::Import { .. } | ItemKind::MixinUse(_) => Self::Import,
134 }
135 }
136
137 const fn of_binder(kind: BinderKind) -> Self {
138 match kind {
139 BinderKind::Local => Self::Local,
140 BinderKind::Param => Self::Param,
141 BinderKind::Capture => Self::Capture,
142 BinderKind::TypeParam => Self::TypeParam,
143 BinderKind::ConstParam => Self::ConstParam,
144 BinderKind::Region => Self::Region,
145 BinderKind::Label => Self::Label,
146 BinderKind::Place => Self::Place,
147 }
148 }
149}
150
151#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
163pub enum Target {
164 Def(DefId),
166 Local(UnitId, BinderId),
168 Extern(Symbol),
170 Import(UnitId, ItemId),
172}
173
174#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
186pub struct Location {
187 pub unit: UnitId,
189 pub span: Span,
192 pub in_source: bool,
195}
196
197#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
207pub struct DefRef(u32);
208
209impl DefRef {
210 #[must_use]
220 pub const fn index(self) -> usize {
221 self.0 as usize
222 }
223
224 #[must_use]
234 pub const fn from_index(i: usize) -> Self {
235 Self(if i > u32::MAX as usize {
236 u32::MAX
237 } else {
238 i as u32
239 })
240 }
241}
242
243#[derive(Clone, Copy, Debug, PartialEq, Eq)]
263pub struct Definition {
264 pub target: Target,
266 pub name: Name,
268 pub kind: SymbolKind,
270 pub location: Option<Location>,
273 pub range: Option<Location>,
275 pub parent: Option<DefRef>,
277}
278
279#[derive(Clone, Copy, Debug, PartialEq, Eq)]
290pub struct Reference {
291 pub location: Location,
293 pub def: DefRef,
295 pub path: PathId,
297 pub segment: u32,
299 pub name: Name,
302 pub via: Option<DefRef>,
304}
305
306#[derive(Clone, Copy, Debug, PartialEq, Eq)]
317pub struct Occurrence {
318 pub def: DefRef,
320 pub reference: Option<u32>,
323}
324
325impl Occurrence {
326 #[must_use]
337 pub const fn is_definition(&self) -> bool {
338 self.reference.is_none()
339 }
340}
341
342#[derive(Clone, Debug)]
355pub struct References<'a> {
356 refs: &'a [Reference],
357 ids: core::slice::Iter<'a, u32>,
358}
359
360impl<'a> Iterator for References<'a> {
361 type Item = &'a Reference;
362
363 fn next(&mut self) -> Option<&'a Reference> {
364 self.ids.find_map(|i| self.refs.get(*i as usize))
367 }
368
369 fn size_hint(&self) -> (usize, Option<usize>) {
370 (self.ids.len(), Some(self.ids.len()))
371 }
372}
373
374impl ExactSizeIterator for References<'_> {}
375
376#[derive(Clone, Debug, Default, PartialEq, Eq)]
387pub struct RenameSet {
388 pub edits: Vec<Location>,
391 pub outside_source: Vec<Location>,
394}
395
396#[derive(Clone, Debug, Default)]
398struct UnitIx {
399 id: UnitId,
400 item_def: Vec<u32>,
401 variant_def: Vec<u32>,
402 binder_def: Vec<u32>,
403 path_off: Vec<u32>,
405 symbols: Vec<u32>,
407 occ: Vec<(u32, u32, u32, u32)>,
409}
410
411#[derive(Clone, Debug, Default)]
442pub struct Index {
443 defs: Vec<Definition>,
444 refs: Vec<Reference>,
445 by_def_off: Vec<u32>,
446 by_def: Vec<u32>,
447 by_via: Vec<(u32, u32)>,
449 externals: Vec<(Target, u32)>,
451 units: Vec<UnitIx>,
452 same_name: Vec<bool>,
455}
456
457struct Mapper {
459 unit: UnitId,
460 sites: Vec<Span>,
462}
463
464impl Mapper {
465 fn new(hir: &Hir) -> Self {
466 let n = hir.count(IdKind::Expansion);
467 let mut sites: Vec<Span> = Vec::with_capacity(n);
468 for i in 1..=n {
469 let e = hir.expansion(ExpnId::from_u32(ix(i)));
470 let site = match e {
471 Some(e) if e.parent.is_root() => e.call_site,
472 Some(e) => sites
473 .get((e.parent.as_u32() as usize).saturating_sub(1))
474 .copied()
475 .unwrap_or(e.call_site),
476 None => Span::empty(0),
477 };
478 sites.push(site);
479 }
480 Self {
481 unit: hir.unit(),
482 sites,
483 }
484 }
485
486 fn map(&self, origin: Origin) -> Location {
487 self.span(origin.span, origin.expn)
488 }
489
490 fn span(&self, span: Span, expn: ExpnId) -> Location {
491 if expn.is_root() {
492 return Location {
493 unit: self.unit,
494 span,
495 in_source: true,
496 };
497 }
498 let site = self
499 .sites
500 .get((expn.as_u32() as usize).saturating_sub(1))
501 .copied()
502 .unwrap_or(span);
503 Location {
504 unit: self.unit,
505 span: site,
506 in_source: false,
507 }
508 }
509}
510
511pub(crate) struct RawRef {
514 pub(crate) path: PathId,
515 pub(crate) seg: u32,
516 pub(crate) target: Target,
517 pub(crate) via: Option<Target>,
518}
519
520pub(crate) struct UnitInput<'a> {
522 pub(crate) hir: &'a Hir,
523 pub(crate) refs: Vec<RawRef>,
524 pub(crate) dead_binders: Vec<BinderId>,
526 pub(crate) aliases: Vec<ItemId>,
528}
529
530impl Index {
531 pub(crate) fn build(units: &[UnitInput<'_>], fold: &crate::model::Fold) -> Self {
534 let mut me = Self::default();
535 let mut maps: Vec<Mapper> = Vec::with_capacity(units.len());
536 for u in units {
537 maps.push(Mapper::new(u.hir));
538 me.units.push(UnitIx {
539 id: u.hir.unit(),
540 item_def: alloc::vec![NONE; u.hir.count(IdKind::Item)],
541 variant_def: alloc::vec![NONE; u.hir.count(IdKind::Variant)],
542 binder_def: alloc::vec![NONE; u.hir.count(IdKind::Binder)],
543 path_off: Vec::new(),
544 symbols: Vec::new(),
545 occ: Vec::new(),
546 });
547 }
548 for (ui, u) in units.iter().enumerate() {
549 let Some(map) = maps.get(ui) else { continue };
550 me.collect_defs(ui, u, map);
551 }
552 let mut externals: Vec<(Target, u32)> = Vec::new();
555 let mut by_via: Vec<(u32, u32)> = Vec::new();
556 for (ui, u) in units.iter().enumerate() {
557 let Some(map) = maps.get(ui) else { continue };
558 let mut refs: Vec<&RawRef> = u.refs.iter().collect();
559 refs.sort_by_key(|r| (r.path, r.seg));
560 refs.dedup_by_key(|r| (r.path, r.seg));
561 let n_paths = u.hir.count(IdKind::Path);
562 let mut off: Vec<u32> = alloc::vec![0; n_paths + 1];
563 for r in refs {
564 let path = u.hir.path(r.path);
565 let Some(seg) = u.hir.list(path.segments).get(r.seg as usize) else {
566 continue;
567 };
568 let Some(def) = me.target_def(r.target, seg.name, &mut externals) else {
569 continue;
570 };
571 let via = r.via.and_then(|t| me.find_target(t, &externals));
572 if let Some(v) = via {
573 by_via.push((v.0, ix(me.refs.len())));
574 }
575 let same = me.defs.get(def as usize).is_some_and(|d| {
576 d.name == seg.name
577 || (via.is_none() && fold.name(d.name) == fold.name(seg.name))
578 });
579 me.same_name.push(same);
580 let reference = Reference {
581 location: map.map(seg.origin),
582 def: DefRef(def),
583 path: r.path,
584 segment: r.seg,
585 name: seg.name,
586 via,
587 };
588 if let Some(o) = off.get_mut(r.path.index() + 1) {
589 *o += 1;
590 }
591 me.refs.push(reference);
592 }
593 let base = ix(me.refs.len()) - off.iter().sum::<u32>();
596 let mut acc = base;
597 for o in &mut off {
598 acc += *o;
599 *o = acc;
600 }
601 if let Some(slot) = me.units.get_mut(ui) {
602 slot.path_off = off;
603 }
604 }
605 by_via.sort_unstable();
606 me.by_via = by_via;
607 me.externals = externals;
608 me.build_by_def();
609 me.build_occurrences();
610 me
611 }
612
613 fn push_def(&mut self, d: Definition) -> u32 {
614 let i = ix(self.defs.len());
615 self.defs.push(d);
616 i
617 }
618
619 fn collect_defs(&mut self, ui: usize, u: &UnitInput<'_>, map: &Mapper) {
620 let hir = u.hir;
621 let unit = hir.unit();
622 let mut stack: Vec<u32> = Vec::new();
623 let mut dead = u.dead_binders.clone();
624 dead.sort();
625 let mut symbols: Vec<u32> = Vec::new();
626 let mut items: Vec<(ItemId, u32)> = Vec::new();
627 let mut variants: Vec<(VariantId, u32)> = Vec::new();
628 let mut binders: Vec<(BinderId, u32)> = Vec::new();
629 let root = hir.root();
630 let mut defs_out: Vec<Definition> = Vec::new();
631 let base = ix(self.defs.len());
632 hir.walk_from(NodeRef::Item(root), |ev| {
633 match ev {
634 hir_lang::Event::Enter(NodeRef::Item(i)) => {
635 let item = hir.item(i);
636 let alias = u.aliases.binary_search(&i).is_ok();
637 let named = item.name.filter(|_| {
638 !matches!(item.kind, ItemKind::Import { .. } | ItemKind::MixinUse(_))
639 || alias
640 });
641 match named {
642 Some(name) if i != root || item.name.is_some() => {
643 let target = if alias {
644 Target::Import(unit, i)
645 } else {
646 Target::Def(DefId::foreign(unit, Def::Item(i)))
647 };
648 let d = base + ix(defs_out.len());
649 defs_out.push(Definition {
650 target,
651 name,
652 kind: if alias {
653 SymbolKind::Import
654 } else {
655 SymbolKind::of_item(&item.kind)
656 },
657 location: (item.name_span != Span::empty(0)).then(|| {
661 map.span(item.name_span, hir.origin(NodeRef::Item(i)).expn)
662 }),
663 range: Some(map.map(hir.origin(NodeRef::Item(i)))),
664 parent: stack.last().copied().filter(|p| *p != NONE).map(DefRef),
665 });
666 items.push((i, d));
667 symbols.push(d);
668 stack.push(d);
669 if let ItemKind::Sum(sum) = item.kind {
670 for &v in hir.list(sum.variants) {
671 let Some(var) = hir.variant(v) else { continue };
672 let vd = base + ix(defs_out.len());
673 let origin = hir.origin(NodeRef::Variant(v));
674 defs_out.push(Definition {
675 target: Target::Def(DefId::foreign(unit, Def::Variant(v))),
676 name: Name::new(var.name.sym),
677 kind: SymbolKind::Variant,
678 location: Some(map.span(var.name.span, origin.expn)),
679 range: Some(map.map(origin)),
680 parent: Some(DefRef(d)),
681 });
682 variants.push((v, vd));
683 symbols.push(vd);
684 }
685 }
686 }
687 _ => stack.push(NONE),
688 }
689 }
690 hir_lang::Event::Leave(NodeRef::Item(_)) => {
691 let _ = stack.pop();
692 }
693 hir_lang::Event::Bind(b) => {
694 if dead.binary_search(&b).is_ok() {
695 return hir_lang::Control::Continue;
696 }
697 let Some(binder) = hir.binder(b) else {
698 return hir_lang::Control::Continue;
699 };
700 let origin = hir.binder_origin(b);
701 let d = base + ix(defs_out.len());
702 defs_out.push(Definition {
703 target: Target::Local(unit, b),
704 name: binder.name,
705 kind: SymbolKind::of_binder(binder.kind),
706 location: Some(map.map(origin)),
707 range: Some(map.map(origin)),
708 parent: stack.iter().rev().copied().find(|p| *p != NONE).map(DefRef),
709 });
710 binders.push((b, d));
711 }
712 _ => {}
713 }
714 hir_lang::Control::Continue
715 });
716 self.defs.extend(defs_out);
717 if let Some(slot) = self.units.get_mut(ui) {
718 for (i, d) in items {
719 if let Some(x) = slot.item_def.get_mut(i.index()) {
720 *x = d;
721 }
722 }
723 for (v, d) in variants {
724 if let Some(x) = slot.variant_def.get_mut(v.index()) {
725 *x = d;
726 }
727 }
728 for (b, d) in binders {
729 if let Some(x) = slot.binder_def.get_mut(b.index()) {
730 *x = d;
731 }
732 }
733 slot.symbols = symbols;
734 }
735 }
736
737 fn unit_ix(&self, unit: UnitId) -> Option<&UnitIx> {
738 self.units.iter().find(|u| u.id == unit)
739 }
740
741 fn find_target(&self, t: Target, externals: &[(Target, u32)]) -> Option<DefRef> {
742 let local = match t {
743 Target::Def(d) => self.unit_ix(d.unit()).and_then(|u| match d.def() {
744 Def::Item(i) => u.item_def.get(i.index()).copied(),
745 Def::Variant(v) => u.variant_def.get(v.index()).copied(),
746 }),
747 Target::Local(unit, b) => self
748 .unit_ix(unit)
749 .and_then(|u| u.binder_def.get(b.index()).copied()),
750 Target::Import(unit, i) => self
751 .unit_ix(unit)
752 .and_then(|u| u.item_def.get(i.index()).copied()),
753 Target::Extern(_) => None,
754 };
755 match local.filter(|d| *d != NONE) {
756 Some(d) => Some(DefRef(d)),
757 None => externals
758 .binary_search_by(|(x, _)| x.cmp(&t))
759 .ok()
760 .and_then(|i| externals.get(i))
761 .map(|(_, d)| DefRef(*d)),
762 }
763 }
764
765 fn target_def(
768 &mut self,
769 t: Target,
770 spelled: Name,
771 externals: &mut Vec<(Target, u32)>,
772 ) -> Option<u32> {
773 if let Some(d) = self.find_target(t, externals) {
774 return Some(d.0);
775 }
776 let name = match t {
777 Target::Def(d) if self.unit_ix(d.unit()).is_some() => return None,
780 Target::Local(..) | Target::Import(..) => return None,
781 Target::Extern(s) => Name::new(s),
782 Target::Def(_) => spelled,
783 };
784 let d = self.push_def(Definition {
785 target: t,
786 name,
787 kind: SymbolKind::External,
788 location: None,
789 range: None,
790 parent: None,
791 });
792 let at = externals.partition_point(|(x, _)| *x < t);
793 externals.insert(at, (t, d));
794 Some(d)
795 }
796
797 fn build_by_def(&mut self) {
798 let n = self.defs.len();
799 let mut count: Vec<u32> = alloc::vec![0; n + 1];
800 for r in &self.refs {
801 if let Some(c) = count.get_mut(r.def.index() + 1) {
802 *c += 1;
803 }
804 }
805 for i in 1..count.len() {
806 let prev = count.get(i - 1).copied().unwrap_or(0);
807 if let Some(c) = count.get_mut(i) {
808 *c += prev;
809 }
810 }
811 let mut fill = count.clone();
812 let mut by_def: Vec<u32> = alloc::vec![0; self.refs.len()];
813 let mut order: Vec<u32> = (0..ix(self.refs.len())).collect();
815 order.sort_by_key(|i| self.refs.get(*i as usize).map(|r| r.location));
816 for i in order {
817 let Some(r) = self.refs.get(i as usize) else {
818 continue;
819 };
820 if let Some(f) = fill.get_mut(r.def.index()) {
821 if let Some(slot) = by_def.get_mut(*f as usize) {
822 *slot = i;
823 }
824 *f += 1;
825 }
826 }
827 self.by_def_off = count;
828 self.by_def = by_def;
829 }
830
831 fn build_occurrences(&mut self) {
832 let mut per_unit: Vec<Vec<(u32, u32, u32, u32)>> =
833 self.units.iter().map(|_| Vec::new()).collect();
834 let unit_pos = |units: &[UnitIx], id: UnitId| units.iter().position(|u| u.id == id);
835 for (d, def) in self.defs.iter().enumerate() {
836 let Some(loc) = def.location.filter(|l| l.in_source && !l.span.is_empty()) else {
837 continue;
838 };
839 if let Some(list) = unit_pos(&self.units, loc.unit).and_then(|u| per_unit.get_mut(u)) {
840 list.push((
841 loc.span.start().to_u32(),
842 loc.span.end().to_u32(),
843 ix(d),
844 NONE,
845 ));
846 }
847 }
848 for (i, r) in self.refs.iter().enumerate() {
849 let loc = r.location;
850 if !loc.in_source || loc.span.is_empty() {
851 continue;
852 }
853 if let Some(list) = unit_pos(&self.units, loc.unit).and_then(|u| per_unit.get_mut(u)) {
854 list.push((
855 loc.span.start().to_u32(),
856 loc.span.end().to_u32(),
857 r.def.0,
858 ix(i),
859 ));
860 }
861 }
862 for (u, mut list) in self.units.iter_mut().zip(per_unit) {
863 list.sort_unstable();
864 list.dedup_by_key(|x| (x.0, x.1));
865 u.occ = list;
866 }
867 }
868
869 #[must_use]
881 pub fn definitions(&self) -> &[Definition] {
882 &self.defs
883 }
884
885 #[must_use]
895 pub fn references_all(&self) -> &[Reference] {
896 &self.refs
897 }
898
899 #[must_use]
909 pub fn definition(&self, def: DefRef) -> Option<&Definition> {
910 self.defs.get(def.index())
911 }
912
913 #[must_use]
924 pub fn references(&self, def: DefRef) -> References<'_> {
925 let ids = match (
926 self.by_def_off.get(def.index()),
927 self.by_def_off.get(def.index() + 1),
928 ) {
929 (Some(&lo), Some(&hi)) => self.by_def.get(lo as usize..hi as usize).unwrap_or(&[]),
930 _ => &[],
931 };
932 References {
933 refs: &self.refs,
934 ids: ids.iter(),
935 }
936 }
937
938 #[must_use]
951 pub fn def_of(&self, target: Target) -> Option<DefRef> {
952 self.find_target(target, &self.externals)
953 }
954
955 #[must_use]
966 pub fn resolve_at(&self, unit: UnitId, path: PathId, segment: u32) -> Option<DefRef> {
967 let u = self.unit_ix(unit)?;
968 let lo = *u.path_off.get(path.index())? as usize;
969 let hi = *u.path_off.get(path.index() + 1)? as usize;
970 self.refs
971 .get(lo..hi)?
972 .iter()
973 .find(|r| r.segment == segment)
974 .map(|r| r.def)
975 }
976
977 #[must_use]
988 pub fn path_references(&self, unit: UnitId, path: PathId) -> &[Reference] {
989 let Some(u) = self.unit_ix(unit) else {
990 return &[];
991 };
992 let (Some(&lo), Some(&hi)) = (
993 u.path_off.get(path.index()),
994 u.path_off.get(path.index() + 1),
995 ) else {
996 return &[];
997 };
998 self.refs.get(lo as usize..hi as usize).unwrap_or(&[])
999 }
1000
1001 #[must_use]
1013 pub fn at(&self, unit: UnitId, offset: u32) -> Option<Occurrence> {
1014 let u = self.unit_ix(unit)?;
1015 let upper = u.occ.partition_point(|(s, _, _, _)| *s <= offset);
1016 let lo = upper.saturating_sub(8);
1019 u.occ
1020 .get(lo..upper)?
1021 .iter()
1022 .rev()
1023 .find(|(s, e, _, _)| *s <= offset && offset < *e)
1024 .map(|&(_, _, d, r)| Occurrence {
1025 def: DefRef(d),
1026 reference: (r != NONE).then_some(r),
1027 })
1028 }
1029
1030 #[must_use]
1044 pub fn rename_set(&self, def: DefRef) -> RenameSet {
1045 let mut set = RenameSet::default();
1046 let Some(d) = self.definition(def) else {
1047 return set;
1048 };
1049 let mut add = |loc: Location| {
1050 if loc.in_source {
1051 set.edits.push(loc);
1052 } else {
1053 set.outside_source.push(loc);
1054 }
1055 };
1056 if let Some(loc) = d.location {
1057 add(loc);
1058 }
1059 if let Target::Import(..) = d.target {
1060 let lo = self.by_via.partition_point(|(v, _)| *v < def.0);
1063 for &(v, r) in self.by_via.get(lo..).unwrap_or(&[]) {
1064 if v != def.0 {
1065 break;
1066 }
1067 if let Some(r) = self.refs.get(r as usize).filter(|r| r.name == d.name) {
1068 add(r.location);
1069 }
1070 }
1071 } else {
1072 let ids = match (
1073 self.by_def_off.get(def.index()),
1074 self.by_def_off.get(def.index() + 1),
1075 ) {
1076 (Some(&lo), Some(&hi)) => self.by_def.get(lo as usize..hi as usize).unwrap_or(&[]),
1077 _ => &[],
1078 };
1079 for &r in ids {
1080 let same = self.same_name.get(r as usize).copied().unwrap_or(false);
1081 if let Some(r) = self.refs.get(r as usize).filter(|_| same) {
1082 add(r.location);
1083 }
1084 }
1085 }
1086 set.edits.sort();
1087 set.edits.dedup();
1088 set.outside_source.sort();
1089 set.outside_source.dedup();
1090 set
1091 }
1092
1093 #[must_use]
1105 pub fn document_symbols(&self, unit: UnitId) -> Vec<(DefRef, &Definition)> {
1106 let Some(u) = self.unit_ix(unit) else {
1107 return Vec::new();
1108 };
1109 u.symbols
1110 .iter()
1111 .filter_map(|d| self.defs.get(*d as usize).map(|def| (DefRef(*d), def)))
1112 .collect()
1113 }
1114}
1115
1116#[cfg(test)]
1117#[allow(clippy::unwrap_used, clippy::expect_used)]
1118mod tests {
1119 use hir_lang::{Builder, Expansion, ExpnKind, Name, Symbol};
1120
1121 use super::*;
1122
1123 #[test]
1124 fn test_mapper_maps_nested_expansions_to_outermost_call_site() {
1125 let mut b = Builder::new();
1126 let sym = Symbol::from_u32(1).unwrap();
1127 let outer = b.expansion(Expansion {
1128 kind: ExpnKind::Macro,
1129 name: sym,
1130 call_site: Span::new(100, 110),
1131 parent: ExpnId::ROOT,
1132 def_site: ExpnId::ROOT,
1133 });
1134 let inner = b.expansion(Expansion {
1135 kind: ExpnKind::Template,
1136 name: sym,
1137 call_site: Span::new(5, 6),
1138 parent: outer,
1139 def_site: ExpnId::ROOT,
1140 });
1141 let root = b.module(None, &[]);
1142 let hir = b.finish(root).unwrap();
1143 let map = Mapper::new(&hir);
1144 let loc = map.span(Span::new(1, 2), inner);
1145 assert_eq!(loc.span, Span::new(100, 110));
1146 assert!(!loc.in_source);
1147 let loc = map.span(Span::new(1, 2), ExpnId::ROOT);
1148 assert_eq!(loc.span, Span::new(1, 2));
1149 assert!(loc.in_source);
1150 }
1151
1152 #[test]
1153 fn test_empty_index_answers_nothing() {
1154 let ix = Index::default();
1155 let d = DefRef::from_index(0);
1156 assert!(ix.definition(d).is_none());
1157 assert_eq!(ix.references(d).len(), 0);
1158 assert!(ix.rename_set(d).edits.is_empty());
1159 assert!(ix.at(UnitId::new(0), 0).is_none());
1160 let t = Target::Extern(Symbol::from_u32(1).unwrap());
1161 assert!(ix.def_of(t).is_none());
1162 let _ = Name::new(Symbol::from_u32(1).unwrap());
1163 }
1164
1165 #[test]
1166 fn test_def_ref_saturates() {
1167 assert_eq!(DefRef::from_index(usize::MAX).index(), u32::MAX as usize);
1168 }
1169}