#![allow(clippy::derive_partial_eq_without_eq)] use itertools::Itertools; use std::fmt; use std::fmt::Debug; use std::ops::Deref; use num_bigint::BigInt; use ruff_text_size::{Ranged, TextRange, TextSize}; /// See also [mod](https://docs.python.org/3/library/ast.html#ast.mod) #[derive(Clone, Debug, PartialEq, is_macro::Is)] pub enum Mod { Module(ModModule), Expression(ModExpression), } /// See also [Module](https://docs.python.org/3/library/ast.html#ast.Module) #[derive(Clone, Debug, PartialEq)] pub struct ModModule { pub range: TextRange, pub body: Vec, } impl From for Mod { fn from(payload: ModModule) -> Self { Mod::Module(payload) } } /// See also [Expression](https://docs.python.org/3/library/ast.html#ast.Expression) #[derive(Clone, Debug, PartialEq)] pub struct ModExpression { pub range: TextRange, pub body: Box, } impl From for Mod { fn from(payload: ModExpression) -> Self { Mod::Expression(payload) } } /// See also [stmt](https://docs.python.org/3/library/ast.html#ast.stmt) #[derive(Clone, Debug, PartialEq, is_macro::Is)] pub enum Stmt { #[is(name = "function_def_stmt")] FunctionDef(StmtFunctionDef), #[is(name = "class_def_stmt")] ClassDef(StmtClassDef), #[is(name = "return_stmt")] Return(StmtReturn), #[is(name = "delete_stmt")] Delete(StmtDelete), #[is(name = "assign_stmt")] Assign(StmtAssign), #[is(name = "aug_assign_stmt")] AugAssign(StmtAugAssign), #[is(name = "ann_assign_stmt")] AnnAssign(StmtAnnAssign), #[is(name = "type_alias_stmt")] TypeAlias(StmtTypeAlias), #[is(name = "for_stmt")] For(StmtFor), #[is(name = "while_stmt")] While(StmtWhile), #[is(name = "if_stmt")] If(StmtIf), #[is(name = "with_stmt")] With(StmtWith), #[is(name = "match_stmt")] Match(StmtMatch), #[is(name = "raise_stmt")] Raise(StmtRaise), #[is(name = "try_stmt")] Try(StmtTry), #[is(name = "assert_stmt")] Assert(StmtAssert), #[is(name = "import_stmt")] Import(StmtImport), #[is(name = "import_from_stmt")] ImportFrom(StmtImportFrom), #[is(name = "global_stmt")] Global(StmtGlobal), #[is(name = "nonlocal_stmt")] Nonlocal(StmtNonlocal), #[is(name = "expr_stmt")] Expr(StmtExpr), #[is(name = "pass_stmt")] Pass(StmtPass), #[is(name = "break_stmt")] Break(StmtBreak), #[is(name = "continue_stmt")] Continue(StmtContinue), // Jupyter notebook specific #[is(name = "ipy_escape_command_stmt")] IpyEscapeCommand(StmtIpyEscapeCommand), } /// An AST node used to represent a IPython escape command at the statement level. /// /// For example, /// ```python /// %matplotlib inline /// ``` /// /// ## Terminology /// /// Escape commands are special IPython syntax which starts with a token to identify /// the escape kind followed by the command value itself. [Escape kind] are the kind /// of escape commands that are recognized by the token: `%`, `%%`, `!`, `!!`, /// `?`, `??`, `/`, `;`, and `,`. /// /// Help command (or Dynamic Object Introspection as it's called) are the escape commands /// of the kind `?` and `??`. For example, `?str.replace`. Help end command are a subset /// of Help command where the token can be at the end of the line i.e., after the value. /// For example, `str.replace?`. /// /// Here's where things get tricky. I'll divide the help end command into two types for /// better understanding: /// 1. Strict version: The token is _only_ at the end of the line. For example, /// `str.replace?` or `str.replace??`. /// 2. Combined version: Along with the `?` or `??` token, which are at the end of the /// line, there are other escape kind tokens that are present at the start as well. /// For example, `%matplotlib?` or `%%timeit?`. /// /// Priority comes into picture for the "Combined version" mentioned above. How do /// we determine the escape kind if there are tokens on both side of the value, i.e., which /// token to choose? The Help end command always takes priority over any other token which /// means that if there is `?`/`??` at the end then that is used to determine the kind. /// For example, in `%matplotlib?` the escape kind is determined using the `?` token /// instead of `%` token. /// /// ## Syntax /// /// `` /// /// The simplest form is an escape kind token followed by the command value. For example, /// `%matplotlib inline`, `/foo`, `!pwd`, etc. /// /// `` /// /// The help end escape command would be the reverse of the above syntax. Here, the /// escape kind token can only be either `?` or `??` and it is at the end of the line. /// For example, `str.replace?`, `math.pi??`, etc. /// /// `` /// /// The final syntax is the combined version of the above two. For example, `%matplotlib?`, /// `%%timeit??`, etc. /// /// [Escape kind]: IpyEscapeKind #[derive(Clone, Debug, PartialEq)] pub struct StmtIpyEscapeCommand { pub range: TextRange, pub kind: IpyEscapeKind, pub value: String, } impl From for Stmt { fn from(payload: StmtIpyEscapeCommand) -> Self { Stmt::IpyEscapeCommand(payload) } } /// See also [FunctionDef](https://docs.python.org/3/library/ast.html#ast.FunctionDef) and /// [AsyncFunctionDef](https://docs.python.org/3/library/ast.html#ast.AsyncFunctionDef). /// /// This type differs from the original Python AST, as it collapses the /// synchronous and asynchronous variants into a single type. #[derive(Clone, Debug, PartialEq)] pub struct StmtFunctionDef { pub range: TextRange, pub is_async: bool, pub decorator_list: Vec, pub name: Identifier, pub type_params: Option, pub parameters: Box, pub returns: Option>, pub body: Vec, } impl From for Stmt { fn from(payload: StmtFunctionDef) -> Self { Stmt::FunctionDef(payload) } } /// See also [ClassDef](https://docs.python.org/3/library/ast.html#ast.ClassDef) #[derive(Clone, Debug, PartialEq)] pub struct StmtClassDef { pub range: TextRange, pub decorator_list: Vec, pub name: Identifier, pub type_params: Option>, pub arguments: Option>, pub body: Vec, } impl StmtClassDef { /// Return an iterator over the bases of the class. pub fn bases(&self) -> &[Expr] { match &self.arguments { Some(arguments) => &arguments.args, None => &[], } } /// Return an iterator over the metaclass keywords of the class. pub fn keywords(&self) -> &[Keyword] { match &self.arguments { Some(arguments) => &arguments.keywords, None => &[], } } } impl From for Stmt { fn from(payload: StmtClassDef) -> Self { Stmt::ClassDef(payload) } } /// See also [Return](https://docs.python.org/3/library/ast.html#ast.Return) #[derive(Clone, Debug, PartialEq)] pub struct StmtReturn { pub range: TextRange, pub value: Option>, } impl From for Stmt { fn from(payload: StmtReturn) -> Self { Stmt::Return(payload) } } /// See also [Delete](https://docs.python.org/3/library/ast.html#ast.Delete) #[derive(Clone, Debug, PartialEq)] pub struct StmtDelete { pub range: TextRange, pub targets: Vec, } impl From for Stmt { fn from(payload: StmtDelete) -> Self { Stmt::Delete(payload) } } /// See also [TypeAlias](https://docs.python.org/3/library/ast.html#ast.TypeAlias) #[derive(Clone, Debug, PartialEq)] pub struct StmtTypeAlias { pub range: TextRange, pub name: Box, pub type_params: Option, pub value: Box, } impl From for Stmt { fn from(payload: StmtTypeAlias) -> Self { Stmt::TypeAlias(payload) } } /// See also [Assign](https://docs.python.org/3/library/ast.html#ast.Assign) #[derive(Clone, Debug, PartialEq)] pub struct StmtAssign { pub range: TextRange, pub targets: Vec, pub value: Box, } impl From for Stmt { fn from(payload: StmtAssign) -> Self { Stmt::Assign(payload) } } /// See also [AugAssign](https://docs.python.org/3/library/ast.html#ast.AugAssign) #[derive(Clone, Debug, PartialEq)] pub struct StmtAugAssign { pub range: TextRange, pub target: Box, pub op: Operator, pub value: Box, } impl From for Stmt { fn from(payload: StmtAugAssign) -> Self { Stmt::AugAssign(payload) } } /// See also [AnnAssign](https://docs.python.org/3/library/ast.html#ast.AnnAssign) #[derive(Clone, Debug, PartialEq)] pub struct StmtAnnAssign { pub range: TextRange, pub target: Box, pub annotation: Box, pub value: Option>, pub simple: bool, } impl From for Stmt { fn from(payload: StmtAnnAssign) -> Self { Stmt::AnnAssign(payload) } } /// See also [For](https://docs.python.org/3/library/ast.html#ast.For) and /// [AsyncFor](https://docs.python.org/3/library/ast.html#ast.AsyncFor). /// /// This type differs from the original Python AST, as it collapses the /// synchronous and asynchronous variants into a single type. #[derive(Clone, Debug, PartialEq)] pub struct StmtFor { pub range: TextRange, pub is_async: bool, pub target: Box, pub iter: Box, pub body: Vec, pub orelse: Vec, } impl From for Stmt { fn from(payload: StmtFor) -> Self { Stmt::For(payload) } } /// See also [While](https://docs.python.org/3/library/ast.html#ast.While) and /// [AsyncWhile](https://docs.python.org/3/library/ast.html#ast.AsyncWhile). #[derive(Clone, Debug, PartialEq)] pub struct StmtWhile { pub range: TextRange, pub test: Box, pub body: Vec, pub orelse: Vec, } impl From for Stmt { fn from(payload: StmtWhile) -> Self { Stmt::While(payload) } } /// See also [If](https://docs.python.org/3/library/ast.html#ast.If) #[derive(Clone, Debug, PartialEq)] pub struct StmtIf { pub range: TextRange, pub test: Box, pub body: Vec, pub elif_else_clauses: Vec, } impl From for Stmt { fn from(payload: StmtIf) -> Self { Stmt::If(payload) } } #[derive(Clone, Debug, PartialEq)] pub struct ElifElseClause { pub range: TextRange, pub test: Option, pub body: Vec, } /// See also [With](https://docs.python.org/3/library/ast.html#ast.With) and /// [AsyncWith](https://docs.python.org/3/library/ast.html#ast.AsyncWith). /// /// This type differs from the original Python AST, as it collapses the /// synchronous and asynchronous variants into a single type. #[derive(Clone, Debug, PartialEq)] pub struct StmtWith { pub range: TextRange, pub is_async: bool, pub items: Vec, pub body: Vec, } impl From for Stmt { fn from(payload: StmtWith) -> Self { Stmt::With(payload) } } /// See also [Match](https://docs.python.org/3/library/ast.html#ast.Match) #[derive(Clone, Debug, PartialEq)] pub struct StmtMatch { pub range: TextRange, pub subject: Box, pub cases: Vec, } impl From for Stmt { fn from(payload: StmtMatch) -> Self { Stmt::Match(payload) } } /// See also [Raise](https://docs.python.org/3/library/ast.html#ast.Raise) #[derive(Clone, Debug, PartialEq)] pub struct StmtRaise { pub range: TextRange, pub exc: Option>, pub cause: Option>, } impl From for Stmt { fn from(payload: StmtRaise) -> Self { Stmt::Raise(payload) } } /// See also [Try](https://docs.python.org/3/library/ast.html#ast.Try) and /// [TryStar](https://docs.python.org/3/library/ast.html#ast.TryStar) #[derive(Clone, Debug, PartialEq)] pub struct StmtTry { pub range: TextRange, pub body: Vec, pub handlers: Vec, pub orelse: Vec, pub finalbody: Vec, pub is_star: bool, } impl From for Stmt { fn from(payload: StmtTry) -> Self { Stmt::Try(payload) } } /// See also [Assert](https://docs.python.org/3/library/ast.html#ast.Assert) #[derive(Clone, Debug, PartialEq)] pub struct StmtAssert { pub range: TextRange, pub test: Box, pub msg: Option>, } impl From for Stmt { fn from(payload: StmtAssert) -> Self { Stmt::Assert(payload) } } /// See also [Import](https://docs.python.org/3/library/ast.html#ast.Import) #[derive(Clone, Debug, PartialEq)] pub struct StmtImport { pub range: TextRange, pub names: Vec, } impl From for Stmt { fn from(payload: StmtImport) -> Self { Stmt::Import(payload) } } /// See also [ImportFrom](https://docs.python.org/3/library/ast.html#ast.ImportFrom) #[derive(Clone, Debug, PartialEq)] pub struct StmtImportFrom { pub range: TextRange, pub module: Option, pub names: Vec, pub level: Option, } impl From for Stmt { fn from(payload: StmtImportFrom) -> Self { Stmt::ImportFrom(payload) } } /// See also [Global](https://docs.python.org/3/library/ast.html#ast.Global) #[derive(Clone, Debug, PartialEq)] pub struct StmtGlobal { pub range: TextRange, pub names: Vec, } impl From for Stmt { fn from(payload: StmtGlobal) -> Self { Stmt::Global(payload) } } /// See also [Nonlocal](https://docs.python.org/3/library/ast.html#ast.Nonlocal) #[derive(Clone, Debug, PartialEq)] pub struct StmtNonlocal { pub range: TextRange, pub names: Vec, } impl From for Stmt { fn from(payload: StmtNonlocal) -> Self { Stmt::Nonlocal(payload) } } /// See also [Expr](https://docs.python.org/3/library/ast.html#ast.Expr) #[derive(Clone, Debug, PartialEq)] pub struct StmtExpr { pub range: TextRange, pub value: Box, } impl From for Stmt { fn from(payload: StmtExpr) -> Self { Stmt::Expr(payload) } } /// See also [Pass](https://docs.python.org/3/library/ast.html#ast.Pass) #[derive(Clone, Debug, PartialEq)] pub struct StmtPass { pub range: TextRange, } impl From for Stmt { fn from(payload: StmtPass) -> Self { Stmt::Pass(payload) } } /// See also [Break](https://docs.python.org/3/library/ast.html#ast.Break) #[derive(Clone, Debug, PartialEq)] pub struct StmtBreak { pub range: TextRange, } impl From for Stmt { fn from(payload: StmtBreak) -> Self { Stmt::Break(payload) } } /// See also [Continue](https://docs.python.org/3/library/ast.html#ast.Continue) #[derive(Clone, Debug, PartialEq)] pub struct StmtContinue { pub range: TextRange, } impl From for Stmt { fn from(payload: StmtContinue) -> Self { Stmt::Continue(payload) } } /// See also [expr](https://docs.python.org/3/library/ast.html#ast.expr) #[derive(Clone, Debug, PartialEq, is_macro::Is)] pub enum Expr { #[is(name = "bool_op_expr")] BoolOp(ExprBoolOp), #[is(name = "named_expr_expr")] NamedExpr(ExprNamedExpr), #[is(name = "bin_op_expr")] BinOp(ExprBinOp), #[is(name = "unary_op_expr")] UnaryOp(ExprUnaryOp), #[is(name = "lambda_expr")] Lambda(ExprLambda), #[is(name = "if_exp_expr")] IfExp(ExprIfExp), #[is(name = "dict_expr")] Dict(ExprDict), #[is(name = "set_expr")] Set(ExprSet), #[is(name = "list_comp_expr")] ListComp(ExprListComp), #[is(name = "set_comp_expr")] SetComp(ExprSetComp), #[is(name = "dict_comp_expr")] DictComp(ExprDictComp), #[is(name = "generator_exp_expr")] GeneratorExp(ExprGeneratorExp), #[is(name = "await_expr")] Await(ExprAwait), #[is(name = "yield_expr")] Yield(ExprYield), #[is(name = "yield_from_expr")] YieldFrom(ExprYieldFrom), #[is(name = "compare_expr")] Compare(ExprCompare), #[is(name = "call_expr")] Call(ExprCall), #[is(name = "formatted_value_expr")] FormattedValue(ExprFormattedValue), #[is(name = "f_string_expr")] FString(ExprFString), #[is(name = "constant_expr")] Constant(ExprConstant), #[is(name = "attribute_expr")] Attribute(ExprAttribute), #[is(name = "subscript_expr")] Subscript(ExprSubscript), #[is(name = "starred_expr")] Starred(ExprStarred), #[is(name = "name_expr")] Name(ExprName), #[is(name = "list_expr")] List(ExprList), #[is(name = "tuple_expr")] Tuple(ExprTuple), #[is(name = "slice_expr")] Slice(ExprSlice), // Jupyter notebook specific #[is(name = "ipy_escape_command_expr")] IpyEscapeCommand(ExprIpyEscapeCommand), } /// An AST node used to represent a IPython escape command at the expression level. /// /// For example, /// ```python /// dir = !pwd /// ``` /// /// Here, the escape kind can only be `!` or `%` otherwise it is a syntax error. /// /// For more information related to terminology and syntax of escape commands, /// see [`StmtIpyEscapeCommand`]. #[derive(Clone, Debug, PartialEq)] pub struct ExprIpyEscapeCommand { pub range: TextRange, pub kind: IpyEscapeKind, pub value: String, } impl From for Expr { fn from(payload: ExprIpyEscapeCommand) -> Self { Expr::IpyEscapeCommand(payload) } } /// See also [BoolOp](https://docs.python.org/3/library/ast.html#ast.BoolOp) #[derive(Clone, Debug, PartialEq)] pub struct ExprBoolOp { pub range: TextRange, pub op: BoolOp, pub values: Vec, } impl From for Expr { fn from(payload: ExprBoolOp) -> Self { Expr::BoolOp(payload) } } /// See also [NamedExpr](https://docs.python.org/3/library/ast.html#ast.NamedExpr) #[derive(Clone, Debug, PartialEq)] pub struct ExprNamedExpr { pub range: TextRange, pub target: Box, pub value: Box, } impl From for Expr { fn from(payload: ExprNamedExpr) -> Self { Expr::NamedExpr(payload) } } /// See also [BinOp](https://docs.python.org/3/library/ast.html#ast.BinOp) #[derive(Clone, Debug, PartialEq)] pub struct ExprBinOp { pub range: TextRange, pub left: Box, pub op: Operator, pub right: Box, } impl From for Expr { fn from(payload: ExprBinOp) -> Self { Expr::BinOp(payload) } } /// See also [UnaryOp](https://docs.python.org/3/library/ast.html#ast.UnaryOp) #[derive(Clone, Debug, PartialEq)] pub struct ExprUnaryOp { pub range: TextRange, pub op: UnaryOp, pub operand: Box, } impl From for Expr { fn from(payload: ExprUnaryOp) -> Self { Expr::UnaryOp(payload) } } /// See also [Lambda](https://docs.python.org/3/library/ast.html#ast.Lambda) #[derive(Clone, Debug, PartialEq)] pub struct ExprLambda { pub range: TextRange, pub parameters: Option>, pub body: Box, } impl From for Expr { fn from(payload: ExprLambda) -> Self { Expr::Lambda(payload) } } /// See also [IfExp](https://docs.python.org/3/library/ast.html#ast.IfExp) #[derive(Clone, Debug, PartialEq)] pub struct ExprIfExp { pub range: TextRange, pub test: Box, pub body: Box, pub orelse: Box, } impl From for Expr { fn from(payload: ExprIfExp) -> Self { Expr::IfExp(payload) } } /// See also [Dict](https://docs.python.org/3/library/ast.html#ast.Dict) #[derive(Clone, Debug, PartialEq)] pub struct ExprDict { pub range: TextRange, pub keys: Vec>, pub values: Vec, } impl From for Expr { fn from(payload: ExprDict) -> Self { Expr::Dict(payload) } } /// See also [Set](https://docs.python.org/3/library/ast.html#ast.Set) #[derive(Clone, Debug, PartialEq)] pub struct ExprSet { pub range: TextRange, pub elts: Vec, } impl From for Expr { fn from(payload: ExprSet) -> Self { Expr::Set(payload) } } /// See also [ListComp](https://docs.python.org/3/library/ast.html#ast.ListComp) #[derive(Clone, Debug, PartialEq)] pub struct ExprListComp { pub range: TextRange, pub elt: Box, pub generators: Vec, } impl From for Expr { fn from(payload: ExprListComp) -> Self { Expr::ListComp(payload) } } /// See also [SetComp](https://docs.python.org/3/library/ast.html#ast.SetComp) #[derive(Clone, Debug, PartialEq)] pub struct ExprSetComp { pub range: TextRange, pub elt: Box, pub generators: Vec, } impl From for Expr { fn from(payload: ExprSetComp) -> Self { Expr::SetComp(payload) } } /// See also [DictComp](https://docs.python.org/3/library/ast.html#ast.DictComp) #[derive(Clone, Debug, PartialEq)] pub struct ExprDictComp { pub range: TextRange, pub key: Box, pub value: Box, pub generators: Vec, } impl From for Expr { fn from(payload: ExprDictComp) -> Self { Expr::DictComp(payload) } } /// See also [GeneratorExp](https://docs.python.org/3/library/ast.html#ast.GeneratorExp) #[derive(Clone, Debug, PartialEq)] pub struct ExprGeneratorExp { pub range: TextRange, pub elt: Box, pub generators: Vec, } impl From for Expr { fn from(payload: ExprGeneratorExp) -> Self { Expr::GeneratorExp(payload) } } /// See also [Await](https://docs.python.org/3/library/ast.html#ast.Await) #[derive(Clone, Debug, PartialEq)] pub struct ExprAwait { pub range: TextRange, pub value: Box, } impl From for Expr { fn from(payload: ExprAwait) -> Self { Expr::Await(payload) } } /// See also [Yield](https://docs.python.org/3/library/ast.html#ast.Yield) #[derive(Clone, Debug, PartialEq)] pub struct ExprYield { pub range: TextRange, pub value: Option>, } impl From for Expr { fn from(payload: ExprYield) -> Self { Expr::Yield(payload) } } /// See also [YieldFrom](https://docs.python.org/3/library/ast.html#ast.YieldFrom) #[derive(Clone, Debug, PartialEq)] pub struct ExprYieldFrom { pub range: TextRange, pub value: Box, } impl From for Expr { fn from(payload: ExprYieldFrom) -> Self { Expr::YieldFrom(payload) } } /// See also [Compare](https://docs.python.org/3/library/ast.html#ast.Compare) #[derive(Clone, Debug, PartialEq)] pub struct ExprCompare { pub range: TextRange, pub left: Box, pub ops: Vec, pub comparators: Vec, } impl From for Expr { fn from(payload: ExprCompare) -> Self { Expr::Compare(payload) } } /// See also [Call](https://docs.python.org/3/library/ast.html#ast.Call) #[derive(Clone, Debug, PartialEq)] pub struct ExprCall { pub range: TextRange, pub func: Box, pub arguments: Arguments, } impl From for Expr { fn from(payload: ExprCall) -> Self { Expr::Call(payload) } } /// See also [FormattedValue](https://docs.python.org/3/library/ast.html#ast.FormattedValue) #[derive(Clone, Debug, PartialEq)] pub struct ExprFormattedValue { pub range: TextRange, pub value: Box, pub debug_text: Option, pub conversion: ConversionFlag, pub format_spec: Option>, } impl From for Expr { fn from(payload: ExprFormattedValue) -> Self { Expr::FormattedValue(payload) } } /// Transforms a value prior to formatting it. #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, is_macro::Is)] #[repr(i8)] #[allow(clippy::cast_possible_wrap)] pub enum ConversionFlag { /// No conversion None = -1, // CPython uses -1 /// Converts by calling `str()`. Str = b's' as i8, /// Converts by calling `ascii()`. Ascii = b'a' as i8, /// Converts by calling `repr()`. Repr = b'r' as i8, } impl ConversionFlag { pub fn to_byte(&self) -> Option { match self { Self::None => None, flag => Some(*flag as u8), } } pub fn to_char(&self) -> Option { Some(self.to_byte()? as char) } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct DebugText { /// The text between the `{` and the expression node. pub leading: String, /// The text between the expression and the conversion, the format_spec, or the `}`, depending on what's present in the source pub trailing: String, } /// See also [JoinedStr](https://docs.python.org/3/library/ast.html#ast.JoinedStr) #[derive(Clone, Debug, PartialEq)] pub struct ExprFString { pub range: TextRange, pub values: Vec, /// Whether the f-string contains multiple string tokens that were implicitly concatenated. pub implicit_concatenated: bool, } impl From for Expr { fn from(payload: ExprFString) -> Self { Expr::FString(payload) } } /// See also [Constant](https://docs.python.org/3/library/ast.html#ast.Constant) #[derive(Clone, Debug, PartialEq)] pub struct ExprConstant { pub range: TextRange, pub value: Constant, } impl From for Expr { fn from(payload: ExprConstant) -> Self { Expr::Constant(payload) } } /// See also [Attribute](https://docs.python.org/3/library/ast.html#ast.Attribute) #[derive(Clone, Debug, PartialEq)] pub struct ExprAttribute { pub range: TextRange, pub value: Box, pub attr: Identifier, pub ctx: ExprContext, } impl From for Expr { fn from(payload: ExprAttribute) -> Self { Expr::Attribute(payload) } } /// See also [Subscript](https://docs.python.org/3/library/ast.html#ast.Subscript) #[derive(Clone, Debug, PartialEq)] pub struct ExprSubscript { pub range: TextRange, pub value: Box, pub slice: Box, pub ctx: ExprContext, } impl From for Expr { fn from(payload: ExprSubscript) -> Self { Expr::Subscript(payload) } } /// See also [Starred](https://docs.python.org/3/library/ast.html#ast.Starred) #[derive(Clone, Debug, PartialEq)] pub struct ExprStarred { pub range: TextRange, pub value: Box, pub ctx: ExprContext, } impl From for Expr { fn from(payload: ExprStarred) -> Self { Expr::Starred(payload) } } /// See also [Name](https://docs.python.org/3/library/ast.html#ast.Name) #[derive(Clone, Debug, PartialEq)] pub struct ExprName { pub range: TextRange, pub id: String, pub ctx: ExprContext, } impl From for Expr { fn from(payload: ExprName) -> Self { Expr::Name(payload) } } /// See also [List](https://docs.python.org/3/library/ast.html#ast.List) #[derive(Clone, Debug, PartialEq)] pub struct ExprList { pub range: TextRange, pub elts: Vec, pub ctx: ExprContext, } impl From for Expr { fn from(payload: ExprList) -> Self { Expr::List(payload) } } /// See also [Tuple](https://docs.python.org/3/library/ast.html#ast.Tuple) #[derive(Clone, Debug, PartialEq)] pub struct ExprTuple { pub range: TextRange, pub elts: Vec, pub ctx: ExprContext, } impl From for Expr { fn from(payload: ExprTuple) -> Self { Expr::Tuple(payload) } } /// See also [Slice](https://docs.python.org/3/library/ast.html#ast.Slice) #[derive(Clone, Debug, PartialEq)] pub struct ExprSlice { pub range: TextRange, pub lower: Option>, pub upper: Option>, pub step: Option>, } impl From for Expr { fn from(payload: ExprSlice) -> Self { Expr::Slice(payload) } } /// See also [expr_context](https://docs.python.org/3/library/ast.html#ast.expr_context) #[derive(Clone, Debug, PartialEq, is_macro::Is, Copy, Hash, Eq)] pub enum ExprContext { Load, Store, Del, } impl ExprContext { #[inline] pub const fn load(&self) -> Option { match self { ExprContext::Load => Some(ExprContextLoad), _ => None, } } #[inline] pub const fn store(&self) -> Option { match self { ExprContext::Store => Some(ExprContextStore), _ => None, } } #[inline] pub const fn del(&self) -> Option { match self { ExprContext::Del => Some(ExprContextDel), _ => None, } } } pub struct ExprContextLoad; impl From for ExprContext { fn from(_: ExprContextLoad) -> Self { ExprContext::Load } } impl std::cmp::PartialEq for ExprContextLoad { #[inline] fn eq(&self, other: &ExprContext) -> bool { matches!(other, ExprContext::Load) } } pub struct ExprContextStore; impl From for ExprContext { fn from(_: ExprContextStore) -> Self { ExprContext::Store } } impl std::cmp::PartialEq for ExprContextStore { #[inline] fn eq(&self, other: &ExprContext) -> bool { matches!(other, ExprContext::Store) } } pub struct ExprContextDel; impl From for ExprContext { fn from(_: ExprContextDel) -> Self { ExprContext::Del } } impl std::cmp::PartialEq for ExprContextDel { #[inline] fn eq(&self, other: &ExprContext) -> bool { matches!(other, ExprContext::Del) } } /// See also [boolop](https://docs.python.org/3/library/ast.html#ast.BoolOp) #[derive(Clone, Debug, PartialEq, is_macro::Is, Copy, Hash, Eq)] pub enum BoolOp { And, Or, } impl BoolOp { #[inline] pub const fn and(&self) -> Option { match self { BoolOp::And => Some(BoolOpAnd), BoolOp::Or => None, } } #[inline] pub const fn or(&self) -> Option { match self { BoolOp::Or => Some(BoolOpOr), BoolOp::And => None, } } } pub struct BoolOpAnd; impl From for BoolOp { fn from(_: BoolOpAnd) -> Self { BoolOp::And } } impl std::cmp::PartialEq for BoolOpAnd { #[inline] fn eq(&self, other: &BoolOp) -> bool { matches!(other, BoolOp::And) } } pub struct BoolOpOr; impl From for BoolOp { fn from(_: BoolOpOr) -> Self { BoolOp::Or } } impl std::cmp::PartialEq for BoolOpOr { #[inline] fn eq(&self, other: &BoolOp) -> bool { matches!(other, BoolOp::Or) } } /// See also [operator](https://docs.python.org/3/library/ast.html#ast.operator) #[derive(Clone, Debug, PartialEq, is_macro::Is, Copy, Hash, Eq)] pub enum Operator { Add, Sub, Mult, MatMult, Div, Mod, Pow, LShift, RShift, BitOr, BitXor, BitAnd, FloorDiv, } impl Operator { #[inline] pub const fn operator_add(&self) -> Option { match self { Operator::Add => Some(OperatorAdd), _ => None, } } #[inline] pub const fn operator_sub(&self) -> Option { match self { Operator::Sub => Some(OperatorSub), _ => None, } } #[inline] pub const fn operator_mult(&self) -> Option { match self { Operator::Mult => Some(OperatorMult), _ => None, } } #[inline] pub const fn operator_mat_mult(&self) -> Option { match self { Operator::MatMult => Some(OperatorMatMult), _ => None, } } #[inline] pub const fn operator_div(&self) -> Option { match self { Operator::Div => Some(OperatorDiv), _ => None, } } #[inline] pub const fn operator_mod(&self) -> Option { match self { Operator::Mod => Some(OperatorMod), _ => None, } } #[inline] pub const fn operator_pow(&self) -> Option { match self { Operator::Pow => Some(OperatorPow), _ => None, } } #[inline] pub const fn operator_l_shift(&self) -> Option { match self { Operator::LShift => Some(OperatorLShift), _ => None, } } #[inline] pub const fn operator_r_shift(&self) -> Option { match self { Operator::RShift => Some(OperatorRShift), _ => None, } } #[inline] pub const fn operator_bit_or(&self) -> Option { match self { Operator::BitOr => Some(OperatorBitOr), _ => None, } } #[inline] pub const fn operator_bit_xor(&self) -> Option { match self { Operator::BitXor => Some(OperatorBitXor), _ => None, } } #[inline] pub const fn operator_bit_and(&self) -> Option { match self { Operator::BitAnd => Some(OperatorBitAnd), _ => None, } } #[inline] pub const fn operator_floor_div(&self) -> Option { match self { Operator::FloorDiv => Some(OperatorFloorDiv), _ => None, } } } pub struct OperatorAdd; impl From for Operator { fn from(_: OperatorAdd) -> Self { Operator::Add } } impl std::cmp::PartialEq for OperatorAdd { #[inline] fn eq(&self, other: &Operator) -> bool { matches!(other, Operator::Add) } } pub struct OperatorSub; impl From for Operator { fn from(_: OperatorSub) -> Self { Operator::Sub } } impl std::cmp::PartialEq for OperatorSub { #[inline] fn eq(&self, other: &Operator) -> bool { matches!(other, Operator::Sub) } } pub struct OperatorMult; impl From for Operator { fn from(_: OperatorMult) -> Self { Operator::Mult } } impl std::cmp::PartialEq for OperatorMult { #[inline] fn eq(&self, other: &Operator) -> bool { matches!(other, Operator::Mult) } } pub struct OperatorMatMult; impl From for Operator { fn from(_: OperatorMatMult) -> Self { Operator::MatMult } } impl std::cmp::PartialEq for OperatorMatMult { #[inline] fn eq(&self, other: &Operator) -> bool { matches!(other, Operator::MatMult) } } pub struct OperatorDiv; impl From for Operator { fn from(_: OperatorDiv) -> Self { Operator::Div } } impl std::cmp::PartialEq for OperatorDiv { #[inline] fn eq(&self, other: &Operator) -> bool { matches!(other, Operator::Div) } } pub struct OperatorMod; impl From for Operator { fn from(_: OperatorMod) -> Self { Operator::Mod } } impl std::cmp::PartialEq for OperatorMod { #[inline] fn eq(&self, other: &Operator) -> bool { matches!(other, Operator::Mod) } } pub struct OperatorPow; impl From for Operator { fn from(_: OperatorPow) -> Self { Operator::Pow } } impl std::cmp::PartialEq for OperatorPow { #[inline] fn eq(&self, other: &Operator) -> bool { matches!(other, Operator::Pow) } } pub struct OperatorLShift; impl From for Operator { fn from(_: OperatorLShift) -> Self { Operator::LShift } } impl std::cmp::PartialEq for OperatorLShift { #[inline] fn eq(&self, other: &Operator) -> bool { matches!(other, Operator::LShift) } } pub struct OperatorRShift; impl From for Operator { fn from(_: OperatorRShift) -> Self { Operator::RShift } } impl std::cmp::PartialEq for OperatorRShift { #[inline] fn eq(&self, other: &Operator) -> bool { matches!(other, Operator::RShift) } } pub struct OperatorBitOr; impl From for Operator { fn from(_: OperatorBitOr) -> Self { Operator::BitOr } } impl std::cmp::PartialEq for OperatorBitOr { #[inline] fn eq(&self, other: &Operator) -> bool { matches!(other, Operator::BitOr) } } pub struct OperatorBitXor; impl From for Operator { fn from(_: OperatorBitXor) -> Self { Operator::BitXor } } impl std::cmp::PartialEq for OperatorBitXor { #[inline] fn eq(&self, other: &Operator) -> bool { matches!(other, Operator::BitXor) } } pub struct OperatorBitAnd; impl From for Operator { fn from(_: OperatorBitAnd) -> Self { Operator::BitAnd } } impl std::cmp::PartialEq for OperatorBitAnd { #[inline] fn eq(&self, other: &Operator) -> bool { matches!(other, Operator::BitAnd) } } pub struct OperatorFloorDiv; impl From for Operator { fn from(_: OperatorFloorDiv) -> Self { Operator::FloorDiv } } impl std::cmp::PartialEq for OperatorFloorDiv { #[inline] fn eq(&self, other: &Operator) -> bool { matches!(other, Operator::FloorDiv) } } /// See also [unaryop](https://docs.python.org/3/library/ast.html#ast.unaryop) #[derive(Clone, Debug, PartialEq, is_macro::Is, Copy, Hash, Eq)] pub enum UnaryOp { Invert, Not, UAdd, USub, } impl UnaryOp { #[inline] pub const fn invert(&self) -> Option { match self { UnaryOp::Invert => Some(UnaryOpInvert), _ => None, } } #[inline] pub const fn not(&self) -> Option { match self { UnaryOp::Not => Some(UnaryOpNot), _ => None, } } #[inline] pub const fn u_add(&self) -> Option { match self { UnaryOp::UAdd => Some(UnaryOpUAdd), _ => None, } } #[inline] pub const fn u_sub(&self) -> Option { match self { UnaryOp::USub => Some(UnaryOpUSub), _ => None, } } } pub struct UnaryOpInvert; impl From for UnaryOp { fn from(_: UnaryOpInvert) -> Self { UnaryOp::Invert } } impl std::cmp::PartialEq for UnaryOpInvert { #[inline] fn eq(&self, other: &UnaryOp) -> bool { matches!(other, UnaryOp::Invert) } } pub struct UnaryOpNot; impl From for UnaryOp { fn from(_: UnaryOpNot) -> Self { UnaryOp::Not } } impl std::cmp::PartialEq for UnaryOpNot { #[inline] fn eq(&self, other: &UnaryOp) -> bool { matches!(other, UnaryOp::Not) } } pub struct UnaryOpUAdd; impl From for UnaryOp { fn from(_: UnaryOpUAdd) -> Self { UnaryOp::UAdd } } impl std::cmp::PartialEq for UnaryOpUAdd { #[inline] fn eq(&self, other: &UnaryOp) -> bool { matches!(other, UnaryOp::UAdd) } } pub struct UnaryOpUSub; impl From for UnaryOp { fn from(_: UnaryOpUSub) -> Self { UnaryOp::USub } } impl std::cmp::PartialEq for UnaryOpUSub { #[inline] fn eq(&self, other: &UnaryOp) -> bool { matches!(other, UnaryOp::USub) } } /// See also [cmpop](https://docs.python.org/3/library/ast.html#ast.cmpop) #[derive(Clone, Debug, PartialEq, is_macro::Is, Copy, Hash, Eq)] pub enum CmpOp { Eq, NotEq, Lt, LtE, Gt, GtE, Is, IsNot, In, NotIn, } impl CmpOp { #[inline] pub const fn cmp_op_eq(&self) -> Option { match self { CmpOp::Eq => Some(CmpOpEq), _ => None, } } #[inline] pub const fn cmp_op_not_eq(&self) -> Option { match self { CmpOp::NotEq => Some(CmpOpNotEq), _ => None, } } #[inline] pub const fn cmp_op_lt(&self) -> Option { match self { CmpOp::Lt => Some(CmpOpLt), _ => None, } } #[inline] pub const fn cmp_op_lt_e(&self) -> Option { match self { CmpOp::LtE => Some(CmpOpLtE), _ => None, } } #[inline] pub const fn cmp_op_gt(&self) -> Option { match self { CmpOp::Gt => Some(CmpOpGt), _ => None, } } #[inline] pub const fn cmp_op_gt_e(&self) -> Option { match self { CmpOp::GtE => Some(CmpOpGtE), _ => None, } } #[inline] pub const fn cmp_op_is(&self) -> Option { match self { CmpOp::Is => Some(CmpOpIs), _ => None, } } #[inline] pub const fn cmp_op_is_not(&self) -> Option { match self { CmpOp::IsNot => Some(CmpOpIsNot), _ => None, } } #[inline] pub const fn cmp_op_in(&self) -> Option { match self { CmpOp::In => Some(CmpOpIn), _ => None, } } #[inline] pub const fn cmp_op_not_in(&self) -> Option { match self { CmpOp::NotIn => Some(CmpOpNotIn), _ => None, } } } pub struct CmpOpEq; impl From for CmpOp { fn from(_: CmpOpEq) -> Self { CmpOp::Eq } } impl std::cmp::PartialEq for CmpOpEq { #[inline] fn eq(&self, other: &CmpOp) -> bool { matches!(other, CmpOp::Eq) } } pub struct CmpOpNotEq; impl From for CmpOp { fn from(_: CmpOpNotEq) -> Self { CmpOp::NotEq } } impl std::cmp::PartialEq for CmpOpNotEq { #[inline] fn eq(&self, other: &CmpOp) -> bool { matches!(other, CmpOp::NotEq) } } pub struct CmpOpLt; impl From for CmpOp { fn from(_: CmpOpLt) -> Self { CmpOp::Lt } } impl std::cmp::PartialEq for CmpOpLt { #[inline] fn eq(&self, other: &CmpOp) -> bool { matches!(other, CmpOp::Lt) } } pub struct CmpOpLtE; impl From for CmpOp { fn from(_: CmpOpLtE) -> Self { CmpOp::LtE } } impl std::cmp::PartialEq for CmpOpLtE { #[inline] fn eq(&self, other: &CmpOp) -> bool { matches!(other, CmpOp::LtE) } } pub struct CmpOpGt; impl From for CmpOp { fn from(_: CmpOpGt) -> Self { CmpOp::Gt } } impl std::cmp::PartialEq for CmpOpGt { #[inline] fn eq(&self, other: &CmpOp) -> bool { matches!(other, CmpOp::Gt) } } pub struct CmpOpGtE; impl From for CmpOp { fn from(_: CmpOpGtE) -> Self { CmpOp::GtE } } impl std::cmp::PartialEq for CmpOpGtE { #[inline] fn eq(&self, other: &CmpOp) -> bool { matches!(other, CmpOp::GtE) } } pub struct CmpOpIs; impl From for CmpOp { fn from(_: CmpOpIs) -> Self { CmpOp::Is } } impl std::cmp::PartialEq for CmpOpIs { #[inline] fn eq(&self, other: &CmpOp) -> bool { matches!(other, CmpOp::Is) } } pub struct CmpOpIsNot; impl From for CmpOp { fn from(_: CmpOpIsNot) -> Self { CmpOp::IsNot } } impl std::cmp::PartialEq for CmpOpIsNot { #[inline] fn eq(&self, other: &CmpOp) -> bool { matches!(other, CmpOp::IsNot) } } pub struct CmpOpIn; impl From for CmpOp { fn from(_: CmpOpIn) -> Self { CmpOp::In } } impl std::cmp::PartialEq for CmpOpIn { #[inline] fn eq(&self, other: &CmpOp) -> bool { matches!(other, CmpOp::In) } } pub struct CmpOpNotIn; impl From for CmpOp { fn from(_: CmpOpNotIn) -> Self { CmpOp::NotIn } } impl std::cmp::PartialEq for CmpOpNotIn { #[inline] fn eq(&self, other: &CmpOp) -> bool { matches!(other, CmpOp::NotIn) } } /// See also [comprehension](https://docs.python.org/3/library/ast.html#ast.comprehension) #[derive(Clone, Debug, PartialEq)] pub struct Comprehension { pub range: TextRange, pub target: Expr, pub iter: Expr, pub ifs: Vec, pub is_async: bool, } /// See also [excepthandler](https://docs.python.org/3/library/ast.html#ast.excepthandler) #[derive(Clone, Debug, PartialEq, is_macro::Is)] pub enum ExceptHandler { ExceptHandler(ExceptHandlerExceptHandler), } /// See also [ExceptHandler](https://docs.python.org/3/library/ast.html#ast.ExceptHandler) #[derive(Clone, Debug, PartialEq)] pub struct ExceptHandlerExceptHandler { pub range: TextRange, pub type_: Option>, pub name: Option, pub body: Vec, } impl From for ExceptHandler { fn from(payload: ExceptHandlerExceptHandler) -> Self { ExceptHandler::ExceptHandler(payload) } } /// See also [arg](https://docs.python.org/3/library/ast.html#ast.arg) #[derive(Clone, Debug, PartialEq)] pub struct Parameter { pub range: TextRange, pub name: Identifier, pub annotation: Option>, } /// See also [keyword](https://docs.python.org/3/library/ast.html#ast.keyword) #[derive(Clone, Debug, PartialEq)] pub struct Keyword { pub range: TextRange, pub arg: Option, pub value: Expr, } /// See also [alias](https://docs.python.org/3/library/ast.html#ast.alias) #[derive(Clone, Debug, PartialEq)] pub struct Alias { pub range: TextRange, pub name: Identifier, pub asname: Option, } /// See also [withitem](https://docs.python.org/3/library/ast.html#ast.withitem) #[derive(Clone, Debug, PartialEq)] pub struct WithItem { pub range: TextRange, pub context_expr: Expr, pub optional_vars: Option>, } /// See also [match_case](https://docs.python.org/3/library/ast.html#ast.match_case) #[derive(Clone, Debug, PartialEq)] pub struct MatchCase { pub range: TextRange, pub pattern: Pattern, pub guard: Option>, pub body: Vec, } /// See also [pattern](https://docs.python.org/3/library/ast.html#ast.pattern) #[derive(Clone, Debug, PartialEq, is_macro::Is)] pub enum Pattern { MatchValue(PatternMatchValue), MatchSingleton(PatternMatchSingleton), MatchSequence(PatternMatchSequence), MatchMapping(PatternMatchMapping), MatchClass(PatternMatchClass), MatchStar(PatternMatchStar), MatchAs(PatternMatchAs), MatchOr(PatternMatchOr), } /// See also [MatchValue](https://docs.python.org/3/library/ast.html#ast.MatchValue) #[derive(Clone, Debug, PartialEq)] pub struct PatternMatchValue { pub range: TextRange, pub value: Box, } impl From for Pattern { fn from(payload: PatternMatchValue) -> Self { Pattern::MatchValue(payload) } } /// See also [MatchSingleton](https://docs.python.org/3/library/ast.html#ast.MatchSingleton) #[derive(Clone, Debug, PartialEq)] pub struct PatternMatchSingleton { pub range: TextRange, pub value: Constant, } impl From for Pattern { fn from(payload: PatternMatchSingleton) -> Self { Pattern::MatchSingleton(payload) } } /// See also [MatchSequence](https://docs.python.org/3/library/ast.html#ast.MatchSequence) #[derive(Clone, Debug, PartialEq)] pub struct PatternMatchSequence { pub range: TextRange, pub patterns: Vec, } impl From for Pattern { fn from(payload: PatternMatchSequence) -> Self { Pattern::MatchSequence(payload) } } /// See also [MatchMapping](https://docs.python.org/3/library/ast.html#ast.MatchMapping) #[derive(Clone, Debug, PartialEq)] pub struct PatternMatchMapping { pub range: TextRange, pub keys: Vec, pub patterns: Vec, pub rest: Option, } impl From for Pattern { fn from(payload: PatternMatchMapping) -> Self { Pattern::MatchMapping(payload) } } /// See also [MatchClass](https://docs.python.org/3/library/ast.html#ast.MatchClass) #[derive(Clone, Debug, PartialEq)] pub struct PatternMatchClass { pub range: TextRange, pub cls: Box, pub arguments: PatternArguments, } impl From for Pattern { fn from(payload: PatternMatchClass) -> Self { Pattern::MatchClass(payload) } } /// An AST node to represent the arguments to a [`PatternMatchClass`], i.e., the /// parenthesized contents in `case Point(1, x=0, y=0)`. /// /// Like [`Arguments`], but for [`PatternMatchClass`]. #[derive(Clone, Debug, PartialEq)] pub struct PatternArguments { pub range: TextRange, pub patterns: Vec, pub keywords: Vec, } /// An AST node to represent the keyword arguments to a [`PatternMatchClass`], i.e., the /// `x=0` and `y=0` in `case Point(x=0, y=0)`. /// /// Like [`Keyword`], but for [`PatternMatchClass`]. #[derive(Clone, Debug, PartialEq)] pub struct PatternKeyword { pub range: TextRange, pub attr: Identifier, pub pattern: Pattern, } /// See also [MatchStar](https://docs.python.org/3/library/ast.html#ast.MatchStar) #[derive(Clone, Debug, PartialEq)] pub struct PatternMatchStar { pub range: TextRange, pub name: Option, } impl From for Pattern { fn from(payload: PatternMatchStar) -> Self { Pattern::MatchStar(payload) } } /// See also [MatchAs](https://docs.python.org/3/library/ast.html#ast.MatchAs) #[derive(Clone, Debug, PartialEq)] pub struct PatternMatchAs { pub range: TextRange, pub pattern: Option>, pub name: Option, } impl From for Pattern { fn from(payload: PatternMatchAs) -> Self { Pattern::MatchAs(payload) } } /// See also [MatchOr](https://docs.python.org/3/library/ast.html#ast.MatchOr) #[derive(Clone, Debug, PartialEq)] pub struct PatternMatchOr { pub range: TextRange, pub patterns: Vec, } impl From for Pattern { fn from(payload: PatternMatchOr) -> Self { Pattern::MatchOr(payload) } } /// See also [type_param](https://docs.python.org/3/library/ast.html#ast.type_param) #[derive(Clone, Debug, PartialEq, is_macro::Is)] pub enum TypeParam { TypeVar(TypeParamTypeVar), ParamSpec(TypeParamParamSpec), TypeVarTuple(TypeParamTypeVarTuple), } /// See also [TypeVar](https://docs.python.org/3/library/ast.html#ast.TypeVar) #[derive(Clone, Debug, PartialEq)] pub struct TypeParamTypeVar { pub range: TextRange, pub name: Identifier, pub bound: Option>, } impl From for TypeParam { fn from(payload: TypeParamTypeVar) -> Self { TypeParam::TypeVar(payload) } } /// See also [ParamSpec](https://docs.python.org/3/library/ast.html#ast.ParamSpec) #[derive(Clone, Debug, PartialEq)] pub struct TypeParamParamSpec { pub range: TextRange, pub name: Identifier, } impl From for TypeParam { fn from(payload: TypeParamParamSpec) -> Self { TypeParam::ParamSpec(payload) } } /// See also [TypeVarTuple](https://docs.python.org/3/library/ast.html#ast.TypeVarTuple) #[derive(Clone, Debug, PartialEq)] pub struct TypeParamTypeVarTuple { pub range: TextRange, pub name: Identifier, } impl From for TypeParam { fn from(payload: TypeParamTypeVarTuple) -> Self { TypeParam::TypeVarTuple(payload) } } /// See also [decorator](https://docs.python.org/3/library/ast.html#ast.decorator) #[derive(Clone, Debug, PartialEq)] pub struct Decorator { pub range: TextRange, pub expression: Expr, } /// An alternative type of AST `arguments`. This is ruff_python_parser-friendly and human-friendly definition of function arguments. /// This form also has advantage to implement pre-order traverse. /// /// `defaults` and `kw_defaults` fields are removed and the default values are placed under each [`ParameterWithDefault`] typed argument. /// `vararg` and `kwarg` are still typed as `arg` because they never can have a default value. /// /// The original Python-style AST type orders `kwonlyargs` fields by default existence; [Parameters] has location-ordered `kwonlyargs` fields. /// /// NOTE: This type differs from the original Python AST. See: [arguments](https://docs.python.org/3/library/ast.html#ast.arguments). #[derive(Clone, Debug, PartialEq)] pub struct Parameters { pub range: TextRange, pub posonlyargs: Vec, pub args: Vec, pub vararg: Option>, pub kwonlyargs: Vec, pub kwarg: Option>, } impl Parameters { /// Returns `true` if a parameter with the given name included in this [`Parameters`]. pub fn includes(&self, name: &str) -> bool { if self .posonlyargs .iter() .chain(&self.args) .chain(&self.kwonlyargs) .any(|arg| arg.parameter.name.as_str() == name) { return true; } if let Some(arg) = &self.vararg { if arg.name.as_str() == name { return true; } } if let Some(arg) = &self.kwarg { if arg.name.as_str() == name { return true; } } false } } /// An alternative type of AST `arg`. This is used for each function argument that might have a default value. /// Used by `Arguments` original type. /// /// NOTE: This type is different from original Python AST. #[derive(Clone, Debug, PartialEq)] pub struct ParameterWithDefault { pub range: TextRange, pub parameter: Parameter, pub default: Option>, } /// An AST node used to represent the arguments passed to a function call or class definition. /// /// For example, given: /// ```python /// foo(1, 2, 3, bar=4, baz=5) /// ``` /// The `Arguments` node would span from the left to right parentheses (inclusive), and contain /// the arguments and keyword arguments in the order they appear in the source code. /// /// Similarly, given: /// ```python /// class Foo(Bar, baz=1, qux=2): /// pass /// ``` /// The `Arguments` node would again span from the left to right parentheses (inclusive), and /// contain the `Bar` argument and the `baz` and `qux` keyword arguments in the order they /// appear in the source code. /// /// In the context of a class definition, the Python-style AST refers to the arguments as `bases`, /// as they represent the "explicitly specified base classes", while the keyword arguments are /// typically used for `metaclass`, with any additional arguments being passed to the `metaclass`. #[derive(Clone, Debug, PartialEq)] pub struct Arguments { pub range: TextRange, pub args: Vec, pub keywords: Vec, } /// An entry in the argument list of a function call. #[derive(Clone, Debug, PartialEq)] pub enum ArgOrKeyword<'a> { Arg(&'a Expr), Keyword(&'a Keyword), } impl<'a> From<&'a Expr> for ArgOrKeyword<'a> { fn from(arg: &'a Expr) -> Self { Self::Arg(arg) } } impl<'a> From<&'a Keyword> for ArgOrKeyword<'a> { fn from(keyword: &'a Keyword) -> Self { Self::Keyword(keyword) } } impl Ranged for ArgOrKeyword<'_> { fn range(&self) -> TextRange { match self { Self::Arg(arg) => arg.range(), Self::Keyword(keyword) => keyword.range(), } } } impl Arguments { /// Return the number of positional and keyword arguments. pub fn len(&self) -> usize { self.args.len() + self.keywords.len() } /// Return `true` if there are no positional or keyword arguments. pub fn is_empty(&self) -> bool { self.len() == 0 } /// Return the [`Keyword`] with the given name, or `None` if no such [`Keyword`] exists. pub fn find_keyword(&self, keyword_name: &str) -> Option<&Keyword> { self.keywords.iter().find(|keyword| { let Keyword { arg, .. } = keyword; arg.as_ref().is_some_and(|arg| arg == keyword_name) }) } /// Return the positional argument at the given index, or `None` if no such argument exists. pub fn find_positional(&self, position: usize) -> Option<&Expr> { self.args .iter() .take_while(|expr| !expr.is_starred_expr()) .nth(position) } /// Return the argument with the given name or at the given position, or `None` if no such /// argument exists. Used to retrieve arguments that can be provided _either_ as keyword or /// positional arguments. pub fn find_argument(&self, name: &str, position: usize) -> Option<&Expr> { self.find_keyword(name) .map(|keyword| &keyword.value) .or_else(|| self.find_positional(position)) } /// Return the positional and keyword arguments in the order of declaration. /// /// Positional arguments are generally before keyword arguments, but star arguments are an /// exception: /// ```python /// class A(*args, a=2, *args2, **kwargs): /// pass /// /// f(*args, a=2, *args2, **kwargs) /// ``` /// where `*args` and `args2` are `args` while `a=1` and `kwargs` are `keywords`. /// /// If you would just chain `args` and `keywords` the call would get reordered which we don't /// want. This function instead "merge sorts" them into the correct order. /// /// Note that the order of evaluation is always first `args`, then `keywords`: /// ```python /// def f(*args, **kwargs): /// pass /// /// def g(x): /// print(x) /// return x /// /// /// f(*g([1]), a=g(2), *g([3]), **g({"4": 5})) /// ``` /// Output: /// ```text /// [1] /// [3] /// 2 /// {'4': 5} /// ``` pub fn arguments_source_order(&self) -> impl Iterator> { let args = self.args.iter().map(ArgOrKeyword::Arg); let keywords = self.keywords.iter().map(ArgOrKeyword::Keyword); args.merge_by(keywords, |left, right| left.start() < right.start()) } } /// An AST node used to represent a sequence of type parameters. /// /// For example, given: /// ```python /// class C[T, U, V]: ... /// ``` /// The `TypeParams` node would span from the left to right brackets (inclusive), and contain /// the `T`, `U`, and `V` type parameters in the order they appear in the source code. #[derive(Clone, Debug, PartialEq)] pub struct TypeParams { pub range: TextRange, pub type_params: Vec, } impl Deref for TypeParams { type Target = [TypeParam]; fn deref(&self) -> &Self::Target { &self.type_params } } pub type Suite = Vec; impl CmpOp { pub fn as_str(&self) -> &'static str { match self { CmpOp::Eq => "==", CmpOp::NotEq => "!=", CmpOp::Lt => "<", CmpOp::LtE => "<=", CmpOp::Gt => ">", CmpOp::GtE => ">=", CmpOp::Is => "is", CmpOp::IsNot => "is not", CmpOp::In => "in", CmpOp::NotIn => "not in", } } } impl Parameters { pub fn empty(range: TextRange) -> Self { Self { range, posonlyargs: Vec::new(), args: Vec::new(), vararg: None, kwonlyargs: Vec::new(), kwarg: None, } } } #[allow(clippy::borrowed_box)] // local utility fn clone_boxed_expr(expr: &Box) -> Box { let expr: &Expr = expr.as_ref(); Box::new(expr.clone()) } impl ParameterWithDefault { pub fn as_parameter(&self) -> &Parameter { &self.parameter } pub fn to_parameter(&self) -> (Parameter, Option>) { let ParameterWithDefault { range: _, parameter, default, } = self; (parameter.clone(), default.as_ref().map(clone_boxed_expr)) } pub fn into_parameter(self) -> (Parameter, Option>) { let ParameterWithDefault { range: _, parameter, default, } = self; (parameter, default) } } impl Parameters { pub fn defaults(&self) -> impl std::iter::Iterator { self.posonlyargs .iter() .chain(self.args.iter()) .filter_map(|arg| arg.default.as_ref().map(std::convert::AsRef::as_ref)) } #[allow(clippy::type_complexity)] pub fn split_kwonlyargs(&self) -> (Vec<&Parameter>, Vec<(&Parameter, &Expr)>) { let mut args = Vec::new(); let mut with_defaults = Vec::new(); for arg in &self.kwonlyargs { if let Some(ref default) = arg.default { with_defaults.push((arg.as_parameter(), &**default)); } else { args.push(arg.as_parameter()); } } (args, with_defaults) } } /// The kind of escape command as defined in [IPython Syntax] in the IPython codebase. /// /// [IPython Syntax]: https://github.com/ipython/ipython/blob/635815e8f1ded5b764d66cacc80bbe25e9e2587f/IPython/core/inputtransformer2.py#L335-L343 #[derive(PartialEq, Eq, Debug, Clone, Hash, Copy)] pub enum IpyEscapeKind { /// Send line to underlying system shell (`!`). Shell, /// Send line to system shell and capture output (`!!`). ShCap, /// Show help on object (`?`). Help, /// Show help on object, with extra verbosity (`??`). Help2, /// Call magic function (`%`). Magic, /// Call cell magic function (`%%`). Magic2, /// Call first argument with rest of line as arguments after splitting on whitespace /// and quote each as string (`,`). Quote, /// Call first argument with rest of line as an argument quoted as a single string (`;`). Quote2, /// Call first argument with rest of line as arguments (`/`). Paren, } impl TryFrom for IpyEscapeKind { type Error = String; fn try_from(ch: char) -> Result { match ch { '!' => Ok(IpyEscapeKind::Shell), '?' => Ok(IpyEscapeKind::Help), '%' => Ok(IpyEscapeKind::Magic), ',' => Ok(IpyEscapeKind::Quote), ';' => Ok(IpyEscapeKind::Quote2), '/' => Ok(IpyEscapeKind::Paren), _ => Err(format!("Unexpected magic escape: {ch}")), } } } impl TryFrom<[char; 2]> for IpyEscapeKind { type Error = String; fn try_from(ch: [char; 2]) -> Result { match ch { ['!', '!'] => Ok(IpyEscapeKind::ShCap), ['?', '?'] => Ok(IpyEscapeKind::Help2), ['%', '%'] => Ok(IpyEscapeKind::Magic2), [c1, c2] => Err(format!("Unexpected magic escape: {c1}{c2}")), } } } impl fmt::Display for IpyEscapeKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.as_str()) } } impl IpyEscapeKind { /// Returns the length of the escape kind token. pub fn prefix_len(self) -> TextSize { let len = match self { IpyEscapeKind::Shell | IpyEscapeKind::Magic | IpyEscapeKind::Help | IpyEscapeKind::Quote | IpyEscapeKind::Quote2 | IpyEscapeKind::Paren => 1, IpyEscapeKind::ShCap | IpyEscapeKind::Magic2 | IpyEscapeKind::Help2 => 2, }; len.into() } /// Returns `true` if the escape kind is help i.e., `?` or `??`. pub const fn is_help(self) -> bool { matches!(self, IpyEscapeKind::Help | IpyEscapeKind::Help2) } /// Returns `true` if the escape kind is magic i.e., `%` or `%%`. pub const fn is_magic(self) -> bool { matches!(self, IpyEscapeKind::Magic | IpyEscapeKind::Magic2) } pub fn as_str(self) -> &'static str { match self { IpyEscapeKind::Shell => "!", IpyEscapeKind::ShCap => "!!", IpyEscapeKind::Help => "?", IpyEscapeKind::Help2 => "??", IpyEscapeKind::Magic => "%", IpyEscapeKind::Magic2 => "%%", IpyEscapeKind::Quote => ",", IpyEscapeKind::Quote2 => ";", IpyEscapeKind::Paren => "/", } } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Identifier { id: String, range: TextRange, } impl Identifier { #[inline] pub fn new(id: impl Into, range: TextRange) -> Self { Self { id: id.into(), range, } } } impl Identifier { #[inline] pub fn as_str(&self) -> &str { self.id.as_str() } } impl PartialEq for Identifier { #[inline] fn eq(&self, other: &str) -> bool { self.id == other } } impl PartialEq for Identifier { #[inline] fn eq(&self, other: &String) -> bool { &self.id == other } } impl std::ops::Deref for Identifier { type Target = str; #[inline] fn deref(&self) -> &Self::Target { self.id.as_str() } } impl AsRef for Identifier { #[inline] fn as_ref(&self) -> &str { self.id.as_str() } } impl AsRef for Identifier { #[inline] fn as_ref(&self) -> &String { &self.id } } impl std::fmt::Display for Identifier { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(&self.id, f) } } impl From for String { #[inline] fn from(identifier: Identifier) -> String { identifier.id } } impl Ranged for Identifier { fn range(&self) -> TextRange { self.range } } #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Int(u32); impl Int { pub fn new(i: u32) -> Self { Self(i) } pub fn to_u32(&self) -> u32 { self.0 } pub fn to_usize(&self) -> usize { self.0 as _ } } impl std::cmp::PartialEq for Int { #[inline] fn eq(&self, other: &u32) -> bool { self.0 == *other } } impl std::cmp::PartialEq for Int { #[inline] fn eq(&self, other: &usize) -> bool { self.0 as usize == *other } } #[derive(Clone, Debug, PartialEq, is_macro::Is)] pub enum Constant { None, Bool(bool), Str(StringConstant), Bytes(BytesConstant), Int(BigInt), Float(f64), Complex { real: f64, imag: f64 }, Ellipsis, } impl Constant { /// Returns `true` if the constant is a string or bytes constant that contains multiple, /// implicitly concatenated string tokens. pub fn is_implicit_concatenated(&self) -> bool { match self { Constant::Str(value) => value.implicit_concatenated, Constant::Bytes(value) => value.implicit_concatenated, _ => false, } } } #[derive(Clone, Debug, PartialEq, Eq)] pub struct StringConstant { /// The string value as resolved by the parser (i.e., without quotes, or escape sequences, or /// implicit concatenations). pub value: String, /// Whether the string is a Unicode string (i.e., `u"..."`). pub unicode: bool, /// Whether the string contains multiple string tokens that were implicitly concatenated. pub implicit_concatenated: bool, } impl Deref for StringConstant { type Target = str; fn deref(&self) -> &Self::Target { self.value.as_str() } } #[derive(Clone, Debug, PartialEq, Eq)] pub struct BytesConstant { /// The bytes value as resolved by the parser (i.e., without quotes, or escape sequences, or /// implicit concatenations). pub value: Vec, /// Whether the string contains multiple string tokens that were implicitly concatenated. pub implicit_concatenated: bool, } impl Deref for BytesConstant { type Target = [u8]; fn deref(&self) -> &Self::Target { self.value.as_slice() } } impl From> for Constant { fn from(value: Vec) -> Constant { Self::Bytes(BytesConstant { value, implicit_concatenated: false, }) } } impl From for Constant { fn from(value: String) -> Constant { Self::Str(StringConstant { value, unicode: false, implicit_concatenated: false, }) } } impl From for Constant { fn from(value: bool) -> Constant { Self::Bool(value) } } #[cfg(feature = "rustpython-literal")] impl std::fmt::Display for Constant { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Constant::None => f.pad("None"), Constant::Bool(b) => f.pad(if *b { "True" } else { "False" }), Constant::Str(s) => rustpython_literal::escape::UnicodeEscape::new_repr(s.as_str()) .str_repr() .write(f), Constant::Bytes(b) => { let escape = rustpython_literal::escape::AsciiEscape::new_repr(b); let repr = escape.bytes_repr().to_string().unwrap(); f.pad(&repr) } Constant::Int(i) => std::fmt::Display::fmt(&i, f), Constant::Float(fp) => f.pad(&rustpython_literal::float::to_string(*fp)), Constant::Complex { real, imag } => { if *real == 0.0 { write!(f, "{imag}j") } else { write!(f, "({real}{imag:+}j)") } } Constant::Ellipsis => f.pad("..."), } } } impl Ranged for crate::nodes::ModModule { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ModExpression { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::Mod { fn range(&self) -> TextRange { match self { Self::Module(node) => node.range(), Self::Expression(node) => node.range(), } } } impl Ranged for crate::nodes::StmtFunctionDef { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtClassDef { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtReturn { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtDelete { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtTypeAlias { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtAssign { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtAugAssign { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtAnnAssign { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtFor { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtWhile { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtIf { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ElifElseClause { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtWith { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtMatch { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtRaise { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtTry { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtAssert { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtImport { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtImportFrom { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtGlobal { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtNonlocal { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtExpr { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtPass { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtBreak { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtContinue { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::StmtIpyEscapeCommand { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::Stmt { fn range(&self) -> TextRange { match self { Self::FunctionDef(node) => node.range(), Self::ClassDef(node) => node.range(), Self::Return(node) => node.range(), Self::Delete(node) => node.range(), Self::TypeAlias(node) => node.range(), Self::Assign(node) => node.range(), Self::AugAssign(node) => node.range(), Self::AnnAssign(node) => node.range(), Self::For(node) => node.range(), Self::While(node) => node.range(), Self::If(node) => node.range(), Self::With(node) => node.range(), Self::Match(node) => node.range(), Self::Raise(node) => node.range(), Self::Try(node) => node.range(), Self::Assert(node) => node.range(), Self::Import(node) => node.range(), Self::ImportFrom(node) => node.range(), Self::Global(node) => node.range(), Self::Nonlocal(node) => node.range(), Self::Expr(node) => node.range(), Self::Pass(node) => node.range(), Self::Break(node) => node.range(), Self::Continue(node) => node.range(), Stmt::IpyEscapeCommand(node) => node.range(), } } } impl Ranged for crate::nodes::ExprBoolOp { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprNamedExpr { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprBinOp { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprUnaryOp { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprLambda { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprIfExp { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprDict { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprSet { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprListComp { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprSetComp { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprDictComp { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprGeneratorExp { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprAwait { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprYield { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprYieldFrom { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprCompare { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprCall { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprFormattedValue { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprFString { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprConstant { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprAttribute { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprSubscript { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprStarred { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprName { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprList { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprTuple { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprSlice { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExprIpyEscapeCommand { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::Expr { fn range(&self) -> TextRange { match self { Self::BoolOp(node) => node.range(), Self::NamedExpr(node) => node.range(), Self::BinOp(node) => node.range(), Self::UnaryOp(node) => node.range(), Self::Lambda(node) => node.range(), Self::IfExp(node) => node.range(), Self::Dict(node) => node.range(), Self::Set(node) => node.range(), Self::ListComp(node) => node.range(), Self::SetComp(node) => node.range(), Self::DictComp(node) => node.range(), Self::GeneratorExp(node) => node.range(), Self::Await(node) => node.range(), Self::Yield(node) => node.range(), Self::YieldFrom(node) => node.range(), Self::Compare(node) => node.range(), Self::Call(node) => node.range(), Self::FormattedValue(node) => node.range(), Self::FString(node) => node.range(), Self::Constant(node) => node.range(), Self::Attribute(node) => node.range(), Self::Subscript(node) => node.range(), Self::Starred(node) => node.range(), Self::Name(node) => node.range(), Self::List(node) => node.range(), Self::Tuple(node) => node.range(), Self::Slice(node) => node.range(), Expr::IpyEscapeCommand(node) => node.range(), } } } impl Ranged for crate::nodes::Comprehension { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ExceptHandlerExceptHandler { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::ExceptHandler { fn range(&self) -> TextRange { match self { Self::ExceptHandler(node) => node.range(), } } } impl Ranged for crate::nodes::Parameter { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::Keyword { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::Alias { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::WithItem { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::MatchCase { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::PatternMatchValue { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::PatternMatchSingleton { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::PatternMatchSequence { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::PatternMatchMapping { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::PatternMatchClass { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::PatternMatchStar { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::PatternMatchAs { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::PatternMatchOr { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::Pattern { fn range(&self) -> TextRange { match self { Self::MatchValue(node) => node.range(), Self::MatchSingleton(node) => node.range(), Self::MatchSequence(node) => node.range(), Self::MatchMapping(node) => node.range(), Self::MatchClass(node) => node.range(), Self::MatchStar(node) => node.range(), Self::MatchAs(node) => node.range(), Self::MatchOr(node) => node.range(), } } } impl Ranged for crate::nodes::PatternArguments { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::PatternKeyword { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::TypeParams { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::TypeParamTypeVar { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::TypeParamTypeVarTuple { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::TypeParamParamSpec { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::TypeParam { fn range(&self) -> TextRange { match self { Self::TypeVar(node) => node.range(), Self::TypeVarTuple(node) => node.range(), Self::ParamSpec(node) => node.range(), } } } impl Ranged for crate::nodes::Decorator { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::Arguments { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::Parameters { fn range(&self) -> TextRange { self.range } } impl Ranged for crate::nodes::ParameterWithDefault { fn range(&self) -> TextRange { self.range } } /// An expression that may be parenthesized. #[derive(Clone, Debug)] pub struct ParenthesizedExpr { /// The range of the expression, including any parentheses. pub range: TextRange, /// The underlying expression. pub expr: Expr, } impl Ranged for ParenthesizedExpr { fn range(&self) -> TextRange { self.range } } impl From for ParenthesizedExpr { fn from(expr: Expr) -> Self { ParenthesizedExpr { range: expr.range(), expr, } } } impl From for Expr { fn from(parenthesized_expr: ParenthesizedExpr) -> Self { parenthesized_expr.expr } } impl From for ParenthesizedExpr { fn from(payload: ExprIpyEscapeCommand) -> Self { Expr::IpyEscapeCommand(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprBoolOp) -> Self { Expr::BoolOp(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprNamedExpr) -> Self { Expr::NamedExpr(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprBinOp) -> Self { Expr::BinOp(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprUnaryOp) -> Self { Expr::UnaryOp(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprLambda) -> Self { Expr::Lambda(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprIfExp) -> Self { Expr::IfExp(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprDict) -> Self { Expr::Dict(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprSet) -> Self { Expr::Set(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprListComp) -> Self { Expr::ListComp(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprSetComp) -> Self { Expr::SetComp(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprDictComp) -> Self { Expr::DictComp(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprGeneratorExp) -> Self { Expr::GeneratorExp(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprAwait) -> Self { Expr::Await(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprYield) -> Self { Expr::Yield(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprYieldFrom) -> Self { Expr::YieldFrom(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprCompare) -> Self { Expr::Compare(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprCall) -> Self { Expr::Call(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprFormattedValue) -> Self { Expr::FormattedValue(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprFString) -> Self { Expr::FString(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprConstant) -> Self { Expr::Constant(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprAttribute) -> Self { Expr::Attribute(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprSubscript) -> Self { Expr::Subscript(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprStarred) -> Self { Expr::Starred(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprName) -> Self { Expr::Name(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprList) -> Self { Expr::List(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprTuple) -> Self { Expr::Tuple(payload).into() } } impl From for ParenthesizedExpr { fn from(payload: ExprSlice) -> Self { Expr::Slice(payload).into() } } #[cfg(target_pointer_width = "64")] mod size_assertions { use static_assertions::assert_eq_size; #[allow(clippy::wildcard_imports)] use super::*; assert_eq_size!(Stmt, [u8; 144]); assert_eq_size!(StmtFunctionDef, [u8; 144]); assert_eq_size!(StmtClassDef, [u8; 104]); assert_eq_size!(StmtTry, [u8; 112]); assert_eq_size!(Expr, [u8; 80]); assert_eq_size!(Constant, [u8; 40]); assert_eq_size!(Pattern, [u8; 96]); assert_eq_size!(Mod, [u8; 32]); }