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    /// By reference: whether it spells its definition's name (up to the
448    /// case folding of the policy), so a rename edits it.
449    same_name: Vec<bool>,
450}
451
452/// Maps an origin to a source location, through expansions.
453struct Mapper {
454    unit: UnitId,
455    /// By expansion id (1-based): the outermost call site.
456    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
506/// A reference waiting to be indexed: (path, segment, target, via import
507/// target).
508pub(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
515/// The input of one unit to the index build.
516pub(crate) struct UnitInput<'a> {
517    pub(crate) hir: &'a Hir,
518    pub(crate) refs: Vec<RawRef>,
519    /// `Pat::Ident` binders that did not bind (their path named a constant).
520    pub(crate) dead_binders: Vec<BinderId>,
521    /// Aliased import items.
522    pub(crate) aliases: Vec<ItemId>,
523}
524
525impl Index {
526    /// Builds the index of a whole program. `fold` decides which spellings
527    /// of a name are the same name (case-insensitive tables).
528    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        // External definitions are created on first reference; keep them
548        // findable by target.
549        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            // Prefix sums turn counts into offsets relative to this unit's
589            // first reference.
590            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                                // Lowering that leaves the name span unset
653                                // gives no name location (the range still
654                                // locates the item).
655                                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    /// The definition of a target, creating an external one (named as the
761    /// reference spells it) if needed.
762    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            // A program target with no definition entry (an unnamed item):
773            // nothing to point at.
774            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        // References are visited in location order so each slice is sorted.
809        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    // ----------------------------------------------------------------- API
865
866    /// Every definition, in unit order, then preorder (externals last).
867    ///
868    /// # Examples
869    ///
870    /// ```
871    /// use resolve_lang::Index;
872    ///
873    /// assert!(Index::default().definitions().is_empty());
874    /// ```
875    #[must_use]
876    pub fn definitions(&self) -> &[Definition] {
877        &self.defs
878    }
879
880    /// Every reference, by unit, then path, then segment.
881    ///
882    /// # Examples
883    ///
884    /// ```
885    /// use resolve_lang::Index;
886    ///
887    /// assert!(Index::default().references_all().is_empty());
888    /// ```
889    #[must_use]
890    pub fn references_all(&self) -> &[Reference] {
891        &self.refs
892    }
893
894    /// One definition.
895    ///
896    /// # Examples
897    ///
898    /// ```
899    /// use resolve_lang::{DefRef, Index};
900    ///
901    /// assert!(Index::default().definition(DefRef::from_index(0)).is_none());
902    /// ```
903    #[must_use]
904    pub fn definition(&self, def: DefRef) -> Option<&Definition> {
905        self.defs.get(def.index())
906    }
907
908    /// The references to a definition, sorted by location (find-references).
909    /// Allocation-free: an iterator over the definition's slice.
910    ///
911    /// # Examples
912    ///
913    /// ```
914    /// use resolve_lang::{DefRef, Index};
915    ///
916    /// assert_eq!(Index::default().references(DefRef::from_index(0)).len(), 0);
917    /// ```
918    #[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    /// The definition of a target (an item, variant, binder, aliased import,
934    /// or a referenced external symbol).
935    ///
936    /// # Examples
937    ///
938    /// ```
939    /// use hir_lang::{BinderId, UnitId};
940    /// use resolve_lang::{Index, Target};
941    ///
942    /// let t = Target::Local(UnitId::new(0), BinderId::from_index(0).unwrap());
943    /// assert!(Index::default().def_of(t).is_none());
944    /// ```
945    #[must_use]
946    pub fn def_of(&self, target: Target) -> Option<DefRef> {
947        self.find_target(target, &self.externals)
948    }
949
950    /// Go-to-definition by HIR id: what segment `segment` of `path` names.
951    ///
952    /// # Examples
953    ///
954    /// ```
955    /// use hir_lang::{PathId, UnitId};
956    /// use resolve_lang::Index;
957    ///
958    /// assert!(Index::default().resolve_at(UnitId::new(0), PathId::from_index(0).unwrap(), 0).is_none());
959    /// ```
960    #[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    /// The references inside one path, by segment.
973    ///
974    /// # Examples
975    ///
976    /// ```
977    /// use hir_lang::{PathId, UnitId};
978    /// use resolve_lang::Index;
979    ///
980    /// assert!(Index::default().path_references(UnitId::new(0), PathId::from_index(0).unwrap()).is_empty());
981    /// ```
982    #[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    /// Go-to-definition by position: the definition or reference whose name
997    /// contains byte `offset` of `unit`'s source.
998    ///
999    /// # Examples
1000    ///
1001    /// ```
1002    /// use hir_lang::UnitId;
1003    /// use resolve_lang::Index;
1004    ///
1005    /// assert!(Index::default().at(UnitId::new(0), 3).is_none());
1006    /// ```
1007    #[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        // Names do not overlap in practice; look back a few entries for
1012        // the innermost one that contains the offset.
1013        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    /// Every edit renaming a definition implies: its own name and every
1026    /// reference that spells the same name, up to the case folding of a
1027    /// case-insensitive table (references through an aliased
1028    /// import spell the alias and are left alone). Renaming an aliased
1029    /// import edits the alias and the references that went through it.
1030    ///
1031    /// # Examples
1032    ///
1033    /// ```
1034    /// use resolve_lang::{DefRef, Index};
1035    ///
1036    /// assert!(Index::default().rename_set(DefRef::from_index(0)).edits.is_empty());
1037    /// ```
1038    #[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            // The alias's references point at the import's target; take the
1056            // ones that went through this import.
1057            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    /// The item definitions of a unit in preorder (with `parent` links), for
1089    /// a document outline.
1090    ///
1091    /// # Examples
1092    ///
1093    /// ```
1094    /// use hir_lang::UnitId;
1095    /// use resolve_lang::Index;
1096    ///
1097    /// assert!(Index::default().document_symbols(UnitId::new(0)).is_empty());
1098    /// ```
1099    #[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}