Skip to content

Commit 1ab8c7f

Browse files
committed
Auto merge of #16349 - Young-Flash:use_error_recovery, r=Veykril
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 rust-lang/rust-analyzer#16227
2 parents 2dfa9b8 + 1c61326 commit 1ab8c7f

File tree

5 files changed

+112
-38
lines changed

5 files changed

+112
-38
lines changed

crates/ide-completion/src/tests/use_tree.rs

+27
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,33 @@ fn check(ra_fixture: &str, expect: Expect) {
88
expect.assert_eq(&actual)
99
}
1010

11+
#[test]
12+
fn use_tree_completion() {
13+
check(
14+
r#"
15+
struct implThing;
16+
17+
use crate::{impl$0};
18+
"#,
19+
expect![[r#"
20+
st implThing implThing
21+
kw self
22+
"#]],
23+
);
24+
25+
check(
26+
r#"
27+
struct implThing;
28+
29+
use crate::{impl$0;
30+
"#,
31+
expect![[r#"
32+
st implThing implThing
33+
kw self
34+
"#]],
35+
);
36+
}
37+
1138
#[test]
1239
fn use_tree_start() {
1340
cov_mark::check!(unqualified_path_selected_only);

crates/parser/src/grammar/items/use_item.rs

+18-10
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub(super) fn use_(p: &mut Parser<'_>, m: Marker) {
1111

1212
// test use_tree
1313
// use outer::tree::{inner::tree};
14-
fn use_tree(p: &mut Parser<'_>, top_level: bool) {
14+
fn use_tree(p: &mut Parser<'_>, top_level: bool) -> bool {
1515
let m = p.start();
1616
match p.current() {
1717
// test use_tree_star
@@ -70,24 +70,32 @@ fn use_tree(p: &mut Parser<'_>, top_level: bool) {
7070
// main balanced `{}`
7171
p.err_and_bump(msg);
7272
}
73-
return;
73+
return false;
7474
}
7575
}
7676
m.complete(p, USE_TREE);
77+
true
7778
}
7879

80+
pub(super) const USE_TREE_LIST_RECOVERY_SET: TokenSet =
81+
TokenSet::new(&[T![;], T![,], T![.], T![ident]]).union(ITEM_RECOVERY_SET);
82+
83+
pub(super) const USE_TREE_LIST_FIRST_SET: TokenSet = TokenSet::new(&[T!['{'], T![ident]]);
84+
7985
// test use_tree_list
8086
// use {a, b, c};
8187
pub(crate) fn use_tree_list(p: &mut Parser<'_>) {
8288
assert!(p.at(T!['{']));
8389
let m = p.start();
84-
p.bump(T!['{']);
85-
while !p.at(EOF) && !p.at(T!['}']) {
86-
use_tree(p, false);
87-
if !p.at(T!['}']) {
88-
p.expect(T![,]);
89-
}
90-
}
91-
p.expect(T!['}']);
90+
91+
// test_err use_tree_list_err_recovery
92+
// use {a;
93+
// use b;
94+
// struct T;
95+
// fn test() {}
96+
delimited(p, T!['{'], T!['}'], T![,], USE_TREE_LIST_FIRST_SET, |p: &mut Parser<'_>| {
97+
use_tree(p, false) || p.at_ts(USE_TREE_LIST_RECOVERY_SET)
98+
});
99+
92100
m.complete(p, USE_TREE_LIST);
93101
}

crates/parser/test_data/parser/err/0036_partial_use.rast

+17-28
Original file line numberDiff line numberDiff line change
@@ -20,32 +20,21 @@ SOURCE_FILE
2020
PATH_SEGMENT
2121
NAME_REF
2222
IDENT "Error"
23-
ERROR
24-
SEMICOLON ";"
25-
WHITESPACE "\n"
26-
ERROR
27-
USE_KW "use"
28-
WHITESPACE " "
29-
USE_TREE
30-
PATH
31-
PATH
32-
PATH_SEGMENT
33-
NAME_REF
34-
IDENT "std"
35-
COLON2 "::"
36-
PATH_SEGMENT
37-
NAME_REF
38-
IDENT "io"
39-
ERROR
40-
SEMICOLON ";"
23+
SEMICOLON ";"
24+
WHITESPACE "\n"
25+
USE
26+
USE_KW "use"
27+
WHITESPACE " "
28+
USE_TREE
29+
PATH
30+
PATH
31+
PATH_SEGMENT
32+
NAME_REF
33+
IDENT "std"
34+
COLON2 "::"
35+
PATH_SEGMENT
36+
NAME_REF
37+
IDENT "io"
38+
SEMICOLON ";"
4139
WHITESPACE "\n"
42-
error 22: expected COMMA
43-
error 22: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
44-
error 23: expected COMMA
45-
error 24: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
46-
error 27: expected COMMA
47-
error 35: expected COMMA
48-
error 35: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
49-
error 36: expected COMMA
50-
error 36: expected R_CURLY
51-
error 36: expected SEMICOLON
40+
error 22: expected R_CURLY
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
SOURCE_FILE
2+
USE
3+
USE_KW "use"
4+
WHITESPACE " "
5+
USE_TREE
6+
USE_TREE_LIST
7+
L_CURLY "{"
8+
USE_TREE
9+
PATH
10+
PATH_SEGMENT
11+
NAME_REF
12+
IDENT "a"
13+
SEMICOLON ";"
14+
WHITESPACE "\n"
15+
USE
16+
USE_KW "use"
17+
WHITESPACE " "
18+
USE_TREE
19+
PATH
20+
PATH_SEGMENT
21+
NAME_REF
22+
IDENT "b"
23+
SEMICOLON ";"
24+
WHITESPACE "\n"
25+
STRUCT
26+
STRUCT_KW "struct"
27+
WHITESPACE " "
28+
NAME
29+
IDENT "T"
30+
SEMICOLON ";"
31+
WHITESPACE "\n"
32+
FN
33+
FN_KW "fn"
34+
WHITESPACE " "
35+
NAME
36+
IDENT "test"
37+
PARAM_LIST
38+
L_PAREN "("
39+
R_PAREN ")"
40+
WHITESPACE " "
41+
BLOCK_EXPR
42+
STMT_LIST
43+
L_CURLY "{"
44+
R_CURLY "}"
45+
WHITESPACE "\n"
46+
error 6: expected R_CURLY
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
use {a;
2+
use b;
3+
struct T;
4+
fn test() {}

0 commit comments

Comments
 (0)