difftreelog
feat(evaluator) function signature help
in: master
When calling functions with wrong arguments, evaluator will now suggest correct function signature
2 files changed
crates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth32 out32 out33}33}3435fn format_signature(sig: &FunctionSignature) -> String {36 let mut out = String::new();37 out.push_str("\nFunction has the following signature: ");38 out.push('(');39 if sig.is_empty() {40 out.push_str("/*no arguments*/");41 } else {42 for (i, (name, has_default)) in sig.iter().enumerate() {43 if i != 0 {44 out.push_str(", ");45 }46 if let Some(name) = name {47 out.push_str(name);48 } else {49 out.push_str("<unnamed>");50 }51 if *has_default {52 out.push_str(" = <default>");53 }54 }55 }56 out.push(')');57 out58}345935const fn format_empty_str(str: &str) -> &str {60const fn format_empty_str(str: &str) -> &str {36 if str.is_empty() {61 if str.is_empty() {40 }65 }41}66}6768type FunctionSignature = Vec<(Option<IStr>, bool)>;426943#[derive(Error, Debug, Clone, Trace)]70#[derive(Error, Debug, Clone, Trace)]44pub enum Error {71pub enum Error {84 UnknownFunctionParameter(String),111 UnknownFunctionParameter(String),85 #[error("argument {0} is already bound")]112 #[error("argument {0} is already bound")]86 BindingParameterASecondTime(IStr),113 BindingParameterASecondTime(IStr),87 #[error("too many args, function has {0}")]114 #[error("too many args, function has {0}{}", format_signature(.1))]88 TooManyArgsFunctionHas(usize),115 TooManyArgsFunctionHas(usize, FunctionSignature),89 #[error("function argument is not passed: {0}")]116 #[error("function argument is not passed: {0}{}", format_signature(.1))]90 FunctionParameterNotBoundInCall(IStr),117 FunctionParameterNotBoundInCall(IStr, FunctionSignature),9111892 #[error("external variable is not defined: {0}")]119 #[error("external variable is not defined: {0}")]93 UndefinedExternalVariable(IStr),120 UndefinedExternalVariable(IStr),crates/jrsonnet-evaluator/src/function/parse.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/function/parse.rs
+++ b/crates/jrsonnet-evaluator/src/function/parse.rs
@@ -48,7 +48,10 @@
) -> Result<Context> {
let mut passed_args = GcHashMap::with_capacity(params.len());
if args.unnamed_len() > params.len() {
- throw!(TooManyArgsFunctionHas(params.len()))
+ throw!(TooManyArgsFunctionHas(
+ params.len(),
+ params.iter().map(|p| (p.0.name(), p.1.is_some())).collect()
+ ))
}
let mut filled_named = 0;
@@ -126,7 +129,8 @@
.0
.clone()
.name()
- .unwrap_or_else(|| "<destruct>".into())
+ .unwrap_or_else(|| "<destruct>".into()),
+ params.iter().map(|p| (p.0.name(), p.1.is_some())).collect()
));
}
}
@@ -159,7 +163,13 @@
) -> Result<GcHashMap<BuiltinParamName, Thunk<Val>>> {
let mut passed_args = GcHashMap::with_capacity(params.len());
if args.unnamed_len() > params.len() {
- throw!(TooManyArgsFunctionHas(params.len()))
+ throw!(TooManyArgsFunctionHas(
+ params.len(),
+ params
+ .iter()
+ .map(|p| (Some(p.name.as_ref().into()), p.has_default))
+ .collect()
+ ))
}
let mut filled_args = 0;
@@ -202,7 +212,13 @@
}
});
if !found {
- throw!(FunctionParameterNotBoundInCall(param.name.clone().into()));
+ throw!(FunctionParameterNotBoundInCall(
+ param.name.clone().into(),
+ params
+ .iter()
+ .map(|p| (Some(p.name.as_ref().into()), p.has_default))
+ .collect()
+ ));
}
}
unreachable!();
@@ -215,11 +231,15 @@
/// and with unbound values causing error to be returned
pub fn parse_default_function_call(body_ctx: Context, params: &ParamsDesc) -> Result<Context> {
#[derive(Trace)]
- struct DependsOnUnbound(IStr);
+ struct DependsOnUnbound(IStr, ParamsDesc);
impl ThunkValue for DependsOnUnbound {
type Output = Val;
fn get(self: Box<Self>, _: State) -> Result<Val> {
- Err(FunctionParameterNotBoundInCall(self.0.clone()).into())
+ Err(FunctionParameterNotBoundInCall(
+ self.0.clone(),
+ self.1.iter().map(|p| (p.0.name(), p.1.is_some())).collect(),
+ )
+ .into())
}
}
@@ -243,7 +263,8 @@
destruct(
¶m.0,
Thunk::new(tb!(DependsOnUnbound(
- param.0.name().unwrap_or_else(|| "<destruct>".into())
+ param.0.name().unwrap_or_else(|| "<destruct>".into()),
+ params.clone()
))),
fctx.clone(),
&mut bindings,