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.rs | 37 |
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(), + )) +} |