typst_analyzer/typst_lang/
symbol_table.rs

1//! This module contains the `SymbolTable` struct, which is used to
2//! store information about symbols and references in a source file.
3
4use std::collections::HashMap;
5
6use oxc_index::IndexVec;
7
8use super::span::Span;
9
10oxc_index::define_index_type! {
11    /// A unique identifier for the symbol in the table.
12    pub struct SymbolId = u32;
13    IMPL_RAW_CONVERSIONS = true;
14}
15
16oxc_index::define_index_type! {
17    pub struct ReferenceId = u32;
18    IMPL_RAW_CONVERSIONS = true;
19}
20/// A mapping from a symbol id to a span.
21pub type SymbolIdToSpan = IndexVec<SymbolId, Span>;
22
23pub type ReferenceIdToReference = IndexVec<ReferenceId, Reference>;
24
25/// A symbol table is a data structure used by lsp servers
26/// to store information about symbols and
27/// references in a source file.
28#[derive(Default, Debug)]
29pub struct SymbolTable {
30    /// To find a SymbolId for a given code location.
31    pub span_to_symbol_id: HashMap<Span, SymbolId>,
32    /// To retrieve the code location for a symbol.
33    pub symbol_id_to_span: SymbolIdToSpan,
34    pub reference_id_to_reference: ReferenceIdToReference,
35    pub span_to_reference_id: HashMap<Span, ReferenceId>,
36    pub symbol_id_to_references: HashMap<SymbolId, Vec<ReferenceId>>,
37}
38
39#[derive(Debug)]
40pub struct Reference {
41    pub span: Span,
42    pub symbol_id: Option<SymbolId>,
43}
44
45impl SymbolTable {
46    pub fn add_symbol(&mut self, span: Span) -> SymbolId {
47        let symbol_id = self.symbol_id_to_span.push(span.clone());
48        self.span_to_symbol_id.insert(span.clone(), symbol_id);
49        symbol_id
50    }
51
52    pub fn add_reference(&mut self, span: Span, symbol_id: Option<SymbolId>) {
53        let reference_id = self.reference_id_to_reference.push(Reference {
54            span: span.clone(),
55            symbol_id,
56        });
57        self.span_to_reference_id.insert(span, reference_id);
58        if let Some(symbol_id) = symbol_id {
59            self.symbol_id_to_references
60                .entry(symbol_id)
61                .or_default()
62                .push(reference_id);
63        }
64    }
65}