mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +00:00
feat: Support macro calls in eager macros for IDE features
This commit is contained in:
parent
9767156a29
commit
d2f8eae2ec
22 changed files with 420 additions and 226 deletions
|
@ -681,19 +681,20 @@ impl<'db> SemanticsImpl<'db> {
|
|||
.filter(|&(_, include_file_id)| include_file_id == file_id)
|
||||
{
|
||||
let macro_file = invoc.as_macro_file();
|
||||
let expansion_info = cache
|
||||
.entry(macro_file)
|
||||
.or_insert_with(|| macro_file.expansion_info(self.db.upcast()));
|
||||
let expansion_info = cache.entry(macro_file).or_insert_with(|| {
|
||||
let exp_info = macro_file.expansion_info(self.db.upcast());
|
||||
|
||||
let InMacroFile { file_id, value } = exp_info.expanded();
|
||||
self.cache(value, file_id.into());
|
||||
|
||||
exp_info
|
||||
});
|
||||
|
||||
// Create the source analyzer for the macro call scope
|
||||
let Some(sa) = self.analyze_no_infer(&self.parse_or_expand(expansion_info.call_file()))
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
{
|
||||
let InMacroFile { file_id: macro_file, value } = expansion_info.expanded();
|
||||
self.cache(value, macro_file.into());
|
||||
}
|
||||
|
||||
// get mapped token in the include! macro file
|
||||
let span = span::SpanData {
|
||||
|
@ -702,7 +703,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||
ctx: SyntaxContextId::ROOT,
|
||||
};
|
||||
let Some(InMacroFile { file_id, value: mut mapped_tokens }) =
|
||||
expansion_info.map_range_down(span)
|
||||
expansion_info.map_range_down_exact(span)
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
@ -753,22 +754,20 @@ impl<'db> SemanticsImpl<'db> {
|
|||
let def_map = sa.resolver.def_map();
|
||||
|
||||
let mut stack: Vec<(_, SmallVec<[_; 2]>)> = vec![(file_id, smallvec![token])];
|
||||
|
||||
let mut process_expansion_for_token = |stack: &mut Vec<_>, macro_file| {
|
||||
let expansion_info = cache
|
||||
.entry(macro_file)
|
||||
.or_insert_with(|| macro_file.expansion_info(self.db.upcast()));
|
||||
let exp_info = cache.entry(macro_file).or_insert_with(|| {
|
||||
let exp_info = macro_file.expansion_info(self.db.upcast());
|
||||
|
||||
{
|
||||
let InMacroFile { file_id, value } = expansion_info.expanded();
|
||||
let InMacroFile { file_id, value } = exp_info.expanded();
|
||||
self.cache(value, file_id.into());
|
||||
}
|
||||
|
||||
let InMacroFile { file_id, value: mapped_tokens } =
|
||||
expansion_info.map_range_down(span)?;
|
||||
exp_info
|
||||
});
|
||||
|
||||
let InMacroFile { file_id, value: mapped_tokens } = exp_info.map_range_down(span)?;
|
||||
let mapped_tokens: SmallVec<[_; 2]> = mapped_tokens.collect();
|
||||
|
||||
// if the length changed we have found a mapping for the token
|
||||
// we have found a mapping for the token if the vec is non-empty
|
||||
let res = mapped_tokens.is_empty().not().then_some(());
|
||||
// requeue the tokens we got from mapping our current token down
|
||||
stack.push((HirFileId::from(file_id), mapped_tokens));
|
||||
|
@ -851,7 +850,13 @@ impl<'db> SemanticsImpl<'db> {
|
|||
// remove any other token in this macro input, all their mappings are the
|
||||
// same as this one
|
||||
tokens.retain(|t| !text_range.contains_range(t.text_range()));
|
||||
process_expansion_for_token(&mut stack, file_id)
|
||||
|
||||
process_expansion_for_token(&mut stack, file_id).or(file_id
|
||||
.eager_arg(self.db.upcast())
|
||||
.and_then(|arg| {
|
||||
// also descend into eager expansions
|
||||
process_expansion_for_token(&mut stack, arg.as_macro_file())
|
||||
}))
|
||||
} else if let Some(meta) = ast::Meta::cast(parent) {
|
||||
// attribute we failed expansion for earlier, this might be a derive invocation
|
||||
// or derive helper attribute
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue