chore: improve messages for unexpected arguments

This commit is contained in:
Shunsuke Shibayama 2023-02-24 10:31:05 +09:00
parent 7c748f223a
commit 73a91dcbbb
4 changed files with 93 additions and 4 deletions

View file

@ -1347,6 +1347,7 @@ impl Context {
))
} else {
let unknown_arg_errors = unknown_args.into_iter().map(|arg| {
let similar = get_similar_name(subr_ty.param_names(), arg.keyword.inspect());
TyCheckError::unexpected_kw_arg_error(
self.cfg.input.clone(),
line!() as usize,
@ -1354,6 +1355,7 @@ impl Context {
&callee.to_string(),
self.caused_by(),
arg.keyword.inspect(),
similar,
)
});
let duplicated_arg_errors = duplicated_args.into_iter().map(|arg| {
@ -1541,6 +1543,7 @@ impl Context {
)
})?;
} else {
let similar = get_similar_name(subr_ty.param_names(), arg.keyword.inspect());
return Err(TyCheckErrors::from(TyCheckError::unexpected_kw_arg_error(
self.cfg.input.clone(),
line!() as usize,
@ -1548,6 +1551,7 @@ impl Context {
&callee.to_string(),
self.caused_by(),
kw_name,
similar,
)));
}
Ok(())

View file

@ -775,7 +775,23 @@ impl Context {
// contravariant
self.sub_unify(rpt.typ(), lpt.typ(), loc, param_name)?;
} else {
unreachable!()
let param_name = lpt.name().map_or("_", |s| &s[..]);
let similar_param = erg_common::levenshtein::get_similar_name(
rsub.default_params
.iter()
.map(|pt| pt.name().map_or("_", |s| &s[..])),
param_name,
);
return Err(TyCheckErrors::from(
TyCheckError::default_param_not_found_error(
self.cfg.input.clone(),
line!() as usize,
loc.loc(),
self.caused_by(),
param_name,
similar_param,
),
));
}
}
// covariant
@ -876,7 +892,15 @@ impl Context {
if let Some((_, sub_ty)) = sub_fields.get_key_value(&sup_field) {
self.sub_unify(sub_ty, &sup_ty, loc, param_name)?;
} else {
unreachable!()
return Err(TyCheckErrors::from(TyCheckError::no_attr_error(
self.cfg.input.clone(),
line!() as usize,
loc.loc(),
self.caused_by(),
sub,
&sup_field.symbol,
self.get_similar_attr(sub, &sup_field.symbol),
)));
}
}
Ok(())

View file

@ -363,6 +363,46 @@ impl TyCheckError {
)
}
pub fn default_param_not_found_error(
input: Input,
errno: usize,
loc: Location,
caused_by: String,
param_name: &str,
similar_name: Option<&str>,
) -> Self {
let hint = match similar_name {
Some(name) => {
let mut s = StyledStrings::default();
switch_lang!(
"japanese" => s.push_str("似た名前の引数があります: "),
"simplified_chinese" => s.push_str("相似的参数: "),
"traditional_chinese" => s.push_str("相似的參數: "),
"english" => s.push_str("exists a similar name parameter: "),
);
s.push_str_with_color_and_attribute(name, HINT, ATTR);
Some(s.to_string())
}
None => None,
};
Self::new(
ErrorCore::new(
vec![SubMessage::ambiguous_new(loc, vec![], hint)],
switch_lang!(
"japanese" => format!("{param_name}という名前のデフォルト引数はありません"),
"simplified_chinese" => format!("没有名为{param_name}的默认参数"),
"traditional_chinese" => format!("沒有名為{param_name}的預設參數"),
"english" => format!("there is no default parameter named {param_name}"),
),
errno,
TypeError,
loc,
),
input,
caused_by,
)
}
pub fn match_error(
input: Input,
errno: usize,
@ -540,14 +580,27 @@ passed keyword args: {kw_args_len}"
callee_name: &str,
caused_by: String,
param_name: &str,
similar_name: Option<&str>,
) -> Self {
let name = StyledStr::new(readable_name(callee_name), Some(WARN), Some(ATTR));
let found = StyledString::new(param_name, Some(ERR), Some(ATTR));
let hint = match similar_name {
Some(similar_name) => {
let similar_name = StyledString::new(similar_name, Some(HINT), Some(ATTR));
Some(switch_lang!(
"japanese" => format!("似た名前の引数があります: {similar_name}"),
"simplified_chinese" => format!("有相似的关参数: {similar_name}"),
"traditional_chinese" => format!("有相似的關參數: {similar_name}"),
"english" => format!("exists a similar name parameter: {similar_name}"),
))
}
None => None,
};
Self::new(
ErrorCore::new(
vec![SubMessage::only_loc(loc)],
vec![SubMessage::ambiguous_new(loc, vec![], hint)],
switch_lang!(
"japanese" => format!("{name}には予期しないキーワード引数{found}が渡されています"),
"japanese" => format!("{name}予期しないキーワード引数{found}が渡されています"),
"simplified_chinese" => format!("{name}得到了意外的关键字参数{found}"),
"traditional_chinese" => format!("{name}得到了意外的關鍵字參數{found}"),
"english" => format!("{name} got unexpected keyword argument {found}"),

View file

@ -463,6 +463,14 @@ impl SubrType {
.chain(self.default_params.iter())
}
}
pub fn param_names(&self) -> impl Iterator<Item = &str> + Clone {
self.non_default_params
.iter()
.chain(self.var_params.as_deref().into_iter())
.chain(self.default_params.iter())
.map(|pt| pt.name().map_or("_", |s| &s[..]))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]