mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-26 11:59:49 +00:00
Move the SpanMap definition into the span crate
This commit is contained in:
parent
66e29be1bd
commit
ec6162308e
8 changed files with 74 additions and 74 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -79,7 +79,6 @@ dependencies = [
|
||||||
"syntax",
|
"syntax",
|
||||||
"test-utils",
|
"test-utils",
|
||||||
"triomphe",
|
"triomphe",
|
||||||
"tt",
|
|
||||||
"vfs",
|
"vfs",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,5 @@ profile.workspace = true
|
||||||
stdx.workspace = true
|
stdx.workspace = true
|
||||||
syntax.workspace = true
|
syntax.workspace = true
|
||||||
test-utils.workspace = true
|
test-utils.workspace = true
|
||||||
tt.workspace = true
|
|
||||||
vfs.workspace = true
|
vfs.workspace = true
|
||||||
span.workspace = true
|
span.workspace = true
|
||||||
|
|
|
@ -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> {
|
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
|
/// This expands the given macro call, but with different arguments. This is
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
//!
|
//!
|
||||||
//! Specifically, `ast` + `Hygiene` allows you to create a `Name`. Note that, at
|
//! Specifically, `ast` + `Hygiene` allows you to create a `Name`. Note that, at
|
||||||
//! this moment, this is horribly incomplete and handles only `$crate`.
|
//! this moment, this is horribly incomplete and handles only `$crate`.
|
||||||
|
|
||||||
|
// FIXME: Consider moving this into the span crate.
|
||||||
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use span::{MacroCallId, Span, SyntaxContextId};
|
use span::{MacroCallId, Span, SyntaxContextId};
|
||||||
|
|
|
@ -259,8 +259,8 @@ mod tests {
|
||||||
assert_eq!(quoted.to_string(), "hello");
|
assert_eq!(quoted.to_string(), "hello");
|
||||||
let t = format!("{quoted:?}");
|
let t = format!("{quoted:?}");
|
||||||
expect![[r#"
|
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) }
|
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 Span { range: 0..0, anchor: SpanAnchor(FileId(937550), 0), ctx: SyntaxContextId(0) }"#]].assert_eq(&t);
|
IDENT hello SpanData { range: 0..0, anchor: SpanAnchor(FileId(937550), 0), ctx: SyntaxContextId(0) }"#]].assert_eq(&t);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -1,14 +1,9 @@
|
||||||
//! Spanmaps allow turning absolute ranges into relative ranges for incrementality purposes as well
|
//! Span maps for real files and macro expansions.
|
||||||
//! as associating spans with text ranges in a particular file.
|
use span::Span;
|
||||||
|
use syntax::TextRange;
|
||||||
// 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};
|
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
||||||
use crate::db::ExpandDatabase;
|
pub use span::RealSpanMap;
|
||||||
|
|
||||||
pub type ExpansionSpanMap = span::SpanMap<Span>;
|
pub type ExpansionSpanMap = span::SpanMap<Span>;
|
||||||
|
|
||||||
|
@ -39,11 +34,6 @@ impl mbe::SpanMapper<Span> for SpanMapRef<'_> {
|
||||||
self.span_for_range(range)
|
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 {
|
impl SpanMap {
|
||||||
pub fn span_for_range(&self, range: TextRange) -> Span {
|
pub fn span_for_range(&self, range: TextRange) -> Span {
|
||||||
|
@ -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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ use salsa::InternId;
|
||||||
|
|
||||||
mod map;
|
mod map;
|
||||||
|
|
||||||
pub use crate::map::SpanMap;
|
pub use crate::map::{RealSpanMap, SpanMap};
|
||||||
pub use syntax::{TextRange, TextSize};
|
pub use syntax::{TextRange, TextSize};
|
||||||
pub use vfs::FileId;
|
pub use vfs::FileId;
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,9 @@ use std::hash::Hash;
|
||||||
|
|
||||||
use stdx::{always, itertools::Itertools};
|
use stdx::{always, itertools::Itertools};
|
||||||
use syntax::{TextRange, TextSize};
|
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.
|
/// Maps absolute text ranges for the corresponding file to the relevant span data.
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
||||||
|
@ -79,3 +82,50 @@ impl<S: Copy> SpanMap<S> {
|
||||||
self.spans.iter().copied()
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue