aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser/src/grammar/items.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_parser/src/grammar/items.rs')
-rw-r--r--crates/ra_parser/src/grammar/items.rs89
1 files changed, 42 insertions, 47 deletions
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index a057c8167..5411589dd 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -35,54 +35,42 @@ pub(super) const ITEM_RECOVERY_SET: TokenSet = token_set![
35]; 35];
36 36
37pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) { 37pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) {
38 let m = p.start(); 38 let mut m = p.start();
39 attributes::outer_attributes(p); 39 attributes::outer_attributes(p);
40 match maybe_item(p, flavor) { 40 m = match maybe_item(p, m, flavor) {
41 MaybeItem::Item(kind) => { 41 Some(m) => m,
42 m.complete(p, kind); 42 None => return,
43 } 43 };
44 MaybeItem::None => { 44 if paths::is_path_start(p) {
45 if paths::is_path_start(p) { 45 match macro_call(p) {
46 match macro_call(p) { 46 BlockLike::Block => (),
47 BlockLike::Block => (), 47 BlockLike::NotBlock => {
48 BlockLike::NotBlock => { 48 p.expect(SEMI);
49 p.expect(SEMI);
50 }
51 }
52 m.complete(p, MACRO_CALL);
53 } else {
54 m.abandon(p);
55 if p.at(L_CURLY) {
56 error_block(p, "expected an item");
57 } else if p.at(R_CURLY) && !stop_on_r_curly {
58 let e = p.start();
59 p.error("unmatched `}`");
60 p.bump();
61 e.complete(p, ERROR);
62 } else if !p.at(EOF) && !p.at(R_CURLY) {
63 p.err_and_bump("expected an item");
64 } else {
65 p.error("expected an item");
66 }
67 } 49 }
68 } 50 }
69 MaybeItem::Modifiers => { 51 m.complete(p, MACRO_CALL);
70 p.error("expected fn, trait or impl"); 52 } else {
71 m.complete(p, ERROR); 53 m.abandon(p);
54 if p.at(L_CURLY) {
55 error_block(p, "expected an item");
56 } else if p.at(R_CURLY) && !stop_on_r_curly {
57 let e = p.start();
58 p.error("unmatched `}`");
59 p.bump();
60 e.complete(p, ERROR);
61 } else if !p.at(EOF) && !p.at(R_CURLY) {
62 p.err_and_bump("expected an item");
63 } else {
64 p.error("expected an item");
72 } 65 }
73 } 66 }
74} 67}
75 68
76pub(super) enum MaybeItem { 69pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Option<Marker> {
77 None,
78 Item(SyntaxKind),
79 Modifiers,
80}
81
82pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
83 opt_visibility(p); 70 opt_visibility(p);
84 if let Some(kind) = items_without_modifiers(p) { 71 if let Some(kind) = items_without_modifiers(p) {
85 return MaybeItem::Item(kind); 72 m.complete(p, kind);
73 return None;
86 } 74 }
87 75
88 let mut has_mods = false; 76 let mut has_mods = false;
@@ -115,7 +103,7 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
115 } 103 }
116 104
117 // items 105 // items
118 let kind = match p.current() { 106 match p.current() {
119 // test async_fn 107 // test async_fn
120 // async fn foo() {} 108 // async fn foo() {}
121 109
@@ -135,7 +123,8 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
135 // unsafe fn foo() {} 123 // unsafe fn foo() {}
136 FN_KW => { 124 FN_KW => {
137 fn_def(p, flavor); 125 fn_def(p, flavor);
138 FN_DEF 126 m.complete(p, FN_DEF);
127 None
139 } 128 }
140 129
141 // test unsafe_trait 130 // test unsafe_trait
@@ -148,7 +137,8 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
148 // unsafe auto trait T {} 137 // unsafe auto trait T {}
149 TRAIT_KW => { 138 TRAIT_KW => {
150 traits::trait_def(p); 139 traits::trait_def(p);
151 TRAIT_DEF 140 m.complete(p, TRAIT_DEF);
141 None
152 } 142 }
153 143
154 // test unsafe_impl 144 // test unsafe_impl
@@ -161,14 +151,19 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
161 // unsafe default impl Foo {} 151 // unsafe default impl Foo {}
162 IMPL_KW => { 152 IMPL_KW => {
163 traits::impl_block(p); 153 traits::impl_block(p);
164 IMPL_BLOCK 154 m.complete(p, IMPL_BLOCK);
155 None
165 } 156 }
166 _ => { 157 _ => {
167 return if has_mods { MaybeItem::Modifiers } else { MaybeItem::None }; 158 if has_mods {
159 p.error("expected fn, trait or impl");
160 m.complete(p, ERROR);
161 None
162 } else {
163 Some(m)
164 }
168 } 165 }
169 }; 166 }
170
171 MaybeItem::Item(kind)
172} 167}
173 168
174fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> { 169fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> {