diff --git a/Cargo.lock b/Cargo.lock index 3f2ee2c57271..9cc5a73c9669 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1833,9 +1833,9 @@ checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae" [[package]] name = "ungrammar" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed01567101450f7d600508e7680df6005ae4fe97119d79b0364cc5910ff39732" +checksum = "a62374cbbda72c1459ce5e7bfcdf1bd284c812a4faf2324aa083e5d9ea87880f" [[package]] name = "unicase" diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index a2b57cb5bdf0..f86f4f3c85b0 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs @@ -525,6 +525,7 @@ impl ExprCollector<'_> { self.alloc_expr(Expr::MacroStmts { tail }, syntax_ptr) } + ast::Expr::UnderscoreExpr(_) => return None, }) } diff --git a/crates/ide_assists/src/handlers/extract_module.rs b/crates/ide_assists/src/handlers/extract_module.rs index 64875adfae23..880617dd38d2 100644 --- a/crates/ide_assists/src/handlers/extract_module.rs +++ b/crates/ide_assists/src/handlers/extract_module.rs @@ -179,7 +179,7 @@ impl Module { //Here impl is not included as each item inside impl will be tied to the parent of //implementing block(a struct, enum, etc), if the parent is in selected module, it will //get updated by ADT section given below or if it is not, then we dont need to do any operation - self.body_items.clone().into_iter().for_each(|item| { + self.body_items.iter().cloned().for_each(|item| { match_ast! { match (item.syntax()) { ast::Adt(it) => { @@ -240,6 +240,11 @@ impl Module { self.expand_and_group_usages_file_wise(ctx, node_def, &mut refs); } }, + ast::Macro(it) => { + if let Some(nod) = ctx.sema.to_def(&it) { + self.expand_and_group_usages_file_wise(ctx, Definition::Macro(nod), &mut refs); + } + }, _ => (), } } @@ -781,7 +786,6 @@ fn get_replacements_for_visibilty_change( ast::Item::Fn(it) => replacements.push((it.visibility(), it.syntax().clone())), //Associated item's visibility should not be changed ast::Item::Impl(it) if it.for_token().is_none() => impls.push(it), - ast::Item::MacroRules(it) => replacements.push((it.visibility(), it.syntax().clone())), ast::Item::MacroDef(it) => replacements.push((it.visibility(), it.syntax().clone())), ast::Item::Module(it) => replacements.push((it.visibility(), it.syntax().clone())), ast::Item::Static(it) => replacements.push((it.visibility(), it.syntax().clone())), @@ -1376,6 +1380,27 @@ mod modname { ) } + #[test] + fn test_extract_module_macro_rules() { + check_assist( + extract_module, + r" +$0macro_rules! m { + () => {}; +}$0 +m! {} + ", + r" +mod modname { + macro_rules! m { + () => {}; + } +} +modname::m! {} + ", + ); + } + #[test] fn test_do_not_apply_visibility_modifier_to_trait_impl_items() { check_assist( diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs index fcad17298483..4a14a7f849b8 100644 --- a/crates/ide_db/src/helpers.rs +++ b/crates/ide_db/src/helpers.rs @@ -187,6 +187,7 @@ pub fn for_each_tail_expr(expr: &ast::Expr, cb: &mut dyn FnMut(&ast::Expr)) { | ast::Expr::TupleExpr(_) | ast::Expr::WhileExpr(_) | ast::Expr::LetExpr(_) + | ast::Expr::UnderscoreExpr(_) | ast::Expr::YieldExpr(_) => cb(expr), } } diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs index 944d3ef87d81..aefb3d059ff3 100644 --- a/crates/mbe/src/expander/matcher.rs +++ b/crates/mbe/src/expander/matcher.rs @@ -690,9 +690,19 @@ fn match_meta_var(kind: &str, input: &mut TtIter) -> ExpandResult parser::PrefixEntryPoint::Item, "vis" => parser::PrefixEntryPoint::Vis, "expr" => { + // `expr` should not match underscores. + // HACK: Macro expansion should not be done using "rollback and try another alternative". + // rustc [explicitly checks the next token][0]. + // [0]: https://github.com/rust-lang/rust/blob/f0c4da499/compiler/rustc_expand/src/mbe/macro_parser.rs#L576 + match input.peek_n(0) { + Some(tt::TokenTree::Leaf(tt::Leaf::Ident(it))) if it.text == "_" => { + return ExpandResult::only_err(ExpandError::NoMatchingRule) + } + _ => {} + }; return input .expect_fragment(parser::PrefixEntryPoint::Expr) - .map(|tt| tt.map(Fragment::Expr)) + .map(|tt| tt.map(Fragment::Expr)); } _ => { let tt_result = match kind { diff --git a/crates/parser/src/grammar/expressions.rs b/crates/parser/src/grammar/expressions.rs index a40db15049de..5d652fb8dc87 100644 --- a/crates/parser/src/grammar/expressions.rs +++ b/crates/parser/src/grammar/expressions.rs @@ -593,7 +593,16 @@ pub(crate) fn record_expr_field_list(p: &mut Parser) { T![.] if p.at(T![..]) => { m.abandon(p); p.bump(T![..]); - expr(p); + + // test destructuring_assignment_struct_rest_pattern + // fn foo() { + // S { .. } = S {}; + // } + + // We permit `.. }` on the left-hand side of a destructuring assignment. + if !p.at(T!['}']) { + expr(p); + } } T!['{'] => { error_block(p, "expected a field"); diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs index e2c1b1fec579..e5f8e8199e1a 100644 --- a/crates/parser/src/grammar/expressions/atom.rs +++ b/crates/parser/src/grammar/expressions/atom.rs @@ -81,6 +81,17 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar T![if] => if_expr(p), T![let] => let_expr(p), + T![_] => { + // test destructuring_assignment_wildcard_pat + // fn foo() { + // _ = 1; + // Some(_) = None; + // } + let m = p.start(); + p.bump(T![_]); + m.complete(p, UNDERSCORE_EXPR) + } + T![loop] => loop_expr(p, None), T![box] => box_expr(p, None), T![for] => for_expr(p, None), diff --git a/crates/parser/src/syntax_kind/generated.rs b/crates/parser/src/syntax_kind/generated.rs index d04b5dbf0087..4e8a0cfe80ae 100644 --- a/crates/parser/src/syntax_kind/generated.rs +++ b/crates/parser/src/syntax_kind/generated.rs @@ -188,6 +188,7 @@ pub enum SyntaxKind { RETURN_EXPR, YIELD_EXPR, LET_EXPR, + UNDERSCORE_EXPR, MATCH_EXPR, MATCH_ARM_LIST, MATCH_ARM, diff --git a/crates/parser/test_data/parser/err/0025_nope.rast b/crates/parser/test_data/parser/err/0025_nope.rast deleted file mode 100644 index b48b4aed8ddf..000000000000 --- a/crates/parser/test_data/parser/err/0025_nope.rast +++ /dev/null @@ -1,204 +0,0 @@ -SOURCE_FILE@0..575 - FN@0..574 - FN_KW@0..2 "fn" - WHITESPACE@2..3 " " - NAME@3..7 - IDENT@3..7 "main" - PARAM_LIST@7..9 - L_PAREN@7..8 "(" - R_PAREN@8..9 ")" - WHITESPACE@9..10 " " - BLOCK_EXPR@10..574 - STMT_LIST@10..574 - L_CURLY@10..11 "{" - WHITESPACE@11..16 "\n " - ENUM@16..152 - ENUM_KW@16..20 "enum" - WHITESPACE@20..21 " " - NAME@21..25 - IDENT@21..25 "Test" - WHITESPACE@25..26 " " - VARIANT_LIST@26..152 - L_CURLY@26..27 "{" - WHITESPACE@27..36 "\n " - VARIANT@36..40 - NAME@36..40 - IDENT@36..40 "Var1" - COMMA@40..41 "," - WHITESPACE@41..50 "\n " - VARIANT@50..62 - NAME@50..54 - IDENT@50..54 "Var2" - TUPLE_FIELD_LIST@54..62 - L_PAREN@54..55 "(" - TUPLE_FIELD@55..61 - PATH_TYPE@55..61 - PATH@55..61 - PATH_SEGMENT@55..61 - NAME_REF@55..61 - IDENT@55..61 "String" - R_PAREN@61..62 ")" - COMMA@62..63 "," - WHITESPACE@63..72 "\n " - VARIANT@72..145 - NAME@72..76 - IDENT@72..76 "Var3" - WHITESPACE@76..77 " " - RECORD_FIELD_LIST@77..145 - L_CURLY@77..78 "{" - WHITESPACE@78..91 "\n " - RECORD_FIELD@91..95 - NAME@91..94 - IDENT@91..94 "abc" - COLON@94..95 ":" - WHITESPACE@95..96 " " - ERROR@96..98 - L_CURLY@96..97 "{" - R_CURLY@97..98 "}" - ERROR@98..99 - COMMA@98..99 "," - WHITESPACE@99..100 " " - COMMENT@100..135 "//~ ERROR: expected t ..." - WHITESPACE@135..144 "\n " - R_CURLY@144..145 "}" - COMMA@145..146 "," - WHITESPACE@146..151 "\n " - R_CURLY@151..152 "}" - WHITESPACE@152..158 "\n\n " - COMMENT@158..171 "// recover..." - WHITESPACE@171..176 "\n " - LET_STMT@176..186 - LET_KW@176..179 "let" - WHITESPACE@179..180 " " - IDENT_PAT@180..181 - NAME@180..181 - IDENT@180..181 "a" - WHITESPACE@181..182 " " - EQ@182..183 "=" - WHITESPACE@183..184 " " - LITERAL@184..185 - INT_NUMBER@184..185 "1" - SEMICOLON@185..186 ";" - WHITESPACE@186..191 "\n " - ENUM@191..223 - ENUM_KW@191..195 "enum" - WHITESPACE@195..196 " " - NAME@196..201 - IDENT@196..201 "Test2" - WHITESPACE@201..202 " " - VARIANT_LIST@202..223 - L_CURLY@202..203 "{" - WHITESPACE@203..212 "\n " - VARIANT@212..216 - NAME@212..216 - IDENT@212..216 "Fine" - COMMA@216..217 "," - WHITESPACE@217..222 "\n " - R_CURLY@222..223 "}" - WHITESPACE@223..229 "\n\n " - ENUM@229..300 - ENUM_KW@229..233 "enum" - WHITESPACE@233..234 " " - NAME@234..239 - IDENT@234..239 "Test3" - WHITESPACE@239..240 " " - VARIANT_LIST@240..300 - L_CURLY@240..241 "{" - WHITESPACE@241..250 "\n " - VARIANT@250..293 - NAME@250..259 - IDENT@250..259 "StillFine" - WHITESPACE@259..260 " " - RECORD_FIELD_LIST@260..293 - L_CURLY@260..261 "{" - WHITESPACE@261..274 "\n " - RECORD_FIELD@274..282 - NAME@274..277 - IDENT@274..277 "def" - COLON@277..278 ":" - WHITESPACE@278..279 " " - PATH_TYPE@279..282 - PATH@279..282 - PATH_SEGMENT@279..282 - NAME_REF@279..282 - IDENT@279..282 "i32" - COMMA@282..283 "," - WHITESPACE@283..292 "\n " - R_CURLY@292..293 "}" - COMMA@293..294 "," - WHITESPACE@294..299 "\n " - R_CURLY@299..300 "}" - WHITESPACE@300..306 "\n\n " - EXPR_STMT@306..459 - BLOCK_EXPR@306..459 - STMT_LIST@306..459 - L_CURLY@306..307 "{" - WHITESPACE@307..316 "\n " - ENUM@316..453 - COMMENT@316..329 "// fail again" - WHITESPACE@329..338 "\n " - ENUM_KW@338..342 "enum" - WHITESPACE@342..343 " " - NAME@343..348 - IDENT@343..348 "Test4" - WHITESPACE@348..349 " " - VARIANT_LIST@349..453 - L_CURLY@349..350 "{" - WHITESPACE@350..363 "\n " - VARIANT@363..372 - NAME@363..367 - IDENT@363..367 "Nope" - TUPLE_FIELD_LIST@367..372 - L_PAREN@367..368 "(" - TUPLE_FIELD@368..371 - PATH_TYPE@368..371 - PATH@368..371 - PATH_SEGMENT@368..371 - NAME_REF@368..371 - IDENT@368..371 "i32" - WHITESPACE@371..372 " " - ERROR@372..372 - ERROR@372..374 - L_CURLY@372..373 "{" - R_CURLY@373..374 "}" - ERROR@374..375 - R_PAREN@374..375 ")" - WHITESPACE@375..376 " " - COMMENT@376..396 "//~ ERROR: found `{`" - WHITESPACE@396..422 "\n ..." - COMMENT@422..443 "//~^ ERROR: found `{`" - WHITESPACE@443..452 "\n " - R_CURLY@452..453 "}" - WHITESPACE@453..458 "\n " - R_CURLY@458..459 "}" - WHITESPACE@459..464 "\n " - COMMENT@464..486 "// still recover later" - WHITESPACE@486..491 "\n " - LET_STMT@491..510 - LET_KW@491..494 "let" - WHITESPACE@494..495 " " - IDENT_PAT@495..505 - NAME@495..505 - IDENT@495..505 "bad_syntax" - WHITESPACE@505..506 " " - EQ@506..507 "=" - WHITESPACE@507..508 " " - ERROR@508..509 - UNDERSCORE@508..509 "_" - SEMICOLON@509..510 ";" - WHITESPACE@510..511 " " - COMMENT@511..572 "//~ ERROR: expected e ..." - WHITESPACE@572..573 "\n" - R_CURLY@573..574 "}" - WHITESPACE@574..575 "\n" -error 95..95: expected type -error 95..95: expected COMMA -error 96..96: expected field -error 98..98: expected field declaration -error 371..371: expected COMMA -error 372..372: expected a type -error 372..372: expected R_PAREN -error 372..372: expected COMMA -error 372..372: expected enum variant -error 374..374: expected enum variant -error 508..508: expected expression diff --git a/crates/parser/test_data/parser/err/0025_nope.rs b/crates/parser/test_data/parser/err/0025_nope.rs index 28726ed5138d..c78abe80ab7e 100644 --- a/crates/parser/test_data/parser/err/0025_nope.rs +++ b/crates/parser/test_data/parser/err/0025_nope.rs @@ -27,5 +27,6 @@ fn main() { } } // still recover later - let bad_syntax = _; //~ ERROR: expected expression, found reserved identifier `_` + let; //~ ERROR: expected pattern + let _ = 0; } diff --git a/crates/parser/test_data/parser/err/0025_nope.txt b/crates/parser/test_data/parser/err/0025_nope.txt index aca57faf96e5..6b49724ec9aa 100644 --- a/crates/parser/test_data/parser/err/0025_nope.txt +++ b/crates/parser/test_data/parser/err/0025_nope.txt @@ -174,20 +174,24 @@ SOURCE_FILE WHITESPACE "\n " COMMENT "// still recover later" WHITESPACE "\n " + LET_STMT + LET_KW "let" + ERROR + SEMICOLON ";" + WHITESPACE " " + COMMENT "//~ ERROR: expected pattern" + WHITESPACE "\n " LET_STMT LET_KW "let" WHITESPACE " " - IDENT_PAT - NAME - IDENT "bad_syntax" + WILDCARD_PAT + UNDERSCORE "_" WHITESPACE " " EQ "=" WHITESPACE " " - ERROR - UNDERSCORE "_" + LITERAL + INT_NUMBER "0" SEMICOLON ";" - WHITESPACE " " - COMMENT "//~ ERROR: expected expression, found reserved identifier `_`" WHITESPACE "\n" R_CURLY "}" WHITESPACE "\n" @@ -201,4 +205,5 @@ error 372: expected R_PAREN error 372: expected COMMA error 372: expected enum variant error 374: expected enum variant -error 508: expected expression +error 494: expected pattern +error 495: expected SEMICOLON diff --git a/crates/parser/test_data/parser/inline/ok/0197_destructuring_assignment_struct_rest_pattern.rs b/crates/parser/test_data/parser/inline/ok/0197_destructuring_assignment_struct_rest_pattern.rs new file mode 100644 index 000000000000..22a5b5f3e31a --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/0197_destructuring_assignment_struct_rest_pattern.rs @@ -0,0 +1,3 @@ +fn foo() { + S { .. } = S {}; +} diff --git a/crates/parser/test_data/parser/inline/ok/0197_destructuring_assignment_struct_rest_pattern.txt b/crates/parser/test_data/parser/inline/ok/0197_destructuring_assignment_struct_rest_pattern.txt new file mode 100644 index 000000000000..fb8aa5accb5a --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/0197_destructuring_assignment_struct_rest_pattern.txt @@ -0,0 +1,44 @@ +SOURCE_FILE + FN + FN_KW "fn" + WHITESPACE " " + NAME + IDENT "foo" + PARAM_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + EXPR_STMT + BIN_EXPR + RECORD_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "S" + WHITESPACE " " + RECORD_EXPR_FIELD_LIST + L_CURLY "{" + WHITESPACE " " + DOT2 ".." + WHITESPACE " " + R_CURLY "}" + WHITESPACE " " + EQ "=" + WHITESPACE " " + RECORD_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "S" + WHITESPACE " " + RECORD_EXPR_FIELD_LIST + L_CURLY "{" + R_CURLY "}" + SEMICOLON ";" + WHITESPACE "\n" + R_CURLY "}" + WHITESPACE "\n" diff --git a/crates/parser/test_data/parser/inline/ok/0198_destructuring_assignment_wildcard_pat.rs b/crates/parser/test_data/parser/inline/ok/0198_destructuring_assignment_wildcard_pat.rs new file mode 100644 index 000000000000..91acfb3a0aed --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/0198_destructuring_assignment_wildcard_pat.rs @@ -0,0 +1,4 @@ +fn foo() { + _ = 1; + Some(_) = None; +} diff --git a/crates/parser/test_data/parser/inline/ok/0198_destructuring_assignment_wildcard_pat.txt b/crates/parser/test_data/parser/inline/ok/0198_destructuring_assignment_wildcard_pat.txt new file mode 100644 index 000000000000..5f53d34510e7 --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/0198_destructuring_assignment_wildcard_pat.txt @@ -0,0 +1,50 @@ +SOURCE_FILE + FN + FN_KW "fn" + WHITESPACE " " + NAME + IDENT "foo" + PARAM_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + EXPR_STMT + BIN_EXPR + UNDERSCORE_EXPR + UNDERSCORE "_" + WHITESPACE " " + EQ "=" + WHITESPACE " " + LITERAL + INT_NUMBER "1" + SEMICOLON ";" + WHITESPACE "\n " + EXPR_STMT + BIN_EXPR + CALL_EXPR + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "Some" + ARG_LIST + L_PAREN "(" + UNDERSCORE_EXPR + UNDERSCORE "_" + R_PAREN ")" + WHITESPACE " " + EQ "=" + WHITESPACE " " + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "None" + SEMICOLON ";" + WHITESPACE "\n" + R_CURLY "}" + WHITESPACE "\n" diff --git a/crates/parser/test_data/parser/ok/0072_destructuring_assignment.rs b/crates/parser/test_data/parser/ok/0072_destructuring_assignment.rs new file mode 100644 index 000000000000..9d3e86603f88 --- /dev/null +++ b/crates/parser/test_data/parser/ok/0072_destructuring_assignment.rs @@ -0,0 +1,14 @@ +fn foo() { + let (mut a, mut b) = (0, 1); + (b, a, ..) = (a, b); + (_) = ..; + struct S { a: i32 } + S { .. } = S { ..S::default() }; + Some(..) = Some(0). + Ok(_) = 0; + let (a, b); + [a, .., b] = [1, .., 2]; + (_, _) = (a, b); + (_) = (a, b); + _ = (a, b); +} diff --git a/crates/parser/test_data/parser/ok/0072_destructuring_assignment.txt b/crates/parser/test_data/parser/ok/0072_destructuring_assignment.txt new file mode 100644 index 000000000000..e8b836dfbd09 --- /dev/null +++ b/crates/parser/test_data/parser/ok/0072_destructuring_assignment.txt @@ -0,0 +1,352 @@ +SOURCE_FILE + FN + FN_KW "fn" + WHITESPACE " " + NAME + IDENT "foo" + PARAM_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + LET_STMT + LET_KW "let" + WHITESPACE " " + TUPLE_PAT + L_PAREN "(" + IDENT_PAT + MUT_KW "mut" + WHITESPACE " " + NAME + IDENT "a" + COMMA "," + WHITESPACE " " + IDENT_PAT + MUT_KW "mut" + WHITESPACE " " + NAME + IDENT "b" + R_PAREN ")" + WHITESPACE " " + EQ "=" + WHITESPACE " " + TUPLE_EXPR + L_PAREN "(" + LITERAL + INT_NUMBER "0" + COMMA "," + WHITESPACE " " + LITERAL + INT_NUMBER "1" + R_PAREN ")" + SEMICOLON ";" + WHITESPACE "\n " + EXPR_STMT + BIN_EXPR + TUPLE_EXPR + L_PAREN "(" + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "b" + COMMA "," + WHITESPACE " " + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "a" + COMMA "," + WHITESPACE " " + RANGE_EXPR + DOT2 ".." + R_PAREN ")" + WHITESPACE " " + EQ "=" + WHITESPACE " " + TUPLE_EXPR + L_PAREN "(" + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "a" + COMMA "," + WHITESPACE " " + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "b" + R_PAREN ")" + SEMICOLON ";" + WHITESPACE "\n " + EXPR_STMT + BIN_EXPR + PAREN_EXPR + L_PAREN "(" + UNDERSCORE_EXPR + UNDERSCORE "_" + R_PAREN ")" + WHITESPACE " " + EQ "=" + WHITESPACE " " + RANGE_EXPR + DOT2 ".." + SEMICOLON ";" + WHITESPACE "\n " + STRUCT + STRUCT_KW "struct" + WHITESPACE " " + NAME + IDENT "S" + WHITESPACE " " + RECORD_FIELD_LIST + L_CURLY "{" + WHITESPACE " " + RECORD_FIELD + NAME + IDENT "a" + COLON ":" + WHITESPACE " " + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + IDENT "i32" + WHITESPACE " " + R_CURLY "}" + WHITESPACE "\n " + EXPR_STMT + BIN_EXPR + RECORD_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "S" + WHITESPACE " " + RECORD_EXPR_FIELD_LIST + L_CURLY "{" + WHITESPACE " " + DOT2 ".." + WHITESPACE " " + R_CURLY "}" + WHITESPACE " " + EQ "=" + WHITESPACE " " + RECORD_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "S" + WHITESPACE " " + RECORD_EXPR_FIELD_LIST + L_CURLY "{" + WHITESPACE " " + DOT2 ".." + CALL_EXPR + PATH_EXPR + PATH + PATH + PATH_SEGMENT + NAME_REF + IDENT "S" + COLON2 "::" + PATH_SEGMENT + NAME_REF + IDENT "default" + ARG_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + R_CURLY "}" + SEMICOLON ";" + WHITESPACE "\n " + EXPR_STMT + BIN_EXPR + BIN_EXPR + CALL_EXPR + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "Some" + ARG_LIST + L_PAREN "(" + RANGE_EXPR + DOT2 ".." + R_PAREN ")" + WHITESPACE " " + EQ "=" + WHITESPACE " " + METHOD_CALL_EXPR + CALL_EXPR + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "Some" + ARG_LIST + L_PAREN "(" + LITERAL + INT_NUMBER "0" + R_PAREN ")" + DOT "." + WHITESPACE "\n " + NAME_REF + IDENT "Ok" + ARG_LIST + L_PAREN "(" + UNDERSCORE_EXPR + UNDERSCORE "_" + R_PAREN ")" + WHITESPACE " " + EQ "=" + WHITESPACE " " + LITERAL + INT_NUMBER "0" + SEMICOLON ";" + WHITESPACE "\n " + LET_STMT + LET_KW "let" + WHITESPACE " " + TUPLE_PAT + L_PAREN "(" + IDENT_PAT + NAME + IDENT "a" + COMMA "," + WHITESPACE " " + IDENT_PAT + NAME + IDENT "b" + R_PAREN ")" + SEMICOLON ";" + WHITESPACE "\n " + EXPR_STMT + BIN_EXPR + ARRAY_EXPR + L_BRACK "[" + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "a" + COMMA "," + WHITESPACE " " + RANGE_EXPR + DOT2 ".." + COMMA "," + WHITESPACE " " + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "b" + R_BRACK "]" + WHITESPACE " " + EQ "=" + WHITESPACE " " + ARRAY_EXPR + L_BRACK "[" + LITERAL + INT_NUMBER "1" + COMMA "," + WHITESPACE " " + RANGE_EXPR + DOT2 ".." + COMMA "," + WHITESPACE " " + LITERAL + INT_NUMBER "2" + R_BRACK "]" + SEMICOLON ";" + WHITESPACE "\n " + EXPR_STMT + BIN_EXPR + TUPLE_EXPR + L_PAREN "(" + UNDERSCORE_EXPR + UNDERSCORE "_" + COMMA "," + WHITESPACE " " + UNDERSCORE_EXPR + UNDERSCORE "_" + R_PAREN ")" + WHITESPACE " " + EQ "=" + WHITESPACE " " + TUPLE_EXPR + L_PAREN "(" + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "a" + COMMA "," + WHITESPACE " " + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "b" + R_PAREN ")" + SEMICOLON ";" + WHITESPACE "\n " + EXPR_STMT + BIN_EXPR + PAREN_EXPR + L_PAREN "(" + UNDERSCORE_EXPR + UNDERSCORE "_" + R_PAREN ")" + WHITESPACE " " + EQ "=" + WHITESPACE " " + TUPLE_EXPR + L_PAREN "(" + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "a" + COMMA "," + WHITESPACE " " + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "b" + R_PAREN ")" + SEMICOLON ";" + WHITESPACE "\n " + EXPR_STMT + BIN_EXPR + UNDERSCORE_EXPR + UNDERSCORE "_" + WHITESPACE " " + EQ "=" + WHITESPACE " " + TUPLE_EXPR + L_PAREN "(" + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "a" + COMMA "," + WHITESPACE " " + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "b" + R_PAREN ")" + SEMICOLON ";" + WHITESPACE "\n" + R_CURLY "}" + WHITESPACE "\n" diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml index f59cd4f257c5..8baea77075b5 100644 --- a/crates/syntax/Cargo.toml +++ b/crates/syntax/Cargo.toml @@ -30,7 +30,7 @@ rayon = "1" expect-test = "1.2.0-pre.1" proc-macro2 = "1.0.8" quote = "1.0.2" -ungrammar = "=1.15.0" +ungrammar = "=1.16.0" test_utils = { path = "../test_utils" } sourcegen = { path = "../sourcegen" } diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index 11247fbf1c98..fc1ee6f601d2 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs @@ -262,6 +262,7 @@ pub struct ExternBlock { impl ast::HasAttrs for ExternBlock {} impl ast::HasDocComments for ExternBlock {} impl ExternBlock { + pub fn unsafe_token(&self) -> Option { support::token(&self.syntax, T![unsafe]) } pub fn abi(&self) -> Option { support::child(&self.syntax) } pub fn extern_item_list(&self) -> Option { support::child(&self.syntax) } } @@ -1062,6 +1063,15 @@ impl LetExpr { pub fn expr(&self) -> Option { support::child(&self.syntax) } } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct UnderscoreExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::HasAttrs for UnderscoreExpr {} +impl UnderscoreExpr { + pub fn underscore_token(&self) -> Option { support::token(&self.syntax, T![_]) } +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct StmtList { pub(crate) syntax: SyntaxNode, @@ -1522,6 +1532,7 @@ pub enum Expr { WhileExpr(WhileExpr), YieldExpr(YieldExpr), LetExpr(LetExpr), + UnderscoreExpr(UnderscoreExpr), } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -2673,6 +2684,17 @@ impl AstNode for LetExpr { } fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl AstNode for UnderscoreExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == UNDERSCORE_EXPR } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} impl AstNode for StmtList { fn can_cast(kind: SyntaxKind) -> bool { kind == STMT_LIST } fn cast(syntax: SyntaxNode) -> Option { @@ -3337,6 +3359,9 @@ impl From for Expr { impl From for Expr { fn from(node: LetExpr) -> Expr { Expr::LetExpr(node) } } +impl From for Expr { + fn from(node: UnderscoreExpr) -> Expr { Expr::UnderscoreExpr(node) } +} impl AstNode for Expr { fn can_cast(kind: SyntaxKind) -> bool { match kind { @@ -3345,7 +3370,7 @@ impl AstNode for Expr { | INDEX_EXPR | LITERAL | LOOP_EXPR | MACRO_CALL | MACRO_STMTS | MATCH_EXPR | METHOD_CALL_EXPR | PAREN_EXPR | PATH_EXPR | PREFIX_EXPR | RANGE_EXPR | RECORD_EXPR | REF_EXPR | RETURN_EXPR | TRY_EXPR | TUPLE_EXPR | WHILE_EXPR - | YIELD_EXPR | LET_EXPR => true, + | YIELD_EXPR | LET_EXPR | UNDERSCORE_EXPR => true, _ => false, } } @@ -3383,6 +3408,7 @@ impl AstNode for Expr { WHILE_EXPR => Expr::WhileExpr(WhileExpr { syntax }), YIELD_EXPR => Expr::YieldExpr(YieldExpr { syntax }), LET_EXPR => Expr::LetExpr(LetExpr { syntax }), + UNDERSCORE_EXPR => Expr::UnderscoreExpr(UnderscoreExpr { syntax }), _ => return None, }; Some(res) @@ -3421,6 +3447,7 @@ impl AstNode for Expr { Expr::WhileExpr(it) => &it.syntax, Expr::YieldExpr(it) => &it.syntax, Expr::LetExpr(it) => &it.syntax, + Expr::UnderscoreExpr(it) => &it.syntax, } } } @@ -3887,6 +3914,7 @@ impl AstNode for AnyHasAttrs { | WHILE_EXPR | YIELD_EXPR | LET_EXPR + | UNDERSCORE_EXPR | STMT_LIST | RECORD_EXPR_FIELD_LIST | RECORD_EXPR_FIELD @@ -4546,6 +4574,11 @@ impl std::fmt::Display for LetExpr { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for UnderscoreExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for StmtList { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) diff --git a/crates/syntax/src/tests/ast_src.rs b/crates/syntax/src/tests/ast_src.rs index aeff851ce4d2..3152137fb8cc 100644 --- a/crates/syntax/src/tests/ast_src.rs +++ b/crates/syntax/src/tests/ast_src.rs @@ -143,6 +143,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { "RETURN_EXPR", "YIELD_EXPR", "LET_EXPR", + "UNDERSCORE_EXPR", "MATCH_EXPR", "MATCH_ARM_LIST", "MATCH_ARM",