2021-05-24 21:47:01 +02:00
|
|
|
//! Mapping between `TokenId`s and the token's position in macro definitions or inputs.
|
|
|
|
|
2021-08-21 18:06:03 +02:00
|
|
|
use std::hash::Hash;
|
|
|
|
|
2023-11-24 16:38:48 +01:00
|
|
|
use stdx::itertools::Itertools;
|
2023-11-28 10:55:21 +01:00
|
|
|
use syntax::{TextRange, TextSize};
|
2023-09-29 12:37:57 +02:00
|
|
|
use tt::Span;
|
|
|
|
|
|
|
|
/// Maps absolute text ranges for the corresponding file to the relevant span data.
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
|
|
|
// FIXME: Rename to SpanMap
|
2023-11-24 16:38:48 +01:00
|
|
|
pub struct TokenMap<S: Span> {
|
2023-09-29 12:37:57 +02:00
|
|
|
// FIXME: This needs to be sorted by (FileId, AstId)
|
|
|
|
// Then we can do a binary search on the file id,
|
2023-11-28 10:55:21 +01:00
|
|
|
// then a bin search on the ast id?
|
|
|
|
spans: Vec<(TextSize, S)>,
|
2021-05-24 18:43:42 +02:00
|
|
|
}
|
|
|
|
|
2023-11-24 16:38:48 +01:00
|
|
|
impl<S: Span> TokenMap<S> {
|
2023-12-01 16:29:58 +01:00
|
|
|
pub fn empty() -> Self {
|
2023-11-28 10:55:21 +01:00
|
|
|
Self { spans: Vec::new() }
|
2021-05-24 18:43:42 +02:00
|
|
|
}
|
|
|
|
|
2023-12-01 16:29:58 +01:00
|
|
|
pub fn finish(&mut self) {
|
2023-11-28 10:55:21 +01:00
|
|
|
assert!(self.spans.iter().tuple_windows().all(|(a, b)| a.0 < b.0));
|
|
|
|
self.spans.shrink_to_fit();
|
2022-02-08 18:13:18 +01:00
|
|
|
}
|
|
|
|
|
2023-12-01 16:29:58 +01:00
|
|
|
pub fn push(&mut self, offset: TextSize, span: S) {
|
2023-11-28 10:55:21 +01:00
|
|
|
self.spans.push((offset, span));
|
2021-05-24 18:43:42 +02:00
|
|
|
}
|
|
|
|
|
2023-09-29 12:37:57 +02:00
|
|
|
pub fn ranges_with_span(&self, span: S) -> impl Iterator<Item = TextRange> + '_ {
|
2023-11-24 16:38:48 +01:00
|
|
|
// FIXME: linear search
|
2023-11-28 10:55:21 +01:00
|
|
|
self.spans.iter().enumerate().filter_map(move |(idx, &(end, s))| {
|
|
|
|
if s != span {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
let start = idx.checked_sub(1).map_or(TextSize::new(0), |prev| self.spans[prev].0);
|
|
|
|
Some(TextRange::new(start, end))
|
|
|
|
})
|
2021-05-24 18:43:42 +02:00
|
|
|
}
|
2023-07-13 09:17:07 +02:00
|
|
|
|
2023-11-24 16:38:48 +01:00
|
|
|
// FIXME: We need APIs for fetching the span of a token as well as for a whole node. The node
|
|
|
|
// one *is* fallible though.
|
2023-11-28 10:55:21 +01:00
|
|
|
pub fn span_at(&self, offset: TextSize) -> S {
|
|
|
|
let entry = self.spans.partition_point(|&(it, _)| it <= offset);
|
|
|
|
self.spans[entry].1
|
2023-11-24 16:38:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn spans_for_node_range(&self, range: TextRange) -> impl Iterator<Item = S> + '_ {
|
2023-11-28 10:55:21 +01:00
|
|
|
let (start, end) = (range.start(), range.end());
|
|
|
|
let start_entry = self.spans.partition_point(|&(it, _)| it <= start);
|
|
|
|
let end_entry = self.spans[start_entry..].partition_point(|&(it, _)| it <= end); // FIXME: this might be wrong?
|
|
|
|
(&self.spans[start_entry..][..end_entry]).iter().map(|&(_, s)| s)
|
2023-07-13 09:17:07 +02:00
|
|
|
}
|
2023-12-01 16:29:58 +01:00
|
|
|
|
|
|
|
pub fn iter(&self) -> impl Iterator<Item = (TextSize, S)> + '_ {
|
|
|
|
self.spans.iter().copied()
|
|
|
|
}
|
2021-05-24 18:43:42 +02:00
|
|
|
}
|