Skip to content

Commit

Permalink
Auto merge of #16349 - Young-Flash:use_error_recovery, r=Veykril
Browse files Browse the repository at this point in the history
fix: add error recovery for use_tree_list parsing

This PR adds error recovery for USE_TREE_LIST parsing, avoid the wrong USE_TREE_LIST making the rest parsing incorrectly.

before

![before](https://github.com/rust-lang/rust-analyzer/assets/71162630/c6643690-f25c-4ad9-93d9-e661ba5b1dc3)

after

![after](https://github.com/rust-lang/rust-analyzer/assets/71162630/30a58c40-2711-48d2-b2e5-fb208fc8636c)

close #16227
  • Loading branch information
bors committed Jan 18, 2024
2 parents 2dfa9b8 + 1c61326 commit 1ab8c7f
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 38 deletions.
27 changes: 27 additions & 0 deletions crates/ide-completion/src/tests/use_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
28 changes: 18 additions & 10 deletions crates/parser/src/grammar/items/use_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
45 changes: 17 additions & 28 deletions crates/parser/test_data/parser/err/0036_partial_use.rast
Original file line number Diff line number Diff line change
Expand Up @@ -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"
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 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
error 22: expected R_CURLY
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
use {a;
use b;
struct T;
fn test() {}

0 comments on commit 1ab8c7f

Please sign in to comment.