diff options
Diffstat (limited to 'crates/ra_parser/src/grammar/items.rs')
-rw-r--r-- | crates/ra_parser/src/grammar/items.rs | 89 |
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 | ||
37 | pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) { | 37 | pub(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 | ||
76 | pub(super) enum MaybeItem { | 69 | pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Option<Marker> { |
77 | None, | ||
78 | Item(SyntaxKind), | ||
79 | Modifiers, | ||
80 | } | ||
81 | |||
82 | pub(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 | ||
174 | fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> { | 169 | fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> { |