ruff/crates/ruff_python_ast/src/nodes.rs
2023-09-06 12:07:34 +05:30

3333 lines
84 KiB
Rust

#![allow(clippy::derive_partial_eq_without_eq)]
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<Stmt>,
}
impl From<ModModule> 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<Expr>,
}
impl From<ModExpression> 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
///
/// `<IpyEscapeKind><Command value>`
///
/// The simplest form is an escape kind token followed by the command value. For example,
/// `%matplotlib inline`, `/foo`, `!pwd`, etc.
///
/// `<Command value><IpyEscapeKind ("?" or "??")>`
///
/// 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.
///
/// `<IpyEscapeKind><Command value><EscapeKind ("?" or "??")>`
///
/// 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<StmtIpyEscapeCommand> 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<Decorator>,
pub name: Identifier,
pub type_params: Option<TypeParams>,
pub parameters: Box<Parameters>,
pub returns: Option<Box<Expr>>,
pub body: Vec<Stmt>,
}
impl From<StmtFunctionDef> 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<Decorator>,
pub name: Identifier,
pub type_params: Option<Box<TypeParams>>,
pub arguments: Option<Box<Arguments>>,
pub body: Vec<Stmt>,
}
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<StmtClassDef> 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<Box<Expr>>,
}
impl From<StmtReturn> 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<Expr>,
}
impl From<StmtDelete> 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<Expr>,
pub type_params: Option<TypeParams>,
pub value: Box<Expr>,
}
impl From<StmtTypeAlias> 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<Expr>,
pub value: Box<Expr>,
}
impl From<StmtAssign> 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<Expr>,
pub op: Operator,
pub value: Box<Expr>,
}
impl From<StmtAugAssign> 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<Expr>,
pub annotation: Box<Expr>,
pub value: Option<Box<Expr>>,
pub simple: bool,
}
impl From<StmtAnnAssign> 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<Expr>,
pub iter: Box<Expr>,
pub body: Vec<Stmt>,
pub orelse: Vec<Stmt>,
}
impl From<StmtFor> 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<Expr>,
pub body: Vec<Stmt>,
pub orelse: Vec<Stmt>,
}
impl From<StmtWhile> 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<Expr>,
pub body: Vec<Stmt>,
pub elif_else_clauses: Vec<ElifElseClause>,
}
impl From<StmtIf> for Stmt {
fn from(payload: StmtIf) -> Self {
Stmt::If(payload)
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct ElifElseClause {
pub range: TextRange,
pub test: Option<Expr>,
pub body: Vec<Stmt>,
}
/// 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<WithItem>,
pub body: Vec<Stmt>,
}
impl From<StmtWith> 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<Expr>,
pub cases: Vec<MatchCase>,
}
impl From<StmtMatch> 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<Box<Expr>>,
pub cause: Option<Box<Expr>>,
}
impl From<StmtRaise> 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<Stmt>,
pub handlers: Vec<ExceptHandler>,
pub orelse: Vec<Stmt>,
pub finalbody: Vec<Stmt>,
pub is_star: bool,
}
impl From<StmtTry> 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<Expr>,
pub msg: Option<Box<Expr>>,
}
impl From<StmtAssert> 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<Alias>,
}
impl From<StmtImport> 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<Identifier>,
pub names: Vec<Alias>,
pub level: Option<Int>,
}
impl From<StmtImportFrom> 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<Identifier>,
}
impl From<StmtGlobal> 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<Identifier>,
}
impl From<StmtNonlocal> 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<Expr>,
}
impl From<StmtExpr> 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<StmtPass> 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<StmtBreak> 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<StmtContinue> 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<ExprIpyEscapeCommand> 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<Expr>,
}
impl From<ExprBoolOp> 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<Expr>,
pub value: Box<Expr>,
}
impl From<ExprNamedExpr> 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<Expr>,
pub op: Operator,
pub right: Box<Expr>,
}
impl From<ExprBinOp> 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<Expr>,
}
impl From<ExprUnaryOp> 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<Box<Parameters>>,
pub body: Box<Expr>,
}
impl From<ExprLambda> 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<Expr>,
pub body: Box<Expr>,
pub orelse: Box<Expr>,
}
impl From<ExprIfExp> 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<Option<Expr>>,
pub values: Vec<Expr>,
}
impl From<ExprDict> 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<Expr>,
}
impl From<ExprSet> 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<Expr>,
pub generators: Vec<Comprehension>,
}
impl From<ExprListComp> 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<Expr>,
pub generators: Vec<Comprehension>,
}
impl From<ExprSetComp> 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<Expr>,
pub value: Box<Expr>,
pub generators: Vec<Comprehension>,
}
impl From<ExprDictComp> 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<Expr>,
pub generators: Vec<Comprehension>,
}
impl From<ExprGeneratorExp> 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<Expr>,
}
impl From<ExprAwait> 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<Box<Expr>>,
}
impl From<ExprYield> 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<Expr>,
}
impl From<ExprYieldFrom> 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<Expr>,
pub ops: Vec<CmpOp>,
pub comparators: Vec<Expr>,
}
impl From<ExprCompare> 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<Expr>,
pub arguments: Arguments,
}
impl From<ExprCall> 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<Expr>,
pub debug_text: Option<DebugText>,
pub conversion: ConversionFlag,
pub format_spec: Option<Box<Expr>>,
}
impl From<ExprFormattedValue> 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(<value>)`.
Str = b's' as i8,
/// Converts by calling `ascii(<value>)`.
Ascii = b'a' as i8,
/// Converts by calling `repr(<value>)`.
Repr = b'r' as i8,
}
impl ConversionFlag {
pub fn to_byte(&self) -> Option<u8> {
match self {
Self::None => None,
flag => Some(*flag as u8),
}
}
pub fn to_char(&self) -> Option<char> {
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<Expr>,
/// Whether the f-string contains multiple string tokens that were implicitly concatenated.
pub implicit_concatenated: bool,
}
impl From<ExprFString> 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,
pub kind: Option<String>,
}
impl From<ExprConstant> 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<Expr>,
pub attr: Identifier,
pub ctx: ExprContext,
}
impl From<ExprAttribute> 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<Expr>,
pub slice: Box<Expr>,
pub ctx: ExprContext,
}
impl From<ExprSubscript> 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<Expr>,
pub ctx: ExprContext,
}
impl From<ExprStarred> 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<ExprName> 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<Expr>,
pub ctx: ExprContext,
}
impl From<ExprList> 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<Expr>,
pub ctx: ExprContext,
}
impl From<ExprTuple> 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<Box<Expr>>,
pub upper: Option<Box<Expr>>,
pub step: Option<Box<Expr>>,
}
impl From<ExprSlice> 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<ExprContextLoad> {
match self {
ExprContext::Load => Some(ExprContextLoad),
_ => None,
}
}
#[inline]
pub const fn store(&self) -> Option<ExprContextStore> {
match self {
ExprContext::Store => Some(ExprContextStore),
_ => None,
}
}
#[inline]
pub const fn del(&self) -> Option<ExprContextDel> {
match self {
ExprContext::Del => Some(ExprContextDel),
_ => None,
}
}
}
pub struct ExprContextLoad;
impl From<ExprContextLoad> for ExprContext {
fn from(_: ExprContextLoad) -> Self {
ExprContext::Load
}
}
impl std::cmp::PartialEq<ExprContext> for ExprContextLoad {
#[inline]
fn eq(&self, other: &ExprContext) -> bool {
matches!(other, ExprContext::Load)
}
}
pub struct ExprContextStore;
impl From<ExprContextStore> for ExprContext {
fn from(_: ExprContextStore) -> Self {
ExprContext::Store
}
}
impl std::cmp::PartialEq<ExprContext> for ExprContextStore {
#[inline]
fn eq(&self, other: &ExprContext) -> bool {
matches!(other, ExprContext::Store)
}
}
pub struct ExprContextDel;
impl From<ExprContextDel> for ExprContext {
fn from(_: ExprContextDel) -> Self {
ExprContext::Del
}
}
impl std::cmp::PartialEq<ExprContext> 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<BoolOpAnd> {
match self {
BoolOp::And => Some(BoolOpAnd),
BoolOp::Or => None,
}
}
#[inline]
pub const fn or(&self) -> Option<BoolOpOr> {
match self {
BoolOp::Or => Some(BoolOpOr),
BoolOp::And => None,
}
}
}
pub struct BoolOpAnd;
impl From<BoolOpAnd> for BoolOp {
fn from(_: BoolOpAnd) -> Self {
BoolOp::And
}
}
impl std::cmp::PartialEq<BoolOp> for BoolOpAnd {
#[inline]
fn eq(&self, other: &BoolOp) -> bool {
matches!(other, BoolOp::And)
}
}
pub struct BoolOpOr;
impl From<BoolOpOr> for BoolOp {
fn from(_: BoolOpOr) -> Self {
BoolOp::Or
}
}
impl std::cmp::PartialEq<BoolOp> 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<OperatorAdd> {
match self {
Operator::Add => Some(OperatorAdd),
_ => None,
}
}
#[inline]
pub const fn operator_sub(&self) -> Option<OperatorSub> {
match self {
Operator::Sub => Some(OperatorSub),
_ => None,
}
}
#[inline]
pub const fn operator_mult(&self) -> Option<OperatorMult> {
match self {
Operator::Mult => Some(OperatorMult),
_ => None,
}
}
#[inline]
pub const fn operator_mat_mult(&self) -> Option<OperatorMatMult> {
match self {
Operator::MatMult => Some(OperatorMatMult),
_ => None,
}
}
#[inline]
pub const fn operator_div(&self) -> Option<OperatorDiv> {
match self {
Operator::Div => Some(OperatorDiv),
_ => None,
}
}
#[inline]
pub const fn operator_mod(&self) -> Option<OperatorMod> {
match self {
Operator::Mod => Some(OperatorMod),
_ => None,
}
}
#[inline]
pub const fn operator_pow(&self) -> Option<OperatorPow> {
match self {
Operator::Pow => Some(OperatorPow),
_ => None,
}
}
#[inline]
pub const fn operator_l_shift(&self) -> Option<OperatorLShift> {
match self {
Operator::LShift => Some(OperatorLShift),
_ => None,
}
}
#[inline]
pub const fn operator_r_shift(&self) -> Option<OperatorRShift> {
match self {
Operator::RShift => Some(OperatorRShift),
_ => None,
}
}
#[inline]
pub const fn operator_bit_or(&self) -> Option<OperatorBitOr> {
match self {
Operator::BitOr => Some(OperatorBitOr),
_ => None,
}
}
#[inline]
pub const fn operator_bit_xor(&self) -> Option<OperatorBitXor> {
match self {
Operator::BitXor => Some(OperatorBitXor),
_ => None,
}
}
#[inline]
pub const fn operator_bit_and(&self) -> Option<OperatorBitAnd> {
match self {
Operator::BitAnd => Some(OperatorBitAnd),
_ => None,
}
}
#[inline]
pub const fn operator_floor_div(&self) -> Option<OperatorFloorDiv> {
match self {
Operator::FloorDiv => Some(OperatorFloorDiv),
_ => None,
}
}
}
pub struct OperatorAdd;
impl From<OperatorAdd> for Operator {
fn from(_: OperatorAdd) -> Self {
Operator::Add
}
}
impl std::cmp::PartialEq<Operator> for OperatorAdd {
#[inline]
fn eq(&self, other: &Operator) -> bool {
matches!(other, Operator::Add)
}
}
pub struct OperatorSub;
impl From<OperatorSub> for Operator {
fn from(_: OperatorSub) -> Self {
Operator::Sub
}
}
impl std::cmp::PartialEq<Operator> for OperatorSub {
#[inline]
fn eq(&self, other: &Operator) -> bool {
matches!(other, Operator::Sub)
}
}
pub struct OperatorMult;
impl From<OperatorMult> for Operator {
fn from(_: OperatorMult) -> Self {
Operator::Mult
}
}
impl std::cmp::PartialEq<Operator> for OperatorMult {
#[inline]
fn eq(&self, other: &Operator) -> bool {
matches!(other, Operator::Mult)
}
}
pub struct OperatorMatMult;
impl From<OperatorMatMult> for Operator {
fn from(_: OperatorMatMult) -> Self {
Operator::MatMult
}
}
impl std::cmp::PartialEq<Operator> for OperatorMatMult {
#[inline]
fn eq(&self, other: &Operator) -> bool {
matches!(other, Operator::MatMult)
}
}
pub struct OperatorDiv;
impl From<OperatorDiv> for Operator {
fn from(_: OperatorDiv) -> Self {
Operator::Div
}
}
impl std::cmp::PartialEq<Operator> for OperatorDiv {
#[inline]
fn eq(&self, other: &Operator) -> bool {
matches!(other, Operator::Div)
}
}
pub struct OperatorMod;
impl From<OperatorMod> for Operator {
fn from(_: OperatorMod) -> Self {
Operator::Mod
}
}
impl std::cmp::PartialEq<Operator> for OperatorMod {
#[inline]
fn eq(&self, other: &Operator) -> bool {
matches!(other, Operator::Mod)
}
}
pub struct OperatorPow;
impl From<OperatorPow> for Operator {
fn from(_: OperatorPow) -> Self {
Operator::Pow
}
}
impl std::cmp::PartialEq<Operator> for OperatorPow {
#[inline]
fn eq(&self, other: &Operator) -> bool {
matches!(other, Operator::Pow)
}
}
pub struct OperatorLShift;
impl From<OperatorLShift> for Operator {
fn from(_: OperatorLShift) -> Self {
Operator::LShift
}
}
impl std::cmp::PartialEq<Operator> for OperatorLShift {
#[inline]
fn eq(&self, other: &Operator) -> bool {
matches!(other, Operator::LShift)
}
}
pub struct OperatorRShift;
impl From<OperatorRShift> for Operator {
fn from(_: OperatorRShift) -> Self {
Operator::RShift
}
}
impl std::cmp::PartialEq<Operator> for OperatorRShift {
#[inline]
fn eq(&self, other: &Operator) -> bool {
matches!(other, Operator::RShift)
}
}
pub struct OperatorBitOr;
impl From<OperatorBitOr> for Operator {
fn from(_: OperatorBitOr) -> Self {
Operator::BitOr
}
}
impl std::cmp::PartialEq<Operator> for OperatorBitOr {
#[inline]
fn eq(&self, other: &Operator) -> bool {
matches!(other, Operator::BitOr)
}
}
pub struct OperatorBitXor;
impl From<OperatorBitXor> for Operator {
fn from(_: OperatorBitXor) -> Self {
Operator::BitXor
}
}
impl std::cmp::PartialEq<Operator> for OperatorBitXor {
#[inline]
fn eq(&self, other: &Operator) -> bool {
matches!(other, Operator::BitXor)
}
}
pub struct OperatorBitAnd;
impl From<OperatorBitAnd> for Operator {
fn from(_: OperatorBitAnd) -> Self {
Operator::BitAnd
}
}
impl std::cmp::PartialEq<Operator> for OperatorBitAnd {
#[inline]
fn eq(&self, other: &Operator) -> bool {
matches!(other, Operator::BitAnd)
}
}
pub struct OperatorFloorDiv;
impl From<OperatorFloorDiv> for Operator {
fn from(_: OperatorFloorDiv) -> Self {
Operator::FloorDiv
}
}
impl std::cmp::PartialEq<Operator> 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<UnaryOpInvert> {
match self {
UnaryOp::Invert => Some(UnaryOpInvert),
_ => None,
}
}
#[inline]
pub const fn not(&self) -> Option<UnaryOpNot> {
match self {
UnaryOp::Not => Some(UnaryOpNot),
_ => None,
}
}
#[inline]
pub const fn u_add(&self) -> Option<UnaryOpUAdd> {
match self {
UnaryOp::UAdd => Some(UnaryOpUAdd),
_ => None,
}
}
#[inline]
pub const fn u_sub(&self) -> Option<UnaryOpUSub> {
match self {
UnaryOp::USub => Some(UnaryOpUSub),
_ => None,
}
}
}
pub struct UnaryOpInvert;
impl From<UnaryOpInvert> for UnaryOp {
fn from(_: UnaryOpInvert) -> Self {
UnaryOp::Invert
}
}
impl std::cmp::PartialEq<UnaryOp> for UnaryOpInvert {
#[inline]
fn eq(&self, other: &UnaryOp) -> bool {
matches!(other, UnaryOp::Invert)
}
}
pub struct UnaryOpNot;
impl From<UnaryOpNot> for UnaryOp {
fn from(_: UnaryOpNot) -> Self {
UnaryOp::Not
}
}
impl std::cmp::PartialEq<UnaryOp> for UnaryOpNot {
#[inline]
fn eq(&self, other: &UnaryOp) -> bool {
matches!(other, UnaryOp::Not)
}
}
pub struct UnaryOpUAdd;
impl From<UnaryOpUAdd> for UnaryOp {
fn from(_: UnaryOpUAdd) -> Self {
UnaryOp::UAdd
}
}
impl std::cmp::PartialEq<UnaryOp> for UnaryOpUAdd {
#[inline]
fn eq(&self, other: &UnaryOp) -> bool {
matches!(other, UnaryOp::UAdd)
}
}
pub struct UnaryOpUSub;
impl From<UnaryOpUSub> for UnaryOp {
fn from(_: UnaryOpUSub) -> Self {
UnaryOp::USub
}
}
impl std::cmp::PartialEq<UnaryOp> 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<CmpOpEq> {
match self {
CmpOp::Eq => Some(CmpOpEq),
_ => None,
}
}
#[inline]
pub const fn cmp_op_not_eq(&self) -> Option<CmpOpNotEq> {
match self {
CmpOp::NotEq => Some(CmpOpNotEq),
_ => None,
}
}
#[inline]
pub const fn cmp_op_lt(&self) -> Option<CmpOpLt> {
match self {
CmpOp::Lt => Some(CmpOpLt),
_ => None,
}
}
#[inline]
pub const fn cmp_op_lt_e(&self) -> Option<CmpOpLtE> {
match self {
CmpOp::LtE => Some(CmpOpLtE),
_ => None,
}
}
#[inline]
pub const fn cmp_op_gt(&self) -> Option<CmpOpGt> {
match self {
CmpOp::Gt => Some(CmpOpGt),
_ => None,
}
}
#[inline]
pub const fn cmp_op_gt_e(&self) -> Option<CmpOpGtE> {
match self {
CmpOp::GtE => Some(CmpOpGtE),
_ => None,
}
}
#[inline]
pub const fn cmp_op_is(&self) -> Option<CmpOpIs> {
match self {
CmpOp::Is => Some(CmpOpIs),
_ => None,
}
}
#[inline]
pub const fn cmp_op_is_not(&self) -> Option<CmpOpIsNot> {
match self {
CmpOp::IsNot => Some(CmpOpIsNot),
_ => None,
}
}
#[inline]
pub const fn cmp_op_in(&self) -> Option<CmpOpIn> {
match self {
CmpOp::In => Some(CmpOpIn),
_ => None,
}
}
#[inline]
pub const fn cmp_op_not_in(&self) -> Option<CmpOpNotIn> {
match self {
CmpOp::NotIn => Some(CmpOpNotIn),
_ => None,
}
}
}
pub struct CmpOpEq;
impl From<CmpOpEq> for CmpOp {
fn from(_: CmpOpEq) -> Self {
CmpOp::Eq
}
}
impl std::cmp::PartialEq<CmpOp> for CmpOpEq {
#[inline]
fn eq(&self, other: &CmpOp) -> bool {
matches!(other, CmpOp::Eq)
}
}
pub struct CmpOpNotEq;
impl From<CmpOpNotEq> for CmpOp {
fn from(_: CmpOpNotEq) -> Self {
CmpOp::NotEq
}
}
impl std::cmp::PartialEq<CmpOp> for CmpOpNotEq {
#[inline]
fn eq(&self, other: &CmpOp) -> bool {
matches!(other, CmpOp::NotEq)
}
}
pub struct CmpOpLt;
impl From<CmpOpLt> for CmpOp {
fn from(_: CmpOpLt) -> Self {
CmpOp::Lt
}
}
impl std::cmp::PartialEq<CmpOp> for CmpOpLt {
#[inline]
fn eq(&self, other: &CmpOp) -> bool {
matches!(other, CmpOp::Lt)
}
}
pub struct CmpOpLtE;
impl From<CmpOpLtE> for CmpOp {
fn from(_: CmpOpLtE) -> Self {
CmpOp::LtE
}
}
impl std::cmp::PartialEq<CmpOp> for CmpOpLtE {
#[inline]
fn eq(&self, other: &CmpOp) -> bool {
matches!(other, CmpOp::LtE)
}
}
pub struct CmpOpGt;
impl From<CmpOpGt> for CmpOp {
fn from(_: CmpOpGt) -> Self {
CmpOp::Gt
}
}
impl std::cmp::PartialEq<CmpOp> for CmpOpGt {
#[inline]
fn eq(&self, other: &CmpOp) -> bool {
matches!(other, CmpOp::Gt)
}
}
pub struct CmpOpGtE;
impl From<CmpOpGtE> for CmpOp {
fn from(_: CmpOpGtE) -> Self {
CmpOp::GtE
}
}
impl std::cmp::PartialEq<CmpOp> for CmpOpGtE {
#[inline]
fn eq(&self, other: &CmpOp) -> bool {
matches!(other, CmpOp::GtE)
}
}
pub struct CmpOpIs;
impl From<CmpOpIs> for CmpOp {
fn from(_: CmpOpIs) -> Self {
CmpOp::Is
}
}
impl std::cmp::PartialEq<CmpOp> for CmpOpIs {
#[inline]
fn eq(&self, other: &CmpOp) -> bool {
matches!(other, CmpOp::Is)
}
}
pub struct CmpOpIsNot;
impl From<CmpOpIsNot> for CmpOp {
fn from(_: CmpOpIsNot) -> Self {
CmpOp::IsNot
}
}
impl std::cmp::PartialEq<CmpOp> for CmpOpIsNot {
#[inline]
fn eq(&self, other: &CmpOp) -> bool {
matches!(other, CmpOp::IsNot)
}
}
pub struct CmpOpIn;
impl From<CmpOpIn> for CmpOp {
fn from(_: CmpOpIn) -> Self {
CmpOp::In
}
}
impl std::cmp::PartialEq<CmpOp> for CmpOpIn {
#[inline]
fn eq(&self, other: &CmpOp) -> bool {
matches!(other, CmpOp::In)
}
}
pub struct CmpOpNotIn;
impl From<CmpOpNotIn> for CmpOp {
fn from(_: CmpOpNotIn) -> Self {
CmpOp::NotIn
}
}
impl std::cmp::PartialEq<CmpOp> 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<Expr>,
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<Box<Expr>>,
pub name: Option<Identifier>,
pub body: Vec<Stmt>,
}
impl From<ExceptHandlerExceptHandler> 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<Box<Expr>>,
}
/// 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<Identifier>,
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<Identifier>,
}
/// 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<Box<Expr>>,
}
/// 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<Box<Expr>>,
pub body: Vec<Stmt>,
}
/// 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<Expr>,
}
impl From<PatternMatchValue> 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<PatternMatchSingleton> 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<Pattern>,
}
impl From<PatternMatchSequence> 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<Expr>,
pub patterns: Vec<Pattern>,
pub rest: Option<Identifier>,
}
impl From<PatternMatchMapping> 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<Expr>,
pub arguments: PatternArguments,
}
impl From<PatternMatchClass> 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<Pattern>,
pub keywords: Vec<PatternKeyword>,
}
/// 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<Identifier>,
}
impl From<PatternMatchStar> 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<Box<Pattern>>,
pub name: Option<Identifier>,
}
impl From<PatternMatchAs> 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<Pattern>,
}
impl From<PatternMatchOr> 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<Box<Expr>>,
}
impl From<TypeParamTypeVar> 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<TypeParamParamSpec> 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<TypeParamTypeVarTuple> 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<ParameterWithDefault>,
pub args: Vec<ParameterWithDefault>,
pub vararg: Option<Box<Parameter>>,
pub kwonlyargs: Vec<ParameterWithDefault>,
pub kwarg: Option<Box<Parameter>>,
}
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<Box<Expr>>,
}
/// 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<Expr>,
pub keywords: Vec<Keyword>,
}
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))
}
}
/// 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<TypeParam>,
}
impl Deref for TypeParams {
type Target = [TypeParam];
fn deref(&self) -> &Self::Target {
&self.type_params
}
}
pub type Suite = Vec<Stmt>;
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<Expr>) -> Box<Expr> {
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<Box<Expr>>) {
let ParameterWithDefault {
range: _,
parameter,
default,
} = self;
(parameter.clone(), default.as_ref().map(clone_boxed_expr))
}
pub fn into_parameter(self) -> (Parameter, Option<Box<Expr>>) {
let ParameterWithDefault {
range: _,
parameter,
default,
} = self;
(parameter, default)
}
}
impl Parameters {
pub fn defaults(&self) -> impl std::iter::Iterator<Item = &Expr> {
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<char> for IpyEscapeKind {
type Error = String;
fn try_from(ch: char) -> Result<Self, Self::Error> {
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<Self, Self::Error> {
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<String>, range: TextRange) -> Self {
Self {
id: id.into(),
range,
}
}
}
impl Identifier {
#[inline]
pub fn as_str(&self) -> &str {
self.id.as_str()
}
}
impl PartialEq<str> for Identifier {
#[inline]
fn eq(&self, other: &str) -> bool {
self.id == other
}
}
impl PartialEq<String> 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<str> for Identifier {
#[inline]
fn as_ref(&self) -> &str {
self.id.as_str()
}
}
impl AsRef<String> 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<Identifier> 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<u32> for Int {
#[inline]
fn eq(&self, other: &u32) -> bool {
self.0 == *other
}
}
impl std::cmp::PartialEq<usize> 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 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<u8>,
/// 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<Vec<u8>> for Constant {
fn from(value: Vec<u8>) -> Constant {
Self::Bytes(BytesConstant {
value,
implicit_concatenated: false,
})
}
}
impl From<String> for Constant {
fn from(value: String) -> Constant {
Self::Str(StringConstant {
value,
implicit_concatenated: false,
})
}
}
impl From<bool> 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<Expr> for ParenthesizedExpr {
fn from(expr: Expr) -> Self {
ParenthesizedExpr {
range: expr.range(),
expr,
}
}
}
impl From<ParenthesizedExpr> for Expr {
fn from(parenthesized_expr: ParenthesizedExpr) -> Self {
parenthesized_expr.expr
}
}
impl From<ExprIpyEscapeCommand> for ParenthesizedExpr {
fn from(payload: ExprIpyEscapeCommand) -> Self {
Expr::IpyEscapeCommand(payload).into()
}
}
impl From<ExprBoolOp> for ParenthesizedExpr {
fn from(payload: ExprBoolOp) -> Self {
Expr::BoolOp(payload).into()
}
}
impl From<ExprNamedExpr> for ParenthesizedExpr {
fn from(payload: ExprNamedExpr) -> Self {
Expr::NamedExpr(payload).into()
}
}
impl From<ExprBinOp> for ParenthesizedExpr {
fn from(payload: ExprBinOp) -> Self {
Expr::BinOp(payload).into()
}
}
impl From<ExprUnaryOp> for ParenthesizedExpr {
fn from(payload: ExprUnaryOp) -> Self {
Expr::UnaryOp(payload).into()
}
}
impl From<ExprLambda> for ParenthesizedExpr {
fn from(payload: ExprLambda) -> Self {
Expr::Lambda(payload).into()
}
}
impl From<ExprIfExp> for ParenthesizedExpr {
fn from(payload: ExprIfExp) -> Self {
Expr::IfExp(payload).into()
}
}
impl From<ExprDict> for ParenthesizedExpr {
fn from(payload: ExprDict) -> Self {
Expr::Dict(payload).into()
}
}
impl From<ExprSet> for ParenthesizedExpr {
fn from(payload: ExprSet) -> Self {
Expr::Set(payload).into()
}
}
impl From<ExprListComp> for ParenthesizedExpr {
fn from(payload: ExprListComp) -> Self {
Expr::ListComp(payload).into()
}
}
impl From<ExprSetComp> for ParenthesizedExpr {
fn from(payload: ExprSetComp) -> Self {
Expr::SetComp(payload).into()
}
}
impl From<ExprDictComp> for ParenthesizedExpr {
fn from(payload: ExprDictComp) -> Self {
Expr::DictComp(payload).into()
}
}
impl From<ExprGeneratorExp> for ParenthesizedExpr {
fn from(payload: ExprGeneratorExp) -> Self {
Expr::GeneratorExp(payload).into()
}
}
impl From<ExprAwait> for ParenthesizedExpr {
fn from(payload: ExprAwait) -> Self {
Expr::Await(payload).into()
}
}
impl From<ExprYield> for ParenthesizedExpr {
fn from(payload: ExprYield) -> Self {
Expr::Yield(payload).into()
}
}
impl From<ExprYieldFrom> for ParenthesizedExpr {
fn from(payload: ExprYieldFrom) -> Self {
Expr::YieldFrom(payload).into()
}
}
impl From<ExprCompare> for ParenthesizedExpr {
fn from(payload: ExprCompare) -> Self {
Expr::Compare(payload).into()
}
}
impl From<ExprCall> for ParenthesizedExpr {
fn from(payload: ExprCall) -> Self {
Expr::Call(payload).into()
}
}
impl From<ExprFormattedValue> for ParenthesizedExpr {
fn from(payload: ExprFormattedValue) -> Self {
Expr::FormattedValue(payload).into()
}
}
impl From<ExprFString> for ParenthesizedExpr {
fn from(payload: ExprFString) -> Self {
Expr::FString(payload).into()
}
}
impl From<ExprConstant> for ParenthesizedExpr {
fn from(payload: ExprConstant) -> Self {
Expr::Constant(payload).into()
}
}
impl From<ExprAttribute> for ParenthesizedExpr {
fn from(payload: ExprAttribute) -> Self {
Expr::Attribute(payload).into()
}
}
impl From<ExprSubscript> for ParenthesizedExpr {
fn from(payload: ExprSubscript) -> Self {
Expr::Subscript(payload).into()
}
}
impl From<ExprStarred> for ParenthesizedExpr {
fn from(payload: ExprStarred) -> Self {
Expr::Starred(payload).into()
}
}
impl From<ExprName> for ParenthesizedExpr {
fn from(payload: ExprName) -> Self {
Expr::Name(payload).into()
}
}
impl From<ExprList> for ParenthesizedExpr {
fn from(payload: ExprList) -> Self {
Expr::List(payload).into()
}
}
impl From<ExprTuple> for ParenthesizedExpr {
fn from(payload: ExprTuple) -> Self {
Expr::Tuple(payload).into()
}
}
impl From<ExprSlice> 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]);
}