mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +00:00
Fix macro expansion expression parenthesis wrapping
This commit is contained in:
parent
efa67294ed
commit
d2a31acda1
18 changed files with 218 additions and 64 deletions
|
@ -1025,7 +1025,7 @@ impl ExprCollector<'_> {
|
|||
|
||||
let id = collector(self, Some(expansion.tree()));
|
||||
self.ast_id_map = prev_ast_id_map;
|
||||
self.expander.exit(self.db, mark);
|
||||
self.expander.exit(mark);
|
||||
id
|
||||
}
|
||||
None => collector(self, None),
|
||||
|
|
|
@ -2,6 +2,7 @@ mod block;
|
|||
|
||||
use base_db::{fixture::WithFixture, SourceDatabase};
|
||||
use expect_test::{expect, Expect};
|
||||
use hir_expand::db::ExpandDatabase;
|
||||
|
||||
use crate::{test_db::TestDB, ModuleDefId};
|
||||
|
||||
|
@ -143,7 +144,6 @@ mod m {
|
|||
|
||||
#[test]
|
||||
fn desugar_builtin_format_args() {
|
||||
// Regression test for a path resolution bug introduced with inner item handling.
|
||||
let (db, body, def) = lower(
|
||||
r#"
|
||||
//- minicore: fmt
|
||||
|
@ -221,3 +221,70 @@ fn main() {
|
|||
}"#]]
|
||||
.assert_eq(&body.pretty_print(&db, def))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_macro_hygiene() {
|
||||
let (db, body, def) = lower(
|
||||
r##"
|
||||
//- minicore: fmt, from
|
||||
//- /main.rs
|
||||
mod error;
|
||||
|
||||
use crate::error::error;
|
||||
|
||||
fn main() {
|
||||
// _ = forces body expansion instead of block def map expansion
|
||||
_ = error!("Failed to resolve path `{}`", node.text());
|
||||
}
|
||||
//- /error.rs
|
||||
macro_rules! _error {
|
||||
($fmt:expr, $($arg:tt)+) => {$crate::error::intermediate!(format_args!($fmt, $($arg)+))}
|
||||
}
|
||||
pub(crate) use _error as error;
|
||||
macro_rules! _intermediate {
|
||||
($arg:expr) => {$crate::error::SsrError::new($arg)}
|
||||
}
|
||||
pub(crate) use _intermediate as intermediate;
|
||||
|
||||
pub struct SsrError(pub(crate) core::fmt::Arguments);
|
||||
|
||||
impl SsrError {
|
||||
pub(crate) fn new(message: impl Into<core::fmt::Arguments>) -> SsrError {
|
||||
SsrError(message.into())
|
||||
}
|
||||
}
|
||||
"##,
|
||||
);
|
||||
println!("{}", db.dump_syntax_contexts());
|
||||
|
||||
assert_eq!(db.body_with_source_map(def.into()).1.diagnostics(), &[]);
|
||||
expect![[r#"
|
||||
fn main() {
|
||||
_ = $crate::error::SsrError::new(
|
||||
builtin#lang(Arguments::new_v1_formatted)(
|
||||
&[
|
||||
"\"Failed to resolve path `", "`\"",
|
||||
],
|
||||
&[
|
||||
builtin#lang(Argument::new_display)(
|
||||
&node.text(),
|
||||
),
|
||||
],
|
||||
&[
|
||||
builtin#lang(Placeholder::new)(
|
||||
0usize,
|
||||
' ',
|
||||
builtin#lang(Alignment::Unknown),
|
||||
0u32,
|
||||
builtin#lang(Count::Implied),
|
||||
builtin#lang(Count::Implied),
|
||||
),
|
||||
],
|
||||
unsafe {
|
||||
builtin#lang(UnsafeArg::new)()
|
||||
},
|
||||
),
|
||||
);
|
||||
}"#]]
|
||||
.assert_eq(&body.pretty_print(&db, def))
|
||||
}
|
||||
|
|
|
@ -794,7 +794,7 @@ impl<'a> AssocItemCollector<'a> {
|
|||
|
||||
self.collect(&item_tree, tree_id, &iter);
|
||||
|
||||
self.expander.exit(self.db, mark);
|
||||
self.expander.exit(mark);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -94,8 +94,8 @@ impl Expander {
|
|||
ExpandResult { value: Some(InFile::new(macro_file.into(), value.0)), err: error.or(err) }
|
||||
}
|
||||
|
||||
pub fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) {
|
||||
self.span_map = db.span_map(mark.file_id);
|
||||
pub fn exit(&mut self, mut mark: Mark) {
|
||||
self.span_map = mark.span_map;
|
||||
self.current_file_id = mark.file_id;
|
||||
if self.recursion_depth == u32::MAX {
|
||||
// Recursion limit has been reached somewhere in the macro expansion tree. Reset the
|
||||
|
@ -174,10 +174,11 @@ impl Expander {
|
|||
let parse = value.cast::<T>()?;
|
||||
|
||||
self.recursion_depth += 1;
|
||||
self.span_map = db.span_map(file_id);
|
||||
let old_span_map = std::mem::replace(&mut self.span_map, db.span_map(file_id));
|
||||
let old_file_id = std::mem::replace(&mut self.current_file_id, file_id);
|
||||
let mark = Mark {
|
||||
file_id: old_file_id,
|
||||
span_map: old_span_map,
|
||||
bomb: DropBomb::new("expansion mark dropped"),
|
||||
};
|
||||
Some((mark, parse))
|
||||
|
@ -190,5 +191,6 @@ impl Expander {
|
|||
#[derive(Debug)]
|
||||
pub struct Mark {
|
||||
file_id: HirFileId,
|
||||
span_map: SpanMap,
|
||||
bomb: DropBomb,
|
||||
}
|
||||
|
|
|
@ -439,7 +439,7 @@ impl GenericParams {
|
|||
let ctx = expander.ctx(db);
|
||||
let type_ref = TypeRef::from_ast(&ctx, expanded.tree());
|
||||
self.fill_implicit_impl_trait_args(db, &mut *exp, &type_ref);
|
||||
exp.1.exit(db, mark);
|
||||
exp.1.exit(mark);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -997,9 +997,9 @@ macro_rules! vec {
|
|||
fn f() {
|
||||
{
|
||||
let mut v = Vec::new();
|
||||
v.push((1));
|
||||
v.push((2));
|
||||
v.push((3));
|
||||
v.push(1);
|
||||
v.push(2);
|
||||
v.push(3);
|
||||
v
|
||||
};
|
||||
}
|
||||
|
@ -1468,8 +1468,8 @@ macro_rules! matches {
|
|||
};
|
||||
}
|
||||
fn main() {
|
||||
match (0) {
|
||||
0|1 if (true )=>true , _=>false
|
||||
match 0 {
|
||||
0|1 if true =>true , _=>false
|
||||
};
|
||||
}
|
||||
"#]],
|
||||
|
|
|
@ -62,10 +62,10 @@ macro_rules !implement_methods {
|
|||
struct Foo;
|
||||
impl Foo {
|
||||
fn alpha() -> &'static[u32] {
|
||||
&[(1), (2), (3)]
|
||||
&[1, 2, 3]
|
||||
}
|
||||
fn beta() -> &'static[u32] {
|
||||
&[(1), (2), (3)]
|
||||
&[1, 2, 3]
|
||||
}
|
||||
}
|
||||
"#]],
|
||||
|
|
|
@ -39,8 +39,8 @@ fn main() {
|
|||
};
|
||||
{
|
||||
let mut v = Vec::new();
|
||||
v.push((1u32));
|
||||
v.push((2));
|
||||
v.push(1u32);
|
||||
v.push(2);
|
||||
v
|
||||
};
|
||||
}
|
||||
|
|
|
@ -192,9 +192,9 @@ macro_rules! constant {
|
|||
($e:expr ;) => {$e};
|
||||
}
|
||||
|
||||
const _: () = (0.0);
|
||||
const _: () = (0.);
|
||||
const _: () = (0e0);
|
||||
const _: () = 0.0;
|
||||
const _: () = 0.;
|
||||
const _: () = 0e0;
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue