Merge pull request #232 from erg-lang/split-err-msg

Split error messages
This commit is contained in:
Shunsuke Shibayama 2022-11-23 15:55:19 +09:00 committed by GitHub
commit 2caa6b6ec9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 1652 additions and 1006 deletions

View file

@ -4,8 +4,10 @@
use std::fmt;
use erg_common::config::Input;
use erg_common::error::{ErrorCore, ErrorDisplay, ErrorKind::*, Location, MultiErrorDisplay};
use erg_common::style::{Attribute, Color, StyledStr, StyledString, Theme};
use erg_common::error::{
ErrorCore, ErrorDisplay, ErrorKind::*, Location, MultiErrorDisplay, SubMessage,
};
use erg_common::style::{Attribute, Color, StyledStr, StyledString, THEME};
use erg_common::traits::Stream;
use erg_common::{impl_display_and_error, impl_stream_for_wrapper, switch_lang};
@ -29,62 +31,68 @@ pub struct LexErrors(Vec<LexError>);
impl_stream_for_wrapper!(LexErrors, LexError);
const ERR: Color = THEME.colors.error;
const HINT: Color = THEME.colors.hint;
const ACCENT: Color = THEME.colors.accent;
impl LexError {
pub fn new(core: ErrorCore) -> Self {
Self(Box::new(core))
}
pub fn set_hint<S: Into<String>>(&mut self, hint: S) {
self.0.hint = Some(hint.into());
if let Some(sub_msg) = self.0.sub_messages.get_mut(0) {
sub_msg.set_hint(hint)
}
}
pub fn compiler_bug(errno: usize, loc: Location, fn_name: &str, line: u32) -> Self {
const URL: StyledStr = StyledStr::new(
"https://github.com/erg-lang/erg",
Some(Color::White),
Some(ACCENT),
Some(Attribute::Underline),
);
Self::new(ErrorCore::new(
errno,
CompilerSystemError,
loc,
vec![SubMessage::only_loc(loc)],
switch_lang!(
"japanese" => format!("これはErg compilerのバグです、開発者に報告して下さい ({URL})\n{fn_name}:{line}より発生"),
"simplified_chinese" => format!("这是Erg编译器的一个错误请报告给{URL}\n原因来自: {fn_name}:{line}"),
"traditional_chinese" => format!("這是Erg編譯器的一個錯誤請報告給{URL}\n原因來自: {fn_name}:{line}"),
"english" => format!("this is a bug of the Erg compiler, please report it to {URL}\ncaused from: {fn_name}:{line}"),
),
None,
errno,
CompilerSystemError,
loc,
))
}
pub fn feature_error(errno: usize, loc: Location, name: &str) -> Self {
Self::new(ErrorCore::new(
errno,
FeatureError,
loc,
vec![SubMessage::only_loc(loc)],
switch_lang!(
"japanese" => format!("この機能({name})はまだ正式に提供されていません"),
"simplified_chinese" => format!("此功能({name})尚未实现"),
"traditional_chinese" => format!("此功能({name})尚未實現"),
"english" => format!("this feature({name}) is not implemented yet"),
),
None,
errno,
FeatureError,
loc,
))
}
pub fn simple_syntax_error(errno: usize, loc: Location) -> Self {
Self::new(ErrorCore::new(
errno,
SyntaxError,
loc,
vec![SubMessage::only_loc(loc)],
switch_lang!(
"japanese" => "不正な構文です",
"simplified_chinese" => "无效的语法",
"traditional_chinese" => "無效的語法",
"english" => "invalid syntax",
),
None,
errno,
SyntaxError,
loc,
))
}
@ -94,7 +102,13 @@ impl LexError {
desc: S,
hint: Option<String>,
) -> Self {
Self::new(ErrorCore::new(errno, SyntaxError, loc, desc, hint))
Self::new(ErrorCore::new(
vec![SubMessage::ambiguous_new(loc, vec![], hint)],
desc,
errno,
SyntaxError,
loc,
))
}
pub fn syntax_warning<S: Into<String>>(
@ -103,7 +117,13 @@ impl LexError {
desc: S,
hint: Option<String>,
) -> Self {
Self::new(ErrorCore::new(errno, SyntaxWarning, loc, desc, hint))
Self::new(ErrorCore::new(
vec![SubMessage::ambiguous_new(loc, vec![], hint)],
desc,
errno,
SyntaxWarning,
loc,
))
}
pub fn no_var_error(
@ -113,6 +133,7 @@ impl LexError {
similar_name: Option<String>,
) -> Self {
let hint = similar_name.map(|n| {
let n = StyledString::new(&n, Some(HINT), Some(Attribute::Bold));
switch_lang!(
"japanese" => format!("似た名前の変数があります: {n}"),
"simplified_chinese" => format!("存在相同名称变量: {n}"),
@ -120,18 +141,18 @@ impl LexError {
"english" => format!("exists a similar name variable: {n}"),
)
});
let name = StyledString::new(name, Some(Color::Red), Some(Attribute::Underline));
let name = StyledString::new(name, Some(ERR), Some(Attribute::Underline));
Self::new(ErrorCore::new(
errno,
NameError,
loc,
vec![SubMessage::ambiguous_new(loc, vec![], hint)],
switch_lang!(
"japanese" => format!("{name}という変数は定義されていません"),
"simplified_chinese" => format!("{name}未定义"),
"traditional_chinese" => format!("{name}未定義"),
"english" => format!("{name} is not defined"),
),
hint,
errno,
NameError,
loc,
))
}
}
@ -164,7 +185,6 @@ pub type DesugaringResult<T> = Result<T, DesugaringError>;
pub struct ParserRunnerError {
pub core: ErrorCore,
pub input: Input,
pub theme: Theme,
}
impl_display_and_error!(ParserRunnerError);
@ -176,9 +196,6 @@ impl ErrorDisplay for ParserRunnerError {
fn input(&self) -> &Input {
&self.input
}
fn theme(&self) -> &Theme {
&self.theme
}
fn caused_by(&self) -> &str {
""
}
@ -188,8 +205,8 @@ impl ErrorDisplay for ParserRunnerError {
}
impl ParserRunnerError {
pub const fn new(core: ErrorCore, input: Input, theme: Theme) -> Self {
Self { core, input, theme }
pub const fn new(core: ErrorCore, input: Input) -> Self {
Self { core, input }
}
}
@ -209,10 +226,10 @@ impl fmt::Display for ParserRunnerErrors {
}
impl ParserRunnerErrors {
pub fn convert(input: &Input, errs: ParseErrors, theme: Theme) -> Self {
pub fn convert(input: &Input, errs: ParseErrors) -> Self {
Self(
errs.into_iter()
.map(|err| ParserRunnerError::new(*err.0, input.clone(), theme))
.map(|err| ParserRunnerError::new(*err.0, input.clone()))
.collect(),
)
}

View file

@ -4,7 +4,6 @@ use std::cmp::Ordering;
use erg_common::cache::CacheSet;
use erg_common::config::ErgConfig;
use erg_common::config::Input;
use erg_common::style::THEME;
use erg_common::traits::{Locational, Runnable, Stream};
use erg_common::{debug_power_assert, fn_name_full, normalize_newline, switch_lang};
@ -43,7 +42,7 @@ impl Runnable for LexerRunner {
let lexer = Lexer::from_str(self.input().read());
let ts = lexer
.lex()
.map_err(|errs| LexerRunnerErrors::convert(self.input(), errs, THEME))?;
.map_err(|errs| LexerRunnerErrors::convert(self.input(), errs))?;
println!("{ts}");
Ok(0)
}
@ -53,13 +52,13 @@ impl Runnable for LexerRunner {
if cfg!(feature = "debug") {
let ts = lexer
.lex()
.map_err(|errs| LexerRunnerErrors::convert(self.input(), errs, THEME))?;
.map_err(|errs| LexerRunnerErrors::convert(self.input(), errs))?;
println!("{ts}");
Ok(ts.to_string())
} else {
Ok(lexer
.lex()
.map_err(|errs| LexerRunnerErrors::convert(self.input(), errs, THEME))?
.map_err(|errs| LexerRunnerErrors::convert(self.input(), errs))?
.to_string())
}
}

View file

@ -11,7 +11,6 @@ use erg_common::error::Location;
use erg_common::option_enum_unwrap;
use erg_common::set::Set as HashSet;
use erg_common::str::Str;
use erg_common::style::THEME;
use erg_common::traits::Runnable;
use erg_common::traits::{Locational, Stream};
use erg_common::{
@ -207,16 +206,16 @@ impl ParserRunner {
pub fn parse_token_stream(&mut self, ts: TokenStream) -> Result<Module, ParserRunnerErrors> {
Parser::new(ts)
.parse()
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs, THEME))
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))
}
pub fn parse(&mut self, src: String) -> Result<Module, ParserRunnerErrors> {
let ts = Lexer::new(Input::Str(src))
.lex()
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs, THEME))?;
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))?;
Parser::new(ts)
.parse()
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs, THEME))
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))
}
}

View file

@ -1,6 +1,5 @@
use erg_common::config::{ErgConfig, Input};
use erg_common::error::MultiErrorDisplay;
use erg_common::style::THEME;
use erg_common::traits::Runnable;
use erg_parser::error::ParserRunnerErrors;
@ -64,7 +63,7 @@ fn parse_test_from_code(file_path: &'static str) -> Result<(), ParserRunnerError
match parser.parse_token_stream(
lexer
.lex()
.map_err(|errs| ParserRunnerErrors::convert(&input, errs, THEME))?,
.map_err(|errs| ParserRunnerErrors::convert(&input, errs))?,
) {
Ok(module) => {
println!("{module}");