diff --git a/format/src/lib.rs b/format/src/lib.rs index ea8786e89..b64ba2600 100644 --- a/format/src/lib.rs +++ b/format/src/lib.rs @@ -271,7 +271,7 @@ impl<'a, 'doc> Formatter<'a> { self.doc_comments.iter().map(|comment| { DOC_COMMENT_DOCUMENT .to_doc(arena) - .append(arena, EcoString::from(comment.content)) + .append(arena, arena.zero_width_str(comment.content)) }), LINE_DOCUMENT, ); @@ -286,7 +286,7 @@ impl<'a, 'doc> Formatter<'a> { let comments = self.module_comments.iter().map(|s| { MODULE_COMMENT_DOCUMENT .to_doc(arena) - .append(arena, EcoString::from(s.content)) + .append(arena, arena.zero_width_str(s.content)) }); arena .join(comments, LINE_DOCUMENT) @@ -845,7 +845,7 @@ impl<'a, 'doc> Formatter<'a> { .join( comments.map(|comment| match comment { Some(comment) => { - DOC_COMMENT_DOCUMENT.append(arena, EcoString::from(comment)) + DOC_COMMENT_DOCUMENT.append(arena, arena.zero_width_str(comment)) } None => unreachable!("empty lines dropped by pop_doc_comments"), }), @@ -3660,7 +3660,9 @@ impl<'a, 'doc> Formatter<'a> { } (_, None) => continue, }; - doc.push(COMMENT_DOCUMENT.append(arena, EcoString::from(comment))); + doc.push( + COMMENT_DOCUMENT.append(arena, arena.zero_width_string(EcoString::from(comment))), + ); match comments.peek() { // Next line is a comment Some((_, Some(_))) => doc.push(LINE_DOCUMENT), @@ -4246,12 +4248,17 @@ fn printed_comments<'a, 'doc>( let _ = comments.peek()?; let mut doc = Vec::new(); - while let Some(c) = comments.next() { - let c = match c { - Some(c) => c, - None => continue, - }; - doc.push("//".to_doc(arena).append(arena, EcoString::from(c))); + while let Some(comment) = comments.next() { + let Some(comment) = comment else { continue }; + + // The comment is turned into a zero width string rather than a regular + // string document: comment lines are never touched by the formatter and + // we don't need to know how long each one is. + // So we can do this to avoid counting the graphemes of each one, which + // is a lot of wasted work. + let comment = arena.zero_width_str(comment); + + doc.push(COMMENT_DOCUMENT.append(arena, comment)); match comments.peek() { // Next line is a comment Some(Some(_)) => doc.push(LINE_DOCUMENT), diff --git a/pretty-arena/src/lib.rs b/pretty-arena/src/lib.rs index f1750c5a5..c46b6bf78 100644 --- a/pretty-arena/src/lib.rs +++ b/pretty-arena/src/lib.rs @@ -1087,6 +1087,17 @@ impl<'string, 'doc> DocumentArena<'string, 'doc> { ) } + /// Same as the `zero_width_string` but this works with string references. + /// This is useful when you already have a string reference and you want to + /// avoid allocating a further string. + /// + pub fn zero_width_str(&'doc self, string: &'string str) -> Document<'string, 'doc> { + Document( + self.documents + .alloc(PrintableDocument::ZeroWidthStr { string }), + ) + } + /// Joins together an iterator of documents into a single document. /// All the documents are gonna be rendered next to each other with no /// spaces in between.