summaryrefslogtreecommitdiffstats
path: root/vendor/indenter
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /vendor/indenter
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/indenter')
-rw-r--r--vendor/indenter/.cargo-checksum.json1
-rw-r--r--vendor/indenter/CHANGELOG.md31
-rw-r--r--vendor/indenter/Cargo.lock5
-rw-r--r--vendor/indenter/Cargo.toml70
-rw-r--r--vendor/indenter/README.md113
-rw-r--r--vendor/indenter/examples/usage.rs12
-rw-r--r--vendor/indenter/src/lib.rs542
7 files changed, 774 insertions, 0 deletions
diff --git a/vendor/indenter/.cargo-checksum.json b/vendor/indenter/.cargo-checksum.json
new file mode 100644
index 000000000..569f4a23c
--- /dev/null
+++ b/vendor/indenter/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"488d07e32f0882080938c8baae0af55ea58937d816f4c4c12f294f057238b064","Cargo.lock":"3df02f6a248110ecf9527ce2ae8c3c91acc295277bd2d0745d9d1d3aa622754f","Cargo.toml":"1ee8d05e19dffa8cd49dc9f7288a30b00d598d3240a06a24298e845e9854541b","README.md":"8f9fff9b73b1205590cb57eba24c1b6e79424cea82c30eccc072d07472062cf7","examples/usage.rs":"5bb66ce0078a6cd1dded6f49122fa96c8f0842c4d6631827299ebf575dfff49d","src/lib.rs":"3e504c87e794adaa522153e350ba1cec7e4671fdb4b71309800b9bdeb6a94400"},"package":"ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"} \ No newline at end of file
diff --git a/vendor/indenter/CHANGELOG.md b/vendor/indenter/CHANGELOG.md
new file mode 100644
index 000000000..3d8a3c634
--- /dev/null
+++ b/vendor/indenter/CHANGELOG.md
@@ -0,0 +1,31 @@
+# Changelog
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+<!-- next-header -->
+
+## [Unreleased] - ReleaseDate
+
+## [0.3.3] - 2021-02-22
+### Added
+- Implement new code dedenting / indenting formatter by cecton
+
+## [0.3.2] - 2021-01-04
+### Fixed
+- Changed indentation logic to better support trailing newlines and improve
+ overall formatting consistency
+
+## [0.3.1] - 2020-12-21
+### Added
+- `with_str` helper method for indenting with static strings
+### Changed
+- Relaxed `Sized` bound on inner writers
+
+
+<!-- next-url -->
+[Unreleased]: https://github.com/yaahc/indenter/compare/v0.3.3...HEAD
+[0.3.3]: https://github.com/yaahc/indenter/compare/v0.3.2...v0.3.3
+[0.3.2]: https://github.com/yaahc/indenter/compare/v0.3.1...v0.3.2
+[0.3.1]: https://github.com/yaahc/indenter/releases/tag/v0.3.1
diff --git a/vendor/indenter/Cargo.lock b/vendor/indenter/Cargo.lock
new file mode 100644
index 000000000..e4e4181ff
--- /dev/null
+++ b/vendor/indenter/Cargo.lock
@@ -0,0 +1,5 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "indenter"
+version = "0.3.3"
diff --git a/vendor/indenter/Cargo.toml b/vendor/indenter/Cargo.toml
new file mode 100644
index 000000000..6afb65425
--- /dev/null
+++ b/vendor/indenter/Cargo.toml
@@ -0,0 +1,70 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "indenter"
+version = "0.3.3"
+authors = ["Jane Lusby <jlusby@yaah.dev>"]
+description = "A formatter wrapper that indents the text, designed for error display impls\n"
+homepage = "https://github.com/yaahc/indenter"
+documentation = "https://docs.rs/indenter"
+readme = "README.md"
+keywords = ["display", "fmt", "Formatter", "error"]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/yaahc/indenter"
+[package.metadata.docs.rs]
+all-features = true
+rustdoc-args = ["--cfg", "docsrs"]
+
+[package.metadata.release]
+no-dev-version = true
+
+[[package.metadata.release.pre-release-replacements]]
+file = "CHANGELOG.md"
+replace = "{{version}}"
+search = "Unreleased"
+
+[[package.metadata.release.pre-release-replacements]]
+exactly = 1
+file = "src/lib.rs"
+replace = "#![doc(html_root_url = \"https://docs.rs/{{crate_name}}/{{version}}\")]"
+search = "#!\\[doc\\(html_root_url.*"
+
+[[package.metadata.release.pre-release-replacements]]
+exactly = 1
+file = "CHANGELOG.md"
+replace = "...{{tag_name}}"
+search = "\\.\\.\\.HEAD"
+
+[[package.metadata.release.pre-release-replacements]]
+file = "CHANGELOG.md"
+replace = "{{date}}"
+search = "ReleaseDate"
+
+[[package.metadata.release.pre-release-replacements]]
+exactly = 1
+file = "CHANGELOG.md"
+replace = "<!-- next-header -->\n\n## [Unreleased] - ReleaseDate"
+search = "<!-- next-header -->"
+
+[[package.metadata.release.pre-release-replacements]]
+exactly = 1
+file = "CHANGELOG.md"
+replace = "<!-- next-url -->\n[Unreleased]: https://github.com/yaahc/{{crate_name}}/compare/{{tag_name}}...HEAD"
+search = "<!-- next-url -->"
+
+[dependencies]
+
+[features]
+default = []
+std = []
diff --git a/vendor/indenter/README.md b/vendor/indenter/README.md
new file mode 100644
index 000000000..98bce3c4c
--- /dev/null
+++ b/vendor/indenter/README.md
@@ -0,0 +1,113 @@
+## indenter
+
+[![Build Status][actions-badge]][actions-url]
+[![Latest Version][version-badge]][version-url]
+[![Rust Documentation][docs-badge]][docs-url]
+
+[actions-badge]: https://github.com/yaahc/indenter/workflows/Continuous%20integration/badge.svg
+[actions-url]: https://github.com/yaahc/indenter/actions?query=workflow%3A%22Continuous+integration%22
+[version-badge]: https://img.shields.io/crates/v/indenter.svg
+[version-url]: https://crates.io/crates/indenter
+[docs-badge]: https://img.shields.io/badge/docs-latest-blue.svg
+[docs-url]: https://docs.rs/indenter
+
+A few wrappers for the `fmt::Write` objects that efficiently appends and remove
+common indentation after every newline
+
+## Setup
+
+Add this to your `Cargo.toml`:
+
+```toml
+[dependencies]
+indenter = "0.2"
+```
+
+## Examples
+
+## Indentation only
+
+This type is intended primarily for writing error reporters that gracefully
+format error messages that span multiple lines.
+
+```rust
+use std::error::Error;
+use std::fmt::{self, Write};
+use indenter::indented;
+
+struct ErrorReporter<'a>(&'a dyn Error);
+
+impl fmt::Debug for ErrorReporter<'_> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let mut source = Some(self.0);
+ let mut i = 0;
+
+ while let Some(error) = source {
+ writeln!(f)?;
+ write!(indented(f).ind(i), "{}", error)?;
+
+ source = error.source();
+ i += 1;
+ }
+
+ Ok(())
+ }
+}
+```
+
+## "Dedenting" (removing common leading indendation)
+
+This type is intended primarily for formatting source code. For example, when
+generating code.
+
+This type requires the feature `std`.
+
+```rust
+use std::error::Error;
+use core::fmt::{self, Write};
+use indenter::CodeFormatter;
+
+let mut output = String::new();
+let mut f = CodeFormatter::new(&mut output, " ");
+
+write!(
+ f,
+ r#"
+ Hello
+ World
+ "#,
+);
+
+assert_eq!(output, "Hello\n World\n");
+
+let mut output = String::new();
+let mut f = CodeFormatter::new(&mut output, " ");
+
+// it can also indent...
+f.indent(2);
+
+write!(
+ f,
+ r#"
+ Hello
+ World
+ "#,
+);
+
+assert_eq!(output, " Hello\n World\n");
+```
+
+#### License
+
+<sup>
+Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
+2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
+</sup>
+
+<br>
+
+<sub>
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
+be dual licensed as above, without any additional terms or conditions.
+</sub>
diff --git a/vendor/indenter/examples/usage.rs b/vendor/indenter/examples/usage.rs
new file mode 100644
index 000000000..3432fccc3
--- /dev/null
+++ b/vendor/indenter/examples/usage.rs
@@ -0,0 +1,12 @@
+use indenter::indented;
+use std::fmt::Write;
+
+fn main() {
+ let input = "verify\nthis";
+ let mut output = String::new();
+
+ indented(&mut output).ind(12).write_str(input).unwrap();
+
+ println!("Before:\n{}\n", input);
+ println!("After:\n{}", output);
+}
diff --git a/vendor/indenter/src/lib.rs b/vendor/indenter/src/lib.rs
new file mode 100644
index 000000000..f9b73ba7a
--- /dev/null
+++ b/vendor/indenter/src/lib.rs
@@ -0,0 +1,542 @@
+//! A few wrappers for the `fmt::Write` objects that efficiently appends and remove
+//! common indentation after every newline
+//!
+//! # Setup
+//!
+//! Add this to your `Cargo.toml`:
+//!
+//! ```toml
+//! [dependencies]
+//! indenter = "0.2"
+//! ```
+//!
+//! # Examples
+//!
+//! ## Indentation only
+//!
+//! This type is intended primarily for writing error reporters that gracefully
+//! format error messages that span multiple lines.
+//!
+//! ```rust
+//! use std::error::Error;
+//! use core::fmt::{self, Write};
+//! use indenter::indented;
+//!
+//! struct ErrorReporter<'a>(&'a dyn Error);
+//!
+//! impl fmt::Debug for ErrorReporter<'_> {
+//! fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+//! let mut source = Some(self.0);
+//! let mut i = 0;
+//!
+//! while let Some(error) = source {
+//! writeln!(f)?;
+//! write!(indented(f).ind(i), "{}", error)?;
+//!
+//! source = error.source();
+//! i += 1;
+//! }
+//!
+//! Ok(())
+//! }
+//! }
+//! ```
+//!
+//! ## "Dedenting" (removing common leading indendation)
+//!
+//! This type is intended primarily for formatting source code. For example, when
+//! generating code.
+//!
+//! This type requires the feature `std`.
+//!
+//! ```rust
+//! # #[cfg(feature = "std")]
+//! # fn main() {
+//! use std::error::Error;
+//! use core::fmt::{self, Write};
+//! use indenter::CodeFormatter;
+//!
+//! let mut output = String::new();
+//! let mut f = CodeFormatter::new(&mut output, " ");
+//!
+//! write!(
+//! f,
+//! r#"
+//! Hello
+//! World
+//! "#,
+//! );
+//!
+//! assert_eq!(output, "Hello\n World\n");
+//!
+//! let mut output = String::new();
+//! let mut f = CodeFormatter::new(&mut output, " ");
+//!
+//! // it can also indent...
+//! f.indent(2);
+//!
+//! write!(
+//! f,
+//! r#"
+//! Hello
+//! World
+//! "#,
+//! );
+//!
+//! assert_eq!(output, " Hello\n World\n");
+//! # }
+//! # #[cfg(not(feature = "std"))]
+//! # fn main() {
+//! # }
+//! ```
+#![cfg_attr(not(feature = "std"), no_std)]
+#![doc(html_root_url = "https://docs.rs/indenter/0.3.3")]
+#![warn(
+ missing_debug_implementations,
+ missing_docs,
+ missing_doc_code_examples,
+ rust_2018_idioms,
+ unreachable_pub,
+ bad_style,
+ const_err,
+ dead_code,
+ improper_ctypes,
+ non_shorthand_field_patterns,
+ no_mangle_generic_items,
+ overflowing_literals,
+ path_statements,
+ patterns_in_fns_without_body,
+ private_in_public,
+ unconditional_recursion,
+ unused,
+ unused_allocation,
+ unused_comparisons,
+ unused_parens,
+ while_true
+)]
+use core::fmt;
+
+/// The set of supported formats for indentation
+#[allow(missing_debug_implementations)]
+pub enum Format<'a> {
+ /// Insert uniform indentation before every line
+ ///
+ /// This format takes a static string as input and inserts it after every newline
+ Uniform {
+ /// The string to insert as indentation
+ indentation: &'static str,
+ },
+ /// Inserts a number before the first line
+ ///
+ /// This format hard codes the indentation level to match the indentation from
+ /// `core::backtrace::Backtrace`
+ Numbered {
+ /// The index to insert before the first line of output
+ ind: usize,
+ },
+ /// A custom indenter which is executed after every newline
+ ///
+ /// Custom indenters are passed the current line number and the buffer to be written to as args
+ Custom {
+ /// The custom indenter
+ inserter: &'a mut Inserter,
+ },
+}
+
+/// Helper struct for efficiently indenting multi line display implementations
+///
+/// # Explanation
+///
+/// This type will never allocate a string to handle inserting indentation. It instead leverages
+/// the `write_str` function that serves as the foundation of the `core::fmt::Write` trait. This
+/// lets it intercept each piece of output as its being written to the output buffer. It then
+/// splits on newlines giving slices into the original string. Finally we alternate writing these
+/// lines and the specified indentation to the output buffer.
+#[allow(missing_debug_implementations)]
+pub struct Indented<'a, D: ?Sized> {
+ inner: &'a mut D,
+ needs_indent: bool,
+ format: Format<'a>,
+}
+
+/// A callback for `Format::Custom` used to insert indenation after a new line
+///
+/// The first argument is the line number within the output, starting from 0
+pub type Inserter = dyn FnMut(usize, &mut dyn fmt::Write) -> fmt::Result;
+
+impl Format<'_> {
+ fn insert_indentation(&mut self, line: usize, f: &mut dyn fmt::Write) -> fmt::Result {
+ match self {
+ Format::Uniform { indentation } => write!(f, "{}", indentation),
+ Format::Numbered { ind } => {
+ if line == 0 {
+ write!(f, "{: >4}: ", ind)
+ } else {
+ write!(f, " ")
+ }
+ }
+ Format::Custom { inserter } => inserter(line, f),
+ }
+ }
+}
+
+impl<'a, D> Indented<'a, D> {
+ /// Sets the format to `Format::Numbered` with the provided index
+ pub fn ind(self, ind: usize) -> Self {
+ self.with_format(Format::Numbered { ind })
+ }
+
+ /// Sets the format to `Format::Uniform` with the provided static string
+ pub fn with_str(self, indentation: &'static str) -> Self {
+ self.with_format(Format::Uniform { indentation })
+ }
+
+ /// Construct an indenter with a user defined format
+ pub fn with_format(mut self, format: Format<'a>) -> Self {
+ self.format = format;
+ self
+ }
+}
+
+impl<T> fmt::Write for Indented<'_, T>
+where
+ T: fmt::Write + ?Sized,
+{
+ fn write_str(&mut self, s: &str) -> fmt::Result {
+ for (ind, line) in s.split('\n').enumerate() {
+ if ind > 0 {
+ self.inner.write_char('\n')?;
+ self.needs_indent = true;
+ }
+
+ if self.needs_indent {
+ // Don't render the line unless its actually got text on it
+ if line.is_empty() {
+ continue;
+ }
+
+ self.format.insert_indentation(ind, &mut self.inner)?;
+ self.needs_indent = false;
+ }
+
+ self.inner.write_fmt(format_args!("{}", line))?;
+ }
+
+ Ok(())
+ }
+}
+
+/// Helper function for creating a default indenter
+pub fn indented<D: ?Sized>(f: &mut D) -> Indented<'_, D> {
+ Indented {
+ inner: f,
+ needs_indent: true,
+ format: Format::Uniform {
+ indentation: " ",
+ },
+ }
+}
+
+/// Helper struct for efficiently dedent and indent multi line display implementations
+///
+/// # Explanation
+///
+/// This type allocates a string once to get the formatted result and then uses the internal
+/// formatter efficiently to: first dedent the output, then re-indent to the desired level.
+#[cfg(feature = "std")]
+#[allow(missing_debug_implementations)]
+pub struct CodeFormatter<'a, T> {
+ f: &'a mut T,
+ level: u32,
+ indentation: String,
+}
+
+#[cfg(feature = "std")]
+impl<'a, T: fmt::Write> fmt::Write for CodeFormatter<'a, T> {
+ fn write_str(&mut self, input: &str) -> fmt::Result {
+ let input = match input.chars().next() {
+ Some('\n') => &input[1..],
+ _ => return self.f.write_str(input),
+ };
+
+ let min = input
+ .split('\n')
+ .map(|line| line.chars().take_while(char::is_ascii_whitespace).count())
+ .filter(|count| *count > 0)
+ .min()
+ .unwrap_or_default();
+
+ let input = input.trim_end_matches(|c| char::is_ascii_whitespace(&c));
+
+ for line in input.split('\n') {
+ if line.len().saturating_sub(min) > 0 {
+ for _ in 0..self.level {
+ self.f.write_str(&self.indentation)?;
+ }
+ }
+
+ if line.len() >= min {
+ self.f.write_str(&line[min..])?;
+ } else {
+ self.f.write_str(&line)?;
+ }
+ self.f.write_char('\n')?;
+ }
+
+ Ok(())
+ }
+
+ fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result {
+ self.write_str(&args.to_string())
+ }
+}
+
+#[cfg(feature = "std")]
+impl<'a, T: fmt::Write> CodeFormatter<'a, T> {
+ /// Wrap the formatter `f`, use `indentation` as base string indentation and return a new
+ /// formatter that implements `std::fmt::Write` that can be used with the macro `write!()`
+ pub fn new<S: Into<String>>(f: &'a mut T, indentation: S) -> Self {
+ Self {
+ f,
+ level: 0,
+ indentation: indentation.into(),
+ }
+ }
+
+ /// Set the indentation level to a specific value
+ pub fn set_level(&mut self, level: u32) {
+ self.level = level;
+ }
+
+ /// Increase the indentation level by `inc`
+ pub fn indent(&mut self, inc: u32) {
+ self.level = self.level.saturating_add(inc);
+ }
+
+ /// Decrease the indentation level by `inc`
+ pub fn dedent(&mut self, inc: u32) {
+ self.level = self.level.saturating_sub(inc);
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ extern crate alloc;
+
+ use super::*;
+ use alloc::string::String;
+ use core::fmt::Write as _;
+
+ #[test]
+ fn one_digit() {
+ let input = "verify\nthis";
+ let expected = " 2: verify\n this";
+ let mut output = String::new();
+
+ indented(&mut output).ind(2).write_str(input).unwrap();
+
+ assert_eq!(expected, output);
+ }
+
+ #[test]
+ fn two_digits() {
+ let input = "verify\nthis";
+ let expected = " 12: verify\n this";
+ let mut output = String::new();
+
+ indented(&mut output).ind(12).write_str(input).unwrap();
+
+ assert_eq!(expected, output);
+ }
+
+ #[test]
+ fn no_digits() {
+ let input = "verify\nthis";
+ let expected = " verify\n this";
+ let mut output = String::new();
+
+ indented(&mut output).write_str(input).unwrap();
+
+ assert_eq!(expected, output);
+ }
+
+ #[test]
+ fn with_str() {
+ let input = "verify\nthis";
+ let expected = "...verify\n...this";
+ let mut output = String::new();
+
+ indented(&mut output)
+ .with_str("...")
+ .write_str(input)
+ .unwrap();
+
+ assert_eq!(expected, output);
+ }
+
+ #[test]
+ fn dyn_write() {
+ let input = "verify\nthis";
+ let expected = " verify\n this";
+ let mut output = String::new();
+ let writer: &mut dyn core::fmt::Write = &mut output;
+
+ indented(writer).write_str(input).unwrap();
+
+ assert_eq!(expected, output);
+ }
+
+ #[test]
+ fn nice_api() {
+ let input = "verify\nthis";
+ let expected = " 1: verify\n this";
+ let output = &mut String::new();
+ let n = 1;
+
+ write!(
+ indented(output).with_format(Format::Custom {
+ inserter: &mut move |line_no, f| {
+ if line_no == 0 {
+ write!(f, "{: >4}: ", n)
+ } else {
+ write!(f, " ")
+ }
+ }
+ }),
+ "{}",
+ input
+ )
+ .unwrap();
+
+ assert_eq!(expected, output);
+ }
+
+ #[test]
+ fn nice_api_2() {
+ let input = "verify\nthis";
+ let expected = " verify\n this";
+ let output = &mut String::new();
+
+ write!(
+ indented(output).with_format(Format::Uniform { indentation: " " }),
+ "{}",
+ input
+ )
+ .unwrap();
+
+ assert_eq!(expected, output);
+ }
+
+ #[test]
+ fn trailing_newlines() {
+ let input = "verify\nthis\n";
+ let expected = " verify\n this\n";
+ let output = &mut String::new();
+
+ write!(indented(output).with_str(" "), "{}", input).unwrap();
+
+ assert_eq!(expected, output);
+ }
+
+ #[test]
+ fn several_interpolations() {
+ let input = "verify\nthis\n";
+ let expected = " verify\n this\n and verify\n this\n";
+ let output = &mut String::new();
+
+ write!(indented(output).with_str(" "), "{} and {}", input, input).unwrap();
+
+ assert_eq!(expected, output);
+ }
+}
+
+#[cfg(all(test, feature = "std"))]
+mod tests_std {
+ use super::*;
+ use core::fmt::Write as _;
+
+ #[test]
+ fn dedent() {
+ let mut s = String::new();
+ let mut f = CodeFormatter::new(&mut s, " ");
+ write!(
+ f,
+ r#"
+ struct Foo;
+
+ impl Foo {{
+ fn foo() {{
+ todo!()
+ }}
+ }}
+ "#,
+ )
+ .unwrap();
+ assert_eq!(
+ s,
+ "struct Foo;\n\nimpl Foo {\n fn foo() {\n todo!()\n }\n}\n"
+ );
+
+ let mut s = String::new();
+ let mut f = CodeFormatter::new(&mut s, " ");
+ write!(
+ f,
+ r#"
+ struct Foo;
+
+ impl Foo {{
+ fn foo() {{
+ todo!()
+ }}
+ }}"#,
+ )
+ .unwrap();
+ assert_eq!(
+ s,
+ "struct Foo;\n\nimpl Foo {\n fn foo() {\n todo!()\n }\n}\n"
+ );
+ }
+
+ #[test]
+ fn indent() {
+ let mut s = String::new();
+ let mut f = CodeFormatter::new(&mut s, " ");
+ f.indent(1);
+ write!(
+ f,
+ r#"
+ struct Foo;
+
+ impl Foo {{
+ fn foo() {{
+ todo!()
+ }}
+ }}
+ "#,
+ )
+ .unwrap();
+ assert_eq!(s, " struct Foo;\n\n impl Foo {\n fn foo() {\n todo!()\n }\n }\n");
+ }
+
+ #[test]
+ fn inline() {
+ let mut s = String::new();
+ let mut f = CodeFormatter::new(&mut s, " ");
+ write!(
+ f,
+ r#"struct Foo;
+ fn foo() {{
+ }}"#,
+ )
+ .unwrap();
+ assert_eq!(s, "struct Foo;\n fn foo() {\n }");
+ }
+
+ #[test]
+ fn split_prefix() {
+ let mut s = String::new();
+ let mut f = CodeFormatter::new(&mut s, " ");
+ writeln!(f).unwrap();
+ assert_eq!(s, "\n");
+ }
+}