Skip to content

Commit

Permalink
More tests for float_literal_trailing_zero option and other small fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
amatveiakin committed Feb 27, 2024
1 parent 6d2380b commit 3d3b398
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 22 deletions.
12 changes: 9 additions & 3 deletions Configurations.md
Original file line number Diff line number Diff line change
Expand Up @@ -1268,13 +1268,19 @@ Control the presence of trailing zero in floating-point literal values

Leave the literal as-is.

```rust
fn main() {
let values = [1.0, 2., 3.0e10, 4f32];
}
```

#### `Always`:

Add a trailing zero to the literal:

```rust
fn main() {
let values = [1.0, 2.0e10, 3.0f32];
let values = [1.0, 2.0, 3.0e10, 4.0f32];
}
```

Expand All @@ -1285,7 +1291,7 @@ and the preceding period are removed:

```rust
fn main() {
let values = [1.0, 2e10, 3f32];
let values = [1.0, 2.0, 3e10, 4f32];
}
```

Expand All @@ -1296,7 +1302,7 @@ period is also removed:

```rust
fn main() {
let values = [1., 2e10, 3f32];
let values = [1., 2., 3e10, 4f32];
}
```

Expand Down
100 changes: 82 additions & 18 deletions src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,6 @@ use crate::utils::{
use crate::vertical::rewrite_with_alignment;
use crate::visitor::FmtVisitor;

lazy_static! {
// This regex may accept invalid float literals (such as `1`, `_` or `2.e3`). That's ok.
// We only use it to parse literals whose validity has already been established.
static ref FLOAT_LITERAL: Regex =
Regex::new(r"^([0-9_]+)(?:\.([0-9_]+)?)?([eE][+-]?[0-9_]+)?$").unwrap();
static ref ZERO_LITERAL: Regex = Regex::new(r"^[0_]+$").unwrap();
}

impl Rewrite for ast::Expr {
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
format_expr(self, ExprType::SubExpression, context, shape)
Expand Down Expand Up @@ -1295,13 +1287,13 @@ fn rewrite_int_lit(
span: Span,
shape: Shape,
) -> Option<String> {
let symbol = token_lit.symbol.as_str();
let suffix = token_lit.suffix.as_ref().map(|s| s.as_str());

if suffix == Some("f32") || suffix == Some("f64") {
if token_lit.is_semantic_float() {
return rewrite_float_lit(context, token_lit, span, shape);
}

let symbol = token_lit.symbol.as_str();
let suffix = token_lit.suffix.as_ref().map(|s| s.as_str());

if let Some(symbol_stripped) = symbol.strip_prefix("0x") {
let hex_lit = match context.config.hex_literal_case() {
HexLiteralCase::Preserve => None,
Expand Down Expand Up @@ -1344,13 +1336,14 @@ fn rewrite_float_lit(
let symbol = token_lit.symbol.as_str();
let suffix = token_lit.suffix.as_ref().map(|s| s.as_str());

let caps = FLOAT_LITERAL.captures(symbol).unwrap();
let integer_part = caps.get(1).unwrap().as_str();
let fractional_part = caps.get(2).map(|s| s.as_str());
let exponent = caps.get(3).map(|s| s.as_str());
let FloatSymbolParts {
integer_part,
fractional_part,
exponent,
} = parse_float_symbol(symbol);

let has_postfix = exponent.is_some() || suffix.is_some();
let fractional_part_nonzero = fractional_part.map_or(false, |s| !ZERO_LITERAL.is_match(s));
let fractional_part_nonzero = fractional_part.map_or(false, |s| !is_zero_integer_literal(s));

let (include_period, include_fractional_part) =
match context.config.float_literal_trailing_zero() {
Expand Down Expand Up @@ -2291,9 +2284,39 @@ pub(crate) fn is_method_call(expr: &ast::Expr) -> bool {
}
}

struct FloatSymbolParts<'a> {
integer_part: &'a str,
fractional_part: Option<&'a str>,
exponent: Option<&'a str>,
}

// Parses a float literal. The `symbol` must be a valid floating point literal without a type
// suffix. Otherwise the function may panic or return wrong result.
fn parse_float_symbol(symbol: &str) -> FloatSymbolParts<'_> {
lazy_static! {
// This regex may accept invalid float literals (such as `1`, `_` or `2.e3`). That's ok.
// We only use it to parse literals whose validity has already been established.
static ref FLOAT_LITERAL: Regex =
Regex::new(r"^([0-9_]+)(?:\.([0-9_]+)?)?([eE][+-]?[0-9_]+)?$").unwrap();
}
let caps = FLOAT_LITERAL.captures(symbol).unwrap();
FloatSymbolParts {
integer_part: caps.get(1).unwrap().as_str(),
fractional_part: caps.get(2).map(|m| m.as_str()),
exponent: caps.get(3).map(|m| m.as_str()),
}
}

fn is_zero_integer_literal(symbol: &str) -> bool {
lazy_static! {
static ref ZERO_LITERAL: Regex = Regex::new(r"^[0_]+$").unwrap();
}
ZERO_LITERAL.is_match(symbol)
}

#[cfg(test)]
mod test {
use super::last_line_offsetted;
use super::*;

#[test]
fn test_last_line_offsetted() {
Expand All @@ -2315,4 +2338,45 @@ mod test {
let lines = "one\n two three";
assert_eq!(last_line_offsetted(2, lines), false);
}

#[test]
fn test_parse_float_symbol() {
let parts = parse_float_symbol("123.456e789");
assert_eq!(parts.integer_part, "123");
assert_eq!(parts.fractional_part, Some("456"));
assert_eq!(parts.exponent, Some("e789"));

let parts = parse_float_symbol("123e789");
assert_eq!(parts.integer_part, "123");
assert_eq!(parts.fractional_part, None);
assert_eq!(parts.exponent, Some("e789"));

let parts = parse_float_symbol("123.");
assert_eq!(parts.integer_part, "123");
assert_eq!(parts.fractional_part, None);
assert_eq!(parts.exponent, None);
}

#[test]
fn test_parse_float_symbol_with_underscores() {
let parts = parse_float_symbol("_123._456e_789");
assert_eq!(parts.integer_part, "_123");
assert_eq!(parts.fractional_part, Some("_456"));
assert_eq!(parts.exponent, Some("e_789"));

let parts = parse_float_symbol("123_.456_e789_");
assert_eq!(parts.integer_part, "123_");
assert_eq!(parts.fractional_part, Some("456_"));
assert_eq!(parts.exponent, Some("e789_"));

let parts = parse_float_symbol("1_23.4_56e7_89");
assert_eq!(parts.integer_part, "1_23");
assert_eq!(parts.fractional_part, Some("4_56"));
assert_eq!(parts.exponent, Some("e7_89"));

let parts = parse_float_symbol("_1_23_._4_56_e_7_89_");
assert_eq!(parts.integer_part, "_1_23_");
assert_eq!(parts.fractional_part, Some("_4_56_"));
assert_eq!(parts.exponent, Some("e_7_89_"));
}
}
24 changes: 24 additions & 0 deletions tests/source/configs/float_literal_trailing_zero/always.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// rustfmt-float_literal_trailing_zero: Always

fn float_literals() {
let a = 0.;
let b = 0.0;
let c = 100.;
let d = 100.0;
let e = 5e3;
let f = 5.0e3;
let g = 7f32;
let h = 7.0f32;
let i = 9e3f32;
let j = 9.0e3f32;
let k = 1000.00;
let l = 1_000_.;
let m = 1_000_.000_000;
}

fn line_wrapping() {
let array = [
1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18.,
];
println!("This is floaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaat {}", 10e3);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,13 @@ fn float_literals() {
let l = 1_000_.;
let m = 1_000_.000_000;
}

fn line_wrapping() {
let array = [
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11., 12., 13., 14., 15., 16., 17., 18.,
];
println!(
"This is floaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaat {}",
10.0e3
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,14 @@ fn float_literals() {
let l = 1_000_.;
let m = 1_000_.000_000;
}

fn line_wrapping() {
let array = [
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0,
17.0, 18.0,
];
println!(
"This is floaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaat {}",
10.0e3
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,14 @@ fn float_literals() {
let l = 1_000_.0;
let m = 1_000_.000_000;
}

fn line_wrapping() {
let array = [
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0,
17.0, 18.0,
];
println!(
"This is floaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaat {}",
10.0e3
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,11 @@ fn float_literals() {
let l = 1_000_.0;
let m = 1_000_.000_000;
}

fn line_wrapping() {
let array = [
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0,
17.0, 18.0,
];
println!("This is floaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaat {}", 10e3);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,10 @@ fn float_literals() {
let l = 1_000_.;
let m = 1_000_.;
}

fn line_wrapping() {
let array = [
1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18.,
];
println!("This is floaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaat {}", 10e3);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// rustfmt-float_literal_trailing_zero: Always
// rustfmt-float_literal_trailing_zero: Preserve

fn float_literals() {
let a = 0.;
Expand Down

0 comments on commit 3d3b398

Please sign in to comment.