987: Refactor maybe_item to use Marker argument r=pcpthm a=pcpthm

As suggested at <https://github.com/rust-analyzer/rust-analyzer/pull/980#issuecomment-473659745>.
For expression paring functions, changing signature
- from `fn(&mut Parser) -> Option<CompletedMarker>` to `fn(&mut Parser, Marker) -> Result<CompletedMarker, Marker>`
- from `fn(&mut Parser) -> CompletedMarker` to `fn(&mut Parser, Marker) -> CompletedMarker`
is my plan.

Co-authored-by: pcpthm <pcpthm@gmail.com>
This commit is contained in:
bors[bot] 2019-03-18 04:16:20 +00:00
commit 4c1ea0b628
2 changed files with 70 additions and 84 deletions

View file

@ -62,47 +62,41 @@ pub(crate) fn expr_block_contents(p: &mut Parser) {
continue; continue;
} }
match items::maybe_item(p, items::ItemFlavor::Mod) { let m = match items::maybe_item(p, m, items::ItemFlavor::Mod) {
items::MaybeItem::Item(kind) => { Ok(()) => continue,
m.complete(p, kind); Err(m) => m,
} };
items::MaybeItem::Modifiers => {
// 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); m.abandon(p);
p.error("expected an item"); } else {
} // test no_semi_after_block
// test pub_expr // fn foo() {
// fn foo() { pub 92; } //FIXME // if true {}
items::MaybeItem::None => { // loop {}
if has_attrs { // match () {}
m.abandon(p); // while true {}
p.error("expected a let statement or an item after attributes in block"); // for _ in () {}
// {}
// {}
// macro_rules! test {
// () => {}
// }
// test!{}
// }
if is_blocklike {
p.eat(SEMI);
} else { } else {
let is_blocklike = expressions::expr_stmt(p) == BlockLike::Block; p.expect(SEMI);
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);
}
} }
m.complete(p, EXPR_STMT);
} }
} }
} }

View file

@ -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) { pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) {
let m = p.start(); let m = p.start();
attributes::outer_attributes(p); attributes::outer_attributes(p);
match maybe_item(p, flavor) { let m = match maybe_item(p, m, flavor) {
MaybeItem::Item(kind) => { Ok(()) => return,
m.complete(p, kind); Err(m) => m,
} };
MaybeItem::None => { if paths::is_path_start(p) {
if paths::is_path_start(p) { match macro_call(p) {
match macro_call(p) { BlockLike::Block => (),
BlockLike::Block => (), BlockLike::NotBlock => {
BlockLike::NotBlock => { p.expect(SEMI);
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");
}
} }
} }
MaybeItem::Modifiers => { m.complete(p, MACRO_CALL);
p.error("expected fn, trait or impl"); } else {
m.complete(p, ERROR); 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 { pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Result<(), Marker> {
None,
Item(SyntaxKind),
Modifiers,
}
pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
opt_visibility(p); opt_visibility(p);
if let Some(kind) = items_without_modifiers(p) { if let Some(kind) = items_without_modifiers(p) {
return MaybeItem::Item(kind); m.complete(p, kind);
return Ok(());
} }
let mut has_mods = false; let mut has_mods = false;
@ -115,7 +103,7 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
} }
// items // items
let kind = match p.current() { match p.current() {
// test async_fn // test async_fn
// async fn foo() {} // async fn foo() {}
@ -135,7 +123,7 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
// unsafe fn foo() {} // unsafe fn foo() {}
FN_KW => { FN_KW => {
fn_def(p, flavor); fn_def(p, flavor);
FN_DEF m.complete(p, FN_DEF);
} }
// test unsafe_trait // test unsafe_trait
@ -148,7 +136,7 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
// unsafe auto trait T {} // unsafe auto trait T {}
TRAIT_KW => { TRAIT_KW => {
traits::trait_def(p); traits::trait_def(p);
TRAIT_DEF m.complete(p, TRAIT_DEF);
} }
// test unsafe_impl // test unsafe_impl
@ -161,14 +149,18 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
// unsafe default impl Foo {} // unsafe default impl Foo {}
IMPL_KW => { IMPL_KW => {
traits::impl_block(p); 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);
}
} }
}; }
Ok(())
MaybeItem::Item(kind)
} }
fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> { fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> {