Skip to main content

resolve_lang/
index.rs

1//! The persistent definition/reference index: the data an LSP needs for
2//! go-to-definition, find-references, rename, and document symbols.
3//!
4//! Built once per resolution and owned by the [`Resolution`](crate::Resolution).
5//! Every lookup is by dense id: definitions and references are vectors, the
6//! references of a definition are one contiguous slice (CSR layout), and
7//! per-unit side tables are keyed by HIR item, variant, binder, and path ids.
8
9use 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/// What kind of thing a definition is, for symbol lists and icons.
19///
20/// # Examples
21///
22/// ```
23/// use resolve_lang::SymbolKind;
24///
25/// assert_eq!(SymbolKind::Function.name(), "function");
26/// ```
27#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
28#[non_exhaustive]
29pub enum SymbolKind {
30    /// A module.
31    Module,
32    /// A function or method.
33    Function,
34    /// A record.
35    Record,
36    /// A sum.
37    Sum,
38    /// A sum variant.
39    Variant,
40    /// A class.
41    Class,
42    /// A mixin (PHP trait).
43    Mixin,
44    /// An interface.
45    Interface,
46    /// An impl block.
47    Impl,
48    /// A type alias.
49    Alias,
50    /// An associated type.
51    AssocType,
52    /// A constant.
53    Const,
54    /// A global.
55    Global,
56    /// An aliased import (`use x as y`): `y` is renameable on its own.
57    Import,
58    /// A local variable.
59    Local,
60    /// A parameter.
61    Param,
62    /// An explicit capture or a closure's self binder.
63    Capture,
64    /// A type parameter.
65    TypeParam,
66    /// A const parameter.
67    ConstParam,
68    /// A region parameter.
69    Region,
70    /// A loop or block label.
71    Label,
72    /// Something outside the program (another package, a host symbol): it
73    /// has references but no location.
74    External,
75}
76
77impl SymbolKind {
78    /// A short lowercase name.
79    ///
80    /// # Examples
81    ///
82    /// ```
83    /// use resolve_lang::SymbolKind;
84    ///
85    /// assert_eq!(SymbolKind::TypeParam.name(), "type parameter");
86    /// ```
87    #[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/// What a definition is, as an identity that survives across units.
147///
148/// # Examples
149///
150/// ```
151/// use hir_lang::{BinderId, UnitId};
152/// use resolve_lang::Target;
153///
154/// let t = Target::Local(UnitId::new(0), BinderId::from_index(3).unwrap());
155/// assert!(matches!(t, Target::Local(..)));
156/// ```
157#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
158pub enum Target {
159    /// An item or variant.
160    Def(DefId),
161    /// A binder of a unit.
162    Local(UnitId, BinderId),
163    /// A host symbol.
164    Extern(Symbol),
165    /// An aliased import item (its own name is the definition).
166    Import(UnitId, ItemId),
167}
168
169/// A place in the source.
170///
171/// # Examples
172///
173/// ```
174/// use hir_lang::{Span, UnitId};
175/// use resolve_lang::Location;
176///
177/// let l = Location { unit: UnitId::new(1), span: Span::new(4, 7), in_source: true };
178/// assert_eq!(l.span.len(), 3);
179/// ```
180#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
181pub struct Location {
182    /// The unit.
183    pub unit: UnitId,
184    /// The span. For a name that came out of a macro or template expansion,
185    /// this is the outermost expansion's call site.
186    pub span: Span,
187    /// Whether the name was written in the source (its origin is not an
188    /// expansion). Only such names are rename edits.
189    pub in_source: bool,
190}
191
192/// An opaque handle to a definition in an [`Index`].
193///
194/// # Examples
195///
196/// ```
197/// use resolve_lang::DefRef;
198///
199/// assert_eq!(DefRef::from_index(5).index(), 5);
200/// ```
201#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
202pub struct DefRef(u32);
203
204impl DefRef {
205    /// The dense position of the definition.
206    ///
207    /// # Examples
208    ///
209    /// ```
210    /// use resolve_lang::DefRef;
211    ///
212    /// assert_eq!(DefRef::from_index(0).index(), 0);
213    /// ```
214    #[must_use]
215    pub const fn index(self) -> usize {
216        self.0 as usize
217    }
218
219    /// A handle from a dense position (saturating past `u32::MAX`).
220    ///
221    /// # Examples
222    ///
223    /// ```
224    /// use resolve_lang::DefRef;
225    ///
226    /// assert_eq!(DefRef::from_index(9), DefRef::from_index(9));
227    /// ```
228    #[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/// One definition.
239///
240/// # Examples
241///
242/// ```
243/// use hir_lang::{Builder, Name};
244/// use intern_lang::Interner;
245/// use resolve_lang::SymbolKind;
246///
247/// let mut names = Interner::new();
248/// let mut b = Builder::new();
249/// let body = b.block(&[], None);
250/// let f = b.func(Name::new(names.intern("f")), &[], body);
251/// let root = b.module(None, &[f]);
252/// let res = resolve_lang::resolve(b.finish(root)?, &names)?;
253/// let def = res.index().definitions().iter().find(|d| d.kind == SymbolKind::Function).unwrap();
254/// assert_eq!(names.resolve(def.name.sym), Some("f"));
255/// # Ok::<(), Box<dyn std::error::Error>>(())
256/// ```
257#[derive(Clone, Copy, Debug, PartialEq, Eq)]
258pub struct Definition {
259    /// What it is.
260    pub target: Target,
261    /// Its name.
262    pub name: Name,
263    /// Its kind.
264    pub kind: SymbolKind,
265    /// Where its name is: `None` for something outside the program, and for
266    /// an item whose lowering recorded no name span (use `range` then).
267    pub location: Option<Location>,
268    /// The span of the whole definition (an item's or binder's own span).
269    pub range: Option<Location>,
270    /// The enclosing item's definition, for symbol trees.
271    pub parent: Option<DefRef>,
272}
273
274/// One resolved name in a path.
275///
276/// # Examples
277///
278/// ```
279/// use resolve_lang::Reference;
280///
281/// fn first_segment(r: &Reference) -> bool { r.segment == 0 }
282/// # let _ = first_segment;
283/// ```
284#[derive(Clone, Copy, Debug, PartialEq, Eq)]
285pub struct Reference {
286    /// Where the name is.
287    pub location: Location,
288    /// What it resolves to.
289    pub def: DefRef,
290    /// The path holding it.
291    pub path: PathId,
292    /// The segment of the path.
293    pub segment: u32,
294    /// The name as written (differs from the definition's name when reached
295    /// through an aliased import).
296    pub name: Name,
297    /// The aliased import the name was reached through, if any.
298    pub via: Option<DefRef>,
299}
300
301/// What [`Index::at`] found at a position.
302///
303/// # Examples
304///
305/// ```
306/// use resolve_lang::{DefRef, Occurrence};
307///
308/// let o = Occurrence { def: DefRef::from_index(0), reference: None };
309/// assert!(o.is_definition());
310/// ```
311#[derive(Clone, Copy, Debug, PartialEq, Eq)]
312pub struct Occurrence {
313    /// The definition named there.
314    pub def: DefRef,
315    /// The reference there (by position in [`Index::references_all`]), or
316    /// `None` if the position is the definition's own name.
317    pub reference: Option<u32>,
318}
319
320impl Occurrence {
321    /// Whether the position is the definition's own name.
322    ///
323    /// # Examples
324    ///
325    /// ```
326    /// use resolve_lang::{DefRef, Occurrence};
327    ///
328    /// let o = Occurrence { def: DefRef::from_index(0), reference: Some(3) };
329    /// assert!(!o.is_definition());
330    /// ```
331    #[must_use]
332    pub const fn is_definition(&self) -> bool {
333        self.reference.is_none()
334    }
335}
336
337/// The references to one definition, in location order: see
338/// [`Index::references`].
339///
340/// # Examples
341///
342/// ```
343/// use resolve_lang::{DefRef, Index};
344///
345/// let index = Index::default();
346/// let mut refs = index.references(DefRef::from_index(3));
347/// assert!(refs.next().is_none());
348/// ```
349#[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        // Every id is a valid position by construction (the CSR is built
360        // from `refs` itself); `get` keeps a corrupted index from panicking.
361        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/// The edits a rename of one definition makes.
372///
373/// # Examples
374///
375/// ```
376/// use resolve_lang::RenameSet;
377///
378/// let r = RenameSet::default();
379/// assert!(r.edits.is_empty() && r.outside_source.is_empty());
380/// ```
381#[derive(Clone, Debug, Default, PartialEq, Eq)]
382pub struct RenameSet {
383    /// Every occurrence written in the source, the definition's name
384    /// included, sorted by location.
385    pub edits: Vec<Location>,
386    /// Occurrences produced by expansions: a rename cannot edit them
387    /// directly (the macro or template that produced them needs a look).
388    pub outside_source: Vec<Location>,
389}
390
391/// Per-unit side tables.
392#[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    /// CSR over paths: references of path `p` are `refs[path_off[p]..path_off[p+1]]`.
399    path_off: Vec<u32>,
400    /// Item definitions in preorder.
401    symbols: Vec<u32>,
402    /// (start, end, def, reference or NONE), sorted by (start, end).
403    occ: Vec<(u32, u32, u32, u32)>,
404}
405
406/// The persistent definition/reference index of a resolved program.
407///
408/// # Examples
409///
410/// ```
411/// use hir_lang::{Builder, Name, Span};
412/// use intern_lang::Interner;
413///
414/// // fn f(n) { n }  — the use of `n` is a reference to the parameter.
415/// let mut names = Interner::new();
416/// let n = Name::new(names.intern("n"));
417/// let mut b = Builder::new();
418/// b.set_span(Span::new(5, 6));
419/// let (param, _) = b.local_param(n);
420/// b.set_span(Span::new(10, 11));
421/// let use_n = b.name_expr(n);
422/// let body = b.block(&[], Some(use_n));
423/// let f = b.func(Name::new(names.intern("f")), &[param], body);
424/// let root = b.module(None, &[f]);
425/// let hir = b.finish(root)?;
426/// let unit = hir.unit();
427///
428/// let res = resolve_lang::resolve(hir, &names)?;
429/// let index = res.index();
430/// let hit = index.at(unit, 10).unwrap();
431/// let def = index.definition(hit.def).unwrap();
432/// assert_eq!(def.location.unwrap().span, Span::new(5, 6));
433/// assert_eq!(index.references(hit.def).len(), 1);
434/// # Ok::<(), Box<dyn std::error::Error>>(())
435/// ```
436#[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    /// (aliased-import definition, reference), sorted.
443    by_via: Vec<(u32, u32)>,
444    /// External definitions by target, sorted.
445    externals: Vec<(Target, u32)>,
446    units: Vec<UnitIx>,
447}
448
449/// Maps an origin to a source location, through expansions.
450struct Mapper {
451    unit: UnitId,
452    /// By expansion id (1-based): the outermost call site.
453    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
503/// A reference waiting to be indexed: (path, segment, target, via import
504/// target).
505pub(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
512/// The input of one unit to the index build.
513pub(crate) struct UnitInput<'a> {
514    pub(crate) hir: &'a Hir,
515    pub(crate) refs: Vec<RawRef>,
516    /// `Pat::Ident` binders that did not bind (their path named a constant).
517    pub(crate) dead_binders: Vec<BinderId>,
518    /// Aliased import items.
519    pub(crate) aliases: Vec<ItemId>,
520}
521
522impl Index {
523    /// Builds the index of a whole program.
524    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        // External definitions are created on first reference; keep them
544        // findable by target.
545        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            // Prefix sums turn counts into offsets relative to this unit's
580            // first reference.
581            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                                // Lowering that leaves the name span unset
644                                // gives no name location (the range still
645                                // locates the item).
646                                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    /// The definition of a target, creating an external one (named as the
752    /// reference spells it) if needed.
753    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            // A program target with no definition entry (an unnamed item):
764            // nothing to point at.
765            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        // References are visited in location order so each slice is sorted.
800        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    // ----------------------------------------------------------------- API
856
857    /// Every definition, in unit order, then preorder (externals last).
858    ///
859    /// # Examples
860    ///
861    /// ```
862    /// use resolve_lang::Index;
863    ///
864    /// assert!(Index::default().definitions().is_empty());
865    /// ```
866    #[must_use]
867    pub fn definitions(&self) -> &[Definition] {
868        &self.defs
869    }
870
871    /// Every reference, by unit, then path, then segment.
872    ///
873    /// # Examples
874    ///
875    /// ```
876    /// use resolve_lang::Index;
877    ///
878    /// assert!(Index::default().references_all().is_empty());
879    /// ```
880    #[must_use]
881    pub fn references_all(&self) -> &[Reference] {
882        &self.refs
883    }
884
885    /// One definition.
886    ///
887    /// # Examples
888    ///
889    /// ```
890    /// use resolve_lang::{DefRef, Index};
891    ///
892    /// assert!(Index::default().definition(DefRef::from_index(0)).is_none());
893    /// ```
894    #[must_use]
895    pub fn definition(&self, def: DefRef) -> Option<&Definition> {
896        self.defs.get(def.index())
897    }
898
899    /// The references to a definition, sorted by location (find-references).
900    /// Allocation-free: an iterator over the definition's slice.
901    ///
902    /// # Examples
903    ///
904    /// ```
905    /// use resolve_lang::{DefRef, Index};
906    ///
907    /// assert_eq!(Index::default().references(DefRef::from_index(0)).len(), 0);
908    /// ```
909    #[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    /// The definition of a target (an item, variant, binder, aliased import,
925    /// or a referenced external symbol).
926    ///
927    /// # Examples
928    ///
929    /// ```
930    /// use hir_lang::{BinderId, UnitId};
931    /// use resolve_lang::{Index, Target};
932    ///
933    /// let t = Target::Local(UnitId::new(0), BinderId::from_index(0).unwrap());
934    /// assert!(Index::default().def_of(t).is_none());
935    /// ```
936    #[must_use]
937    pub fn def_of(&self, target: Target) -> Option<DefRef> {
938        self.find_target(target, &self.externals)
939    }
940
941    /// Go-to-definition by HIR id: what segment `segment` of `path` names.
942    ///
943    /// # Examples
944    ///
945    /// ```
946    /// use hir_lang::{PathId, UnitId};
947    /// use resolve_lang::Index;
948    ///
949    /// assert!(Index::default().resolve_at(UnitId::new(0), PathId::from_index(0).unwrap(), 0).is_none());
950    /// ```
951    #[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    /// The references inside one path, by segment.
964    ///
965    /// # Examples
966    ///
967    /// ```
968    /// use hir_lang::{PathId, UnitId};
969    /// use resolve_lang::Index;
970    ///
971    /// assert!(Index::default().path_references(UnitId::new(0), PathId::from_index(0).unwrap()).is_empty());
972    /// ```
973    #[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    /// Go-to-definition by position: the definition or reference whose name
988    /// contains byte `offset` of `unit`'s source.
989    ///
990    /// # Examples
991    ///
992    /// ```
993    /// use hir_lang::UnitId;
994    /// use resolve_lang::Index;
995    ///
996    /// assert!(Index::default().at(UnitId::new(0), 3).is_none());
997    /// ```
998    #[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        // Names do not overlap in practice; look back a few entries for
1003        // the innermost one that contains the offset.
1004        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    /// Every edit renaming a definition implies: its own name and every
1017    /// reference that spells the same name (references through an aliased
1018    /// import spell the alias and are left alone). Renaming an aliased
1019    /// import edits the alias and the references that went through it.
1020    ///
1021    /// # Examples
1022    ///
1023    /// ```
1024    /// use resolve_lang::{DefRef, Index};
1025    ///
1026    /// assert!(Index::default().rename_set(DefRef::from_index(0)).edits.is_empty());
1027    /// ```
1028    #[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            // The alias's references point at the import's target; take the
1046            // ones that went through this import.
1047            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    /// The item definitions of a unit in preorder (with `parent` links), for
1071    /// a document outline.
1072    ///
1073    /// # Examples
1074    ///
1075    /// ```
1076    /// use hir_lang::UnitId;
1077    /// use resolve_lang::Index;
1078    ///
1079    /// assert!(Index::default().document_symbols(UnitId::new(0)).is_empty());
1080    /// ```
1081    #[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}