Skip to content

Commit c337507

Browse files
committed
Merge pull request #137 from nrc/struct-lit-opt
Options for formatting struct literals
2 parents fa4ef4d + a32b0e7 commit c337507

17 files changed

+309
-131
lines changed

src/changes.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@ pub struct ChangeSet<'a> {
3535
impl<'a> ChangeSet<'a> {
3636
// Create a new ChangeSet for a given libsyntax CodeMap.
3737
pub fn from_codemap(codemap: &'a CodeMap) -> ChangeSet<'a> {
38-
let mut result = ChangeSet { file_map: HashMap::new(),
39-
codemap: codemap,
40-
file_spans: Vec::with_capacity(codemap.files.borrow().len()), };
38+
let mut result = ChangeSet {
39+
file_map: HashMap::new(),
40+
codemap: codemap,
41+
file_spans: Vec::with_capacity(codemap.files.borrow().len()),
42+
};
4143

4244
for f in codemap.files.borrow().iter() {
4345
// Use the length of the file as a heuristic for how much space we

src/comment.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@ pub fn rewrite_comment(orig: &str, block_style: bool, width: usize, offset: usiz
2424
let max_chars = width.checked_sub(closer.len()).unwrap_or(1)
2525
.checked_sub(opener.len()).unwrap_or(1);
2626

27-
let fmt = StringFormat { opener: "",
28-
closer: "",
29-
line_start: line_start,
30-
line_end: "",
31-
width: max_chars,
32-
offset: offset + opener.len() - line_start.len(),
33-
trim_end: true, };
27+
let fmt = StringFormat {
28+
opener: "",
29+
closer: "",
30+
line_start: line_start,
31+
line_end: "",
32+
width: max_chars,
33+
offset: offset + opener.len() - line_start.len(),
34+
trim_end: true,
35+
};
3436

3537
let indent_str = make_indent(offset);
3638
let line_breaks = s.chars().filter(|&c| c == '\n').count();

src/config.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
extern crate toml;
1212

13-
use {NewlineStyle, BraceStyle, ReturnIndent};
13+
use {NewlineStyle, BraceStyle, ReturnIndent, StructLitStyle};
1414
use lists::SeparatorTactic;
1515
use issues::ReportTactic;
1616

@@ -26,6 +26,7 @@ pub struct Config {
2626
pub fn_args_paren_newline: bool,
2727
pub struct_trailing_comma: SeparatorTactic,
2828
pub struct_lit_trailing_comma: SeparatorTactic,
29+
pub struct_lit_style: StructLitStyle,
2930
pub enum_trailing_comma: bool,
3031
pub report_todo: ReportTactic,
3132
pub report_fixme: ReportTactic,
@@ -35,6 +36,14 @@ pub struct Config {
3536
impl Config {
3637
pub fn from_toml(toml: &str) -> Config {
3738
let parsed = toml.parse().unwrap();
38-
toml::decode(parsed).unwrap()
39+
match toml::decode(parsed) {
40+
Some(decoded) => decoded,
41+
None => {
42+
println!("Decoding config file failed. Config:\n{}", toml);
43+
let parsed: toml::Value = toml.parse().unwrap();
44+
println!("\n\nParsed:\n{:?}", parsed);
45+
panic!();
46+
}
47+
}
3948
}
4049
}

src/default.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ fn_brace_style = "SameLineWhere"
77
fn_return_indent = "WithArgs"
88
fn_args_paren_newline = true
99
struct_trailing_comma = "Vertical"
10+
struct_lit_style = "BlockIndent"
1011
struct_lit_trailing_comma = "Vertical"
1112
enum_trailing_comma = true
1213
report_todo = "Always"

src/expr.rs

Lines changed: 63 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use rewrite::{Rewrite, RewriteContext};
1212
use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic};
1313
use string::{StringFormat, rewrite_string};
14+
use StructLitStyle;
1415
use utils::{span_after, make_indent};
1516
use visitor::FmtVisitor;
1617

@@ -100,13 +101,15 @@ fn rewrite_string_lit(context: &RewriteContext,
100101
if l_loc.line == r_loc.line && r_loc.col.to_usize() <= context.config.max_width {
101102
return context.codemap.span_to_snippet(span).ok();
102103
}
103-
let fmt = StringFormat { opener: "\"",
104-
closer: "\"",
105-
line_start: " ",
106-
line_end: "\\",
107-
width: width,
108-
offset: offset,
109-
trim_end: false, };
104+
let fmt = StringFormat {
105+
opener: "\"",
106+
closer: "\"",
107+
line_start: " ",
108+
line_end: "\\",
109+
width: width,
110+
offset: offset,
111+
trim_end: false,
112+
};
110113

111114
Some(rewrite_string(&s.escape_default(), &fmt))
112115
}
@@ -146,13 +149,15 @@ fn rewrite_call(context: &RewriteContext,
146149
callee.span.hi + BytePos(1),
147150
span.hi);
148151

149-
let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical,
150-
separator: ",",
151-
trailing_separator: SeparatorTactic::Never,
152-
indent: offset,
153-
h_width: remaining_width,
154-
v_width: remaining_width,
155-
ends_with_newline: true, };
152+
let fmt = ListFormatting {
153+
tactic: ListTactic::HorizontalVertical,
154+
separator: ",",
155+
trailing_separator: SeparatorTactic::Never,
156+
indent: offset,
157+
h_width: remaining_width,
158+
v_width: remaining_width,
159+
ends_with_newline: true,
160+
};
156161

157162
Some(format!("{}({})", callee_str, write_list(&items, &fmt)))
158163
}
@@ -187,9 +192,19 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext,
187192
}
188193

189194
let path_str = pprust::path_to_string(path);
190-
// Foo { a: Foo } - indent is +3, width is -5.
191-
let indent = offset + path_str.len() + 3;
192-
let budget = width - (path_str.len() + 5);
195+
let (indent, h_budget, v_budget) = match context.config.struct_lit_style {
196+
StructLitStyle::VisualIndent => {
197+
// Foo { a: Foo } - indent is +3, width is -5.
198+
let budget = width - (path_str.len() + 5);
199+
(offset + path_str.len() + 3, budget, budget)
200+
}
201+
StructLitStyle::BlockIndent => {
202+
// If we are all on one line, then we'll ignore the indent, and we
203+
// have a smaller budget.
204+
let indent = context.block_indent + context.config.tab_spaces;
205+
(indent, width - (path_str.len() + 5), width - indent)
206+
}
207+
};
193208

194209
let field_iter = fields.into_iter().map(StructLitField::Regular)
195210
.chain(base.into_iter().map(StructLitField::Base));
@@ -215,13 +230,13 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext,
215230
|item| {
216231
match *item {
217232
StructLitField::Regular(ref field) => {
218-
rewrite_field(context, &field, budget, indent)
233+
rewrite_field(context, &field, h_budget, indent)
219234
.unwrap_or(context.codemap.span_to_snippet(field.span)
220235
.unwrap())
221236
},
222237
StructLitField::Base(ref expr) => {
223238
// 2 = ..
224-
expr.rewrite(context, budget - 2, indent + 2)
239+
expr.rewrite(context, h_budget - 2, indent + 2)
225240
.map(|s| format!("..{}", s))
226241
.unwrap_or(context.codemap.span_to_snippet(expr.span)
227242
.unwrap())
@@ -231,24 +246,32 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext,
231246
span_after(span, "{", context.codemap),
232247
span.hi);
233248

234-
let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical,
235-
separator: ",",
236-
trailing_separator: if base.is_some() {
249+
let fmt = ListFormatting {
250+
tactic: ListTactic::HorizontalVertical,
251+
separator: ",",
252+
trailing_separator: if base.is_some() {
237253
SeparatorTactic::Never
238254
} else {
239255
context.config.struct_lit_trailing_comma
240256
},
241-
indent: indent,
242-
h_width: budget,
243-
v_width: budget,
244-
ends_with_newline: true, };
257+
indent: indent,
258+
h_width: h_budget,
259+
v_width: v_budget,
260+
ends_with_newline: true,
261+
};
245262
let fields_str = write_list(&items, &fmt);
246-
Some(format!("{} {{ {} }}", path_str, fields_str))
247263

248-
// FIXME if the usual multi-line layout is too wide, we should fall back to
249-
// Foo {
250-
// a: ...,
251-
// }
264+
match context.config.struct_lit_style {
265+
StructLitStyle::BlockIndent if fields_str.contains('\n') => {
266+
let inner_indent = make_indent(context.block_indent + context.config.tab_spaces);
267+
let outer_indent = make_indent(context.block_indent);
268+
Some(format!("{} {{\n{}{}\n{}}}", path_str, inner_indent, fields_str, outer_indent))
269+
}
270+
_ => Some(format!("{} {{ {} }}", path_str, fields_str)),
271+
}
272+
273+
// FIXME if context.config.struct_lit_style == VisualIndent, but we run out
274+
// of space, we should fall back to BlockIndent.
252275
}
253276

254277
fn rewrite_field(context: &RewriteContext,
@@ -291,13 +314,15 @@ fn rewrite_tuple_lit(context: &RewriteContext,
291314
span.lo + BytePos(1), // Remove parens
292315
span.hi - BytePos(1));
293316

294-
let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical,
295-
separator: ",",
296-
trailing_separator: SeparatorTactic::Never,
297-
indent: indent,
298-
h_width: width - 2,
299-
v_width: width - 2,
300-
ends_with_newline: true, };
317+
let fmt = ListFormatting {
318+
tactic: ListTactic::HorizontalVertical,
319+
separator: ",",
320+
trailing_separator: SeparatorTactic::Never,
321+
indent: indent,
322+
h_width: width - 2,
323+
v_width: width - 2,
324+
ends_with_newline: true,
325+
};
301326

302327
Some(format!("({})", write_list(&items, &fmt)))
303328
}

src/imports.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,15 @@ impl<'a> FmtVisitor<'a> {
7171
let remaining_line_budget = one_line_budget.checked_sub(used_width).unwrap_or(0);
7272
let remaining_multi_budget = multi_line_budget.checked_sub(used_width).unwrap_or(0);
7373

74-
let fmt = ListFormatting { tactic: ListTactic::Mixed,
75-
separator: ",",
76-
trailing_separator: SeparatorTactic::Never,
77-
indent: block_indent + indent,
78-
h_width: remaining_line_budget,
79-
v_width: remaining_multi_budget,
80-
ends_with_newline: true, };
74+
let fmt = ListFormatting {
75+
tactic: ListTactic::Mixed,
76+
separator: ",",
77+
trailing_separator: SeparatorTactic::Never,
78+
indent: block_indent + indent,
79+
h_width: remaining_line_budget,
80+
v_width: remaining_multi_budget,
81+
ends_with_newline: true,
82+
};
8183

8284
let mut items = itemize_list(self.codemap,
8385
vec![ListItem::from_str("")], /* Dummy value, explanation

src/issues.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,11 @@ pub struct BadIssueSeeker {
9696

9797
impl BadIssueSeeker {
9898
pub fn new(report_todo: ReportTactic, report_fixme: ReportTactic) -> BadIssueSeeker {
99-
BadIssueSeeker { state: Seeking::Issue { todo_idx: 0, fixme_idx: 0 },
100-
report_todo: report_todo,
101-
report_fixme: report_fixme, }
99+
BadIssueSeeker {
100+
state: Seeking::Issue { todo_idx: 0, fixme_idx: 0 },
101+
report_todo: report_todo,
102+
report_fixme: report_fixme,
103+
}
102104
}
103105

104106
// Check whether or not the current char is conclusive evidence for an

src/items.rs

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -305,13 +305,15 @@ impl<'a> FmtVisitor<'a> {
305305
item.item = arg;
306306
}
307307

308-
let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical,
309-
separator: ",",
310-
trailing_separator: SeparatorTactic::Never,
311-
indent: arg_indent,
312-
h_width: one_line_budget,
313-
v_width: multi_line_budget,
314-
ends_with_newline: true, };
308+
let fmt = ListFormatting {
309+
tactic: ListTactic::HorizontalVertical,
310+
separator: ",",
311+
trailing_separator: SeparatorTactic::Never,
312+
indent: arg_indent,
313+
h_width: one_line_budget,
314+
v_width: multi_line_budget,
315+
ends_with_newline: true,
316+
};
315317

316318
write_list(&arg_items, &fmt)
317319
}
@@ -567,13 +569,15 @@ impl<'a> FmtVisitor<'a> {
567569

568570
// 1 = ,
569571
let budget = self.config.ideal_width - offset + self.config.tab_spaces - 1;
570-
let fmt = ListFormatting { tactic: tactic,
571-
separator: ",",
572-
trailing_separator: self.config.struct_trailing_comma,
573-
indent: offset + self.config.tab_spaces,
574-
h_width: self.config.max_width,
575-
v_width: budget,
576-
ends_with_newline: false, };
572+
let fmt = ListFormatting {
573+
tactic: tactic,
574+
separator: ",",
575+
trailing_separator: self.config.struct_trailing_comma,
576+
indent: offset + self.config.tab_spaces,
577+
h_width: self.config.max_width,
578+
v_width: budget,
579+
ends_with_newline: false,
580+
};
577581

578582
result.push_str(&write_list(&items, &fmt));
579583

@@ -708,13 +712,15 @@ impl<'a> FmtVisitor<'a> {
708712
item.item = ty;
709713
}
710714

711-
let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical,
712-
separator: ",",
713-
trailing_separator: SeparatorTactic::Never,
714-
indent: offset + 1,
715-
h_width: budget,
716-
v_width: budget,
717-
ends_with_newline: true, };
715+
let fmt = ListFormatting {
716+
tactic: ListTactic::HorizontalVertical,
717+
separator: ",",
718+
trailing_separator: SeparatorTactic::Never,
719+
indent: offset + 1,
720+
h_width: budget,
721+
v_width: budget,
722+
ends_with_newline: true,
723+
};
718724
result.push_str(&write_list(&items, &fmt));
719725

720726
result.push('>');
@@ -749,13 +755,15 @@ impl<'a> FmtVisitor<'a> {
749755
span_end);
750756

751757
let budget = self.config.ideal_width + self.config.leeway - indent - 10;
752-
let fmt = ListFormatting { tactic: ListTactic::Vertical,
753-
separator: ",",
754-
trailing_separator: SeparatorTactic::Never,
755-
indent: indent + 10,
756-
h_width: budget,
757-
v_width: budget,
758-
ends_with_newline: true, };
758+
let fmt = ListFormatting {
759+
tactic: ListTactic::Vertical,
760+
separator: ",",
761+
trailing_separator: SeparatorTactic::Never,
762+
indent: indent + 10,
763+
h_width: budget,
764+
v_width: budget,
765+
ends_with_newline: true,
766+
};
759767
result.push_str(&write_list(&items, &fmt));
760768

761769
result

src/lib.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,19 @@ pub enum ReturnIndent {
111111

112112
impl_enum_decodable!(ReturnIndent, WithArgs, WithWhereClause);
113113

114+
// How to stle a struct literal.
115+
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
116+
pub enum StructLitStyle {
117+
// First line on the same line as the opening brace, all lines aligned with
118+
// the first line.
119+
VisualIndent,
120+
// First line is on a new line and all lines align with block indent.
121+
BlockIndent,
122+
// FIXME Maybe we should also have an option to align types.
123+
}
124+
125+
impl_enum_decodable!(StructLitStyle, VisualIndent, BlockIndent);
126+
114127
enum ErrorKind {
115128
// Line has exceeded character limit
116129
LineOverflow,

0 commit comments

Comments
 (0)