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}
448
449struct Mapper {
451 unit: UnitId,
452 sites: Vec<Span>,
454}
455
456impl Mapper {
457 fn new(hir: &Hir) -> Self {
458 let n = hir.count(IdKind::Expansion);
459 let mut sites: Vec<Span> = Vec::with_capacity(n);
460 for i in 1..=n {
461 let e = hir.expansion(ExpnId::from_u32(ix(i)));
462 let site = match e {
463 Some(e) if e.parent.is_root() => e.call_site,
464 Some(e) => sites
465 .get((e.parent.as_u32() as usize).saturating_sub(1))
466 .copied()
467 .unwrap_or(e.call_site),
468 None => Span::empty(0),
469 };
470 sites.push(site);
471 }
472 Self {
473 unit: hir.unit(),
474 sites,
475 }
476 }
477
478 fn map(&self, origin: Origin) -> Location {
479 self.span(origin.span, origin.expn)
480 }
481
482 fn span(&self, span: Span, expn: ExpnId) -> Location {
483 if expn.is_root() {
484 return Location {
485 unit: self.unit,
486 span,
487 in_source: true,
488 };
489 }
490 let site = self
491 .sites
492 .get((expn.as_u32() as usize).saturating_sub(1))
493 .copied()
494 .unwrap_or(span);
495 Location {
496 unit: self.unit,
497 span: site,
498 in_source: false,
499 }
500 }
501}
502
503pub(crate) struct RawRef {
506 pub(crate) path: PathId,
507 pub(crate) seg: u32,
508 pub(crate) target: Target,
509 pub(crate) via: Option<Target>,
510}
511
512pub(crate) struct UnitInput<'a> {
514 pub(crate) hir: &'a Hir,
515 pub(crate) refs: Vec<RawRef>,
516 pub(crate) dead_binders: Vec<BinderId>,
518 pub(crate) aliases: Vec<ItemId>,
520}
521
522impl Index {
523 pub(crate) fn build(units: &[UnitInput<'_>]) -> Self {
525 let mut me = Self::default();
526 let mut maps: Vec<Mapper> = Vec::with_capacity(units.len());
527 for u in units {
528 maps.push(Mapper::new(u.hir));
529 me.units.push(UnitIx {
530 id: u.hir.unit(),
531 item_def: alloc::vec![NONE; u.hir.count(IdKind::Item)],
532 variant_def: alloc::vec![NONE; u.hir.count(IdKind::Variant)],
533 binder_def: alloc::vec![NONE; u.hir.count(IdKind::Binder)],
534 path_off: Vec::new(),
535 symbols: Vec::new(),
536 occ: Vec::new(),
537 });
538 }
539 for (ui, u) in units.iter().enumerate() {
540 let Some(map) = maps.get(ui) else { continue };
541 me.collect_defs(ui, u, map);
542 }
543 let mut externals: Vec<(Target, u32)> = Vec::new();
546 let mut by_via: Vec<(u32, u32)> = Vec::new();
547 for (ui, u) in units.iter().enumerate() {
548 let Some(map) = maps.get(ui) else { continue };
549 let mut refs: Vec<&RawRef> = u.refs.iter().collect();
550 refs.sort_by_key(|r| (r.path, r.seg));
551 refs.dedup_by_key(|r| (r.path, r.seg));
552 let n_paths = u.hir.count(IdKind::Path);
553 let mut off: Vec<u32> = alloc::vec![0; n_paths + 1];
554 for r in refs {
555 let path = u.hir.path(r.path);
556 let Some(seg) = u.hir.list(path.segments).get(r.seg as usize) else {
557 continue;
558 };
559 let Some(def) = me.target_def(r.target, seg.name, &mut externals) else {
560 continue;
561 };
562 let via = r.via.and_then(|t| me.find_target(t, &externals));
563 if let Some(v) = via {
564 by_via.push((v.0, ix(me.refs.len())));
565 }
566 let reference = Reference {
567 location: map.map(seg.origin),
568 def: DefRef(def),
569 path: r.path,
570 segment: r.seg,
571 name: seg.name,
572 via,
573 };
574 if let Some(o) = off.get_mut(r.path.index() + 1) {
575 *o += 1;
576 }
577 me.refs.push(reference);
578 }
579 let base = ix(me.refs.len()) - off.iter().sum::<u32>();
582 let mut acc = base;
583 for o in &mut off {
584 acc += *o;
585 *o = acc;
586 }
587 if let Some(slot) = me.units.get_mut(ui) {
588 slot.path_off = off;
589 }
590 }
591 by_via.sort_unstable();
592 me.by_via = by_via;
593 me.externals = externals;
594 me.build_by_def();
595 me.build_occurrences();
596 me
597 }
598
599 fn push_def(&mut self, d: Definition) -> u32 {
600 let i = ix(self.defs.len());
601 self.defs.push(d);
602 i
603 }
604
605 fn collect_defs(&mut self, ui: usize, u: &UnitInput<'_>, map: &Mapper) {
606 let hir = u.hir;
607 let unit = hir.unit();
608 let mut stack: Vec<u32> = Vec::new();
609 let mut dead = u.dead_binders.clone();
610 dead.sort();
611 let mut symbols: Vec<u32> = Vec::new();
612 let mut items: Vec<(ItemId, u32)> = Vec::new();
613 let mut variants: Vec<(VariantId, u32)> = Vec::new();
614 let mut binders: Vec<(BinderId, u32)> = Vec::new();
615 let root = hir.root();
616 let mut defs_out: Vec<Definition> = Vec::new();
617 let base = ix(self.defs.len());
618 hir.walk_from(NodeRef::Item(root), |ev| {
619 match ev {
620 hir_lang::Event::Enter(NodeRef::Item(i)) => {
621 let item = hir.item(i);
622 let alias = u.aliases.binary_search(&i).is_ok();
623 let named = item.name.filter(|_| {
624 !matches!(item.kind, ItemKind::Import { .. } | ItemKind::MixinUse(_))
625 || alias
626 });
627 match named {
628 Some(name) if i != root || item.name.is_some() => {
629 let target = if alias {
630 Target::Import(unit, i)
631 } else {
632 Target::Def(DefId::foreign(unit, Def::Item(i)))
633 };
634 let d = base + ix(defs_out.len());
635 defs_out.push(Definition {
636 target,
637 name,
638 kind: if alias {
639 SymbolKind::Import
640 } else {
641 SymbolKind::of_item(&item.kind)
642 },
643 location: (item.name_span != Span::empty(0)).then(|| {
647 map.span(item.name_span, hir.origin(NodeRef::Item(i)).expn)
648 }),
649 range: Some(map.map(hir.origin(NodeRef::Item(i)))),
650 parent: stack.last().copied().filter(|p| *p != NONE).map(DefRef),
651 });
652 items.push((i, d));
653 symbols.push(d);
654 stack.push(d);
655 if let ItemKind::Sum(sum) = item.kind {
656 for &v in hir.list(sum.variants) {
657 let Some(var) = hir.variant(v) else { continue };
658 let vd = base + ix(defs_out.len());
659 let origin = hir.origin(NodeRef::Variant(v));
660 defs_out.push(Definition {
661 target: Target::Def(DefId::foreign(unit, Def::Variant(v))),
662 name: Name::new(var.name.sym),
663 kind: SymbolKind::Variant,
664 location: Some(map.span(var.name.span, origin.expn)),
665 range: Some(map.map(origin)),
666 parent: Some(DefRef(d)),
667 });
668 variants.push((v, vd));
669 symbols.push(vd);
670 }
671 }
672 }
673 _ => stack.push(NONE),
674 }
675 }
676 hir_lang::Event::Leave(NodeRef::Item(_)) => {
677 let _ = stack.pop();
678 }
679 hir_lang::Event::Bind(b) => {
680 if dead.binary_search(&b).is_ok() {
681 return hir_lang::Control::Continue;
682 }
683 let Some(binder) = hir.binder(b) else {
684 return hir_lang::Control::Continue;
685 };
686 let origin = hir.binder_origin(b);
687 let d = base + ix(defs_out.len());
688 defs_out.push(Definition {
689 target: Target::Local(unit, b),
690 name: binder.name,
691 kind: SymbolKind::of_binder(binder.kind),
692 location: Some(map.map(origin)),
693 range: Some(map.map(origin)),
694 parent: stack.iter().rev().copied().find(|p| *p != NONE).map(DefRef),
695 });
696 binders.push((b, d));
697 }
698 _ => {}
699 }
700 hir_lang::Control::Continue
701 });
702 self.defs.extend(defs_out);
703 if let Some(slot) = self.units.get_mut(ui) {
704 for (i, d) in items {
705 if let Some(x) = slot.item_def.get_mut(i.index()) {
706 *x = d;
707 }
708 }
709 for (v, d) in variants {
710 if let Some(x) = slot.variant_def.get_mut(v.index()) {
711 *x = d;
712 }
713 }
714 for (b, d) in binders {
715 if let Some(x) = slot.binder_def.get_mut(b.index()) {
716 *x = d;
717 }
718 }
719 slot.symbols = symbols;
720 }
721 }
722
723 fn unit_ix(&self, unit: UnitId) -> Option<&UnitIx> {
724 self.units.iter().find(|u| u.id == unit)
725 }
726
727 fn find_target(&self, t: Target, externals: &[(Target, u32)]) -> Option<DefRef> {
728 let local = match t {
729 Target::Def(d) => self.unit_ix(d.unit()).and_then(|u| match d.def() {
730 Def::Item(i) => u.item_def.get(i.index()).copied(),
731 Def::Variant(v) => u.variant_def.get(v.index()).copied(),
732 }),
733 Target::Local(unit, b) => self
734 .unit_ix(unit)
735 .and_then(|u| u.binder_def.get(b.index()).copied()),
736 Target::Import(unit, i) => self
737 .unit_ix(unit)
738 .and_then(|u| u.item_def.get(i.index()).copied()),
739 Target::Extern(_) => None,
740 };
741 match local.filter(|d| *d != NONE) {
742 Some(d) => Some(DefRef(d)),
743 None => externals
744 .binary_search_by(|(x, _)| x.cmp(&t))
745 .ok()
746 .and_then(|i| externals.get(i))
747 .map(|(_, d)| DefRef(*d)),
748 }
749 }
750
751 fn target_def(
754 &mut self,
755 t: Target,
756 spelled: Name,
757 externals: &mut Vec<(Target, u32)>,
758 ) -> Option<u32> {
759 if let Some(d) = self.find_target(t, externals) {
760 return Some(d.0);
761 }
762 let name = match t {
763 Target::Def(d) if self.unit_ix(d.unit()).is_some() => return None,
766 Target::Local(..) | Target::Import(..) => return None,
767 Target::Extern(s) => Name::new(s),
768 Target::Def(_) => spelled,
769 };
770 let d = self.push_def(Definition {
771 target: t,
772 name,
773 kind: SymbolKind::External,
774 location: None,
775 range: None,
776 parent: None,
777 });
778 let at = externals.partition_point(|(x, _)| *x < t);
779 externals.insert(at, (t, d));
780 Some(d)
781 }
782
783 fn build_by_def(&mut self) {
784 let n = self.defs.len();
785 let mut count: Vec<u32> = alloc::vec![0; n + 1];
786 for r in &self.refs {
787 if let Some(c) = count.get_mut(r.def.index() + 1) {
788 *c += 1;
789 }
790 }
791 for i in 1..count.len() {
792 let prev = count.get(i - 1).copied().unwrap_or(0);
793 if let Some(c) = count.get_mut(i) {
794 *c += prev;
795 }
796 }
797 let mut fill = count.clone();
798 let mut by_def: Vec<u32> = alloc::vec![0; self.refs.len()];
799 let mut order: Vec<u32> = (0..ix(self.refs.len())).collect();
801 order.sort_by_key(|i| self.refs.get(*i as usize).map(|r| r.location));
802 for i in order {
803 let Some(r) = self.refs.get(i as usize) else {
804 continue;
805 };
806 if let Some(f) = fill.get_mut(r.def.index()) {
807 if let Some(slot) = by_def.get_mut(*f as usize) {
808 *slot = i;
809 }
810 *f += 1;
811 }
812 }
813 self.by_def_off = count;
814 self.by_def = by_def;
815 }
816
817 fn build_occurrences(&mut self) {
818 let mut per_unit: Vec<Vec<(u32, u32, u32, u32)>> =
819 self.units.iter().map(|_| Vec::new()).collect();
820 let unit_pos = |units: &[UnitIx], id: UnitId| units.iter().position(|u| u.id == id);
821 for (d, def) in self.defs.iter().enumerate() {
822 let Some(loc) = def.location.filter(|l| l.in_source && !l.span.is_empty()) else {
823 continue;
824 };
825 if let Some(list) = unit_pos(&self.units, loc.unit).and_then(|u| per_unit.get_mut(u)) {
826 list.push((
827 loc.span.start().to_u32(),
828 loc.span.end().to_u32(),
829 ix(d),
830 NONE,
831 ));
832 }
833 }
834 for (i, r) in self.refs.iter().enumerate() {
835 let loc = r.location;
836 if !loc.in_source || loc.span.is_empty() {
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 r.def.0,
844 ix(i),
845 ));
846 }
847 }
848 for (u, mut list) in self.units.iter_mut().zip(per_unit) {
849 list.sort_unstable();
850 list.dedup_by_key(|x| (x.0, x.1));
851 u.occ = list;
852 }
853 }
854
855 #[must_use]
867 pub fn definitions(&self) -> &[Definition] {
868 &self.defs
869 }
870
871 #[must_use]
881 pub fn references_all(&self) -> &[Reference] {
882 &self.refs
883 }
884
885 #[must_use]
895 pub fn definition(&self, def: DefRef) -> Option<&Definition> {
896 self.defs.get(def.index())
897 }
898
899 #[must_use]
910 pub fn references(&self, def: DefRef) -> References<'_> {
911 let ids = match (
912 self.by_def_off.get(def.index()),
913 self.by_def_off.get(def.index() + 1),
914 ) {
915 (Some(&lo), Some(&hi)) => self.by_def.get(lo as usize..hi as usize).unwrap_or(&[]),
916 _ => &[],
917 };
918 References {
919 refs: &self.refs,
920 ids: ids.iter(),
921 }
922 }
923
924 #[must_use]
937 pub fn def_of(&self, target: Target) -> Option<DefRef> {
938 self.find_target(target, &self.externals)
939 }
940
941 #[must_use]
952 pub fn resolve_at(&self, unit: UnitId, path: PathId, segment: u32) -> Option<DefRef> {
953 let u = self.unit_ix(unit)?;
954 let lo = *u.path_off.get(path.index())? as usize;
955 let hi = *u.path_off.get(path.index() + 1)? as usize;
956 self.refs
957 .get(lo..hi)?
958 .iter()
959 .find(|r| r.segment == segment)
960 .map(|r| r.def)
961 }
962
963 #[must_use]
974 pub fn path_references(&self, unit: UnitId, path: PathId) -> &[Reference] {
975 let Some(u) = self.unit_ix(unit) else {
976 return &[];
977 };
978 let (Some(&lo), Some(&hi)) = (
979 u.path_off.get(path.index()),
980 u.path_off.get(path.index() + 1),
981 ) else {
982 return &[];
983 };
984 self.refs.get(lo as usize..hi as usize).unwrap_or(&[])
985 }
986
987 #[must_use]
999 pub fn at(&self, unit: UnitId, offset: u32) -> Option<Occurrence> {
1000 let u = self.unit_ix(unit)?;
1001 let upper = u.occ.partition_point(|(s, _, _, _)| *s <= offset);
1002 let lo = upper.saturating_sub(8);
1005 u.occ
1006 .get(lo..upper)?
1007 .iter()
1008 .rev()
1009 .find(|(s, e, _, _)| *s <= offset && offset < *e)
1010 .map(|&(_, _, d, r)| Occurrence {
1011 def: DefRef(d),
1012 reference: (r != NONE).then_some(r),
1013 })
1014 }
1015
1016 #[must_use]
1029 pub fn rename_set(&self, def: DefRef) -> RenameSet {
1030 let mut set = RenameSet::default();
1031 let Some(d) = self.definition(def) else {
1032 return set;
1033 };
1034 let mut add = |loc: Location| {
1035 if loc.in_source {
1036 set.edits.push(loc);
1037 } else {
1038 set.outside_source.push(loc);
1039 }
1040 };
1041 if let Some(loc) = d.location {
1042 add(loc);
1043 }
1044 if let Target::Import(..) = d.target {
1045 let lo = self.by_via.partition_point(|(v, _)| *v < def.0);
1048 for &(v, r) in self.by_via.get(lo..).unwrap_or(&[]) {
1049 if v != def.0 {
1050 break;
1051 }
1052 if let Some(r) = self.refs.get(r as usize).filter(|r| r.name == d.name) {
1053 add(r.location);
1054 }
1055 }
1056 } else {
1057 for r in self.references(def) {
1058 if r.name == d.name {
1059 add(r.location);
1060 }
1061 }
1062 }
1063 set.edits.sort();
1064 set.edits.dedup();
1065 set.outside_source.sort();
1066 set.outside_source.dedup();
1067 set
1068 }
1069
1070 #[must_use]
1082 pub fn document_symbols(&self, unit: UnitId) -> Vec<(DefRef, &Definition)> {
1083 let Some(u) = self.unit_ix(unit) else {
1084 return Vec::new();
1085 };
1086 u.symbols
1087 .iter()
1088 .filter_map(|d| self.defs.get(*d as usize).map(|def| (DefRef(*d), def)))
1089 .collect()
1090 }
1091}
1092
1093#[cfg(test)]
1094#[allow(clippy::unwrap_used, clippy::expect_used)]
1095mod tests {
1096 use hir_lang::{Builder, Expansion, ExpnKind, Name, Symbol};
1097
1098 use super::*;
1099
1100 #[test]
1101 fn test_mapper_maps_nested_expansions_to_outermost_call_site() {
1102 let mut b = Builder::new();
1103 let sym = Symbol::from_u32(1).unwrap();
1104 let outer = b.expansion(Expansion {
1105 kind: ExpnKind::Macro,
1106 name: sym,
1107 call_site: Span::new(100, 110),
1108 parent: ExpnId::ROOT,
1109 def_site: ExpnId::ROOT,
1110 });
1111 let inner = b.expansion(Expansion {
1112 kind: ExpnKind::Template,
1113 name: sym,
1114 call_site: Span::new(5, 6),
1115 parent: outer,
1116 def_site: ExpnId::ROOT,
1117 });
1118 let root = b.module(None, &[]);
1119 let hir = b.finish(root).unwrap();
1120 let map = Mapper::new(&hir);
1121 let loc = map.span(Span::new(1, 2), inner);
1122 assert_eq!(loc.span, Span::new(100, 110));
1123 assert!(!loc.in_source);
1124 let loc = map.span(Span::new(1, 2), ExpnId::ROOT);
1125 assert_eq!(loc.span, Span::new(1, 2));
1126 assert!(loc.in_source);
1127 }
1128
1129 #[test]
1130 fn test_empty_index_answers_nothing() {
1131 let ix = Index::default();
1132 let d = DefRef::from_index(0);
1133 assert!(ix.definition(d).is_none());
1134 assert_eq!(ix.references(d).len(), 0);
1135 assert!(ix.rename_set(d).edits.is_empty());
1136 assert!(ix.at(UnitId::new(0), 0).is_none());
1137 let t = Target::Extern(Symbol::from_u32(1).unwrap());
1138 assert!(ix.def_of(t).is_none());
1139 let _ = Name::new(Symbol::from_u32(1).unwrap());
1140 }
1141
1142 #[test]
1143 fn test_def_ref_saturates() {
1144 assert_eq!(DefRef::from_index(usize::MAX).index(), u32::MAX as usize);
1145 }
1146}