⬆️ rust-analyzer

This commit is contained in:
Laurențiu Nicola 2023-03-13 10:42:24 +02:00
parent 15b867b5db
commit b2f6fd4f96
217 changed files with 12639 additions and 3059 deletions

View file

@ -198,6 +198,10 @@ impl BlockLike {
fn is_block(self) -> bool {
self == BlockLike::Block
}
fn is_blocklike(kind: SyntaxKind) -> bool {
matches!(kind, BLOCK_EXPR | IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR)
}
}
const VISIBILITY_FIRST: TokenSet = TokenSet::new(&[T![pub], T![crate]]);

View file

@ -43,7 +43,7 @@ pub(super) fn meta(p: &mut Parser<'_>) {
match p.current() {
T![=] => {
p.bump(T![=]);
if !expressions::expr(p) {
if expressions::expr(p).is_none() {
p.error("expected expression");
}
}

View file

@ -16,9 +16,9 @@ pub(super) enum Semicolon {
const EXPR_FIRST: TokenSet = LHS_FIRST;
pub(super) fn expr(p: &mut Parser<'_>) -> bool {
pub(super) fn expr(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let r = Restrictions { forbid_structs: false, prefer_stmt: false };
expr_bp(p, None, r, 1).is_some()
expr_bp(p, None, r, 1).map(|(m, _)| m)
}
pub(super) fn expr_stmt(
@ -120,16 +120,27 @@ pub(super) fn stmt(p: &mut Parser<'_>, semicolon: Semicolon) {
// fn f() { let x: i32; }
types::ascription(p);
}
let mut expr_after_eq: Option<CompletedMarker> = None;
if p.eat(T![=]) {
// test let_stmt_init
// fn f() { let x = 92; }
expressions::expr(p);
expr_after_eq = expressions::expr(p);
}
if p.at(T![else]) {
// test_err let_else_right_curly_brace
// fn func() { let Some(_) = {Some(1)} else { panic!("h") };}
if let Some(expr) = expr_after_eq {
if BlockLike::is_blocklike(expr.kind()) {
p.error(
"right curly brace `}` before `else` in a `let...else` statement not allowed",
)
}
}
// test let_else
// fn f() { let Some(x) = opt else { return }; }
let m = p.start();
p.bump(T![else]);
block_expr(p);
@ -578,7 +589,14 @@ fn arg_list(p: &mut Parser<'_>) {
// fn main() {
// foo(#[attr] 92)
// }
delimited(p, T!['('], T![')'], T![,], EXPR_FIRST.union(ATTRIBUTE_FIRST), expr);
delimited(
p,
T!['('],
T![')'],
T![,],
EXPR_FIRST.union(ATTRIBUTE_FIRST),
|p: &mut Parser<'_>| expr(p).is_some(),
);
m.complete(p, ARG_LIST);
}

View file

@ -163,10 +163,8 @@ pub(super) fn atom_expr(
return None;
}
};
let blocklike = match done.kind() {
IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR => BlockLike::Block,
_ => BlockLike::NotBlock,
};
let blocklike =
if BlockLike::is_blocklike(done.kind()) { BlockLike::Block } else { BlockLike::NotBlock };
Some((done, blocklike))
}
@ -188,7 +186,7 @@ fn tuple_expr(p: &mut Parser<'_>) -> CompletedMarker {
// test tuple_attrs
// const A: (i64, i64) = (1, #[cfg(test)] 2);
if !expr(p) {
if expr(p).is_none() {
break;
}
@ -221,7 +219,7 @@ fn array_expr(p: &mut Parser<'_>) -> CompletedMarker {
// test array_attrs
// const A: &[i64] = &[1, #[cfg(test)] 2];
if !expr(p) {
if expr(p).is_none() {
break;
}

View file

@ -20,7 +20,7 @@ pub(super) fn trait_(p: &mut Parser<'_>, m: Marker) {
// trait Z<U> = where Self: T<U>;
generic_params::opt_where_clause(p);
p.expect(T![;]);
m.complete(p, TRAIT);
m.complete(p, TRAIT_ALIAS);
return;
}

View file

@ -77,6 +77,9 @@ fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) {
// type X = <A as B>::Output;
// fn foo() { <usize as Default>::default(); }
if first && p.eat(T![<]) {
// test_err angled_path_without_qual
// type X = <()>;
// type Y = <A as B>;
types::type_(p);
if p.eat(T![as]) {
if is_use_path_start(p) {
@ -86,6 +89,9 @@ fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) {
}
}
p.expect(T![>]);
if !p.at(T![::]) {
p.error("expected `::`");
}
} else {
let empty = if first {
p.eat(T![::]);

View file

@ -135,6 +135,7 @@ pub enum SyntaxKind {
STATIC,
CONST,
TRAIT,
TRAIT_ALIAS,
IMPL,
TYPE_ALIAS,
MACRO_CALL,