mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 14:21:44 +00:00
Thinner TokenMap
This commit is contained in:
parent
92d447f976
commit
98cfdde8ba
13 changed files with 123 additions and 259 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue