1use std::collections::{BTreeMap, HashMap};
2
3use spade_codespan::{ByteIndex, Span};
4
5use crate::location_info::Loc;
6
7#[derive(Debug)]
9pub struct LocMap<T> {
10 inner: HashMap<usize, BTreeMap<ByteIndex, BTreeMap<ByteIndex, Vec<T>>>>,
11}
12
13impl<T> LocMap<T> {
14 pub fn new() -> Self {
15 Self {
16 inner: HashMap::new(),
17 }
18 }
19
20 pub fn insert(&mut self, thing: Loc<T>) {
21 self.inner
22 .entry(thing.file_id)
23 .or_insert(Default::default())
24 .entry(thing.span.start())
25 .or_insert(Default::default())
26 .entry(thing.span.end())
27 .or_insert(Default::default())
28 .push(thing.inner)
29 }
30
31 pub fn around(&self, loc: &Loc<()>) -> Vec<Loc<&T>> {
32 self.inner
33 .get(&loc.file_id)
34 .map(|starts| {
35 let after_start = starts.range(..=loc.span.start());
36 after_start
37 .map(|(start, ends)| {
38 ends.range(loc.span.end()..)
39 .map(|(end, things)| {
40 let with_locs = things.iter().map(|thing| {
41 Loc::new(thing, Span::new(*start, *end), loc.file_id)
42 });
43 with_locs
44 })
45 .flatten()
46 })
47 .flatten()
48 .rev()
49 .collect::<Vec<_>>()
50 })
51 .unwrap_or_default()
52 }
53}
54
55#[test]
56fn around_tests() {
57 let mut test = LocMap::new();
58
59 test.insert(Loc::new("a", Span::new(100, 105), 1));
60 test.insert(Loc::new("b", Span::new(262, 265), 1));
61 test.insert(Loc::new("c", Span::new(300, 305), 1));
62 test.insert(Loc::new("d", Span::new(400, 405), 1));
63 test.insert(Loc::new("e", Span::new(500, 500), 1));
64
65 test.insert(Loc::new("0", Span::new(0, 100), 1));
66 test.insert(Loc::new("1", Span::new(30, 70), 1));
67 test.insert(Loc::new("2", Span::new(40, 60), 1));
68 test.insert(Loc::new("3", Span::new(40, 70), 1));
69 test.insert(Loc::new("4", Span::new(45, 50), 1));
70
71 println!("{test:?}");
72
73 assert_eq!(
74 test.around(&Loc::new((), Span::new(263, 263), 1))
75 .iter()
76 .map(|l| *l.inner)
77 .collect::<Vec<_>>(),
78 vec!["b"]
79 );
80
81 assert_eq!(
82 test.around(&Loc::new((), Span::new(500, 500), 1))
83 .iter()
84 .map(|l| *l.inner)
85 .collect::<Vec<_>>(),
86 vec!["e"]
87 );
88
89 assert_eq!(
90 test.around(&Loc::new((), Span::new(50, 50), 1))
91 .iter()
92 .map(|l| *l.inner)
93 .collect::<Vec<_>>(),
94 vec!["4", "3", "2", "1", "0"],
95 )
96}