rust-lang/rustfmt

Newlines between commented code in call chains get removed

Closed this issue · 2 comments

fn main() {
  let el = EventLoop::builder()
    .with_msg_hook(|msg| {
      let msg = msg as *const MSG;

      if unsafe { (*msg).message == WM_NCCALCSIZE && (*msg).wParam.0 == 1 } {
        return true;
      }

      false
    })
    .build()
    .unwrap();
}

Using vscode I comment out the following to test something quickly, and save

fn main() {
  let el = EventLoop::builder()
    // .with_msg_hook(|msg| {
    //   let msg = msg as *const MSG;

    //   if unsafe { (*msg).message == WM_NCCALCSIZE && (*msg).wParam.0 == 1 } {
    //     return true;
    //   }

    //   false
    // })
    .build()
    .unwrap();
}

Rustfmt produces the following output

fn main() {
  let el = EventLoop::builder()
    // .with_msg_hook(|msg| {
    //   let msg = msg as *const MSG;
    //   if unsafe { (*msg).message == WM_NCCALCSIZE && (*msg).wParam.0 == 1 } {
    //     return true;
    //   }
    //   false
    // })
    .build()
    .unwrap();
}

I finish testing.
The commented code is still highlighted and I need to Ctrl-Z 2 times and save again to get my original, clear, code.

I would expect 2+(incl.) newlines to get reduced to 1, but single ones should be kept.
Commented section does not necessarily need to be code.

$rustfmt --version
rustfmt 1.7.1-stable (f6e511e 2024-10-15)

I think this is caused in the following part.

let pre_comment_snippet = trim_tries(context.snippet(pre_comment_span));

rustfmt intentionally trims the try operator and then removes the resulting blank line (the try operator is checked elsewhere and reattached later). However, it appears that it mistakenly removes the blank line even when there isn’t a try operator. —just my guess, though.

rustfmt/src/chains.rs

Lines 1015 to 1038 in 777e25a

/// Removes try operators (`?`s) that appear in the given string. If removing
/// them leaves an empty line, remove that line as well unless it is the first
/// line (we need the first newline for detecting pre/post comment).
fn trim_tries(s: &str) -> String {
let mut result = String::with_capacity(s.len());
let mut line_buffer = String::with_capacity(s.len());
for (kind, rich_char) in CharClasses::new(s.chars()) {
match rich_char.get_char() {
'\n' => {
if result.is_empty() || !line_buffer.trim().is_empty() {
result.push_str(&line_buffer);
result.push('\n')
}
line_buffer.clear();
}
'?' if kind == FullCodeCharKind::Normal => continue,
c => line_buffer.push(c),
}
}
if !line_buffer.trim().is_empty() {
result.push_str(&line_buffer);
}
result
}

Just now realizing that this is a duplicate of #4012