diff --git a/crates/ruff_python_formatter/src/format/expr.rs b/crates/ruff_python_formatter/src/format/expr.rs index abe717d902..7ac9c3460c 100644 --- a/crates/ruff_python_formatter/src/format/expr.rs +++ b/crates/ruff_python_formatter/src/format/expr.rs @@ -13,6 +13,7 @@ use crate::cst::{ Arguments, Boolop, Cmpop, Comprehension, Expr, ExprKind, Keyword, Operator, Unaryop, }; use crate::format::helpers::{is_self_closing, is_simple_power, is_simple_slice}; +use crate::format::numbers::int_literal; use crate::format::strings::string_literal; use crate::shared_traits::AsFormat; use crate::trivia::{Parenthesize, Relationship, TriviaKind}; @@ -652,6 +653,7 @@ fn format_constant( write!(f, [text("False")])?; } } + Constant::Int(_) => write!(f, [int_literal(Range::from_located(expr))])?, Constant::Str(_) | Constant::Bytes(_) => write!(f, [string_literal(expr)])?, _ => write!(f, [literal(Range::from_located(expr))])?, } diff --git a/crates/ruff_python_formatter/src/format/mod.rs b/crates/ruff_python_formatter/src/format/mod.rs index 5dae9fd406..3032b5a9b3 100644 --- a/crates/ruff_python_formatter/src/format/mod.rs +++ b/crates/ruff_python_formatter/src/format/mod.rs @@ -8,6 +8,7 @@ mod comprehension; mod excepthandler; mod expr; mod helpers; +mod numbers; mod operator; mod stmt; mod strings; diff --git a/crates/ruff_python_formatter/src/format/numbers.rs b/crates/ruff_python_formatter/src/format/numbers.rs new file mode 100644 index 0000000000..f24a2171cc --- /dev/null +++ b/crates/ruff_python_formatter/src/format/numbers.rs @@ -0,0 +1,53 @@ +use ruff_formatter::prelude::*; +use ruff_formatter::{write, Format}; +use ruff_text_size::TextSize; + +use crate::builders::literal; +use crate::context::ASTFormatContext; +use crate::core::types::Range; + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct IntLiteral { + range: Range, +} + +impl Format> for IntLiteral { + fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + let (source, start, end) = f.context().locator().slice(self.range); + + for prefix in ["0b", "0B", "0o", "0O", "0x", "0X"] { + if source[start..end].starts_with(prefix) { + // In each case, the prefix must be lowercase, while the suffix must be uppercase. + let prefix = &source[start..start + prefix.len()]; + let suffix = &source[start + prefix.len()..end]; + + if prefix.bytes().any(|b| b.is_ascii_uppercase()) + || suffix.bytes().any(|b| b.is_ascii_lowercase()) + { + // Write out the fixed version. + write!( + f, + [ + dynamic_text(&prefix.to_lowercase(), TextSize::default()), + dynamic_text(&suffix.to_uppercase(), TextSize::default()) + ] + )?; + } else { + // Use the existing source. + write!(f, [literal(self.range)])?; + } + + return Ok(()); + } + } + + write!(f, [literal(self.range)])?; + + Ok(()) + } +} + +#[inline] +pub const fn int_literal(range: Range) -> IntLiteral { + IntLiteral { range } +} diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__attribute_access_on_number_literals_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__attribute_access_on_number_literals_py.snap index b16631a1c1..7d3fbd4397 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__attribute_access_on_number_literals_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__attribute_access_on_number_literals_py.snap @@ -48,11 +48,6 @@ y = 100(no) -x = (123456789e123456789).conjugate() -x = 123456789j.real -x = 123456789.123456789j.__add__(0b1011.bit_length()) --x = 0xB1ACC.conjugate() --x = 0b1011.conjugate() --x = 0o777.real --x = (0.000000006).hex() --x = -100.0000j +x = .1.is_integer() +x = 1..imag +x = 1E+1.imag @@ -62,9 +57,11 @@ y = 100(no) +x = 123456789E123456789.conjugate() +x = 123456789J.real +x = 123456789.123456789J.__add__(0b1011.bit_length()) -+x = 0XB1ACC.conjugate() -+x = 0B1011.conjugate() -+x = 0O777.real + x = 0xB1ACC.conjugate() + x = 0b1011.conjugate() + x = 0o777.real +-x = (0.000000006).hex() +-x = -100.0000j +x = 0.000000006.hex() +x = -100.0000J @@ -91,9 +88,9 @@ x = 123456789.123456789E123456789.real x = 123456789E123456789.conjugate() x = 123456789J.real x = 123456789.123456789J.__add__(0b1011.bit_length()) -x = 0XB1ACC.conjugate() -x = 0B1011.conjugate() -x = 0O777.real +x = 0xB1ACC.conjugate() +x = 0b1011.conjugate() +x = 0o777.real x = 0.000000006.hex() x = -100.0000J