diff --git a/crates/ruff/src/rules/ruff/rules/unreachable.rs b/crates/ruff/src/rules/ruff/rules/unreachable.rs index 872eb50c88e25c..6b3e81fd5d5016 100644 --- a/crates/ruff/src/rules/ruff/rules/unreachable.rs +++ b/crates/ruff/src/rules/ruff/rules/unreachable.rs @@ -671,11 +671,13 @@ impl<'stmt> BasicBlocksBuilder<'stmt> { | Expr::Await(_) | Expr::Yield(_) | Expr::YieldFrom(_) => self.unconditional_next_block(after), + Expr::LineMagic(_) => todo!(), } } // The tough branches are done, here is an easy one. Stmt::Return(_) => NextBlock::Terminate, Stmt::TypeAlias(_) => todo!(), + Stmt::LineMagic(_) => todo!(), }; // Include any statements in the block that don't divert the control flow. @@ -922,6 +924,7 @@ fn needs_next_block(stmts: &[Stmt]) -> bool { | Stmt::TryStar(_) | Stmt::Assert(_) => true, Stmt::TypeAlias(_) => todo!(), + Stmt::LineMagic(_) => todo!(), } } @@ -957,6 +960,7 @@ fn is_control_flow_stmt(stmt: &Stmt) -> bool { | Stmt::Break(_) | Stmt::Continue(_) => true, Stmt::TypeAlias(_) => todo!(), + Stmt::LineMagic(_) => todo!(), } } diff --git a/crates/ruff_python_ast/src/comparable.rs b/crates/ruff_python_ast/src/comparable.rs index ceb2a1c48bf4ee..2825347f0d46da 100644 --- a/crates/ruff_python_ast/src/comparable.rs +++ b/crates/ruff_python_ast/src/comparable.rs @@ -652,6 +652,12 @@ pub struct ExprSlice<'a> { step: Option>>, } +#[derive(Debug, PartialEq, Eq, Hash)] +pub struct ExprLineMagic<'a> { + kind: ast::MagicKind, + value: &'a str, +} + #[derive(Debug, PartialEq, Eq, Hash)] pub enum ComparableExpr<'a> { BoolOp(ExprBoolOp<'a>), @@ -681,6 +687,7 @@ pub enum ComparableExpr<'a> { List(ExprList<'a>), Tuple(ExprTuple<'a>), Slice(ExprSlice<'a>), + LineMagic(ExprLineMagic<'a>), } impl<'a> From<&'a Box> for Box> { @@ -925,6 +932,14 @@ impl<'a> From<&'a ast::Expr> for ComparableExpr<'a> { upper: upper.as_ref().map(Into::into), step: step.as_ref().map(Into::into), }), + ast::Expr::LineMagic(ast::ExprLineMagic { + kind, + value, + range: _range, + }) => Self::LineMagic(ExprLineMagic { + kind: *kind, + value: value.as_str(), + }), } } } @@ -1155,6 +1170,12 @@ pub struct StmtExpr<'a> { value: ComparableExpr<'a>, } +#[derive(Debug, PartialEq, Eq, Hash)] +pub struct StmtLineMagic<'a> { + kind: ast::MagicKind, + value: &'a str, +} + #[derive(Debug, PartialEq, Eq, Hash)] pub enum ComparableStmt<'a> { FunctionDef(StmtFunctionDef<'a>), @@ -1181,6 +1202,7 @@ pub enum ComparableStmt<'a> { ImportFrom(StmtImportFrom<'a>), Global(StmtGlobal<'a>), Nonlocal(StmtNonlocal<'a>), + LineMagic(StmtLineMagic<'a>), Expr(StmtExpr<'a>), Pass, Break, @@ -1440,6 +1462,14 @@ impl<'a> From<&'a ast::Stmt> for ComparableStmt<'a> { }) => Self::Nonlocal(StmtNonlocal { names: names.iter().map(ast::Identifier::as_str).collect(), }), + ast::Stmt::LineMagic(ast::StmtLineMagic { + kind, + value, + range: _range, + }) => Self::LineMagic(StmtLineMagic { + kind: *kind, + value: value.as_str(), + }), ast::Stmt::Expr(ast::StmtExpr { value, range: _range, diff --git a/crates/ruff_python_ast/src/helpers.rs b/crates/ruff_python_ast/src/helpers.rs index 176845502779ad..8ec41b8d072fac 100644 --- a/crates/ruff_python_ast/src/helpers.rs +++ b/crates/ruff_python_ast/src/helpers.rs @@ -262,6 +262,7 @@ where .map_or(false, |value| any_over_expr(value, func)) } Expr::Name(_) | Expr::Constant(_) => false, + Expr::LineMagic(_) => false, } } @@ -564,6 +565,7 @@ where range: _range, }) => any_over_expr(value, func), Stmt::Pass(_) | Stmt::Break(_) | Stmt::Continue(_) => false, + Stmt::LineMagic(_) => false, } } diff --git a/crates/ruff_python_ast/src/node.rs b/crates/ruff_python_ast/src/node.rs index b4abd477cf6dfe..f47b25cc0a2a8c 100644 --- a/crates/ruff_python_ast/src/node.rs +++ b/crates/ruff_python_ast/src/node.rs @@ -53,6 +53,7 @@ pub enum AnyNode { StmtPass(ast::StmtPass), StmtBreak(ast::StmtBreak), StmtContinue(ast::StmtContinue), + StmtLineMagic(ast::StmtLineMagic), ExprBoolOp(ast::ExprBoolOp), ExprNamedExpr(ast::ExprNamedExpr), ExprBinOp(ast::ExprBinOp), @@ -80,6 +81,7 @@ pub enum AnyNode { ExprList(ast::ExprList), ExprTuple(ast::ExprTuple), ExprSlice(ast::ExprSlice), + ExprLineMagic(ast::ExprLineMagic), ExceptHandlerExceptHandler(ast::ExceptHandlerExceptHandler), PatternMatchValue(ast::PatternMatchValue), PatternMatchSingleton(ast::PatternMatchSingleton), @@ -133,6 +135,7 @@ impl AnyNode { AnyNode::StmtPass(node) => Some(Stmt::Pass(node)), AnyNode::StmtBreak(node) => Some(Stmt::Break(node)), AnyNode::StmtContinue(node) => Some(Stmt::Continue(node)), + AnyNode::StmtLineMagic(node) => Some(Stmt::LineMagic(node)), AnyNode::ModModule(_) | AnyNode::ModInteractive(_) @@ -165,6 +168,7 @@ impl AnyNode { | AnyNode::ExprList(_) | AnyNode::ExprTuple(_) | AnyNode::ExprSlice(_) + | AnyNode::ExprLineMagic(_) | AnyNode::ExceptHandlerExceptHandler(_) | AnyNode::PatternMatchValue(_) | AnyNode::PatternMatchSingleton(_) @@ -217,6 +221,7 @@ impl AnyNode { AnyNode::ExprList(node) => Some(Expr::List(node)), AnyNode::ExprTuple(node) => Some(Expr::Tuple(node)), AnyNode::ExprSlice(node) => Some(Expr::Slice(node)), + AnyNode::ExprLineMagic(node) => Some(Expr::LineMagic(node)), AnyNode::ModModule(_) | AnyNode::ModInteractive(_) @@ -250,6 +255,7 @@ impl AnyNode { | AnyNode::StmtPass(_) | AnyNode::StmtBreak(_) | AnyNode::StmtContinue(_) + | AnyNode::StmtLineMagic(_) | AnyNode::ExceptHandlerExceptHandler(_) | AnyNode::PatternMatchValue(_) | AnyNode::PatternMatchSingleton(_) @@ -308,6 +314,7 @@ impl AnyNode { | AnyNode::StmtPass(_) | AnyNode::StmtBreak(_) | AnyNode::StmtContinue(_) + | AnyNode::StmtLineMagic(_) | AnyNode::ExprBoolOp(_) | AnyNode::ExprNamedExpr(_) | AnyNode::ExprBinOp(_) @@ -335,6 +342,7 @@ impl AnyNode { | AnyNode::ExprList(_) | AnyNode::ExprTuple(_) | AnyNode::ExprSlice(_) + | AnyNode::ExprLineMagic(_) | AnyNode::ExceptHandlerExceptHandler(_) | AnyNode::PatternMatchValue(_) | AnyNode::PatternMatchSingleton(_) @@ -401,6 +409,7 @@ impl AnyNode { | AnyNode::StmtPass(_) | AnyNode::StmtBreak(_) | AnyNode::StmtContinue(_) + | AnyNode::StmtLineMagic(_) | AnyNode::ExprBoolOp(_) | AnyNode::ExprNamedExpr(_) | AnyNode::ExprBinOp(_) @@ -428,6 +437,7 @@ impl AnyNode { | AnyNode::ExprList(_) | AnyNode::ExprTuple(_) | AnyNode::ExprSlice(_) + | AnyNode::ExprLineMagic(_) | AnyNode::ExceptHandlerExceptHandler(_) | AnyNode::TypeIgnoreTypeIgnore(_) | AnyNode::Comprehension(_) @@ -479,6 +489,7 @@ impl AnyNode { | AnyNode::StmtPass(_) | AnyNode::StmtBreak(_) | AnyNode::StmtContinue(_) + | AnyNode::StmtLineMagic(_) | AnyNode::ExprBoolOp(_) | AnyNode::ExprNamedExpr(_) | AnyNode::ExprBinOp(_) @@ -506,6 +517,7 @@ impl AnyNode { | AnyNode::ExprList(_) | AnyNode::ExprTuple(_) | AnyNode::ExprSlice(_) + | AnyNode::ExprLineMagic(_) | AnyNode::PatternMatchValue(_) | AnyNode::PatternMatchSingleton(_) | AnyNode::PatternMatchSequence(_) @@ -564,6 +576,7 @@ impl AnyNode { | AnyNode::StmtPass(_) | AnyNode::StmtBreak(_) | AnyNode::StmtContinue(_) + | AnyNode::StmtLineMagic(_) | AnyNode::ExprBoolOp(_) | AnyNode::ExprNamedExpr(_) | AnyNode::ExprBinOp(_) @@ -591,6 +604,7 @@ impl AnyNode { | AnyNode::ExprList(_) | AnyNode::ExprTuple(_) | AnyNode::ExprSlice(_) + | AnyNode::ExprLineMagic(_) | AnyNode::PatternMatchValue(_) | AnyNode::PatternMatchSingleton(_) | AnyNode::PatternMatchSequence(_) @@ -671,6 +685,7 @@ impl AnyNode { Self::StmtPass(node) => AnyNodeRef::StmtPass(node), Self::StmtBreak(node) => AnyNodeRef::StmtBreak(node), Self::StmtContinue(node) => AnyNodeRef::StmtContinue(node), + Self::StmtLineMagic(node) => AnyNodeRef::StmtLineMagic(node), Self::ExprBoolOp(node) => AnyNodeRef::ExprBoolOp(node), Self::ExprNamedExpr(node) => AnyNodeRef::ExprNamedExpr(node), Self::ExprBinOp(node) => AnyNodeRef::ExprBinOp(node), @@ -698,6 +713,7 @@ impl AnyNode { Self::ExprList(node) => AnyNodeRef::ExprList(node), Self::ExprTuple(node) => AnyNodeRef::ExprTuple(node), Self::ExprSlice(node) => AnyNodeRef::ExprSlice(node), + Self::ExprLineMagic(node) => AnyNodeRef::ExprLineMagic(node), Self::ExceptHandlerExceptHandler(node) => AnyNodeRef::ExceptHandlerExceptHandler(node), Self::PatternMatchValue(node) => AnyNodeRef::PatternMatchValue(node), Self::PatternMatchSingleton(node) => AnyNodeRef::PatternMatchSingleton(node), @@ -1651,6 +1667,34 @@ impl AstNode for ast::StmtContinue { AnyNode::from(self) } } +impl AstNode for ast::StmtLineMagic { + fn cast(kind: AnyNode) -> Option + where + Self: Sized, + { + if let AnyNode::StmtLineMagic(node) = kind { + Some(node) + } else { + None + } + } + + fn cast_ref(kind: AnyNodeRef) -> Option<&Self> { + if let AnyNodeRef::StmtLineMagic(node) = kind { + Some(node) + } else { + None + } + } + + fn as_any_node_ref(&self) -> AnyNodeRef { + AnyNodeRef::from(self) + } + + fn into_any_node(self) -> AnyNode { + AnyNode::from(self) + } +} impl AstNode for ast::ExprBoolOp { fn cast(kind: AnyNode) -> Option where @@ -2407,6 +2451,34 @@ impl AstNode for ast::ExprSlice { AnyNode::from(self) } } +impl AstNode for ast::ExprLineMagic { + fn cast(kind: AnyNode) -> Option + where + Self: Sized, + { + if let AnyNode::ExprLineMagic(node) = kind { + Some(node) + } else { + None + } + } + + fn cast_ref(kind: AnyNodeRef) -> Option<&Self> { + if let AnyNodeRef::ExprLineMagic(node) = kind { + Some(node) + } else { + None + } + } + + fn as_any_node_ref(&self) -> AnyNodeRef { + AnyNodeRef::from(self) + } + + fn into_any_node(self) -> AnyNode { + AnyNode::from(self) + } +} impl AstNode for ast::ExceptHandlerExceptHandler { fn cast(kind: AnyNode) -> Option where @@ -2973,6 +3045,7 @@ impl From for AnyNode { Stmt::Pass(node) => AnyNode::StmtPass(node), Stmt::Break(node) => AnyNode::StmtBreak(node), Stmt::Continue(node) => AnyNode::StmtContinue(node), + Stmt::LineMagic(node) => AnyNode::StmtLineMagic(node), } } } @@ -3007,6 +3080,7 @@ impl From for AnyNode { Expr::List(node) => AnyNode::ExprList(node), Expr::Tuple(node) => AnyNode::ExprTuple(node), Expr::Slice(node) => AnyNode::ExprSlice(node), + Expr::LineMagic(node) => AnyNode::ExprLineMagic(node), } } } @@ -3251,6 +3325,12 @@ impl From for AnyNode { } } +impl From for AnyNode { + fn from(node: ast::StmtLineMagic) -> Self { + AnyNode::StmtLineMagic(node) + } +} + impl From for AnyNode { fn from(node: ast::ExprBoolOp) -> Self { AnyNode::ExprBoolOp(node) @@ -3413,6 +3493,12 @@ impl From for AnyNode { } } +impl From for AnyNode { + fn from(node: ast::ExprLineMagic) -> Self { + AnyNode::ExprLineMagic(node) + } +} + impl From for AnyNode { fn from(node: ast::ExceptHandlerExceptHandler) -> Self { AnyNode::ExceptHandlerExceptHandler(node) @@ -3554,6 +3640,7 @@ impl Ranged for AnyNode { AnyNode::StmtPass(node) => node.range(), AnyNode::StmtBreak(node) => node.range(), AnyNode::StmtContinue(node) => node.range(), + AnyNode::StmtLineMagic(node) => node.range(), AnyNode::ExprBoolOp(node) => node.range(), AnyNode::ExprNamedExpr(node) => node.range(), AnyNode::ExprBinOp(node) => node.range(), @@ -3581,6 +3668,7 @@ impl Ranged for AnyNode { AnyNode::ExprList(node) => node.range(), AnyNode::ExprTuple(node) => node.range(), AnyNode::ExprSlice(node) => node.range(), + AnyNode::ExprLineMagic(node) => node.range(), AnyNode::ExceptHandlerExceptHandler(node) => node.range(), AnyNode::PatternMatchValue(node) => node.range(), AnyNode::PatternMatchSingleton(node) => node.range(), @@ -3639,6 +3727,7 @@ pub enum AnyNodeRef<'a> { StmtPass(&'a ast::StmtPass), StmtBreak(&'a ast::StmtBreak), StmtContinue(&'a ast::StmtContinue), + StmtLineMagic(&'a ast::StmtLineMagic), ExprBoolOp(&'a ast::ExprBoolOp), ExprNamedExpr(&'a ast::ExprNamedExpr), ExprBinOp(&'a ast::ExprBinOp), @@ -3666,6 +3755,7 @@ pub enum AnyNodeRef<'a> { ExprList(&'a ast::ExprList), ExprTuple(&'a ast::ExprTuple), ExprSlice(&'a ast::ExprSlice), + ExprLineMagic(&'a ast::ExprLineMagic), ExceptHandlerExceptHandler(&'a ast::ExceptHandlerExceptHandler), PatternMatchValue(&'a ast::PatternMatchValue), PatternMatchSingleton(&'a ast::PatternMatchSingleton), @@ -3723,6 +3813,7 @@ impl AnyNodeRef<'_> { AnyNodeRef::StmtPass(node) => NonNull::from(*node).cast(), AnyNodeRef::StmtBreak(node) => NonNull::from(*node).cast(), AnyNodeRef::StmtContinue(node) => NonNull::from(*node).cast(), + AnyNodeRef::StmtLineMagic(node) => NonNull::from(*node).cast(), AnyNodeRef::ExprBoolOp(node) => NonNull::from(*node).cast(), AnyNodeRef::ExprNamedExpr(node) => NonNull::from(*node).cast(), AnyNodeRef::ExprBinOp(node) => NonNull::from(*node).cast(), @@ -3750,6 +3841,7 @@ impl AnyNodeRef<'_> { AnyNodeRef::ExprList(node) => NonNull::from(*node).cast(), AnyNodeRef::ExprTuple(node) => NonNull::from(*node).cast(), AnyNodeRef::ExprSlice(node) => NonNull::from(*node).cast(), + AnyNodeRef::ExprLineMagic(node) => NonNull::from(*node).cast(), AnyNodeRef::ExceptHandlerExceptHandler(node) => NonNull::from(*node).cast(), AnyNodeRef::PatternMatchValue(node) => NonNull::from(*node).cast(), AnyNodeRef::PatternMatchSingleton(node) => NonNull::from(*node).cast(), @@ -3813,6 +3905,7 @@ impl AnyNodeRef<'_> { AnyNodeRef::StmtPass(_) => NodeKind::StmtPass, AnyNodeRef::StmtBreak(_) => NodeKind::StmtBreak, AnyNodeRef::StmtContinue(_) => NodeKind::StmtContinue, + AnyNodeRef::StmtLineMagic(_) => NodeKind::StmtLineMagic, AnyNodeRef::ExprBoolOp(_) => NodeKind::ExprBoolOp, AnyNodeRef::ExprNamedExpr(_) => NodeKind::ExprNamedExpr, AnyNodeRef::ExprBinOp(_) => NodeKind::ExprBinOp, @@ -3840,6 +3933,7 @@ impl AnyNodeRef<'_> { AnyNodeRef::ExprList(_) => NodeKind::ExprList, AnyNodeRef::ExprTuple(_) => NodeKind::ExprTuple, AnyNodeRef::ExprSlice(_) => NodeKind::ExprSlice, + AnyNodeRef::ExprLineMagic(_) => NodeKind::ExprLineMagic, AnyNodeRef::ExceptHandlerExceptHandler(_) => NodeKind::ExceptHandlerExceptHandler, AnyNodeRef::PatternMatchValue(_) => NodeKind::PatternMatchValue, AnyNodeRef::PatternMatchSingleton(_) => NodeKind::PatternMatchSingleton, @@ -3892,7 +3986,8 @@ impl AnyNodeRef<'_> { | AnyNodeRef::StmtExpr(_) | AnyNodeRef::StmtPass(_) | AnyNodeRef::StmtBreak(_) - | AnyNodeRef::StmtContinue(_) => true, + | AnyNodeRef::StmtContinue(_) + | AnyNodeRef::StmtLineMagic(_) => true, AnyNodeRef::ModModule(_) | AnyNodeRef::ModInteractive(_) @@ -3925,6 +4020,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::ExprList(_) | AnyNodeRef::ExprTuple(_) | AnyNodeRef::ExprSlice(_) + | AnyNodeRef::ExprLineMagic(_) | AnyNodeRef::ExceptHandlerExceptHandler(_) | AnyNodeRef::PatternMatchValue(_) | AnyNodeRef::PatternMatchSingleton(_) @@ -3976,7 +4072,8 @@ impl AnyNodeRef<'_> { | AnyNodeRef::ExprName(_) | AnyNodeRef::ExprList(_) | AnyNodeRef::ExprTuple(_) - | AnyNodeRef::ExprSlice(_) => true, + | AnyNodeRef::ExprSlice(_) + | AnyNodeRef::ExprLineMagic(_) => true, AnyNodeRef::ModModule(_) | AnyNodeRef::ModInteractive(_) @@ -4010,6 +4107,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::StmtPass(_) | AnyNodeRef::StmtBreak(_) | AnyNodeRef::StmtContinue(_) + | AnyNodeRef::StmtLineMagic(_) | AnyNodeRef::ExceptHandlerExceptHandler(_) | AnyNodeRef::PatternMatchValue(_) | AnyNodeRef::PatternMatchSingleton(_) @@ -4068,6 +4166,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::StmtPass(_) | AnyNodeRef::StmtBreak(_) | AnyNodeRef::StmtContinue(_) + | AnyNodeRef::StmtLineMagic(_) | AnyNodeRef::ExprBoolOp(_) | AnyNodeRef::ExprNamedExpr(_) | AnyNodeRef::ExprBinOp(_) @@ -4095,6 +4194,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::ExprList(_) | AnyNodeRef::ExprTuple(_) | AnyNodeRef::ExprSlice(_) + | AnyNodeRef::ExprLineMagic(_) | AnyNodeRef::ExceptHandlerExceptHandler(_) | AnyNodeRef::PatternMatchValue(_) | AnyNodeRef::PatternMatchSingleton(_) @@ -4161,6 +4261,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::StmtPass(_) | AnyNodeRef::StmtBreak(_) | AnyNodeRef::StmtContinue(_) + | AnyNodeRef::StmtLineMagic(_) | AnyNodeRef::ExprBoolOp(_) | AnyNodeRef::ExprNamedExpr(_) | AnyNodeRef::ExprBinOp(_) @@ -4188,6 +4289,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::ExprList(_) | AnyNodeRef::ExprTuple(_) | AnyNodeRef::ExprSlice(_) + | AnyNodeRef::ExprLineMagic(_) | AnyNodeRef::ExceptHandlerExceptHandler(_) | AnyNodeRef::TypeIgnoreTypeIgnore(_) | AnyNodeRef::Comprehension(_) @@ -4239,6 +4341,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::StmtPass(_) | AnyNodeRef::StmtBreak(_) | AnyNodeRef::StmtContinue(_) + | AnyNodeRef::StmtLineMagic(_) | AnyNodeRef::ExprBoolOp(_) | AnyNodeRef::ExprNamedExpr(_) | AnyNodeRef::ExprBinOp(_) @@ -4266,6 +4369,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::ExprList(_) | AnyNodeRef::ExprTuple(_) | AnyNodeRef::ExprSlice(_) + | AnyNodeRef::ExprLineMagic(_) | AnyNodeRef::PatternMatchValue(_) | AnyNodeRef::PatternMatchSingleton(_) | AnyNodeRef::PatternMatchSequence(_) @@ -4324,6 +4428,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::StmtPass(_) | AnyNodeRef::StmtBreak(_) | AnyNodeRef::StmtContinue(_) + | AnyNodeRef::StmtLineMagic(_) | AnyNodeRef::ExprBoolOp(_) | AnyNodeRef::ExprNamedExpr(_) | AnyNodeRef::ExprBinOp(_) @@ -4351,6 +4456,7 @@ impl AnyNodeRef<'_> { | AnyNodeRef::ExprList(_) | AnyNodeRef::ExprTuple(_) | AnyNodeRef::ExprSlice(_) + | AnyNodeRef::ExprLineMagic(_) | AnyNodeRef::PatternMatchValue(_) | AnyNodeRef::PatternMatchSingleton(_) | AnyNodeRef::PatternMatchSequence(_) @@ -4590,6 +4696,12 @@ impl<'a> From<&'a ast::StmtContinue> for AnyNodeRef<'a> { } } +impl<'a> From<&'a ast::StmtLineMagic> for AnyNodeRef<'a> { + fn from(node: &'a ast::StmtLineMagic) -> Self { + AnyNodeRef::StmtLineMagic(node) + } +} + impl<'a> From<&'a ast::ExprBoolOp> for AnyNodeRef<'a> { fn from(node: &'a ast::ExprBoolOp) -> Self { AnyNodeRef::ExprBoolOp(node) @@ -4752,6 +4864,12 @@ impl<'a> From<&'a ast::ExprSlice> for AnyNodeRef<'a> { } } +impl<'a> From<&'a ast::ExprLineMagic> for AnyNodeRef<'a> { + fn from(node: &'a ast::ExprLineMagic) -> Self { + AnyNodeRef::ExprLineMagic(node) + } +} + impl<'a> From<&'a ast::ExceptHandlerExceptHandler> for AnyNodeRef<'a> { fn from(node: &'a ast::ExceptHandlerExceptHandler) -> Self { AnyNodeRef::ExceptHandlerExceptHandler(node) @@ -4849,6 +4967,7 @@ impl<'a> From<&'a Stmt> for AnyNodeRef<'a> { Stmt::Pass(node) => AnyNodeRef::StmtPass(node), Stmt::Break(node) => AnyNodeRef::StmtBreak(node), Stmt::Continue(node) => AnyNodeRef::StmtContinue(node), + Stmt::LineMagic(node) => AnyNodeRef::StmtLineMagic(node), } } } @@ -4883,6 +5002,7 @@ impl<'a> From<&'a Expr> for AnyNodeRef<'a> { Expr::List(node) => AnyNodeRef::ExprList(node), Expr::Tuple(node) => AnyNodeRef::ExprTuple(node), Expr::Slice(node) => AnyNodeRef::ExprSlice(node), + Expr::LineMagic(node) => AnyNodeRef::ExprLineMagic(node), } } } @@ -5007,6 +5127,7 @@ impl Ranged for AnyNodeRef<'_> { AnyNodeRef::StmtPass(node) => node.range(), AnyNodeRef::StmtBreak(node) => node.range(), AnyNodeRef::StmtContinue(node) => node.range(), + AnyNodeRef::StmtLineMagic(node) => node.range(), AnyNodeRef::ExprBoolOp(node) => node.range(), AnyNodeRef::ExprNamedExpr(node) => node.range(), AnyNodeRef::ExprBinOp(node) => node.range(), @@ -5034,6 +5155,7 @@ impl Ranged for AnyNodeRef<'_> { AnyNodeRef::ExprList(node) => node.range(), AnyNodeRef::ExprTuple(node) => node.range(), AnyNodeRef::ExprSlice(node) => node.range(), + AnyNodeRef::ExprLineMagic(node) => node.range(), AnyNodeRef::ExceptHandlerExceptHandler(node) => node.range(), AnyNodeRef::PatternMatchValue(node) => node.range(), AnyNodeRef::PatternMatchSingleton(node) => node.range(), @@ -5088,6 +5210,7 @@ pub enum NodeKind { StmtImportFrom, StmtGlobal, StmtNonlocal, + StmtLineMagic, StmtExpr, StmtPass, StmtBreak, @@ -5119,6 +5242,7 @@ pub enum NodeKind { ExprList, ExprTuple, ExprSlice, + ExprLineMagic, ExceptHandlerExceptHandler, PatternMatchValue, PatternMatchSingleton, diff --git a/crates/ruff_python_ast/src/relocate.rs b/crates/ruff_python_ast/src/relocate.rs index b05b170ec421ea..4d16c4d8ba077f 100644 --- a/crates/ruff_python_ast/src/relocate.rs +++ b/crates/ruff_python_ast/src/relocate.rs @@ -200,5 +200,8 @@ pub fn relocate_expr(expr: &mut Expr, location: TextRange) { relocate_expr(expr, location); } } + Expr::LineMagic(ast::ExprLineMagic { range, .. }) => { + *range = location; + } } } diff --git a/crates/ruff_python_ast/src/source_code/generator.rs b/crates/ruff_python_ast/src/source_code/generator.rs index 778ee8762b58a8..1bea32a200ae35 100644 --- a/crates/ruff_python_ast/src/source_code/generator.rs +++ b/crates/ruff_python_ast/src/source_code/generator.rs @@ -720,6 +720,11 @@ impl<'a> Generator<'a> { self.p("continue"); }); } + Stmt::LineMagic(ast::StmtLineMagic { kind, value, .. }) => { + statement!({ + self.p(&format!("{kind}{value}")); + }); + } } } @@ -1270,6 +1275,9 @@ impl<'a> Generator<'a> { self.unparse_expr(step, precedence::SLICE); } } + Expr::LineMagic(ast::ExprLineMagic { kind, value, .. }) => { + self.p(&format!("{kind}{value}")); + } } } diff --git a/crates/ruff_python_ast/src/visitor.rs b/crates/ruff_python_ast/src/visitor.rs index bf2f87ac9256a7..fe8047b21d31b3 100644 --- a/crates/ruff_python_ast/src/visitor.rs +++ b/crates/ruff_python_ast/src/visitor.rs @@ -335,6 +335,7 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) { }) => visitor.visit_expr(value), Stmt::Pass(_) | Stmt::Break(_) | Stmt::Continue(_) => {} Stmt::TypeAlias(_) => todo!(), + Stmt::LineMagic(_) => {} } } @@ -586,6 +587,7 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) { visitor.visit_expr(expr); } } + Expr::LineMagic(_) => {} } } diff --git a/crates/ruff_python_ast/src/visitor/preorder.rs b/crates/ruff_python_ast/src/visitor/preorder.rs index ae9209d21fd718..e73723c199b30c 100644 --- a/crates/ruff_python_ast/src/visitor/preorder.rs +++ b/crates/ruff_python_ast/src/visitor/preorder.rs @@ -399,7 +399,8 @@ where | Stmt::Break(_) | Stmt::Continue(_) | Stmt::Global(_) - | Stmt::Nonlocal(_) => {} + | Stmt::Nonlocal(_) + | Stmt::LineMagic(_) => {} Stmt::TypeAlias(_) => todo!(), } } @@ -695,6 +696,7 @@ where visitor.visit_expr(expr); } } + Expr::LineMagic(_) => (), } }