Skip to content

Commit dae9fb6

Browse files
authored
Merge pull request #2656 from topecongiro/issue-2594
Use consistent formatting for empty enum and struct
2 parents fb9a5ad + 3432807 commit dae9fb6

File tree

8 files changed

+102
-66
lines changed

8 files changed

+102
-66
lines changed

Diff for: src/items.rs

+66-60
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,7 @@ use rewrite::{Rewrite, RewriteContext};
3333
use shape::{Indent, Shape};
3434
use spanned::Spanned;
3535
use types::TraitTyParamBounds;
36-
use utils::{colon_spaces, contains_skip, first_line_width, format_abi, format_auto,
37-
format_constness, format_defaultness, format_mutability, format_unsafety,
38-
format_visibility, is_attributes_extendable, last_line_contains_single_line_comment,
39-
last_line_used_width, last_line_width, mk_sp, semicolon_for_expr, starts_with_newline,
40-
stmt_expr, trimmed_last_line_width};
36+
use utils::*;
4137
use vertical::rewrite_with_alignment;
4238
use visitor::FmtVisitor;
4339

@@ -458,35 +454,39 @@ impl<'a> FmtVisitor<'a> {
458454

459455
self.last_pos = body_start;
460456

461-
self.block_indent = self.block_indent.block_indent(self.config);
462-
let variant_list = self.format_variant_list(enum_def, body_start, span.hi() - BytePos(1));
463-
match variant_list {
464-
Some(ref body_str) => self.push_str(body_str),
465-
None => self.format_missing_no_indent(span.hi() - BytePos(1)),
466-
}
467-
self.block_indent = self.block_indent.block_unindent(self.config);
468-
469-
if variant_list.is_some() || contains_comment(&enum_snippet[brace_pos..]) {
470-
let indent_str = self.block_indent.to_string(self.config);
471-
self.push_str(&indent_str);
457+
match self.format_variant_list(enum_def, body_start, span.hi()) {
458+
Some(ref s) if enum_def.variants.is_empty() => self.push_str(s),
459+
rw => {
460+
self.push_rewrite(mk_sp(body_start, span.hi()), rw);
461+
self.block_indent = self.block_indent.block_unindent(self.config);
462+
}
472463
}
473-
self.push_str("}");
474-
self.last_pos = span.hi();
475464
}
476465

477466
// Format the body of an enum definition
478467
fn format_variant_list(
479-
&self,
468+
&mut self,
480469
enum_def: &ast::EnumDef,
481470
body_lo: BytePos,
482471
body_hi: BytePos,
483472
) -> Option<String> {
484473
if enum_def.variants.is_empty() {
485-
return None;
474+
let mut buffer = String::with_capacity(128);
475+
// 1 = "}"
476+
let span = mk_sp(body_lo, body_hi - BytePos(1));
477+
format_empty_struct_or_tuple(
478+
&self.get_context(),
479+
span,
480+
self.block_indent,
481+
&mut buffer,
482+
"",
483+
"}",
484+
);
485+
return Some(buffer);
486486
}
487487
let mut result = String::with_capacity(1024);
488-
let indentation = self.block_indent.to_string_with_newline(self.config);
489-
result.push_str(&indentation);
488+
let original_offset = self.block_indent;
489+
self.block_indent = self.block_indent.block_indent(self.config);
490490

491491
let itemize_list_with = |one_line_width: usize| {
492492
itemize_list(
@@ -531,7 +531,8 @@ impl<'a> FmtVisitor<'a> {
531531

532532
let list = write_list(&items, &fmt)?;
533533
result.push_str(&list);
534-
result.push('\n');
534+
result.push_str(&original_offset.to_string_with_newline(self.config));
535+
result.push('}');
535536
Some(result)
536537
}
537538

@@ -1195,18 +1196,8 @@ pub fn format_struct_struct(
11951196
}
11961197

11971198
if fields.is_empty() {
1198-
let snippet = context.snippet(mk_sp(body_lo, span.hi() - BytePos(1)));
1199-
if snippet.trim().is_empty() {
1200-
// `struct S {}`
1201-
} else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') {
1202-
// fix indent
1203-
result.push_str(snippet.trim_right());
1204-
result.push('\n');
1205-
result.push_str(&offset.to_string(context.config));
1206-
} else {
1207-
result.push_str(snippet);
1208-
}
1209-
result.push('}');
1199+
let inner_span = mk_sp(body_lo, span.hi() - BytePos(1));
1200+
format_empty_struct_or_tuple(context, inner_span, offset, &mut result, "", "}");
12101201
return Some(result);
12111202
}
12121203

@@ -1247,6 +1238,41 @@ fn get_bytepos_after_visibility(vis: &ast::Visibility, default_span: Span) -> By
12471238
}
12481239
}
12491240

1241+
// Format tuple or struct without any fields. We need to make sure that the comments
1242+
// inside the delimiters are preserved.
1243+
fn format_empty_struct_or_tuple(
1244+
context: &RewriteContext,
1245+
span: Span,
1246+
offset: Indent,
1247+
result: &mut String,
1248+
opener: &str,
1249+
closer: &str,
1250+
) {
1251+
// 3 = " {}" or "();"
1252+
let used_width = last_line_used_width(&result, offset.width()) + 3;
1253+
if used_width > context.config.max_width() {
1254+
result.push_str(&offset.to_string_with_newline(context.config))
1255+
}
1256+
result.push_str(opener);
1257+
match rewrite_missing_comment(span, Shape::indented(offset, context.config), context) {
1258+
Some(ref s) if s.is_empty() => (),
1259+
Some(ref s) => {
1260+
if !is_single_line(s) || first_line_contains_single_line_comment(s) {
1261+
let nested_indent_str = offset
1262+
.block_indent(context.config)
1263+
.to_string_with_newline(context.config);
1264+
result.push_str(&nested_indent_str);
1265+
}
1266+
result.push_str(s);
1267+
if last_line_contains_single_line_comment(s) {
1268+
result.push_str(&offset.to_string_with_newline(context.config));
1269+
}
1270+
}
1271+
None => result.push_str(context.snippet(span)),
1272+
}
1273+
result.push_str(closer);
1274+
}
1275+
12501276
fn format_tuple_struct(
12511277
context: &RewriteContext,
12521278
struct_parts: &StructParts,
@@ -1310,31 +1336,11 @@ fn format_tuple_struct(
13101336
};
13111337

13121338
if fields.is_empty() {
1313-
// 3 = `();`
1314-
let used_width = last_line_used_width(&result, offset.width()) + 3;
1315-
if used_width > context.config.max_width() {
1316-
result.push('\n');
1317-
result.push_str(&offset
1318-
.block_indent(context.config)
1319-
.to_string(context.config))
1320-
}
1321-
result.push('(');
1322-
let snippet = context.snippet(mk_sp(
1323-
body_lo,
1324-
context
1325-
.snippet_provider
1326-
.span_before(mk_sp(body_lo, span.hi()), ")"),
1327-
));
1328-
if snippet.is_empty() {
1329-
// `struct S ()`
1330-
} else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') {
1331-
result.push_str(snippet.trim_right());
1332-
result.push('\n');
1333-
result.push_str(&offset.to_string(context.config));
1334-
} else {
1335-
result.push_str(snippet);
1336-
}
1337-
result.push(')');
1339+
let body_hi = context
1340+
.snippet_provider
1341+
.span_before(mk_sp(body_lo, span.hi()), ")");
1342+
let inner_span = mk_sp(body_lo, body_hi);
1343+
format_empty_struct_or_tuple(context, inner_span, offset, &mut result, "(", ")");
13381344
} else {
13391345
let shape = Shape::indented(offset, context.config).sub_width(1)?;
13401346
let fields = &fields.iter().collect::<Vec<_>>();

Diff for: src/utils.rs

+10
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,16 @@ pub fn outer_attributes(attrs: &[ast::Attribute]) -> Vec<ast::Attribute> {
134134
filter_attributes(attrs, ast::AttrStyle::Outer)
135135
}
136136

137+
#[inline]
138+
pub fn is_single_line(s: &str) -> bool {
139+
s.chars().find(|&c| c == '\n').is_none()
140+
}
141+
142+
#[inline]
143+
pub fn first_line_contains_single_line_comment(s: &str) -> bool {
144+
s.lines().next().map_or(false, |l| l.contains("//"))
145+
}
146+
137147
#[inline]
138148
pub fn last_line_contains_single_line_comment(s: &str) -> bool {
139149
s.lines().last().map_or(false, |l| l.contains("//"))

Diff for: tests/source/enum.rs

+4
Original file line numberDiff line numberDiff line change
@@ -192,3 +192,7 @@ pub enum QlError {
192192
// (kind, input, expected)
193193
#[fail(display = "Could not find {}: Found: {}, expected: {:?}", 0, 1, 2)] ResolveError(&'static str, String, Option<String>),
194194
}
195+
196+
// #2594
197+
enum Foo {}
198+
enum Bar { }

Diff for: tests/target/configs/struct_field_align_threshold/20.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,12 @@ struct Foo {
255255
struct Foo {
256256
// trailing space ->
257257
}
258-
struct Foo { /* comment */ }
259-
struct Foo( /* comment */ );
258+
struct Foo {
259+
// comment
260+
}
261+
struct Foo(
262+
// comment
263+
);
260264

261265
struct LongStruct {
262266
a: A,

Diff for: tests/target/enum.rs

+4
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,7 @@ pub enum QlError {
258258
#[fail(display = "Could not find {}: Found: {}, expected: {:?}", 0, 1, 2)]
259259
ResolveError(&'static str, String, Option<String>),
260260
}
261+
262+
// #2594
263+
enum Foo {}
264+
enum Bar {}

Diff for: tests/target/issue-977.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
trait NameC {
55
// comment
66
}
7-
struct FooC { /* comment */ }
7+
struct FooC {
8+
// comment
9+
}
810
enum MooC {
911
// comment
1012
}

Diff for: tests/target/structs.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,12 @@ struct Foo {
228228
struct Foo {
229229
// trailing space ->
230230
}
231-
struct Foo { /* comment */ }
232-
struct Foo( /* comment */ );
231+
struct Foo {
232+
// comment
233+
}
234+
struct Foo(
235+
// comment
236+
);
233237

234238
struct LongStruct {
235239
a: A,

Diff for: tests/target/unions.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,9 @@ union Foo {
136136
union Foo {
137137
// trailing space ->
138138
}
139-
union Foo { /* comment */ }
139+
union Foo {
140+
// comment
141+
}
140142

141143
union LongUnion {
142144
a: A,

0 commit comments

Comments
 (0)