Skip to content

Commit 6ca2756

Browse files
committed
Merge pull request #238 from nrc/fn-decl
Customisation of function decls
2 parents 0264d92 + 8d81aa1 commit 6ca2756

File tree

14 files changed

+400
-19
lines changed

14 files changed

+400
-19
lines changed

src/config.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
extern crate toml;
1212

1313
use {NewlineStyle, BraceStyle, ReturnIndent, StructLitStyle};
14-
use lists::SeparatorTactic;
14+
use lists::{SeparatorTactic, ListTactic};
1515
use issues::ReportTactic;
1616

1717
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
@@ -26,6 +26,25 @@ pub enum BlockIndentStyle {
2626

2727
impl_enum_decodable!(BlockIndentStyle, Inherit, Tabbed, Visual);
2828

29+
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
30+
pub enum Density {
31+
// Fit as much on one line as possible.
32+
Compressed,
33+
// Use more lines.
34+
Tall,
35+
}
36+
37+
impl_enum_decodable!(Density, Compressed, Tall);
38+
39+
impl Density {
40+
pub fn to_list_tactic(self) -> ListTactic {
41+
match self {
42+
Density::Compressed => ListTactic::Mixed,
43+
Density::Tall => ListTactic::HorizontalVertical,
44+
}
45+
}
46+
}
47+
2948
macro_rules! create_config {
3049
($($i:ident: $ty:ty),+ $(,)*) => (
3150
#[derive(RustcDecodable, Clone)]
@@ -70,6 +89,14 @@ create_config! {
7089
fn_brace_style: BraceStyle,
7190
fn_return_indent: ReturnIndent,
7291
fn_args_paren_newline: bool,
92+
fn_args_layout: Density,
93+
fn_arg_indent: BlockIndentStyle,
94+
where_density: Density, // Should we at least try to put the where clause on the same line as
95+
// the rest of the function decl?
96+
where_indent: BlockIndentStyle, // Visual will be treated like Tabbed
97+
where_layout: ListTactic,
98+
where_pred_indent: BlockIndentStyle,
99+
generics_indent: BlockIndentStyle,
73100
struct_trailing_comma: SeparatorTactic,
74101
struct_lit_trailing_comma: SeparatorTactic,
75102
struct_lit_style: StructLitStyle,
@@ -95,6 +122,13 @@ impl Default for Config {
95122
fn_brace_style: BraceStyle::SameLineWhere,
96123
fn_return_indent: ReturnIndent::WithArgs,
97124
fn_args_paren_newline: true,
125+
fn_args_layout: Density::Tall,
126+
fn_arg_indent: BlockIndentStyle::Visual,
127+
where_density: Density::Tall,
128+
where_indent: BlockIndentStyle::Tabbed,
129+
where_layout: ListTactic::Vertical,
130+
where_pred_indent: BlockIndentStyle::Visual,
131+
generics_indent: BlockIndentStyle::Visual,
98132
struct_trailing_comma: SeparatorTactic::Vertical,
99133
struct_lit_trailing_comma: SeparatorTactic::Vertical,
100134
struct_lit_style: StructLitStyle::BlockIndent,

src/items.rs

Lines changed: 75 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use expr::rewrite_assign_rhs;
1818
use comment::FindUncommented;
1919
use visitor::FmtVisitor;
2020
use rewrite::Rewrite;
21-
use config::Config;
21+
use config::{Config, BlockIndentStyle, Density};
2222

2323
use syntax::{ast, abi};
2424
use syntax::codemap::{self, Span, BytePos};
@@ -99,7 +99,7 @@ impl<'a> FmtVisitor<'a> {
9999
vis: ast::Visibility,
100100
span: Span)
101101
-> String {
102-
let newline_brace = self.newline_for_brace(&generics.where_clause);
102+
let mut newline_brace = self.newline_for_brace(&generics.where_clause);
103103

104104
let mut result = self.rewrite_fn_base(indent,
105105
ident,
@@ -113,6 +113,10 @@ impl<'a> FmtVisitor<'a> {
113113
span,
114114
newline_brace);
115115

116+
if self.config.fn_brace_style != BraceStyle::AlwaysNextLine && !result.contains('\n') {
117+
newline_brace = false;
118+
}
119+
116120
// Prepare for the function body by possibly adding a newline and
117121
// indent.
118122
// FIXME we'll miss anything between the end of the signature and the
@@ -196,6 +200,7 @@ impl<'a> FmtVisitor<'a> {
196200
// Generics.
197201
let generics_indent = indent + result.len();
198202
result.push_str(&self.rewrite_generics(generics,
203+
indent,
199204
generics_indent,
200205
codemap::mk_sp(span.lo,
201206
span_for_return(&fd.output).lo)));
@@ -237,6 +242,7 @@ impl<'a> FmtVisitor<'a> {
237242
explicit_self,
238243
one_line_budget,
239244
multi_line_budget,
245+
indent,
240246
arg_indent,
241247
args_span));
242248
result.push(')');
@@ -279,10 +285,18 @@ impl<'a> FmtVisitor<'a> {
279285
}
280286
}
281287

288+
let where_density = if self.config.where_density == Density::Compressed &&
289+
!result.contains('\n') {
290+
Density::Compressed
291+
} else {
292+
Density::Tall
293+
};
294+
282295
// Where clause.
283296
result.push_str(&self.rewrite_where_clause(where_clause,
284297
self.config,
285298
indent,
299+
where_density,
286300
span.hi));
287301

288302
result
@@ -293,6 +307,7 @@ impl<'a> FmtVisitor<'a> {
293307
explicit_self: Option<&ast::ExplicitSelf>,
294308
one_line_budget: usize,
295309
multi_line_budget: usize,
310+
indent: usize,
296311
arg_indent: usize,
297312
span: Span)
298313
-> String {
@@ -341,11 +356,17 @@ impl<'a> FmtVisitor<'a> {
341356
item.item = arg;
342357
}
343358

359+
let indent = match self.config.fn_arg_indent {
360+
BlockIndentStyle::Inherit => indent,
361+
BlockIndentStyle::Tabbed => indent + self.config.tab_spaces,
362+
BlockIndentStyle::Visual => arg_indent,
363+
};
364+
344365
let fmt = ListFormatting {
345-
tactic: ListTactic::HorizontalVertical,
366+
tactic: self.config.fn_args_layout.to_list_tactic(),
346367
separator: ",",
347368
trailing_separator: SeparatorTactic::Never,
348-
indent: arg_indent,
369+
indent: indent,
349370
h_width: one_line_budget,
350371
v_width: multi_line_budget,
351372
ends_with_newline: false,
@@ -424,6 +445,7 @@ impl<'a> FmtVisitor<'a> {
424445
let body_start = span.lo + BytePos(enum_snippet.find_uncommented("{").unwrap() as u32 + 1);
425446
let generics_str = self.format_generics(generics,
426447
" {",
448+
self.block_indent,
427449
self.block_indent + self.config.tab_spaces,
428450
codemap::mk_sp(span.lo,
429451
body_start));
@@ -565,6 +587,7 @@ impl<'a> FmtVisitor<'a> {
565587
let generics_str = match generics {
566588
Some(g) => self.format_generics(g,
567589
opener,
590+
offset,
568591
offset + header_str.len(),
569592
codemap::mk_sp(span.lo,
570593
struct_def.fields[0].span.lo)),
@@ -662,14 +685,16 @@ impl<'a> FmtVisitor<'a> {
662685
generics: &ast::Generics,
663686
opener: &str,
664687
offset: usize,
688+
generics_offset: usize,
665689
span: Span)
666690
-> String {
667-
let mut result = self.rewrite_generics(generics, offset, span);
691+
let mut result = self.rewrite_generics(generics, offset, generics_offset, span);
668692

669693
if !generics.where_clause.predicates.is_empty() || result.contains('\n') {
670694
result.push_str(&self.rewrite_where_clause(&generics.where_clause,
671695
self.config,
672696
self.block_indent,
697+
Density::Tall,
673698
span.hi));
674699
result.push_str(&make_indent(self.block_indent));
675700
result.push('\n');
@@ -714,7 +739,12 @@ impl<'a> FmtVisitor<'a> {
714739
}
715740
}
716741

717-
fn rewrite_generics(&self, generics: &ast::Generics, offset: usize, span: Span) -> String {
742+
fn rewrite_generics(&self,
743+
generics: &ast::Generics,
744+
offset: usize,
745+
generics_offset: usize,
746+
span: Span)
747+
-> String {
718748
// FIXME convert bounds to where clauses where they get too big or if
719749
// there is a where clause at all.
720750
let lifetimes: &[_] = &generics.lifetimes;
@@ -723,18 +753,24 @@ impl<'a> FmtVisitor<'a> {
723753
return String::new();
724754
}
725755

726-
let budget = self.config.max_width - offset - 2;
756+
let offset = match self.config.generics_indent {
757+
BlockIndentStyle::Inherit => offset,
758+
BlockIndentStyle::Tabbed => offset + self.config.tab_spaces,
759+
// 1 = <
760+
BlockIndentStyle::Visual => generics_offset + 1,
761+
};
762+
763+
let h_budget = self.config.max_width - generics_offset - 2;
727764
// TODO might need to insert a newline if the generics are really long
728765

729766
// Strings for the generics.
730-
// 1 = <
731767
let context = self.get_context();
732768
// FIXME: don't unwrap
733769
let lt_strs = lifetimes.iter().map(|lt| {
734-
lt.rewrite(&context, budget, offset + 1).unwrap()
770+
lt.rewrite(&context, h_budget, offset).unwrap()
735771
});
736772
let ty_strs = tys.iter().map(|ty_param| {
737-
ty_param.rewrite(&context, budget, offset + 1).unwrap()
773+
ty_param.rewrite(&context, h_budget, offset).unwrap()
738774
});
739775

740776
// Extract comments between generics.
@@ -762,7 +798,7 @@ impl<'a> FmtVisitor<'a> {
762798
item.item = ty;
763799
}
764800

765-
let fmt = ListFormatting::for_fn(budget, offset + 1);
801+
let fmt = ListFormatting::for_fn(h_budget, offset);
766802

767803
format!("<{}>", write_list(&items, &fmt))
768804
}
@@ -771,15 +807,29 @@ impl<'a> FmtVisitor<'a> {
771807
where_clause: &ast::WhereClause,
772808
config: &Config,
773809
indent: usize,
810+
density: Density,
774811
span_end: BytePos)
775812
-> String {
776813
if where_clause.predicates.is_empty() {
777814
return String::new();
778815
}
779816

817+
let extra_indent = match self.config.where_indent {
818+
BlockIndentStyle::Inherit => 0,
819+
BlockIndentStyle::Tabbed | BlockIndentStyle::Visual => config.tab_spaces,
820+
};
821+
780822
let context = self.get_context();
781-
// 6 = "where ".len()
782-
let offset = indent + config.tab_spaces + 6;
823+
824+
let offset = match self.config.where_pred_indent {
825+
BlockIndentStyle::Inherit => indent + extra_indent,
826+
BlockIndentStyle::Tabbed => indent + extra_indent + config.tab_spaces,
827+
// 6 = "where ".len()
828+
BlockIndentStyle::Visual => indent + extra_indent + 6,
829+
};
830+
// FIXME: if where_pred_indent != Visual, then the budgets below might
831+
// be out by a char or two.
832+
783833
let budget = self.config.ideal_width + self.config.leeway - offset;
784834
let span_start = span_for_where_pred(&where_clause.predicates[0]).lo;
785835
let items = itemize_list(self.codemap,
@@ -795,18 +845,25 @@ impl<'a> FmtVisitor<'a> {
795845
span_end);
796846

797847
let fmt = ListFormatting {
798-
tactic: ListTactic::Vertical,
848+
tactic: self.config.where_layout,
799849
separator: ",",
800850
trailing_separator: SeparatorTactic::Never,
801851
indent: offset,
802852
h_width: budget,
803853
v_width: budget,
804854
ends_with_newline: true,
805855
};
806-
807-
format!("\n{}where {}",
808-
make_indent(indent + config.tab_spaces),
809-
write_list(&items.collect::<Vec<_>>(), &fmt))
856+
let preds_str = write_list(&items.collect::<Vec<_>>(), &fmt);
857+
858+
// 9 = " where ".len() + " {".len()
859+
if density == Density::Tall || preds_str.contains('\n') ||
860+
indent + 9 + preds_str.len() > self.config.max_width {
861+
format!("\n{}where {}",
862+
make_indent(indent + extra_indent),
863+
preds_str)
864+
} else {
865+
format!(" where {}", preds_str)
866+
}
810867
}
811868

812869
fn rewrite_return(&self, ret: &ast::FunctionRetTy) -> String {

src/lists.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ pub enum ListTactic {
2828
Mixed,
2929
}
3030

31+
impl_enum_decodable!(ListTactic, Vertical, Horizontal, HorizontalVertical, Mixed);
32+
3133
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
3234
pub enum SeparatorTactic {
3335
Always,

tests/config/small_tabs.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ newline_style = "Unix"
66
fn_brace_style = "SameLineWhere"
77
fn_return_indent = "WithArgs"
88
fn_args_paren_newline = true
9+
fn_args_layout = "Tall"
10+
fn_arg_indent = "Visual"
11+
where_density = "Tall"
12+
where_indent = "Tabbed"
13+
where_layout = "Vertical"
14+
where_pred_indent = "Visual"
15+
generics_indent = "Visual"
916
struct_trailing_comma = "Vertical"
1017
struct_lit_trailing_comma = "Vertical"
1118
struct_lit_style = "BlockIndent"

tests/source/fn-custom-2.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// rustfmt-fn_arg_indent: Inherit
2+
// rustfmt-generics_indent: Tabbed
3+
// rustfmt-where_indent: Inherit
4+
// rustfmt-where_layout: Mixed
5+
// Test different indents.
6+
7+
fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) {
8+
foo();
9+
}
10+
11+
fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) {
12+
bar();
13+
}
14+
15+
fn baz() where X: TTTTTTTT {
16+
baz();
17+
}
18+
19+
fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT {
20+
baz();
21+
}
22+
23+
impl Foo {
24+
fn foo(self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) {
25+
foo();
26+
}
27+
28+
fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) {
29+
bar();
30+
}
31+
32+
fn baz() where X: TTTTTTTT {
33+
baz();
34+
}
35+
}
36+
37+
struct Foo<TTTTTTTTTTTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUU, VVVVVVVVVVVVVVVVVVVVVVVVVVV, WWWWWWWWWWWWWWWWWWWWWWWW> {
38+
foo: Foo,
39+
}

0 commit comments

Comments
 (0)