Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-expand/src/lib.rs')
| -rw-r--r-- | crates/hir-expand/src/lib.rs | 91 |
1 files changed, 39 insertions, 52 deletions
diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs index 4e5aa90312..9027ea1c27 100644 --- a/crates/hir-expand/src/lib.rs +++ b/crates/hir-expand/src/lib.rs @@ -44,7 +44,7 @@ use crate::{ db::TokenExpander, mod_path::ModPath, proc_macro::ProcMacroExpander, - span::ExpansionSpanMap, + span::{ExpansionSpanMap, SpanMap}, }; pub use crate::ast_id_map::{AstId, ErasedAstId, ErasedFileAstId}; @@ -172,7 +172,6 @@ pub trait HirFileIdExt { /// For macro-expansion files, returns the file original source file the /// expansion originated from. fn original_file(self, db: &dyn db::ExpandDatabase) -> FileId; - fn expansion_level(self, db: &dyn db::ExpandDatabase) -> u32; /// If this is a macro call, returns the syntax node of the call. fn call_node(self, db: &dyn db::ExpandDatabase) -> Option<InFile<SyntaxNode>>; @@ -218,18 +217,6 @@ impl HirFileIdExt for HirFileId { } } - fn expansion_level(self, db: &dyn db::ExpandDatabase) -> u32 { - let mut level = 0; - let mut curr = self; - while let Some(macro_file) = curr.macro_file() { - let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id); - - level += 1; - curr = loc.kind.file_id(); - } - level - } - fn call_node(self, db: &dyn db::ExpandDatabase) -> Option<InFile<SyntaxNode>> { let macro_file = self.macro_file()?; let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id); @@ -330,6 +317,32 @@ impl HirFileIdExt for HirFileId { } } +pub trait MacroFileIdExt { + fn expansion_level(self, db: &dyn db::ExpandDatabase) -> u32; + fn expansion_info(self, db: &dyn db::ExpandDatabase) -> ExpansionInfo; +} + +impl MacroFileIdExt for MacroFileId { + fn expansion_level(self, db: &dyn db::ExpandDatabase) -> u32 { + let mut level = 0; + let mut macro_file = self; + loop { + let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id); + + level += 1; + macro_file = match loc.kind.file_id().repr() { + HirFileIdRepr::FileId(_) => break level, + HirFileIdRepr::MacroFile(it) => it, + }; + } + } + + /// Return expansion information if it is a macro-expansion file + fn expansion_info(self, db: &dyn db::ExpandDatabase) -> ExpansionInfo { + ExpansionInfo::new(db, self) + } +} + impl MacroDefId { pub fn as_lazy_macro( self, @@ -398,7 +411,7 @@ impl MacroCallLoc { match file_id.repr() { HirFileIdRepr::FileId(file_id) => db.real_span_map(file_id).span_for_range(range), HirFileIdRepr::MacroFile(m) => { - db.parse_macro_expansion(m).value.1.span_for_range(range) + db.parse_macro_expansion(m).value.1.span_at(range.start()) } } } @@ -565,9 +578,8 @@ pub struct ExpansionInfo { macro_def: TokenExpander, macro_arg: Arc<tt::Subtree>, - exp_map: Arc<ExpansionSpanMap>, - /// [`None`] if the call is in a real file - arg_map: Option<Arc<ExpansionSpanMap>>, + pub exp_map: Arc<ExpansionSpanMap>, + arg_map: SpanMap, } impl ExpansionInfo { @@ -582,38 +594,14 @@ impl ExpansionInfo { /// Maps the passed in file range down into a macro expansion if it is the input to a macro call. pub fn map_range_down<'a>( &'a self, - db: &'a dyn db::ExpandDatabase, - FileRange { file_id, range: absolute_range }: FileRange, + span: SpanData, // FIXME: use this for range mapping, so that we can resolve inline format args _relative_token_offset: Option<TextSize>, // FIXME: ret ty should be wrapped in InMacroFile ) -> Option<impl Iterator<Item = InFile<SyntaxToken>> + 'a> { - // search for all entries in the span map that have the given span and return the - // corresponding text ranges inside the expansion - // FIXME: Make this proper - let span_map = &self.exp_map.span_map; - let (start, end) = if span_map - .first() - .map_or(false, |(_, span)| span.anchor.file_id == file_id) - { - (0, span_map.partition_point(|a| a.1.anchor.file_id == file_id)) - } else { - let start = span_map.partition_point(|a| a.1.anchor.file_id != file_id); - (start, start + span_map[start..].partition_point(|a| a.1.anchor.file_id == file_id)) - }; - let tokens = span_map[start..end] - .iter() - .filter_map(move |(range, span)| { - // we need to resolve the relative ranges here to make sure that we are in fact - // considering differently anchored spans (this might occur with proc-macros) - let offset = db - .ast_id_map(span.anchor.file_id.into()) - .get_erased(span.anchor.ast_id) - .text_range() - .start(); - let abs_range = span.range + offset; - absolute_range.eq(&abs_range).then_some(*range) - }) + let tokens = self + .exp_map + .ranges_with_span(span) .flat_map(move |range| self.expanded.value.covering_element(range).into_token()); Some(tokens.map(move |token| InFile::new(self.expanded.file_id.into(), token))) @@ -626,7 +614,7 @@ impl ExpansionInfo { range: TextRange, ) -> (FileRange, SyntaxContextId) { debug_assert!(self.expanded.value.text_range().contains_range(range)); - let span = self.exp_map.span_for_range(range); + let span = self.exp_map.span_at(range.start()); let anchor_offset = db .ast_id_map(span.anchor.file_id.into()) .get_erased(span.anchor.ast_id) @@ -672,15 +660,15 @@ impl ExpansionInfo { token: TextRange, ) -> InFile<smallvec::SmallVec<[TextRange; 1]>> { debug_assert!(self.expanded.value.text_range().contains_range(token)); - let span = self.exp_map.span_for_range(token); + let span = self.exp_map.span_at(token.start()); match &self.arg_map { - None => { + SpanMap::RealSpanMap(_) => { let file_id = span.anchor.file_id.into(); let anchor_offset = db.ast_id_map(file_id).get_erased(span.anchor.ast_id).text_range().start(); InFile { file_id, value: smallvec::smallvec![span.range + anchor_offset] } } - Some(arg_map) => { + SpanMap::ExpansionSpanMap(arg_map) => { let arg_range = self .arg .value @@ -701,8 +689,7 @@ impl ExpansionInfo { let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id); let arg_tt = loc.kind.arg(db); - let arg_map = - arg_tt.file_id.macro_file().map(|file| db.parse_macro_expansion(file).value.1); + let arg_map = db.span_map(arg_tt.file_id); let macro_def = db.macro_expander(loc.def); let (parse, exp_map) = db.parse_macro_expansion(macro_file).value; |