mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 21:43:37 +00:00
Wrap macros in expr position in MacroExpr
node
This commit is contained in:
parent
5a6918f1c4
commit
872b7b9660
31 changed files with 642 additions and 548 deletions
|
@ -110,8 +110,8 @@ impl SourceAnalyzer {
|
||||||
|
|
||||||
fn expr_id(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<ExprId> {
|
fn expr_id(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<ExprId> {
|
||||||
let src = match expr {
|
let src = match expr {
|
||||||
ast::Expr::MacroCall(call) => {
|
ast::Expr::MacroExpr(expr) => {
|
||||||
self.expand_expr(db, InFile::new(self.file_id, call.clone()))?
|
self.expand_expr(db, InFile::new(self.file_id, expr.macro_call()?.clone()))?
|
||||||
}
|
}
|
||||||
_ => InFile::new(self.file_id, expr.clone()),
|
_ => InFile::new(self.file_id, expr.clone()),
|
||||||
};
|
};
|
||||||
|
|
|
@ -506,7 +506,8 @@ impl ExprCollector<'_> {
|
||||||
None => self.alloc_expr(Expr::Missing, syntax_ptr),
|
None => self.alloc_expr(Expr::Missing, syntax_ptr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::Expr::MacroCall(e) => {
|
ast::Expr::MacroExpr(e) => {
|
||||||
|
let e = e.macro_call()?;
|
||||||
let macro_ptr = AstPtr::new(&e);
|
let macro_ptr = AstPtr::new(&e);
|
||||||
let id = self.collect_macro_call(e, macro_ptr.clone(), true, |this, expansion| {
|
let id = self.collect_macro_call(e, macro_ptr.clone(), true, |this, expansion| {
|
||||||
expansion.map(|it| this.collect_expr(it))
|
expansion.map(|it| this.collect_expr(it))
|
||||||
|
@ -629,7 +630,11 @@ impl ExprCollector<'_> {
|
||||||
}
|
}
|
||||||
let has_semi = stmt.semicolon_token().is_some();
|
let has_semi = stmt.semicolon_token().is_some();
|
||||||
// Note that macro could be expended to multiple statements
|
// Note that macro could be expended to multiple statements
|
||||||
if let Some(ast::Expr::MacroCall(m)) = stmt.expr() {
|
if let Some(ast::Expr::MacroExpr(e)) = stmt.expr() {
|
||||||
|
let m = match e.macro_call() {
|
||||||
|
Some(it) => it,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
let macro_ptr = AstPtr::new(&m);
|
let macro_ptr = AstPtr::new(&m);
|
||||||
let syntax_ptr = AstPtr::new(&stmt.expr().unwrap());
|
let syntax_ptr = AstPtr::new(&stmt.expr().unwrap());
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,34 @@ fn main() { n_nuple!(1,2,3); }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_3642_bad_macro_stackover() {
|
||||||
|
lower(
|
||||||
|
r#"
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! match_ast {
|
||||||
|
(match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) };
|
||||||
|
|
||||||
|
(match ($node:expr) {
|
||||||
|
$( ast::$ast:ident($it:ident) => $res:expr, )*
|
||||||
|
_ => $catch_all:expr $(,)?
|
||||||
|
}) => {{
|
||||||
|
$( if let Some($it) = ast::$ast::cast($node.clone()) { $res } else )*
|
||||||
|
{ $catch_all }
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let anchor = match_ast! {
|
||||||
|
match parent {
|
||||||
|
as => {},
|
||||||
|
_ => return None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn macro_resolve() {
|
fn macro_resolve() {
|
||||||
// Regression test for a path resolution bug introduced with inner item handling.
|
// Regression test for a path resolution bug introduced with inner item handling.
|
||||||
|
|
|
@ -371,3 +371,27 @@ fn outer() {
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn stmt_macro_expansion_with_trailing_expr() {
|
||||||
|
cov_mark::check!(macro_stmt_with_trailing_macro_expr);
|
||||||
|
check_at(
|
||||||
|
r#"
|
||||||
|
macro_rules! mac {
|
||||||
|
() => { mac!($) };
|
||||||
|
($x:tt) => { fn inner() {} };
|
||||||
|
}
|
||||||
|
fn foo() {
|
||||||
|
mac!();
|
||||||
|
$0
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
block scope
|
||||||
|
inner: v
|
||||||
|
|
||||||
|
crate
|
||||||
|
foo: v
|
||||||
|
"#]],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -48,22 +48,33 @@ impl<'a> Ctx<'a> {
|
||||||
pub(super) fn lower_macro_stmts(mut self, stmts: ast::MacroStmts) -> ItemTree {
|
pub(super) fn lower_macro_stmts(mut self, stmts: ast::MacroStmts) -> ItemTree {
|
||||||
self.tree.top_level = stmts
|
self.tree.top_level = stmts
|
||||||
.statements()
|
.statements()
|
||||||
.filter_map(|stmt| match stmt {
|
.filter_map(|stmt| {
|
||||||
|
match stmt {
|
||||||
ast::Stmt::Item(item) => Some(item),
|
ast::Stmt::Item(item) => Some(item),
|
||||||
// Macro calls can be both items and expressions. The syntax library always treats
|
// Macro calls can be both items and expressions. The syntax library always treats
|
||||||
// them as expressions here, so we undo that.
|
// them as expressions here, so we undo that.
|
||||||
ast::Stmt::ExprStmt(es) => match es.expr()? {
|
ast::Stmt::ExprStmt(es) => match es.expr()? {
|
||||||
ast::Expr::MacroCall(call) => {
|
ast::Expr::MacroExpr(expr) => {
|
||||||
cov_mark::hit!(macro_call_in_macro_stmts_is_added_to_item_tree);
|
cov_mark::hit!(macro_call_in_macro_stmts_is_added_to_item_tree);
|
||||||
Some(call.into())
|
Some(expr.macro_call()?.into())
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.flat_map(|item| self.lower_mod_item(&item))
|
.flat_map(|item| self.lower_mod_item(&item))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
if let Some(ast::Expr::MacroExpr(tail_macro)) = stmts.expr() {
|
||||||
|
if let Some(call) = tail_macro.macro_call() {
|
||||||
|
cov_mark::hit!(macro_stmt_with_trailing_macro_expr);
|
||||||
|
if let Some(mod_item) = self.lower_mod_item(&call.into()) {
|
||||||
|
self.tree.top_level.push(mod_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.tree
|
self.tree
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +86,7 @@ impl<'a> Ctx<'a> {
|
||||||
// Macro calls can be both items and expressions. The syntax library always treats
|
// Macro calls can be both items and expressions. The syntax library always treats
|
||||||
// them as expressions here, so we undo that.
|
// them as expressions here, so we undo that.
|
||||||
ast::Stmt::ExprStmt(es) => match es.expr()? {
|
ast::Stmt::ExprStmt(es) => match es.expr()? {
|
||||||
ast::Expr::MacroCall(call) => self.lower_mod_item(&call.into()),
|
ast::Expr::MacroExpr(expr) => self.lower_mod_item(&expr.macro_call()?.into()),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
|
@ -249,8 +249,7 @@ macro_rules! format_args {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _ =
|
let _ =
|
||||||
// +errors
|
format_args!/*+errors*/("{} {:?}", a.);
|
||||||
format_args!("{} {:?}", a.);
|
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
expect![[r##"
|
expect![[r##"
|
||||||
|
|
|
@ -530,8 +530,7 @@ macro_rules! m {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn f() -> i32 {
|
fn f() -> i32 {
|
||||||
// +tree
|
m!/*+tree*/{}
|
||||||
m!{}
|
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
|
|
|
@ -885,6 +885,16 @@ impl ExpandTo {
|
||||||
None => return ExpandTo::Statements,
|
None => return ExpandTo::Statements,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// FIXME: macros in statement position are treated as expression statements, they should
|
||||||
|
// probably be their own statement kind. The *grand*parent indicates what's valid.
|
||||||
|
if parent.kind() == MACRO_EXPR
|
||||||
|
&& parent
|
||||||
|
.parent()
|
||||||
|
.map_or(true, |p| matches!(p.kind(), EXPR_STMT | STMT_LIST | MACRO_STMTS))
|
||||||
|
{
|
||||||
|
return ExpandTo::Statements;
|
||||||
|
}
|
||||||
|
|
||||||
match parent.kind() {
|
match parent.kind() {
|
||||||
MACRO_ITEMS | SOURCE_FILE | ITEM_LIST => ExpandTo::Items,
|
MACRO_ITEMS | SOURCE_FILE | ITEM_LIST => ExpandTo::Items,
|
||||||
MACRO_STMTS | EXPR_STMT | STMT_LIST => ExpandTo::Statements,
|
MACRO_STMTS | EXPR_STMT | STMT_LIST => ExpandTo::Statements,
|
||||||
|
@ -895,26 +905,13 @@ impl ExpandTo {
|
||||||
| CLOSURE_EXPR | FIELD_EXPR | FOR_EXPR | IF_EXPR | INDEX_EXPR | LET_EXPR
|
| CLOSURE_EXPR | FIELD_EXPR | FOR_EXPR | IF_EXPR | INDEX_EXPR | LET_EXPR
|
||||||
| MATCH_ARM | MATCH_EXPR | MATCH_GUARD | METHOD_CALL_EXPR | PAREN_EXPR | PATH_EXPR
|
| MATCH_ARM | MATCH_EXPR | MATCH_GUARD | METHOD_CALL_EXPR | PAREN_EXPR | PATH_EXPR
|
||||||
| PREFIX_EXPR | RANGE_EXPR | RECORD_EXPR_FIELD | REF_EXPR | RETURN_EXPR | TRY_EXPR
|
| PREFIX_EXPR | RANGE_EXPR | RECORD_EXPR_FIELD | REF_EXPR | RETURN_EXPR | TRY_EXPR
|
||||||
| TUPLE_EXPR | WHILE_EXPR => ExpandTo::Expr,
|
| TUPLE_EXPR | WHILE_EXPR | MACRO_EXPR => ExpandTo::Expr,
|
||||||
_ => {
|
_ => {
|
||||||
match ast::LetStmt::cast(parent) {
|
|
||||||
Some(let_stmt) => {
|
|
||||||
if let Some(true) = let_stmt.initializer().map(|it| it.syntax() == syn) {
|
|
||||||
ExpandTo::Expr
|
|
||||||
} else if let Some(true) = let_stmt.ty().map(|it| it.syntax() == syn) {
|
|
||||||
ExpandTo::Type
|
|
||||||
} else {
|
|
||||||
ExpandTo::Pattern
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
// Unknown , Just guess it is `Items`
|
// Unknown , Just guess it is `Items`
|
||||||
ExpandTo::Items
|
ExpandTo::Items
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -444,34 +444,6 @@ fn test() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn issue_3642_bad_macro_stackover() {
|
|
||||||
check_no_mismatches(
|
|
||||||
r#"
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! match_ast {
|
|
||||||
(match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) };
|
|
||||||
|
|
||||||
(match ($node:expr) {
|
|
||||||
$( ast::$ast:ident($it:ident) => $res:expr, )*
|
|
||||||
_ => $catch_all:expr $(,)?
|
|
||||||
}) => {{
|
|
||||||
$( if let Some($it) = ast::$ast::cast($node.clone()) { $res } else )*
|
|
||||||
{ $catch_all }
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let anchor = match_ast! {
|
|
||||||
match parent {
|
|
||||||
as => {},
|
|
||||||
_ => return None
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}"#,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn issue_3999_slice() {
|
fn issue_3999_slice() {
|
||||||
check_infer(
|
check_infer(
|
||||||
|
|
|
@ -156,7 +156,7 @@ fn highlight_exit_points(
|
||||||
highlights.push(HighlightedRange { category: None, range: token.text_range() });
|
highlights.push(HighlightedRange { category: None, range: token.text_range() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::Expr::MethodCallExpr(_) | ast::Expr::CallExpr(_) | ast::Expr::MacroCall(_) => {
|
ast::Expr::MethodCallExpr(_) | ast::Expr::CallExpr(_) | ast::Expr::MacroExpr(_) => {
|
||||||
if sema.type_of_expr(&expr).map_or(false, |ty| ty.original.is_never()) {
|
if sema.type_of_expr(&expr).map_or(false, |ty| ty.original.is_never()) {
|
||||||
highlights.push(HighlightedRange {
|
highlights.push(HighlightedRange {
|
||||||
category: None,
|
category: None,
|
||||||
|
|
|
@ -163,6 +163,7 @@ fn test() {
|
||||||
L_CURLY@10..11 "{"
|
L_CURLY@10..11 "{"
|
||||||
WHITESPACE@11..16 "\n "
|
WHITESPACE@11..16 "\n "
|
||||||
EXPR_STMT@16..58
|
EXPR_STMT@16..58
|
||||||
|
MACRO_EXPR@16..57
|
||||||
MACRO_CALL@16..57
|
MACRO_CALL@16..57
|
||||||
PATH@16..22
|
PATH@16..22
|
||||||
PATH_SEGMENT@16..22
|
PATH_SEGMENT@16..22
|
||||||
|
@ -214,6 +215,7 @@ fn test() {
|
||||||
}"#,
|
}"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
EXPR_STMT@16..58
|
EXPR_STMT@16..58
|
||||||
|
MACRO_EXPR@16..57
|
||||||
MACRO_CALL@16..57
|
MACRO_CALL@16..57
|
||||||
PATH@16..22
|
PATH@16..22
|
||||||
PATH_SEGMENT@16..22
|
PATH_SEGMENT@16..22
|
||||||
|
|
|
@ -601,6 +601,17 @@ sdasdasdasdasd
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn noop_in_item_position_with_macro() {
|
||||||
|
type_char_noop('{', r#"$0println!();"#);
|
||||||
|
type_char_noop(
|
||||||
|
'{',
|
||||||
|
r#"
|
||||||
|
fn main() $0println!("hello");
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn adds_closing_brace_for_use_tree() {
|
fn adds_closing_brace_for_use_tree() {
|
||||||
type_char(
|
type_char(
|
||||||
|
|
|
@ -111,7 +111,7 @@ pub(crate) fn convert_if_to_bool_then(acc: &mut Assists, ctx: &AssistContext) ->
|
||||||
| ast::Expr::ForExpr(_)
|
| ast::Expr::ForExpr(_)
|
||||||
| ast::Expr::IfExpr(_)
|
| ast::Expr::IfExpr(_)
|
||||||
| ast::Expr::LoopExpr(_)
|
| ast::Expr::LoopExpr(_)
|
||||||
| ast::Expr::MacroCall(_)
|
| ast::Expr::MacroExpr(_)
|
||||||
| ast::Expr::MatchExpr(_)
|
| ast::Expr::MatchExpr(_)
|
||||||
| ast::Expr::PrefixExpr(_)
|
| ast::Expr::PrefixExpr(_)
|
||||||
| ast::Expr::RangeExpr(_)
|
| ast::Expr::RangeExpr(_)
|
||||||
|
|
|
@ -649,8 +649,8 @@ impl FunctionBody {
|
||||||
ast::Expr::PathExpr(path_expr) => {
|
ast::Expr::PathExpr(path_expr) => {
|
||||||
cb(path_expr.path().and_then(|it| it.as_single_name_ref()))
|
cb(path_expr.path().and_then(|it| it.as_single_name_ref()))
|
||||||
}
|
}
|
||||||
ast::Expr::MacroCall(call) => {
|
ast::Expr::MacroExpr(expr) => {
|
||||||
if let Some(tt) = call.token_tree() {
|
if let Some(tt) = expr.macro_call().and_then(|call| call.token_tree()) {
|
||||||
tt.syntax()
|
tt.syntax()
|
||||||
.children_with_tokens()
|
.children_with_tokens()
|
||||||
.flat_map(SyntaxElement::into_token)
|
.flat_map(SyntaxElement::into_token)
|
||||||
|
@ -923,7 +923,7 @@ fn reference_is_exclusive(
|
||||||
|
|
||||||
/// checks if this expr requires `&mut` access, recurses on field access
|
/// checks if this expr requires `&mut` access, recurses on field access
|
||||||
fn expr_require_exclusive_access(ctx: &AssistContext, expr: &ast::Expr) -> Option<bool> {
|
fn expr_require_exclusive_access(ctx: &AssistContext, expr: &ast::Expr) -> Option<bool> {
|
||||||
if let ast::Expr::MacroCall(_) = expr {
|
if let ast::Expr::MacroExpr(_) = expr {
|
||||||
// FIXME: expand macro and check output for mutable usages of the variable?
|
// FIXME: expand macro and check output for mutable usages of the variable?
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -1015,7 +1015,7 @@ fn path_element_of_reference(
|
||||||
None
|
None
|
||||||
})?;
|
})?;
|
||||||
stdx::always!(
|
stdx::always!(
|
||||||
matches!(path, ast::Expr::PathExpr(_) | ast::Expr::MacroCall(_)),
|
matches!(path, ast::Expr::PathExpr(_) | ast::Expr::MacroExpr(_)),
|
||||||
"unexpected expression type for variable usage: {:?}",
|
"unexpected expression type for variable usage: {:?}",
|
||||||
path
|
path
|
||||||
);
|
);
|
||||||
|
|
|
@ -39,15 +39,16 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
||||||
.map(|mut tokens| syntax::hacks::parse_expr_from_str(&tokens.join("")))
|
.map(|mut tokens| syntax::hacks::parse_expr_from_str(&tokens.join("")))
|
||||||
.collect::<Option<Vec<ast::Expr>>>()?;
|
.collect::<Option<Vec<ast::Expr>>>()?;
|
||||||
|
|
||||||
let parent = macro_call.syntax().parent()?;
|
let macro_expr = ast::MacroExpr::cast(macro_call.syntax().parent()?)?;
|
||||||
|
let parent = macro_expr.syntax().parent()?;
|
||||||
let (range, text) = match &*input_expressions {
|
let (range, text) = match &*input_expressions {
|
||||||
// dbg!()
|
// dbg!()
|
||||||
[] => {
|
[] => {
|
||||||
match_ast! {
|
match_ast! {
|
||||||
match parent {
|
match parent {
|
||||||
ast::StmtList(__) => {
|
ast::StmtList(__) => {
|
||||||
let range = macro_call.syntax().text_range();
|
let range = macro_expr.syntax().text_range();
|
||||||
let range = match whitespace_start(macro_call.syntax().prev_sibling_or_token()) {
|
let range = match whitespace_start(macro_expr.syntax().prev_sibling_or_token()) {
|
||||||
Some(start) => range.cover_offset(start),
|
Some(start) => range.cover_offset(start),
|
||||||
None => range,
|
None => range,
|
||||||
};
|
};
|
||||||
|
|
|
@ -62,11 +62,6 @@ pub fn preorder_expr(start: &ast::Expr, cb: &mut dyn FnMut(WalkEvent<ast::Expr>)
|
||||||
match ast::Stmt::cast(node.clone()) {
|
match ast::Stmt::cast(node.clone()) {
|
||||||
// Don't skip subtree since we want to process the expression child next
|
// Don't skip subtree since we want to process the expression child next
|
||||||
Some(ast::Stmt::ExprStmt(_)) | Some(ast::Stmt::LetStmt(_)) => (),
|
Some(ast::Stmt::ExprStmt(_)) | Some(ast::Stmt::LetStmt(_)) => (),
|
||||||
// This might be an expression
|
|
||||||
Some(ast::Stmt::Item(ast::Item::MacroCall(mcall))) => {
|
|
||||||
cb(WalkEvent::Enter(ast::Expr::MacroCall(mcall)));
|
|
||||||
preorder.skip_subtree();
|
|
||||||
}
|
|
||||||
// skip inner items which might have their own expressions
|
// skip inner items which might have their own expressions
|
||||||
Some(ast::Stmt::Item(_)) => preorder.skip_subtree(),
|
Some(ast::Stmt::Item(_)) => preorder.skip_subtree(),
|
||||||
None => {
|
None => {
|
||||||
|
@ -319,7 +314,7 @@ pub fn for_each_tail_expr(expr: &ast::Expr, cb: &mut dyn FnMut(&ast::Expr)) {
|
||||||
| ast::Expr::ForExpr(_)
|
| ast::Expr::ForExpr(_)
|
||||||
| ast::Expr::IndexExpr(_)
|
| ast::Expr::IndexExpr(_)
|
||||||
| ast::Expr::Literal(_)
|
| ast::Expr::Literal(_)
|
||||||
| ast::Expr::MacroCall(_)
|
| ast::Expr::MacroExpr(_)
|
||||||
| ast::Expr::MacroStmts(_)
|
| ast::Expr::MacroStmts(_)
|
||||||
| ast::Expr::MethodCallExpr(_)
|
| ast::Expr::MethodCallExpr(_)
|
||||||
| ast::Expr::ParenExpr(_)
|
| ast::Expr::ParenExpr(_)
|
||||||
|
|
|
@ -552,7 +552,7 @@ fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) {
|
||||||
}
|
}
|
||||||
T![!] if !p.at(T![!=]) => {
|
T![!] if !p.at(T![!=]) => {
|
||||||
let block_like = items::macro_call_after_excl(p);
|
let block_like = items::macro_call_after_excl(p);
|
||||||
(m.complete(p, MACRO_CALL), block_like)
|
(m.complete(p, MACRO_CALL).precede(p).complete(p, MACRO_EXPR), block_like)
|
||||||
}
|
}
|
||||||
_ => (m.complete(p, PATH_EXPR), BlockLike::NotBlock),
|
_ => (m.complete(p, PATH_EXPR), BlockLike::NotBlock),
|
||||||
}
|
}
|
||||||
|
|
|
@ -605,6 +605,7 @@ fn try_block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
|
||||||
if p.nth_at(1, T![!]) {
|
if p.nth_at(1, T![!]) {
|
||||||
// test try_macro_fallback
|
// test try_macro_fallback
|
||||||
// fn foo() { try!(Ok(())); }
|
// fn foo() { try!(Ok(())); }
|
||||||
|
let macro_call = p.start();
|
||||||
let path = p.start();
|
let path = p.start();
|
||||||
let path_segment = p.start();
|
let path_segment = p.start();
|
||||||
let name_ref = p.start();
|
let name_ref = p.start();
|
||||||
|
@ -613,7 +614,8 @@ fn try_block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
|
||||||
path_segment.complete(p, PATH_SEGMENT);
|
path_segment.complete(p, PATH_SEGMENT);
|
||||||
path.complete(p, PATH);
|
path.complete(p, PATH);
|
||||||
let _block_like = items::macro_call_after_excl(p);
|
let _block_like = items::macro_call_after_excl(p);
|
||||||
return m.complete(p, MACRO_CALL);
|
macro_call.complete(p, MACRO_CALL);
|
||||||
|
return m.complete(p, MACRO_EXPR);
|
||||||
}
|
}
|
||||||
|
|
||||||
p.bump(T![try]);
|
p.bump(T![try]);
|
||||||
|
|
|
@ -190,6 +190,7 @@ pub enum SyntaxKind {
|
||||||
YIELD_EXPR,
|
YIELD_EXPR,
|
||||||
LET_EXPR,
|
LET_EXPR,
|
||||||
UNDERSCORE_EXPR,
|
UNDERSCORE_EXPR,
|
||||||
|
MACRO_EXPR,
|
||||||
MATCH_EXPR,
|
MATCH_EXPR,
|
||||||
MATCH_ARM_LIST,
|
MATCH_ARM_LIST,
|
||||||
MATCH_ARM,
|
MATCH_ARM,
|
||||||
|
|
|
@ -104,6 +104,7 @@ SOURCE_FILE
|
||||||
IDENT "entries"
|
IDENT "entries"
|
||||||
COLON ":"
|
COLON ":"
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
|
MACRO_EXPR
|
||||||
MACRO_CALL
|
MACRO_CALL
|
||||||
PATH
|
PATH
|
||||||
PATH_SEGMENT
|
PATH_SEGMENT
|
||||||
|
|
|
@ -12,6 +12,7 @@ SOURCE_FILE
|
||||||
STMT_LIST
|
STMT_LIST
|
||||||
L_CURLY "{"
|
L_CURLY "{"
|
||||||
WHITESPACE "\n "
|
WHITESPACE "\n "
|
||||||
|
MACRO_EXPR
|
||||||
MACRO_CALL
|
MACRO_CALL
|
||||||
PATH
|
PATH
|
||||||
PATH_SEGMENT
|
PATH_SEGMENT
|
||||||
|
|
|
@ -81,6 +81,7 @@ SOURCE_FILE
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
EQ "="
|
EQ "="
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
|
MACRO_EXPR
|
||||||
MACRO_CALL
|
MACRO_CALL
|
||||||
PATH
|
PATH
|
||||||
PATH_SEGMENT
|
PATH_SEGMENT
|
||||||
|
|
|
@ -110,6 +110,7 @@ SOURCE_FILE
|
||||||
WHITESPACE "\n "
|
WHITESPACE "\n "
|
||||||
R_CURLY "}"
|
R_CURLY "}"
|
||||||
WHITESPACE "\n "
|
WHITESPACE "\n "
|
||||||
|
MACRO_EXPR
|
||||||
MACRO_CALL
|
MACRO_CALL
|
||||||
PATH
|
PATH
|
||||||
PATH_SEGMENT
|
PATH_SEGMENT
|
||||||
|
|
|
@ -35,7 +35,7 @@ SOURCE_FILE
|
||||||
SEMICOLON ";"
|
SEMICOLON ";"
|
||||||
WHITESPACE "\n "
|
WHITESPACE "\n "
|
||||||
EXPR_STMT
|
EXPR_STMT
|
||||||
MACRO_CALL
|
MACRO_EXPR
|
||||||
ATTR
|
ATTR
|
||||||
POUND "#"
|
POUND "#"
|
||||||
L_BRACK "["
|
L_BRACK "["
|
||||||
|
@ -46,6 +46,7 @@ SOURCE_FILE
|
||||||
IDENT "B"
|
IDENT "B"
|
||||||
R_BRACK "]"
|
R_BRACK "]"
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
|
MACRO_CALL
|
||||||
PATH
|
PATH
|
||||||
PATH_SEGMENT
|
PATH_SEGMENT
|
||||||
NAME_REF
|
NAME_REF
|
||||||
|
|
|
@ -13,6 +13,7 @@ SOURCE_FILE
|
||||||
L_CURLY "{"
|
L_CURLY "{"
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
EXPR_STMT
|
EXPR_STMT
|
||||||
|
MACRO_EXPR
|
||||||
MACRO_CALL
|
MACRO_CALL
|
||||||
PATH
|
PATH
|
||||||
PATH_SEGMENT
|
PATH_SEGMENT
|
||||||
|
|
|
@ -396,6 +396,7 @@ SOURCE_FILE
|
||||||
SEMICOLON ";"
|
SEMICOLON ";"
|
||||||
WHITESPACE "\n "
|
WHITESPACE "\n "
|
||||||
EXPR_STMT
|
EXPR_STMT
|
||||||
|
MACRO_EXPR
|
||||||
MACRO_CALL
|
MACRO_CALL
|
||||||
PATH
|
PATH
|
||||||
PATH_SEGMENT
|
PATH_SEGMENT
|
||||||
|
@ -887,6 +888,7 @@ SOURCE_FILE
|
||||||
PAREN_EXPR
|
PAREN_EXPR
|
||||||
L_PAREN "("
|
L_PAREN "("
|
||||||
BIN_EXPR
|
BIN_EXPR
|
||||||
|
MACRO_EXPR
|
||||||
MACRO_CALL
|
MACRO_CALL
|
||||||
PATH
|
PATH
|
||||||
PATH_SEGMENT
|
PATH_SEGMENT
|
||||||
|
@ -905,6 +907,7 @@ SOURCE_FILE
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
PAREN_EXPR
|
PAREN_EXPR
|
||||||
L_PAREN "("
|
L_PAREN "("
|
||||||
|
MACRO_EXPR
|
||||||
MACRO_CALL
|
MACRO_CALL
|
||||||
PATH
|
PATH
|
||||||
PATH_SEGMENT
|
PATH_SEGMENT
|
||||||
|
@ -934,6 +937,7 @@ SOURCE_FILE
|
||||||
PAREN_EXPR
|
PAREN_EXPR
|
||||||
L_PAREN "("
|
L_PAREN "("
|
||||||
BIN_EXPR
|
BIN_EXPR
|
||||||
|
MACRO_EXPR
|
||||||
MACRO_CALL
|
MACRO_CALL
|
||||||
PATH
|
PATH
|
||||||
PATH_SEGMENT
|
PATH_SEGMENT
|
||||||
|
@ -978,6 +982,7 @@ SOURCE_FILE
|
||||||
PAREN_EXPR
|
PAREN_EXPR
|
||||||
L_PAREN "("
|
L_PAREN "("
|
||||||
BIN_EXPR
|
BIN_EXPR
|
||||||
|
MACRO_EXPR
|
||||||
MACRO_CALL
|
MACRO_CALL
|
||||||
PATH
|
PATH
|
||||||
PATH_SEGMENT
|
PATH_SEGMENT
|
||||||
|
@ -1130,6 +1135,7 @@ SOURCE_FILE
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
FAT_ARROW "=>"
|
FAT_ARROW "=>"
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
|
MACRO_EXPR
|
||||||
MACRO_CALL
|
MACRO_CALL
|
||||||
PATH
|
PATH
|
||||||
PATH_SEGMENT
|
PATH_SEGMENT
|
||||||
|
@ -1176,6 +1182,7 @@ SOURCE_FILE
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
EQ "="
|
EQ "="
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
|
MACRO_EXPR
|
||||||
MACRO_CALL
|
MACRO_CALL
|
||||||
PATH
|
PATH
|
||||||
PATH_SEGMENT
|
PATH_SEGMENT
|
||||||
|
@ -1204,6 +1211,7 @@ SOURCE_FILE
|
||||||
L_CURLY "{"
|
L_CURLY "{"
|
||||||
WHITESPACE "\n "
|
WHITESPACE "\n "
|
||||||
EXPR_STMT
|
EXPR_STMT
|
||||||
|
MACRO_EXPR
|
||||||
MACRO_CALL
|
MACRO_CALL
|
||||||
PATH
|
PATH
|
||||||
PATH_SEGMENT
|
PATH_SEGMENT
|
||||||
|
@ -1353,6 +1361,7 @@ SOURCE_FILE
|
||||||
L_CURLY "{"
|
L_CURLY "{"
|
||||||
WHITESPACE "\n "
|
WHITESPACE "\n "
|
||||||
EXPR_STMT
|
EXPR_STMT
|
||||||
|
MACRO_EXPR
|
||||||
MACRO_CALL
|
MACRO_CALL
|
||||||
PATH
|
PATH
|
||||||
PATH_SEGMENT
|
PATH_SEGMENT
|
||||||
|
@ -1508,6 +1517,7 @@ SOURCE_FILE
|
||||||
L_CURLY "{"
|
L_CURLY "{"
|
||||||
WHITESPACE "\n "
|
WHITESPACE "\n "
|
||||||
EXPR_STMT
|
EXPR_STMT
|
||||||
|
MACRO_EXPR
|
||||||
MACRO_CALL
|
MACRO_CALL
|
||||||
PATH
|
PATH
|
||||||
PATH_SEGMENT
|
PATH_SEGMENT
|
||||||
|
@ -1741,6 +1751,7 @@ SOURCE_FILE
|
||||||
SEMICOLON ";"
|
SEMICOLON ";"
|
||||||
WHITESPACE "\n "
|
WHITESPACE "\n "
|
||||||
EXPR_STMT
|
EXPR_STMT
|
||||||
|
MACRO_EXPR
|
||||||
MACRO_CALL
|
MACRO_CALL
|
||||||
PATH
|
PATH
|
||||||
PATH_SEGMENT
|
PATH_SEGMENT
|
||||||
|
|
|
@ -42,6 +42,7 @@ SOURCE_FILE
|
||||||
STMT_LIST
|
STMT_LIST
|
||||||
L_CURLY "{"
|
L_CURLY "{"
|
||||||
WHITESPACE "\n "
|
WHITESPACE "\n "
|
||||||
|
MACRO_EXPR
|
||||||
MACRO_CALL
|
MACRO_CALL
|
||||||
PATH
|
PATH
|
||||||
PATH_SEGMENT
|
PATH_SEGMENT
|
||||||
|
|
|
@ -38,6 +38,7 @@ SOURCE_FILE
|
||||||
IDENT "B"
|
IDENT "B"
|
||||||
R_BRACK "]"
|
R_BRACK "]"
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
|
MACRO_EXPR
|
||||||
MACRO_CALL
|
MACRO_CALL
|
||||||
PATH
|
PATH
|
||||||
PATH_SEGMENT
|
PATH_SEGMENT
|
||||||
|
|
|
@ -342,7 +342,7 @@ Expr =
|
||||||
| IndexExpr
|
| IndexExpr
|
||||||
| Literal
|
| Literal
|
||||||
| LoopExpr
|
| LoopExpr
|
||||||
| MacroCall
|
| MacroExpr
|
||||||
| MacroStmts
|
| MacroStmts
|
||||||
| MatchExpr
|
| MatchExpr
|
||||||
| MethodCallExpr
|
| MethodCallExpr
|
||||||
|
@ -360,6 +360,9 @@ Expr =
|
||||||
| LetExpr
|
| LetExpr
|
||||||
| UnderscoreExpr
|
| UnderscoreExpr
|
||||||
|
|
||||||
|
MacroExpr =
|
||||||
|
MacroCall
|
||||||
|
|
||||||
Literal =
|
Literal =
|
||||||
Attr* value:(
|
Attr* value:(
|
||||||
'int_number' | 'float_number'
|
'int_number' | 'float_number'
|
||||||
|
|
|
@ -918,6 +918,14 @@ impl LoopExpr {
|
||||||
pub fn loop_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![loop]) }
|
pub fn loop_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![loop]) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct MacroExpr {
|
||||||
|
pub(crate) syntax: SyntaxNode,
|
||||||
|
}
|
||||||
|
impl MacroExpr {
|
||||||
|
pub fn macro_call(&self) -> Option<MacroCall> { support::child(&self.syntax) }
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct MatchExpr {
|
pub struct MatchExpr {
|
||||||
pub(crate) syntax: SyntaxNode,
|
pub(crate) syntax: SyntaxNode,
|
||||||
|
@ -1518,7 +1526,7 @@ pub enum Expr {
|
||||||
IndexExpr(IndexExpr),
|
IndexExpr(IndexExpr),
|
||||||
Literal(Literal),
|
Literal(Literal),
|
||||||
LoopExpr(LoopExpr),
|
LoopExpr(LoopExpr),
|
||||||
MacroCall(MacroCall),
|
MacroExpr(MacroExpr),
|
||||||
MacroStmts(MacroStmts),
|
MacroStmts(MacroStmts),
|
||||||
MatchExpr(MatchExpr),
|
MatchExpr(MatchExpr),
|
||||||
MethodCallExpr(MethodCallExpr),
|
MethodCallExpr(MethodCallExpr),
|
||||||
|
@ -2532,6 +2540,17 @@ impl AstNode for LoopExpr {
|
||||||
}
|
}
|
||||||
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||||
}
|
}
|
||||||
|
impl AstNode for MacroExpr {
|
||||||
|
fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_EXPR }
|
||||||
|
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||||
|
if Self::can_cast(syntax.kind()) {
|
||||||
|
Some(Self { syntax })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||||
|
}
|
||||||
impl AstNode for MatchExpr {
|
impl AstNode for MatchExpr {
|
||||||
fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_EXPR }
|
fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_EXPR }
|
||||||
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||||
|
@ -3313,8 +3332,8 @@ impl From<Literal> for Expr {
|
||||||
impl From<LoopExpr> for Expr {
|
impl From<LoopExpr> for Expr {
|
||||||
fn from(node: LoopExpr) -> Expr { Expr::LoopExpr(node) }
|
fn from(node: LoopExpr) -> Expr { Expr::LoopExpr(node) }
|
||||||
}
|
}
|
||||||
impl From<MacroCall> for Expr {
|
impl From<MacroExpr> for Expr {
|
||||||
fn from(node: MacroCall) -> Expr { Expr::MacroCall(node) }
|
fn from(node: MacroExpr) -> Expr { Expr::MacroExpr(node) }
|
||||||
}
|
}
|
||||||
impl From<MacroStmts> for Expr {
|
impl From<MacroStmts> for Expr {
|
||||||
fn from(node: MacroStmts) -> Expr { Expr::MacroStmts(node) }
|
fn from(node: MacroStmts) -> Expr { Expr::MacroStmts(node) }
|
||||||
|
@ -3369,7 +3388,7 @@ impl AstNode for Expr {
|
||||||
match kind {
|
match kind {
|
||||||
ARRAY_EXPR | AWAIT_EXPR | BIN_EXPR | BLOCK_EXPR | BOX_EXPR | BREAK_EXPR | CALL_EXPR
|
ARRAY_EXPR | AWAIT_EXPR | BIN_EXPR | BLOCK_EXPR | BOX_EXPR | BREAK_EXPR | CALL_EXPR
|
||||||
| CAST_EXPR | CLOSURE_EXPR | CONTINUE_EXPR | FIELD_EXPR | FOR_EXPR | IF_EXPR
|
| CAST_EXPR | CLOSURE_EXPR | CONTINUE_EXPR | FIELD_EXPR | FOR_EXPR | IF_EXPR
|
||||||
| INDEX_EXPR | LITERAL | LOOP_EXPR | MACRO_CALL | MACRO_STMTS | MATCH_EXPR
|
| INDEX_EXPR | LITERAL | LOOP_EXPR | MACRO_EXPR | MACRO_STMTS | MATCH_EXPR
|
||||||
| METHOD_CALL_EXPR | PAREN_EXPR | PATH_EXPR | PREFIX_EXPR | RANGE_EXPR
|
| METHOD_CALL_EXPR | PAREN_EXPR | PATH_EXPR | PREFIX_EXPR | RANGE_EXPR
|
||||||
| RECORD_EXPR | REF_EXPR | RETURN_EXPR | TRY_EXPR | TUPLE_EXPR | WHILE_EXPR
|
| RECORD_EXPR | REF_EXPR | RETURN_EXPR | TRY_EXPR | TUPLE_EXPR | WHILE_EXPR
|
||||||
| YIELD_EXPR | LET_EXPR | UNDERSCORE_EXPR => true,
|
| YIELD_EXPR | LET_EXPR | UNDERSCORE_EXPR => true,
|
||||||
|
@ -3394,7 +3413,7 @@ impl AstNode for Expr {
|
||||||
INDEX_EXPR => Expr::IndexExpr(IndexExpr { syntax }),
|
INDEX_EXPR => Expr::IndexExpr(IndexExpr { syntax }),
|
||||||
LITERAL => Expr::Literal(Literal { syntax }),
|
LITERAL => Expr::Literal(Literal { syntax }),
|
||||||
LOOP_EXPR => Expr::LoopExpr(LoopExpr { syntax }),
|
LOOP_EXPR => Expr::LoopExpr(LoopExpr { syntax }),
|
||||||
MACRO_CALL => Expr::MacroCall(MacroCall { syntax }),
|
MACRO_EXPR => Expr::MacroExpr(MacroExpr { syntax }),
|
||||||
MACRO_STMTS => Expr::MacroStmts(MacroStmts { syntax }),
|
MACRO_STMTS => Expr::MacroStmts(MacroStmts { syntax }),
|
||||||
MATCH_EXPR => Expr::MatchExpr(MatchExpr { syntax }),
|
MATCH_EXPR => Expr::MatchExpr(MatchExpr { syntax }),
|
||||||
METHOD_CALL_EXPR => Expr::MethodCallExpr(MethodCallExpr { syntax }),
|
METHOD_CALL_EXPR => Expr::MethodCallExpr(MethodCallExpr { syntax }),
|
||||||
|
@ -3433,7 +3452,7 @@ impl AstNode for Expr {
|
||||||
Expr::IndexExpr(it) => &it.syntax,
|
Expr::IndexExpr(it) => &it.syntax,
|
||||||
Expr::Literal(it) => &it.syntax,
|
Expr::Literal(it) => &it.syntax,
|
||||||
Expr::LoopExpr(it) => &it.syntax,
|
Expr::LoopExpr(it) => &it.syntax,
|
||||||
Expr::MacroCall(it) => &it.syntax,
|
Expr::MacroExpr(it) => &it.syntax,
|
||||||
Expr::MacroStmts(it) => &it.syntax,
|
Expr::MacroStmts(it) => &it.syntax,
|
||||||
Expr::MatchExpr(it) => &it.syntax,
|
Expr::MatchExpr(it) => &it.syntax,
|
||||||
Expr::MethodCallExpr(it) => &it.syntax,
|
Expr::MethodCallExpr(it) => &it.syntax,
|
||||||
|
@ -4506,6 +4525,11 @@ impl std::fmt::Display for LoopExpr {
|
||||||
std::fmt::Display::fmt(self.syntax(), f)
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl std::fmt::Display for MacroExpr {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
|
}
|
||||||
|
}
|
||||||
impl std::fmt::Display for MatchExpr {
|
impl std::fmt::Display for MatchExpr {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
std::fmt::Display::fmt(self.syntax(), f)
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
|
|
|
@ -144,6 +144,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
|
||||||
"YIELD_EXPR",
|
"YIELD_EXPR",
|
||||||
"LET_EXPR",
|
"LET_EXPR",
|
||||||
"UNDERSCORE_EXPR",
|
"UNDERSCORE_EXPR",
|
||||||
|
"MACRO_EXPR",
|
||||||
"MATCH_EXPR",
|
"MATCH_EXPR",
|
||||||
"MATCH_ARM_LIST",
|
"MATCH_ARM_LIST",
|
||||||
"MATCH_ARM",
|
"MATCH_ARM",
|
||||||
|
|
Loading…
Reference in a new issue