mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-19 03:48:29 +00:00
[ty] Support attribute-expression TYPE_CHECKING conditionals (#21449)
This commit is contained in:
parent
e9a5337136
commit
5f501374c4
2 changed files with 61 additions and 6 deletions
|
|
@ -132,8 +132,29 @@ def f(x: int | str):
|
|||
Inside an `if TYPE_CHECKING` block, we allow "stub" style function definitions with empty bodies,
|
||||
since these functions will never actually be called.
|
||||
|
||||
`compat/__init__.py`:
|
||||
|
||||
```py
|
||||
```
|
||||
|
||||
`compat/sub/__init__.py`:
|
||||
|
||||
```py
|
||||
```
|
||||
|
||||
`compat/sub/sub.py`:
|
||||
|
||||
```py
|
||||
from typing import TYPE_CHECKING
|
||||
```
|
||||
|
||||
`main.py`:
|
||||
|
||||
```py
|
||||
from typing import TYPE_CHECKING
|
||||
import typing
|
||||
import typing as t
|
||||
import compat.sub.sub
|
||||
|
||||
if TYPE_CHECKING:
|
||||
def f() -> int: ...
|
||||
|
|
@ -199,6 +220,24 @@ if get_bool():
|
|||
if TYPE_CHECKING:
|
||||
if not TYPE_CHECKING:
|
||||
def n() -> str: ...
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
def o() -> str: ...
|
||||
|
||||
if not typing.TYPE_CHECKING:
|
||||
def p() -> str: ... # error: [invalid-return-type]
|
||||
|
||||
if compat.sub.sub.TYPE_CHECKING:
|
||||
def q() -> str: ...
|
||||
|
||||
if not compat.sub.sub.TYPE_CHECKING:
|
||||
def r() -> str: ... # error: [invalid-return-type]
|
||||
|
||||
if t.TYPE_CHECKING:
|
||||
def s() -> str: ...
|
||||
|
||||
if not t.TYPE_CHECKING:
|
||||
def t() -> str: ... # error: [invalid-return-type]
|
||||
```
|
||||
|
||||
## Conditional return type
|
||||
|
|
|
|||
|
|
@ -3131,15 +3131,31 @@ impl ExpressionsScopeMapBuilder {
|
|||
|
||||
/// Returns if the expression is a `TYPE_CHECKING` expression.
|
||||
fn is_if_type_checking(expr: &ast::Expr) -> bool {
|
||||
matches!(expr, ast::Expr::Name(ast::ExprName { id, .. }) if id == "TYPE_CHECKING")
|
||||
fn is_dotted_name(expr: &ast::Expr) -> bool {
|
||||
match expr {
|
||||
ast::Expr::Name(_) => true,
|
||||
ast::Expr::Attribute(ast::ExprAttribute { value, .. }) => is_dotted_name(value),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
match expr {
|
||||
ast::Expr::Name(ast::ExprName { id, .. }) => id == "TYPE_CHECKING",
|
||||
ast::Expr::Attribute(ast::ExprAttribute { value, attr, .. }) => {
|
||||
attr == "TYPE_CHECKING" && is_dotted_name(value)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns if the expression is a `not TYPE_CHECKING` expression.
|
||||
fn is_if_not_type_checking(expr: &ast::Expr) -> bool {
|
||||
matches!(expr, ast::Expr::UnaryOp(ast::ExprUnaryOp { op, operand, .. }) if *op == ruff_python_ast::UnaryOp::Not
|
||||
&& matches!(
|
||||
&**operand,
|
||||
ast::Expr::Name(ast::ExprName { id, .. }) if id == "TYPE_CHECKING"
|
||||
)
|
||||
matches!(
|
||||
expr,
|
||||
ast::Expr::UnaryOp(ast::ExprUnaryOp {
|
||||
op: ast::UnaryOp::Not,
|
||||
operand,
|
||||
..
|
||||
}) if is_if_type_checking(operand)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue