Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-expand/src/span_map.rs')
-rw-r--r--crates/hir-expand/src/span_map.rs37
1 files changed, 34 insertions, 3 deletions
diff --git a/crates/hir-expand/src/span_map.rs b/crates/hir-expand/src/span_map.rs
index 4ec6e657f9..8e624f5585 100644
--- a/crates/hir-expand/src/span_map.rs
+++ b/crates/hir-expand/src/span_map.rs
@@ -1,10 +1,12 @@
//! Span maps for real files and macro expansions.
-use span::Span;
-use syntax::TextRange;
+use span::{FileId, HirFileId, HirFileIdRepr, Span};
+use syntax::{AstNode, TextRange};
use triomphe::Arc;
pub use span::RealSpanMap;
+use crate::db::ExpandDatabase;
+
pub type ExpansionSpanMap = span::SpanMap<Span>;
/// Spanmap for a macro file or a real file
@@ -34,7 +36,6 @@ impl mbe::SpanMapper<Span> for SpanMapRef<'_> {
self.span_for_range(range)
}
}
-
impl SpanMap {
pub fn span_for_range(&self, range: TextRange) -> Span {
match self {
@@ -53,6 +54,16 @@ impl SpanMap {
Self::RealSpanMap(span_map) => SpanMapRef::RealSpanMap(span_map),
}
}
+
+ #[inline]
+ pub(crate) fn new(db: &dyn ExpandDatabase, file_id: HirFileId) -> SpanMap {
+ match file_id.repr() {
+ HirFileIdRepr::FileId(file_id) => SpanMap::RealSpanMap(db.real_span_map(file_id)),
+ HirFileIdRepr::MacroFile(m) => {
+ SpanMap::ExpansionSpanMap(db.parse_macro_expansion(m).value.1)
+ }
+ }
+ }
}
impl SpanMapRef<'_> {
@@ -63,3 +74,23 @@ impl SpanMapRef<'_> {
}
}
}
+
+pub(crate) fn real_span_map(db: &dyn ExpandDatabase, file_id: FileId) -> Arc<RealSpanMap> {
+ 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();
+ // FIXME: Descend into modules and other item containing items that are not annotated with attributes
+ // and allocate pairs for those as well. This gives us finer grained span anchors resulting in
+ // better incrementality
+ 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(),
+ ))
+}