From 2007f30b1137eec20678e3e9cd96788dc6c1b222 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Tue, 28 Nov 2023 18:54:51 +0100 Subject: [PATCH] Better error message for named instead of positional argument --- crates/typst/src/foundations/args.rs | 20 ++++++++++++++++++-- tests/typ/compiler/call.typ | 5 +++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/crates/typst/src/foundations/args.rs b/crates/typst/src/foundations/args.rs index 8732c7b50..74e8e2be2 100644 --- a/crates/typst/src/foundations/args.rs +++ b/crates/typst/src/foundations/args.rs @@ -2,7 +2,7 @@ use std::fmt::{self, Debug, Formatter}; use ecow::{eco_format, eco_vec, EcoString, EcoVec}; -use crate::diag::{bail, At, SourceDiagnostic, SourceResult}; +use crate::diag::{bail, error, At, SourceDiagnostic, SourceResult}; use crate::foundations::{ func, repr, scope, ty, Array, Dict, FromValue, IntoValue, Repr, Str, Value, }; @@ -121,10 +121,26 @@ impl Args { { match self.eat()? { Some(v) => Ok(v), - None => bail!(self.span, "missing argument: {what}"), + None => bail!(self.missing_argument(what)), } } + /// The error message for missing arguments. + fn missing_argument(&self, what: &str) -> SourceDiagnostic { + for item in &self.items { + let Some(name) = item.name.as_deref() else { continue }; + if name == what { + return error!( + item.span, + "the argument `{what}` is positional"; + hint: "try removing `{}:`", name, + ); + } + } + + error!(self.span, "missing argument: {what}") + } + /// Find and consume the first castable positional argument. pub fn find(&mut self) -> SourceResult> where diff --git a/tests/typ/compiler/call.typ b/tests/typ/compiler/call.typ index 5297ec159..e48eabfd7 100644 --- a/tests/typ/compiler/call.typ +++ b/tests/typ/compiler/call.typ @@ -47,6 +47,11 @@ // Error: 26-30 duplicate argument: font #set text(font: "Arial", font: "Helvetica") +--- +// Error: 4-15 the argument `amount` is positional +// Hint: 4-15 try removing `amount:` +#h(amount: 0.5) + --- // Error: 2-6 expected function, found boolean #true()