Preserve blank line between `match` inner attrs and first arm
Open
@ding-young is already working on this.
Since Mar 18, 2024.
A-matches
A-whitespace
C-enhancement
X-requires-next-style-edition
- Dominant language
- Rust
- Stars
- 7k
- Forks
- 1.1k
- Avg merge
- 2d 13h
- Merged PRs (30d)
- 24
Description
Example real-world code, which I have manually formatted exactly as I would want; this is the input and desired output:
#![feature(non_exhaustive_omitted_patterns_lint)]
use syn::*;
pub fn attrs_mut(e: &mut Expr) -> Option<&mut Vec<Attribute>> {
match e {
#![deny(non_exhaustive_omitted_patterns)]
Expr::Array(ExprArray { attrs, .. })
| Expr::Assign(ExprAssign { attrs, .. })
| Expr::Async(ExprAsync { attrs, .. })
| Expr::Await(ExprAwait { attrs, .. })
| Expr::Binary(ExprBinary { attrs, .. })
| Expr::Block(ExprBlock { attrs, .. })
| Expr::Break(ExprBreak { attrs, .. })
| Expr::Call(ExprCall { attrs, .. })
| Expr::Cast(ExprCast { attrs, .. })
| Expr::Closure(ExprClosure { attrs, .. })
| Expr::Const(ExprConst { attrs, .. })
| Expr::Continue(ExprContinue { attrs, .. })
| Expr::Field(ExprField { attrs, .. })
| Expr::ForLoop(ExprForLoop { attrs, .. })
| Expr::Group(ExprGroup { attrs, .. })
| Expr::If(ExprIf { attrs, .. })
| Expr::Index(ExprIndex { attrs, .. })
| Expr::Infer(ExprInfer { attrs, .. })
| Expr::Let(ExprLet { attrs, .. })
| Expr::Lit(ExprLit { attrs, .. })
| Expr::Loop(ExprLoop { attrs, .. })
| Expr::Macro(ExprMacro { attrs, .. })
| Expr::Match(ExprMatch { attrs, .. })
| Expr::MethodCall(ExprMethodCall { attrs, .. })
| Expr::Paren(ExprParen { attrs, .. })
| Expr::Path(ExprPath { attrs, .. })
| Expr::Range(ExprRange { attrs, .. })
| Expr::Reference(ExprReference { attrs, .. })
| Expr::Repeat(ExprRepeat { attrs, .. })
| Expr::Return(ExprReturn { attrs, .. })
| Expr::Struct(ExprStruct { attrs, .. })
| Expr::Try(ExprTry { attrs, .. })
| Expr::TryBlock(ExprTryBlock { attrs, .. })
| Expr::Tuple(ExprTuple { attrs, .. })
| Expr::Unary(ExprUnary { attrs, .. })
| Expr::Unsafe(ExprUnsafe { attrs, .. })
| Expr::While(ExprWhile { attrs, .. })
| Expr::Yield(ExprYield { attrs, .. }) => Some(attrs),
Expr::Verbatim(_) => None,
_ => None,
}
}
But, rustfmt applies the following diff, which is undesirable.
pub fn attrs_mut(e: &mut Expr) -> Option<&mut Vec<Attribute>> {
match e {
#![deny(non_exhaustive_omitted_patterns)]
-
Expr::Array(ExprArray { attrs, .. })
| Expr::Assign(ExprAssign { attrs, .. })
| Expr::Async(ExprAsync { attrs, .. })
Rustfmt's formatting makes it look as though the inner attr is an outer attr on the first arm.
pub fn attrs_mut(e: &mut Expr) -> Option<&mut Vec<Attribute>> {
match e {
#![deny(non_exhaustive_omitted_patterns)]
Expr::Array(ExprArray { attrs, .. })
| Expr::Assign(ExprAssign { attrs, .. })
| Expr::Async(ExprAsync { attrs, .. })
Module-level inner attrs, like the #![feature(...)] above, are not affected. If rustfmt were removing blank line between module-level inner attrs and the first item, I think it's obvious that would be considered undesirable:
#![feature(non_exhaustive_omitted_patterns_lint)]
use syn::*;
pub fn attrs_mut(e: &mut Expr) -> Option<&mut Vec<Attribute>> {
match e {...}
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.