mirror of https://github.com/mtshiba/pylyzer
Add tests for errors/warns
This commit is contained in:
parent
b755ceb274
commit
6dd9af7d09
|
|
@ -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);
|
||||
base_type = Some(base_t);
|
||||
attrs.push(ClassAttr::Def(init_def));
|
||||
init_is_defined = true;
|
||||
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<_>>();
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
# W0188: unused value
|
||||
|
||||
1 # Warn
|
||||
|
||||
def f(): return "a"
|
||||
f() # Warn
|
||||
|
||||
def f(): return None
|
||||
f() # OK
|
||||
Loading…
Reference in New Issue