diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs index 9f282c74d31..53bb26c5ff6 100644 --- a/crates/ra_parser/src/grammar/expressions/atom.rs +++ b/crates/ra_parser/src/grammar/expressions/atom.rs @@ -93,6 +93,11 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar } } + ASYNC_KW if la == L_CURLY => { + let m = p.start(); + p.bump(); + block_expr(p, Some(m)) + } MATCH_KW => match_expr(p), UNSAFE_KW if la == L_CURLY => { let m = p.start(); diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs index ab9d2de9064..a057c816756 100644 --- a/crates/ra_parser/src/grammar/items.rs +++ b/crates/ra_parser/src/grammar/items.rs @@ -86,9 +86,15 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem { } let mut has_mods = false; - // modifiers - has_mods |= p.eat(CONST_KW); + // modifiers + // test_err async_without_semicolon + // fn foo() { let _ = async {} } + has_mods |= p.eat(CONST_KW); + if p.at(ASYNC_KW) && p.nth(1) != L_CURLY { + p.eat(ASYNC_KW); + has_mods = true; + } // test_err unsafe_block_in_mod // fn foo(){} unsafe { } fn bar(){} if p.at(UNSAFE_KW) && p.nth(1) != L_CURLY { @@ -110,6 +116,9 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem { // items let kind = match p.current() { + // test async_fn + // async fn foo() {} + // test extern_fn // extern fn foo() {} diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs index 0eed44ecfde..03247ae38cd 100644 --- a/crates/ra_parser/src/syntax_kind/generated.rs +++ b/crates/ra_parser/src/syntax_kind/generated.rs @@ -66,6 +66,7 @@ pub enum SyntaxKind { SHR, SHLEQ, SHREQ, + ASYNC_KW, USE_KW, FN_KW, STRUCT_KW, @@ -233,6 +234,7 @@ use self::SyntaxKind::*; impl SyntaxKind { pub fn is_keyword(self) -> bool { match self { + | ASYNC_KW | USE_KW | FN_KW | STRUCT_KW @@ -403,6 +405,7 @@ impl SyntaxKind { SHR => &SyntaxInfo { name: "SHR" }, SHLEQ => &SyntaxInfo { name: "SHLEQ" }, SHREQ => &SyntaxInfo { name: "SHREQ" }, + ASYNC_KW => &SyntaxInfo { name: "ASYNC_KW" }, USE_KW => &SyntaxInfo { name: "USE_KW" }, FN_KW => &SyntaxInfo { name: "FN_KW" }, STRUCT_KW => &SyntaxInfo { name: "STRUCT_KW" }, @@ -570,6 +573,7 @@ impl SyntaxKind { } pub fn from_keyword(ident: &str) -> Option { let kw = match ident { + "async" => ASYNC_KW, "use" => USE_KW, "fn" => FN_KW, "struct" => STRUCT_KW, diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index b7a2d1c01b3..66f1339c109 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron @@ -59,6 +59,7 @@ Grammar( [">>=", "SHREQ"], ], keywords: [ + "async", "use", "fn", "struct", diff --git a/crates/ra_syntax/tests/data/lexer/0011_keywords.rs b/crates/ra_syntax/tests/data/lexer/0011_keywords.rs index e6bf64d4d61..1e91bff4e7d 100644 --- a/crates/ra_syntax/tests/data/lexer/0011_keywords.rs +++ b/crates/ra_syntax/tests/data/lexer/0011_keywords.rs @@ -1,3 +1,3 @@ -fn use struct trait enum impl true false as extern crate +async fn use struct trait enum impl true false as extern crate mod pub self super in where for loop while if match const static mut type ref let else move return diff --git a/crates/ra_syntax/tests/data/lexer/0011_keywords.txt b/crates/ra_syntax/tests/data/lexer/0011_keywords.txt index d6a1abe8ac6..22c00eefb62 100644 --- a/crates/ra_syntax/tests/data/lexer/0011_keywords.txt +++ b/crates/ra_syntax/tests/data/lexer/0011_keywords.txt @@ -1,3 +1,5 @@ +ASYNC_KW 5 "async" +WHITESPACE 1 " " FN_KW 2 "fn" WHITESPACE 1 " " USE_KW 3 "use" diff --git a/crates/ra_syntax/tests/data/parser/inline/err/0007_async_without_semicolon.rs b/crates/ra_syntax/tests/data/parser/inline/err/0007_async_without_semicolon.rs new file mode 100644 index 00000000000..9a423248c27 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/err/0007_async_without_semicolon.rs @@ -0,0 +1 @@ +fn foo() { let _ = async {} } diff --git a/crates/ra_syntax/tests/data/parser/inline/err/0007_async_without_semicolon.txt b/crates/ra_syntax/tests/data/parser/inline/err/0007_async_without_semicolon.txt new file mode 100644 index 00000000000..bb9a2d0295d --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/err/0007_async_without_semicolon.txt @@ -0,0 +1,31 @@ +SOURCE_FILE@[0; 30) + FN_DEF@[0; 29) + FN_KW@[0; 2) + WHITESPACE@[2; 3) + NAME@[3; 6) + IDENT@[3; 6) "foo" + PARAM_LIST@[6; 8) + L_PAREN@[6; 7) + R_PAREN@[7; 8) + WHITESPACE@[8; 9) + BLOCK@[9; 29) + L_CURLY@[9; 10) + WHITESPACE@[10; 11) + LET_STMT@[11; 27) + LET_KW@[11; 14) + WHITESPACE@[14; 15) + PLACEHOLDER_PAT@[15; 16) + UNDERSCORE@[15; 16) + WHITESPACE@[16; 17) + EQ@[17; 18) + WHITESPACE@[18; 19) + BLOCK_EXPR@[19; 27) + ASYNC_KW@[19; 24) + WHITESPACE@[24; 25) + BLOCK@[25; 27) + L_CURLY@[25; 26) + R_CURLY@[26; 27) + err: `expected SEMI` + WHITESPACE@[27; 28) + R_CURLY@[28; 29) + WHITESPACE@[29; 30) diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0124_async_fn.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0124_async_fn.rs new file mode 100644 index 00000000000..f4adcb62b3b --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0124_async_fn.rs @@ -0,0 +1 @@ +async fn foo() {} diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0124_async_fn.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0124_async_fn.txt new file mode 100644 index 00000000000..d1a706ecc35 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0124_async_fn.txt @@ -0,0 +1,16 @@ +SOURCE_FILE@[0; 18) + FN_DEF@[0; 17) + ASYNC_KW@[0; 5) + WHITESPACE@[5; 6) + FN_KW@[6; 8) + WHITESPACE@[8; 9) + NAME@[9; 12) + IDENT@[9; 12) "foo" + PARAM_LIST@[12; 14) + L_PAREN@[12; 13) + R_PAREN@[13; 14) + WHITESPACE@[14; 15) + BLOCK@[15; 17) + L_CURLY@[15; 16) + R_CURLY@[16; 17) + WHITESPACE@[17; 18)