mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-19 01:51:30 +00:00
[flake8-pyi
] Check for kwarg and vararg NoReturn
type annotations (#8948)
## Summary Triggers `no-return-argument-annotation-in-stub` (`PYI050`) for vararg and kwarg `NoReturn` type annotations. Related to #8771. ## Test Plan `cargo test`
This commit is contained in:
parent
506be68782
commit
d66063bb33
3 changed files with 105 additions and 12 deletions
|
@ -10,3 +10,14 @@ def foo_no_return_typing_extensions(
|
|||
def foo_no_return_kwarg(arg: int, *, arg2: NoReturn): ... # Error: PYI050
|
||||
def foo_no_return_pos_only(arg: int, /, arg2: NoReturn): ... # Error: PYI050
|
||||
def foo_never(arg: Never): ...
|
||||
def foo_args(*args: NoReturn): ... # Error: PYI050
|
||||
def foo_kwargs(**kwargs: NoReturn): ... # Error: PYI050
|
||||
def foo_args_kwargs(*args: NoReturn, **kwargs: NoReturn): ... # Error: PYI050
|
||||
def foo_int_args(*args: int): ...
|
||||
def foo_int_kwargs(**kwargs: int): ...
|
||||
def foo_int_args_kwargs(*args: int, **kwargs: int): ...
|
||||
def foo_int_args_no_return(*args: int, **kwargs: NoReturn): ... # Error: PYI050
|
||||
def foo_int_kwargs_no_return(*args: NoReturn, **kwargs: int): ... # Error: PYI050
|
||||
def foo_args_never(*args: Never): ...
|
||||
def foo_kwargs_never(**kwargs: Never): ...
|
||||
def foo_args_kwargs_never(*args: Never, **kwargs: Never): ...
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::fmt;
|
|||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::Parameters;
|
||||
use ruff_python_ast::{Expr, Parameters};
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
@ -51,6 +51,9 @@ impl Violation for NoReturnArgumentAnnotationInStub {
|
|||
|
||||
/// PYI050
|
||||
pub(crate) fn no_return_argument_annotation(checker: &mut Checker, parameters: &Parameters) {
|
||||
// Ex) def func(arg: NoReturn): ...
|
||||
// Ex) def func(arg: NoReturn, /): ...
|
||||
// Ex) def func(*, arg: NoReturn): ...
|
||||
for annotation in parameters
|
||||
.posonlyargs
|
||||
.iter()
|
||||
|
@ -58,19 +61,37 @@ pub(crate) fn no_return_argument_annotation(checker: &mut Checker, parameters: &
|
|||
.chain(¶meters.kwonlyargs)
|
||||
.filter_map(|arg| arg.parameter.annotation.as_ref())
|
||||
{
|
||||
if checker.semantic().match_typing_expr(annotation, "NoReturn") {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
NoReturnArgumentAnnotationInStub {
|
||||
module: if checker.settings.target_version >= Py311 {
|
||||
TypingModule::Typing
|
||||
} else {
|
||||
TypingModule::TypingExtensions
|
||||
},
|
||||
},
|
||||
annotation.range(),
|
||||
));
|
||||
check_no_return_argument_annotation(checker, annotation);
|
||||
}
|
||||
|
||||
// Ex) def func(*args: NoReturn): ...
|
||||
if let Some(arg) = ¶meters.vararg {
|
||||
if let Some(annotation) = &arg.annotation {
|
||||
check_no_return_argument_annotation(checker, annotation);
|
||||
}
|
||||
}
|
||||
|
||||
// Ex) def func(**kwargs: NoReturn): ...
|
||||
if let Some(arg) = ¶meters.kwarg {
|
||||
if let Some(annotation) = &arg.annotation {
|
||||
check_no_return_argument_annotation(checker, annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_no_return_argument_annotation(checker: &mut Checker, annotation: &Expr) {
|
||||
if checker.semantic().match_typing_expr(annotation, "NoReturn") {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
NoReturnArgumentAnnotationInStub {
|
||||
module: if checker.settings.target_version >= Py311 {
|
||||
TypingModule::Typing
|
||||
} else {
|
||||
TypingModule::TypingExtensions
|
||||
},
|
||||
},
|
||||
annotation.range(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
|
|
|
@ -28,6 +28,67 @@ PYI050.pyi:11:47: PYI050 Prefer `typing.Never` over `NoReturn` for argument anno
|
|||
11 | def foo_no_return_pos_only(arg: int, /, arg2: NoReturn): ... # Error: PYI050
|
||||
| ^^^^^^^^ PYI050
|
||||
12 | def foo_never(arg: Never): ...
|
||||
13 | def foo_args(*args: NoReturn): ... # Error: PYI050
|
||||
|
|
||||
|
||||
PYI050.pyi:13:21: PYI050 Prefer `typing.Never` over `NoReturn` for argument annotations
|
||||
|
|
||||
11 | def foo_no_return_pos_only(arg: int, /, arg2: NoReturn): ... # Error: PYI050
|
||||
12 | def foo_never(arg: Never): ...
|
||||
13 | def foo_args(*args: NoReturn): ... # Error: PYI050
|
||||
| ^^^^^^^^ PYI050
|
||||
14 | def foo_kwargs(**kwargs: NoReturn): ... # Error: PYI050
|
||||
15 | def foo_args_kwargs(*args: NoReturn, **kwargs: NoReturn): ... # Error: PYI050
|
||||
|
|
||||
|
||||
PYI050.pyi:14:26: PYI050 Prefer `typing.Never` over `NoReturn` for argument annotations
|
||||
|
|
||||
12 | def foo_never(arg: Never): ...
|
||||
13 | def foo_args(*args: NoReturn): ... # Error: PYI050
|
||||
14 | def foo_kwargs(**kwargs: NoReturn): ... # Error: PYI050
|
||||
| ^^^^^^^^ PYI050
|
||||
15 | def foo_args_kwargs(*args: NoReturn, **kwargs: NoReturn): ... # Error: PYI050
|
||||
16 | def foo_int_args(*args: int): ...
|
||||
|
|
||||
|
||||
PYI050.pyi:15:28: PYI050 Prefer `typing.Never` over `NoReturn` for argument annotations
|
||||
|
|
||||
13 | def foo_args(*args: NoReturn): ... # Error: PYI050
|
||||
14 | def foo_kwargs(**kwargs: NoReturn): ... # Error: PYI050
|
||||
15 | def foo_args_kwargs(*args: NoReturn, **kwargs: NoReturn): ... # Error: PYI050
|
||||
| ^^^^^^^^ PYI050
|
||||
16 | def foo_int_args(*args: int): ...
|
||||
17 | def foo_int_kwargs(**kwargs: int): ...
|
||||
|
|
||||
|
||||
PYI050.pyi:15:48: PYI050 Prefer `typing.Never` over `NoReturn` for argument annotations
|
||||
|
|
||||
13 | def foo_args(*args: NoReturn): ... # Error: PYI050
|
||||
14 | def foo_kwargs(**kwargs: NoReturn): ... # Error: PYI050
|
||||
15 | def foo_args_kwargs(*args: NoReturn, **kwargs: NoReturn): ... # Error: PYI050
|
||||
| ^^^^^^^^ PYI050
|
||||
16 | def foo_int_args(*args: int): ...
|
||||
17 | def foo_int_kwargs(**kwargs: int): ...
|
||||
|
|
||||
|
||||
PYI050.pyi:19:50: PYI050 Prefer `typing.Never` over `NoReturn` for argument annotations
|
||||
|
|
||||
17 | def foo_int_kwargs(**kwargs: int): ...
|
||||
18 | def foo_int_args_kwargs(*args: int, **kwargs: int): ...
|
||||
19 | def foo_int_args_no_return(*args: int, **kwargs: NoReturn): ... # Error: PYI050
|
||||
| ^^^^^^^^ PYI050
|
||||
20 | def foo_int_kwargs_no_return(*args: NoReturn, **kwargs: int): ... # Error: PYI050
|
||||
21 | def foo_args_never(*args: Never): ...
|
||||
|
|
||||
|
||||
PYI050.pyi:20:37: PYI050 Prefer `typing.Never` over `NoReturn` for argument annotations
|
||||
|
|
||||
18 | def foo_int_args_kwargs(*args: int, **kwargs: int): ...
|
||||
19 | def foo_int_args_no_return(*args: int, **kwargs: NoReturn): ... # Error: PYI050
|
||||
20 | def foo_int_kwargs_no_return(*args: NoReturn, **kwargs: int): ... # Error: PYI050
|
||||
| ^^^^^^^^ PYI050
|
||||
21 | def foo_args_never(*args: Never): ...
|
||||
22 | def foo_kwargs_never(**kwargs: Never): ...
|
||||
|
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue