mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 12:33:33 +00:00
Merge #9978
9978: fix: Expand attributes recursively in expand_macro r=Veykril a=Veykril bors r+ Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
commit
8cd171cd94
2 changed files with 29 additions and 8 deletions
|
@ -278,6 +278,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
|
|||
self.imp.resolve_macro_call(macro_call)
|
||||
}
|
||||
|
||||
pub fn resolve_attr_macro_call(&self, item: &ast::Item) -> Option<MacroDef> {
|
||||
self.imp.resolve_attr_macro_call(item)
|
||||
}
|
||||
|
||||
pub fn resolve_path(&self, path: &ast::Path) -> Option<PathResolution> {
|
||||
self.imp.resolve_path(path)
|
||||
}
|
||||
|
@ -634,6 +638,12 @@ impl<'db> SemanticsImpl<'db> {
|
|||
sa.resolve_macro_call(self.db, macro_call)
|
||||
}
|
||||
|
||||
fn resolve_attr_macro_call(&self, item: &ast::Item) -> Option<MacroDef> {
|
||||
let item_in_file = self.find_file(item.syntax().clone()).with_value(item.clone());
|
||||
let macro_call_id = self.with_ctx(|ctx| ctx.item_to_macro_call(item_in_file))?;
|
||||
Some(MacroDef { id: self.db.lookup_intern_macro(macro_call_id).def })
|
||||
}
|
||||
|
||||
fn resolve_path(&self, path: &ast::Path) -> Option<PathResolution> {
|
||||
self.analyze(path.syntax()).resolve_path(self.db, path)
|
||||
}
|
||||
|
|
|
@ -34,11 +34,9 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
|
|||
let mut name = None;
|
||||
for node in tok.ancestors() {
|
||||
if let Some(item) = ast::Item::cast(node.clone()) {
|
||||
expanded = sema.expand_attr_macro(&item);
|
||||
if expanded.is_some() {
|
||||
// FIXME: add the macro name
|
||||
// FIXME: make this recursive too
|
||||
name = Some("?".to_string());
|
||||
if let Some(def) = sema.resolve_attr_macro_call(&item) {
|
||||
name = def.name(db).map(|name| name.to_string());
|
||||
expanded = expand_attr_macro_recur(&sema, &item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +52,7 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
|
|||
// macro expansion may lose all white space information
|
||||
// But we hope someday we can use ra_fmt for that
|
||||
let expansion = insert_whitespaces(expanded?);
|
||||
Some(ExpandedMacro { name: name?, expansion })
|
||||
Some(ExpandedMacro { name: name.unwrap_or_else(|| "???".to_owned()), expansion })
|
||||
}
|
||||
|
||||
fn expand_macro_recur(
|
||||
|
@ -62,12 +60,25 @@ fn expand_macro_recur(
|
|||
macro_call: &ast::MacroCall,
|
||||
) -> Option<SyntaxNode> {
|
||||
let expanded = sema.expand(macro_call)?.clone_for_update();
|
||||
expand(sema, expanded, ast::MacroCall::cast, expand_macro_recur)
|
||||
}
|
||||
|
||||
let children = expanded.descendants().filter_map(ast::MacroCall::cast);
|
||||
fn expand_attr_macro_recur(sema: &Semantics<RootDatabase>, item: &ast::Item) -> Option<SyntaxNode> {
|
||||
let expanded = sema.expand_attr_macro(item)?.clone_for_update();
|
||||
expand(sema, expanded, ast::Item::cast, expand_attr_macro_recur)
|
||||
}
|
||||
|
||||
fn expand<T: AstNode>(
|
||||
sema: &Semantics<RootDatabase>,
|
||||
expanded: SyntaxNode,
|
||||
f: impl FnMut(SyntaxNode) -> Option<T>,
|
||||
exp: impl Fn(&Semantics<RootDatabase>, &T) -> Option<SyntaxNode>,
|
||||
) -> Option<SyntaxNode> {
|
||||
let children = expanded.descendants().filter_map(f);
|
||||
let mut replacements = Vec::new();
|
||||
|
||||
for child in children {
|
||||
if let Some(new_node) = expand_macro_recur(sema, &child) {
|
||||
if let Some(new_node) = exp(sema, &child) {
|
||||
// check if the whole original syntax is replaced
|
||||
if expanded == *child.syntax() {
|
||||
return Some(new_node);
|
||||
|
|
Loading…
Reference in a new issue