rust-lang / rustfmt

Format Rust code
https://rust-lang.github.io/rustfmt/
Apache License 2.0
6.04k stars 889 forks source link

Bad line wrapping inside blocks passed as marco arguments #1468

Closed hsivonen closed 7 years ago

hsivonen commented 7 years ago

The indent of long code lines inside a block that's passed as a marco argument occasionally becomes a dedent.

Steps to reproduce (using rustfmt 0.8.3):

git clone https://github.com/hsivonen/encoding_rs
cd encoding_rs
git checkout afac5e3d9a59ae1b6bc972a3c0673cf15676dfb9
cargo fmt
less src/big5.rs
less src/euc_jp.rs

Actual results:

From line 182 in big5.rs

    ascii_compatible_encoder_functions!({
                                            // For simplicity, unified ideographs
                                            // in the pointer range 11206...11212 are handled
                                            // as Level 1 Hanzi.
                                            if let Some((lead, trail)) =
            big5_level1_hanzi_encode(bmp) {
                                                handle.write_two(lead, trail)
                                            } else {
                                                let pointer = if let Some(pointer) =
                big5_box_encode(bmp) {
                                                    pointer
                                                } else if let Some(pointer) =
                big5_other_encode(bmp) {
                pointer
            } else {
                return (EncoderResult::unmappable_from_bmp(bmp),
                        source.consumed(),
                        handle.written());
            };

From line 71 in euc_jp.rs:

    euc_jp_decoder_functions!({
                                  let trail_minus_offset = byte.wrapping_sub(0xA1);
                                  // Fast-track Hiragana (60% according to Lunde)
                                  // and Katakana (10% acconding to Lunde).
                                  if jis0208_lead_minus_offset == 0x03 &&
                                     trail_minus_offset < 0x53 {
                                      // Hiragana
                                      handle.write_upper_bmp(0x3041 + trail_minus_offset as u16)
                                  } else if jis0208_lead_minus_offset == 0x04 &&
                  trail_minus_offset < 0x56 {
            // Katakana
            handle.write_upper_bmp(0x30A1 + trail_minus_offset as u16)
        } else if trail_minus_offset > (0xFE - 0xA1) {
            if byte < 0x80 {
                return (DecoderResult::Malformed(1, 0),
                        unread_handle_trail.unread(),
                        handle.written());
            }
            return (DecoderResult::Malformed(2, 0),
                    unread_handle_trail.consumed(),
                    handle.written());
        } else {

Expected results:

Expected the wrapped part of a long line not to start to the left of the start of the line that got wrapped.

To make lines less likely to reach the wrapping limit, expected the indent of blocks passed as macro arguments not to depend on the length of the macro name.

topecongiro commented 7 years ago

For a workaround, you could add fn_call_style = "block" in rustfmt.toml.

hsivonen commented 7 years ago

For a workaround, you could add fn_call_style = "block" in rustfmt.toml.

Thank you. This workaround works.

However, the referenced pull request, without the configuration change, didn't fix this.

topecongiro commented 7 years ago

@hsivonen Thanks for your comment!

1522 fixes the last else block being unindented.

As far as I know, block ({...}) being visually indented is by design. Please take a look at the following example:

fn foo() {
    euc_jp_decoder_functions!({
                                  x
                              },
                              y,
                              z);
}