Skip to content

Commit

Permalink
Move the SpanMap definition into the span crate
Browse files Browse the repository at this point in the history
  • Loading branch information
Veykril committed Dec 18, 2023
1 parent 66e29be commit ec61623
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 74 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion crates/base-db/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,5 @@ profile.workspace = true
stdx.workspace = true
syntax.workspace = true
test-utils.workspace = true
tt.workspace = true
vfs.workspace = true
span.workspace = true
15 changes: 14 additions & 1 deletion crates/hir-expand/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,20 @@ pub fn span_map(db: &dyn ExpandDatabase, file_id: HirFileId) -> SpanMap {
}

pub fn real_span_map(db: &dyn ExpandDatabase, file_id: FileId) -> Arc<RealSpanMap> {
Arc::new(RealSpanMap::from_file(db, file_id))
use syntax::ast::HasModuleItem;
let mut pairs = vec![(syntax::TextSize::new(0), span::ROOT_ERASED_FILE_AST_ID)];
let ast_id_map = db.ast_id_map(file_id.into());
let tree = db.parse(file_id).tree();
pairs.extend(
tree.items()
.map(|item| (item.syntax().text_range().start(), ast_id_map.ast_id(&item).erase())),
);

Arc::new(RealSpanMap::from_file(
file_id,
pairs.into_boxed_slice(),
tree.syntax().text_range().end(),
))
}

/// This expands the given macro call, but with different arguments. This is
Expand Down
3 changes: 3 additions & 0 deletions crates/hir-expand/src/hygiene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
//!
//! Specifically, `ast` + `Hygiene` allows you to create a `Name`. Note that, at
//! this moment, this is horribly incomplete and handles only `$crate`.
// FIXME: Consider moving this into the span crate.

use std::iter;

use span::{MacroCallId, Span, SyntaxContextId};
Expand Down
4 changes: 2 additions & 2 deletions crates/hir-expand/src/quote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,8 @@ mod tests {
assert_eq!(quoted.to_string(), "hello");
let t = format!("{quoted:?}");
expect![[r#"
SUBTREE $$ Span { range: 0..0, anchor: SpanAnchor(FileId(937550), 0), ctx: SyntaxContextId(0) } Span { range: 0..0, anchor: SpanAnchor(FileId(937550), 0), ctx: SyntaxContextId(0) }
IDENT hello Span { range: 0..0, anchor: SpanAnchor(FileId(937550), 0), ctx: SyntaxContextId(0) }"#]].assert_eq(&t);
SUBTREE $$ SpanData { range: 0..0, anchor: SpanAnchor(FileId(937550), 0), ctx: SyntaxContextId(0) } SpanData { range: 0..0, anchor: SpanAnchor(FileId(937550), 0), ctx: SyntaxContextId(0) }
IDENT hello SpanData { range: 0..0, anchor: SpanAnchor(FileId(937550), 0), ctx: SyntaxContextId(0) }"#]].assert_eq(&t);
}

#[test]
Expand Down
72 changes: 4 additions & 68 deletions crates/hir-expand/src/span_map.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
//! Spanmaps allow turning absolute ranges into relative ranges for incrementality purposes as well
//! as associating spans with text ranges in a particular file.
// FIXME: Consider moving this into the span crate

use base_db::FileId;
use span::{ErasedFileAstId, Span, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID};
use syntax::{ast::HasModuleItem, AstNode, TextRange, TextSize};
//! Span maps for real files and macro expansions.
use span::Span;
use syntax::TextRange;
use triomphe::Arc;

use crate::db::ExpandDatabase;
pub use span::RealSpanMap;

pub type ExpansionSpanMap = span::SpanMap<Span>;

Expand Down Expand Up @@ -39,11 +34,6 @@ impl mbe::SpanMapper<Span> for SpanMapRef<'_> {
self.span_for_range(range)
}
}
impl mbe::SpanMapper<Span> for RealSpanMap {
fn span_for(&self, range: TextRange) -> Span {
self.span_for_range(range)
}
}

impl SpanMap {
pub fn span_for_range(&self, range: TextRange) -> Span {
Expand All @@ -69,57 +59,3 @@ impl SpanMapRef<'_> {
}
}
}

#[derive(PartialEq, Eq, Hash, Debug)]
pub struct RealSpanMap {
file_id: FileId,
/// Invariant: Sorted vec over TextSize
// FIXME: SortedVec<(TextSize, ErasedFileAstId)>?
pairs: Box<[(TextSize, ErasedFileAstId)]>,
end: TextSize,
}

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 {
RealSpanMap {
file_id,
pairs: Box::from([(TextSize::new(0), ROOT_ERASED_FILE_AST_ID)]),
end: TextSize::new(!0),
}
}

pub fn from_file(db: &dyn ExpandDatabase, file_id: FileId) -> Self {
let mut pairs = vec![(TextSize::new(0), ROOT_ERASED_FILE_AST_ID)];
let ast_id_map = db.ast_id_map(file_id.into());
let tree = db.parse(file_id).tree();
pairs
.extend(tree.items().map(|item| {
(item.syntax().text_range().start(), ast_id_map.ast_id(&item).erase())
}));
RealSpanMap {
file_id,
pairs: pairs.into_boxed_slice(),
end: tree.syntax().text_range().end(),
}
}

pub fn span_for_range(&self, range: TextRange) -> Span {
assert!(
range.end() <= self.end,
"range {range:?} goes beyond the end of the file {:?}",
self.end
);
let start = range.start();
let idx = self
.pairs
.binary_search_by(|&(it, _)| it.cmp(&start).then(std::cmp::Ordering::Less))
.unwrap_err();
let (offset, ast_id) = self.pairs[idx - 1];
Span {
range: range - offset,
anchor: SpanAnchor { file_id: self.file_id, ast_id },
ctx: SyntaxContextId::ROOT,
}
}
}
2 changes: 1 addition & 1 deletion crates/span/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use salsa::InternId;

mod map;

pub use crate::map::SpanMap;
pub use crate::map::{RealSpanMap, SpanMap};
pub use syntax::{TextRange, TextSize};
pub use vfs::FileId;

Expand Down
50 changes: 50 additions & 0 deletions crates/span/src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ use std::hash::Hash;

use stdx::{always, itertools::Itertools};
use syntax::{TextRange, TextSize};
use vfs::FileId;

use crate::{ErasedFileAstId, Span, SpanAnchor, 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)]
Expand Down Expand Up @@ -79,3 +82,50 @@ impl<S: Copy> SpanMap<S> {
self.spans.iter().copied()
}
}

#[derive(PartialEq, Eq, Hash, Debug)]
pub struct RealSpanMap {
file_id: FileId,
/// Invariant: Sorted vec over TextSize
// FIXME: SortedVec<(TextSize, ErasedFileAstId)>?
pairs: Box<[(TextSize, ErasedFileAstId)]>,
end: TextSize,
}

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 {
RealSpanMap {
file_id,
pairs: Box::from([(TextSize::new(0), ROOT_ERASED_FILE_AST_ID)]),
end: TextSize::new(!0),
}
}

pub fn from_file(
file_id: FileId,
pairs: Box<[(TextSize, ErasedFileAstId)]>,
end: TextSize,
) -> Self {
Self { file_id, pairs, end }
}

pub fn span_for_range(&self, range: TextRange) -> Span {
assert!(
range.end() <= self.end,
"range {range:?} goes beyond the end of the file {:?}",
self.end
);
let start = range.start();
let idx = self
.pairs
.binary_search_by(|&(it, _)| it.cmp(&start).then(std::cmp::Ordering::Less))
.unwrap_err();
let (offset, ast_id) = self.pairs[idx - 1];
Span {
range: range - offset,
anchor: SpanAnchor { file_id: self.file_id, ast_id },
ctx: SyntaxContextId::ROOT,
}
}
}

0 comments on commit ec61623

Please sign in to comment.