mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Improve hint when provided array for destructuring has fewer elements than expected (#5139)
Co-authored-by: Laurenz <laurmaedje@gmail.com>
This commit is contained in:
parent
2a40eb518c
commit
bb39d8f10a
@ -1,6 +1,8 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use crate::diag::{bail, At, SourceResult};
|
use ecow::eco_format;
|
||||||
|
|
||||||
|
use crate::diag::{bail, error, At, SourceDiagnostic, SourceResult};
|
||||||
use crate::eval::{Access, Eval, Vm};
|
use crate::eval::{Access, Eval, Vm};
|
||||||
use crate::foundations::{Array, Dict, Value};
|
use crate::foundations::{Array, Dict, Value};
|
||||||
use crate::syntax::ast::{self, AstNode};
|
use crate::syntax::ast::{self, AstNode};
|
||||||
@ -96,10 +98,7 @@ where
|
|||||||
match p {
|
match p {
|
||||||
ast::DestructuringItem::Pattern(pattern) => {
|
ast::DestructuringItem::Pattern(pattern) => {
|
||||||
let Ok(v) = value.at(i as i64, None) else {
|
let Ok(v) = value.at(i as i64, None) else {
|
||||||
bail!(
|
bail!(wrong_number_of_elements(destruct, len));
|
||||||
pattern.span(), "not enough elements to destructure";
|
|
||||||
hint: "the provided array has a length of {len}",
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
destructure_impl(vm, pattern, v, f)?;
|
destructure_impl(vm, pattern, v, f)?;
|
||||||
i += 1;
|
i += 1;
|
||||||
@ -108,10 +107,7 @@ where
|
|||||||
let sink_size = (1 + len).checked_sub(destruct.items().count());
|
let sink_size = (1 + len).checked_sub(destruct.items().count());
|
||||||
let sink = sink_size.and_then(|s| value.as_slice().get(i..i + s));
|
let sink = sink_size.and_then(|s| value.as_slice().get(i..i + s));
|
||||||
let (Some(sink_size), Some(sink)) = (sink_size, sink) else {
|
let (Some(sink_size), Some(sink)) = (sink_size, sink) else {
|
||||||
bail!(
|
bail!(wrong_number_of_elements(destruct, len));
|
||||||
spread.span(), "not enough elements to destructure";
|
|
||||||
hint: "the provided array has a length of {len}",
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
if let Some(expr) = spread.sink_expr() {
|
if let Some(expr) = spread.sink_expr() {
|
||||||
f(vm, expr, Value::Array(sink.into()))?;
|
f(vm, expr, Value::Array(sink.into()))?;
|
||||||
@ -125,22 +121,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
if i < len {
|
if i < len {
|
||||||
if i == 0 {
|
bail!(wrong_number_of_elements(destruct, len));
|
||||||
bail!(
|
|
||||||
destruct.span(), "too many elements to destructure";
|
|
||||||
hint: "the provided array has a length of {len}, but the pattern expects an empty array",
|
|
||||||
)
|
|
||||||
} else if i == 1 {
|
|
||||||
bail!(
|
|
||||||
destruct.span(), "too many elements to destructure";
|
|
||||||
hint: "the provided array has a length of {len}, but the pattern expects a single element",
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
bail!(
|
|
||||||
destruct.span(), "too many elements to destructure";
|
|
||||||
hint: "the provided array has a length of {len}, but the pattern expects {i} elements",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -193,3 +174,36 @@ where
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The error message when the number of elements of the destructuring and the
|
||||||
|
/// array is mismatched.
|
||||||
|
#[cold]
|
||||||
|
fn wrong_number_of_elements(
|
||||||
|
destruct: ast::Destructuring,
|
||||||
|
len: usize,
|
||||||
|
) -> SourceDiagnostic {
|
||||||
|
let mut count = 0;
|
||||||
|
let mut spread = false;
|
||||||
|
|
||||||
|
for p in destruct.items() {
|
||||||
|
match p {
|
||||||
|
ast::DestructuringItem::Pattern(_) => count += 1,
|
||||||
|
ast::DestructuringItem::Spread(_) => spread = true,
|
||||||
|
ast::DestructuringItem::Named(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let quantifier = if len > count { "too many" } else { "not enough" };
|
||||||
|
let expected = match (spread, count) {
|
||||||
|
(true, c) => eco_format!("at least {c} elements"),
|
||||||
|
(false, 0) => "an empty array".into(),
|
||||||
|
(false, 1) => "a single element".into(),
|
||||||
|
(false, c) => eco_format!("{c} elements",),
|
||||||
|
};
|
||||||
|
|
||||||
|
error!(
|
||||||
|
destruct.span(), "{quantifier} elements to destructure";
|
||||||
|
hint: "the provided array has a length of {len}, \
|
||||||
|
but the pattern expects {expected}",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -128,13 +128,13 @@
|
|||||||
#let () = (1, 2)
|
#let () = (1, 2)
|
||||||
|
|
||||||
--- destructuring-let-array-too-few-elements ---
|
--- destructuring-let-array-too-few-elements ---
|
||||||
// Error: 13-14 not enough elements to destructure
|
// Error: 6-15 not enough elements to destructure
|
||||||
// Hint: 13-14 the provided array has a length of 2
|
// Hint: 6-15 the provided array has a length of 2, but the pattern expects 3 elements
|
||||||
#let (a, b, c) = (1, 2)
|
#let (a, b, c) = (1, 2)
|
||||||
|
|
||||||
--- destructuring-let-array-too-few-elements-with-sink ---
|
--- destructuring-let-array-too-few-elements-with-sink ---
|
||||||
// Error: 7-10 not enough elements to destructure
|
// Error: 6-20 not enough elements to destructure
|
||||||
// Hint: 7-10 the provided array has a length of 2
|
// Hint: 6-20 the provided array has a length of 2, but the pattern expects at least 3 elements
|
||||||
#let (..a, b, c, d) = (1, 2)
|
#let (..a, b, c, d) = (1, 2)
|
||||||
|
|
||||||
--- destructuring-let-array-bool-invalid ---
|
--- destructuring-let-array-bool-invalid ---
|
||||||
@ -192,8 +192,8 @@
|
|||||||
|
|
||||||
--- destructuring-let-array-trailing-placeholders ---
|
--- destructuring-let-array-trailing-placeholders ---
|
||||||
// Trailing placeholders.
|
// Trailing placeholders.
|
||||||
// Error: 10-11 not enough elements to destructure
|
// Error: 6-21 not enough elements to destructure
|
||||||
// Hint: 10-11 the provided array has a length of 1
|
// Hint: 6-21 the provided array has a length of 1, but the pattern expects 5 elements
|
||||||
#let (a, _, _, _, _) = (1,)
|
#let (a, _, _, _, _) = (1,)
|
||||||
#test(a, 1)
|
#test(a, 1)
|
||||||
|
|
||||||
@ -360,8 +360,8 @@
|
|||||||
#for (x, y) in (1, 2) {}
|
#for (x, y) in (1, 2) {}
|
||||||
|
|
||||||
--- issue-3275-destructuring-loop-over-2d-array-1 ---
|
--- issue-3275-destructuring-loop-over-2d-array-1 ---
|
||||||
// Error: 10-11 not enough elements to destructure
|
// Error: 6-12 not enough elements to destructure
|
||||||
// Hint: 10-11 the provided array has a length of 1
|
// Hint: 6-12 the provided array has a length of 1, but the pattern expects 2 elements
|
||||||
#for (x, y) in ((1,), (2,)) {}
|
#for (x, y) in ((1,), (2,)) {}
|
||||||
|
|
||||||
--- issue-3275-destructuring-loop-over-2d-array-2 ---
|
--- issue-3275-destructuring-loop-over-2d-array-2 ---
|
||||||
|
Loading…
x
Reference in New Issue
Block a user