mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 18:28:24 +00:00
Add support for PEP 696 syntax (#11120)
This commit is contained in:
parent
45725d3275
commit
cd3e319538
49 changed files with 4338 additions and 669 deletions
|
@ -1173,21 +1173,29 @@ impl<'a> From<&'a ast::TypeParam> for ComparableTypeParam<'a> {
|
|||
ast::TypeParam::TypeVar(ast::TypeParamTypeVar {
|
||||
name,
|
||||
bound,
|
||||
default,
|
||||
range: _,
|
||||
}) => Self::TypeVar(TypeParamTypeVar {
|
||||
name: name.as_str(),
|
||||
bound: bound.as_ref().map(Into::into),
|
||||
default: default.as_ref().map(Into::into),
|
||||
}),
|
||||
ast::TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple {
|
||||
name,
|
||||
default,
|
||||
range: _,
|
||||
}) => Self::TypeVarTuple(TypeParamTypeVarTuple {
|
||||
name: name.as_str(),
|
||||
default: default.as_ref().map(Into::into),
|
||||
}),
|
||||
ast::TypeParam::ParamSpec(ast::TypeParamParamSpec {
|
||||
name,
|
||||
default,
|
||||
range: _,
|
||||
}) => Self::ParamSpec(TypeParamParamSpec {
|
||||
name: name.as_str(),
|
||||
default: default.as_ref().map(Into::into),
|
||||
}),
|
||||
ast::TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple { name, range: _ }) => {
|
||||
Self::TypeVarTuple(TypeParamTypeVarTuple {
|
||||
name: name.as_str(),
|
||||
})
|
||||
}
|
||||
ast::TypeParam::ParamSpec(ast::TypeParamParamSpec { name, range: _ }) => {
|
||||
Self::ParamSpec(TypeParamParamSpec {
|
||||
name: name.as_str(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1196,16 +1204,19 @@ impl<'a> From<&'a ast::TypeParam> for ComparableTypeParam<'a> {
|
|||
pub struct TypeParamTypeVar<'a> {
|
||||
pub name: &'a str,
|
||||
pub bound: Option<Box<ComparableExpr<'a>>>,
|
||||
pub default: Option<Box<ComparableExpr<'a>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
pub struct TypeParamParamSpec<'a> {
|
||||
pub name: &'a str,
|
||||
pub default: Option<Box<ComparableExpr<'a>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
pub struct TypeParamTypeVarTuple<'a> {
|
||||
pub name: &'a str,
|
||||
pub default: Option<Box<ComparableExpr<'a>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
|
|
|
@ -264,11 +264,20 @@ pub fn any_over_expr(expr: &Expr, func: &dyn Fn(&Expr) -> bool) -> bool {
|
|||
|
||||
pub fn any_over_type_param(type_param: &TypeParam, func: &dyn Fn(&Expr) -> bool) -> bool {
|
||||
match type_param {
|
||||
TypeParam::TypeVar(ast::TypeParamTypeVar { bound, .. }) => bound
|
||||
TypeParam::TypeVar(ast::TypeParamTypeVar { bound, default, .. }) => {
|
||||
bound
|
||||
.as_ref()
|
||||
.is_some_and(|value| any_over_expr(value, func))
|
||||
|| default
|
||||
.as_ref()
|
||||
.is_some_and(|value| any_over_expr(value, func))
|
||||
}
|
||||
TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple { default, .. }) => default
|
||||
.as_ref()
|
||||
.is_some_and(|value| any_over_expr(value, func)),
|
||||
TypeParam::ParamSpec(ast::TypeParamParamSpec { default, .. }) => default
|
||||
.as_ref()
|
||||
.is_some_and(|value| any_over_expr(value, func)),
|
||||
TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple { .. }) => false,
|
||||
TypeParam::ParamSpec(ast::TypeParamParamSpec { .. }) => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1619,11 +1628,13 @@ mod tests {
|
|||
let type_var_one = TypeParam::TypeVar(TypeParamTypeVar {
|
||||
range: TextRange::default(),
|
||||
bound: Some(Box::new(constant_one.clone())),
|
||||
default: None,
|
||||
name: Identifier::new("x", TextRange::default()),
|
||||
});
|
||||
let type_var_two = TypeParam::TypeVar(TypeParamTypeVar {
|
||||
range: TextRange::default(),
|
||||
bound: Some(Box::new(constant_two.clone())),
|
||||
bound: None,
|
||||
default: Some(Box::new(constant_two.clone())),
|
||||
name: Identifier::new("x", TextRange::default()),
|
||||
});
|
||||
let type_alias = Stmt::TypeAlias(StmtTypeAlias {
|
||||
|
@ -1650,30 +1661,49 @@ mod tests {
|
|||
let type_var_no_bound = TypeParam::TypeVar(TypeParamTypeVar {
|
||||
range: TextRange::default(),
|
||||
bound: None,
|
||||
default: None,
|
||||
name: Identifier::new("x", TextRange::default()),
|
||||
});
|
||||
assert!(!any_over_type_param(&type_var_no_bound, &|_expr| true));
|
||||
|
||||
let bound = Expr::NumberLiteral(ExprNumberLiteral {
|
||||
let constant = Expr::NumberLiteral(ExprNumberLiteral {
|
||||
value: Number::Int(Int::ONE),
|
||||
range: TextRange::default(),
|
||||
});
|
||||
|
||||
let type_var_with_bound = TypeParam::TypeVar(TypeParamTypeVar {
|
||||
range: TextRange::default(),
|
||||
bound: Some(Box::new(bound.clone())),
|
||||
bound: Some(Box::new(constant.clone())),
|
||||
default: None,
|
||||
name: Identifier::new("x", TextRange::default()),
|
||||
});
|
||||
assert!(
|
||||
any_over_type_param(&type_var_with_bound, &|expr| {
|
||||
assert_eq!(
|
||||
*expr, bound,
|
||||
*expr, constant,
|
||||
"the received expression should be the unwrapped bound"
|
||||
);
|
||||
true
|
||||
}),
|
||||
"if true is returned from `func` it should be respected"
|
||||
);
|
||||
|
||||
let type_var_with_default = TypeParam::TypeVar(TypeParamTypeVar {
|
||||
range: TextRange::default(),
|
||||
default: Some(Box::new(constant.clone())),
|
||||
bound: None,
|
||||
name: Identifier::new("x", TextRange::default()),
|
||||
});
|
||||
assert!(
|
||||
any_over_type_param(&type_var_with_default, &|expr| {
|
||||
assert_eq!(
|
||||
*expr, constant,
|
||||
"the received expression should be the unwrapped default"
|
||||
);
|
||||
true
|
||||
}),
|
||||
"if true is returned from `func` it should be respected"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1681,10 +1711,32 @@ mod tests {
|
|||
let type_var_tuple = TypeParam::TypeVarTuple(TypeParamTypeVarTuple {
|
||||
range: TextRange::default(),
|
||||
name: Identifier::new("x", TextRange::default()),
|
||||
default: None,
|
||||
});
|
||||
assert!(
|
||||
!any_over_type_param(&type_var_tuple, &|_expr| true),
|
||||
"type var tuples have no expressions to visit"
|
||||
"this TypeVarTuple has no expressions to visit"
|
||||
);
|
||||
|
||||
let constant = Expr::NumberLiteral(ExprNumberLiteral {
|
||||
value: Number::Int(Int::ONE),
|
||||
range: TextRange::default(),
|
||||
});
|
||||
|
||||
let type_var_tuple_with_default = TypeParam::TypeVarTuple(TypeParamTypeVarTuple {
|
||||
range: TextRange::default(),
|
||||
default: Some(Box::new(constant.clone())),
|
||||
name: Identifier::new("x", TextRange::default()),
|
||||
});
|
||||
assert!(
|
||||
any_over_type_param(&type_var_tuple_with_default, &|expr| {
|
||||
assert_eq!(
|
||||
*expr, constant,
|
||||
"the received expression should be the unwrapped default"
|
||||
);
|
||||
true
|
||||
}),
|
||||
"if true is returned from `func` it should be respected"
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1693,10 +1745,32 @@ mod tests {
|
|||
let type_param_spec = TypeParam::ParamSpec(TypeParamParamSpec {
|
||||
range: TextRange::default(),
|
||||
name: Identifier::new("x", TextRange::default()),
|
||||
default: None,
|
||||
});
|
||||
assert!(
|
||||
!any_over_type_param(&type_param_spec, &|_expr| true),
|
||||
"param specs have no expressions to visit"
|
||||
"this ParamSpec has no expressions to visit"
|
||||
);
|
||||
|
||||
let constant = Expr::NumberLiteral(ExprNumberLiteral {
|
||||
value: Number::Int(Int::ONE),
|
||||
range: TextRange::default(),
|
||||
});
|
||||
|
||||
let param_spec_with_default = TypeParam::TypeVarTuple(TypeParamTypeVarTuple {
|
||||
range: TextRange::default(),
|
||||
default: Some(Box::new(constant.clone())),
|
||||
name: Identifier::new("x", TextRange::default()),
|
||||
});
|
||||
assert!(
|
||||
any_over_type_param(¶m_spec_with_default, &|expr| {
|
||||
assert_eq!(
|
||||
*expr, constant,
|
||||
"the received expression should be the unwrapped default"
|
||||
);
|
||||
true
|
||||
}),
|
||||
"if true is returned from `func` it should be respected"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4317,6 +4317,7 @@ impl AstNode for ast::TypeParamTypeVar {
|
|||
{
|
||||
let ast::TypeParamTypeVar {
|
||||
bound,
|
||||
default,
|
||||
name: _,
|
||||
range: _,
|
||||
} = self;
|
||||
|
@ -4324,6 +4325,9 @@ impl AstNode for ast::TypeParamTypeVar {
|
|||
if let Some(expr) = bound {
|
||||
visitor.visit_expr(expr);
|
||||
}
|
||||
if let Some(expr) = default {
|
||||
visitor.visit_expr(expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
impl AstNode for ast::TypeParamTypeVarTuple {
|
||||
|
@ -4355,11 +4359,18 @@ impl AstNode for ast::TypeParamTypeVarTuple {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_preorder<'a, V>(&'a self, _visitor: &mut V)
|
||||
fn visit_preorder<'a, V>(&'a self, visitor: &mut V)
|
||||
where
|
||||
V: PreorderVisitor<'a> + ?Sized,
|
||||
{
|
||||
let ast::TypeParamTypeVarTuple { range: _, name: _ } = self;
|
||||
let ast::TypeParamTypeVarTuple {
|
||||
range: _,
|
||||
name: _,
|
||||
default,
|
||||
} = self;
|
||||
if let Some(expr) = default {
|
||||
visitor.visit_expr(expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
impl AstNode for ast::TypeParamParamSpec {
|
||||
|
@ -4391,11 +4402,18 @@ impl AstNode for ast::TypeParamParamSpec {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_preorder<'a, V>(&'a self, _visitor: &mut V)
|
||||
fn visit_preorder<'a, V>(&'a self, visitor: &mut V)
|
||||
where
|
||||
V: PreorderVisitor<'a> + ?Sized,
|
||||
{
|
||||
let ast::TypeParamParamSpec { range: _, name: _ } = self;
|
||||
let ast::TypeParamParamSpec {
|
||||
range: _,
|
||||
name: _,
|
||||
default,
|
||||
} = self;
|
||||
if let Some(expr) = default {
|
||||
visitor.visit_expr(expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
impl AstNode for ast::FString {
|
||||
|
|
|
@ -3132,6 +3132,7 @@ pub struct TypeParamTypeVar {
|
|||
pub range: TextRange,
|
||||
pub name: Identifier,
|
||||
pub bound: Option<Box<Expr>>,
|
||||
pub default: Option<Box<Expr>>,
|
||||
}
|
||||
|
||||
impl From<TypeParamTypeVar> for TypeParam {
|
||||
|
@ -3145,6 +3146,7 @@ impl From<TypeParamTypeVar> for TypeParam {
|
|||
pub struct TypeParamParamSpec {
|
||||
pub range: TextRange,
|
||||
pub name: Identifier,
|
||||
pub default: Option<Box<Expr>>,
|
||||
}
|
||||
|
||||
impl From<TypeParamParamSpec> for TypeParam {
|
||||
|
@ -3158,6 +3160,7 @@ impl From<TypeParamParamSpec> for TypeParam {
|
|||
pub struct TypeParamTypeVarTuple {
|
||||
pub range: TextRange,
|
||||
pub name: Identifier,
|
||||
pub default: Option<Box<Expr>>,
|
||||
}
|
||||
|
||||
impl From<TypeParamTypeVarTuple> for TypeParam {
|
||||
|
|
|
@ -7,7 +7,8 @@ use crate::{
|
|||
self as ast, Alias, Arguments, BoolOp, BytesLiteral, CmpOp, Comprehension, Decorator,
|
||||
ElifElseClause, ExceptHandler, Expr, ExprContext, FString, FStringElement, FStringPart,
|
||||
Keyword, MatchCase, Operator, Parameter, Parameters, Pattern, PatternArguments, PatternKeyword,
|
||||
Stmt, StringLiteral, TypeParam, TypeParamTypeVar, TypeParams, UnaryOp, WithItem,
|
||||
Stmt, StringLiteral, TypeParam, TypeParamParamSpec, TypeParamTypeVar, TypeParamTypeVarTuple,
|
||||
TypeParams, UnaryOp, WithItem,
|
||||
};
|
||||
|
||||
/// A trait for AST visitors. Visits all nodes in the AST recursively in evaluation-order.
|
||||
|
@ -666,14 +667,35 @@ pub fn walk_type_param<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, type_param:
|
|||
match type_param {
|
||||
TypeParam::TypeVar(TypeParamTypeVar {
|
||||
bound,
|
||||
default,
|
||||
name: _,
|
||||
range: _,
|
||||
}) => {
|
||||
if let Some(expr) = bound {
|
||||
visitor.visit_expr(expr);
|
||||
}
|
||||
if let Some(expr) = default {
|
||||
visitor.visit_expr(expr);
|
||||
}
|
||||
}
|
||||
TypeParam::TypeVarTuple(TypeParamTypeVarTuple {
|
||||
default,
|
||||
name: _,
|
||||
range: _,
|
||||
}) => {
|
||||
if let Some(expr) = default {
|
||||
visitor.visit_expr(expr);
|
||||
}
|
||||
}
|
||||
TypeParam::ParamSpec(TypeParamParamSpec {
|
||||
default,
|
||||
name: _,
|
||||
range: _,
|
||||
}) => {
|
||||
if let Some(expr) = default {
|
||||
visitor.visit_expr(expr);
|
||||
}
|
||||
}
|
||||
TypeParam::TypeVarTuple(_) | TypeParam::ParamSpec(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,8 @@ use crate::{
|
|||
self as ast, Alias, Arguments, BoolOp, BytesLiteral, CmpOp, Comprehension, Decorator,
|
||||
ElifElseClause, ExceptHandler, Expr, ExprContext, FString, FStringElement, Keyword, MatchCase,
|
||||
Operator, Parameter, Parameters, Pattern, PatternArguments, PatternKeyword, Stmt,
|
||||
StringLiteral, TypeParam, TypeParamTypeVar, TypeParams, UnaryOp, WithItem,
|
||||
StringLiteral, TypeParam, TypeParamParamSpec, TypeParamTypeVar, TypeParamTypeVarTuple,
|
||||
TypeParams, UnaryOp, WithItem,
|
||||
};
|
||||
|
||||
/// A trait for transforming ASTs. Visits all nodes in the AST recursively in evaluation-order.
|
||||
|
@ -652,14 +653,35 @@ pub fn walk_type_param<V: Transformer + ?Sized>(visitor: &V, type_param: &mut Ty
|
|||
match type_param {
|
||||
TypeParam::TypeVar(TypeParamTypeVar {
|
||||
bound,
|
||||
default,
|
||||
name: _,
|
||||
range: _,
|
||||
}) => {
|
||||
if let Some(expr) = bound {
|
||||
visitor.visit_expr(expr);
|
||||
}
|
||||
if let Some(expr) = default {
|
||||
visitor.visit_expr(expr);
|
||||
}
|
||||
}
|
||||
TypeParam::TypeVarTuple(TypeParamTypeVarTuple {
|
||||
default,
|
||||
name: _,
|
||||
range: _,
|
||||
}) => {
|
||||
if let Some(expr) = default {
|
||||
visitor.visit_expr(expr);
|
||||
}
|
||||
}
|
||||
TypeParam::ParamSpec(TypeParamParamSpec {
|
||||
default,
|
||||
name: _,
|
||||
range: _,
|
||||
}) => {
|
||||
if let Some(expr) = default {
|
||||
visitor.visit_expr(expr);
|
||||
}
|
||||
}
|
||||
TypeParam::TypeVarTuple(_) | TypeParam::ParamSpec(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue