Skip to content

Commit

Permalink
Merge pull request #18419 from ChayimFriedman2/leading-or
Browse files Browse the repository at this point in the history
fix: Put leading `|` in patterns under `OrPat`
  • Loading branch information
Veykril authored Oct 27, 2024
2 parents 715b67c + e12a001 commit 3b3a87f
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 31 deletions.
4 changes: 4 additions & 0 deletions crates/hir-def/src/body/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1598,6 +1598,10 @@ impl ExprCollector<'_> {
for (id, _) in current_is_used.into_iter() {
binding_list.check_is_used(self, id);
}
if let &[pat] = &*pats {
// Leading pipe without real OR pattern. Leaving an one-item OR pattern may confuse later stages.
return pat;
}
Pat::Or(pats.into())
}
ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat(), binding_list),
Expand Down
3 changes: 3 additions & 0 deletions crates/ide-assists/src/handlers/unmerge_match_arm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
pub(crate) fn unmerge_match_arm(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
let pipe_token = ctx.find_token_syntax_at_offset(T![|])?;
let or_pat = ast::OrPat::cast(pipe_token.parent()?)?.clone_for_update();
if or_pat.leading_pipe().is_some_and(|it| it == pipe_token) {
return None;
}
let match_arm = ast::MatchArm::cast(or_pat.syntax().parent()?)?;
let match_arm_body = match_arm.expr()?;

Expand Down
13 changes: 7 additions & 6 deletions crates/parser/src/grammar/patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ const RANGE_PAT_END_FIRST: TokenSet =
expressions::LITERAL_FIRST.union(paths::PATH_FIRST).union(TokenSet::new(&[T![-], T![const]]));

pub(crate) fn pattern(p: &mut Parser<'_>) {
pattern_r(p, PAT_RECOVERY_SET);
let m = p.start();
pattern_r(p, m, false, PAT_RECOVERY_SET);
}

/// Parses a pattern list separated by pipes `|`.
Expand All @@ -36,8 +37,9 @@ pub(crate) fn pattern_single(p: &mut Parser<'_>) {
/// Parses a pattern list separated by pipes `|`
/// using the given `recovery_set`.
pub(super) fn pattern_top_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
p.eat(T![|]);
pattern_r(p, recovery_set);
let m = p.start();
let has_leading_pipe = p.eat(T![|]);
pattern_r(p, m, has_leading_pipe, recovery_set);
}

// test or_pattern
Expand All @@ -51,11 +53,10 @@ pub(super) fn pattern_top_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
// }
/// Parses a pattern list separated by pipes `|`, with no leading `|`,using the
/// given `recovery_set`.
fn pattern_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
let m = p.start();
fn pattern_r(p: &mut Parser<'_>, m: Marker, has_leading_pipe: bool, recovery_set: TokenSet) {
pattern_single_r(p, recovery_set);

if !p.at(T![|]) {
if !p.at(T![|]) && !has_leading_pipe {
m.abandon(p);
return;
}
Expand Down
32 changes: 32 additions & 0 deletions crates/parser/src/tests/top_entries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,38 @@ fn macro_pattern() {
error 0: expected pattern
"#]],
);

check(
TopEntryPoint::Pattern,
"| 42 | 43",
expect![[r#"
OR_PAT
PIPE "|"
WHITESPACE " "
LITERAL_PAT
LITERAL
INT_NUMBER "42"
WHITESPACE " "
PIPE "|"
WHITESPACE " "
LITERAL_PAT
LITERAL
INT_NUMBER "43"
"#]],
);

check(
TopEntryPoint::Pattern,
"| 42",
expect![[r#"
OR_PAT
PIPE "|"
WHITESPACE " "
LITERAL_PAT
LITERAL
INT_NUMBER "42"
"#]],
);
}

#[test]
Expand Down
15 changes: 8 additions & 7 deletions crates/parser/test_data/parser/inline/ok/match_arm.rast
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ SOURCE_FILE
COMMA ","
WHITESPACE "\n "
MATCH_ARM
PIPE "|"
WHITESPACE " "
OR_PAT
PIPE "|"
WHITESPACE " "
IDENT_PAT
NAME
IDENT "X"
Expand Down Expand Up @@ -132,11 +132,12 @@ SOURCE_FILE
COMMA ","
WHITESPACE "\n "
MATCH_ARM
PIPE "|"
WHITESPACE " "
IDENT_PAT
NAME
IDENT "X"
OR_PAT
PIPE "|"
WHITESPACE " "
IDENT_PAT
NAME
IDENT "X"
WHITESPACE " "
FAT_ARROW "=>"
WHITESPACE " "
Expand Down
11 changes: 6 additions & 5 deletions crates/parser/test_data/parser/inline/ok/slice_pat.rast
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,12 @@ SOURCE_FILE
WHITESPACE " "
SLICE_PAT
L_BRACK "["
PIPE "|"
WHITESPACE " "
IDENT_PAT
NAME
IDENT "a"
OR_PAT
PIPE "|"
WHITESPACE " "
IDENT_PAT
NAME
IDENT "a"
COMMA ","
WHITESPACE " "
REST_PAT
Expand Down
15 changes: 8 additions & 7 deletions crates/parser/test_data/parser/inline/ok/tuple_pat.rast
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ SOURCE_FILE
WHITESPACE " "
TUPLE_PAT
L_PAREN "("
PIPE "|"
WHITESPACE " "
OR_PAT
PIPE "|"
WHITESPACE " "
IDENT_PAT
NAME
IDENT "a"
Expand All @@ -105,11 +105,12 @@ SOURCE_FILE
IDENT "a"
COMMA ","
WHITESPACE " "
PIPE "|"
WHITESPACE " "
IDENT_PAT
NAME
IDENT "b"
OR_PAT
PIPE "|"
WHITESPACE " "
IDENT_PAT
NAME
IDENT "b"
R_PAREN ")"
WHITESPACE " "
EQ "="
Expand Down
11 changes: 6 additions & 5 deletions crates/parser/test_data/parser/inline/ok/tuple_pat_fields.rast
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,12 @@ SOURCE_FILE
NAME_REF
IDENT "S"
L_PAREN "("
PIPE "|"
WHITESPACE " "
IDENT_PAT
NAME
IDENT "a"
OR_PAT
PIPE "|"
WHITESPACE " "
IDENT_PAT
NAME
IDENT "a"
R_PAREN ")"
WHITESPACE " "
EQ "="
Expand Down
2 changes: 1 addition & 1 deletion crates/syntax/rust.ungram
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,7 @@ PathPat =
Path

OrPat =
(Pat ('|' Pat)* '|'?)
'|'? (Pat ('|' Pat)*)

BoxPat =
'box' Pat
Expand Down
2 changes: 2 additions & 0 deletions crates/syntax/src/ast/generated/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,8 @@ pub struct OrPat {
impl OrPat {
#[inline]
pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
#[inline]
pub fn pipe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![|]) }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
Expand Down
10 changes: 10 additions & 0 deletions crates/syntax/src/ast/node_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1140,3 +1140,13 @@ impl From<ast::AssocItem> for ast::AnyHasAttrs {
Self::new(node)
}
}

impl ast::OrPat {
pub fn leading_pipe(&self) -> Option<SyntaxToken> {
self.syntax
.children_with_tokens()
.find(|it| !it.kind().is_trivia())
.and_then(NodeOrToken::into_token)
.filter(|it| it.kind() == T![|])
}
}

0 comments on commit 3b3a87f

Please sign in to comment.