Implement F704 (#66)

This commit is contained in:
Charlie Marsh 2022-08-31 19:11:59 -04:00 committed by GitHub
parent c28ac75591
commit 2bac3027a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 72 additions and 0 deletions

View file

@ -0,0 +1,10 @@
def f() -> int:
yield 1
class Foo:
yield 2
yield 3
yield from 3

View file

@ -7,6 +7,7 @@ select = [
"F403",
"F541",
"F634",
"F704",
"F706",
"F821",
"F831",

View file

@ -349,6 +349,21 @@ impl Visitor for Checker<'_> {
| ExprKind::DictComp { .. }
| ExprKind::SetComp { .. } => self.push_scope(Scope::new(Generator)),
ExprKind::Lambda { .. } => self.push_scope(Scope::new(Function)),
ExprKind::Yield { .. } | ExprKind::YieldFrom { .. } => {
let scope = self.scopes.last().expect("No current scope found.");
if self
.settings
.select
.contains(CheckKind::YieldOutsideFunction.code())
&& matches!(scope.kind, ScopeKind::Class)
|| matches!(scope.kind, ScopeKind::Module)
{
self.checks.push(Check {
kind: CheckKind::YieldOutsideFunction,
location: expr.location,
});
}
}
ExprKind::JoinedStr { values } => {
if !self.in_f_string
&& self

View file

@ -12,6 +12,7 @@ pub enum CheckCode {
F403,
F541,
F634,
F704,
F706,
F821,
F831,
@ -30,6 +31,7 @@ impl FromStr for CheckCode {
"F403" => Ok(CheckCode::F403),
"F541" => Ok(CheckCode::F541),
"F634" => Ok(CheckCode::F634),
"F704" => Ok(CheckCode::F704),
"F706" => Ok(CheckCode::F706),
"F821" => Ok(CheckCode::F821),
"F831" => Ok(CheckCode::F831),
@ -49,6 +51,7 @@ impl CheckCode {
CheckCode::F403 => "F403",
CheckCode::F541 => "F541",
CheckCode::F634 => "F634",
CheckCode::F704 => "F704",
CheckCode::F706 => "F706",
CheckCode::F821 => "F821",
CheckCode::F831 => "F831",
@ -66,6 +69,7 @@ impl CheckCode {
CheckCode::F403 => &LintSource::AST,
CheckCode::F541 => &LintSource::AST,
CheckCode::F634 => &LintSource::AST,
CheckCode::F704 => &LintSource::AST,
CheckCode::F706 => &LintSource::AST,
CheckCode::F821 => &LintSource::AST,
CheckCode::F831 => &LintSource::AST,
@ -90,6 +94,7 @@ pub enum CheckKind {
ImportStarUsage,
LineTooLong,
RaiseNotImplemented,
YieldOutsideFunction,
ReturnOutsideFunction,
UndefinedName(String),
UndefinedLocal(String),
@ -107,6 +112,7 @@ impl CheckKind {
CheckKind::ImportStarUsage => &CheckCode::F403,
CheckKind::LineTooLong => &CheckCode::E501,
CheckKind::RaiseNotImplemented => &CheckCode::F901,
CheckKind::YieldOutsideFunction => &CheckCode::F704,
CheckKind::ReturnOutsideFunction => &CheckCode::F706,
CheckKind::UndefinedName(_) => &CheckCode::F821,
CheckKind::UndefinedLocal(_) => &CheckCode::F832,
@ -132,6 +138,9 @@ impl CheckKind {
CheckKind::RaiseNotImplemented => {
"'raise NotImplemented' should be 'raise NotImplementedError".to_string()
}
CheckKind::YieldOutsideFunction => {
"a `yield` or `yield from` statement outside of a function/method".to_string()
}
CheckKind::ReturnOutsideFunction => {
"a `return` statement outside of a function/method".to_string()
}

View file

@ -222,6 +222,42 @@ mod tests {
Ok(())
}
#[test]
fn f704() -> Result<()> {
let actual = check_path(
&Path::new("./resources/test/src/F704.py"),
&settings::Settings {
line_length: 88,
exclude: vec![],
select: BTreeSet::from([CheckCode::F704]),
},
&cache::Mode::None,
)?;
let expected = vec![
Message {
kind: CheckKind::YieldOutsideFunction,
location: Location::new(6, 5),
filename: "./resources/test/src/F704.py".to_string(),
},
Message {
kind: CheckKind::YieldOutsideFunction,
location: Location::new(9, 1),
filename: "./resources/test/src/F704.py".to_string(),
},
Message {
kind: CheckKind::YieldOutsideFunction,
location: Location::new(10, 1),
filename: "./resources/test/src/F704.py".to_string(),
},
];
assert_eq!(actual.len(), expected.len());
for i in 0..actual.len() {
assert_eq!(actual[i], expected[i]);
}
Ok(())
}
#[test]
fn f706() -> Result<()> {
let actual = check_path(

View file

@ -235,6 +235,7 @@ other-attribute = 1
CheckCode::F403,
CheckCode::F541,
CheckCode::F634,
CheckCode::F704,
CheckCode::F706,
CheckCode::F821,
CheckCode::F831,