format_collect

This commit is contained in:
Johann Hemmann 2024-01-30 14:12:42 +01:00
parent d37f4e0d21
commit 771c6c9271
8 changed files with 54 additions and 39 deletions

View File

@ -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"

View File

@ -25,7 +25,7 @@
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();

View File

@ -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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
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"))
}

View File

@ -32,6 +32,7 @@
};
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 @@ macro_rules! set {
#[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 @@ fn manual(fields: &[(&'static str, &'static str, &[&str], &str)]) -> String {
{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)]

View File

@ -31,6 +31,7 @@
};
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

View File

@ -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

View File

@ -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 @@ fn from_text(text: &str) -> ast::MatchArm {
}
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 {

View File

@ -11,6 +11,7 @@
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");
}
}