mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 12:54:58 +00:00
internal: Improve rooted upmapping
This commit is contained in:
parent
03d2d9016d
commit
9ba4493918
24 changed files with 231 additions and 153 deletions
|
@ -7,17 +7,20 @@ use stdx::{always, itertools::Itertools};
|
|||
use syntax::{TextRange, TextSize};
|
||||
use vfs::FileId;
|
||||
|
||||
use crate::{ErasedFileAstId, Span, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID};
|
||||
use crate::{
|
||||
ErasedFileAstId, Span, SpanAnchor, SpanData, SyntaxContextId, ROOT_ERASED_FILE_AST_ID,
|
||||
};
|
||||
|
||||
/// Maps absolute text ranges for the corresponding file to the relevant span data.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
||||
pub struct SpanMap<S> {
|
||||
spans: Vec<(TextSize, S)>,
|
||||
// FIXME: Should be
|
||||
// spans: Vec<(TextSize, crate::SyntaxContextId)>,
|
||||
spans: Vec<(TextSize, SpanData<S>)>,
|
||||
}
|
||||
|
||||
impl<S: Copy> SpanMap<S> {
|
||||
impl<S> SpanMap<S>
|
||||
where
|
||||
SpanData<S>: Copy,
|
||||
{
|
||||
/// Creates a new empty [`SpanMap`].
|
||||
pub fn empty() -> Self {
|
||||
Self { spans: Vec::new() }
|
||||
|
@ -34,7 +37,7 @@ impl<S: Copy> SpanMap<S> {
|
|||
}
|
||||
|
||||
/// Pushes a new span onto the [`SpanMap`].
|
||||
pub fn push(&mut self, offset: TextSize, span: S) {
|
||||
pub fn push(&mut self, offset: TextSize, span: SpanData<S>) {
|
||||
if cfg!(debug_assertions) {
|
||||
if let Some(&(last_offset, _)) = self.spans.last() {
|
||||
assert!(
|
||||
|
@ -49,13 +52,12 @@ impl<S: Copy> SpanMap<S> {
|
|||
/// Returns all [`TextRange`]s that correspond to the given span.
|
||||
///
|
||||
/// Note this does a linear search through the entire backing vector.
|
||||
pub fn ranges_with_span(&self, span: S) -> impl Iterator<Item = TextRange> + '_
|
||||
pub fn ranges_with_span(&self, span: SpanData<S>) -> impl Iterator<Item = TextRange> + '_
|
||||
where
|
||||
S: Eq,
|
||||
S: Copy,
|
||||
{
|
||||
// FIXME: This should ignore the syntax context!
|
||||
self.spans.iter().enumerate().filter_map(move |(idx, &(end, s))| {
|
||||
if s != span {
|
||||
if !s.eq_ignoring_ctx(span) {
|
||||
return None;
|
||||
}
|
||||
let start = idx.checked_sub(1).map_or(TextSize::new(0), |prev| self.spans[prev].0);
|
||||
|
@ -64,21 +66,21 @@ impl<S: Copy> SpanMap<S> {
|
|||
}
|
||||
|
||||
/// Returns the span at the given position.
|
||||
pub fn span_at(&self, offset: TextSize) -> S {
|
||||
pub fn span_at(&self, offset: TextSize) -> SpanData<S> {
|
||||
let entry = self.spans.partition_point(|&(it, _)| it <= offset);
|
||||
self.spans[entry].1
|
||||
}
|
||||
|
||||
/// Returns the spans associated with the given range.
|
||||
/// In other words, this will return all spans that correspond to all offsets within the given range.
|
||||
pub fn spans_for_range(&self, range: TextRange) -> impl Iterator<Item = S> + '_ {
|
||||
pub fn spans_for_range(&self, range: TextRange) -> impl Iterator<Item = SpanData<S>> + '_ {
|
||||
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)
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = (TextSize, S)> + '_ {
|
||||
pub fn iter(&self) -> impl Iterator<Item = (TextSize, SpanData<S>)> + '_ {
|
||||
self.spans.iter().copied()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue