mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-30 12:51:10 +00:00
Merge pull request #232 from erg-lang/split-err-msg
Split error messages
This commit is contained in:
commit
2caa6b6ec9
15 changed files with 1652 additions and 1006 deletions
|
@ -241,7 +241,8 @@ impl Context {
|
|||
match subr {
|
||||
ConstSubr::User(_user) => todo!(),
|
||||
ConstSubr::Builtin(builtin) => builtin.call(args, self).map_err(|mut e| {
|
||||
e.0.loc = loc;
|
||||
// TODO: Is it possible to get 0?
|
||||
e.0.sub_messages.get_mut(0).unwrap().loc = loc;
|
||||
EvalErrors::from(EvalError::new(
|
||||
*e.0,
|
||||
self.cfg.input.clone(),
|
||||
|
|
|
@ -6,29 +6,39 @@ use crate::context::Context;
|
|||
use crate::ty::constructors::{and, mono};
|
||||
use crate::ty::value::{EvalValueResult, GenTypeObj, TypeObj, ValueObj};
|
||||
use crate::ty::ValueArgs;
|
||||
use erg_common::error::{ErrorCore, ErrorKind, Location};
|
||||
use erg_common::style::{RED, RESET, YELLOW};
|
||||
use erg_common::error::{ErrorCore, ErrorKind, Location, SubMessage};
|
||||
use erg_common::style::{Color, StyledStr, StyledString, THEME};
|
||||
|
||||
const ERR: Color = THEME.colors.error;
|
||||
const WARN: Color = THEME.colors.warning;
|
||||
|
||||
const SUP_ERR: StyledStr = StyledStr::new("Super", Some(ERR), None);
|
||||
const SUP_WARN: StyledStr = StyledStr::new("Super", Some(WARN), None);
|
||||
const CLASS_ERR: StyledStr = StyledStr::new("Class", Some(ERR), None);
|
||||
const REQ_ERR: StyledStr = StyledStr::new("Requirement", Some(ERR), None);
|
||||
const REQ_WARN: StyledStr = StyledStr::new("Requirement", Some(WARN), None);
|
||||
|
||||
/// Requirement: Type, Impl := Type -> ClassType
|
||||
pub fn class_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueObj> {
|
||||
let require = args.remove_left_or_key("Requirement").ok_or_else(|| {
|
||||
ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!("{REQ_ERR} is not passed"),
|
||||
line!() as usize,
|
||||
ErrorKind::TypeError,
|
||||
Location::Unknown,
|
||||
format!("{RED}Requirement{RESET} is not passed"),
|
||||
None,
|
||||
)
|
||||
})?;
|
||||
let Some(require) = require.as_type() else {
|
||||
let require = StyledString::new(&format!("{}", require), Some(ERR), None);
|
||||
return Err(ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!(
|
||||
"non-type object {require} is passed to {REQ_WARN}",
|
||||
),
|
||||
line!() as usize,
|
||||
ErrorKind::TypeError,
|
||||
Location::Unknown,
|
||||
format!(
|
||||
"non-type object {RED}{require}{RESET} is passed to {YELLOW}Requirement{RESET}",
|
||||
),
|
||||
None,
|
||||
).into());
|
||||
};
|
||||
let impls = args.remove_left_or_key("Impl");
|
||||
|
@ -40,23 +50,25 @@ pub fn class_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueOb
|
|||
/// Super: ClassType, Impl := Type, Additional := Type -> ClassType
|
||||
pub fn inherit_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueObj> {
|
||||
let sup = args.remove_left_or_key("Super").ok_or_else(|| {
|
||||
let sup = StyledStr::new("Super", Some(ERR), None);
|
||||
ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!("{sup} is not passed"),
|
||||
line!() as usize,
|
||||
ErrorKind::KeyError,
|
||||
Location::Unknown,
|
||||
format!("{RED}Super{RESET} is not passed"),
|
||||
None,
|
||||
)
|
||||
})?;
|
||||
let Some(sup) = sup.as_type() else {
|
||||
let sup_ty = StyledString::new(&format!("{}", sup), Some(ERR), None);
|
||||
return Err(ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!(
|
||||
"non-class object {sup_ty} is passed to {SUP_WARN}",
|
||||
),
|
||||
line!() as usize,
|
||||
ErrorKind::TypeError,
|
||||
Location::Unknown,
|
||||
format!(
|
||||
"non-class object {RED}{sup}{RESET} is passed to {YELLOW}Super{RESET}",
|
||||
),
|
||||
None,
|
||||
).into());
|
||||
};
|
||||
let impls = args.remove_left_or_key("Impl");
|
||||
|
@ -74,11 +86,11 @@ pub fn inherit_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<Value
|
|||
pub fn inheritable_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<ValueObj> {
|
||||
let class = args.remove_left_or_key("Class").ok_or_else(|| {
|
||||
ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!("{CLASS_ERR} is not passed"),
|
||||
line!() as usize,
|
||||
ErrorKind::KeyError,
|
||||
Location::Unknown,
|
||||
format!("{RED}Class{RESET} is not passed"),
|
||||
None,
|
||||
)
|
||||
})?;
|
||||
match class {
|
||||
|
@ -106,22 +118,23 @@ pub fn inheritable_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<
|
|||
pub fn trait_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueObj> {
|
||||
let require = args.remove_left_or_key("Requirement").ok_or_else(|| {
|
||||
ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!("{REQ_ERR} is not passed"),
|
||||
line!() as usize,
|
||||
ErrorKind::KeyError,
|
||||
Location::Unknown,
|
||||
format!("{RED}Requirement{RESET} is not passed"),
|
||||
None,
|
||||
)
|
||||
})?;
|
||||
let Some(require) = require.as_type() else {
|
||||
let require = StyledString::new(&format!("{}", require), Some(ERR), None);
|
||||
return Err(ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!(
|
||||
"non-type object {require} is passed to {REQ_WARN}",
|
||||
),
|
||||
line!() as usize,
|
||||
ErrorKind::TypeError,
|
||||
Location::Unknown,
|
||||
format!(
|
||||
"non-type object {RED}{require}{RESET} is passed to {YELLOW}Requirement{RESET}",
|
||||
),
|
||||
None,
|
||||
).into());
|
||||
};
|
||||
let impls = args.remove_left_or_key("Impl");
|
||||
|
@ -134,22 +147,23 @@ pub fn trait_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueOb
|
|||
pub fn subsume_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueObj> {
|
||||
let sup = args.remove_left_or_key("Super").ok_or_else(|| {
|
||||
ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!("{SUP_ERR} is not passed"),
|
||||
line!() as usize,
|
||||
ErrorKind::KeyError,
|
||||
Location::Unknown,
|
||||
format!("{RED}Super{RESET} is not passed"),
|
||||
None,
|
||||
)
|
||||
})?;
|
||||
let Some(sup) = sup.as_type() else {
|
||||
let sup = StyledString::new(&format!("{}", sup), Some(ERR), None);
|
||||
return Err(ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!(
|
||||
"non-trait object {sup} is passed to {SUP_WARN}",
|
||||
),
|
||||
line!() as usize,
|
||||
ErrorKind::TypeError,
|
||||
Location::Unknown,
|
||||
format!(
|
||||
"non-trait object {RED}{sup}{RESET} is passed to {YELLOW}Super{RESET}",
|
||||
),
|
||||
None,
|
||||
).into());
|
||||
};
|
||||
let impls = args.remove_left_or_key("Impl");
|
||||
|
@ -171,16 +185,16 @@ pub fn __array_getitem__(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<
|
|||
Ok(v.clone())
|
||||
} else {
|
||||
Err(ErrorCore::new(
|
||||
line!() as usize,
|
||||
ErrorKind::IndexError,
|
||||
Location::Unknown,
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!(
|
||||
"[{}] has {} elements, but accessed {}th element",
|
||||
erg_common::fmt_vec(&slf),
|
||||
slf.len(),
|
||||
index
|
||||
),
|
||||
None,
|
||||
line!() as usize,
|
||||
ErrorKind::IndexError,
|
||||
Location::Unknown,
|
||||
)
|
||||
.into())
|
||||
}
|
||||
|
@ -210,11 +224,11 @@ pub fn __dict_getitem__(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<V
|
|||
Ok(v.clone())
|
||||
} else {
|
||||
Err(ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!("{slf} has no key {index}"),
|
||||
line!() as usize,
|
||||
ErrorKind::IndexError,
|
||||
Location::Unknown,
|
||||
format!("{slf} has no key {index}"),
|
||||
None,
|
||||
)
|
||||
.into())
|
||||
}
|
||||
|
@ -235,11 +249,11 @@ pub fn __range_getitem__(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult
|
|||
Ok(ValueObj::Nat(start + index))
|
||||
} else {
|
||||
Err(ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!("Index out of range: {}", index),
|
||||
line!() as usize,
|
||||
ErrorKind::IndexError,
|
||||
Location::Unknown,
|
||||
format!("Index out of range: {index}"),
|
||||
None,
|
||||
)
|
||||
.into())
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::path::{Path, PathBuf};
|
|||
|
||||
use erg_common::config::Input;
|
||||
use erg_common::env::erg_pystd_path;
|
||||
use erg_common::error::{ErrorCore, ErrorKind, Location};
|
||||
use erg_common::error::{ErrorCore, ErrorKind, Location, SubMessage};
|
||||
use erg_common::levenshtein::get_similar_name;
|
||||
use erg_common::set::Set;
|
||||
use erg_common::traits::{Locational, Stream};
|
||||
|
@ -756,13 +756,21 @@ impl Context {
|
|||
TyCheckErrors::new(
|
||||
errs.into_iter()
|
||||
.map(|e| {
|
||||
// HACK: dname.loc()はダミーLocationしか返さないので、エラーならop.loc()で上書きする
|
||||
let mut sub_msges = Vec::new();
|
||||
for sub_msg in e.core.sub_messages {
|
||||
sub_msges.push(SubMessage::ambiguous_new(
|
||||
// HACK: dname.loc()はダミーLocationしか返さないので、エラーならop.loc()で上書きする
|
||||
bin.loc(),
|
||||
vec![],
|
||||
sub_msg.get_hint(),
|
||||
));
|
||||
}
|
||||
let core = ErrorCore::new(
|
||||
sub_msges,
|
||||
e.core.main_message,
|
||||
e.core.errno,
|
||||
e.core.kind,
|
||||
bin.loc(),
|
||||
e.core.desc,
|
||||
e.core.hint,
|
||||
e.core.loc,
|
||||
);
|
||||
TyCheckError::new(core, self.cfg.input.clone(), e.caused_by)
|
||||
})
|
||||
|
@ -797,12 +805,20 @@ impl Context {
|
|||
TyCheckErrors::new(
|
||||
errs.into_iter()
|
||||
.map(|e| {
|
||||
let mut sub_msges = Vec::new();
|
||||
for sub_msg in e.core.sub_messages {
|
||||
sub_msges.push(SubMessage::ambiguous_new(
|
||||
unary.loc(),
|
||||
vec![],
|
||||
sub_msg.get_hint(),
|
||||
));
|
||||
}
|
||||
let core = ErrorCore::new(
|
||||
sub_msges,
|
||||
e.core.main_message,
|
||||
e.core.errno,
|
||||
e.core.kind,
|
||||
unary.loc(),
|
||||
e.core.desc,
|
||||
e.core.hint,
|
||||
e.core.loc,
|
||||
);
|
||||
TyCheckError::new(core, self.cfg.input.clone(), e.caused_by)
|
||||
})
|
||||
|
@ -1052,7 +1068,8 @@ impl Context {
|
|||
TyCheckError::type_mismatch_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
e.core.loc,
|
||||
// TODO: Is it possible to get 0?
|
||||
e.core.sub_messages.get(0).unwrap().loc,
|
||||
e.caused_by,
|
||||
&name[..],
|
||||
Some(nth),
|
||||
|
@ -1107,7 +1124,8 @@ impl Context {
|
|||
TyCheckError::type_mismatch_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
e.core.loc,
|
||||
// TODO: Is it possible to get 0?
|
||||
e.core.sub_messages.get(0).unwrap().loc,
|
||||
e.caused_by,
|
||||
&name[..],
|
||||
Some(nth),
|
||||
|
@ -1164,7 +1182,8 @@ impl Context {
|
|||
TyCheckError::type_mismatch_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
e.core.loc,
|
||||
// TODO: Is it possible to get 0?
|
||||
e.core.sub_messages.get(0).unwrap().loc,
|
||||
e.caused_by,
|
||||
&name[..],
|
||||
Some(nth),
|
||||
|
|
|
@ -416,7 +416,8 @@ impl Context {
|
|||
TyCheckError::return_type_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
e.core.loc,
|
||||
// TODO: is it possible to get 0?
|
||||
e.core.sub_messages.get(0).unwrap().loc,
|
||||
e.caused_by,
|
||||
readable_name(name.inspect()),
|
||||
spec_ret_t,
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -191,7 +191,7 @@ impl ASTLowerer {
|
|||
"traditional_chinese" => "如果您不想使用該值,請使用discard函數",
|
||||
"english" => "if you don't use the value, use discard function",
|
||||
)
|
||||
.into(),
|
||||
.to_owned(),
|
||||
),
|
||||
))
|
||||
} else {
|
||||
|
@ -266,7 +266,8 @@ impl ASTLowerer {
|
|||
"simplified_chinese" => "数组元素必须全部是相同类型",
|
||||
"traditional_chinese" => "數組元素必須全部是相同類型",
|
||||
"english" => "all elements of an array must be of the same type",
|
||||
),
|
||||
)
|
||||
.to_owned(),
|
||||
Some(
|
||||
switch_lang!(
|
||||
"japanese" => "Int or Strなど明示的に型を指定してください",
|
||||
|
@ -274,7 +275,7 @@ impl ASTLowerer {
|
|||
"traditional_chinese" => "請明確指定類型,例如: Int or Str",
|
||||
"english" => "please specify the type explicitly, e.g. Int or Str",
|
||||
)
|
||||
.into(),
|
||||
.to_owned(),
|
||||
),
|
||||
)));
|
||||
}
|
||||
|
@ -412,7 +413,8 @@ impl ASTLowerer {
|
|||
"simplified_chinese" => "集合元素必须全部是相同类型",
|
||||
"traditional_chinese" => "集合元素必須全部是相同類型",
|
||||
"english" => "all elements of a set must be of the same type",
|
||||
),
|
||||
)
|
||||
.to_owned(),
|
||||
Some(
|
||||
switch_lang!(
|
||||
"japanese" => "Int or Strなど明示的に型を指定してください",
|
||||
|
@ -420,7 +422,7 @@ impl ASTLowerer {
|
|||
"traditional_chinese" => "明確指定類型,例如: Int or Str",
|
||||
"english" => "please specify the type explicitly, e.g. Int or Str",
|
||||
)
|
||||
.into(),
|
||||
.to_owned(),
|
||||
),
|
||||
)));
|
||||
}
|
||||
|
@ -538,7 +540,8 @@ impl ASTLowerer {
|
|||
"simplified_chinese" => "Dict的值必须是同一类型",
|
||||
"traditional_chinese" => "Dict的值必須是同一類型",
|
||||
"english" => "Values of Dict must be the same type",
|
||||
),
|
||||
)
|
||||
.to_owned(),
|
||||
Some(
|
||||
switch_lang!(
|
||||
"japanese" => "Int or Strなど明示的に型を指定してください",
|
||||
|
@ -546,7 +549,7 @@ impl ASTLowerer {
|
|||
"traditional_chinese" => "明確指定類型,例如: Int or Str",
|
||||
"english" => "please specify the type explicitly, e.g. Int or Str",
|
||||
)
|
||||
.into(),
|
||||
.to_owned(),
|
||||
),
|
||||
)));
|
||||
}
|
||||
|
@ -692,7 +695,7 @@ impl ASTLowerer {
|
|||
line!() as usize,
|
||||
call.args.loc(),
|
||||
self.ctx.caused_by(),
|
||||
"invalid assert casting type",
|
||||
"invalid assert casting type".to_owned(),
|
||||
None,
|
||||
)));
|
||||
}
|
||||
|
@ -751,7 +754,7 @@ impl ASTLowerer {
|
|||
line!() as usize,
|
||||
other.loc(),
|
||||
self.ctx.caused_by(),
|
||||
"",
|
||||
"".to_owned(),
|
||||
None,
|
||||
)))
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::string::FromUtf8Error;
|
|||
use erg_common::cache::CacheSet;
|
||||
use erg_common::config::{ErgConfig, Input};
|
||||
use erg_common::dict::Dict;
|
||||
use erg_common::error::{ErrorCore, ErrorKind, Location};
|
||||
use erg_common::error::{ErrorCore, ErrorKind, Location, SubMessage};
|
||||
use erg_common::python_util::PythonVersion;
|
||||
use erg_common::serialize::DataTypePrefix;
|
||||
use erg_common::{fn_name, switch_lang};
|
||||
|
@ -39,11 +39,11 @@ impl From<FromUtf8Error> for DeserializeError {
|
|||
impl From<DeserializeError> for ErrorCore {
|
||||
fn from(err: DeserializeError) -> Self {
|
||||
ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
err.desc,
|
||||
err.errno,
|
||||
ErrorKind::ImportError,
|
||||
Location::Unknown,
|
||||
err.desc,
|
||||
Option::<String>::None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue