1
/**
2
 * Source map for mapping span IDs to source code locations and related metadata.
3
 * This is used for error reporting and diagnostics.
4
 */
5
use crate::diagnostics::diagnostics_api::{Position, SymbolKind};
6
use rangemap::RangeMap;
7
pub type SpanId = u32;
8

            
9
#[derive(Debug)]
10
pub struct HoverInfo {
11
    pub description: String,       // keyword description, type info...
12
    pub kind: Option<SymbolKind>,  // var, domain, function...
13
    pub ty: Option<String>,        // type info like int(0..10)
14
    pub decl_span: Option<SpanId>, // where declared (not sure that's doable)
15
}
16
// source span with start and end positions
17
// in the essence source code
18
#[derive(Debug)]
19
pub struct SourceSpan {
20
    pub start_byte: usize, // byte offset in the source code
21
    pub end_byte: usize,
22
    pub start_point: Position,
23
    pub end_point: Position,
24
    pub hover_info: Option<HoverInfo>,
25
}
26

            
27
// can add more metadata for hovering and stuff
28
#[derive(Debug, Default)]
29
pub struct SourceMap {
30
    pub spans: Vec<SourceSpan>,
31
    pub by_byte: RangeMap<usize, SpanId>,
32
}
33

            
34
// allocate a new span and return span id
35
// put the position of the span in the source map
36
11984
pub fn alloc_span(
37
11984
    range: tree_sitter::Range,
38
11984
    source_map: &mut SourceMap,
39
11984
    hover_info: Option<HoverInfo>,
40
11984
) -> SpanId {
41
11984
    let span_id = source_map.spans.len() as SpanId;
42
11984
    source_map.spans.push(SourceSpan {
43
11984
        start_byte: range.start_byte,
44
11984
        end_byte: range.end_byte,
45
11984
        start_point: Position {
46
11984
            line: range.start_point.row as u32,
47
11984
            character: range.start_point.column as u32,
48
11984
        },
49
11984
        end_point: Position {
50
11984
            line: range.end_point.row as u32,
51
11984
            character: range.end_point.column as u32,
52
11984
        },
53
11984
        hover_info,
54
11984
    });
55
    // map byte offsets to span id (RangeMap handles lookup)
56
11984
    source_map
57
11984
        .by_byte
58
11984
        .insert(range.start_byte..range.end_byte, span_id);
59
11984
    span_id
60
11984
}
61

            
62
impl SourceMap {
63
    // helper to get hover info for a given byte offset (e.g. cursor position)
64
    pub fn span_id_at_byte(&self, byte: usize) -> Option<SpanId> {
65
        self.by_byte.get(&byte).copied()
66
    }
67
}
68

            
69
// helper to allocate a span with hover info directly from a tree-sitter node
70
// source is not used yet but could be for more complex hover info (e.g. showing the actual code snippet)
71
11984
pub fn span_with_hover(
72
11984
    node: &tree_sitter::Node,
73
11984
    _source: &str,
74
11984
    map: &mut SourceMap,
75
11984
    info: HoverInfo,
76
11984
) -> SpanId {
77
11984
    alloc_span(node.range(), map, Some(info))
78
11984
}