Skip to content

Commit b38fb1a

Browse files
committed
ssr/matching: Ignore trailing semicolon in let stmt, take 2
1 parent 45ac872 commit b38fb1a

File tree

1 file changed

+28
-6
lines changed

1 file changed

+28
-6
lines changed

crates/ssr/src/matching.rs

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ macro_rules! match_error {
2323
Some(format!("{}", $e))
2424
} else {
2525
None
26-
}
26+
},
27+
missing_semicolon: false,
2728
}
2829
}};
2930
($fmt:expr, $($arg:tt)+) => {{
@@ -32,7 +33,8 @@ macro_rules! match_error {
3233
Some(format!($fmt, $($arg)+))
3334
} else {
3435
None
35-
}
36+
},
37+
missing_semicolon: false,
3638
}
3739
}};
3840
}
@@ -81,7 +83,9 @@ pub(crate) struct MatchFailureReason {
8183
pub(crate) struct MatchFailed {
8284
/// The reason why we failed to match. Only present when debug_active true in call to
8385
/// `get_match`.
86+
// FIXME: Turn this into an enum?
8487
pub(crate) reason: Option<String>,
88+
pub(crate) missing_semicolon: bool,
8589
}
8690

8791
/// Checks if `code` matches the search pattern found in `search_scope`, returning information about
@@ -215,10 +219,29 @@ impl<'db, 'sema> Matcher<'db, 'sema> {
215219
}
216220
SyntaxKind::TOKEN_TREE => self.attempt_match_token_tree(phase, pattern, code),
217221
SyntaxKind::PATH => self.attempt_match_path(phase, pattern, code),
222+
SyntaxKind::LET_STMT => self.attempt_match_let(phase, pattern, code),
218223
_ => self.attempt_match_node_children(phase, pattern, code),
219224
}
220225
}
221226

227+
fn attempt_match_let(
228+
&self,
229+
phase: &mut Phase,
230+
pattern: &SyntaxNode,
231+
code: &SyntaxNode,
232+
) -> Result<(), MatchFailed> {
233+
let pattern_it = PatternIterator::new(pattern);
234+
let code_it = code.children_with_tokens();
235+
236+
match self.attempt_match_sequences(phase, pattern_it, code_it) {
237+
// For now this error is only surfaced when the pattern is empty
238+
Err(MatchFailed { missing_semicolon: true, .. }) /* if pattern_it.peek().is_none() */ => {
239+
Ok(())
240+
}
241+
res => res,
242+
}
243+
}
244+
222245
fn attempt_match_node_children(
223246
&self,
224247
phase: &mut Phase,
@@ -283,10 +306,6 @@ impl<'db, 'sema> Matcher<'db, 'sema> {
283306
if p.kind() == SyntaxKind::COMMA && is_closing_token(code.kind()) {
284307
pattern.next();
285308
}
286-
} else if code.kind() == SyntaxKind::SEMICOLON {
287-
// If the pattern ends but the code still has a trailing semicolon, accept the match.
288-
// Allows to match `let x = y; ...` with `let $a = $b`.
289-
return Ok(());
290309
}
291310

292311
// Consume an element from the pattern and make sure it matches.
@@ -312,6 +331,9 @@ impl<'db, 'sema> Matcher<'db, 'sema> {
312331
);
313332
}
314333
None => {
334+
if code.kind() == SyntaxKind::SEMICOLON {
335+
return Err(MatchFailed { reason: None, missing_semicolon: true });
336+
}
315337
fail_match!("Pattern exhausted, while code remains: `{}`", code.text());
316338
}
317339
}

0 commit comments

Comments
 (0)