diff --git a/crates/erg_common/build.rs b/crates/erg_common/build.rs index 58a103f77..5793c006a 100644 --- a/crates/erg_common/build.rs +++ b/crates/erg_common/build.rs @@ -27,6 +27,6 @@ fn main() -> std::io::Result<()> { } else { true }; - println!("cargo:rustc-env=CASE_SENSITIVE={}", case_sensitive); + println!("cargo:rustc-env=CASE_SENSITIVE={case_sensitive}"); Ok(()) } diff --git a/crates/erg_compiler/hir.rs b/crates/erg_compiler/hir.rs index a5ab30642..8710b38dd 100644 --- a/crates/erg_compiler/hir.rs +++ b/crates/erg_compiler/hir.rs @@ -1982,8 +1982,8 @@ pub enum GuardClause { impl NestedDisplay for GuardClause { fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result { match self { - GuardClause::Condition(cond) => write!(f, "{}", cond), - GuardClause::Bind(bind) => write!(f, "{}", bind), + GuardClause::Condition(cond) => write!(f, "{cond}"), + GuardClause::Bind(bind) => write!(f, "{bind}"), } } } diff --git a/crates/erg_compiler/ty/codeobj.rs b/crates/erg_compiler/ty/codeobj.rs index 238fa581f..b2a76c6dd 100644 --- a/crates/erg_compiler/ty/codeobj.rs +++ b/crates/erg_compiler/ty/codeobj.rs @@ -642,14 +642,14 @@ impl CodeObj { write!(instrs, "{arg} ({})", self.cellvars[arg]).unwrap(); } Opcode308::JUMP_ABSOLUTE => { - write!(instrs, "{arg} (to {})", arg).unwrap(); + write!(instrs, "{arg} (to {arg})").unwrap(); } Opcode308::JUMP_FORWARD => { write!(instrs, "{arg} (to {})", idx + arg + 2).unwrap(); } // REVIEW: *2? Opcode308::POP_JUMP_IF_FALSE | Opcode308::POP_JUMP_IF_TRUE => { - write!(instrs, "{arg} (to {})", arg).unwrap(); + write!(instrs, "{arg} (to {arg})").unwrap(); } Opcode308::BINARY_ADD | Opcode308::BINARY_SUBTRACT @@ -690,14 +690,14 @@ impl CodeObj { write!(instrs, "{arg} ({})", self.cellvars[arg]).unwrap(); } Opcode309::JUMP_ABSOLUTE => { - write!(instrs, "{arg} (to {})", arg).unwrap(); + write!(instrs, "{arg} (to {arg})").unwrap(); } Opcode309::JUMP_FORWARD => { write!(instrs, "{arg} (to {})", idx + arg + 2).unwrap(); } // REVIEW: *2? Opcode309::POP_JUMP_IF_FALSE | Opcode309::POP_JUMP_IF_TRUE => { - write!(instrs, "{arg} (to {})", arg).unwrap(); + write!(instrs, "{arg} (to {arg})").unwrap(); } Opcode309::BINARY_ADD | Opcode309::BINARY_SUBTRACT diff --git a/crates/erg_compiler/ty/constructors.rs b/crates/erg_compiler/ty/constructors.rs index 5f2dc35f0..ddf5bc479 100644 --- a/crates/erg_compiler/ty/constructors.rs +++ b/crates/erg_compiler/ty/constructors.rs @@ -183,12 +183,12 @@ pub fn try_v_enum(s: Set) -> Result> { } pub fn v_enum(s: Set) -> Type { - try_v_enum(s).unwrap_or_else(|set| panic!("not homogeneous: {}", set)) + try_v_enum(s).unwrap_or_else(|set| panic!("not homogeneous: {set}")) } pub fn t_enum(s: Set) -> Type { try_v_enum(s.into_iter().map(ValueObj::builtin_type).collect()) - .unwrap_or_else(|set| panic!("not homogeneous: {}", set)) + .unwrap_or_else(|set| panic!("not homogeneous: {set}")) } pub fn t_singleton(t: Type) -> Type { diff --git a/crates/erg_compiler/ty/mod.rs b/crates/erg_compiler/ty/mod.rs index 308b08697..dceaeeee8 100644 --- a/crates/erg_compiler/ty/mod.rs +++ b/crates/erg_compiler/ty/mod.rs @@ -451,7 +451,7 @@ impl LimitedDisplay for SubrType { } write!(f, "*")?; if let Some(name) = var_params.name() { - write!(f, "{}: ", name)?; + write!(f, "{name}: ")?; } var_params.typ().limited_fmt(f, limit - 1)?; } diff --git a/crates/erg_parser/ast.rs b/crates/erg_parser/ast.rs index 5b8f3f6a9..8e90ef166 100644 --- a/crates/erg_parser/ast.rs +++ b/crates/erg_parser/ast.rs @@ -2162,19 +2162,19 @@ impl NestedDisplay for Call { if i != 0 { write!(f, ", ")?; } - write!(f, "{}", arg)?; + write!(f, "{arg}")?; } if let Some(rest) = self.args.var_args.as_ref() { if !self.args.pos_args().is_empty() { write!(f, ", ")?; } - write!(f, "*{}", rest)?; + write!(f, "*{rest}")?; } for (i, kw_arg) in self.args.kw_args().iter().enumerate() { if i != 0 || !self.args.pos_args().is_empty() || self.args.var_args.is_some() { write!(f, ", ")?; } - write!(f, "{}", kw_arg)?; + write!(f, "{kw_arg}")?; } write!(f, ")") } else { @@ -3194,7 +3194,7 @@ impl NestedDisplay for ConstApp { fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result { writeln!(f, "{}", self.obj)?; if let Some(attr_name) = &self.attr_name { - writeln!(f, "{}", attr_name)?; + writeln!(f, "{attr_name}")?; } writeln!(f, "(")?; self.args.fmt_nest(f, level + 1)?; @@ -4446,11 +4446,11 @@ impl fmt::Display for VarName { #[pymethods] impl VarName { pub fn __repr__(&self) -> String { - format!("VarName({})", self) + format!("VarName({self})") } pub fn __str__(&self) -> String { - format!("VarName({})", self) + format!("VarName({self})") } #[staticmethod] @@ -4715,11 +4715,11 @@ impl From for Expr { #[pymethods] impl Identifier { pub fn __repr__(&self) -> String { - format!("Identifier({})", self) + format!("Identifier({self})") } pub fn __str__(&self) -> String { - format!("Identifier({})", self) + format!("Identifier({self})") } pub fn is_const(&self) -> bool { @@ -5245,11 +5245,11 @@ impl VarSignature { } pub fn __repr__(&self) -> String { - format!("VarSignature({})", self) + format!("VarSignature({self})") } pub fn __str__(&self) -> String { - format!("VarSignature({})", self) + format!("VarSignature({self})") } } @@ -5704,8 +5704,8 @@ pub enum GuardClause { impl NestedDisplay for GuardClause { fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result { match self { - Self::Condition(cond) => write!(f, "{}", cond), - Self::Bind(def) => write!(f, "{}", def), + Self::Condition(cond) => write!(f, "{cond}"), + Self::Bind(def) => write!(f, "{def}"), } } } diff --git a/crates/erg_parser/error.rs b/crates/erg_parser/error.rs index ea9211442..ad990ffde 100644 --- a/crates/erg_parser/error.rs +++ b/crates/erg_parser/error.rs @@ -175,6 +175,23 @@ impl LexError { )) } + pub fn parenthesize_error(errno: usize, loc: Location, got: &str) -> Self { + let msg = switch_lang!( + "japanese" => "不適切な閉じ括弧があります", + "simplified_chinese" => "存在不匹配的右括号", + "traditional_chinese" => "存在不匹配的右括號", + "english" => "unmatched closing parenthesis found", + ); + let got = StyledStr::new(got, Some(ERR), Some(ATTR)); + let hint = switch_lang!( + "japanese" => format!("この{}は対応する開き括弧がないため、削除するか開き括弧を追加してください", got), + "simplified_chinese" => format!("{}缺少对应的左括号,请删除或添加左括号", got), + "traditional_chinese" => format!("{}缺少對應的左括號,請刪除或添加左括號", got), + "english" => format!("{} has no matching opening parenthesis - either remove it or add an opening parenthesis", got), + ); + Self::syntax_error(errno, loc, msg, Some(hint)) + } + pub fn expect_next_line_error(errno: usize, loc: Location, caused: &str) -> Self { Self::new(ErrorCore::new( vec![SubMessage::ambiguous_new( diff --git a/crates/erg_parser/parse.rs b/crates/erg_parser/parse.rs index 6236de1d7..cde39f981 100644 --- a/crates/erg_parser/parse.rs +++ b/crates/erg_parser/parse.rs @@ -2050,6 +2050,13 @@ impl Parser { debug_exit_info!(self); return Err(()); } + Some(t) if t.is(RParen) => { + let err = ParseError::parenthesize_error(line!() as usize, t.loc(), ")"); + self.errs.push(err); + self.next_expr(); + debug_exit_info!(self); + return Err(()); + } _ => { if stack.len() <= 1 { break; diff --git a/crates/erg_parser/tests/parse_test.rs b/crates/erg_parser/tests/parse_test.rs index 8b780a362..6f56729f1 100644 --- a/crates/erg_parser/tests/parse_test.rs +++ b/crates/erg_parser/tests/parse_test.rs @@ -84,6 +84,11 @@ fn parse_invalid_class_definition() -> Result<(), ()> { expect_failure("tests/invalid_class_definition.er", 0, 7) } +#[test] +fn parse_missing_paren() -> Result<(), ()> { + expect_failure("tests/unmatched_paren.er", 0, 1) +} + #[test] fn parse_warns() -> Result<(), ()> { expect_success("tests/warns.er", 1) diff --git a/crates/erg_parser/tests/unmatched_paren.er b/crates/erg_parser/tests/unmatched_paren.er new file mode 100644 index 000000000..fdcb10430 --- /dev/null +++ b/crates/erg_parser/tests/unmatched_paren.er @@ -0,0 +1 @@ +func a, b) = a + b \ No newline at end of file diff --git a/src/dummy.rs b/src/dummy.rs index e858edce6..615c75d3e 100644 --- a/src/dummy.rs +++ b/src/dummy.rs @@ -454,7 +454,7 @@ impl PackageManagerRunner { { Ok(out) => ExitStatus::new(out.status.code().unwrap_or(0), 0, 0), Err(err) => { - eprintln!("Error: {}", err); + eprintln!("Error: {err}"); ExitStatus::ERR1 } }