10420: Parse outer attributes on StructPatternEtCetera r=jonas-schievink a=XFFXFF

Try to fix https://github.com/rust-analyzer/rust-analyzer/issues/8610  
Related pr in ungrammer: https://github.com/rust-analyzer/ungrammar/pull/41

Co-authored-by: zhoufan <1247714429@qq.com>
This commit is contained in:
bors[bot] 2021-10-06 15:05:40 +00:00 committed by GitHub
commit 94fa49c0a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 101 additions and 37 deletions

View File

@ -818,7 +818,7 @@ impl ExprCollector<'_> {
let ellipsis = p
.record_pat_field_list()
.expect("every struct should have a field list")
.dotdot_token()
.rest_pat()
.is_some();
Pat::Record { path, args, ellipsis }

View File

@ -205,46 +205,64 @@ fn tuple_pat_fields(p: &mut Parser) {
p.expect(T![')']);
}
// test record_pat_field
// fn foo() {
// let S { 0: 1 } = ();
// let S { x: 1 } = ();
// let S { #[cfg(any())] x: 1 } = ();
// }
fn record_pat_field(p: &mut Parser) {
match p.current() {
IDENT | INT_NUMBER if p.nth(1) == T![:] => {
name_ref_or_index(p);
p.bump(T![:]);
pattern(p);
}
T![.] => {
if p.at(T![..]) {
p.bump(T![..]);
} else {
ident_pat(p, false);
}
}
T![box] => {
// FIXME: not all box patterns should be allowed
box_pat(p);
}
_ => {
ident_pat(p, false);
}
}
}
// test record_pat_field_list
// fn foo() {
// let S {} = ();
// let S { f, ref mut g } = ();
// let S { h: _, ..} = ();
// let S { h: _, } = ();
// let S { #[cfg(any())] .. } = ();
// }
fn record_pat_field_list(p: &mut Parser) {
assert!(p.at(T!['{']));
let m = p.start();
p.bump(T!['{']);
while !p.at(EOF) && !p.at(T!['}']) {
let m = p.start();
attributes::outer_attrs(p);
match p.current() {
// A trailing `..` is *not* treated as a REST_PAT.
T![.] if p.at(T![..]) => p.bump(T![..]),
T!['{'] => error_block(p, "expected ident"),
T![.] if p.at(T![..]) => {
p.bump(T![..]);
m.complete(p, REST_PAT);
}
T!['{'] => {
error_block(p, "expected ident");
m.abandon(p);
}
_ => {
let m = p.start();
attributes::outer_attrs(p);
match p.current() {
// test record_pat_field
// fn foo() {
// let S { 0: 1 } = ();
// let S { x: 1 } = ();
// let S { #[cfg(any())] x: 1 } = ();
// }
IDENT | INT_NUMBER if p.nth(1) == T![:] => {
name_ref_or_index(p);
p.bump(T![:]);
pattern(p);
}
T![box] => {
// FIXME: not all box patterns should be allowed
box_pat(p);
}
_ => {
ident_pat(p, false);
}
}
record_pat_field(p);
m.complete(p, RECORD_PAT_FIELD);
}
}

View File

@ -29,7 +29,7 @@ rayon = "1"
expect-test = "1.1"
proc-macro2 = "1.0.8"
quote = "1.0.2"
ungrammar = "=1.14.5"
ungrammar = "=1.14.6"
test_utils = { path = "../test_utils" }
sourcegen = { path = "../sourcegen" }

View File

@ -1290,6 +1290,7 @@ impl BoxPat {
pub struct RestPat {
pub(crate) syntax: SyntaxNode,
}
impl ast::HasAttrs for RestPat {}
impl RestPat {
pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
}
@ -1418,7 +1419,7 @@ pub struct RecordPatFieldList {
impl RecordPatFieldList {
pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
pub fn fields(&self) -> AstChildren<RecordPatField> { support::children(&self.syntax) }
pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
pub fn rest_pat(&self) -> Option<RestPat> { support::child(&self.syntax) }
pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
}
@ -3836,6 +3837,7 @@ impl AstNode for AnyHasAttrs {
| MATCH_ARM_LIST
| MATCH_ARM
| IDENT_PAT
| REST_PAT
| RECORD_PAT_FIELD => true,
_ => false,
}

View File

@ -62,7 +62,8 @@ SOURCE_FILE@0..103
RECORD_PAT_FIELD_LIST@66..72
L_CURLY@66..67 "{"
WHITESPACE@67..68 " "
DOT2@68..70 ".."
REST_PAT@68..70
DOT2@68..70 ".."
WHITESPACE@70..71 " "
R_CURLY@71..72 "}"
WHITESPACE@72..73 " "

View File

@ -1,5 +1,5 @@
SOURCE_FILE@0..119
FN@0..118
SOURCE_FILE@0..156
FN@0..155
FN_KW@0..2 "fn"
WHITESPACE@2..3 " "
NAME@3..6
@ -8,8 +8,8 @@ SOURCE_FILE@0..119
L_PAREN@6..7 "("
R_PAREN@7..8 ")"
WHITESPACE@8..9 " "
BLOCK_EXPR@9..118
STMT_LIST@9..118
BLOCK_EXPR@9..155
STMT_LIST@9..155
L_CURLY@9..10 "{"
WHITESPACE@10..15 "\n "
LET_STMT@15..29
@ -89,7 +89,8 @@ SOURCE_FILE@0..119
UNDERSCORE@78..79 "_"
COMMA@79..80 ","
WHITESPACE@80..81 " "
DOT2@81..83 ".."
REST_PAT@81..83
DOT2@81..83 ".."
R_CURLY@83..84 "}"
WHITESPACE@84..85 " "
EQ@85..86 "="
@ -128,6 +129,47 @@ SOURCE_FILE@0..119
L_PAREN@113..114 "("
R_PAREN@114..115 ")"
SEMICOLON@115..116 ";"
WHITESPACE@116..117 "\n"
R_CURLY@117..118 "}"
WHITESPACE@118..119 "\n"
WHITESPACE@116..121 "\n "
LET_STMT@121..153
LET_KW@121..124 "let"
WHITESPACE@124..125 " "
RECORD_PAT@125..147
PATH@125..126
PATH_SEGMENT@125..126
NAME_REF@125..126
IDENT@125..126 "S"
WHITESPACE@126..127 " "
RECORD_PAT_FIELD_LIST@127..147
L_CURLY@127..128 "{"
WHITESPACE@128..129 " "
REST_PAT@129..145
ATTR@129..142
POUND@129..130 "#"
L_BRACK@130..131 "["
META@131..141
PATH@131..134
PATH_SEGMENT@131..134
NAME_REF@131..134
IDENT@131..134 "cfg"
TOKEN_TREE@134..141
L_PAREN@134..135 "("
IDENT@135..138 "any"
TOKEN_TREE@138..140
L_PAREN@138..139 "("
R_PAREN@139..140 ")"
R_PAREN@140..141 ")"
R_BRACK@141..142 "]"
WHITESPACE@142..143 " "
DOT2@143..145 ".."
WHITESPACE@145..146 " "
R_CURLY@146..147 "}"
WHITESPACE@147..148 " "
EQ@148..149 "="
WHITESPACE@149..150 " "
TUPLE_EXPR@150..152
L_PAREN@150..151 "("
R_PAREN@151..152 ")"
SEMICOLON@152..153 ";"
WHITESPACE@153..154 "\n"
R_CURLY@154..155 "}"
WHITESPACE@155..156 "\n"

View File

@ -3,4 +3,5 @@ fn foo() {
let S { f, ref mut g } = ();
let S { h: _, ..} = ();
let S { h: _, } = ();
let S { #[cfg(any())] .. } = ();
}