feat: Support macro calls in eager macros for IDE features

This commit is contained in:
Lukas Wirth 2024-03-14 12:02:23 +01:00
parent 9767156a29
commit d2f8eae2ec
22 changed files with 420 additions and 226 deletions

View file

@ -26,9 +26,19 @@ use salsa::{InternId, InternValue};
use crate::MacroCallId;
/// Interned [`SyntaxContextData`].
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SyntaxContextId(InternId);
impl fmt::Debug for SyntaxContextId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.alternate() {
write!(f, "{}", self.0.as_u32())
} else {
f.debug_tuple("SyntaxContextId").field(&self.0).finish()
}
}
}
impl salsa::InternKey for SyntaxContextId {
fn from_intern_id(v: salsa::InternId) -> Self {
SyntaxContextId(v)

View file

@ -44,7 +44,7 @@ pub const FIXUP_ERASED_FILE_AST_ID_MARKER: ErasedFileAstId =
pub type Span = SpanData<SyntaxContextId>;
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct SpanData<Ctx> {
/// The text range of this span, relative to the anchor.
/// We need the anchor for incrementality, as storing absolute ranges will require
@ -56,6 +56,26 @@ pub struct SpanData<Ctx> {
pub ctx: Ctx,
}
impl<Ctx: fmt::Debug> fmt::Debug for SpanData<Ctx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.alternate() {
fmt::Debug::fmt(&self.anchor.file_id.index(), f)?;
f.write_char(':')?;
fmt::Debug::fmt(&self.anchor.ast_id.into_raw(), f)?;
f.write_char('@')?;
fmt::Debug::fmt(&self.range, f)?;
f.write_char('#')?;
self.ctx.fmt(f)
} else {
f.debug_struct("SpanData")
.field("range", &self.range)
.field("anchor", &self.anchor)
.field("ctx", &self.ctx)
.finish()
}
}
}
impl<Ctx: Copy> SpanData<Ctx> {
pub fn eq_ignoring_ctx(self, other: Self) -> bool {
self.anchor == other.anchor && self.range == other.range

View file

@ -1,7 +1,7 @@
//! A map that maps a span to every position in a file. Usually maps a span to some range of positions.
//! Allows bidirectional lookup.
use std::hash::Hash;
use std::{fmt, hash::Hash};
use stdx::{always, itertools::Itertools};
use syntax::{TextRange, TextSize};
@ -52,7 +52,7 @@ where
/// 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: SpanData<S>) -> impl Iterator<Item = TextRange> + '_
pub fn ranges_with_span_exact(&self, span: SpanData<S>) -> impl Iterator<Item = TextRange> + '_
where
S: Copy,
{
@ -65,6 +65,25 @@ where
})
}
/// Returns all [`TextRange`]s whose spans contain the given span.
///
/// Note this does a linear search through the entire backing vector.
pub fn ranges_with_span(&self, span: SpanData<S>) -> impl Iterator<Item = TextRange> + '_
where
S: Copy,
{
self.spans.iter().enumerate().filter_map(move |(idx, &(end, s))| {
if s.anchor != span.anchor {
return None;
}
if !s.range.contains_range(span.range) {
return None;
}
let start = idx.checked_sub(1).map_or(TextSize::new(0), |prev| self.spans[prev].0);
Some(TextRange::new(start, end))
})
}
/// Returns the span at the given position.
pub fn span_at(&self, offset: TextSize) -> SpanData<S> {
let entry = self.spans.partition_point(|&(it, _)| it <= offset);
@ -94,6 +113,16 @@ pub struct RealSpanMap {
end: TextSize,
}
impl fmt::Display for RealSpanMap {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "RealSpanMap({:?}):", self.file_id)?;
for span in self.pairs.iter() {
writeln!(f, "{}: {}", u32::from(span.0), span.1.into_raw().into_u32())?;
}
Ok(())
}
}
impl RealSpanMap {
/// Creates a real file span map that returns absolute ranges (relative ranges to the root ast id).
pub fn absolute(file_id: FileId) -> Self {