diff --git a/crates/ide-completion/src/tests/use_tree.rs b/crates/ide-completion/src/tests/use_tree.rs index 167bdec546d..f8b76571ca0 100644 --- a/crates/ide-completion/src/tests/use_tree.rs +++ b/crates/ide-completion/src/tests/use_tree.rs @@ -8,6 +8,33 @@ fn check(ra_fixture: &str, expect: Expect) { expect.assert_eq(&actual) } +#[test] +fn use_tree_completion() { + check( + r#" +struct implThing; + +use crate::{impl$0}; +"#, + expect![[r#" + st implThing implThing + kw self + "#]], + ); + + check( + r#" +struct implThing; + +use crate::{impl$0; +"#, + expect![[r#" + st implThing implThing + kw self + "#]], + ); +} + #[test] fn use_tree_start() { cov_mark::check!(unqualified_path_selected_only); diff --git a/crates/parser/src/grammar/items/use_item.rs b/crates/parser/src/grammar/items/use_item.rs index 69880b7946b..f689c06b31c 100644 --- a/crates/parser/src/grammar/items/use_item.rs +++ b/crates/parser/src/grammar/items/use_item.rs @@ -11,7 +11,7 @@ pub(super) fn use_(p: &mut Parser<'_>, m: Marker) { // test use_tree // use outer::tree::{inner::tree}; -fn use_tree(p: &mut Parser<'_>, top_level: bool) { +fn use_tree(p: &mut Parser<'_>, top_level: bool) -> bool { let m = p.start(); match p.current() { // test use_tree_star @@ -70,24 +70,32 @@ fn use_tree(p: &mut Parser<'_>, top_level: bool) { // main balanced `{}` p.err_and_bump(msg); } - return; + return false; } } m.complete(p, USE_TREE); + true } +pub(super) const USE_TREE_LIST_RECOVERY_SET: TokenSet = + TokenSet::new(&[T![;], T![,], T![.], T![ident]]).union(ITEM_RECOVERY_SET); + +pub(super) const USE_TREE_LIST_FIRST_SET: TokenSet = TokenSet::new(&[T!['{'], T![ident]]); + // test use_tree_list // use {a, b, c}; pub(crate) fn use_tree_list(p: &mut Parser<'_>) { assert!(p.at(T!['{'])); let m = p.start(); - p.bump(T!['{']); - while !p.at(EOF) && !p.at(T!['}']) { - use_tree(p, false); - if !p.at(T!['}']) { - p.expect(T![,]); - } - } - p.expect(T!['}']); + + // test_err use_tree_list_err_recovery + // use {a; + // use b; + // struct T; + // fn test() {} + delimited(p, T!['{'], T!['}'], T![,], USE_TREE_LIST_FIRST_SET, |p: &mut Parser<'_>| { + use_tree(p, false) || p.at_ts(USE_TREE_LIST_RECOVERY_SET) + }); + m.complete(p, USE_TREE_LIST); } diff --git a/crates/parser/test_data/parser/err/0036_partial_use.rast b/crates/parser/test_data/parser/err/0036_partial_use.rast index 13e76e68307..e27c9417939 100644 --- a/crates/parser/test_data/parser/err/0036_partial_use.rast +++ b/crates/parser/test_data/parser/err/0036_partial_use.rast @@ -20,32 +20,21 @@ SOURCE_FILE PATH_SEGMENT NAME_REF IDENT "Error" - ERROR - SEMICOLON ";" - WHITESPACE "\n" - ERROR - USE_KW "use" - WHITESPACE " " - USE_TREE - PATH - PATH - PATH_SEGMENT - NAME_REF - IDENT "std" - COLON2 "::" - PATH_SEGMENT - NAME_REF - IDENT "io" - ERROR - SEMICOLON ";" + SEMICOLON ";" WHITESPACE "\n" -error 22: expected COMMA -error 22: expected one of `*`, `::`, `{`, `self`, `super` or an identifier -error 23: expected COMMA -error 24: expected one of `*`, `::`, `{`, `self`, `super` or an identifier -error 27: expected COMMA -error 35: expected COMMA -error 35: expected one of `*`, `::`, `{`, `self`, `super` or an identifier -error 36: expected COMMA -error 36: expected R_CURLY -error 36: expected SEMICOLON + USE + USE_KW "use" + WHITESPACE " " + USE_TREE + PATH + PATH + PATH_SEGMENT + NAME_REF + IDENT "std" + COLON2 "::" + PATH_SEGMENT + NAME_REF + IDENT "io" + SEMICOLON ";" + WHITESPACE "\n" +error 22: expected R_CURLY diff --git a/crates/parser/test_data/parser/inline/err/0026_use_tree_list_err_recovery.rast b/crates/parser/test_data/parser/inline/err/0026_use_tree_list_err_recovery.rast new file mode 100644 index 00000000000..cb90b093ba0 --- /dev/null +++ b/crates/parser/test_data/parser/inline/err/0026_use_tree_list_err_recovery.rast @@ -0,0 +1,46 @@ +SOURCE_FILE + USE + USE_KW "use" + WHITESPACE " " + USE_TREE + USE_TREE_LIST + L_CURLY "{" + USE_TREE + PATH + PATH_SEGMENT + NAME_REF + IDENT "a" + SEMICOLON ";" + WHITESPACE "\n" + USE + USE_KW "use" + WHITESPACE " " + USE_TREE + PATH + PATH_SEGMENT + NAME_REF + IDENT "b" + SEMICOLON ";" + WHITESPACE "\n" + STRUCT + STRUCT_KW "struct" + WHITESPACE " " + NAME + IDENT "T" + SEMICOLON ";" + WHITESPACE "\n" + FN + FN_KW "fn" + WHITESPACE " " + NAME + IDENT "test" + PARAM_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + R_CURLY "}" + WHITESPACE "\n" +error 6: expected R_CURLY diff --git a/crates/parser/test_data/parser/inline/err/0026_use_tree_list_err_recovery.rs b/crates/parser/test_data/parser/inline/err/0026_use_tree_list_err_recovery.rs new file mode 100644 index 00000000000..f16959c25f2 --- /dev/null +++ b/crates/parser/test_data/parser/inline/err/0026_use_tree_list_err_recovery.rs @@ -0,0 +1,4 @@ +use {a; +use b; +struct T; +fn test() {}