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)
|
Block::new(new_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_init_self(&mut self, init_def: &Def) {
|
fn check_init_sig(&mut self, sig: &Signature) -> Option<()> {
|
||||||
match &init_def.sig {
|
match sig {
|
||||||
Signature::Subr(subr) => {
|
Signature::Subr(subr) => {
|
||||||
if let Some(first) = subr.params.non_defaults.get(0) {
|
if let Some(first) = subr.params.non_defaults.get(0) {
|
||||||
if first.inspect().map(|s| &s[..]) == Some("self") {
|
if first.inspect().map(|s| &s[..]) == Some("self") {
|
||||||
return;
|
return Some(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.errs.push(self_not_found_error(
|
self.errs.push(self_not_found_error(
|
||||||
|
|
@ -538,6 +538,7 @@ impl ASTConverter {
|
||||||
subr.loc(),
|
subr.loc(),
|
||||||
self.namespace.join("."),
|
self.namespace.join("."),
|
||||||
));
|
));
|
||||||
|
Some(())
|
||||||
}
|
}
|
||||||
Signature::Var(var) => {
|
Signature::Var(var) => {
|
||||||
self.errs.push(init_var_error(
|
self.errs.push(init_var_error(
|
||||||
|
|
@ -545,6 +546,7 @@ impl ASTConverter {
|
||||||
var.loc(),
|
var.loc(),
|
||||||
self.namespace.join("."),
|
self.namespace.join("."),
|
||||||
));
|
));
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -555,8 +557,8 @@ impl ASTConverter {
|
||||||
// self.z = z
|
// self.z = z
|
||||||
// ↓
|
// ↓
|
||||||
// {x: Int, y: Int, z: Never}, .__call__(x: Int, y: Int, z: Obj): Self = .unreachable()
|
// {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) {
|
fn extract_init(&mut self, init_def: Def) -> Option<(Expr, Def)> {
|
||||||
self.find_init_self(&init_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 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 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!() };
|
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 = Expr::Accessor(Accessor::Ident(unreachable_acc)).call_expr(Args::empty());
|
||||||
let body = DefBody::new(EQUAL, Block::new(vec![body]), DefId(0));
|
let body = DefBody::new(EQUAL, Block::new(vec![body]), DefId(0));
|
||||||
let def = Def::new(sig, body);
|
let def = Def::new(sig, body);
|
||||||
(Expr::Record(record), def)
|
Some((Expr::Record(record), def))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_default_init(&self, line: usize) -> Def {
|
fn gen_default_init(&self, line: usize) -> Def {
|
||||||
|
|
@ -624,11 +626,12 @@ impl ASTConverter {
|
||||||
let chunk = self.convert_statement(stmt, true);
|
let chunk = self.convert_statement(stmt, true);
|
||||||
match chunk {
|
match chunk {
|
||||||
Expr::Def(def) => {
|
Expr::Def(def) => {
|
||||||
if def.is_subr() && &def.sig.ident().unwrap().inspect()[..] == "__init__" {
|
if def.sig.ident().map(|id| &id.inspect()[..] == "__init__").unwrap_or(false) {
|
||||||
let (base_t, init_def) = self.extract_init(def);
|
if let Some((base_t, init_def)) = self.extract_init(def) {
|
||||||
base_type = Some(base_t);
|
base_type = Some(base_t);
|
||||||
attrs.push(ClassAttr::Def(init_def));
|
attrs.push(ClassAttr::Def(init_def));
|
||||||
init_is_defined = true;
|
init_is_defined = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
attrs.push(ClassAttr::Def(def));
|
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 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) {
|
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(),
|
self.cfg.input.clone(),
|
||||||
pyloc_to_ergloc(stmt.location, name.len()),
|
pyloc_to_ergloc(stmt.location, name.len()),
|
||||||
self.namespace.join("."),
|
self.namespace.join("."),
|
||||||
&name
|
&name
|
||||||
);
|
);
|
||||||
self.warns.push(warn);
|
self.errs.push(err);
|
||||||
Expr::Dummy(Dummy::empty())
|
Expr::Dummy(Dummy::empty())
|
||||||
} else {
|
} else {
|
||||||
let decos = decorator_list.into_iter().map(|ex| Decorator(self.convert_expr(ex))).collect::<HashSet<_>>();
|
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(
|
ErrorCore::new(
|
||||||
vec![SubMessage::only_loc(loc)],
|
vec![SubMessage::only_loc(loc)],
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
"japanese" => format!("__init__はメソッドです。メンバ変数として宣言することはできません"),
|
"japanese" => format!("`__init__`はメソッドです。メンバ変数として宣言するべきではありません"),
|
||||||
"simplified_chinese" => format!("__init__是方法。不能声明为变量"),
|
"simplified_chinese" => format!("__init__是方法。不能宣告为变量"),
|
||||||
"traditional_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,
|
3,
|
||||||
ErrorKind::NameError,
|
ErrorKind::NameError,
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
# E0001
|
||||||
|
|
||||||
def a(): return 1
|
def a(): return 1
|
||||||
def a(): return "a" # OK
|
def a(): return "a" # OK
|
||||||
|
|
||||||
|
|
@ -7,3 +9,15 @@ def g(): return f()
|
||||||
|
|
||||||
def f(): return 1
|
def f(): return 1
|
||||||
def f(): return "a" # E0001: Reassignment of a function referenced by other functions
|
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]
|
#[test]
|
||||||
fn exec_e0001() {
|
fn exec_errors() {
|
||||||
expect("tests/e0001.py", 1, 0);
|
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