Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/span/src/lib.rs')
| -rw-r--r-- | crates/span/src/lib.rs | 53 |
1 files changed, 41 insertions, 12 deletions
diff --git a/crates/span/src/lib.rs b/crates/span/src/lib.rs index ae9e038459..bfe7b2620d 100644 --- a/crates/span/src/lib.rs +++ b/crates/span/src/lib.rs @@ -1,4 +1,10 @@ //! File and span related types. + +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] + +#[cfg(feature = "in-rust-tree")] +extern crate rustc_driver as _; + use std::fmt::{self, Write}; mod ast_id; @@ -8,7 +14,7 @@ mod map; pub use self::{ ast_id::{ AstIdMap, AstIdNode, ErasedFileAstId, FIXUP_ERASED_FILE_AST_ID_MARKER, FileAstId, - ROOT_ERASED_FILE_AST_ID, + NO_DOWNMAP_ERASED_FILE_AST_ID_MARKER, ROOT_ERASED_FILE_AST_ID, }, hygiene::{SyntaxContext, Transparency}, map::{RealSpanMap, SpanMap}, @@ -18,8 +24,6 @@ pub use syntax::Edition; pub use text_size::{TextRange, TextSize}; pub use vfs::FileId; -pub type Span = SpanData<SyntaxContext>; - impl Span { pub fn cover(self, other: Span) -> Span { if self.anchor != other.anchor { @@ -28,13 +32,44 @@ impl Span { let range = self.range.cover(other.range); Span { range, ..self } } + + pub fn join( + self, + other: Span, + differing_anchor: impl FnOnce(Span, Span) -> Option<Span>, + ) -> Option<Span> { + // We can't modify the span range for fixup spans, those are meaningful to fixup, so just + // prefer the non-fixup span. + if self.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER { + return Some(other); + } + if other.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER { + return Some(self); + } + if self.anchor != other.anchor { + return differing_anchor(self, other); + } + // Differing context, we can't merge these so prefer the one that's root + if self.ctx != other.ctx { + if self.ctx.is_root() { + return Some(other); + } else if other.ctx.is_root() { + return Some(self); + } + } + Some(Span { range: self.range.cover(other.range), anchor: other.anchor, ctx: other.ctx }) + } + + pub fn eq_ignoring_ctx(self, other: Self) -> bool { + self.anchor == other.anchor && self.range == other.range + } } /// Spans represent a region of code, used by the IDE to be able link macro inputs and outputs /// together. Positions in spans are relative to some [`SpanAnchor`] to make them more incremental /// friendly. #[derive(Clone, Copy, PartialEq, Eq, Hash)] -pub struct SpanData<Ctx> { +pub struct Span { /// The text range of this span, relative to the anchor. /// We need the anchor for incrementality, as storing absolute ranges will require /// recomputation on every change in a file at all times. @@ -42,10 +77,10 @@ pub struct SpanData<Ctx> { /// The anchor this span is relative to. pub anchor: SpanAnchor, /// The syntax context of the span. - pub ctx: Ctx, + pub ctx: SyntaxContext, } -impl<Ctx: fmt::Debug> fmt::Debug for SpanData<Ctx> { +impl fmt::Debug for Span { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if f.alternate() { fmt::Debug::fmt(&self.anchor.file_id.file_id().index(), f)?; @@ -65,12 +100,6 @@ impl<Ctx: fmt::Debug> fmt::Debug for SpanData<Ctx> { } } -impl<Ctx: Copy> SpanData<Ctx> { - pub fn eq_ignoring_ctx(self, other: Self) -> bool { - self.anchor == other.anchor && self.range == other.range - } -} - impl fmt::Display for Span { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self.anchor.file_id.file_id().index(), f)?; |