aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs20
-rw-r--r--crates/ra_parser/src/parser.rs57
2 files changed, 37 insertions, 40 deletions
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index c8ce07179..73e1acd5a 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -82,16 +82,15 @@ pub(crate) fn expr_block_contents(p: &mut Parser) {
82 }; 82 };
83 83
84 let (cm, blocklike) = expr_stmt(p); 84 let (cm, blocklike) = expr_stmt(p);
85 let kind = cm.as_ref().map(|cm| cm.kind()).unwrap_or(ERROR);
85 86
86 if let Some(cm) = &cm { 87 if has_attrs && !is_expr_stmt_attr_allowed(kind) {
87 if has_attrs && !is_expr_stmt_attr_allowed(cm.kind()) { 88 // test_err attr_on_expr_not_allowed
88 // test_err attr_on_expr_not_allowed 89 // fn foo() {
89 // fn foo() { 90 // #[A] 1 + 2;
90 // #[A] 1 + 2; 91 // #[B] if true {};
91 // #[B] if true {}; 92 // }
92 // } 93 p.error(format!("attributes are not allowed on {:?}", kind));
93 p.error(format!("attributes are not allowed on {:?}", cm.kind()));
94 }
95 } 94 }
96 95
97 if p.at(R_CURLY) { 96 if p.at(R_CURLY) {
@@ -101,7 +100,8 @@ pub(crate) fn expr_block_contents(p: &mut Parser) {
101 // #[B] &() 100 // #[B] &()
102 // } 101 // }
103 if let Some(cm) = cm { 102 if let Some(cm) = cm {
104 m.contract_child(p, cm); 103 cm.undo_completion(p).abandon(p);
104 m.complete(p, kind);
105 } else { 105 } else {
106 m.abandon(p); 106 m.abandon(p);
107 } 107 }
diff --git a/crates/ra_parser/src/parser.rs b/crates/ra_parser/src/parser.rs
index fa036bdbf..3c326452b 100644
--- a/crates/ra_parser/src/parser.rs
+++ b/crates/ra_parser/src/parser.rs
@@ -212,8 +212,9 @@ impl Marker {
212 } 212 }
213 _ => unreachable!(), 213 _ => unreachable!(),
214 } 214 }
215 let finish_pos = p.events.len() as u32;
215 p.push_event(Event::Finish); 216 p.push_event(Event::Finish);
216 CompletedMarker::new(self.pos, kind) 217 CompletedMarker::new(self.pos, finish_pos, kind)
217 } 218 }
218 219
219 /// Abandons the syntax tree node. All its children 220 /// Abandons the syntax tree node. All its children
@@ -228,36 +229,17 @@ impl Marker {
228 } 229 }
229 } 230 }
230 } 231 }
231
232 /// Contract a node `cm` and complete as `cm`'s `kind`.
233 /// `cm` must be a child of `m` to work correctly.
234 /// ```text
235 /// m--A m--A
236 /// +--cm--B -> +--B
237 /// +--C C
238 ///
239 /// [m: TOMBSTONE, A, cm: Start(k), B, Finish, C]
240 /// [m: Start(k), A, cm: TOMBSTONE, B, Finish, C]
241 /// ```
242 pub(crate) fn contract_child(mut self, p: &mut Parser, cm: CompletedMarker) -> CompletedMarker {
243 self.bomb.defuse();
244 match p.events[self.pos as usize] {
245 Event::Start { kind: ref mut slot, .. } => *slot = cm.kind(),
246 _ => unreachable!(),
247 };
248 match p.events[cm.0 as usize] {
249 Event::Start { kind: ref mut slot, .. } => *slot = TOMBSTONE,
250 _ => unreachable!(),
251 };
252 CompletedMarker::new(self.pos, cm.kind())
253 }
254} 232}
255 233
256pub(crate) struct CompletedMarker(u32, SyntaxKind); 234pub(crate) struct CompletedMarker {
235 start_pos: u32,
236 finish_pos: u32,
237 kind: SyntaxKind,
238}
257 239
258impl CompletedMarker { 240impl CompletedMarker {
259 fn new(pos: u32, kind: SyntaxKind) -> Self { 241 fn new(start_pos: u32, finish_pos: u32, kind: SyntaxKind) -> Self {
260 CompletedMarker(pos, kind) 242 CompletedMarker { start_pos, finish_pos, kind }
261 } 243 }
262 244
263 /// This method allows to create a new node which starts 245 /// This method allows to create a new node which starts
@@ -274,17 +256,32 @@ impl CompletedMarker {
274 /// distance to `NEWSTART` into forward_parent(=2 in this case); 256 /// distance to `NEWSTART` into forward_parent(=2 in this case);
275 pub(crate) fn precede(self, p: &mut Parser) -> Marker { 257 pub(crate) fn precede(self, p: &mut Parser) -> Marker {
276 let new_pos = p.start(); 258 let new_pos = p.start();
277 let idx = self.0 as usize; 259 let idx = self.start_pos as usize;
278 match p.events[idx] { 260 match p.events[idx] {
279 Event::Start { ref mut forward_parent, .. } => { 261 Event::Start { ref mut forward_parent, .. } => {
280 *forward_parent = Some(new_pos.pos - self.0); 262 *forward_parent = Some(new_pos.pos - self.start_pos);
281 } 263 }
282 _ => unreachable!(), 264 _ => unreachable!(),
283 } 265 }
284 new_pos 266 new_pos
285 } 267 }
286 268
269 /// Undo this completion and turns into a `Marker`
270 pub(crate) fn undo_completion(self, p: &mut Parser) -> Marker {
271 let start_idx = self.start_pos as usize;
272 let finish_idx = self.finish_pos as usize;
273 match p.events[start_idx] {
274 Event::Start { ref mut kind, forward_parent: None } => *kind = TOMBSTONE,
275 _ => unreachable!(),
276 }
277 match p.events[finish_idx] {
278 ref mut slot @ Event::Finish => *slot = Event::tombstone(),
279 _ => unreachable!(),
280 }
281 Marker::new(self.start_pos)
282 }
283
287 pub(crate) fn kind(&self) -> SyntaxKind { 284 pub(crate) fn kind(&self) -> SyntaxKind {
288 self.1 285 self.kind
289 } 286 }
290} 287}