Add tests for errors/warns

This commit is contained in:
Shunsuke Shibayama 2022-12-24 12:14:31 +09:00
parent b755ceb274
commit 6dd9af7d09
5 changed files with 49 additions and 18 deletions

View File

@ -525,12 +525,12 @@ impl ASTConverter {
Block::new(new_block)
}
fn find_init_self(&mut self, init_def: &Def) {
match &init_def.sig {
fn check_init_sig(&mut self, sig: &Signature) -> Option<()> {
match sig {
Signature::Subr(subr) => {
if let Some(first) = subr.params.non_defaults.get(0) {
if first.inspect().map(|s| &s[..]) == Some("self") {
return;
return Some(());
}
}
self.errs.push(self_not_found_error(
@ -538,6 +538,7 @@ impl ASTConverter {
subr.loc(),
self.namespace.join("."),
));
Some(())
}
Signature::Var(var) => {
self.errs.push(init_var_error(
@ -545,6 +546,7 @@ impl ASTConverter {
var.loc(),
self.namespace.join("."),
));
None
}
}
}
@ -555,8 +557,8 @@ impl ASTConverter {
// self.z = z
// ↓
// {x: Int, y: Int, z: Never}, .__call__(x: Int, y: Int, z: Obj): Self = .unreachable()
fn extract_init(&mut self, init_def: Def) -> (Expr, Def) {
self.find_init_self(&init_def);
fn extract_init(&mut self, init_def: Def) -> Option<(Expr, Def)> {
self.check_init_sig(&init_def.sig)?;
let l_brace = Token::new(TokenKind::LBrace, "{", init_def.ln_begin().unwrap_or(0), init_def.col_begin().unwrap_or(0));
let r_brace = Token::new(TokenKind::RBrace, "}", init_def.ln_end().unwrap_or(0), init_def.col_end().unwrap_or(0));
let Signature::Subr(sig) = init_def.sig else { unreachable!() };
@ -601,7 +603,7 @@ impl ASTConverter {
let body = Expr::Accessor(Accessor::Ident(unreachable_acc)).call_expr(Args::empty());
let body = DefBody::new(EQUAL, Block::new(vec![body]), DefId(0));
let def = Def::new(sig, body);
(Expr::Record(record), def)
Some((Expr::Record(record), def))
}
fn gen_default_init(&self, line: usize) -> Def {
@ -624,11 +626,12 @@ impl ASTConverter {
let chunk = self.convert_statement(stmt, true);
match chunk {
Expr::Def(def) => {
if def.is_subr() && &def.sig.ident().unwrap().inspect()[..] == "__init__" {
let (base_t, init_def) = self.extract_init(def);
if def.sig.ident().map(|id| &id.inspect()[..] == "__init__").unwrap_or(false) {
if let Some((base_t, init_def)) = self.extract_init(def) {
base_type = Some(base_t);
attrs.push(ClassAttr::Def(init_def));
init_is_defined = true;
}
} else {
attrs.push(ClassAttr::Def(def));
}
@ -833,13 +836,13 @@ impl ASTConverter {
} => {
// if reassigning of a function referenced by other functions is occurred, it is an error
if self.get_name(&name).map(|info| info.defined_times > 0 && !info.referenced.difference(&set!{name.clone()}).is_empty()).unwrap_or(false) {
let warn = reassign_func_error(
let err = reassign_func_error(
self.cfg.input.clone(),
pyloc_to_ergloc(stmt.location, name.len()),
self.namespace.join("."),
&name
);
self.warns.push(warn);
self.errs.push(err);
Expr::Dummy(Dummy::empty())
} else {
let decos = decorator_list.into_iter().map(|ex| Decorator(self.convert_expr(ex))).collect::<HashSet<_>>();

View File

@ -59,10 +59,10 @@ pub(crate) fn init_var_error(
ErrorCore::new(
vec![SubMessage::only_loc(loc)],
switch_lang!(
"japanese" => format!("__init__はメソッドです。メンバ変数として宣言することはできません"),
"simplified_chinese" => format!("__init__是方法。不能声明为变量"),
"japanese" => format!("`__init__`はメソッドです。メンバ変数として宣言するべきではありません"),
"simplified_chinese" => format!("__init__是方法。不能宣告为变量"),
"traditional_chinese" => format!("__init__是方法。不能宣告為變量"),
"english" => format!("__init__ is a method. It cannot be declared as a member variable"),
"english" => format!("`__init__` should be a method. It should not be defined as a member variable"),
),
3,
ErrorKind::NameError,

View File

@ -1,3 +1,5 @@
# E0001
def a(): return 1
def a(): return "a" # OK
@ -7,3 +9,15 @@ def g(): return f()
def f(): return 1
def f(): return "a" # E0001: Reassignment of a function referenced by other functions
# E0002
class C:
def __init__(self): pass # OK
class C:
def __init__(a): pass # ERR
# E0003
class C:
__init__ = 1 # ERR

View File

@ -46,6 +46,11 @@ fn exec_class() {
}
#[test]
fn exec_e0001() {
expect("tests/e0001.py", 1, 0);
fn exec_errors() {
expect("tests/errors.py", 0, 3);
}
#[test]
fn exec_warns() {
expect("tests/warns.py", 2, 0);
}

9
tests/warns.py Normal file
View File

@ -0,0 +1,9 @@
# W0188: unused value
1 # Warn
def f(): return "a"
f() # Warn
def f(): return None
f() # OK