mirror of
https://github.com/typst/typst
synced 2025-05-15 17:45:27 +08:00
Parameter pattern bug (#1062)
This commit is contained in:
parent
ffad8516af
commit
db6a710638
@ -739,7 +739,7 @@ fn with_paren(p: &mut Parser, allow_destructuring: bool) {
|
|||||||
let m = p.marker();
|
let m = p.marker();
|
||||||
let mut kind = collection(p, true);
|
let mut kind = collection(p, true);
|
||||||
if p.at(SyntaxKind::Arrow) {
|
if p.at(SyntaxKind::Arrow) {
|
||||||
validate_params(p, m);
|
validate_params_at(p, m);
|
||||||
p.wrap(m, SyntaxKind::Params);
|
p.wrap(m, SyntaxKind::Params);
|
||||||
p.assert(SyntaxKind::Arrow);
|
p.assert(SyntaxKind::Arrow);
|
||||||
code_expr(p);
|
code_expr(p);
|
||||||
@ -747,7 +747,7 @@ fn with_paren(p: &mut Parser, allow_destructuring: bool) {
|
|||||||
} else if p.at(SyntaxKind::Eq) && kind != SyntaxKind::Parenthesized {
|
} else if p.at(SyntaxKind::Eq) && kind != SyntaxKind::Parenthesized {
|
||||||
// TODO: add warning if p.at(SyntaxKind::Eq) && kind == SyntaxKind::Parenthesized
|
// TODO: add warning if p.at(SyntaxKind::Eq) && kind == SyntaxKind::Parenthesized
|
||||||
|
|
||||||
validate_destruct_pattern(p, m, false);
|
validate_pattern_at(p, m, false);
|
||||||
p.wrap(m, SyntaxKind::Destructuring);
|
p.wrap(m, SyntaxKind::Destructuring);
|
||||||
p.assert(SyntaxKind::Eq);
|
p.assert(SyntaxKind::Eq);
|
||||||
code_expr(p);
|
code_expr(p);
|
||||||
@ -755,9 +755,11 @@ fn with_paren(p: &mut Parser, allow_destructuring: bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match kind {
|
match kind {
|
||||||
SyntaxKind::Array => validate_array(p, m),
|
SyntaxKind::Array if !allow_destructuring => validate_array_at(p, m),
|
||||||
SyntaxKind::Dict => validate_dict(p, m),
|
SyntaxKind::Dict if !allow_destructuring => validate_dict_at(p, m),
|
||||||
SyntaxKind::Parenthesized => validate_parenthesized(p, m),
|
SyntaxKind::Parenthesized if !allow_destructuring => {
|
||||||
|
validate_parenthesized_at(p, m)
|
||||||
|
}
|
||||||
SyntaxKind::Destructuring if !allow_destructuring => {
|
SyntaxKind::Destructuring if !allow_destructuring => {
|
||||||
invalidate_destructuring(p, m)
|
invalidate_destructuring(p, m)
|
||||||
}
|
}
|
||||||
@ -914,7 +916,7 @@ fn args(p: &mut Parser) {
|
|||||||
let m = p.marker();
|
let m = p.marker();
|
||||||
if p.at(SyntaxKind::LeftParen) {
|
if p.at(SyntaxKind::LeftParen) {
|
||||||
collection(p, false);
|
collection(p, false);
|
||||||
validate_args(p, m);
|
validate_args_at(p, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
while p.directly_at(SyntaxKind::LeftBracket) {
|
while p.directly_at(SyntaxKind::LeftBracket) {
|
||||||
@ -934,7 +936,7 @@ fn pattern(p: &mut Parser) -> PatternKind {
|
|||||||
let m = p.marker();
|
let m = p.marker();
|
||||||
if p.at(SyntaxKind::LeftParen) {
|
if p.at(SyntaxKind::LeftParen) {
|
||||||
let kind = collection(p, false);
|
let kind = collection(p, false);
|
||||||
validate_destruct_pattern(p, m, true);
|
validate_pattern_at(p, m, true);
|
||||||
|
|
||||||
if kind == SyntaxKind::Parenthesized {
|
if kind == SyntaxKind::Parenthesized {
|
||||||
PatternKind::Ident
|
PatternKind::Ident
|
||||||
@ -963,7 +965,7 @@ fn let_binding(p: &mut Parser) {
|
|||||||
if closure {
|
if closure {
|
||||||
let m3 = p.marker();
|
let m3 = p.marker();
|
||||||
collection(p, false);
|
collection(p, false);
|
||||||
validate_params(p, m3);
|
validate_params_at(p, m3);
|
||||||
p.wrap(m3, SyntaxKind::Params);
|
p.wrap(m3, SyntaxKind::Params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1114,36 +1116,51 @@ fn return_stmt(p: &mut Parser) {
|
|||||||
p.wrap(m, SyntaxKind::FuncReturn);
|
p.wrap(m, SyntaxKind::FuncReturn);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_parenthesized(p: &mut Parser, m: Marker) {
|
fn validate_parenthesized_at(p: &mut Parser, m: Marker) {
|
||||||
for child in p.post_process(m) {
|
for child in p.post_process(m) {
|
||||||
let kind = child.kind();
|
let kind = child.kind();
|
||||||
if kind == SyntaxKind::Underscore {
|
match kind {
|
||||||
child.convert_to_error(eco_format!(
|
SyntaxKind::Array => validate_array(child.children_mut().iter_mut()),
|
||||||
"expected expression, found {}",
|
SyntaxKind::Dict => validate_dict(child.children_mut().iter_mut()),
|
||||||
kind.name()
|
SyntaxKind::Underscore => {
|
||||||
));
|
child.convert_to_error(eco_format!(
|
||||||
|
"expected expression, found {}",
|
||||||
|
kind.name()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_array(p: &mut Parser, m: Marker) {
|
fn validate_array_at(p: &mut Parser, m: Marker) {
|
||||||
for child in p.post_process(m) {
|
validate_array(p.post_process(m))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate_array<'a>(children: impl Iterator<Item = &'a mut SyntaxNode>) {
|
||||||
|
for child in children {
|
||||||
let kind = child.kind();
|
let kind = child.kind();
|
||||||
if kind == SyntaxKind::Named
|
match kind {
|
||||||
|| kind == SyntaxKind::Keyed
|
SyntaxKind::Array => validate_array(child.children_mut().iter_mut()),
|
||||||
|| kind == SyntaxKind::Underscore
|
SyntaxKind::Dict => validate_dict(child.children_mut().iter_mut()),
|
||||||
{
|
SyntaxKind::Named | SyntaxKind::Keyed | SyntaxKind::Underscore => {
|
||||||
child.convert_to_error(eco_format!(
|
child.convert_to_error(eco_format!(
|
||||||
"expected expression, found {}",
|
"expected expression, found {}",
|
||||||
kind.name()
|
kind.name()
|
||||||
));
|
));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_dict(p: &mut Parser, m: Marker) {
|
fn validate_dict_at(p: &mut Parser, m: Marker) {
|
||||||
|
validate_dict(p.post_process(m))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate_dict<'a>(children: impl Iterator<Item = &'a mut SyntaxNode>) {
|
||||||
let mut used = HashSet::new();
|
let mut used = HashSet::new();
|
||||||
for child in p.post_process(m) {
|
for child in children {
|
||||||
match child.kind() {
|
match child.kind() {
|
||||||
SyntaxKind::Named | SyntaxKind::Keyed => {
|
SyntaxKind::Named | SyntaxKind::Keyed => {
|
||||||
let Some(first) = child.children_mut().first_mut() else { continue };
|
let Some(first) = child.children_mut().first_mut() else { continue };
|
||||||
@ -1172,7 +1189,7 @@ fn validate_dict(p: &mut Parser, m: Marker) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_params(p: &mut Parser, m: Marker) {
|
fn validate_params_at(p: &mut Parser, m: Marker) {
|
||||||
let mut used_spread = false;
|
let mut used_spread = false;
|
||||||
let mut used = HashSet::new();
|
let mut used = HashSet::new();
|
||||||
for child in p.post_process(m) {
|
for child in p.post_process(m) {
|
||||||
@ -1238,7 +1255,7 @@ fn validate_params(p: &mut Parser, m: Marker) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_args(p: &mut Parser, m: Marker) {
|
fn validate_args_at(p: &mut Parser, m: Marker) {
|
||||||
let mut used = HashSet::new();
|
let mut used = HashSet::new();
|
||||||
for child in p.post_process(m) {
|
for child in p.post_process(m) {
|
||||||
if child.kind() == SyntaxKind::Named {
|
if child.kind() == SyntaxKind::Named {
|
||||||
@ -1256,7 +1273,7 @@ fn validate_args(p: &mut Parser, m: Marker) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_destruct_pattern(p: &mut Parser, m: Marker, forbid_expressions: bool) {
|
fn validate_pattern_at(p: &mut Parser, m: Marker, forbid_expressions: bool) {
|
||||||
let mut used = HashSet::new();
|
let mut used = HashSet::new();
|
||||||
validate_pattern(p.post_process(m), &mut used, forbid_expressions);
|
validate_pattern(p.post_process(m), &mut used, forbid_expressions);
|
||||||
}
|
}
|
||||||
|
5
tests/typ/bugs/parameter-pattern.typ
Normal file
5
tests/typ/bugs/parameter-pattern.typ
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// Test that underscore works in parameter patterns.
|
||||||
|
// Ref: false
|
||||||
|
|
||||||
|
---
|
||||||
|
#test((1, 2, 3).zip((1, 2, 3)).map(((_, x)) => x), (1, 2, 3))
|
Loading…
x
Reference in New Issue
Block a user