Merge pull request #1765 from topecongiro/v-alignment/struct-field

Add vertical alignment option for struct fields
This commit is contained in:
Nick Cameron 2017-07-05 12:11:52 +12:00 committed by GitHub
commit 734de8b2b7
16 changed files with 1431 additions and 233 deletions

View File

@ -1209,6 +1209,33 @@ fn lorem<T: Eq>(t: T) {
See also: [`space_before_bound`](#space_before_bound).
## `struct_field_align_threshold`
The maximum diff of width between struct fields to be aligned with each other.
- **Default value** : 0
- **Possible values**: any positive integer
#### `0`:
```rust
struct Foo {
x: u32,
yy: u32,
zzz: u32,
}
```
#### `20`:
```rust
struct Foo {
x: u32,
yy: u32,
zzz: u32,
}
```
## `space_after_struct_lit_field_colon`
Leave a space after the colon in a struct literal field

View File

@ -598,7 +598,9 @@ create_config! {
"What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage";
condense_wildcard_suffixes: bool, false, "Replace strings of _ wildcards by a single .. in \
tuple patterns";
combine_control_expr: bool, true, "Combine control expressions with funciton calls."
combine_control_expr: bool, true, "Combine control expressions with funciton calls.";
struct_field_align_threshold: usize, 0, "Align struct fields if their diffs fits within \
threshold."
}
#[cfg(test)]

View File

@ -30,6 +30,7 @@ use items::{span_lo_for_arg, span_hi_for_arg};
use chains::rewrite_chain;
use macros::{rewrite_macro, MacroPosition};
use patterns::{TuplePatField, can_be_overflowed_pat};
use vertical::rewrite_with_alignment;
use syntax::{ast, ptr};
use syntax::codemap::{CodeMap, Span, BytePos};
@ -2551,6 +2552,14 @@ fn rewrite_index(
}
}
fn struct_lit_can_be_aligned(fields: &[ast::Field], base: &Option<&ast::Expr>) -> bool {
if base.is_some() {
return false;
}
fields.iter().all(|field| !field.is_shorthand)
}
fn rewrite_struct_lit<'a>(
context: &RewriteContext,
path: &ast::Path,
@ -2580,76 +2589,100 @@ fn rewrite_struct_lit<'a>(
return Some(format!("{} {{}}", path_str));
}
let field_iter = fields
.into_iter()
.map(StructLitField::Regular)
.chain(base.into_iter().map(StructLitField::Base));
// Foo { a: Foo } - indent is +3, width is -5.
let (h_shape, v_shape) = try_opt!(struct_lit_shape(shape, context, path_str.len() + 3, 2));
let span_lo = |item: &StructLitField| match *item {
StructLitField::Regular(field) => field.span.lo,
StructLitField::Base(expr) => {
let last_field_hi = fields.last().map_or(span.lo, |field| field.span.hi);
let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo));
let pos = snippet.find_uncommented("..").unwrap();
last_field_hi + BytePos(pos as u32)
}
};
let span_hi = |item: &StructLitField| match *item {
StructLitField::Regular(field) => field.span.hi,
StructLitField::Base(expr) => expr.span.hi,
};
let rewrite = |item: &StructLitField| match *item {
StructLitField::Regular(field) => {
// The 1 taken from the v_budget is for the comma.
rewrite_field(context, field, try_opt!(v_shape.sub_width(1)))
}
StructLitField::Base(expr) => {
// 2 = ..
expr.rewrite(context, try_opt!(v_shape.shrink_left(2)))
.map(|s| format!("..{}", s))
}
let one_line_width = h_shape.map_or(0, |shape| shape.width);
let body_lo = context.codemap.span_after(span, "{");
let fields_str = if struct_lit_can_be_aligned(fields, &base) &&
context.config.struct_field_align_threshold() > 0
{
try_opt!(rewrite_with_alignment(
fields,
context,
shape,
mk_sp(body_lo, span.hi),
one_line_width,
))
} else {
let field_iter = fields
.into_iter()
.map(StructLitField::Regular)
.chain(base.into_iter().map(StructLitField::Base));
let span_lo = |item: &StructLitField| match *item {
StructLitField::Regular(field) => field.span().lo,
StructLitField::Base(expr) => {
let last_field_hi = fields.last().map_or(span.lo, |field| field.span.hi);
let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo));
let pos = snippet.find_uncommented("..").unwrap();
last_field_hi + BytePos(pos as u32)
}
};
let span_hi = |item: &StructLitField| match *item {
StructLitField::Regular(field) => field.span().hi,
StructLitField::Base(expr) => expr.span.hi,
};
let rewrite = |item: &StructLitField| match *item {
StructLitField::Regular(field) => {
// The 1 taken from the v_budget is for the comma.
rewrite_field(context, field, try_opt!(v_shape.sub_width(1)), 0)
}
StructLitField::Base(expr) => {
// 2 = ..
expr.rewrite(context, try_opt!(v_shape.shrink_left(2)))
.map(|s| format!("..{}", s))
}
};
let items = itemize_list(
context.codemap,
field_iter,
"}",
span_lo,
span_hi,
rewrite,
body_lo,
span.hi,
);
let item_vec = items.collect::<Vec<_>>();
let tactic = struct_lit_tactic(h_shape, context, &item_vec);
let nested_shape = shape_for_tactic(tactic, h_shape, v_shape);
let fmt = struct_lit_formatting(nested_shape, tactic, context, base.is_some());
try_opt!(write_list(&item_vec, &fmt))
};
let items = itemize_list(
context.codemap,
field_iter,
"}",
span_lo,
span_hi,
rewrite,
context.codemap.span_after(span, "{"),
span.hi,
);
let item_vec = items.collect::<Vec<_>>();
let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width);
Some(format!("{} {{{}}}", path_str, fields_str))
let tactic = struct_lit_tactic(h_shape, context, &item_vec);
let nested_shape = shape_for_tactic(tactic, h_shape, v_shape);
let fmt = struct_lit_formatting(nested_shape, tactic, context, base.is_some());
// FIXME if context.config.struct_lit_style() == Visual, but we run out
// of space, we should fall back to BlockIndent.
}
let fields_str = try_opt!(write_list(&item_vec, &fmt));
let fields_str = if context.config.struct_lit_style() == IndentStyle::Block &&
pub fn wrap_struct_field(
context: &RewriteContext,
fields_str: &str,
shape: Shape,
nested_shape: Shape,
one_line_width: usize,
) -> String {
if context.config.struct_lit_style() == IndentStyle::Block &&
(fields_str.contains('\n') ||
context.config.struct_lit_multiline_style() == MultilineStyle::ForceMulti ||
fields_str.len() > h_shape.map(|s| s.width).unwrap_or(0))
fields_str.len() > one_line_width)
{
format!(
"\n{}{}\n{}",
v_shape.indent.to_string(context.config),
nested_shape.indent.to_string(context.config),
fields_str,
shape.indent.to_string(context.config)
)
} else {
// One liner or visual indent.
format!(" {} ", fields_str)
};
Some(format!("{} {{{}}}", path_str, fields_str))
// FIXME if context.config.struct_lit_style() == Visual, but we run out
// of space, we should fall back to BlockIndent.
}
}
pub fn struct_lit_field_separator(config: &Config) -> &str {
@ -2659,18 +2692,32 @@ pub fn struct_lit_field_separator(config: &Config) -> &str {
)
}
fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) -> Option<String> {
pub fn rewrite_field(
context: &RewriteContext,
field: &ast::Field,
shape: Shape,
prefix_max_width: usize,
) -> Option<String> {
if contains_skip(&field.attrs) {
return wrap_str(
context.snippet(field.span()),
context.config.max_width(),
shape,
);
}
let name = &field.ident.node.to_string();
if field.is_shorthand {
Some(name.to_string())
} else {
let separator = struct_lit_field_separator(context.config);
let mut separator = String::from(struct_lit_field_separator(context.config));
for _ in 0..prefix_max_width.checked_sub(name.len()).unwrap_or(0) {
separator.push(' ');
}
let overhead = name.len() + separator.len();
let mut expr_shape = try_opt!(shape.sub_width(overhead));
expr_shape.offset += overhead;
let expr_shape = try_opt!(shape.offset_left(overhead));
let expr = field.expr.rewrite(context, expr_shape);
let mut attrs_str = try_opt!((*field.attrs).rewrite(context, shape));
let mut attrs_str = try_opt!(field.attrs.rewrite(context, shape));
if !attrs_str.is_empty() {
attrs_str.push_str(&format!("\n{}", shape.indent.to_string(context.config)));
};

View File

@ -23,6 +23,7 @@ use visitor::FmtVisitor;
use rewrite::{Rewrite, RewriteContext};
use config::{Config, IndentStyle, Density, ReturnIndent, BraceStyle, Style};
use types::join_bounds;
use vertical::rewrite_with_alignment;
use syntax::{ast, abi, ptr, symbol};
use syntax::codemap::{Span, BytePos};
@ -1100,49 +1101,14 @@ fn format_struct_struct(
return Some(result);
}
let item_indent = offset.block_indent(context.config);
// 1 = ","
let item_budget = try_opt!(
context
.config
.max_width()
.checked_sub(item_indent.width() + 1)
);
let items_str = try_opt!(rewrite_with_alignment(
fields,
context,
Shape::indented(offset, context.config),
mk_sp(body_lo, span.hi),
one_line_width.unwrap_or(0),
));
let items = itemize_list(
context.codemap,
fields.iter(),
"}",
|field| {
// Include attributes and doc comments, if present
if !field.attrs.is_empty() {
field.attrs[0].span.lo
} else {
field.span.lo
}
},
|field| field.ty.span.hi,
|field| field.rewrite(context, Shape::legacy(item_budget, item_indent)),
context.codemap.span_after(span, "{"),
span.hi,
).collect::<Vec<_>>();
// 1 = ,
let budget = context.config.max_width() - offset.width() + context.config.tab_spaces() - 1;
let tactic = match one_line_width {
Some(w) => definitive_tactic(&items, ListTactic::LimitedHorizontalVertical(w), budget),
None => DefinitiveListTactic::Vertical,
};
let fmt = ListFormatting {
tactic: tactic,
separator: ",",
trailing_separator: context.config.trailing_comma(),
shape: Shape::legacy(budget, item_indent),
ends_with_newline: true,
config: context.config,
};
let items_str = try_opt!(write_list(&items, &fmt));
if one_line_width.is_some() && !items_str.contains('\n') {
Some(format!("{} {} }}", result, items_str))
} else {
@ -1257,7 +1223,9 @@ fn format_tuple_struct(
}
},
|field| field.ty.span.hi,
|field| field.rewrite(context, Shape::legacy(item_budget, item_indent)),
|field| {
rewrite_struct_field(context, field, Shape::legacy(item_budget, item_indent), 0)
},
context.codemap.span_after(span, "("),
span.hi,
);
@ -1430,96 +1398,124 @@ fn rewrite_missing_comment_on_field(
}
}
impl Rewrite for ast::StructField {
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
if contains_skip(&self.attrs) {
let span = context.snippet(mk_sp(self.attrs[0].span.lo, self.span.hi));
return wrap_str(span, context.config.max_width(), shape);
}
let name = self.ident;
let vis = format_visibility(&self.vis);
let mut attr_str = try_opt!(
self.attrs
.rewrite(context, Shape::indented(shape.indent, context.config))
);
// Try format missing comments after attributes
let missing_comment = if !self.attrs.is_empty() {
rewrite_missing_comment_on_field(
context,
shape,
self.attrs[self.attrs.len() - 1].span.hi,
self.span.lo,
&mut attr_str,
).unwrap_or(String::new())
} else {
String::new()
};
let type_annotation_spacing = type_annotation_spacing(context.config);
let mut result = match name {
Some(name) => {
format!(
"{}{}{}{}{}:",
attr_str,
missing_comment,
vis,
name,
type_annotation_spacing.0
)
}
None => format!("{}{}{}", attr_str, missing_comment, vis),
};
let type_offset = shape.indent.block_indent(context.config);
let rewrite_type_in_next_line = || {
self.ty
.rewrite(context, Shape::indented(type_offset, context.config))
};
let last_line_width = last_line_width(&result) + type_annotation_spacing.1.len();
let budget = try_opt!(shape.width.checked_sub(last_line_width));
let ty_rewritten = self.ty.rewrite(
pub fn rewrite_struct_field_prefix(
context: &RewriteContext,
field: &ast::StructField,
shape: Shape,
) -> Option<String> {
let vis = format_visibility(&field.vis);
let mut attr_str = try_opt!(
field
.attrs
.rewrite(context, Shape::indented(shape.indent, context.config))
);
// Try format missing comments after attributes
let missing_comment = if !field.attrs.is_empty() {
rewrite_missing_comment_on_field(
context,
Shape::legacy(budget, shape.indent + last_line_width),
);
match ty_rewritten {
Some(ref ty) if ty.contains('\n') => {
let new_ty = rewrite_type_in_next_line();
match new_ty {
Some(ref new_ty)
if !new_ty.contains('\n') &&
new_ty.len() + type_offset.width() <= context.config.max_width() => {
Some(format!(
"{}\n{}{}",
result,
type_offset.to_string(&context.config),
&new_ty
))
}
_ => {
if name.is_some() {
result.push_str(type_annotation_spacing.1);
}
Some(result + &ty)
}
shape,
field.attrs[field.attrs.len() - 1].span.hi,
field.span.lo,
&mut attr_str,
).unwrap_or(String::new())
} else {
String::new()
};
let type_annotation_spacing = type_annotation_spacing(context.config);
Some(match field.ident {
Some(name) => {
format!(
"{}{}{}{}{}:",
attr_str,
missing_comment,
vis,
name,
type_annotation_spacing.0
)
}
None => format!("{}{}{}", attr_str, missing_comment, vis),
})
}
fn rewrite_struct_field_type(
context: &RewriteContext,
last_line_width: usize,
field: &ast::StructField,
spacing: &str,
shape: Shape,
) -> Option<String> {
let ty_shape = try_opt!(shape.offset_left(last_line_width + spacing.len()));
field
.ty
.rewrite(context, ty_shape)
.map(|ty| format!("{}{}", spacing, ty))
}
pub fn rewrite_struct_field(
context: &RewriteContext,
field: &ast::StructField,
shape: Shape,
lhs_max_width: usize,
) -> Option<String> {
if contains_skip(&field.attrs) {
let span = context.snippet(mk_sp(field.attrs[0].span.lo, field.span.hi));
return wrap_str(span, context.config.max_width(), shape);
}
let type_annotation_spacing = type_annotation_spacing(context.config);
let prefix = try_opt!(rewrite_struct_field_prefix(context, field, shape));
// Try to put everything on a single line.
let last_line_width = last_line_width(&prefix);
let mut spacing = String::from(if field.ident.is_some() {
type_annotation_spacing.1
} else {
""
});
let lhs_offset = lhs_max_width.checked_sub(last_line_width).unwrap_or(0);
for _ in 0..lhs_offset {
spacing.push(' ');
}
let ty_rewritten = rewrite_struct_field_type(context, last_line_width, field, &spacing, shape);
if let Some(ref ty) = ty_rewritten {
if !ty.contains('\n') {
return Some(prefix + &ty);
}
}
// We must use multiline.
let type_offset = shape.indent.block_indent(context.config);
let rewrite_type_in_next_line = || {
field
.ty
.rewrite(context, Shape::indented(type_offset, context.config))
};
match ty_rewritten {
// If we start from the next line and type fits in a single line, then do so.
Some(ref ty) => {
match rewrite_type_in_next_line() {
Some(ref new_ty) if !new_ty.contains('\n') => {
Some(format!(
"{}\n{}{}",
prefix,
type_offset.to_string(&context.config),
&new_ty
))
}
_ => Some(prefix + &ty),
}
Some(ty) => {
if name.is_some() {
result.push_str(type_annotation_spacing.1);
}
Some(result + &ty)
}
None => {
let ty = try_opt!(rewrite_type_in_next_line());
Some(format!(
"{}\n{}{}",
result,
type_offset.to_string(&context.config),
&ty
))
}
}
_ => {
let ty = try_opt!(rewrite_type_in_next_line());
Some(format!(
"{}\n{}{}",
prefix,
type_offset.to_string(&context.config),
&ty
))
}
}
}

View File

@ -48,6 +48,7 @@ use filemap::FileMap;
use visitor::FmtVisitor;
use config::Config;
use checkstyle::{output_header, output_footer};
use utils::mk_sp;
pub use self::summary::Summary;
@ -75,6 +76,7 @@ mod chains;
mod macros;
mod patterns;
mod summary;
mod vertical;
const MIN_STRING: usize = 10;
// When we get scoped annotations, we should have rustfmt::skip.
@ -112,6 +114,28 @@ impl Spanned for ast::Arg {
}
}
impl Spanned for ast::StructField {
fn span(&self) -> Span {
if self.attrs.is_empty() {
mk_sp(self.span.lo, self.ty.span.hi)
} else {
// Include attributes and doc comments, if present
mk_sp(self.attrs[0].span.lo, self.ty.span.hi)
}
}
}
impl Spanned for ast::Field {
fn span(&self) -> Span {
let lo = if self.attrs.is_empty() {
self.span.lo
} else {
self.attrs[0].span.lo
};
mk_sp(lo, self.span.hi)
}
}
#[derive(Copy, Clone, Debug)]
pub struct Indent {
// Width of the block indent, in characters. Must be a multiple of
@ -398,7 +422,9 @@ pub struct FormatReport {
impl FormatReport {
fn new() -> FormatReport {
FormatReport { file_error_map: HashMap::new() }
FormatReport {
file_error_map: HashMap::new(),
}
}
pub fn warning_count(&self) -> usize {

View File

@ -555,8 +555,13 @@ pub fn struct_lit_shape(
}
}
};
let h_shape = shape.sub_width(prefix_width + suffix_width);
Some((h_shape, v_shape))
let shape_width = shape.width.checked_sub(prefix_width + suffix_width);
if let Some(w) = shape_width {
let shape_width = cmp::min(w, context.config.struct_lit_width());
Some((Some(Shape::legacy(shape_width, shape.indent)), v_shape))
} else {
Some((None, v_shape))
}
}
// Compute the tactic for the internals of a struct-lit-like thing.
@ -566,16 +571,10 @@ pub fn struct_lit_tactic(
items: &[ListItem],
) -> DefinitiveListTactic {
if let Some(h_shape) = h_shape {
let mut prelim_tactic = match (context.config.struct_lit_style(), items.len()) {
let prelim_tactic = match (context.config.struct_lit_style(), items.len()) {
(IndentStyle::Visual, 1) => ListTactic::HorizontalVertical,
_ => context.config.struct_lit_multiline_style().to_list_tactic(),
};
if prelim_tactic == ListTactic::HorizontalVertical && items.len() > 1 {
prelim_tactic =
ListTactic::LimitedHorizontalVertical(context.config.struct_lit_width());
}
definitive_tactic(items, prelim_tactic, h_shape.width)
} else {
DefinitiveListTactic::Vertical

View File

@ -10,12 +10,12 @@
use Shape;
use codemap::SpanUtils;
use config::{IndentStyle, MultilineStyle};
use rewrite::{Rewrite, RewriteContext};
use utils::{wrap_str, format_mutability, mk_sp};
use lists::{DefinitiveListTactic, SeparatorTactic, itemize_list, struct_lit_shape,
struct_lit_tactic, shape_for_tactic, struct_lit_formatting, write_list};
use expr::{rewrite_call_inner, rewrite_unary_prefix, rewrite_pair, can_be_overflowed_expr};
use expr::{rewrite_call_inner, rewrite_unary_prefix, rewrite_pair, can_be_overflowed_expr,
wrap_struct_field};
use types::{rewrite_path, PathContext};
use super::Spanned;
use comment::FindUncommented;
@ -181,9 +181,10 @@ fn rewrite_struct_pat(
let fmt = struct_lit_formatting(nested_shape, tactic, context, false);
let mut fields_str = try_opt!(write_list(&item_vec, &fmt));
let one_line_width = h_shape.map_or(0, |shape| shape.width);
if elipses {
if fields_str.contains('\n') {
if fields_str.contains('\n') || fields_str.len() > one_line_width {
// Add a missing trailing comma.
if fmt.trailing_separator == SeparatorTactic::Never {
fields_str.push_str(",");
@ -205,23 +206,7 @@ fn rewrite_struct_pat(
}
}
let fields_str = if context.config.struct_lit_style() == IndentStyle::Block &&
(fields_str.contains('\n') ||
context.config.struct_lit_multiline_style() == MultilineStyle::ForceMulti ||
fields_str.len() > h_shape.map(|s| s.width).unwrap_or(0))
{
format!(
"\n{}{}\n{}",
v_shape.indent.to_string(context.config),
fields_str,
shape.indent.to_string(context.config)
)
} else {
// One liner or visual indent.
format!(" {} ", fields_str)
};
let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width);
Some(format!("{} {{{}}}", path_str, fields_str))
}

271
src/vertical.rs Normal file
View File

@ -0,0 +1,271 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Format with vertical alignment.
use std::cmp;
use {Indent, Shape, Spanned};
use codemap::SpanUtils;
use comment::contains_comment;
use expr::rewrite_field;
use items::{rewrite_struct_field, rewrite_struct_field_prefix};
use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTactic};
use rewrite::{Rewrite, RewriteContext};
use utils::{contains_skip, mk_sp};
use syntax::ast;
use syntax::codemap::{Span, BytePos};
pub trait AlignedItem {
fn skip(&self) -> bool;
fn get_span(&self) -> Span;
fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option<String>;
fn rewrite_aligned_item(
&self,
context: &RewriteContext,
shape: Shape,
prefix_max_width: usize,
) -> Option<String>;
}
impl AlignedItem for ast::StructField {
fn skip(&self) -> bool {
contains_skip(&self.attrs)
}
fn get_span(&self) -> Span {
self.span()
}
fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
rewrite_struct_field_prefix(context, self, shape)
}
fn rewrite_aligned_item(
&self,
context: &RewriteContext,
shape: Shape,
prefix_max_width: usize,
) -> Option<String> {
rewrite_struct_field(context, self, shape, prefix_max_width)
}
}
impl AlignedItem for ast::Field {
fn skip(&self) -> bool {
contains_skip(&self.attrs)
}
fn get_span(&self) -> Span {
self.span()
}
fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
let mut attrs_str = try_opt!(self.attrs.rewrite(context, shape));
if !attrs_str.is_empty() {
attrs_str.push_str(&format!("\n{}", shape.indent.to_string(context.config)));
};
let name = &self.ident.node.to_string();
Some(format!("{}{}", attrs_str, name))
}
fn rewrite_aligned_item(
&self,
context: &RewriteContext,
shape: Shape,
prefix_max_width: usize,
) -> Option<String> {
rewrite_field(context, self, shape, prefix_max_width)
}
}
pub fn rewrite_with_alignment<T: AlignedItem>(
fields: &[T],
context: &RewriteContext,
shape: Shape,
span: Span,
one_line_width: usize,
) -> Option<String> {
let (spaces, group_index) = if context.config.struct_field_align_threshold() > 0 {
group_aligned_items(context, fields)
} else {
("", fields.len() - 1)
};
let init = &fields[0..group_index + 1];
let rest = &fields[group_index + 1..];
let init_last_pos = if rest.is_empty() {
span.hi
} else {
// Decide whether the missing comments should stick to init or rest.
let init_hi = init[init.len() - 1].get_span().hi;
let rest_lo = rest[0].get_span().lo;
let missing_span = mk_sp(init_hi, rest_lo);
let missing_span = mk_sp(
context.codemap.span_after(missing_span, ","),
missing_span.hi,
);
let snippet = context.snippet(missing_span);
if snippet.trim_left().starts_with("//") {
let offset = snippet.lines().next().map_or(0, |l| l.len());
// 2 = "," + "\n"
init_hi + BytePos(offset as u32 + 2)
} else if snippet.trim_left().starts_with("/*") {
let comment_lines = snippet
.lines()
.position(|line| line.trim_right().ends_with("*/"))
.unwrap_or(0);
let offset = snippet
.lines()
.take(comment_lines + 1)
.collect::<Vec<_>>()
.join("\n")
.len();
init_hi + BytePos(offset as u32 + 2)
} else {
missing_span.lo
}
};
let init_span = mk_sp(span.lo, init_last_pos);
let one_line_width = if rest.is_empty() { one_line_width } else { 0 };
let result = try_opt!(rewrite_aligned_items_inner(
context,
init,
init_span,
shape.indent,
one_line_width,
));
if rest.is_empty() {
Some(result + spaces)
} else {
let rest_span = mk_sp(init_last_pos, span.hi);
let rest_str = try_opt!(rewrite_with_alignment(
rest,
context,
shape,
rest_span,
one_line_width,
));
Some(
result + spaces + "\n" +
&shape
.indent
.block_indent(context.config)
.to_string(context.config) + &rest_str,
)
}
}
fn struct_field_preix_max_min_width<T: AlignedItem>(
context: &RewriteContext,
fields: &[T],
shape: Shape,
) -> (usize, usize) {
fields
.iter()
.map(|field| {
field.rewrite_prefix(context, shape).and_then(
|field_str| if field_str.contains('\n') {
None
} else {
Some(field_str.len())
},
)
})
.fold(Some((0, ::std::usize::MAX)), |acc, len| match (acc, len) {
(Some((max_len, min_len)), Some(len)) => {
Some((cmp::max(max_len, len), cmp::min(min_len, len)))
}
_ => None,
})
.unwrap_or((0, 0))
}
fn rewrite_aligned_items_inner<T: AlignedItem>(
context: &RewriteContext,
fields: &[T],
span: Span,
offset: Indent,
one_line_width: usize,
) -> Option<String> {
let item_indent = offset.block_indent(context.config);
// 1 = ","
let item_shape = try_opt!(Shape::indented(item_indent, context.config).sub_width(1));
let (mut field_prefix_max_width, field_prefix_min_width) =
struct_field_preix_max_min_width(context, fields, item_shape);
let max_diff = field_prefix_max_width
.checked_sub(field_prefix_min_width)
.unwrap_or(0);
if max_diff > context.config.struct_field_align_threshold() {
field_prefix_max_width = 0;
}
let items = itemize_list(
context.codemap,
fields.iter(),
"}",
|field| field.get_span().lo,
|field| field.get_span().hi,
|field| field.rewrite_aligned_item(context, item_shape, field_prefix_max_width),
span.lo,
span.hi,
).collect::<Vec<_>>();
let tactic = definitive_tactic(&items, ListTactic::HorizontalVertical, one_line_width);
let fmt = ListFormatting {
tactic: tactic,
separator: ",",
trailing_separator: context.config.trailing_comma(),
shape: item_shape,
ends_with_newline: true,
config: context.config,
};
write_list(&items, &fmt)
}
fn group_aligned_items<T: AlignedItem>(
context: &RewriteContext,
fields: &[T],
) -> (&'static str, usize) {
let mut index = 0;
for i in 0..fields.len() - 1 {
if fields[i].skip() {
return ("", index);
}
// See if there are comments or empty lines between fields.
let span = mk_sp(fields[i].get_span().hi, fields[i + 1].get_span().lo);
let snippet = context
.snippet(span)
.lines()
.skip(1)
.collect::<Vec<_>>()
.join("\n");
let spacings = if snippet
.lines()
.rev()
.skip(1)
.find(|l| l.trim().is_empty())
.is_some()
{
"\n"
} else {
""
};
if contains_comment(&snippet) || snippet.lines().count() > 1 {
return (spacings, index);
}
index += 1;
}
("", index)
}

View File

@ -0,0 +1,383 @@
// rustfmt-struct_field_align_threshold: 20
// rustfmt-normalize_comments: true
// rustfmt-wrap_comments: true
// rustfmt-error_on_line_overflow: false
struct Foo {
x: u32,
yy: u32, // comment
zzz: u32,
}
pub struct Bar {
x: u32,
yy: u32,
zzz: u32,
xxxxxxx: u32,
}
fn main() {
let foo = Foo {
x: 0,
yy: 1,
zzz: 2,
};
let bar = Bar {
x: 0,
yy: 1,
zzz: 2,
xxxxxxx: 3,
};
}
/// A Doc comment
#[AnAttribute]
pub struct Foo {
#[rustfmt_skip]
f : SomeType, // Comment beside a field
f: SomeType, // Comment beside a field
// Comment on a field
#[AnAttribute]
g: SomeOtherType,
/// A doc comment on a field
h: AThirdType,
pub i: TypeForPublicField
}
// #1029
pub struct Foo {
#[doc(hidden)]
// This will NOT get deleted!
bar: String, // hi
}
// #1029
struct X {
// `x` is an important number.
#[allow(unused)] // TODO: use
x: u32,
}
// #410
#[allow(missing_docs)]
pub struct Writebatch<K: Key> {
#[allow(dead_code)] //only used for holding the internal pointer
writebatch: RawWritebatch,
marker: PhantomData<K>,
}
struct Bar;
struct NewType(Type, OtherType);
struct
NewInt <T: Copy>(pub i32, SomeType /* inline comment */, T /* sup */
);
struct Qux<'a,
N: Clone + 'a,
E: Clone + 'a,
G: Labeller<'a, N, E> + GraphWalk<'a, N, E>,
W: Write + Copy>
(
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,
#[AnAttr]
// Comment
/// Testdoc
G,
pub W,
);
struct Tuple(/*Comment 1*/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,
/* Comment 2 */ BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,);
// With a where clause and generics.
pub struct Foo<'a, Y: Baz>
where X: Whatever
{
f: SomeType, // Comment beside a field
}
struct Baz {
a: A, // Comment A
b: B, // Comment B
c: C, // Comment C
}
struct Baz {
a: A, // Comment A
b: B, // Comment B
c: C, // Comment C
}
struct Baz {
a: A,
b: B,
c: C,
d: D
}
struct Baz
{
// Comment A
a: A,
// Comment B
b: B,
// Comment C
c: C,}
// Will this be a one-liner?
struct Tuple(
A, //Comment
B
);
pub struct State<F: FnMut() -> time::Timespec> { now: F }
pub struct State<F: FnMut() -> ()> { now: F }
pub struct State<F: FnMut()> { now: F }
struct Palette { /// A map of indizes in the palette to a count of pixels in approximately that color
foo: i32}
// Splitting a single line comment into a block previously had a misalignment
// when the field had attributes
struct FieldsWithAttributes {
// Pre Comment
#[rustfmt_skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB
//Another pre comment
#[attr1]
#[attr2] pub id: usize // CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC
}
struct Deep {
deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle<IdRef<'id, Node<K, V>>,
Type,
NodeType>,
}
struct Foo<T>(T);
struct Foo<T>(T) where T: Copy, T: Eq;
struct Foo<T>(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUU);
struct Foo<T>(TTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT) where T: PartialEq;
struct Foo<T>(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTTTT) where T: PartialEq;
struct Foo<T>(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUU) where T: PartialEq;
struct Foo<T>(TTTTTTTTTTTTTTTTT, // Foo
UUUUUUUUUUUUUUUUUUUUUUUU /* Bar */,
// Baz
TTTTTTTTTTTTTTTTTTT,
// Qux (FIXME #572 - doc comment)
UUUUUUUUUUUUUUUUUUU);
mod m {
struct X<T> where T: Sized {
a: T,
}
}
struct Foo<T>(TTTTTTTTTTTTTTTTTTT,
/// Qux
UUUUUUUUUUUUUUUUUUU);
struct Issue677 {
pub ptr: *const libc::c_void,
pub trace: fn( obj:
*const libc::c_void, tracer : *mut JSTracer ),
}
struct Foo {}
struct Foo {
}
struct Foo {
// comment
}
struct Foo {
// trailing space ->
}
struct Foo { /* comment */ }
struct Foo( /* comment */ );
struct LongStruct {
a: A,
the_quick_brown_fox_jumps_over_the_lazy_dog:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,
}
struct Deep {
deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle<IdRef<'id, Node<Key, Value>>,
Type,
NodeType>,
}
struct Foo<C=()>(String);
// #1364
fn foo() {
convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 });
convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 });
convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 });
convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 });
}
fn main() {
let x = Bar;
// Comment
let y = Foo {a: x };
Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something };
Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), };
Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), };
Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo {
// Comment
a: foo(), // Comment
// Comment
b: bar(), // Comment
};
Foo { a:Bar,
b:f() };
Quux { x: if cond { bar(); }, y: baz() };
A {
// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor.
first: item(),
// Praesent et diam eget libero egestas mattis sit amet vitae augue.
// Nam tincidunt congue enim, ut porta lorem lacinia consectetur.
second: Item
};
Some(Data::MethodCallData(MethodCallData {
span: sub_span.unwrap(),
scope: self.enclosing_scope(id),
ref_id: def_id,
decl_id: Some(decl_id),
}));
Diagram { /* o This graph demonstrates how
* / \ significant whitespace is
* o o preserved.
* /|\ \
* o o o o */
graph: G, }
}
fn matcher() {
TagTerminatedByteMatcher {
matcher: ByteMatcher {
pattern: b"<HTML",
mask: b"\xFF\xDF\xDF\xDF\xDF\xFF",
},
};
}
fn issue177() {
struct Foo<T> { memb: T }
let foo = Foo::<i64> { memb: 10 };
}
fn issue201() {
let s = S{a:0, .. b};
}
fn issue201_2() {
let s = S{a: S2{ .. c}, .. b};
}
fn issue278() {
let s = S {
a: 0,
//
b: 0,
};
let s1 = S {
a: 0,
// foo
//
// bar
b: 0,
};
}
fn struct_exprs() {
Foo
{ a : 1, b:f( 2)};
Foo{a:1,b:f(2),..g(3)};
LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { ..base };
IntrinsicISizesContribution { content_intrinsic_sizes: IntrinsicISizes { minimum_inline_size: 0, }, };
}
fn issue123() {
Foo { a: b, c: d, e: f };
Foo { a: bb, c: dd, e: ff };
Foo { a: ddddddddddddddddddddd, b: cccccccccccccccccccccccccccccccccccccc };
}
fn issue491() {
Foo {
guard: None,
arm: 0, // Comment
};
Foo {
arm: 0, // Comment
};
Foo { a: aaaaaaaaaa, b: bbbbbbbb, c: cccccccccc, d: dddddddddd, /* a comment */
e: eeeeeeeee };
}
fn issue698() {
Record {
ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
};
Record {
ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
}
}
fn issue835() {
MyStruct {};
MyStruct { /* a comment */ };
MyStruct {
// Another comment
};
MyStruct {}
}
fn field_init_shorthand() {
MyStruct { x, y, z };
MyStruct { x, y, z, .. base };
Foo { aaaaaaaaaa, bbbbbbbb, cccccccccc, dddddddddd, /* a comment */
eeeeeeeee };
Record { ffffffffffffffffffffffffffieldsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa };
}

View File

@ -1,6 +1,5 @@
// rustfmt-normalize_comments: true
// rustfmt-wrap_comments: true
// rustfmt-error_on_line_overflow: false
/// A Doc comment
#[AnAttribute]

View File

@ -56,8 +56,12 @@ struct Foo {
fn foo() {
#[cfg(target_os = "freertos")]
match port_id {
'a' | 'A' => GpioPort { port_address: GPIO_A },
'b' | 'B' => GpioPort { port_address: GPIO_B },
'a' | 'A' => GpioPort {
port_address: GPIO_A,
},
'b' | 'B' => GpioPort {
port_address: GPIO_B,
},
_ => panic!(),
}

View File

@ -0,0 +1,451 @@
// rustfmt-struct_field_align_threshold: 20
// rustfmt-normalize_comments: true
// rustfmt-wrap_comments: true
// rustfmt-error_on_line_overflow: false
struct Foo {
x: u32,
yy: u32, // comment
zzz: u32,
}
pub struct Bar {
x: u32,
yy: u32,
zzz: u32,
xxxxxxx: u32,
}
fn main() {
let foo = Foo {
x: 0,
yy: 1,
zzz: 2,
};
let bar = Bar {
x: 0,
yy: 1,
zzz: 2,
xxxxxxx: 3,
};
}
/// A Doc comment
#[AnAttribute]
pub struct Foo {
#[rustfmt_skip]
f : SomeType, // Comment beside a field
f: SomeType, // Comment beside a field
// Comment on a field
#[AnAttribute]
g: SomeOtherType,
/// A doc comment on a field
h: AThirdType,
pub i: TypeForPublicField,
}
// #1029
pub struct Foo {
#[doc(hidden)]
// This will NOT get deleted!
bar: String, // hi
}
// #1029
struct X {
// `x` is an important number.
#[allow(unused)] // TODO: use
x: u32,
}
// #410
#[allow(missing_docs)]
pub struct Writebatch<K: Key> {
#[allow(dead_code)] // only used for holding the internal pointer
writebatch: RawWritebatch,
marker: PhantomData<K>,
}
struct Bar;
struct NewType(Type, OtherType);
struct NewInt<T: Copy>(pub i32, SomeType /* inline comment */, T /* sup */);
struct Qux<'a,
N: Clone + 'a,
E: Clone + 'a,
G: Labeller<'a, N, E> + GraphWalk<'a, N, E>,
W: Write + Copy>
(
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,
#[AnAttr]
// Comment
/// Testdoc
G,
pub W,
);
struct Tuple(
// Comment 1
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,
// Comment 2
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
);
// With a where clause and generics.
pub struct Foo<'a, Y: Baz>
where
X: Whatever,
{
f: SomeType, // Comment beside a field
}
struct Baz {
a: A, // Comment A
b: B, // Comment B
c: C, // Comment C
}
struct Baz {
a: A, // Comment A
b: B, // Comment B
c: C, // Comment C
}
struct Baz {
a: A,
b: B,
c: C,
d: D,
}
struct Baz {
// Comment A
a: A,
// Comment B
b: B,
// Comment C
c: C,
}
// Will this be a one-liner?
struct Tuple(A /* Comment */, B);
pub struct State<F: FnMut() -> time::Timespec> {
now: F,
}
pub struct State<F: FnMut() -> ()> {
now: F,
}
pub struct State<F: FnMut()> {
now: F,
}
struct Palette {
/// A map of indizes in the palette to a count of pixels in approximately
/// that color
foo: i32,
}
// Splitting a single line comment into a block previously had a misalignment
// when the field had attributes
struct FieldsWithAttributes {
// Pre Comment
#[rustfmt_skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB
* BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB */
// Another pre comment
#[attr1]
#[attr2]
pub id: usize, /* CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC
* CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC */
}
struct Deep {
deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep:
node::Handle<IdRef<'id, Node<K, V>>, Type, NodeType>,
}
struct Foo<T>(T);
struct Foo<T>(T)
where
T: Copy,
T: Eq;
struct Foo<T>(
TTTTTTTTTTTTTTTTT,
UUUUUUUUUUUUUUUUUUUUUUUU,
TTTTTTTTTTTTTTTTTTT,
UUUUUUUUUUUUUUUUUUU
);
struct Foo<T>(TTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT)
where
T: PartialEq;
struct Foo<T>(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTTTT)
where
T: PartialEq;
struct Foo<T>(
TTTTTTTTTTTTTTTTT,
UUUUUUUUUUUUUUUUUUUUUUUU,
TTTTTTTTTTTTTTTTTTT,
UUUUUUUUUUUUUUUUUUU
)
where
T: PartialEq;
struct Foo<T>(
TTTTTTTTTTTTTTTTT, // Foo
UUUUUUUUUUUUUUUUUUUUUUUU, // Bar
// Baz
TTTTTTTTTTTTTTTTTTT,
// Qux (FIXME #572 - doc comment)
UUUUUUUUUUUUUUUUUUU
);
mod m {
struct X<T>
where
T: Sized,
{
a: T,
}
}
struct Foo<T>(
TTTTTTTTTTTTTTTTTTT,
/// Qux
UUUUUUUUUUUUUUUUUUU
);
struct Issue677 {
pub ptr: *const libc::c_void,
pub trace: fn(obj: *const libc::c_void, tracer: *mut JSTracer),
}
struct Foo {}
struct Foo {}
struct Foo {
// comment
}
struct Foo {
// trailing space ->
}
struct Foo { /* comment */ }
struct Foo( /* comment */ );
struct LongStruct {
a: A,
the_quick_brown_fox_jumps_over_the_lazy_dog:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,
}
struct Deep {
deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep:
node::Handle<IdRef<'id, Node<Key, Value>>, Type, NodeType>,
}
struct Foo<C = ()>(String);
// #1364
fn foo() {
convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 });
convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 });
convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 });
convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 });
}
fn main() {
let x = Bar;
// Comment
let y = Foo { a: x };
Foo {
a: foo(), // comment
// comment
b: bar(),
..something
};
Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b() };
Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo {
a: f(),
b: b(),
};
Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo {
// Comment
a: foo(), // Comment
// Comment
b: bar(), // Comment
};
Foo { a: Bar, b: f() };
Quux {
x: if cond {
bar();
},
y: baz(),
};
A {
// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit
// amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante
// hendrerit. Donec et mollis dolor.
first: item(),
// Praesent et diam eget libero egestas mattis sit amet vitae augue.
// Nam tincidunt congue enim, ut porta lorem lacinia consectetur.
second: Item,
};
Some(Data::MethodCallData(MethodCallData {
span: sub_span.unwrap(),
scope: self.enclosing_scope(id),
ref_id: def_id,
decl_id: Some(decl_id),
}));
Diagram {
// o This graph demonstrates how
// / \ significant whitespace is
// o o preserved.
// /|\ \
// o o o o
graph: G,
}
}
fn matcher() {
TagTerminatedByteMatcher {
matcher: ByteMatcher {
pattern: b"<HTML",
mask: b"\xFF\xDF\xDF\xDF\xDF\xFF",
},
};
}
fn issue177() {
struct Foo<T> {
memb: T,
}
let foo = Foo::<i64> { memb: 10 };
}
fn issue201() {
let s = S { a: 0, ..b };
}
fn issue201_2() {
let s = S { a: S2 { ..c }, ..b };
}
fn issue278() {
let s = S {
a: 0,
//
b: 0,
};
let s1 = S {
a: 0,
// foo
//
// bar
b: 0,
};
}
fn struct_exprs() {
Foo { a: 1, b: f(2) };
Foo {
a: 1,
b: f(2),
..g(3)
};
LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct {
..base
};
IntrinsicISizesContribution {
content_intrinsic_sizes: IntrinsicISizes {
minimum_inline_size: 0,
},
};
}
fn issue123() {
Foo { a: b, c: d, e: f };
Foo {
a: bb,
c: dd,
e: ff,
};
Foo {
a: ddddddddddddddddddddd,
b: cccccccccccccccccccccccccccccccccccccc,
};
}
fn issue491() {
Foo {
guard: None,
arm: 0, // Comment
};
Foo {
arm: 0, // Comment
};
Foo {
a: aaaaaaaaaa,
b: bbbbbbbb,
c: cccccccccc,
d: dddddddddd, // a comment
e: eeeeeeeee,
};
}
fn issue698() {
Record {
ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
};
Record {
ffffffffffffffffffffffffffields:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
}
}
fn issue835() {
MyStruct {};
MyStruct { /* a comment */ };
MyStruct {
// Another comment
};
MyStruct {}
}
fn field_init_shorthand() {
MyStruct { x, y, z };
MyStruct { x, y, z, ..base };
Foo {
aaaaaaaaaa,
bbbbbbbb,
cccccccccc,
dddddddddd, // a comment
eeeeeeeee,
};
Record {
ffffffffffffffffffffffffffieldsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
};
}

View File

@ -12,7 +12,8 @@ fn baz(p: Packet) {
loop {
loop {
if let Packet::Transaction {
state: TransactionState::Committed(ts, ..), ..
state: TransactionState::Committed(ts, ..),
..
} = p
{
unreachable!()

View File

@ -3,7 +3,10 @@ fn main() {
for event in event_pump.poll_iter() {
match event {
Event::Quit { .. } |
Event::KeyDown { keycode: Some(Keycode::Escape), .. } => break 'running,
Event::KeyDown {
keycode: Some(Keycode::Escape),
..
} => break 'running,
}
}
}
@ -14,9 +17,10 @@ fn main2() {
for event in event_pump.poll_iter() {
match event {
Event::Quit { .. } |
Event::KeyDownXXXXXXXXXXXXX { keycode: Some(Keycode::Escape), .. } => {
break 'running
}
Event::KeyDownXXXXXXXXXXXXX {
keycode: Some(Keycode::Escape),
..
} => break 'running,
}
}
}

View File

@ -116,7 +116,9 @@ fn struct_exprs() {
..base
};
IntrinsicISizesContribution {
content_intrinsic_sizes: IntrinsicISizes { minimum_inline_size: 0 },
content_intrinsic_sizes: IntrinsicISizes {
minimum_inline_size: 0,
},
};
}
@ -141,7 +143,9 @@ fn issue491() {
arm: 0, // Comment
};
Foo { arm: 0 /* Comment */ };
Foo {
arm: 0, // Comment
};
Foo {
a: aaaaaaaaaa,

View File

@ -1,6 +1,5 @@
// rustfmt-normalize_comments: true
// rustfmt-wrap_comments: true
// rustfmt-error_on_line_overflow: false
/// A Doc comment
#[AnAttribute]
@ -132,13 +131,13 @@ struct Palette {
// when the field had attributes
struct FieldsWithAttributes {
// Pre Comment
#[rustfmt_skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB
* BBBBBBBBBBBBBBBBB BBBBBBBBBBB */
#[rustfmt_skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB
* BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB */
// Another pre comment
#[attr1]
#[attr2]
pub id: usize, /* CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC
* CCCCCCCCCCCCCC CCCCCCCCCCCC */
pub id: usize, /* CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC
* CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC */
}
struct Deep {