Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b31732f

Browse files
committed
Refactor logic and expand comments
1 parent ca91cb7 commit b31732f

2 files changed

Lines changed: 37 additions & 41 deletions

File tree

crates/ruff_python_semantic/src/analyze/typing.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ where
408408
return;
409409
}
410410

411-
// Ex) Union[Union[a, b]] and Union[a | b | c]
411+
// Ex) `Union[Union[a, b]]` and `Union[a | b | c]``
412412
inner(func, semantic, slice, Some(expr));
413413
return;
414414
}

crates/ruff_python_semantic/src/model.rs

Lines changed: 36 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_hash::FxHashMap;
55

66
use ruff_python_ast::helpers::from_relative_import;
77
use ruff_python_ast::name::{QualifiedName, UnqualifiedName};
8-
use ruff_python_ast::{self as ast, Expr, ExprContext, Operator, PySourceType, Stmt};
8+
use ruff_python_ast::{self as ast, Expr, ExprContext, PySourceType, Stmt};
99
use ruff_text_size::{Ranged, TextRange, TextSize};
1010

1111
use crate::binding::{
@@ -1508,52 +1508,48 @@ impl<'a> SemanticModel<'a> {
15081508
/// Return `true` if the model is in a nested union expression (e.g., the inner `Union` in
15091509
/// `Union[Union[int, str], float]`).
15101510
pub fn in_nested_union(&self) -> bool {
1511-
// Ex) `Union[Union[int, str], float]`
1512-
if self
1513-
.current_expression_grandparent()
1514-
.and_then(Expr::as_subscript_expr)
1515-
.is_some_and(|parent| self.match_typing_expr(&parent.value, "Union"))
1516-
{
1517-
return true;
1518-
}
1519-
1520-
// Ex) `int | Union[str, float]`
1521-
if self.current_expression_parent().is_some_and(|parent| {
1522-
matches!(
1523-
parent,
1524-
Expr::BinOp(ast::ExprBinOp {
1525-
op: Operator::BitOr,
1526-
..
1527-
})
1528-
)
1529-
}) {
1530-
return true;
1511+
let mut parent_expressions = self.current_expressions().skip(1);
1512+
1513+
match parent_expressions.next() {
1514+
// The parent expression is of the inner union is a single `typing.Union`.
1515+
// Ex) `Union[Union[a, b]]`
1516+
Some(Expr::Subscript(parent)) => self.match_typing_expr(&parent.value, "Union"),
1517+
// The parent expression is of the inner union is a tuple with two or more
1518+
// comma-separated elements and the parent of that tuple is a `typing.Union`.
1519+
// Ex) `Union[Union[a, b], Union[c, d]]`
1520+
Some(Expr::Tuple(_)) => parent_expressions
1521+
.next()
1522+
.and_then(Expr::as_subscript_expr)
1523+
.is_some_and(|grandparent| self.match_typing_expr(&grandparent.value, "Union")),
1524+
// The parent expression of the inner union is a PEP604-style union.
1525+
// Ex) `a | b | c` or `Union[a, b] | c`
1526+
// In contrast to `typing.Union`, PEP604-style unions are always binary operations, e.g.
1527+
// the expression `a | b | c` is represented by two binary unions: `(a | b) | c`.
1528+
Some(Expr::BinOp(bin_op)) => bin_op.op.is_bit_or(),
1529+
// Not a nested union otherwise.
1530+
_ => false,
15311531
}
1532-
1533-
// Ex) `Union[Union[int, int]]` or `Union[int | int]`
1534-
self.current_expression_parent()
1535-
.and_then(Expr::as_subscript_expr)
1536-
.is_some_and(|parent| self.match_typing_expr(&parent.value, "Union"))
15371532
}
15381533

15391534
/// Return `true` if the model is in a nested literal expression (e.g., the inner `Literal` in
15401535
/// `Literal[Literal[int, str], float]`).
15411536
pub fn in_nested_literal(&self) -> bool {
1542-
// Parent is union or tuple
1543-
// Ex) `Literal[Literal[int, str], float]`
1544-
if self
1545-
.current_expression_grandparent()
1546-
.and_then(Expr::as_subscript_expr)
1547-
.is_some_and(|parent| self.match_typing_expr(&parent.value, "Literal"))
1548-
{
1549-
return true;
1537+
let mut parent_expressions = self.current_expressions().skip(1);
1538+
1539+
match parent_expressions.next() {
1540+
// The parent expression of the current `Literal` is a tuple, and the
1541+
// grandparent is a `Literal`.
1542+
// Ex) `Literal[Literal[str], Literal[int]]`
1543+
Some(Expr::Tuple(_)) => parent_expressions
1544+
.next()
1545+
.and_then(Expr::as_subscript_expr)
1546+
.is_some_and(|grandparent| self.match_typing_expr(&grandparent.value, "Literal")),
1547+
// The parent expression of the current `Literal` is also a `Literal`.
1548+
// Ex) `Literal[Literal[str]]`
1549+
Some(Expr::Subscript(parent)) => self.match_typing_expr(&parent.value, "Literal"),
1550+
// Not a nested literal otherwise
1551+
_ => false,
15501552
}
1551-
1552-
// Parent is `Literal`
1553-
// Ex) `Literal[Literal[int]]`
1554-
self.current_expression_parent()
1555-
.and_then(Expr::as_subscript_expr)
1556-
.is_some_and(|parent| self.match_typing_expr(&parent.value, "Literal"))
15571553
}
15581554

15591555
/// Returns `true` if `left` and `right` are in the same branches of an `if`, `match`, or

0 commit comments

Comments
 (0)