Format assignment

This commit is contained in:
Marcus Klaas 2015-08-21 13:31:09 +02:00
parent ca39467cde
commit 120fd2426e
16 changed files with 284 additions and 76 deletions

View File

@ -104,14 +104,13 @@ fn format_comments() {
let input = "// comment";
let expected = "/* com\n \
* men\n * \
t */";
* men\n \
* t */";
assert_eq!(expected, rewrite_comment(input, true, 9, 69));
assert_eq!("/* trimmed */", rewrite_comment("/* trimmed */", true, 100, 100));
}
pub trait FindUncommented {
fn find_uncommented(&self, pat: &str) -> Option<usize>;
}

View File

@ -106,6 +106,12 @@ fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Opti
ast::Expr_::ExprPath(ref qself, ref path) => {
rewrite_path(context, qself.as_ref(), path, width, offset)
}
ast::Expr_::ExprAssign(ref lhs, ref rhs) => {
rewrite_assignment(context, lhs, rhs, None, width, offset)
}
ast::Expr_::ExprAssignOp(ref op, ref lhs, ref rhs) => {
rewrite_assignment(context, lhs, rhs, Some(op), width, offset)
}
// FIXME #184 Note that this formatting is broken due to a bad span
// from the parser.
// `continue`
@ -116,10 +122,47 @@ fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Opti
};
Some(format!("continue{}", id_str))
}
ast::Expr_::ExprBreak(ref opt_ident) => {
let id_str = match *opt_ident {
Some(ident) => format!(" {}", ident),
None => String::new(),
};
Some(format!("break{}", id_str))
}
ast::Expr_::ExprClosure(capture, ref fn_decl, ref body) => {
rewrite_closure(capture, fn_decl, body, self.span, context, width, offset)
}
_ => context.codemap.span_to_snippet(self.span).ok(),
_ => {
// We do not format these expressions yet, but they should still
// satisfy our width restrictions.
let snippet = context.codemap.span_to_snippet(self.span).unwrap();
{
let mut lines = snippet.lines();
// The caller of this function has already placed `offset`
// characters on the first line.
let first_line_max_len = try_opt!(context.config.max_width.checked_sub(offset));
if lines.next().unwrap().len() > first_line_max_len {
return None;
}
// The other lines must fit within the maximum width.
if lines.find(|line| line.len() > context.config.max_width).is_some() {
return None;
}
// `width` is the maximum length of the last line, excluding
// indentation.
// A special check for the last line, since the caller may
// place trailing characters on this line.
if snippet.lines().rev().next().unwrap().len() > offset + width {
return None;
}
}
Some(snippet)
}
}
}
}
@ -402,7 +445,7 @@ fn rewrite_match(context: &RewriteContext,
width: usize,
offset: usize)
-> Option<String> {
if arms.len() == 0 {
if arms.is_empty() {
return None;
}
@ -440,7 +483,7 @@ fn rewrite_match(context: &RewriteContext,
result.push('\n');
}
let missed_str = missed_str.trim();
if missed_str.len() > 0 {
if !missed_str.is_empty() {
result.push('\n');
result.push_str(&arm_indent_str);
result.push_str(missed_str);
@ -473,7 +516,7 @@ fn rewrite_match(context: &RewriteContext,
fn arm_start_pos(arm: &ast::Arm) -> BytePos {
let &ast::Arm { ref attrs, ref pats, .. } = arm;
if attrs.len() > 0 {
if !attrs.is_empty() {
return attrs[0].span.lo
}
@ -492,7 +535,7 @@ fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Opti
// FIXME this is all a bit grotty, would be nice to abstract out the
// treatment of attributes.
let attr_str = if attrs.len() > 0 {
let attr_str = if !attrs.is_empty() {
// We only use this visitor for the attributes, should we use it for
// more?
let mut attr_visitor = FmtVisitor::from_codemap(context.codemap, context.config);
@ -539,7 +582,7 @@ fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Opti
let mut pats_str = String::new();
for p in pat_strs {
if pats_str.len() > 0 {
if !pats_str.is_empty() {
if vertical {
pats_str.push_str(" |\n");
pats_str.push_str(&indent_str);
@ -584,7 +627,7 @@ fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Opti
}
// We have to push the body to the next line.
if comma.len() == 0 {
if comma.is_empty() {
// We're trying to fit a block in, but it still failed, give up.
return None;
}
@ -645,6 +688,8 @@ fn rewrite_pat_expr(context: &RewriteContext,
pat: Option<&ast::Pat>,
expr: &ast::Expr,
matcher: &str,
// Connecting piece between pattern and expression,
// *without* trailing space.
connector: &str,
width: usize,
offset: usize)
@ -665,18 +710,18 @@ fn rewrite_pat_expr(context: &RewriteContext,
// The expression may (partionally) fit on the current line.
if width > extra_offset + 1 {
let mut corrected_offset = extra_offset;
if pat.is_some() {
result.push(' ');
corrected_offset += 1;
}
let spacer = if pat.is_some() {
" "
} else {
""
};
let expr_rewrite = expr.rewrite(context,
width - corrected_offset,
offset + corrected_offset);
width - extra_offset - spacer.len(),
offset + extra_offset + spacer.len());
if let Some(expr_string) = expr_rewrite {
result.push_str(spacer);
result.push_str(&expr_string);
return Some(result);
}
@ -810,7 +855,7 @@ enum StructLitField<'a> {
let path_str = try_opt!(path.rewrite(context, width - 2, offset));
// Foo { a: Foo } - indent is +3, width is -5.
let h_budget = width.checked_sub(path_str.len() + 5).unwrap_or(0);
let h_budget = try_opt!(width.checked_sub(path_str.len() + 5));
let (indent, v_budget) = match context.config.struct_lit_style {
StructLitStyle::VisualIndent => {
(offset + path_str.len() + 3, h_budget)
@ -1008,7 +1053,62 @@ fn rewrite_unary_op(context: &RewriteContext,
ast::UnOp::UnNeg => "-",
};
let subexpr = try_opt!(expr.rewrite(context, try_opt!(width.checked_sub(operator_str.len())), offset));
let subexpr =
try_opt!(expr.rewrite(context, try_opt!(width.checked_sub(operator_str.len())), offset));
Some(format!("{}{}", operator_str, subexpr))
}
fn rewrite_assignment(context: &RewriteContext,
lhs: &ast::Expr,
rhs: &ast::Expr,
op: Option<&ast::BinOp>,
width: usize,
offset: usize)
-> Option<String> {
let operator_str = match op {
Some(op) => context.codemap.span_to_snippet(op.span).unwrap(),
None => "=".to_owned(),
};
// 1 = space between lhs and operator.
let max_width = try_opt!(width.checked_sub(operator_str.len() + 1));
let lhs_str = format!("{} {}", try_opt!(lhs.rewrite(context, max_width, offset)), operator_str);
rewrite_assign_rhs(&context, lhs_str, rhs, width, offset)
}
// The left hand side must contain everything up to, and including, the
// assignment operator.
pub fn rewrite_assign_rhs<S: Into<String>>(context: &RewriteContext,
lhs: S,
ex: &ast::Expr,
width: usize,
offset: usize)
-> Option<String> {
let mut result = lhs.into();
// 1 = space between operator and rhs.
let max_width = try_opt!(width.checked_sub(result.len() + 1));
let rhs = ex.rewrite(&context, max_width, offset + result.len() + 1);
match rhs {
Some(new_str) => {
result.push(' ');
result.push_str(&new_str)
}
None => {
// Expression did not fit on the same line as the identifier. Retry
// on the next line.
let new_offset = offset + context.config.tab_spaces;
result.push_str(&format!("\n{}", make_indent(new_offset)));
let max_width = try_opt!(context.config.max_width.checked_sub(new_offset + 1));
let rhs = try_opt!(ex.rewrite(&context, max_width, new_offset));
result.push_str(&rhs);
}
}
Some(result)
}

View File

@ -214,10 +214,7 @@ fn inspect_number(&mut self,
NumberPart::CloseParen => {}
}
self.state = Seeking::Number {
part: part,
issue: issue
};
self.state = Seeking::Number { part: part, issue: issue };
IssueClassification::None
}

View File

@ -14,8 +14,10 @@
use utils::{format_mutability, format_visibility, make_indent, contains_skip, span_after,
end_typaram};
use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic};
use expr::rewrite_assign_rhs;
use comment::FindUncommented;
use visitor::FmtVisitor;
use rewrite::Rewrite;
use config::Config;
@ -25,6 +27,67 @@
use syntax::parse::token;
impl<'a> FmtVisitor<'a> {
pub fn visit_let(&mut self, local: &ast::Local, span: Span) {
self.format_missing_with_indent(span.lo);
// String that is placed within the assignment pattern and expression.
let infix = {
let mut infix = String::new();
if let Some(ref ty) = local.ty {
infix.push_str(": ");
infix.push_str(&pprust::ty_to_string(ty));
}
if local.init.is_some() {
infix.push_str(" =");
}
infix
};
// New scope so we drop the borrow of self (context) in time to mutably
// borrow self to mutate its buffer.
let result = {
let context = self.get_context();
let mut result = "let ".to_owned();
let pattern_offset = self.block_indent + result.len() + infix.len();
// 1 = ;
let pattern_width = match self.config.max_width.checked_sub(pattern_offset + 1) {
Some(width) => width,
None => return,
};
match local.pat.rewrite(&context, pattern_offset, pattern_width) {
Some(ref pat_string) => result.push_str(pat_string),
None => return,
}
result.push_str(&infix);
if let Some(ref ex) = local.init {
let max_width = match self.config.max_width.checked_sub(context.block_indent + 1) {
Some(width) => width,
None => return,
};
// 1 = trailing semicolon;
let rhs = rewrite_assign_rhs(&context, result, ex, max_width, context.block_indent);
match rhs {
Some(result) => result,
None => return,
}
} else {
result
}
};
self.buffer.push_str(&result);
self.buffer.push_str(";");
self.last_pos = span.hi;
}
pub fn rewrite_fn(&mut self,
indent: usize,
ident: ast::Ident,
@ -51,9 +114,11 @@ pub fn rewrite_fn(&mut self,
span,
newline_brace);
// Prepare for the function body by possibly adding a newline and indent.
// FIXME we'll miss anything between the end of the signature and the start
// of the body, but we need more spans from the compiler to solve this.
// Prepare for the function body by possibly adding a newline and
// indent.
// FIXME we'll miss anything between the end of the signature and the
// start of the body, but we need more spans from the compiler to solve
// this.
if newline_brace {
result.push('\n');
result.push_str(&make_indent(indent));
@ -783,7 +848,8 @@ fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, args: &[ast::Arg]) -
// this hacky solution caused by absence of `Mutability` in `SelfValue`.
let mut_str = {
if let ast::Pat_::PatIdent(ast::BindingMode::BindByValue(mutability), _, _) = args[0].pat.node {
if let ast::Pat_::PatIdent(ast::BindingMode::BindByValue(mutability), _, _) =
args[0].pat.node {
format_mutability(mutability)
} else {
panic!("there is a bug or change in structure of AST, aborting.");

View File

@ -325,6 +325,8 @@ fn no_input(&mut self,
panic!("No input supplied to RustFmt");
}
#[rustfmt_skip]
// FIXME(#195): closure is formatted poorly.
fn build_controller(&mut self, _: &Session) -> driver::CompileController<'a> {
let write_mode = self.write_mode;

View File

@ -99,7 +99,7 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St
let mut tactic = formatting.tactic;
// Conservatively overestimates because of the changing separator tactic.
let sep_count = if formatting.trailing_separator != SeparatorTactic::Never {
let sep_count = if formatting.trailing_separator == SeparatorTactic::Always {
items.len()
} else {
items.len() - 1
@ -113,8 +113,7 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St
if tactic == ListTactic::HorizontalVertical {
debug!("write_list: total_width: {}, total_sep_len: {}, h_width: {}",
total_width, total_sep_len, formatting.h_width);
tactic = if fits_single &&
!items.iter().any(ListItem::is_multiline) {
tactic = if fits_single && !items.iter().any(ListItem::is_multiline) {
ListTactic::Horizontal
} else {
ListTactic::Vertical
@ -187,13 +186,11 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St
// Pre-comments
if let Some(ref comment) = item.pre_comment {
result.push_str(&rewrite_comment(comment,
// Block style in non-vertical mode
tactic != ListTactic::Vertical,
// Width restriction is only
// relevant in vertical mode.
formatting.v_width,
formatting.indent));
// Block style in non-vertical mode.
let block_mode = tactic != ListTactic::Vertical;
// Width restriction is only relevant in vertical mode.
let max_width = formatting.v_width;
result.push_str(&rewrite_comment(comment, block_mode, max_width, formatting.indent));
if tactic == ListTactic::Vertical {
result.push('\n');

View File

@ -28,6 +28,8 @@ pub struct FmtVisitor<'a> {
}
impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
// FIXME: We'd rather not format expressions here, as we have little
// context. How are we still reaching this?
fn visit_expr(&mut self, ex: &'v ast::Expr) {
debug!("visit_expr: {:?} {:?}",
self.codemap.lookup_char_pos(ex.span.lo),
@ -44,23 +46,37 @@ fn visit_expr(&mut self, ex: &'v ast::Expr) {
}
fn visit_stmt(&mut self, stmt: &'v ast::Stmt) {
// If the stmt is actually an item, then we'll handle any missing spans
// there. This is important because of annotations.
// Although it might make more sense for the statement span to include
// any annotations on the item.
let skip_missing = match stmt.node {
match stmt.node {
ast::Stmt_::StmtDecl(ref decl, _) => {
match decl.node {
ast::Decl_::DeclItem(_) => true,
_ => false,
return match decl.node {
ast::Decl_::DeclLocal(ref local) => self.visit_let(local, stmt.span),
ast::Decl_::DeclItem(..) => visit::walk_stmt(self, stmt),
};
}
ast::Stmt_::StmtExpr(ref ex, _) | ast::Stmt_::StmtSemi(ref ex, _) => {
self.format_missing_with_indent(stmt.span.lo);
let suffix = if let ast::Stmt_::StmtExpr(..) = stmt.node {
""
} else {
";"
};
// 1 = trailing semicolon;
let rewrite = ex.rewrite(&self.get_context(),
self.config.max_width - self.block_indent - suffix.len(),
self.block_indent);
if let Some(new_str) = rewrite {
self.buffer.push_str(&new_str);
self.buffer.push_str(suffix);
self.last_pos = stmt.span.hi;
}
}
_ => false,
};
if !skip_missing {
self.format_missing_with_indent(stmt.span.lo);
ast::Stmt_::StmtMac(..) => {
self.format_missing_with_indent(stmt.span.lo);
visit::walk_stmt(self, stmt);
}
}
visit::walk_stmt(self, stmt);
}
fn visit_block(&mut self, b: &'v ast::Block) {

View File

@ -0,0 +1,16 @@
// Test assignment
fn main() {
let some_var : Type ;
let mut mutable;
let variable = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA::BBBBBBBBBBBBBBBBBBBBBB::CCCCCCCCCCCCCCCCCCCCCC::EEEEEE;
variable = LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG;
let single_line_fit =
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD;
single_line_fit = 5;single_lit_fit >>= 10;
}

View File

@ -2,23 +2,22 @@
fn foo() -> bool {
let boxed: Box<i32> = box 5;
let referenced = &5;
let referenced = &5 ;
let very_long_variable_name = ( a + first + simple + test );
let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c);
//FIXME this exceeds width limit. Needs assignments reformatting
let is_internalxxxx = self.codemap.span_to_filename(s) == self.codemap.span_to_filename(m.inner);
let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb / (bbbbbb -
function_call(x, *very_long_pointer, y))
+ 1000;
+ 1000 ;
some_ridiculously_loooooooooooooooooooooong_function(10000 * 30000000000 + 40000 / 1002200000000
- 50000 * sqrt(-1),
trivial_value);
(((((((((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + a +
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaa)))))))));
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaa))))))))) ;
{ for _ in 0..10 {} }
@ -64,9 +63,9 @@ fn bar() {
syntactically_correct(loop { sup( '?'); }, if cond { 0 } else { 1 });
let third = ..10;
let infi_range = ..;
let infi_range = .. ;
let foo = 1..;
let bar = 5;
let bar = 5 ;
let nonsense = (10 .. 0)..(0..10);
let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&

View File

@ -15,8 +15,6 @@ fn main() {
Quux::<ParamOne, // Comment 1
ParamTwo, // Comment 2
>::some_func();
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA::BBBBBBBBBBBBBBBBBBBBBBBBBBBB::CCCCCCCCCCCCCCCCCCCCCC::quux();
}
fn op(foo: Bar, key : &[u8], upd : Fn(Option<&memcache::Item> , Baz ) -> Result) -> MapResult {}

View File

@ -0,0 +1,18 @@
// Test assignment
fn main() {
let some_var: Type;
let mut mutable;
let variable =
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA::BBBBBBBBBBBBBBBBBBBBBB::CCCCCCCCCCCCCCCCCCCCCC::EEEEEE;
variable =
LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG;
let single_line_fit = DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD;
single_line_fit = 5;
single_lit_fit >>= 10;
}

View File

@ -8,8 +8,8 @@ fn foo() -> bool {
let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA +
BBBBBBBBBBBBBBBBB + b + c);
//FIXME this exceeds width limit. Needs assignments reformatting
let is_internalxxxx = self.codemap.span_to_filename(s) == self.codemap.span_to_filename(m.inner);
let is_internalxxxx = self.codemap.span_to_filename(s) ==
self.codemap.span_to_filename(m.inner);
let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb /
(bbbbbb - function_call(x, *very_long_pointer, y)) + 1000;

View File

@ -134,7 +134,7 @@ fn main() {
42usize);
let rc = RefCell::new(42usize, remaining_width, remaining_width); // a comment
let x = "Hello!!!!!!!!! abcd abcd abcd abcd abcd abcd\n abcd abcd abcd abcd abcd abcd abcd \
abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \
abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \
abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \
abcd";
abcd abcd";
}

View File

@ -13,8 +13,6 @@ fn main() {
supports_clipboard);
Quux::<ParamOne /* Comment 1 */, ParamTwo /* Comment 2 */>::some_func();
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA::BBBBBBBBBBBBBBBBBBBBBBBBBBBB::CCCCCCCCCCCCCCCCCCCCCC::quux();
}
fn op(foo: Bar, key: &[u8], upd: Fn(Option<&memcache::Item>, Baz) -> Result) -> MapResult {

View File

@ -3,21 +3,22 @@
fn main() -> &'static str {
let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAaAA \
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa";
let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAaAa";
let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAaAa";
let str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
let too_many_lines = "Hello";
// Make sure we don't break after an escape character.
let odd_length_name = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\
\n\n";
let odd_length_name = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\
\n\n\n";
let even_length_name = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\
\n\n\n";
let really_long_variable_name = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
let really_long_variable_name = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AA";
let raw_string = r#"Do
not

View File

@ -13,10 +13,10 @@ fn main() {
b: bar(),
..something };
Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(),
b: bar(), };
Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar() };
Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment
Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Commen
// t
a: foo(), /* C
* o
* m
@ -24,7 +24,8 @@ fn main() {
* e
* n
* t */
// Comment
// Commen
// t
b: bar(), /* C
* o
* m