mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-19 01:51:30 +00:00
Make BoolOp its own located token (#3265)
This commit is contained in:
parent
470e1c1754
commit
061495a9eb
19 changed files with 355 additions and 301 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2141,6 +2141,7 @@ dependencies = [
|
||||||
"clap 4.1.6",
|
"clap 4.1.6",
|
||||||
"insta",
|
"insta",
|
||||||
"is-macro",
|
"is-macro",
|
||||||
|
"itertools",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"ruff_formatter",
|
"ruff_formatter",
|
||||||
"ruff_python",
|
"ruff_python",
|
||||||
|
|
|
@ -14,6 +14,7 @@ ruff_text_size = { path = "../ruff_text_size" }
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
clap = { workspace = true }
|
clap = { workspace = true }
|
||||||
is-macro = { workspace = true }
|
is-macro = { workspace = true }
|
||||||
|
itertools = { workspace = true }
|
||||||
once_cell = { workspace = true }
|
once_cell = { workspace = true }
|
||||||
rustc-hash = { workspace = true }
|
rustc-hash = { workspace = true }
|
||||||
rustpython-common = { workspace = true }
|
rustpython-common = { workspace = true }
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use crate::core::visitor;
|
use crate::core::visitor;
|
||||||
use crate::core::visitor::Visitor;
|
use crate::core::visitor::Visitor;
|
||||||
use crate::cst::{Alias, Arg, Body, Excepthandler, Expr, Pattern, SliceIndex, Stmt};
|
use crate::cst::{
|
||||||
|
Alias, Arg, Body, BoolOp, Excepthandler, Expr, Keyword, Pattern, SliceIndex, Stmt,
|
||||||
|
};
|
||||||
use crate::trivia::{decorate_trivia, TriviaIndex, TriviaToken};
|
use crate::trivia::{decorate_trivia, TriviaIndex, TriviaToken};
|
||||||
|
|
||||||
struct AttachmentVisitor {
|
struct AttachmentVisitor {
|
||||||
|
@ -56,6 +58,22 @@ impl<'a> Visitor<'a> for AttachmentVisitor {
|
||||||
visitor::walk_excepthandler(self, excepthandler);
|
visitor::walk_excepthandler(self, excepthandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_keyword(&mut self, keyword: &'a mut Keyword) {
|
||||||
|
let trivia = self.index.keyword.remove(&keyword.id());
|
||||||
|
if let Some(comments) = trivia {
|
||||||
|
keyword.trivia.extend(comments);
|
||||||
|
}
|
||||||
|
visitor::walk_keyword(self, keyword);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_bool_op(&mut self, bool_op: &'a mut BoolOp) {
|
||||||
|
let trivia = self.index.bool_op.remove(&bool_op.id());
|
||||||
|
if let Some(comments) = trivia {
|
||||||
|
bool_op.trivia.extend(comments);
|
||||||
|
}
|
||||||
|
visitor::walk_bool_op(self, bool_op);
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_slice_index(&mut self, slice_index: &'a mut SliceIndex) {
|
fn visit_slice_index(&mut self, slice_index: &'a mut SliceIndex) {
|
||||||
let trivia = self.index.slice_index.remove(&slice_index.id());
|
let trivia = self.index.slice_index.remove(&slice_index.id());
|
||||||
if let Some(comments) = trivia {
|
if let Some(comments) = trivia {
|
||||||
|
|
|
@ -28,6 +28,7 @@ pub fn trailing_quote(content: &str) -> Option<&&str> {
|
||||||
.find(|&pattern| content.ends_with(pattern))
|
.find(|&pattern| content.ends_with(pattern))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return `true` if the given string is a radix literal (e.g., `0b101`).
|
||||||
pub fn is_radix_literal(content: &str) -> bool {
|
pub fn is_radix_literal(content: &str) -> bool {
|
||||||
content.starts_with("0b")
|
content.starts_with("0b")
|
||||||
|| content.starts_with("0o")
|
|| content.starts_with("0o")
|
||||||
|
@ -37,6 +38,29 @@ pub fn is_radix_literal(content: &str) -> bool {
|
||||||
|| content.starts_with("0X")
|
|| content.starts_with("0X")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Find the first token in the given range that satisfies the given predicate.
|
||||||
|
pub fn find_tok(
|
||||||
|
location: Location,
|
||||||
|
end_location: Location,
|
||||||
|
locator: &Locator,
|
||||||
|
f: impl Fn(rustpython_parser::Tok) -> bool,
|
||||||
|
) -> (Location, Location) {
|
||||||
|
let (source, start_index, end_index) = locator.slice(Range::new(location, end_location));
|
||||||
|
for (start, tok, end) in rustpython_parser::lexer::lex_located(
|
||||||
|
&source[start_index..end_index],
|
||||||
|
rustpython_parser::Mode::Module,
|
||||||
|
location,
|
||||||
|
)
|
||||||
|
.flatten()
|
||||||
|
{
|
||||||
|
if f(tok) {
|
||||||
|
return (start, end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
/// Expand the range of a compound statement.
|
/// Expand the range of a compound statement.
|
||||||
///
|
///
|
||||||
/// `location` is the start of the compound statement (e.g., the `if` in `if x:`).
|
/// `location` is the start of the compound statement (e.g., the `if` in `if x:`).
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use rustpython_parser::ast::Constant;
|
use rustpython_parser::ast::Constant;
|
||||||
|
|
||||||
use crate::cst::{
|
use crate::cst::{
|
||||||
Alias, Arg, Arguments, Body, Boolop, Cmpop, Comprehension, Excepthandler, ExcepthandlerKind,
|
Alias, Arg, Arguments, Body, BoolOp, Cmpop, Comprehension, Excepthandler, ExcepthandlerKind,
|
||||||
Expr, ExprContext, ExprKind, Keyword, MatchCase, Operator, Pattern, PatternKind, SliceIndex,
|
Expr, ExprContext, ExprKind, Keyword, MatchCase, Operator, Pattern, PatternKind, SliceIndex,
|
||||||
SliceIndexKind, Stmt, StmtKind, Unaryop, Withitem,
|
SliceIndexKind, Stmt, StmtKind, Unaryop, Withitem,
|
||||||
};
|
};
|
||||||
|
@ -22,8 +22,8 @@ pub trait Visitor<'a> {
|
||||||
fn visit_expr_context(&mut self, expr_context: &'a mut ExprContext) {
|
fn visit_expr_context(&mut self, expr_context: &'a mut ExprContext) {
|
||||||
walk_expr_context(self, expr_context);
|
walk_expr_context(self, expr_context);
|
||||||
}
|
}
|
||||||
fn visit_boolop(&mut self, boolop: &'a mut Boolop) {
|
fn visit_bool_op(&mut self, bool_op: &'a mut BoolOp) {
|
||||||
walk_boolop(self, boolop);
|
walk_bool_op(self, bool_op);
|
||||||
}
|
}
|
||||||
fn visit_operator(&mut self, operator: &'a mut Operator) {
|
fn visit_operator(&mut self, operator: &'a mut Operator) {
|
||||||
walk_operator(self, operator);
|
walk_operator(self, operator);
|
||||||
|
@ -294,10 +294,12 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a mut Stm
|
||||||
|
|
||||||
pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a mut Expr) {
|
pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a mut Expr) {
|
||||||
match &mut expr.node {
|
match &mut expr.node {
|
||||||
ExprKind::BoolOp { op, values } => {
|
ExprKind::BoolOp { ops, values } => {
|
||||||
visitor.visit_boolop(op);
|
for op in ops {
|
||||||
for expr in values {
|
visitor.visit_bool_op(op);
|
||||||
visitor.visit_expr(expr);
|
}
|
||||||
|
for value in values {
|
||||||
|
visitor.visit_expr(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::NamedExpr { target, value } => {
|
ExprKind::NamedExpr { target, value } => {
|
||||||
|
@ -600,7 +602,7 @@ pub fn walk_expr_context<'a, V: Visitor<'a> + ?Sized>(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
pub fn walk_boolop<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, boolop: &'a mut Boolop) {}
|
pub fn walk_bool_op<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, bool_op: &'a mut BoolOp) {}
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
pub fn walk_operator<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, operator: &'a mut Operator) {}
|
pub fn walk_operator<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, operator: &'a mut Operator) {}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
#![allow(clippy::derive_partial_eq_without_eq)]
|
#![allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
|
||||||
use crate::core::helpers::{expand_indented_block, is_elif};
|
|
||||||
use rustpython_parser::ast::{Constant, Location};
|
use rustpython_parser::ast::{Constant, Location};
|
||||||
use rustpython_parser::Mode;
|
use rustpython_parser::Mode;
|
||||||
|
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
use crate::core::helpers::{expand_indented_block, find_tok, is_elif};
|
||||||
use crate::core::locator::Locator;
|
use crate::core::locator::Locator;
|
||||||
use crate::core::types::Range;
|
use crate::core::types::Range;
|
||||||
use crate::trivia::{Parenthesize, Trivia};
|
use crate::trivia::{Parenthesize, Trivia};
|
||||||
|
@ -57,13 +59,13 @@ impl From<rustpython_parser::ast::ExprContext> for ExprContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum Boolop {
|
pub enum BoolOpKind {
|
||||||
And,
|
And,
|
||||||
Or,
|
Or,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<rustpython_parser::ast::Boolop> for Boolop {
|
impl From<&rustpython_parser::ast::Boolop> for BoolOpKind {
|
||||||
fn from(op: rustpython_parser::ast::Boolop) -> Self {
|
fn from(op: &rustpython_parser::ast::Boolop) -> Self {
|
||||||
match op {
|
match op {
|
||||||
rustpython_parser::ast::Boolop::And => Self::And,
|
rustpython_parser::ast::Boolop::And => Self::And,
|
||||||
rustpython_parser::ast::Boolop::Or => Self::Or,
|
rustpython_parser::ast::Boolop::Or => Self::Or,
|
||||||
|
@ -71,6 +73,8 @@ impl From<rustpython_parser::ast::Boolop> for Boolop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type BoolOp = Located<BoolOpKind>;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum Operator {
|
pub enum Operator {
|
||||||
Add,
|
Add,
|
||||||
|
@ -308,7 +312,7 @@ pub type Stmt = Located<StmtKind>;
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum ExprKind {
|
pub enum ExprKind {
|
||||||
BoolOp {
|
BoolOp {
|
||||||
op: Boolop,
|
ops: Vec<BoolOp>,
|
||||||
values: Vec<Expr>,
|
values: Vec<Expr>,
|
||||||
},
|
},
|
||||||
NamedExpr {
|
NamedExpr {
|
||||||
|
@ -1677,7 +1681,23 @@ impl From<(rustpython_parser::ast::Expr, &Locator<'_>)> for Expr {
|
||||||
location: expr.location,
|
location: expr.location,
|
||||||
end_location: expr.end_location,
|
end_location: expr.end_location,
|
||||||
node: ExprKind::BoolOp {
|
node: ExprKind::BoolOp {
|
||||||
op: op.into(),
|
ops: values
|
||||||
|
.iter()
|
||||||
|
.tuple_windows()
|
||||||
|
.map(|(left, right)| {
|
||||||
|
let target = match &op {
|
||||||
|
rustpython_parser::ast::Boolop::And => rustpython_parser::Tok::And,
|
||||||
|
rustpython_parser::ast::Boolop::Or => rustpython_parser::Tok::Or,
|
||||||
|
};
|
||||||
|
let (op_location, op_end_location) = find_tok(
|
||||||
|
left.end_location.unwrap(),
|
||||||
|
right.location,
|
||||||
|
locator,
|
||||||
|
|tok| tok == target,
|
||||||
|
);
|
||||||
|
BoolOp::new(op_location, op_end_location, (&op).into())
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
values: values
|
values: values
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|node| (node, locator).into())
|
.map(|node| (node, locator).into())
|
||||||
|
|
38
crates/ruff_python_formatter/src/format/bool_op.rs
Normal file
38
crates/ruff_python_formatter/src/format/bool_op.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
use ruff_formatter::prelude::*;
|
||||||
|
use ruff_formatter::write;
|
||||||
|
|
||||||
|
use crate::context::ASTFormatContext;
|
||||||
|
use crate::cst::{BoolOp, BoolOpKind};
|
||||||
|
use crate::format::comments::{end_of_line_comments, leading_comments, trailing_comments};
|
||||||
|
use crate::shared_traits::AsFormat;
|
||||||
|
|
||||||
|
pub struct FormatBoolOp<'a> {
|
||||||
|
item: &'a BoolOp,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsFormat<ASTFormatContext<'_>> for BoolOp {
|
||||||
|
type Format<'a> = FormatBoolOp<'a>;
|
||||||
|
|
||||||
|
fn format(&self) -> Self::Format<'_> {
|
||||||
|
FormatBoolOp { item: self }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Format<ASTFormatContext<'_>> for FormatBoolOp<'_> {
|
||||||
|
fn fmt(&self, f: &mut Formatter<ASTFormatContext>) -> FormatResult<()> {
|
||||||
|
let boolop = self.item;
|
||||||
|
|
||||||
|
write!(f, [leading_comments(boolop)])?;
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
[text(match boolop.node {
|
||||||
|
BoolOpKind::And => "and",
|
||||||
|
BoolOpKind::Or => "or",
|
||||||
|
})]
|
||||||
|
)?;
|
||||||
|
write!(f, [end_of_line_comments(boolop)])?;
|
||||||
|
write!(f, [trailing_comments(boolop)])?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,32 +0,0 @@
|
||||||
use ruff_formatter::prelude::*;
|
|
||||||
use ruff_formatter::write;
|
|
||||||
|
|
||||||
use crate::context::ASTFormatContext;
|
|
||||||
use crate::cst::Boolop;
|
|
||||||
use crate::shared_traits::AsFormat;
|
|
||||||
|
|
||||||
pub struct FormatBoolop<'a> {
|
|
||||||
item: &'a Boolop,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsFormat<ASTFormatContext<'_>> for Boolop {
|
|
||||||
type Format<'a> = FormatBoolop<'a>;
|
|
||||||
|
|
||||||
fn format(&self) -> Self::Format<'_> {
|
|
||||||
FormatBoolop { item: self }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Format<ASTFormatContext<'_>> for FormatBoolop<'_> {
|
|
||||||
fn fmt(&self, f: &mut Formatter<ASTFormatContext>) -> FormatResult<()> {
|
|
||||||
let boolop = self.item;
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
[text(match boolop {
|
|
||||||
Boolop::And => "and",
|
|
||||||
Boolop::Or => "or",
|
|
||||||
})]
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,7 +9,7 @@ use ruff_text_size::TextSize;
|
||||||
use crate::context::ASTFormatContext;
|
use crate::context::ASTFormatContext;
|
||||||
use crate::core::types::Range;
|
use crate::core::types::Range;
|
||||||
use crate::cst::{
|
use crate::cst::{
|
||||||
Arguments, Boolop, Cmpop, Comprehension, Expr, ExprKind, Keyword, Operator, SliceIndex,
|
Arguments, BoolOp, Cmpop, Comprehension, Expr, ExprKind, Keyword, Operator, SliceIndex,
|
||||||
SliceIndexKind, Unaryop,
|
SliceIndexKind, Unaryop,
|
||||||
};
|
};
|
||||||
use crate::format::builders::literal;
|
use crate::format::builders::literal;
|
||||||
|
@ -338,38 +338,10 @@ fn format_call(
|
||||||
if args.is_empty() && keywords.is_empty() {
|
if args.is_empty() && keywords.is_empty() {
|
||||||
write!(f, [text("(")])?;
|
write!(f, [text("(")])?;
|
||||||
write!(f, [text(")")])?;
|
write!(f, [text(")")])?;
|
||||||
|
write!(f, [end_of_line_comments(expr)])?;
|
||||||
// Format any end-of-line comments.
|
|
||||||
let mut first = true;
|
|
||||||
for range in expr.trivia.iter().filter_map(|trivia| {
|
|
||||||
if trivia.relationship.is_trailing() {
|
|
||||||
trivia.kind.end_of_line_comment()
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
if std::mem::take(&mut first) {
|
|
||||||
write!(f, [line_suffix(&text(" "))])?;
|
|
||||||
}
|
|
||||||
write!(f, [line_suffix(&literal(range))])?;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
write!(f, [text("(")])?;
|
write!(f, [text("(")])?;
|
||||||
|
write!(f, [end_of_line_comments(expr)])?;
|
||||||
// Format any end-of-line comments.
|
|
||||||
let mut first = true;
|
|
||||||
for range in expr.trivia.iter().filter_map(|trivia| {
|
|
||||||
if trivia.relationship.is_trailing() {
|
|
||||||
trivia.kind.end_of_line_comment()
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
if std::mem::take(&mut first) {
|
|
||||||
write!(f, [line_suffix(&text(" "))])?;
|
|
||||||
}
|
|
||||||
write!(f, [line_suffix(&literal(range))])?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let magic_trailing_comma = expr.trivia.iter().any(|c| c.kind.is_magic_trailing_comma());
|
let magic_trailing_comma = expr.trivia.iter().any(|c| c.kind.is_magic_trailing_comma());
|
||||||
write!(
|
write!(
|
||||||
|
@ -394,14 +366,7 @@ fn format_call(
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
[group(&format_args![&format_with(|f| {
|
[group(&format_args![&format_with(|f| {
|
||||||
if let Some(arg) = &keyword.node.arg {
|
write!(f, [keyword.format()])?;
|
||||||
write!(f, [dynamic_text(arg, TextSize::default())])?;
|
|
||||||
write!(f, [text("=")])?;
|
|
||||||
write!(f, [keyword.node.value.format()])?;
|
|
||||||
} else {
|
|
||||||
write!(f, [text("**")])?;
|
|
||||||
write!(f, [keyword.node.value.format()])?;
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})])]
|
})])]
|
||||||
)?;
|
)?;
|
||||||
|
@ -736,19 +701,15 @@ fn format_named_expr(
|
||||||
fn format_bool_op(
|
fn format_bool_op(
|
||||||
f: &mut Formatter<ASTFormatContext<'_>>,
|
f: &mut Formatter<ASTFormatContext<'_>>,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
op: &Boolop,
|
ops: &[BoolOp],
|
||||||
values: &[Expr],
|
values: &[Expr],
|
||||||
) -> FormatResult<()> {
|
) -> FormatResult<()> {
|
||||||
let mut first = true;
|
write!(f, [group(&format_args![values[0].format()])])?;
|
||||||
for value in values {
|
for (op, value) in ops.iter().zip(&values[1..]) {
|
||||||
if std::mem::take(&mut first) {
|
write!(f, [soft_line_break_or_space()])?;
|
||||||
write!(f, [group(&format_args![value.format()])])?;
|
write!(f, [op.format()])?;
|
||||||
} else {
|
write!(f, [space()])?;
|
||||||
write!(f, [soft_line_break_or_space()])?;
|
write!(f, [group(&format_args![value.format()])])?;
|
||||||
write!(f, [op.format()])?;
|
|
||||||
write!(f, [space()])?;
|
|
||||||
write!(f, [group(&format_args![value.format()])])?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
write!(f, [end_of_line_comments(expr)])?;
|
write!(f, [end_of_line_comments(expr)])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -851,7 +812,7 @@ impl Format<ASTFormatContext<'_>> for FormatExpr<'_> {
|
||||||
write!(f, [leading_comments(self.item)])?;
|
write!(f, [leading_comments(self.item)])?;
|
||||||
|
|
||||||
match &self.item.node {
|
match &self.item.node {
|
||||||
ExprKind::BoolOp { op, values } => format_bool_op(f, self.item, op, values),
|
ExprKind::BoolOp { ops, values } => format_bool_op(f, self.item, ops, values),
|
||||||
ExprKind::NamedExpr { target, value } => format_named_expr(f, self.item, target, value),
|
ExprKind::NamedExpr { target, value } => format_named_expr(f, self.item, target, value),
|
||||||
ExprKind::BinOp { left, op, right } => format_bin_op(f, self.item, left, op, right),
|
ExprKind::BinOp { left, op, right } => format_bin_op(f, self.item, left, op, right),
|
||||||
ExprKind::UnaryOp { op, operand } => format_unary_op(f, self.item, op, operand),
|
ExprKind::UnaryOp { op, operand } => format_unary_op(f, self.item, op, operand),
|
||||||
|
|
40
crates/ruff_python_formatter/src/format/keyword.rs
Normal file
40
crates/ruff_python_formatter/src/format/keyword.rs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
use ruff_formatter::prelude::*;
|
||||||
|
use ruff_formatter::write;
|
||||||
|
use ruff_text_size::TextSize;
|
||||||
|
|
||||||
|
use crate::context::ASTFormatContext;
|
||||||
|
use crate::cst::Keyword;
|
||||||
|
use crate::format::comments::{end_of_line_comments, leading_comments, trailing_comments};
|
||||||
|
use crate::shared_traits::AsFormat;
|
||||||
|
|
||||||
|
pub struct FormatKeyword<'a> {
|
||||||
|
item: &'a Keyword,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsFormat<ASTFormatContext<'_>> for Keyword {
|
||||||
|
type Format<'a> = FormatKeyword<'a>;
|
||||||
|
|
||||||
|
fn format(&self) -> Self::Format<'_> {
|
||||||
|
FormatKeyword { item: self }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Format<ASTFormatContext<'_>> for FormatKeyword<'_> {
|
||||||
|
fn fmt(&self, f: &mut Formatter<ASTFormatContext>) -> FormatResult<()> {
|
||||||
|
let keyword = self.item;
|
||||||
|
|
||||||
|
write!(f, [leading_comments(keyword)])?;
|
||||||
|
if let Some(arg) = &keyword.node.arg {
|
||||||
|
write!(f, [dynamic_text(arg, TextSize::default())])?;
|
||||||
|
write!(f, [text("=")])?;
|
||||||
|
write!(f, [keyword.node.value.format()])?;
|
||||||
|
} else {
|
||||||
|
write!(f, [text("**")])?;
|
||||||
|
write!(f, [keyword.node.value.format()])?;
|
||||||
|
}
|
||||||
|
write!(f, [end_of_line_comments(keyword)])?;
|
||||||
|
write!(f, [trailing_comments(keyword)])?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
mod alias;
|
mod alias;
|
||||||
mod arg;
|
mod arg;
|
||||||
mod arguments;
|
mod arguments;
|
||||||
mod boolop;
|
mod bool_op;
|
||||||
pub mod builders;
|
pub mod builders;
|
||||||
mod cmpop;
|
mod cmpop;
|
||||||
mod comments;
|
mod comments;
|
||||||
|
@ -9,6 +9,7 @@ mod comprehension;
|
||||||
mod excepthandler;
|
mod excepthandler;
|
||||||
mod expr;
|
mod expr;
|
||||||
mod helpers;
|
mod helpers;
|
||||||
|
mod keyword;
|
||||||
mod match_case;
|
mod match_case;
|
||||||
mod numbers;
|
mod numbers;
|
||||||
mod operator;
|
mod operator;
|
||||||
|
|
|
@ -131,18 +131,7 @@ fn format_class_def(
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i, keyword) in keywords.iter().enumerate() {
|
for (i, keyword) in keywords.iter().enumerate() {
|
||||||
if let Some(arg) = &keyword.node.arg {
|
write!(f, [keyword.format()])?;
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
[
|
|
||||||
dynamic_text(arg, TextSize::default()),
|
|
||||||
text("="),
|
|
||||||
keyword.node.value.format()
|
|
||||||
]
|
|
||||||
)?;
|
|
||||||
} else {
|
|
||||||
write!(f, [text("**"), keyword.node.value.format()])?;
|
|
||||||
}
|
|
||||||
if i < keywords.len() - 1 {
|
if i < keywords.len() - 1 {
|
||||||
write!(f, [text(","), soft_line_break_or_space()])?;
|
write!(f, [text(","), soft_line_break_or_space()])?;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2,7 +2,10 @@ use rustpython_parser::ast::Constant;
|
||||||
|
|
||||||
use crate::core::visitor;
|
use crate::core::visitor;
|
||||||
use crate::core::visitor::Visitor;
|
use crate::core::visitor::Visitor;
|
||||||
use crate::cst::{ExcepthandlerKind, Expr, ExprKind, Stmt, StmtKind};
|
use crate::cst::{
|
||||||
|
Alias, Arg, BoolOp, Excepthandler, ExcepthandlerKind, Expr, ExprKind, Keyword, Pattern,
|
||||||
|
SliceIndex, Stmt, StmtKind,
|
||||||
|
};
|
||||||
use crate::trivia::{Relationship, Trivia, TriviaKind};
|
use crate::trivia::{Relationship, Trivia, TriviaKind};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
@ -296,9 +299,43 @@ struct ExprNormalizer;
|
||||||
impl<'a> Visitor<'a> for ExprNormalizer {
|
impl<'a> Visitor<'a> for ExprNormalizer {
|
||||||
fn visit_expr(&mut self, expr: &'a mut Expr) {
|
fn visit_expr(&mut self, expr: &'a mut Expr) {
|
||||||
expr.trivia.retain(|c| !c.kind.is_empty_line());
|
expr.trivia.retain(|c| !c.kind.is_empty_line());
|
||||||
|
|
||||||
visitor::walk_expr(self, expr);
|
visitor::walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_alias(&mut self, alias: &'a mut Alias) {
|
||||||
|
alias.trivia.retain(|c| !c.kind.is_empty_line());
|
||||||
|
visitor::walk_alias(self, alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_arg(&mut self, arg: &'a mut Arg) {
|
||||||
|
arg.trivia.retain(|c| !c.kind.is_empty_line());
|
||||||
|
visitor::walk_arg(self, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_excepthandler(&mut self, excepthandler: &'a mut Excepthandler) {
|
||||||
|
excepthandler.trivia.retain(|c| !c.kind.is_empty_line());
|
||||||
|
visitor::walk_excepthandler(self, excepthandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_keyword(&mut self, keyword: &'a mut Keyword) {
|
||||||
|
keyword.trivia.retain(|c| !c.kind.is_empty_line());
|
||||||
|
visitor::walk_keyword(self, keyword);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_bool_op(&mut self, bool_op: &'a mut BoolOp) {
|
||||||
|
bool_op.trivia.retain(|c| !c.kind.is_empty_line());
|
||||||
|
visitor::walk_bool_op(self, bool_op);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_slice_index(&mut self, slice_index: &'a mut SliceIndex) {
|
||||||
|
slice_index.trivia.retain(|c| !c.kind.is_empty_line());
|
||||||
|
visitor::walk_slice_index(self, slice_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_pattern(&mut self, pattern: &'a mut Pattern) {
|
||||||
|
pattern.trivia.retain(|c| !c.kind.is_empty_line());
|
||||||
|
visitor::walk_pattern(self, pattern);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn normalize_newlines(python_cst: &mut [Stmt]) {
|
pub fn normalize_newlines(python_cst: &mut [Stmt]) {
|
||||||
|
|
|
@ -178,7 +178,7 @@ instruction()#comment with bad spacing
|
||||||
```diff
|
```diff
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
@@ -72,14 +72,20 @@
|
@@ -72,7 +72,11 @@
|
||||||
body,
|
body,
|
||||||
parameters.children[-1], # )2
|
parameters.children[-1], # )2
|
||||||
]
|
]
|
||||||
|
@ -190,21 +190,8 @@ instruction()#comment with bad spacing
|
||||||
+ ] # type: ignore
|
+ ] # type: ignore
|
||||||
if (
|
if (
|
||||||
self._proc is not None
|
self._proc is not None
|
||||||
- # has the child process finished?
|
# has the child process finished?
|
||||||
- and self._returncode is None
|
@@ -103,35 +107,35 @@
|
||||||
- # the child process has finished, but the
|
|
||||||
+ and # has the child process finished?
|
|
||||||
+ self._returncode
|
|
||||||
+ is None
|
|
||||||
+ and # the child process has finished, but the
|
|
||||||
# transport hasn't been notified yet?
|
|
||||||
- and self._proc.poll() is None
|
|
||||||
+ self._proc.poll()
|
|
||||||
+ is None
|
|
||||||
):
|
|
||||||
pass
|
|
||||||
# no newline before or after
|
|
||||||
@@ -103,35 +109,35 @@
|
|
||||||
############################################################################
|
############################################################################
|
||||||
|
|
||||||
call2(
|
call2(
|
||||||
|
@ -219,10 +206,8 @@ instruction()#comment with bad spacing
|
||||||
"""
|
"""
|
||||||
short
|
short
|
||||||
""",
|
""",
|
||||||
- # yup
|
# yup
|
||||||
- arg3=True,
|
arg3=True,
|
||||||
+ arg3=# yup
|
|
||||||
+ True,
|
|
||||||
)
|
)
|
||||||
- lcomp = [
|
- lcomp = [
|
||||||
- element for element in collection if element is not None # yup # yup # right
|
- element for element in collection if element is not None # yup # yup # right
|
||||||
|
@ -256,7 +241,7 @@ instruction()#comment with bad spacing
|
||||||
]
|
]
|
||||||
while True:
|
while True:
|
||||||
if False:
|
if False:
|
||||||
@@ -167,7 +173,7 @@
|
@@ -167,7 +171,7 @@
|
||||||
#######################
|
#######################
|
||||||
|
|
||||||
|
|
||||||
|
@ -351,13 +336,11 @@ def inline_comments_in_brackets_ruin_everything():
|
||||||
] # type: ignore
|
] # type: ignore
|
||||||
if (
|
if (
|
||||||
self._proc is not None
|
self._proc is not None
|
||||||
and # has the child process finished?
|
# has the child process finished?
|
||||||
self._returncode
|
and self._returncode is None
|
||||||
is None
|
# the child process has finished, but the
|
||||||
and # the child process has finished, but the
|
|
||||||
# transport hasn't been notified yet?
|
# transport hasn't been notified yet?
|
||||||
self._proc.poll()
|
and self._proc.poll() is None
|
||||||
is None
|
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
# no newline before or after
|
# no newline before or after
|
||||||
|
@ -389,8 +372,8 @@ short
|
||||||
"""
|
"""
|
||||||
short
|
short
|
||||||
""",
|
""",
|
||||||
arg3=# yup
|
# yup
|
||||||
True,
|
arg3=True,
|
||||||
)
|
)
|
||||||
lcomp = [element for element in collection if element is not None] # yup # yup # right
|
lcomp = [element for element in collection if element is not None] # yup # yup # right
|
||||||
lcomp2 = [
|
lcomp2 = [
|
||||||
|
|
|
@ -77,30 +77,6 @@ def func():
|
||||||
]
|
]
|
||||||
# Capture each of the exceptions in the MultiError along with each of their causes and contexts
|
# Capture each of the exceptions in the MultiError along with each of their causes and contexts
|
||||||
if isinstance(exc_value, MultiError):
|
if isinstance(exc_value, MultiError):
|
||||||
@@ -26,9 +27,9 @@
|
|
||||||
limit=limit,
|
|
||||||
lookup_lines=lookup_lines,
|
|
||||||
capture_locals=capture_locals,
|
|
||||||
- # copy the set of _seen exceptions so that duplicates
|
|
||||||
+ _seen=# copy the set of _seen exceptions so that duplicates
|
|
||||||
# shared between sub-exceptions are not omitted
|
|
||||||
- _seen=set(_seen),
|
|
||||||
+ set(_seen),
|
|
||||||
)
|
|
||||||
# This should be left alone (after)
|
|
||||||
)
|
|
||||||
@@ -39,9 +40,9 @@
|
|
||||||
limit=limit,
|
|
||||||
lookup_lines=lookup_lines,
|
|
||||||
capture_locals=capture_locals,
|
|
||||||
- # copy the set of _seen exceptions so that duplicates
|
|
||||||
+ _seen=# copy the set of _seen exceptions so that duplicates
|
|
||||||
# shared between sub-exceptions are not omitted
|
|
||||||
- _seen=set(_seen),
|
|
||||||
+ set(_seen),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Ruff Output
|
## Ruff Output
|
||||||
|
@ -135,9 +111,9 @@ def func():
|
||||||
limit=limit,
|
limit=limit,
|
||||||
lookup_lines=lookup_lines,
|
lookup_lines=lookup_lines,
|
||||||
capture_locals=capture_locals,
|
capture_locals=capture_locals,
|
||||||
_seen=# copy the set of _seen exceptions so that duplicates
|
# copy the set of _seen exceptions so that duplicates
|
||||||
# shared between sub-exceptions are not omitted
|
# shared between sub-exceptions are not omitted
|
||||||
set(_seen),
|
_seen=set(_seen),
|
||||||
)
|
)
|
||||||
# This should be left alone (after)
|
# This should be left alone (after)
|
||||||
)
|
)
|
||||||
|
@ -148,9 +124,9 @@ def func():
|
||||||
limit=limit,
|
limit=limit,
|
||||||
lookup_lines=lookup_lines,
|
lookup_lines=lookup_lines,
|
||||||
capture_locals=capture_locals,
|
capture_locals=capture_locals,
|
||||||
_seen=# copy the set of _seen exceptions so that duplicates
|
# copy the set of _seen exceptions so that duplicates
|
||||||
# shared between sub-exceptions are not omitted
|
# shared between sub-exceptions are not omitted
|
||||||
set(_seen),
|
_seen=set(_seen),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -204,15 +204,9 @@ class C:
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
unstyle(str(report)),
|
unstyle(str(report)),
|
||||||
@@ -22,133 +23,155 @@
|
@@ -25,11 +26,8 @@
|
||||||
if (
|
# Rule 2
|
||||||
# Rule 1
|
and i % 3 == 0
|
||||||
i % 2 == 0
|
|
||||||
- # Rule 2
|
|
||||||
- and i % 3 == 0
|
|
||||||
+ and # Rule 2
|
|
||||||
+ i % 3
|
|
||||||
+ == 0
|
|
||||||
):
|
):
|
||||||
- while (
|
- while (
|
||||||
- # Just a comment
|
- # Just a comment
|
||||||
|
@ -224,13 +218,9 @@ class C:
|
||||||
print(i)
|
print(i)
|
||||||
xxxxxxxxxxxxxxxx = Yyyy2YyyyyYyyyyy(
|
xxxxxxxxxxxxxxxx = Yyyy2YyyyyYyyyyy(
|
||||||
push_manager=context.request.resource_manager,
|
push_manager=context.request.resource_manager,
|
||||||
max_items_to_push=num_items,
|
@@ -39,116 +37,140 @@
|
||||||
batch_size=Yyyy2YyyyYyyyyYyyy.FULL_SIZE,
|
# Only send the first n items.
|
||||||
).push(
|
items=items[:num_items]
|
||||||
- # Only send the first n items.
|
|
||||||
- items=items[:num_items]
|
|
||||||
+ items=# Only send the first n items.
|
|
||||||
+ items[:num_items]
|
|
||||||
)
|
)
|
||||||
- return (
|
- return (
|
||||||
- 'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s'
|
- 'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s'
|
||||||
|
@ -460,7 +450,7 @@ class C:
|
||||||
"Not what we expected and the message is too long to fit in one line"
|
"Not what we expected and the message is too long to fit in one line"
|
||||||
" because it's too long"
|
" because it's too long"
|
||||||
)
|
)
|
||||||
@@ -161,9 +184,8 @@
|
@@ -161,9 +183,8 @@
|
||||||
8 STORE_ATTR 0 (x)
|
8 STORE_ATTR 0 (x)
|
||||||
10 LOAD_CONST 0 (None)
|
10 LOAD_CONST 0 (None)
|
||||||
12 RETURN_VALUE
|
12 RETURN_VALUE
|
||||||
|
@ -502,9 +492,8 @@ class C:
|
||||||
if (
|
if (
|
||||||
# Rule 1
|
# Rule 1
|
||||||
i % 2 == 0
|
i % 2 == 0
|
||||||
and # Rule 2
|
# Rule 2
|
||||||
i % 3
|
and i % 3 == 0
|
||||||
== 0
|
|
||||||
):
|
):
|
||||||
while # Just a comment
|
while # Just a comment
|
||||||
call():
|
call():
|
||||||
|
@ -514,8 +503,8 @@ class C:
|
||||||
max_items_to_push=num_items,
|
max_items_to_push=num_items,
|
||||||
batch_size=Yyyy2YyyyYyyyyYyyy.FULL_SIZE,
|
batch_size=Yyyy2YyyyYyyyyYyyy.FULL_SIZE,
|
||||||
).push(
|
).push(
|
||||||
items=# Only send the first n items.
|
# Only send the first n items.
|
||||||
items[:num_items]
|
items=items[:num_items]
|
||||||
)
|
)
|
||||||
return 'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s'
|
return 'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s'
|
||||||
% (test.name, test.filename, lineno, lname, err)
|
% (test.name, test.filename, lineno, lname, err)
|
||||||
|
|
|
@ -204,15 +204,9 @@ class C:
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
unstyle(str(report)),
|
unstyle(str(report)),
|
||||||
@@ -22,133 +23,155 @@
|
@@ -25,11 +26,8 @@
|
||||||
if (
|
# Rule 2
|
||||||
# Rule 1
|
and i % 3 == 0
|
||||||
i % 2 == 0
|
|
||||||
- # Rule 2
|
|
||||||
- and i % 3 == 0
|
|
||||||
+ and # Rule 2
|
|
||||||
+ i % 3
|
|
||||||
+ == 0
|
|
||||||
):
|
):
|
||||||
- while (
|
- while (
|
||||||
- # Just a comment
|
- # Just a comment
|
||||||
|
@ -224,13 +218,9 @@ class C:
|
||||||
print(i)
|
print(i)
|
||||||
xxxxxxxxxxxxxxxx = Yyyy2YyyyyYyyyyy(
|
xxxxxxxxxxxxxxxx = Yyyy2YyyyyYyyyyy(
|
||||||
push_manager=context.request.resource_manager,
|
push_manager=context.request.resource_manager,
|
||||||
max_items_to_push=num_items,
|
@@ -39,116 +37,140 @@
|
||||||
batch_size=Yyyy2YyyyYyyyyYyyy.FULL_SIZE,
|
# Only send the first n items.
|
||||||
).push(
|
items=items[:num_items]
|
||||||
- # Only send the first n items.
|
|
||||||
- items=items[:num_items]
|
|
||||||
+ items=# Only send the first n items.
|
|
||||||
+ items[:num_items]
|
|
||||||
)
|
)
|
||||||
- return (
|
- return (
|
||||||
- 'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s'
|
- 'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s'
|
||||||
|
@ -460,7 +450,7 @@ class C:
|
||||||
"Not what we expected and the message is too long to fit in one line"
|
"Not what we expected and the message is too long to fit in one line"
|
||||||
" because it's too long"
|
" because it's too long"
|
||||||
)
|
)
|
||||||
@@ -161,9 +184,8 @@
|
@@ -161,9 +183,8 @@
|
||||||
8 STORE_ATTR 0 (x)
|
8 STORE_ATTR 0 (x)
|
||||||
10 LOAD_CONST 0 (None)
|
10 LOAD_CONST 0 (None)
|
||||||
12 RETURN_VALUE
|
12 RETURN_VALUE
|
||||||
|
@ -502,9 +492,8 @@ class C:
|
||||||
if (
|
if (
|
||||||
# Rule 1
|
# Rule 1
|
||||||
i % 2 == 0
|
i % 2 == 0
|
||||||
and # Rule 2
|
# Rule 2
|
||||||
i % 3
|
and i % 3 == 0
|
||||||
== 0
|
|
||||||
):
|
):
|
||||||
while # Just a comment
|
while # Just a comment
|
||||||
call():
|
call():
|
||||||
|
@ -514,8 +503,8 @@ class C:
|
||||||
max_items_to_push=num_items,
|
max_items_to_push=num_items,
|
||||||
batch_size=Yyyy2YyyyYyyyyYyyy.FULL_SIZE,
|
batch_size=Yyyy2YyyyYyyyyYyyy.FULL_SIZE,
|
||||||
).push(
|
).push(
|
||||||
items=# Only send the first n items.
|
# Only send the first n items.
|
||||||
items[:num_items]
|
items=items[:num_items]
|
||||||
)
|
)
|
||||||
return 'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s'
|
return 'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s'
|
||||||
% (test.name, test.filename, lineno, lname, err)
|
% (test.name, test.filename, lineno, lname, err)
|
||||||
|
|
|
@ -394,25 +394,8 @@ d={'a':1,
|
||||||
# fmt: on
|
# fmt: on
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -200,8 +213,8 @@
|
@@ -217,8 +230,7 @@
|
||||||
xxxxxx_xxxxxx=2,
|
xxxxxxxxxx_xxxxxxxxxxx_xxxxxxx_xxxxxxxxx=5,
|
||||||
xxxxxx_xxxxx_xxxxxxxx=70,
|
|
||||||
xxxxxx_xxxxxx_xxxxx=True,
|
|
||||||
- # fmt: off
|
|
||||||
- xxxxxxx_xxxxxxxxxxxx={
|
|
||||||
+ xxxxxxx_xxxxxxxxxxxx=# fmt: off
|
|
||||||
+ {
|
|
||||||
"xxxxxxxx": {
|
|
||||||
"xxxxxx": False,
|
|
||||||
"xxxxxxx": False,
|
|
||||||
@@ -213,12 +226,11 @@
|
|
||||||
"xxxx_xxxxxx": "xxxxxx",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
- # fmt: on
|
|
||||||
- xxxxxxxxxx_xxxxxxxxxxx_xxxxxxx_xxxxxxxxx=5,
|
|
||||||
+ xxxxxxxxxx_xxxxxxxxxxx_xxxxxxx_xxxxxxxxx=# fmt: on
|
|
||||||
+ 5,
|
|
||||||
)
|
)
|
||||||
# fmt: off
|
# fmt: off
|
||||||
-yield 'hello'
|
-yield 'hello'
|
||||||
|
@ -643,8 +626,8 @@ cfg.rule(
|
||||||
xxxxxx_xxxxxx=2,
|
xxxxxx_xxxxxx=2,
|
||||||
xxxxxx_xxxxx_xxxxxxxx=70,
|
xxxxxx_xxxxx_xxxxxxxx=70,
|
||||||
xxxxxx_xxxxxx_xxxxx=True,
|
xxxxxx_xxxxxx_xxxxx=True,
|
||||||
xxxxxxx_xxxxxxxxxxxx=# fmt: off
|
# fmt: off
|
||||||
{
|
xxxxxxx_xxxxxxxxxxxx={
|
||||||
"xxxxxxxx": {
|
"xxxxxxxx": {
|
||||||
"xxxxxx": False,
|
"xxxxxx": False,
|
||||||
"xxxxxxx": False,
|
"xxxxxxx": False,
|
||||||
|
@ -656,8 +639,8 @@ cfg.rule(
|
||||||
"xxxx_xxxxxx": "xxxxxx",
|
"xxxx_xxxxxx": "xxxxxx",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
xxxxxxxxxx_xxxxxxxxxxx_xxxxxxx_xxxxxxxxx=# fmt: on
|
# fmt: on
|
||||||
5,
|
xxxxxxxxxx_xxxxxxxxxxx_xxxxxxx_xxxxxxxxx=5,
|
||||||
)
|
)
|
||||||
# fmt: off
|
# fmt: off
|
||||||
yield "hello"
|
yield "hello"
|
||||||
|
|
|
@ -5,35 +5,39 @@ use rustpython_parser::Tok;
|
||||||
|
|
||||||
use crate::core::types::Range;
|
use crate::core::types::Range;
|
||||||
use crate::cst::{
|
use crate::cst::{
|
||||||
Alias, Arg, Body, Excepthandler, ExcepthandlerKind, Expr, ExprKind, Pattern, PatternKind,
|
Alias, Arg, Body, BoolOp, Excepthandler, ExcepthandlerKind, Expr, ExprKind, Keyword, Pattern,
|
||||||
SliceIndex, SliceIndexKind, Stmt, StmtKind,
|
PatternKind, SliceIndex, SliceIndexKind, Stmt, StmtKind,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Node<'a> {
|
pub enum Node<'a> {
|
||||||
Mod(&'a [Stmt]),
|
|
||||||
Body(&'a Body),
|
|
||||||
Stmt(&'a Stmt),
|
|
||||||
Expr(&'a Expr),
|
|
||||||
Alias(&'a Alias),
|
Alias(&'a Alias),
|
||||||
Arg(&'a Arg),
|
Arg(&'a Arg),
|
||||||
|
Body(&'a Body),
|
||||||
|
BoolOp(&'a BoolOp),
|
||||||
Excepthandler(&'a Excepthandler),
|
Excepthandler(&'a Excepthandler),
|
||||||
SliceIndex(&'a SliceIndex),
|
Expr(&'a Expr),
|
||||||
|
Keyword(&'a Keyword),
|
||||||
|
Mod(&'a [Stmt]),
|
||||||
Pattern(&'a Pattern),
|
Pattern(&'a Pattern),
|
||||||
|
SliceIndex(&'a SliceIndex),
|
||||||
|
Stmt(&'a Stmt),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node<'_> {
|
impl Node<'_> {
|
||||||
pub fn id(&self) -> usize {
|
pub fn id(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
Node::Mod(nodes) => nodes as *const _ as usize,
|
|
||||||
Node::Body(node) => node.id(),
|
|
||||||
Node::Stmt(node) => node.id(),
|
|
||||||
Node::Expr(node) => node.id(),
|
|
||||||
Node::Alias(node) => node.id(),
|
Node::Alias(node) => node.id(),
|
||||||
Node::Arg(node) => node.id(),
|
Node::Arg(node) => node.id(),
|
||||||
|
Node::Body(node) => node.id(),
|
||||||
|
Node::BoolOp(node) => node.id(),
|
||||||
Node::Excepthandler(node) => node.id(),
|
Node::Excepthandler(node) => node.id(),
|
||||||
Node::SliceIndex(node) => node.id(),
|
Node::Expr(node) => node.id(),
|
||||||
|
Node::Keyword(node) => node.id(),
|
||||||
|
Node::Mod(nodes) => nodes as *const _ as usize,
|
||||||
Node::Pattern(node) => node.id(),
|
Node::Pattern(node) => node.id(),
|
||||||
|
Node::SliceIndex(node) => node.id(),
|
||||||
|
Node::Stmt(node) => node.id(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,6 +240,7 @@ fn sorted_child_nodes_inner<'a>(node: &Node<'a>, result: &mut Vec<Node<'a>>) {
|
||||||
result.push(Node::Stmt(stmt));
|
result.push(Node::Stmt(stmt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Node::BoolOp(..) => {}
|
||||||
Node::Stmt(stmt) => match &stmt.node {
|
Node::Stmt(stmt) => match &stmt.node {
|
||||||
StmtKind::Return { value } => {
|
StmtKind::Return { value } => {
|
||||||
if let Some(value) = value {
|
if let Some(value) = value {
|
||||||
|
@ -309,7 +314,7 @@ fn sorted_child_nodes_inner<'a>(node: &Node<'a>, result: &mut Vec<Node<'a>>) {
|
||||||
result.push(Node::Expr(base));
|
result.push(Node::Expr(base));
|
||||||
}
|
}
|
||||||
for keyword in keywords {
|
for keyword in keywords {
|
||||||
result.push(Node::Expr(&keyword.node.value));
|
result.push(Node::Keyword(keyword));
|
||||||
}
|
}
|
||||||
result.push(Node::Body(body));
|
result.push(Node::Body(body));
|
||||||
}
|
}
|
||||||
|
@ -448,8 +453,10 @@ fn sorted_child_nodes_inner<'a>(node: &Node<'a>, result: &mut Vec<Node<'a>>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Node::Expr(expr) => match &expr.node {
|
Node::Expr(expr) => match &expr.node {
|
||||||
ExprKind::BoolOp { values, .. } => {
|
ExprKind::BoolOp { ops, values } => {
|
||||||
for value in values {
|
result.push(Node::Expr(&values[0]));
|
||||||
|
for (op, value) in ops.iter().zip(&values[1..]) {
|
||||||
|
result.push(Node::BoolOp(op));
|
||||||
result.push(Node::Expr(value));
|
result.push(Node::Expr(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -565,7 +572,7 @@ fn sorted_child_nodes_inner<'a>(node: &Node<'a>, result: &mut Vec<Node<'a>>) {
|
||||||
result.push(Node::Expr(arg));
|
result.push(Node::Expr(arg));
|
||||||
}
|
}
|
||||||
for keyword in keywords {
|
for keyword in keywords {
|
||||||
result.push(Node::Expr(&keyword.node.value));
|
result.push(Node::Keyword(keyword));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::FormattedValue {
|
ExprKind::FormattedValue {
|
||||||
|
@ -612,6 +619,9 @@ fn sorted_child_nodes_inner<'a>(node: &Node<'a>, result: &mut Vec<Node<'a>>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Node::Keyword(keyword) => {
|
||||||
|
result.push(Node::Expr(&keyword.node.value));
|
||||||
|
}
|
||||||
Node::Alias(..) => {}
|
Node::Alias(..) => {}
|
||||||
Node::Excepthandler(excepthandler) => {
|
Node::Excepthandler(excepthandler) => {
|
||||||
let ExcepthandlerKind::ExceptHandler { type_, body, .. } = &excepthandler.node;
|
let ExcepthandlerKind::ExceptHandler { type_, body, .. } = &excepthandler.node;
|
||||||
|
@ -703,52 +713,60 @@ pub fn decorate_token<'a>(
|
||||||
let middle = (left + right) / 2;
|
let middle = (left + right) / 2;
|
||||||
let child = &child_nodes[middle];
|
let child = &child_nodes[middle];
|
||||||
let start = match &child {
|
let start = match &child {
|
||||||
Node::Body(node) => node.location,
|
|
||||||
Node::Stmt(node) => node.location,
|
|
||||||
Node::Expr(node) => node.location,
|
|
||||||
Node::Alias(node) => node.location,
|
Node::Alias(node) => node.location,
|
||||||
Node::Arg(node) => node.location,
|
Node::Arg(node) => node.location,
|
||||||
|
Node::Body(node) => node.location,
|
||||||
|
Node::BoolOp(node) => node.location,
|
||||||
Node::Excepthandler(node) => node.location,
|
Node::Excepthandler(node) => node.location,
|
||||||
Node::SliceIndex(node) => node.location,
|
Node::Expr(node) => node.location,
|
||||||
Node::Pattern(node) => node.location,
|
Node::Keyword(node) => node.location,
|
||||||
Node::Mod(..) => unreachable!("Node::Mod cannot be a child node"),
|
Node::Mod(..) => unreachable!("Node::Mod cannot be a child node"),
|
||||||
|
Node::Pattern(node) => node.location,
|
||||||
|
Node::SliceIndex(node) => node.location,
|
||||||
|
Node::Stmt(node) => node.location,
|
||||||
};
|
};
|
||||||
let end = match &child {
|
let end = match &child {
|
||||||
Node::Body(node) => node.end_location.unwrap(),
|
|
||||||
Node::Stmt(node) => node.end_location.unwrap(),
|
|
||||||
Node::Expr(node) => node.end_location.unwrap(),
|
|
||||||
Node::Alias(node) => node.end_location.unwrap(),
|
Node::Alias(node) => node.end_location.unwrap(),
|
||||||
Node::Arg(node) => node.end_location.unwrap(),
|
Node::Arg(node) => node.end_location.unwrap(),
|
||||||
|
Node::Body(node) => node.end_location.unwrap(),
|
||||||
|
Node::BoolOp(node) => node.end_location.unwrap(),
|
||||||
Node::Excepthandler(node) => node.end_location.unwrap(),
|
Node::Excepthandler(node) => node.end_location.unwrap(),
|
||||||
Node::SliceIndex(node) => node.end_location.unwrap(),
|
Node::Expr(node) => node.end_location.unwrap(),
|
||||||
Node::Pattern(node) => node.end_location.unwrap(),
|
Node::Keyword(node) => node.end_location.unwrap(),
|
||||||
Node::Mod(..) => unreachable!("Node::Mod cannot be a child node"),
|
Node::Mod(..) => unreachable!("Node::Mod cannot be a child node"),
|
||||||
|
Node::Pattern(node) => node.end_location.unwrap(),
|
||||||
|
Node::SliceIndex(node) => node.end_location.unwrap(),
|
||||||
|
Node::Stmt(node) => node.end_location.unwrap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(existing) = &enclosed_node {
|
if let Some(existing) = &enclosed_node {
|
||||||
// Special-case: if we're dealing with a statement that's a single expression,
|
// Special-case: if we're dealing with a statement that's a single expression,
|
||||||
// we want to treat the expression as the enclosed node.
|
// we want to treat the expression as the enclosed node.
|
||||||
let existing_start = match &existing {
|
let existing_start = match &existing {
|
||||||
Node::Body(node) => node.location,
|
|
||||||
Node::Stmt(node) => node.location,
|
|
||||||
Node::Expr(node) => node.location,
|
|
||||||
Node::Alias(node) => node.location,
|
Node::Alias(node) => node.location,
|
||||||
Node::Arg(node) => node.location,
|
Node::Arg(node) => node.location,
|
||||||
|
Node::Body(node) => node.location,
|
||||||
|
Node::BoolOp(node) => node.location,
|
||||||
Node::Excepthandler(node) => node.location,
|
Node::Excepthandler(node) => node.location,
|
||||||
Node::SliceIndex(node) => node.location,
|
Node::Expr(node) => node.location,
|
||||||
Node::Pattern(node) => node.location,
|
Node::Keyword(node) => node.location,
|
||||||
Node::Mod(..) => unreachable!("Node::Mod cannot be a child node"),
|
Node::Mod(..) => unreachable!("Node::Mod cannot be a child node"),
|
||||||
|
Node::Pattern(node) => node.location,
|
||||||
|
Node::SliceIndex(node) => node.location,
|
||||||
|
Node::Stmt(node) => node.location,
|
||||||
};
|
};
|
||||||
let existing_end = match &existing {
|
let existing_end = match &existing {
|
||||||
Node::Body(node) => node.end_location.unwrap(),
|
|
||||||
Node::Stmt(node) => node.end_location.unwrap(),
|
|
||||||
Node::Expr(node) => node.end_location.unwrap(),
|
|
||||||
Node::Alias(node) => node.end_location.unwrap(),
|
Node::Alias(node) => node.end_location.unwrap(),
|
||||||
Node::Arg(node) => node.end_location.unwrap(),
|
Node::Arg(node) => node.end_location.unwrap(),
|
||||||
|
Node::Body(node) => node.end_location.unwrap(),
|
||||||
|
Node::BoolOp(node) => node.end_location.unwrap(),
|
||||||
Node::Excepthandler(node) => node.end_location.unwrap(),
|
Node::Excepthandler(node) => node.end_location.unwrap(),
|
||||||
Node::SliceIndex(node) => node.end_location.unwrap(),
|
Node::Expr(node) => node.end_location.unwrap(),
|
||||||
Node::Pattern(node) => node.end_location.unwrap(),
|
Node::Keyword(node) => node.end_location.unwrap(),
|
||||||
Node::Mod(..) => unreachable!("Node::Mod cannot be a child node"),
|
Node::Mod(..) => unreachable!("Node::Mod cannot be a child node"),
|
||||||
|
Node::Pattern(node) => node.end_location.unwrap(),
|
||||||
|
Node::SliceIndex(node) => node.end_location.unwrap(),
|
||||||
|
Node::Stmt(node) => node.end_location.unwrap(),
|
||||||
};
|
};
|
||||||
if start == existing_start && end == existing_end {
|
if start == existing_start && end == existing_end {
|
||||||
enclosed_node = Some(child.clone());
|
enclosed_node = Some(child.clone());
|
||||||
|
@ -803,40 +821,20 @@ pub fn decorate_token<'a>(
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct TriviaIndex {
|
pub struct TriviaIndex {
|
||||||
pub body: FxHashMap<usize, Vec<Trivia>>,
|
|
||||||
pub stmt: FxHashMap<usize, Vec<Trivia>>,
|
|
||||||
pub expr: FxHashMap<usize, Vec<Trivia>>,
|
|
||||||
pub alias: FxHashMap<usize, Vec<Trivia>>,
|
pub alias: FxHashMap<usize, Vec<Trivia>>,
|
||||||
pub arg: FxHashMap<usize, Vec<Trivia>>,
|
pub arg: FxHashMap<usize, Vec<Trivia>>,
|
||||||
|
pub body: FxHashMap<usize, Vec<Trivia>>,
|
||||||
|
pub bool_op: FxHashMap<usize, Vec<Trivia>>,
|
||||||
pub excepthandler: FxHashMap<usize, Vec<Trivia>>,
|
pub excepthandler: FxHashMap<usize, Vec<Trivia>>,
|
||||||
pub slice_index: FxHashMap<usize, Vec<Trivia>>,
|
pub expr: FxHashMap<usize, Vec<Trivia>>,
|
||||||
|
pub keyword: FxHashMap<usize, Vec<Trivia>>,
|
||||||
pub pattern: FxHashMap<usize, Vec<Trivia>>,
|
pub pattern: FxHashMap<usize, Vec<Trivia>>,
|
||||||
|
pub slice_index: FxHashMap<usize, Vec<Trivia>>,
|
||||||
|
pub stmt: FxHashMap<usize, Vec<Trivia>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_comment(comment: Trivia, node: &Node, trivia: &mut TriviaIndex) {
|
fn add_comment(comment: Trivia, node: &Node, trivia: &mut TriviaIndex) {
|
||||||
match node {
|
match node {
|
||||||
Node::Mod(_) => {}
|
|
||||||
Node::Body(node) => {
|
|
||||||
trivia
|
|
||||||
.body
|
|
||||||
.entry(node.id())
|
|
||||||
.or_insert_with(Vec::new)
|
|
||||||
.push(comment);
|
|
||||||
}
|
|
||||||
Node::Stmt(node) => {
|
|
||||||
trivia
|
|
||||||
.stmt
|
|
||||||
.entry(node.id())
|
|
||||||
.or_insert_with(Vec::new)
|
|
||||||
.push(comment);
|
|
||||||
}
|
|
||||||
Node::Expr(node) => {
|
|
||||||
trivia
|
|
||||||
.expr
|
|
||||||
.entry(node.id())
|
|
||||||
.or_insert_with(Vec::new)
|
|
||||||
.push(comment);
|
|
||||||
}
|
|
||||||
Node::Alias(node) => {
|
Node::Alias(node) => {
|
||||||
trivia
|
trivia
|
||||||
.alias
|
.alias
|
||||||
|
@ -851,6 +849,20 @@ fn add_comment(comment: Trivia, node: &Node, trivia: &mut TriviaIndex) {
|
||||||
.or_insert_with(Vec::new)
|
.or_insert_with(Vec::new)
|
||||||
.push(comment);
|
.push(comment);
|
||||||
}
|
}
|
||||||
|
Node::Body(node) => {
|
||||||
|
trivia
|
||||||
|
.body
|
||||||
|
.entry(node.id())
|
||||||
|
.or_insert_with(Vec::new)
|
||||||
|
.push(comment);
|
||||||
|
}
|
||||||
|
Node::BoolOp(node) => {
|
||||||
|
trivia
|
||||||
|
.bool_op
|
||||||
|
.entry(node.id())
|
||||||
|
.or_insert_with(Vec::new)
|
||||||
|
.push(comment);
|
||||||
|
}
|
||||||
Node::Excepthandler(node) => {
|
Node::Excepthandler(node) => {
|
||||||
trivia
|
trivia
|
||||||
.excepthandler
|
.excepthandler
|
||||||
|
@ -858,9 +870,16 @@ fn add_comment(comment: Trivia, node: &Node, trivia: &mut TriviaIndex) {
|
||||||
.or_insert_with(Vec::new)
|
.or_insert_with(Vec::new)
|
||||||
.push(comment);
|
.push(comment);
|
||||||
}
|
}
|
||||||
Node::SliceIndex(node) => {
|
Node::Expr(node) => {
|
||||||
trivia
|
trivia
|
||||||
.slice_index
|
.expr
|
||||||
|
.entry(node.id())
|
||||||
|
.or_insert_with(Vec::new)
|
||||||
|
.push(comment);
|
||||||
|
}
|
||||||
|
Node::Keyword(node) => {
|
||||||
|
trivia
|
||||||
|
.keyword
|
||||||
.entry(node.id())
|
.entry(node.id())
|
||||||
.or_insert_with(Vec::new)
|
.or_insert_with(Vec::new)
|
||||||
.push(comment);
|
.push(comment);
|
||||||
|
@ -872,6 +891,21 @@ fn add_comment(comment: Trivia, node: &Node, trivia: &mut TriviaIndex) {
|
||||||
.or_insert_with(Vec::new)
|
.or_insert_with(Vec::new)
|
||||||
.push(comment);
|
.push(comment);
|
||||||
}
|
}
|
||||||
|
Node::SliceIndex(node) => {
|
||||||
|
trivia
|
||||||
|
.slice_index
|
||||||
|
.entry(node.id())
|
||||||
|
.or_insert_with(Vec::new)
|
||||||
|
.push(comment);
|
||||||
|
}
|
||||||
|
Node::Stmt(node) => {
|
||||||
|
trivia
|
||||||
|
.stmt
|
||||||
|
.entry(node.id())
|
||||||
|
.or_insert_with(Vec::new)
|
||||||
|
.push(comment);
|
||||||
|
}
|
||||||
|
Node::Mod(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue