Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option to prefer (force?) consistency in match statements [guidance for impl is ❤️] #3176

Closed
kestred opened this issue Nov 6, 2018 · 1 comment
Assignees
Labels
feature-request only-with-option requires a non-default option value to reproduce

Comments

@kestred
Copy link
Contributor

kestred commented Nov 6, 2018

I'm hoping one of the more experienced rustfmt contributors might point me in a good architectural direction (or discuss the feasibly, if likely difficult) for an implementation of an option that does the following.

Suppose an unformatted rust snippet:

match (dberr.schema.as_ref(), dberr.table.as_ref()) {
    (Some(schema), None) =>
        message.push_str(&format!(" with schema `{}`", schema)),
    (Some(schema), Some(table)) =>
        message.push_str(&format!(" with table `{}.{}`", schema, table)), // this line is too long
    (None, Some(table)) =>
        message.push_str(&format!(" with table `{}`", table)),

    _ => return Err(()),
}

Rustfmt currently formats this as the following (a pretty ok format):

// NOTE: One line was too long
match (dberr.schema.as_ref(), dberr.table.as_ref()) {
    (Some(schema), None) => message.push_str(&format!(" with schema `{}`", schema)),
    (Some(schema), Some(table)) => {
        message.push_str(&format!(" with table `{}.{}`", schema, table))
    }
    (None, Some(table)) => message.push_str(&format!(" with table `{}`", table)),

    _ => return Err(()),
}

The option I'd like to add would be to force that match branches use either _ => $expr, or _ => $block consistently within a single match statement. As a (more difficult to implement?) but likely better extension, only match branches not separated by a blank line would be forced to be consistent; e.g.

Formatting with proposed option:

// NOTE: All of the expressions stay vertically aligned
match (dberr.schema.as_ref(), dberr.table.as_ref()) {
    (Some(schema), None) => {
        message.push_str(&format!(" with schema `{}`", schema))
    }
    (Some(schema), Some(table)) => {
        message.push_str(&format!(" with table `{}.{}`", schema, table))
    }
    (None, Some(table)) => {
        message.push_str(&format!(" with table `{}`", table))
    }

    _ => return Err(()),
}

Prefer vs Force (Added in edit)

Mostly a note to self?

This option could prefer consistency (rather than force it) by only forcing consistency
if all blocks contain exactly one expression (~ or overflow to at most 1 line?). I'll see if its also fairly simple to add both with an enum option rather than a boolean (probably Off, Prefer, and Force).

@nrc nrc added only-with-option requires a non-default option value to reproduce feature-request labels Nov 9, 2018
@nrc
Copy link
Member

nrc commented Nov 9, 2018

This would be fairly easy to implement, but I don't think there is much hope of having a nice implementation.

Basically, when formatting each match arm you would need some extra mutable state in the context (which might mean needing more flexibility in the Rewrite trait) so you can set a flag if any arm is formatted using a block. Then if any arm sets that flag, you start over forcing every arm to use a block. You could try looking at the output of formatting an arm and force a block if any arm includes a newline, however, whether that would work depends on the precise behaviour you want around newlines in the pattern, comments, etc.

If you implemented this and it didn't have too much overhead, then I think it would be a fine option to support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request only-with-option requires a non-default option value to reproduce
Projects
None yet
Development

No branches or pull requests

3 participants