Unnamed repository; edit this file 'description' to name the repository.
format_collect
Johann Hemmann 2024-02-01
parent d37f4e0 · commit 771c6c9
-rw-r--r--Cargo.toml1
-rw-r--r--crates/hir-def/src/macro_expansion_tests/mod.rs5
-rw-r--r--crates/ide-assists/src/tests/sourcegen.rs7
-rw-r--r--crates/rust-analyzer/src/config.rs31
-rw-r--r--crates/rust-analyzer/tests/slow-tests/main.rs7
-rw-r--r--crates/stdx/src/macros.rs16
-rw-r--r--crates/syntax/src/ast/make.rs18
-rw-r--r--crates/syntax/src/tests.rs8
8 files changed, 54 insertions, 39 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 53581c4460..5a74864811 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -169,7 +169,6 @@ new_ret_no_self = "allow"
borrowed_box = "allow"
derived_hash_with_manual_eq = "allow"
forget_non_drop = "allow"
-format_collect = "allow"
needless_doctest_main = "allow"
non_canonical_clone_impl = "allow"
non_canonical_partial_ord_impl = "allow"
diff --git a/crates/hir-def/src/macro_expansion_tests/mod.rs b/crates/hir-def/src/macro_expansion_tests/mod.rs
index ec29940538..e315414e9b 100644
--- a/crates/hir-def/src/macro_expansion_tests/mod.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mod.rs
@@ -25,7 +25,7 @@ use hir_expand::{
InFile, MacroFileId, MacroFileIdExt,
};
use span::Span;
-use stdx::format_to;
+use stdx::{format_to, format_to_acc};
use syntax::{
ast::{self, edit::IndentLevel},
AstNode,
@@ -149,8 +149,7 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
if tree {
let tree = format!("{:#?}", parse.syntax_node())
.split_inclusive('\n')
- .map(|line| format!("// {line}"))
- .collect::<String>();
+ .fold(String::new(), |mut acc, line| format_to_acc!(acc, "// {line}"));
format_to!(expn_text, "\n{}", tree)
}
let range = call.syntax().text_range();
diff --git a/crates/ide-assists/src/tests/sourcegen.rs b/crates/ide-assists/src/tests/sourcegen.rs
index ad5ec83287..088d93f9a6 100644
--- a/crates/ide-assists/src/tests/sourcegen.rs
+++ b/crates/ide-assists/src/tests/sourcegen.rs
@@ -2,6 +2,7 @@
use std::{fmt, fs, path::Path};
+use stdx::format_to_acc;
use test_utils::project_root;
#[test]
@@ -172,8 +173,7 @@ impl fmt::Display for Assist {
fn hide_hash_comments(text: &str) -> String {
text.split('\n') // want final newline
.filter(|&it| !(it.starts_with("# ") || it == "#"))
- .map(|it| format!("{it}\n"))
- .collect()
+ .fold(String::new(), |mut acc, it| format_to_acc!(acc, "{it}\n"))
}
fn reveal_hash_comments(text: &str) -> String {
@@ -187,6 +187,5 @@ fn reveal_hash_comments(text: &str) -> String {
it
}
})
- .map(|it| format!("{it}\n"))
- .collect()
+ .fold(String::new(), |mut acc, it| format_to_acc!(acc, "{it}\n"))
}
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 54d96ab138..815f6ea12e 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -32,6 +32,7 @@ use project_model::{
};
use rustc_hash::{FxHashMap, FxHashSet};
use serde::{de::DeserializeOwned, Deserialize};
+use stdx::format_to_acc;
use vfs::{AbsPath, AbsPathBuf};
use crate::{
@@ -2563,14 +2564,13 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
#[cfg(test)]
fn manual(fields: &[(&'static str, &'static str, &[&str], &str)]) -> String {
- fields
- .iter()
- .map(|(field, _ty, doc, default)| {
- let name = format!("rust-analyzer.{}", field.replace('_', "."));
- let doc = doc_comment_to_string(doc);
- if default.contains('\n') {
- format!(
- r#"[[{name}]]{name}::
+ fields.iter().fold(String::new(), |mut acc, (field, _ty, doc, default)| {
+ let name = format!("rust-analyzer.{}", field.replace('_', "."));
+ let doc = doc_comment_to_string(doc);
+ if default.contains('\n') {
+ format_to_acc!(
+ acc,
+ r#"[[{name}]]{name}::
+
--
Default:
@@ -2580,16 +2580,17 @@ Default:
{doc}
--
"#
- )
- } else {
- format!("[[{name}]]{name} (default: `{default}`)::\n+\n--\n{doc}--\n")
- }
- })
- .collect::<String>()
+ )
+ } else {
+ format_to_acc!(acc, "[[{name}]]{name} (default: `{default}`)::\n+\n--\n{doc}--\n")
+ }
+ })
}
fn doc_comment_to_string(doc: &[&str]) -> String {
- doc.iter().map(|it| it.strip_prefix(' ').unwrap_or(it)).map(|it| format!("{it}\n")).collect()
+ doc.iter()
+ .map(|it| it.strip_prefix(' ').unwrap_or(it))
+ .fold(String::new(), |mut acc, it| format_to_acc!(acc, "{it}\n"))
}
#[cfg(test)]
diff --git a/crates/rust-analyzer/tests/slow-tests/main.rs b/crates/rust-analyzer/tests/slow-tests/main.rs
index f7f654b890..19890110d5 100644
--- a/crates/rust-analyzer/tests/slow-tests/main.rs
+++ b/crates/rust-analyzer/tests/slow-tests/main.rs
@@ -31,6 +31,7 @@ use lsp_types::{
};
use rust_analyzer::lsp::ext::{OnEnter, Runnables, RunnablesParams};
use serde_json::json;
+use stdx::format_to_acc;
use test_utils::skip_slow_tests;
use crate::{
@@ -591,8 +592,10 @@ fn diagnostics_dont_block_typing() {
return;
}
- let librs: String = (0..10).map(|i| format!("mod m{i};")).collect();
- let libs: String = (0..10).map(|i| format!("//- /src/m{i}.rs\nfn foo() {{}}\n\n")).collect();
+ let librs: String = (0..10).fold(String::new(), |mut acc, i| format_to_acc!(acc, "mod m{i};"));
+ let libs: String = (0..10).fold(String::new(), |mut acc, i| {
+ format_to_acc!(acc, "//- /src/m{i}.rs\nfn foo() {{}}\n\n")
+ });
let server = Project::with_fixture(&format!(
r#"
//- /Cargo.toml
diff --git a/crates/stdx/src/macros.rs b/crates/stdx/src/macros.rs
index d71e418c89..5713abb6fc 100644
--- a/crates/stdx/src/macros.rs
+++ b/crates/stdx/src/macros.rs
@@ -24,6 +24,22 @@ macro_rules! format_to {
};
}
+/// Appends formatted string to a `String` and returns the `String`.
+///
+/// Useful for folding iterators into a `String`.
+#[macro_export]
+macro_rules! format_to_acc {
+ ($buf:expr, $lit:literal $($arg:tt)*) => {
+ {
+ use ::std::fmt::Write as _;
+ // We can't do ::std::fmt::Write::write_fmt($buf, format_args!($lit $($arg)*))
+ // unfortunately, as that loses out on autoref behavior.
+ _ = $buf.write_fmt(format_args!($lit $($arg)*));
+ $buf
+ }
+ };
+}
+
/// Generates `From` impls for `Enum E { Foo(Foo), Bar(Bar) }` enums
///
/// # Example
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index 62d64319e3..d5eda8f15e 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -9,10 +9,11 @@
//! API should require to assemble every node piecewise. The trick of
//! `parse(format!())` we use internally is an implementation detail -- long
//! term, it will be replaced with direct tree manipulation.
+
use itertools::Itertools;
use parser::T;
use rowan::NodeOrToken;
-use stdx::{format_to, never};
+use stdx::{format_to, format_to_acc, never};
use crate::{ast, utils::is_raw_identifier, AstNode, SourceFile, SyntaxKind, SyntaxToken};
@@ -759,15 +760,12 @@ pub fn match_arm_with_guard(
}
pub fn match_arm_list(arms: impl IntoIterator<Item = ast::MatchArm>) -> ast::MatchArmList {
- let arms_str = arms
- .into_iter()
- .map(|arm| {
- let needs_comma = arm.expr().map_or(true, |it| !it.is_block_like());
- let comma = if needs_comma { "," } else { "" };
- let arm = arm.syntax();
- format!(" {arm}{comma}\n")
- })
- .collect::<String>();
+ let arms_str = arms.into_iter().fold(String::new(), |mut acc, arm| {
+ let needs_comma = arm.expr().map_or(true, |it| !it.is_block_like());
+ let comma = if needs_comma { "," } else { "" };
+ let arm = arm.syntax();
+ format_to_acc!(acc, " {arm}{comma}\n")
+ });
return from_text(&arms_str);
fn from_text(text: &str) -> ast::MatchArmList {
diff --git a/crates/syntax/src/tests.rs b/crates/syntax/src/tests.rs
index 8ae1242cf7..4c0a538f71 100644
--- a/crates/syntax/src/tests.rs
+++ b/crates/syntax/src/tests.rs
@@ -11,6 +11,7 @@ use std::{
use ast::HasName;
use expect_test::expect_file;
use rayon::prelude::*;
+use stdx::format_to_acc;
use test_utils::{bench, bench_fixture, project_root};
use crate::{ast, fuzz, AstNode, SourceFile, SyntaxError};
@@ -104,10 +105,9 @@ fn self_hosting_parsing() {
.collect::<Vec<_>>();
if !errors.is_empty() {
- let errors = errors
- .into_iter()
- .map(|(path, err)| format!("{}: {:?}\n", path.display(), err[0]))
- .collect::<String>();
+ let errors = errors.into_iter().fold(String::new(), |mut acc, (path, err)| {
+ format_to_acc!(acc, "{}: {:?}\n", path.display(), err[0])
+ });
panic!("Parsing errors:\n{errors}\n");
}
}