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 External,
75}
76
77impl SymbolKind {
78 #[must_use]
88 pub const fn name(self) -> &'static str {
89 match self {
90 Self::Module => "module",
91 Self::Function => "function",
92 Self::Record => "record",
93 Self::Sum => "sum",
94 Self::Variant => "variant",
95 Self::Class => "class",
96 Self::Mixin => "mixin",
97 Self::Interface => "interface",
98 Self::Impl => "impl",
99 Self::Alias => "alias",
100 Self::AssocType => "associated type",
101 Self::Const => "constant",
102 Self::Global => "global",
103 Self::Import => "import",
104 Self::Local => "local",
105 Self::Param => "parameter",
106 Self::Capture => "capture",
107 Self::TypeParam => "type parameter",
108 Self::ConstParam => "const parameter",
109 Self::Region => "region",
110 Self::Label => "label",
111 Self::External => "external",
112 }
113 }
114
115 const fn of_item(kind: &ItemKind) -> Self {
116 match kind {
117 ItemKind::Fn(_) => Self::Function,
118 ItemKind::Record(_) => Self::Record,
119 ItemKind::Sum(_) => Self::Sum,
120 ItemKind::Class(c) if c.mixin => Self::Mixin,
121 ItemKind::Class(_) => Self::Class,
122 ItemKind::Interface(_) => Self::Interface,
123 ItemKind::Impl(_) => Self::Impl,
124 ItemKind::Alias { .. } => Self::Alias,
125 ItemKind::AssocType { .. } => Self::AssocType,
126 ItemKind::Const { .. } => Self::Const,
127 ItemKind::Global { .. } => Self::Global,
128 ItemKind::Module { .. } | ItemKind::Err => Self::Module,
129 ItemKind::Import { .. } | ItemKind::MixinUse(_) => Self::Import,
130 }
131 }
132
133 const fn of_binder(kind: BinderKind) -> Self {
134 match kind {
135 BinderKind::Local => Self::Local,
136 BinderKind::Param => Self::Param,
137 BinderKind::Capture => Self::Capture,
138 BinderKind::TypeParam => Self::TypeParam,
139 BinderKind::ConstParam => Self::ConstParam,
140 BinderKind::Region => Self::Region,
141 BinderKind::Label => Self::Label,
142 }
143 }
144}
145
146#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
158pub enum Target {
159 Def(DefId),
161 Local(UnitId, BinderId),
163 Extern(Symbol),
165 Import(UnitId, ItemId),
167}
168
169#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
181pub struct Location {
182 pub unit: UnitId,
184 pub span: Span,
187 pub in_source: bool,
190}
191
192#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
202pub struct DefRef(u32);
203
204impl DefRef {
205 #[must_use]
215 pub const fn index(self) -> usize {
216 self.0 as usize
217 }
218
219 #[must_use]
229 pub const fn from_index(i: usize) -> Self {
230 Self(if i > u32::MAX as usize {
231 u32::MAX
232 } else {
233 i as u32
234 })
235 }
236}
237
238#[derive(Clone, Copy, Debug, PartialEq, Eq)]
258pub struct Definition {
259 pub target: Target,
261 pub name: Name,
263 pub kind: SymbolKind,
265 pub location: Option<Location>,
268 pub range: Option<Location>,
270 pub parent: Option<DefRef>,
272}
273
274#[derive(Clone, Copy, Debug, PartialEq, Eq)]
285pub struct Reference {
286 pub location: Location,
288 pub def: DefRef,
290 pub path: PathId,
292 pub segment: u32,
294 pub name: Name,
297 pub via: Option<DefRef>,
299}
300
301#[derive(Clone, Copy, Debug, PartialEq, Eq)]
312pub struct Occurrence {
313 pub def: DefRef,
315 pub reference: Option<u32>,
318}
319
320impl Occurrence {
321 #[must_use]
332 pub const fn is_definition(&self) -> bool {
333 self.reference.is_none()
334 }
335}
336
337#[derive(Clone, Debug)]
350pub struct References<'a> {
351 refs: &'a [Reference],
352 ids: core::slice::Iter<'a, u32>,
353}
354
355impl<'a> Iterator for References<'a> {
356 type Item = &'a Reference;
357
358 fn next(&mut self) -> Option<&'a Reference> {
359 self.ids.find_map(|i| self.refs.get(*i as usize))
362 }
363
364 fn size_hint(&self) -> (usize, Option<usize>) {
365 (self.ids.len(), Some(self.ids.len()))
366 }
367}
368
369impl ExactSizeIterator for References<'_> {}
370
371#[derive(Clone, Debug, Default, PartialEq, Eq)]
382pub struct RenameSet {
383 pub edits: Vec<Location>,
386 pub outside_source: Vec<Location>,
389}
390
391#[derive(Clone, Debug, Default)]
393struct UnitIx {
394 id: UnitId,
395 item_def: Vec<u32>,
396 variant_def: Vec<u32>,
397 binder_def: Vec<u32>,
398 path_off: Vec<u32>,
400 symbols: Vec<u32>,
402 occ: Vec<(u32, u32, u32, u32)>,
404}
405
406#[derive(Clone, Debug, Default)]
437pub struct Index {
438 defs: Vec<Definition>,
439 refs: Vec<Reference>,
440 by_def_off: Vec<u32>,
441 by_def: Vec<u32>,
442 by_via: Vec<(u32, u32)>,
444 externals: Vec<(Target, u32)>,
446 units: Vec<UnitIx>,
447 same_name: Vec<bool>,
450}
451
452struct Mapper {
454 unit: UnitId,
455 sites: Vec<Span>,
457}
458
459impl Mapper {
460 fn new(hir: &Hir) -> Self {
461 let n = hir.count(IdKind::Expansion);
462 let mut sites: Vec<Span> = Vec::with_capacity(n);
463 for i in 1..=n {
464 let e = hir.expansion(ExpnId::from_u32(ix(i)));
465 let site = match e {
466 Some(e) if e.parent.is_root() => e.call_site,
467 Some(e) => sites
468 .get((e.parent.as_u32() as usize).saturating_sub(1))
469 .copied()
470 .unwrap_or(e.call_site),
471 None => Span::empty(0),
472 };
473 sites.push(site);
474 }
475 Self {
476 unit: hir.unit(),
477 sites,
478 }
479 }
480
481 fn map(&self, origin: Origin) -> Location {
482 self.span(origin.span, origin.expn)
483 }
484
485 fn span(&self, span: Span, expn: ExpnId) -> Location {
486 if expn.is_root() {
487 return Location {
488 unit: self.unit,
489 span,
490 in_source: true,
491 };
492 }
493 let site = self
494 .sites
495 .get((expn.as_u32() as usize).saturating_sub(1))
496 .copied()
497 .unwrap_or(span);
498 Location {
499 unit: self.unit,
500 span: site,
501 in_source: false,
502 }
503 }
504}
505
506pub(crate) struct RawRef {
509 pub(crate) path: PathId,
510 pub(crate) seg: u32,
511 pub(crate) target: Target,
512 pub(crate) via: Option<Target>,
513}
514
515pub(crate) struct UnitInput<'a> {
517 pub(crate) hir: &'a Hir,
518 pub(crate) refs: Vec<RawRef>,
519 pub(crate) dead_binders: Vec<BinderId>,
521 pub(crate) aliases: Vec<ItemId>,
523}
524
525impl Index {
526 pub(crate) fn build(units: &[UnitInput<'_>], fold: &crate::model::Fold) -> Self {
529 let mut me = Self::default();
530 let mut maps: Vec<Mapper> = Vec::with_capacity(units.len());
531 for u in units {
532 maps.push(Mapper::new(u.hir));
533 me.units.push(UnitIx {
534 id: u.hir.unit(),
535 item_def: alloc::vec![NONE; u.hir.count(IdKind::Item)],
536 variant_def: alloc::vec![NONE; u.hir.count(IdKind::Variant)],
537 binder_def: alloc::vec![NONE; u.hir.count(IdKind::Binder)],
538 path_off: Vec::new(),
539 symbols: Vec::new(),
540 occ: Vec::new(),
541 });
542 }
543 for (ui, u) in units.iter().enumerate() {
544 let Some(map) = maps.get(ui) else { continue };
545 me.collect_defs(ui, u, map);
546 }
547 let mut externals: Vec<(Target, u32)> = Vec::new();
550 let mut by_via: Vec<(u32, u32)> = Vec::new();
551 for (ui, u) in units.iter().enumerate() {
552 let Some(map) = maps.get(ui) else { continue };
553 let mut refs: Vec<&RawRef> = u.refs.iter().collect();
554 refs.sort_by_key(|r| (r.path, r.seg));
555 refs.dedup_by_key(|r| (r.path, r.seg));
556 let n_paths = u.hir.count(IdKind::Path);
557 let mut off: Vec<u32> = alloc::vec![0; n_paths + 1];
558 for r in refs {
559 let path = u.hir.path(r.path);
560 let Some(seg) = u.hir.list(path.segments).get(r.seg as usize) else {
561 continue;
562 };
563 let Some(def) = me.target_def(r.target, seg.name, &mut externals) else {
564 continue;
565 };
566 let via = r.via.and_then(|t| me.find_target(t, &externals));
567 if let Some(v) = via {
568 by_via.push((v.0, ix(me.refs.len())));
569 }
570 let same = me.defs.get(def as usize).is_some_and(|d| {
571 d.name == seg.name
572 || (via.is_none() && fold.name(d.name) == fold.name(seg.name))
573 });
574 me.same_name.push(same);
575 let reference = Reference {
576 location: map.map(seg.origin),
577 def: DefRef(def),
578 path: r.path,
579 segment: r.seg,
580 name: seg.name,
581 via,
582 };
583 if let Some(o) = off.get_mut(r.path.index() + 1) {
584 *o += 1;
585 }
586 me.refs.push(reference);
587 }
588 let base = ix(me.refs.len()) - off.iter().sum::<u32>();
591 let mut acc = base;
592 for o in &mut off {
593 acc += *o;
594 *o = acc;
595 }
596 if let Some(slot) = me.units.get_mut(ui) {
597 slot.path_off = off;
598 }
599 }
600 by_via.sort_unstable();
601 me.by_via = by_via;
602 me.externals = externals;
603 me.build_by_def();
604 me.build_occurrences();
605 me
606 }
607
608 fn push_def(&mut self, d: Definition) -> u32 {
609 let i = ix(self.defs.len());
610 self.defs.push(d);
611 i
612 }
613
614 fn collect_defs(&mut self, ui: usize, u: &UnitInput<'_>, map: &Mapper) {
615 let hir = u.hir;
616 let unit = hir.unit();
617 let mut stack: Vec<u32> = Vec::new();
618 let mut dead = u.dead_binders.clone();
619 dead.sort();
620 let mut symbols: Vec<u32> = Vec::new();
621 let mut items: Vec<(ItemId, u32)> = Vec::new();
622 let mut variants: Vec<(VariantId, u32)> = Vec::new();
623 let mut binders: Vec<(BinderId, u32)> = Vec::new();
624 let root = hir.root();
625 let mut defs_out: Vec<Definition> = Vec::new();
626 let base = ix(self.defs.len());
627 hir.walk_from(NodeRef::Item(root), |ev| {
628 match ev {
629 hir_lang::Event::Enter(NodeRef::Item(i)) => {
630 let item = hir.item(i);
631 let alias = u.aliases.binary_search(&i).is_ok();
632 let named = item.name.filter(|_| {
633 !matches!(item.kind, ItemKind::Import { .. } | ItemKind::MixinUse(_))
634 || alias
635 });
636 match named {
637 Some(name) if i != root || item.name.is_some() => {
638 let target = if alias {
639 Target::Import(unit, i)
640 } else {
641 Target::Def(DefId::foreign(unit, Def::Item(i)))
642 };
643 let d = base + ix(defs_out.len());
644 defs_out.push(Definition {
645 target,
646 name,
647 kind: if alias {
648 SymbolKind::Import
649 } else {
650 SymbolKind::of_item(&item.kind)
651 },
652 location: (item.name_span != Span::empty(0)).then(|| {
656 map.span(item.name_span, hir.origin(NodeRef::Item(i)).expn)
657 }),
658 range: Some(map.map(hir.origin(NodeRef::Item(i)))),
659 parent: stack.last().copied().filter(|p| *p != NONE).map(DefRef),
660 });
661 items.push((i, d));
662 symbols.push(d);
663 stack.push(d);
664 if let ItemKind::Sum(sum) = item.kind {
665 for &v in hir.list(sum.variants) {
666 let Some(var) = hir.variant(v) else { continue };
667 let vd = base + ix(defs_out.len());
668 let origin = hir.origin(NodeRef::Variant(v));
669 defs_out.push(Definition {
670 target: Target::Def(DefId::foreign(unit, Def::Variant(v))),
671 name: Name::new(var.name.sym),
672 kind: SymbolKind::Variant,
673 location: Some(map.span(var.name.span, origin.expn)),
674 range: Some(map.map(origin)),
675 parent: Some(DefRef(d)),
676 });
677 variants.push((v, vd));
678 symbols.push(vd);
679 }
680 }
681 }
682 _ => stack.push(NONE),
683 }
684 }
685 hir_lang::Event::Leave(NodeRef::Item(_)) => {
686 let _ = stack.pop();
687 }
688 hir_lang::Event::Bind(b) => {
689 if dead.binary_search(&b).is_ok() {
690 return hir_lang::Control::Continue;
691 }
692 let Some(binder) = hir.binder(b) else {
693 return hir_lang::Control::Continue;
694 };
695 let origin = hir.binder_origin(b);
696 let d = base + ix(defs_out.len());
697 defs_out.push(Definition {
698 target: Target::Local(unit, b),
699 name: binder.name,
700 kind: SymbolKind::of_binder(binder.kind),
701 location: Some(map.map(origin)),
702 range: Some(map.map(origin)),
703 parent: stack.iter().rev().copied().find(|p| *p != NONE).map(DefRef),
704 });
705 binders.push((b, d));
706 }
707 _ => {}
708 }
709 hir_lang::Control::Continue
710 });
711 self.defs.extend(defs_out);
712 if let Some(slot) = self.units.get_mut(ui) {
713 for (i, d) in items {
714 if let Some(x) = slot.item_def.get_mut(i.index()) {
715 *x = d;
716 }
717 }
718 for (v, d) in variants {
719 if let Some(x) = slot.variant_def.get_mut(v.index()) {
720 *x = d;
721 }
722 }
723 for (b, d) in binders {
724 if let Some(x) = slot.binder_def.get_mut(b.index()) {
725 *x = d;
726 }
727 }
728 slot.symbols = symbols;
729 }
730 }
731
732 fn unit_ix(&self, unit: UnitId) -> Option<&UnitIx> {
733 self.units.iter().find(|u| u.id == unit)
734 }
735
736 fn find_target(&self, t: Target, externals: &[(Target, u32)]) -> Option<DefRef> {
737 let local = match t {
738 Target::Def(d) => self.unit_ix(d.unit()).and_then(|u| match d.def() {
739 Def::Item(i) => u.item_def.get(i.index()).copied(),
740 Def::Variant(v) => u.variant_def.get(v.index()).copied(),
741 }),
742 Target::Local(unit, b) => self
743 .unit_ix(unit)
744 .and_then(|u| u.binder_def.get(b.index()).copied()),
745 Target::Import(unit, i) => self
746 .unit_ix(unit)
747 .and_then(|u| u.item_def.get(i.index()).copied()),
748 Target::Extern(_) => None,
749 };
750 match local.filter(|d| *d != NONE) {
751 Some(d) => Some(DefRef(d)),
752 None => externals
753 .binary_search_by(|(x, _)| x.cmp(&t))
754 .ok()
755 .and_then(|i| externals.get(i))
756 .map(|(_, d)| DefRef(*d)),
757 }
758 }
759
760 fn target_def(
763 &mut self,
764 t: Target,
765 spelled: Name,
766 externals: &mut Vec<(Target, u32)>,
767 ) -> Option<u32> {
768 if let Some(d) = self.find_target(t, externals) {
769 return Some(d.0);
770 }
771 let name = match t {
772 Target::Def(d) if self.unit_ix(d.unit()).is_some() => return None,
775 Target::Local(..) | Target::Import(..) => return None,
776 Target::Extern(s) => Name::new(s),
777 Target::Def(_) => spelled,
778 };
779 let d = self.push_def(Definition {
780 target: t,
781 name,
782 kind: SymbolKind::External,
783 location: None,
784 range: None,
785 parent: None,
786 });
787 let at = externals.partition_point(|(x, _)| *x < t);
788 externals.insert(at, (t, d));
789 Some(d)
790 }
791
792 fn build_by_def(&mut self) {
793 let n = self.defs.len();
794 let mut count: Vec<u32> = alloc::vec![0; n + 1];
795 for r in &self.refs {
796 if let Some(c) = count.get_mut(r.def.index() + 1) {
797 *c += 1;
798 }
799 }
800 for i in 1..count.len() {
801 let prev = count.get(i - 1).copied().unwrap_or(0);
802 if let Some(c) = count.get_mut(i) {
803 *c += prev;
804 }
805 }
806 let mut fill = count.clone();
807 let mut by_def: Vec<u32> = alloc::vec![0; self.refs.len()];
808 let mut order: Vec<u32> = (0..ix(self.refs.len())).collect();
810 order.sort_by_key(|i| self.refs.get(*i as usize).map(|r| r.location));
811 for i in order {
812 let Some(r) = self.refs.get(i as usize) else {
813 continue;
814 };
815 if let Some(f) = fill.get_mut(r.def.index()) {
816 if let Some(slot) = by_def.get_mut(*f as usize) {
817 *slot = i;
818 }
819 *f += 1;
820 }
821 }
822 self.by_def_off = count;
823 self.by_def = by_def;
824 }
825
826 fn build_occurrences(&mut self) {
827 let mut per_unit: Vec<Vec<(u32, u32, u32, u32)>> =
828 self.units.iter().map(|_| Vec::new()).collect();
829 let unit_pos = |units: &[UnitIx], id: UnitId| units.iter().position(|u| u.id == id);
830 for (d, def) in self.defs.iter().enumerate() {
831 let Some(loc) = def.location.filter(|l| l.in_source && !l.span.is_empty()) else {
832 continue;
833 };
834 if let Some(list) = unit_pos(&self.units, loc.unit).and_then(|u| per_unit.get_mut(u)) {
835 list.push((
836 loc.span.start().to_u32(),
837 loc.span.end().to_u32(),
838 ix(d),
839 NONE,
840 ));
841 }
842 }
843 for (i, r) in self.refs.iter().enumerate() {
844 let loc = r.location;
845 if !loc.in_source || loc.span.is_empty() {
846 continue;
847 }
848 if let Some(list) = unit_pos(&self.units, loc.unit).and_then(|u| per_unit.get_mut(u)) {
849 list.push((
850 loc.span.start().to_u32(),
851 loc.span.end().to_u32(),
852 r.def.0,
853 ix(i),
854 ));
855 }
856 }
857 for (u, mut list) in self.units.iter_mut().zip(per_unit) {
858 list.sort_unstable();
859 list.dedup_by_key(|x| (x.0, x.1));
860 u.occ = list;
861 }
862 }
863
864 #[must_use]
876 pub fn definitions(&self) -> &[Definition] {
877 &self.defs
878 }
879
880 #[must_use]
890 pub fn references_all(&self) -> &[Reference] {
891 &self.refs
892 }
893
894 #[must_use]
904 pub fn definition(&self, def: DefRef) -> Option<&Definition> {
905 self.defs.get(def.index())
906 }
907
908 #[must_use]
919 pub fn references(&self, def: DefRef) -> References<'_> {
920 let ids = match (
921 self.by_def_off.get(def.index()),
922 self.by_def_off.get(def.index() + 1),
923 ) {
924 (Some(&lo), Some(&hi)) => self.by_def.get(lo as usize..hi as usize).unwrap_or(&[]),
925 _ => &[],
926 };
927 References {
928 refs: &self.refs,
929 ids: ids.iter(),
930 }
931 }
932
933 #[must_use]
946 pub fn def_of(&self, target: Target) -> Option<DefRef> {
947 self.find_target(target, &self.externals)
948 }
949
950 #[must_use]
961 pub fn resolve_at(&self, unit: UnitId, path: PathId, segment: u32) -> Option<DefRef> {
962 let u = self.unit_ix(unit)?;
963 let lo = *u.path_off.get(path.index())? as usize;
964 let hi = *u.path_off.get(path.index() + 1)? as usize;
965 self.refs
966 .get(lo..hi)?
967 .iter()
968 .find(|r| r.segment == segment)
969 .map(|r| r.def)
970 }
971
972 #[must_use]
983 pub fn path_references(&self, unit: UnitId, path: PathId) -> &[Reference] {
984 let Some(u) = self.unit_ix(unit) else {
985 return &[];
986 };
987 let (Some(&lo), Some(&hi)) = (
988 u.path_off.get(path.index()),
989 u.path_off.get(path.index() + 1),
990 ) else {
991 return &[];
992 };
993 self.refs.get(lo as usize..hi as usize).unwrap_or(&[])
994 }
995
996 #[must_use]
1008 pub fn at(&self, unit: UnitId, offset: u32) -> Option<Occurrence> {
1009 let u = self.unit_ix(unit)?;
1010 let upper = u.occ.partition_point(|(s, _, _, _)| *s <= offset);
1011 let lo = upper.saturating_sub(8);
1014 u.occ
1015 .get(lo..upper)?
1016 .iter()
1017 .rev()
1018 .find(|(s, e, _, _)| *s <= offset && offset < *e)
1019 .map(|&(_, _, d, r)| Occurrence {
1020 def: DefRef(d),
1021 reference: (r != NONE).then_some(r),
1022 })
1023 }
1024
1025 #[must_use]
1039 pub fn rename_set(&self, def: DefRef) -> RenameSet {
1040 let mut set = RenameSet::default();
1041 let Some(d) = self.definition(def) else {
1042 return set;
1043 };
1044 let mut add = |loc: Location| {
1045 if loc.in_source {
1046 set.edits.push(loc);
1047 } else {
1048 set.outside_source.push(loc);
1049 }
1050 };
1051 if let Some(loc) = d.location {
1052 add(loc);
1053 }
1054 if let Target::Import(..) = d.target {
1055 let lo = self.by_via.partition_point(|(v, _)| *v < def.0);
1058 for &(v, r) in self.by_via.get(lo..).unwrap_or(&[]) {
1059 if v != def.0 {
1060 break;
1061 }
1062 if let Some(r) = self.refs.get(r as usize).filter(|r| r.name == d.name) {
1063 add(r.location);
1064 }
1065 }
1066 } else {
1067 let ids = match (
1068 self.by_def_off.get(def.index()),
1069 self.by_def_off.get(def.index() + 1),
1070 ) {
1071 (Some(&lo), Some(&hi)) => self.by_def.get(lo as usize..hi as usize).unwrap_or(&[]),
1072 _ => &[],
1073 };
1074 for &r in ids {
1075 let same = self.same_name.get(r as usize).copied().unwrap_or(false);
1076 if let Some(r) = self.refs.get(r as usize).filter(|_| same) {
1077 add(r.location);
1078 }
1079 }
1080 }
1081 set.edits.sort();
1082 set.edits.dedup();
1083 set.outside_source.sort();
1084 set.outside_source.dedup();
1085 set
1086 }
1087
1088 #[must_use]
1100 pub fn document_symbols(&self, unit: UnitId) -> Vec<(DefRef, &Definition)> {
1101 let Some(u) = self.unit_ix(unit) else {
1102 return Vec::new();
1103 };
1104 u.symbols
1105 .iter()
1106 .filter_map(|d| self.defs.get(*d as usize).map(|def| (DefRef(*d), def)))
1107 .collect()
1108 }
1109}
1110
1111#[cfg(test)]
1112#[allow(clippy::unwrap_used, clippy::expect_used)]
1113mod tests {
1114 use hir_lang::{Builder, Expansion, ExpnKind, Name, Symbol};
1115
1116 use super::*;
1117
1118 #[test]
1119 fn test_mapper_maps_nested_expansions_to_outermost_call_site() {
1120 let mut b = Builder::new();
1121 let sym = Symbol::from_u32(1).unwrap();
1122 let outer = b.expansion(Expansion {
1123 kind: ExpnKind::Macro,
1124 name: sym,
1125 call_site: Span::new(100, 110),
1126 parent: ExpnId::ROOT,
1127 def_site: ExpnId::ROOT,
1128 });
1129 let inner = b.expansion(Expansion {
1130 kind: ExpnKind::Template,
1131 name: sym,
1132 call_site: Span::new(5, 6),
1133 parent: outer,
1134 def_site: ExpnId::ROOT,
1135 });
1136 let root = b.module(None, &[]);
1137 let hir = b.finish(root).unwrap();
1138 let map = Mapper::new(&hir);
1139 let loc = map.span(Span::new(1, 2), inner);
1140 assert_eq!(loc.span, Span::new(100, 110));
1141 assert!(!loc.in_source);
1142 let loc = map.span(Span::new(1, 2), ExpnId::ROOT);
1143 assert_eq!(loc.span, Span::new(1, 2));
1144 assert!(loc.in_source);
1145 }
1146
1147 #[test]
1148 fn test_empty_index_answers_nothing() {
1149 let ix = Index::default();
1150 let d = DefRef::from_index(0);
1151 assert!(ix.definition(d).is_none());
1152 assert_eq!(ix.references(d).len(), 0);
1153 assert!(ix.rename_set(d).edits.is_empty());
1154 assert!(ix.at(UnitId::new(0), 0).is_none());
1155 let t = Target::Extern(Symbol::from_u32(1).unwrap());
1156 assert!(ix.def_of(t).is_none());
1157 let _ = Name::new(Symbol::from_u32(1).unwrap());
1158 }
1159
1160 #[test]
1161 fn test_def_ref_saturates() {
1162 assert_eq!(DefRef::from_index(usize::MAX).index(), u32::MAX as usize);
1163 }
1164}