diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs index 5a3b9f589d..ccbc905ab5 100644 --- a/crates/ra_parser/src/grammar/expressions.rs +++ b/crates/ra_parser/src/grammar/expressions.rs @@ -62,47 +62,41 @@ pub(crate) fn expr_block_contents(p: &mut Parser) { continue; } - match items::maybe_item(p, items::ItemFlavor::Mod) { - items::MaybeItem::Item(kind) => { - m.complete(p, kind); - } - items::MaybeItem::Modifiers => { + let m = match items::maybe_item(p, m, items::ItemFlavor::Mod) { + Ok(()) => continue, + Err(m) => m, + }; + + // test pub_expr + // fn foo() { pub 92; } //FIXME + if has_attrs { + m.abandon(p); + p.error("expected a let statement or an item after attributes in block"); + } else { + let is_blocklike = expressions::expr_stmt(p) == BlockLike::Block; + if p.at(R_CURLY) { m.abandon(p); - p.error("expected an item"); - } - // test pub_expr - // fn foo() { pub 92; } //FIXME - items::MaybeItem::None => { - if has_attrs { - m.abandon(p); - p.error("expected a let statement or an item after attributes in block"); + } else { + // test no_semi_after_block + // fn foo() { + // if true {} + // loop {} + // match () {} + // while true {} + // for _ in () {} + // {} + // {} + // macro_rules! test { + // () => {} + // } + // test!{} + // } + if is_blocklike { + p.eat(SEMI); } else { - let is_blocklike = expressions::expr_stmt(p) == BlockLike::Block; - if p.at(R_CURLY) { - m.abandon(p); - } else { - // test no_semi_after_block - // fn foo() { - // if true {} - // loop {} - // match () {} - // while true {} - // for _ in () {} - // {} - // {} - // macro_rules! test { - // () => {} - // } - // test!{} - // } - if is_blocklike { - p.eat(SEMI); - } else { - p.expect(SEMI); - } - m.complete(p, EXPR_STMT); - } + p.expect(SEMI); } + m.complete(p, EXPR_STMT); } } } diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs index a057c81675..94b93a02b7 100644 --- a/crates/ra_parser/src/grammar/items.rs +++ b/crates/ra_parser/src/grammar/items.rs @@ -37,52 +37,40 @@ pub(super) const ITEM_RECOVERY_SET: TokenSet = token_set![ pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) { let m = p.start(); attributes::outer_attributes(p); - match maybe_item(p, flavor) { - MaybeItem::Item(kind) => { - m.complete(p, kind); - } - MaybeItem::None => { - if paths::is_path_start(p) { - match macro_call(p) { - BlockLike::Block => (), - BlockLike::NotBlock => { - p.expect(SEMI); - } - } - m.complete(p, MACRO_CALL); - } else { - m.abandon(p); - if p.at(L_CURLY) { - error_block(p, "expected an item"); - } else if p.at(R_CURLY) && !stop_on_r_curly { - let e = p.start(); - p.error("unmatched `}`"); - p.bump(); - e.complete(p, ERROR); - } else if !p.at(EOF) && !p.at(R_CURLY) { - p.err_and_bump("expected an item"); - } else { - p.error("expected an item"); - } + let m = match maybe_item(p, m, flavor) { + Ok(()) => return, + Err(m) => m, + }; + if paths::is_path_start(p) { + match macro_call(p) { + BlockLike::Block => (), + BlockLike::NotBlock => { + p.expect(SEMI); } } - MaybeItem::Modifiers => { - p.error("expected fn, trait or impl"); - m.complete(p, ERROR); + m.complete(p, MACRO_CALL); + } else { + m.abandon(p); + if p.at(L_CURLY) { + error_block(p, "expected an item"); + } else if p.at(R_CURLY) && !stop_on_r_curly { + let e = p.start(); + p.error("unmatched `}`"); + p.bump(); + e.complete(p, ERROR); + } else if !p.at(EOF) && !p.at(R_CURLY) { + p.err_and_bump("expected an item"); + } else { + p.error("expected an item"); } } } -pub(super) enum MaybeItem { - None, - Item(SyntaxKind), - Modifiers, -} - -pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem { +pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Result<(), Marker> { opt_visibility(p); if let Some(kind) = items_without_modifiers(p) { - return MaybeItem::Item(kind); + m.complete(p, kind); + return Ok(()); } let mut has_mods = false; @@ -115,7 +103,7 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem { } // items - let kind = match p.current() { + match p.current() { // test async_fn // async fn foo() {} @@ -135,7 +123,7 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem { // unsafe fn foo() {} FN_KW => { fn_def(p, flavor); - FN_DEF + m.complete(p, FN_DEF); } // test unsafe_trait @@ -148,7 +136,7 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem { // unsafe auto trait T {} TRAIT_KW => { traits::trait_def(p); - TRAIT_DEF + m.complete(p, TRAIT_DEF); } // test unsafe_impl @@ -161,14 +149,18 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem { // unsafe default impl Foo {} IMPL_KW => { traits::impl_block(p); - IMPL_BLOCK + m.complete(p, IMPL_BLOCK); } _ => { - return if has_mods { MaybeItem::Modifiers } else { MaybeItem::None }; + if !has_mods { + return Err(m); + } else { + p.error("expected fn, trait or impl"); + m.complete(p, ERROR); + } } - }; - - MaybeItem::Item(kind) + } + Ok(()) } fn items_without_modifiers(p: &mut Parser) -> Option {