mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-12-27 16:07:46 +00:00
fix
test case
This commit is contained in:
parent
ea1d2998f2
commit
a769fbdb87
@ -108,6 +108,42 @@ fn main() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ty_fragment_followed_by_expr() {
|
||||
check(
|
||||
r#"
|
||||
macro_rules! a {
|
||||
($t:tt) => {};
|
||||
}
|
||||
|
||||
macro_rules! b {
|
||||
($t:ty) => {
|
||||
a!($t);
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
b!(&'static str);
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
macro_rules! a {
|
||||
($t:tt) => {};
|
||||
}
|
||||
|
||||
macro_rules! b {
|
||||
($t:ty) => {
|
||||
a!($t);
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
a!(&'static str);;
|
||||
}
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_winapi_struct() {
|
||||
// from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/macros.rs#L366
|
||||
|
||||
@ -128,7 +128,10 @@ enum Fragment<'a> {
|
||||
#[default]
|
||||
Empty,
|
||||
/// token fragments are just copy-pasted into the output
|
||||
Tokens(tt::TokenTreesView<'a, Span>),
|
||||
Tokens {
|
||||
tree: tt::TokenTreesView<'a, Span>,
|
||||
origin: TokensOrigin,
|
||||
},
|
||||
/// Expr ast fragments are surrounded with `()` on transcription to preserve precedence.
|
||||
/// Note that this impl is different from the one currently in `rustc` --
|
||||
/// `rustc` doesn't translate fragments into token trees at all.
|
||||
@ -156,10 +159,16 @@ impl Fragment<'_> {
|
||||
fn is_empty(&self) -> bool {
|
||||
match self {
|
||||
Fragment::Empty => true,
|
||||
Fragment::Tokens(it) => it.len() == 0,
|
||||
Fragment::Tokens { tree, .. } => tree.len() == 0,
|
||||
Fragment::Expr(it) => it.len() == 0,
|
||||
Fragment::Path(it) => it.len() == 0,
|
||||
Fragment::TokensOwned(it) => it.0.is_empty(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum TokensOrigin {
|
||||
Raw,
|
||||
Ast,
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ use tt::{
|
||||
|
||||
use crate::{
|
||||
ExpandError, ExpandErrorKind, MetaTemplate, ValueResult,
|
||||
expander::{Binding, Bindings, ExpandResult, Fragment},
|
||||
expander::{Binding, Bindings, ExpandResult, Fragment, TokensOrigin},
|
||||
expect_fragment,
|
||||
parser::{ExprKind, MetaVarKind, Op, RepeatKind, Separator},
|
||||
};
|
||||
@ -842,18 +842,23 @@ fn match_meta_var<'t>(
|
||||
}
|
||||
.err();
|
||||
let tt_result = input.from_savepoint(savepoint);
|
||||
return ValueResult { value: Fragment::Tokens(tt_result), err };
|
||||
return ValueResult {
|
||||
value: Fragment::Tokens { tree: tt_result, origin: TokensOrigin::Raw },
|
||||
err,
|
||||
};
|
||||
}
|
||||
MetaVarKind::Ty => parser::PrefixEntryPoint::Ty,
|
||||
MetaVarKind::Pat => parser::PrefixEntryPoint::PatTop,
|
||||
MetaVarKind::PatParam => parser::PrefixEntryPoint::Pat,
|
||||
MetaVarKind::Stmt => parser::PrefixEntryPoint::Stmt,
|
||||
MetaVarKind::Block => parser::PrefixEntryPoint::Block,
|
||||
MetaVarKind::Meta => parser::PrefixEntryPoint::MetaItem,
|
||||
MetaVarKind::Item => parser::PrefixEntryPoint::Item,
|
||||
MetaVarKind::Vis => parser::PrefixEntryPoint::Vis,
|
||||
MetaVarKind::Ty => (parser::PrefixEntryPoint::Ty, TokensOrigin::Ast),
|
||||
MetaVarKind::Pat => (parser::PrefixEntryPoint::PatTop, TokensOrigin::Ast),
|
||||
MetaVarKind::PatParam => (parser::PrefixEntryPoint::Pat, TokensOrigin::Ast),
|
||||
MetaVarKind::Stmt => (parser::PrefixEntryPoint::Stmt, TokensOrigin::Ast),
|
||||
MetaVarKind::Block => (parser::PrefixEntryPoint::Block, TokensOrigin::Ast),
|
||||
MetaVarKind::Meta => (parser::PrefixEntryPoint::MetaItem, TokensOrigin::Ast),
|
||||
MetaVarKind::Item => (parser::PrefixEntryPoint::Item, TokensOrigin::Ast),
|
||||
MetaVarKind::Vis => (parser::PrefixEntryPoint::Vis, TokensOrigin::Ast),
|
||||
};
|
||||
expect_fragment(db, input, fragment, delim_span).map(Fragment::Tokens)
|
||||
let (entry_point, origin) = fragment;
|
||||
expect_fragment(db, input, entry_point, delim_span)
|
||||
.map(|tree| Fragment::Tokens { tree, origin })
|
||||
}
|
||||
|
||||
fn collect_vars(collector_fun: &mut impl FnMut(Symbol), pattern: &MetaTemplate) {
|
||||
|
||||
@ -5,6 +5,7 @@ use intern::{Symbol, sym};
|
||||
use span::{Edition, Span};
|
||||
use tt::{Delimiter, TopSubtreeBuilder, iter::TtElement};
|
||||
|
||||
use super::TokensOrigin;
|
||||
use crate::{
|
||||
ExpandError, ExpandErrorKind, ExpandResult, MetaTemplate,
|
||||
expander::{Binding, Bindings, Fragment},
|
||||
@ -313,7 +314,7 @@ fn expand_subtree(
|
||||
}
|
||||
};
|
||||
let values = match &var_value {
|
||||
Fragment::Tokens(tokens) => {
|
||||
Fragment::Tokens { tree: tokens, .. } => {
|
||||
let mut iter = tokens.iter();
|
||||
(iter.next(), iter.next())
|
||||
}
|
||||
@ -393,7 +394,13 @@ fn expand_var(
|
||||
// rustc spacing is not like ours. Ours is like proc macros', it dictates how puncts will actually be joined.
|
||||
// rustc uses them mostly for pretty printing. So we have to deviate a bit from what rustc does here.
|
||||
// Basically, a metavariable can never be joined with whatever after it.
|
||||
Fragment::Tokens(tt) => builder.extend_with_tt_alone(tt.strip_invisible()),
|
||||
Fragment::Tokens { tree, origin } => {
|
||||
let view = match origin {
|
||||
TokensOrigin::Raw => tree.strip_invisible(),
|
||||
TokensOrigin::Ast => tree,
|
||||
};
|
||||
builder.extend_with_tt_alone(view);
|
||||
}
|
||||
Fragment::TokensOwned(tt) => {
|
||||
builder.extend_with_tt_alone(tt.view().strip_invisible())
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user