diff --git a/rustfmt-core/src/comment.rs b/rustfmt-core/src/comment.rs index 67678f59074..14749d4db12 100644 --- a/rustfmt-core/src/comment.rs +++ b/rustfmt-core/src/comment.rs @@ -10,7 +10,7 @@ // Formatting and tools for comments. -use std::{self, iter}; +use std::{self, iter, borrow::Cow}; use syntax::codemap::Span; @@ -154,6 +154,9 @@ pub fn combine_strs_with_missing_comments( shape: Shape, allow_extend: bool, ) -> Option { + let mut result = + String::with_capacity(prev_str.len() + next_str.len() + shape.indent.width() + 128); + result.push_str(prev_str); let mut allow_one_line = !prev_str.contains('\n') && !next_str.contains('\n'); let first_sep = if prev_str.is_empty() || next_str.is_empty() { "" @@ -163,20 +166,18 @@ pub fn combine_strs_with_missing_comments( let mut one_line_width = last_line_width(prev_str) + first_line_width(next_str) + first_sep.len(); - let indent_str = shape.indent.to_string(context.config); + let config = context.config; + let indent = shape.indent; let missing_comment = rewrite_missing_comment(span, shape, context)?; if missing_comment.is_empty() { if allow_extend && prev_str.len() + first_sep.len() + next_str.len() <= shape.width { - return Some(format!("{}{}{}", prev_str, first_sep, next_str)); - } else { - let sep = if prev_str.is_empty() { - String::new() - } else { - String::from("\n") + &indent_str - }; - return Some(format!("{}{}{}", prev_str, sep, next_str)); + result.push_str(first_sep); + } else if !prev_str.is_empty() { + result.push_str(&indent.to_string_with_newline(config)) } + result.push_str(next_str); + return Some(result); } // We have a missing comment between the first expression and the second expression. @@ -193,32 +194,35 @@ pub fn combine_strs_with_missing_comments( one_line_width -= first_sep.len(); let first_sep = if prev_str.is_empty() || missing_comment.is_empty() { - String::new() + Cow::from("") } else { let one_line_width = last_line_width(prev_str) + first_line_width(&missing_comment) + 1; if prefer_same_line && one_line_width <= shape.width { - String::from(" ") + Cow::from(" ") } else { - format!("\n{}", indent_str) + indent.to_string_with_newline(config) } }; + result.push_str(&first_sep); + result.push_str(&missing_comment); + let second_sep = if missing_comment.is_empty() || next_str.is_empty() { - String::new() + Cow::from("") } else if missing_comment.starts_with("//") { - format!("\n{}", indent_str) + indent.to_string_with_newline(config) } else { one_line_width += missing_comment.len() + first_sep.len() + 1; allow_one_line &= !missing_comment.starts_with("//") && !missing_comment.contains('\n'); if prefer_same_line && allow_one_line && one_line_width <= shape.width { - String::from(" ") + Cow::from(" ") } else { - format!("\n{}", indent_str) + indent.to_string_with_newline(config) } }; - Some(format!( - "{}{}{}{}{}", - prev_str, first_sep, missing_comment, second_sep, next_str, - )) + result.push_str(&second_sep); + result.push_str(next_str); + + Some(result) } pub fn rewrite_doc_comment(orig: &str, shape: Shape, config: &Config) -> Option { diff --git a/rustfmt-core/src/shape.rs b/rustfmt-core/src/shape.rs index 8fe2e2b18c0..1c98052c493 100644 --- a/rustfmt-core/src/shape.rs +++ b/rustfmt-core/src/shape.rs @@ -25,7 +25,7 @@ pub struct Indent { // INDENT_BUFFER.len() = 80 const INDENT_BUFFER_LEN: usize = 80; const INDENT_BUFFER: &str = - " "; + "\n "; impl Indent { pub fn new(block_indent: usize, alignment: usize) -> Indent { Indent { @@ -74,16 +74,27 @@ pub fn width(&self) -> usize { } pub fn to_string(&self, config: &Config) -> Cow<'static, str> { + self.to_string_inner(config, 1) + } + + pub fn to_string_with_newline(&self, config: &Config) -> Cow<'static, str> { + self.to_string_inner(config, 0) + } + + pub fn to_string_inner(&self, config: &Config, offset: usize) -> Cow<'static, str> { let (num_tabs, num_spaces) = if config.hard_tabs() { (self.block_indent / config.tab_spaces(), self.alignment) } else { (0, self.width()) }; let num_chars = num_tabs + num_spaces; - if num_tabs == 0 && num_chars <= INDENT_BUFFER_LEN { - Cow::from(&INDENT_BUFFER[0..num_chars]) + if num_tabs == 0 && num_chars + offset <= INDENT_BUFFER_LEN { + Cow::from(&INDENT_BUFFER[offset..num_chars + 1]) } else { - let mut indent = String::with_capacity(num_chars); + let mut indent = String::with_capacity(num_chars + if offset == 0 { 1 } else { 0 }); + if offset == 0 { + indent.push('\n'); + } for _ in 0..num_tabs { indent.push('\t') }