summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/parser/src
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/rust-analyzer/crates/parser/src')
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs26
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs5
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs47
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs130
4 files changed, 170 insertions, 38 deletions
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
index e7402104e..dcaceade6 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
@@ -564,8 +564,10 @@ fn path_expr(p: &mut Parser<'_>, r: Restrictions) -> (CompletedMarker, BlockLike
// test record_lit
// fn foo() {
// S {};
+// S { x };
// S { x, y: 32, };
// S { x, y: 32, ..Default::default() };
+// S { x: ::default() };
// TupleStruct { 0: 1 };
// }
pub(crate) fn record_expr_field_list(p: &mut Parser<'_>) {
@@ -582,16 +584,26 @@ pub(crate) fn record_expr_field_list(p: &mut Parser<'_>) {
match p.current() {
IDENT | INT_NUMBER => {
- // test_err record_literal_before_ellipsis_recovery
+ // test_err record_literal_missing_ellipsis_recovery
// fn main() {
- // S { field ..S::default() }
+ // S { S::default() }
// }
- if p.nth_at(1, T![:]) || p.nth_at(1, T![..]) {
- name_ref_or_index(p);
- p.expect(T![:]);
+ if p.nth_at(1, T![::]) {
+ m.abandon(p);
+ p.expect(T![..]);
+ expr(p);
+ } else {
+ // test_err record_literal_before_ellipsis_recovery
+ // fn main() {
+ // S { field ..S::default() }
+ // }
+ if p.nth_at(1, T![:]) || p.nth_at(1, T![..]) {
+ name_ref_or_index(p);
+ p.expect(T![:]);
+ }
+ expr(p);
+ m.complete(p, RECORD_EXPR_FIELD);
}
- expr(p);
- m.complete(p, RECORD_EXPR_FIELD);
}
T![.] if p.at(T![..]) => {
m.abandon(p);
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs
index 8de5d33a1..5dc9c6c82 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs
@@ -118,6 +118,11 @@ fn opt_path_type_args(p: &mut Parser<'_>, mode: Mode) {
match mode {
Mode::Use => {}
Mode::Type => {
+ // test typepathfn_with_coloncolon
+ // type F = Start::(Middle) -> (Middle)::End;
+ if p.at(T![::]) && p.nth_at(2, T!['(']) {
+ p.bump(T![::]);
+ }
// test path_fn_trait_args
// type F = Box<Fn(i32) -> ()>;
if p.at(T!['(']) {
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs
index 4cbf10306..bc1224af9 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs
@@ -13,6 +13,8 @@ pub(super) const PATTERN_FIRST: TokenSet =
T![.],
]));
+const PAT_TOP_FIRST: TokenSet = PATTERN_FIRST.union(TokenSet::new(&[T![|]]));
+
pub(crate) fn pattern(p: &mut Parser<'_>) {
pattern_r(p, PAT_RECOVERY_SET);
}
@@ -75,6 +77,16 @@ fn pattern_single_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
// Some(1..) => ()
// }
//
+ // match () {
+ // S { a: 0 } => (),
+ // S { a: 1.. } => (),
+ // }
+ //
+ // match () {
+ // [0] => (),
+ // [1..] => (),
+ // }
+ //
// match (10 as u8, 5 as u8) {
// (0, _) => (),
// (1.., _) => ()
@@ -88,11 +100,27 @@ fn pattern_single_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
let m = lhs.precede(p);
p.bump(range_op);
- // `0 .. =>` or `let 0 .. =` or `Some(0 .. )`
- // ^ ^ ^
- if p.at(T![=]) | p.at(T![')']) | p.at(T![,]) {
+ // testing if we're at one of the following positions:
+ // `0 .. =>`
+ // ^
+ // `let 0 .. =`
+ // ^
+ // `let 0..: _ =`
+ // ^
+ // (1.., _)
+ // ^
+ // `Some(0 .. )`
+ // ^
+ // `S { t: 0.. }`
+ // ^
+ // `[0..]`
+ // ^
+ if matches!(p.current(), T![=] | T![,] | T![:] | T![')'] | T!['}'] | T![']']) {
// test half_open_range_pat
- // fn f() { let 0 .. = 1u32; }
+ // fn f() {
+ // let 0 .. = 1u32;
+ // let 0..: _ = 1u32;
+ // }
} else {
atom_pat(p, recovery_set);
}
@@ -202,6 +230,7 @@ fn path_or_macro_pat(p: &mut Parser<'_>) -> CompletedMarker {
// let S(_) = ();
// let S(_,) = ();
// let S(_, .. , x) = ();
+// let S(| a) = ();
// }
fn tuple_pat_fields(p: &mut Parser<'_>) {
assert!(p.at(T!['(']));
@@ -337,6 +366,7 @@ fn ref_pat(p: &mut Parser<'_>) -> CompletedMarker {
// let (a,) = ();
// let (..) = ();
// let () = ();
+// let (| a | a, | b) = ((),());
// }
fn tuple_pat(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(T!['(']));
@@ -347,13 +377,13 @@ fn tuple_pat(p: &mut Parser<'_>) -> CompletedMarker {
let mut has_rest = false;
while !p.at(EOF) && !p.at(T![')']) {
has_pat = true;
- if !p.at_ts(PATTERN_FIRST) {
+ if !p.at_ts(PAT_TOP_FIRST) {
p.error("expected a pattern");
break;
}
has_rest |= p.at(T![..]);
- pattern(p);
+ pattern_top(p);
if !p.at(T![')']) {
has_comma = true;
p.expect(T![,]);
@@ -367,6 +397,7 @@ fn tuple_pat(p: &mut Parser<'_>) -> CompletedMarker {
// test slice_pat
// fn main() {
// let [a, b, ..] = [];
+// let [| a, ..] = [];
// }
fn slice_pat(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(T!['[']));
@@ -379,12 +410,12 @@ fn slice_pat(p: &mut Parser<'_>) -> CompletedMarker {
fn pat_list(p: &mut Parser<'_>, ket: SyntaxKind) {
while !p.at(EOF) && !p.at(ket) {
- if !p.at_ts(PATTERN_FIRST) {
+ if !p.at_ts(PAT_TOP_FIRST) {
p.error("expected a pattern");
break;
}
- pattern(p);
+ pattern_top(p);
if !p.at(ket) {
p.expect(T![,]);
}
diff --git a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs
index 628fa745e..c84f45f1f 100644
--- a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs
@@ -262,33 +262,117 @@ pub enum SyntaxKind {
use self::SyntaxKind::*;
impl SyntaxKind {
pub fn is_keyword(self) -> bool {
- match self {
- AS_KW | ASYNC_KW | AWAIT_KW | BOX_KW | BREAK_KW | CONST_KW | CONTINUE_KW | CRATE_KW
- | DYN_KW | ELSE_KW | ENUM_KW | EXTERN_KW | FALSE_KW | FN_KW | FOR_KW | IF_KW
- | IMPL_KW | IN_KW | LET_KW | LOOP_KW | MACRO_KW | MATCH_KW | MOD_KW | MOVE_KW
- | MUT_KW | PUB_KW | REF_KW | RETURN_KW | SELF_KW | SELF_TYPE_KW | STATIC_KW
- | STRUCT_KW | SUPER_KW | TRAIT_KW | TRUE_KW | TRY_KW | TYPE_KW | UNSAFE_KW | USE_KW
- | WHERE_KW | WHILE_KW | YIELD_KW | AUTO_KW | DEFAULT_KW | EXISTENTIAL_KW | UNION_KW
- | RAW_KW | MACRO_RULES_KW => true,
- _ => false,
- }
+ matches!(
+ self,
+ AS_KW
+ | ASYNC_KW
+ | AWAIT_KW
+ | BOX_KW
+ | BREAK_KW
+ | CONST_KW
+ | CONTINUE_KW
+ | CRATE_KW
+ | DYN_KW
+ | ELSE_KW
+ | ENUM_KW
+ | EXTERN_KW
+ | FALSE_KW
+ | FN_KW
+ | FOR_KW
+ | IF_KW
+ | IMPL_KW
+ | IN_KW
+ | LET_KW
+ | LOOP_KW
+ | MACRO_KW
+ | MATCH_KW
+ | MOD_KW
+ | MOVE_KW
+ | MUT_KW
+ | PUB_KW
+ | REF_KW
+ | RETURN_KW
+ | SELF_KW
+ | SELF_TYPE_KW
+ | STATIC_KW
+ | STRUCT_KW
+ | SUPER_KW
+ | TRAIT_KW
+ | TRUE_KW
+ | TRY_KW
+ | TYPE_KW
+ | UNSAFE_KW
+ | USE_KW
+ | WHERE_KW
+ | WHILE_KW
+ | YIELD_KW
+ | AUTO_KW
+ | DEFAULT_KW
+ | EXISTENTIAL_KW
+ | UNION_KW
+ | RAW_KW
+ | MACRO_RULES_KW
+ )
}
pub fn is_punct(self) -> bool {
- match self {
- SEMICOLON | COMMA | L_PAREN | R_PAREN | L_CURLY | R_CURLY | L_BRACK | R_BRACK
- | L_ANGLE | R_ANGLE | AT | POUND | TILDE | QUESTION | DOLLAR | AMP | PIPE | PLUS
- | STAR | SLASH | CARET | PERCENT | UNDERSCORE | DOT | DOT2 | DOT3 | DOT2EQ | COLON
- | COLON2 | EQ | EQ2 | FAT_ARROW | BANG | NEQ | MINUS | THIN_ARROW | LTEQ | GTEQ
- | PLUSEQ | MINUSEQ | PIPEEQ | AMPEQ | CARETEQ | SLASHEQ | STAREQ | PERCENTEQ | AMP2
- | PIPE2 | SHL | SHR | SHLEQ | SHREQ => true,
- _ => false,
- }
+ matches!(
+ self,
+ SEMICOLON
+ | COMMA
+ | L_PAREN
+ | R_PAREN
+ | L_CURLY
+ | R_CURLY
+ | L_BRACK
+ | R_BRACK
+ | L_ANGLE
+ | R_ANGLE
+ | AT
+ | POUND
+ | TILDE
+ | QUESTION
+ | DOLLAR
+ | AMP
+ | PIPE
+ | PLUS
+ | STAR
+ | SLASH
+ | CARET
+ | PERCENT
+ | UNDERSCORE
+ | DOT
+ | DOT2
+ | DOT3
+ | DOT2EQ
+ | COLON
+ | COLON2
+ | EQ
+ | EQ2
+ | FAT_ARROW
+ | BANG
+ | NEQ
+ | MINUS
+ | THIN_ARROW
+ | LTEQ
+ | GTEQ
+ | PLUSEQ
+ | MINUSEQ
+ | PIPEEQ
+ | AMPEQ
+ | CARETEQ
+ | SLASHEQ
+ | STAREQ
+ | PERCENTEQ
+ | AMP2
+ | PIPE2
+ | SHL
+ | SHR
+ | SHLEQ
+ | SHREQ
+ )
}
pub fn is_literal(self) -> bool {
- match self {
- INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE | STRING | BYTE_STRING => true,
- _ => false,
- }
+ matches!(self, INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE | STRING | BYTE_STRING)
}
pub fn from_keyword(ident: &str) -> Option<SyntaxKind> {
let kw = match ident {