Skip to content

Commit

Permalink
Auto merge of rust-lang#16834 - Veykril:macarons, r=Veykril
Browse files Browse the repository at this point in the history
feat: Support macro calls in eager macros for IDE features

Basically hovering `concat` and `env` in `include!(concat!(env!("OUT_DIR"), "/foo.rs"))` now works and highlights as expected.

This also fixes a few bugs/problems to make it work. Prior we set the call site span to the entire macro call which is kind of wrong, typing inside the call would invalidate the span causing us to leak `MacroCallLoc`s whenever that happened. The same happened for attributes both of which now define their path as the call site.
  • Loading branch information
bors committed Mar 14, 2024
2 parents 6fc3a3e + d085ade commit 14558af
Show file tree
Hide file tree
Showing 26 changed files with 456 additions and 262 deletions.
8 changes: 4 additions & 4 deletions crates/hir-def/src/data/adt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,9 @@ impl StructData {
let krate = loc.container.krate;
let item_tree = loc.id.item_tree(db);
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
let cfg_options = db.crate_graph()[krate].cfg_options.clone();

let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into());
let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());

let mut flags = StructFlags::NO_FLAGS;
if attrs.by_key("rustc_has_incoherent_inherent_impls").exists() {
Expand Down Expand Up @@ -248,9 +248,9 @@ impl StructData {
let krate = loc.container.krate;
let item_tree = loc.id.item_tree(db);
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
let cfg_options = db.crate_graph()[krate].cfg_options.clone();

let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into());
let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());
let mut flags = StructFlags::NO_FLAGS;
if attrs.by_key("rustc_has_incoherent_inherent_impls").exists() {
flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL;
Expand Down
10 changes: 3 additions & 7 deletions crates/hir-def/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,13 +309,10 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId {
kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()),
local_inner: false,
allow_internal_unsafe: loc.allow_internal_unsafe,
span: db
.span_map(loc.id.file_id())
.span_for_range(db.ast_id_map(loc.id.file_id()).get(makro.ast_id).text_range()),
span: makro.def_site,
edition: loc.edition,
}
}

MacroId::MacroRulesId(it) => {
let loc: MacroRulesLoc = it.lookup(db);

Expand All @@ -328,9 +325,7 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId {
allow_internal_unsafe: loc
.flags
.contains(MacroRulesLocFlags::ALLOW_INTERNAL_UNSAFE),
span: db
.span_map(loc.id.file_id())
.span_for_range(db.ast_id_map(loc.id.file_id()).get(makro.ast_id).text_range()),
span: makro.def_site,
edition: loc.edition,
}
}
Expand All @@ -348,6 +343,7 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId {
),
local_inner: false,
allow_internal_unsafe: false,
// FIXME: This is wrong, this should point to the name
span: db
.span_map(loc.id.file_id())
.span_for_range(db.ast_id_map(loc.id.file_id()).get(makro.ast_id).text_range()),
Expand Down
3 changes: 2 additions & 1 deletion crates/hir-def/src/item_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,6 @@ pub struct MacroCall {
pub path: Interned<ModPath>,
pub ast_id: FileAstId<ast::MacroCall>,
pub expand_to: ExpandTo,
// FIXME: We need to move this out. It invalidates the item tree when typing inside the macro call.
pub call_site: Span,
}

Expand All @@ -799,6 +798,7 @@ pub struct MacroRules {
/// The name of the declared macro.
pub name: Name,
pub ast_id: FileAstId<ast::MacroRules>,
pub def_site: Span,
}

/// "Macros 2.0" macro definition.
Expand All @@ -807,6 +807,7 @@ pub struct Macro2 {
pub name: Name,
pub visibility: RawVisibilityId,
pub ast_id: FileAstId<ast::MacroDef>,
pub def_site: Span,
}

impl Use {
Expand Down
21 changes: 10 additions & 11 deletions crates/hir-def/src/item_tree/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -560,35 +560,34 @@ impl<'a> Ctx<'a> {

fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> {
let span_map = self.span_map();
let path = Interned::new(ModPath::from_src(self.db.upcast(), m.path()?, &mut |range| {
let path = m.path()?;
let range = path.syntax().text_range();
let path = Interned::new(ModPath::from_src(self.db.upcast(), path, &mut |range| {
span_map.span_for_range(range).ctx
})?);
let ast_id = self.source_ast_id_map.ast_id(m);
let expand_to = hir_expand::ExpandTo::from_call_site(m);
let res = MacroCall {
path,
ast_id,
expand_to,
call_site: span_map.span_for_range(m.syntax().text_range()),
};
let res = MacroCall { path, ast_id, expand_to, call_site: span_map.span_for_range(range) };
Some(id(self.data().macro_calls.alloc(res)))
}

fn lower_macro_rules(&mut self, m: &ast::MacroRules) -> Option<FileItemTreeId<MacroRules>> {
let name = m.name().map(|it| it.as_name())?;
let name = m.name()?;
let def_site = self.span_map().span_for_range(name.syntax().text_range());
let ast_id = self.source_ast_id_map.ast_id(m);

let res = MacroRules { name, ast_id };
let res = MacroRules { name: name.as_name(), ast_id, def_site };
Some(id(self.data().macro_rules.alloc(res)))
}

fn lower_macro_def(&mut self, m: &ast::MacroDef) -> Option<FileItemTreeId<Macro2>> {
let name = m.name().map(|it| it.as_name())?;
let name = m.name()?;
let def_site = self.span_map().span_for_range(name.syntax().text_range());

let ast_id = self.source_ast_id_map.ast_id(m);
let visibility = self.lower_visibility(m);

let res = Macro2 { name, ast_id, visibility };
let res = Macro2 { name: name.as_name(), ast_id, visibility, def_site };
Some(id(self.data().macro_defs.alloc(res)))
}

Expand Down
18 changes: 14 additions & 4 deletions crates/hir-def/src/item_tree/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -498,13 +498,23 @@ impl Printer<'_> {
wln!(self, "{}!(...);", path.display(self.db.upcast()));
}
ModItem::MacroRules(it) => {
let MacroRules { name, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
let MacroRules { name, ast_id, def_site } = &self.tree[it];
let _ = writeln!(
self,
"// AstId: {:?}, Span: {}",
ast_id.erase().into_raw(),
def_site,
);
wln!(self, "macro_rules! {} {{ ... }}", name.display(self.db.upcast()));
}
ModItem::Macro2(it) => {
let Macro2 { name, visibility, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
let Macro2 { name, visibility, ast_id, def_site } = &self.tree[it];
let _ = writeln!(
self,
"// AstId: {:?}, Span: {}",
ast_id.erase().into_raw(),
def_site,
);
self.print_visibility(*visibility);
wln!(self, "macro {} {{ ... }}", name.display(self.db.upcast()));
}
Expand Down
6 changes: 3 additions & 3 deletions crates/hir-def/src/item_tree/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,13 +272,13 @@ pub macro m2() {}
m!();
"#,
expect![[r#"
// AstId: 1
// AstId: 1, Span: 0:[email protected]#0
macro_rules! m { ... }
// AstId: 2
// AstId: 2, Span: 0:[email protected]#0
pub macro m2 { ... }
// AstId: 3, Span: 0:3@0..5#0, ExpandTo: Items
// AstId: 3, Span: 0:3@0..1#0, ExpandTo: Items
m!(...);
"#]],
);
Expand Down
11 changes: 6 additions & 5 deletions crates/hir-def/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1342,17 +1342,18 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
let span_map = db.span_map(self.file_id);
let path = self.value.path().and_then(|path| {
path::ModPath::from_src(db, path, &mut |range| {
let range = path.syntax().text_range();
let mod_path = path::ModPath::from_src(db, path, &mut |range| {
span_map.as_ref().span_for_range(range).ctx
})
})?;
let call_site = span_map.span_for_range(range);
Some((call_site, mod_path))
});

let Some(path) = path else {
let Some((call_site, path)) = path else {
return Ok(ExpandResult::only_err(ExpandError::other("malformed macro invocation")));
};

let call_site = span_map.span_for_range(self.value.syntax().text_range());

macro_call_as_call_id_with_eager(
db,
&AstIdWithPath::new(ast_id.file_id, ast_id.value, path),
Expand Down
2 changes: 1 addition & 1 deletion crates/hir-def/src/macro_expansion_tests/mbe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ fn main(foo: ()) {
}
fn main(foo: ()) {
/* error: unresolved macro unresolved */"helloworld!"#0:3@207..323#2#;
/* error: unresolved macro unresolved */"helloworld!"#0:3@236..321#0#;
}
}
Expand Down
6 changes: 4 additions & 2 deletions crates/hir-expand/src/attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,12 @@ impl Attr {
span_map: SpanMapRef<'_>,
id: AttrId,
) -> Option<Attr> {
let path = Interned::new(ModPath::from_src(db, ast.path()?, &mut |range| {
let path = ast.path()?;
let range = path.syntax().text_range();
let path = Interned::new(ModPath::from_src(db, path, &mut |range| {
span_map.span_for_range(range).ctx
})?);
let span = span_map.span_for_range(ast.syntax().text_range());
let span = span_map.span_for_range(range);
let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() {
let value = match lit.kind() {
ast::LiteralKind::String(string) => string.value()?.into(),
Expand Down
Loading

0 comments on commit 14558af

Please sign in to comment.