Skip to content

Commit fc15e9f

Browse files
authored
Merge pull request #2042 from topecongiro/refactoring
Refactorings
2 parents 5798fe6 + c7250d1 commit fc15e9f

File tree

5 files changed

+107
-139
lines changed

5 files changed

+107
-139
lines changed

src/chains.rs

Lines changed: 47 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@
2424
/// alignment).
2525
/// E.g., `let foo = { aaaa; bbb; ccc }.bar.baz();`, we would layout for the
2626
/// following values of `chain_indent`:
27+
/// Block:
28+
/// ```
29+
/// let foo = {
30+
/// aaaa;
31+
/// bbb;
32+
/// ccc
33+
/// }.bar
34+
/// .baz();
35+
/// ```
2736
/// Visual:
2837
/// ```
2938
/// let foo = {
@@ -34,46 +43,20 @@
3443
/// .bar
3544
/// .baz();
3645
/// ```
37-
/// Inherit:
38-
/// ```
39-
/// let foo = {
40-
/// aaaa;
41-
/// bbb;
42-
/// ccc
43-
/// }
44-
/// .bar
45-
/// .baz();
46-
/// ```
47-
/// Tabbed:
48-
/// ```
49-
/// let foo = {
50-
/// aaaa;
51-
/// bbb;
52-
/// ccc
53-
/// }
54-
/// .bar
55-
/// .baz();
56-
/// ```
5746
///
5847
/// If the first item in the chain is a block expression, we align the dots with
5948
/// the braces.
60-
/// Visual:
61-
/// ```
62-
/// let a = foo.bar
63-
/// .baz()
64-
/// .qux
65-
/// ```
66-
/// Inherit:
49+
/// Block:
6750
/// ```
6851
/// let a = foo.bar
69-
/// .baz()
70-
/// .qux
52+
/// .baz()
53+
/// .qux
7154
/// ```
72-
/// Tabbed:
55+
/// Visual:
7356
/// ```
7457
/// let a = foo.bar
75-
/// .baz()
76-
/// .qux
58+
/// .baz()
59+
/// .qux
7760
/// ```
7861
7962
use shape::Shape;
@@ -182,13 +165,23 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -
182165
let all_in_one_line = !parent_rewrite_contains_newline
183166
&& rewrites.iter().all(|s| !s.contains('\n'))
184167
&& almost_total < one_line_budget;
185-
let rewrite_last = || rewrite_chain_subexpr(last_subexpr, total_span, context, nested_shape);
168+
let last_shape = if rewrites.is_empty() {
169+
// We only have a single child.
170+
first_child_shape
171+
} else {
172+
match context.config.chain_indent() {
173+
IndentStyle::Visual => other_child_shape.sub_width(shape.rhs_overhead(context.config))?,
174+
IndentStyle::Block => other_child_shape,
175+
}
176+
};
177+
let last_shape = last_shape.sub_width(suffix_try_num)?;
178+
let rewrite_last = || rewrite_chain_subexpr(last_subexpr, total_span, context, last_shape);
186179
let (last_subexpr_str, fits_single_line) = if all_in_one_line || extend_last_subexr {
187180
parent_shape.offset_left(almost_total).map(|shape| {
188181
if let Some(rw) = rewrite_chain_subexpr(last_subexpr, total_span, context, shape) {
189182
let line_count = rw.lines().count();
190183
let fits_single_line = almost_total + first_line_width(&rw) <= one_line_budget;
191-
if (line_count >= 5 && fits_single_line) || extend_last_subexr {
184+
if fits_single_line && (line_count >= 5 || extend_last_subexr) {
192185
(Some(rw), true)
193186
} else {
194187
match rewrite_last() {
@@ -229,38 +222,37 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -
229222
connector.as_str()
230223
};
231224

232-
let subexpr_num = subexpr_list.len();
233225
let result = if is_small_parent && rewrites.len() > 1 {
234-
let second_connector = choose_first_connector(
235-
context,
236-
&rewrites[0],
237-
&rewrites[1],
238-
&connector,
239-
&subexpr_list[..subexpr_num - 1],
240-
false,
241-
);
226+
let second_connector = if fits_single_line || rewrites[1] == "?"
227+
|| last_line_extendable(&rewrites[0])
228+
|| context.config.chain_indent() == IndentStyle::Visual
229+
{
230+
""
231+
} else {
232+
&connector
233+
};
242234
format!(
243235
"{}{}{}{}{}",
244236
parent_rewrite,
245237
first_connector,
246238
rewrites[0],
247239
second_connector,
248-
join_rewrites(&rewrites[1..], &subexpr_list[..subexpr_num - 1], &connector)
240+
join_rewrites(&rewrites[1..], &connector)
249241
)
250242
} else {
251243
format!(
252244
"{}{}{}",
253245
parent_rewrite,
254246
first_connector,
255-
join_rewrites(&rewrites, subexpr_list, &connector)
247+
join_rewrites(&rewrites, &connector)
256248
)
257249
};
258250
let result = format!("{}{}", result, repeat_try(suffix_try_num));
259-
wrap_str(result, context.config.max_width(), shape)
260-
}
261-
262-
fn is_extendable_parent(context: &RewriteContext, parent_str: &str) -> bool {
263-
context.config.chain_indent() == IndentStyle::Block && last_line_extendable(parent_str)
251+
if context.config.chain_indent() == IndentStyle::Visual {
252+
wrap_str(result, context.config.max_width(), shape)
253+
} else {
254+
Some(result)
255+
}
264256
}
265257

266258
// True if the chain is only `?`s.
@@ -288,17 +280,14 @@ fn rewrite_try(
288280
Some(format!("{}{}", sub_expr, repeat_try(try_count)))
289281
}
290282

291-
fn join_rewrites(rewrites: &[String], subexps: &[ast::Expr], connector: &str) -> String {
283+
fn join_rewrites(rewrites: &[String], connector: &str) -> String {
292284
let mut rewrite_iter = rewrites.iter();
293285
let mut result = rewrite_iter.next().unwrap().clone();
294-
let mut subexpr_iter = subexps.iter().rev();
295-
subexpr_iter.next();
296286

297-
for (rewrite, expr) in rewrite_iter.zip(subexpr_iter) {
298-
match expr.node {
299-
ast::ExprKind::Try(_) => (),
300-
_ => result.push_str(connector),
301-
};
287+
for rewrite in rewrite_iter {
288+
if rewrite != "?" {
289+
result.push_str(connector);
290+
}
302291
result.push_str(&rewrite[..]);
303292
}
304293

@@ -431,32 +420,6 @@ fn is_try(expr: &ast::Expr) -> bool {
431420
}
432421
}
433422

434-
fn choose_first_connector<'a>(
435-
context: &RewriteContext,
436-
parent_str: &str,
437-
first_child_str: &str,
438-
connector: &'a str,
439-
subexpr_list: &[ast::Expr],
440-
extend: bool,
441-
) -> &'a str {
442-
if subexpr_list.is_empty() {
443-
""
444-
} else if extend || subexpr_list.last().map_or(false, is_try)
445-
|| is_extendable_parent(context, parent_str)
446-
{
447-
// 1 = ";", being conservative here.
448-
if last_line_width(parent_str) + first_line_width(first_child_str) + 1
449-
<= context.config.max_width()
450-
{
451-
""
452-
} else {
453-
connector
454-
}
455-
} else {
456-
connector
457-
}
458-
}
459-
460423
fn rewrite_method_call(
461424
method_name: ast::Ident,
462425
types: &[ptr::P<ast::Ty>],

src/expr.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -718,9 +718,7 @@ fn rewrite_closure_block(
718718
if block_str.matches('\n').count() <= block_threshold as usize
719719
&& !need_block_indent(&block_str, shape)
720720
{
721-
if let Some(block_str) = block_str.rewrite(context, shape) {
722-
return Some(format!("{} {}", prefix, block_str));
723-
}
721+
return Some(format!("{} {}", prefix, block_str));
724722
}
725723
}
726724
}

src/shape.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use std::borrow::Cow;
1112
use std::ops::{Add, Sub};
1213

1314
use Config;
@@ -21,6 +22,10 @@ pub struct Indent {
2122
pub alignment: usize,
2223
}
2324

25+
// INDENT_BUFFER.len() = 80
26+
const INDENT_BUFFER_LEN: usize = 80;
27+
const INDENT_BUFFER: &str =
28+
" ";
2429
impl Indent {
2530
pub fn new(block_indent: usize, alignment: usize) -> Indent {
2631
Indent {
@@ -68,21 +73,25 @@ impl Indent {
6873
self.block_indent + self.alignment
6974
}
7075

71-
pub fn to_string(&self, config: &Config) -> String {
76+
pub fn to_string(&self, config: &Config) -> Cow<'static, str> {
7277
let (num_tabs, num_spaces) = if config.hard_tabs() {
7378
(self.block_indent / config.tab_spaces(), self.alignment)
7479
} else {
7580
(0, self.width())
7681
};
7782
let num_chars = num_tabs + num_spaces;
78-
let mut indent = String::with_capacity(num_chars);
79-
for _ in 0..num_tabs {
80-
indent.push('\t')
81-
}
82-
for _ in 0..num_spaces {
83-
indent.push(' ')
83+
if num_tabs == 0 && num_chars <= INDENT_BUFFER_LEN {
84+
Cow::from(&INDENT_BUFFER[0..num_chars])
85+
} else {
86+
let mut indent = String::with_capacity(num_chars);
87+
for _ in 0..num_tabs {
88+
indent.push('\t')
89+
}
90+
for _ in 0..num_spaces {
91+
indent.push(' ')
92+
}
93+
Cow::from(indent)
8494
}
85-
indent
8695
}
8796
}
8897

src/types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ impl Rewrite for ast::TyParamBounds {
550550
let strs = self.iter()
551551
.map(|b| b.rewrite(context, shape))
552552
.collect::<Option<Vec<_>>>()?;
553-
join_bounds(context, shape, &strs).rewrite(context, shape)
553+
Some(join_bounds(context, shape, &strs))
554554
}
555555
}
556556

@@ -660,7 +660,7 @@ impl Rewrite for ast::Ty {
660660
mut_str,
661661
mt.ty.rewrite(
662662
context,
663-
Shape::legacy(budget, shape.indent + 1 + mut_len),
663+
Shape::legacy(budget, shape.indent + 1 + mut_len)
664664
)?
665665
)
666666
}

src/utils.rs

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use syntax::ast::{self, Attribute, MetaItem, MetaItemKind, NestedMetaItem, Neste
1515
Path, Visibility};
1616
use syntax::codemap::{BytePos, Span, NO_EXPANSION};
1717

18-
use rewrite::{Rewrite, RewriteContext};
18+
use rewrite::RewriteContext;
1919
use shape::Shape;
2020

2121
// When we get scoped annotations, we should have rustfmt::skip.
@@ -171,12 +171,18 @@ pub fn trimmed_last_line_width(s: &str) -> usize {
171171

172172
#[inline]
173173
pub fn last_line_extendable(s: &str) -> bool {
174-
s.lines().last().map_or(false, |s| {
175-
s.ends_with("\"#")
176-
|| s.trim()
177-
.chars()
178-
.all(|c| c == ')' || c == ']' || c == '}' || c == '?')
179-
})
174+
if s.ends_with("\"#") {
175+
return true;
176+
}
177+
for c in s.chars().rev() {
178+
match c {
179+
')' | ']' | '}' | '?' => continue,
180+
'\n' => break,
181+
_ if c.is_whitespace() => continue,
182+
_ => return false,
183+
}
184+
}
185+
true
180186
}
181187

182188
#[inline]
@@ -390,45 +396,37 @@ macro_rules! skip_out_of_file_lines_range_visitor {
390396
}
391397
}
392398

393-
// Wraps string-like values in an Option. Returns Some when the string adheres
394-
// to the Rewrite constraints defined for the Rewrite trait and else otherwise.
395-
pub fn wrap_str<S: AsRef<str>>(s: S, max_width: usize, shape: Shape) -> Option<S> {
396-
{
397-
let snippet = s.as_ref();
398-
399-
if !snippet.is_empty() {
400-
if !snippet.contains('\n') && snippet.len() > shape.width {
401-
return None;
402-
} else {
403-
let mut lines = snippet.lines();
404-
405-
if lines.next().unwrap().len() > shape.width {
406-
return None;
407-
}
408-
409-
// The other lines must fit within the maximum width.
410-
if lines.any(|line| line.len() > max_width) {
411-
return None;
412-
}
413-
414-
// `width` is the maximum length of the last line, excluding
415-
// indentation.
416-
// A special check for the last line, since the caller may
417-
// place trailing characters on this line.
418-
if snippet.lines().rev().next().unwrap().len() > shape.used_width() + shape.width {
419-
return None;
420-
}
421-
}
422-
}
399+
// Wraps String in an Option. Returns Some when the string adheres to the
400+
// Rewrite constraints defined for the Rewrite trait and else otherwise.
401+
pub fn wrap_str(s: String, max_width: usize, shape: Shape) -> Option<String> {
402+
if is_valid_str(&s, max_width, shape) {
403+
Some(s)
404+
} else {
405+
None
423406
}
424-
425-
Some(s)
426407
}
427408

428-
impl Rewrite for String {
429-
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
430-
wrap_str(self, context.config.max_width(), shape).map(ToOwned::to_owned)
409+
fn is_valid_str(snippet: &str, max_width: usize, shape: Shape) -> bool {
410+
if !snippet.is_empty() {
411+
// First line must fits with `shape.width`.
412+
if first_line_width(snippet) > shape.width {
413+
return false;
414+
}
415+
// If the snippet does not include newline, we are done.
416+
if first_line_width(snippet) == snippet.len() {
417+
return true;
418+
}
419+
// The other lines must fit within the maximum width.
420+
if snippet.lines().skip(1).any(|line| line.len() > max_width) {
421+
return false;
422+
}
423+
// A special check for the last line, since the caller may
424+
// place trailing characters on this line.
425+
if last_line_width(snippet) > shape.used_width() + shape.width {
426+
return false;
427+
}
431428
}
429+
true
432430
}
433431

434432
#[inline]

0 commit comments

Comments
 (0)