Auto merge of #90680 - calebcartwright:rustfmt-sync, r=calebcartwright

sync rustfmt subtree
This commit is contained in:
bors 2021-11-08 05:13:41 +00:00
commit b3074819f6
59 changed files with 671 additions and 373 deletions

View File

@ -0,0 +1,25 @@
name: rustdoc check
on:
push:
branches:
- master
pull_request:
jobs:
rustdoc_check:
runs-on: ubuntu-latest
name: rustdoc check
steps:
- name: checkout
uses: actions/checkout@v2
- name: install rustup
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh
sh rustup-init.sh -y --default-toolchain none
rustup target add x86_64-unknown-linux-gnu
- name: document rustfmt
env:
RUSTDOCFLAGS: --document-private-items --enable-index-page --show-type-layout --generate-link-to-definition -Zunstable-options -Dwarnings
run: cargo doc -Zskip-rustdoc-fingerprint --no-deps -p rustfmt-nightly -p rustfmt-config_proc_macro

View File

@ -2062,7 +2062,7 @@ use sit;
Controls the strategy for how imports are grouped together. Controls the strategy for how imports are grouped together.
- **Default value**: `Preserve` - **Default value**: `Preserve`
- **Possible values**: `Preserve`, `StdExternalCrate` - **Possible values**: `Preserve`, `StdExternalCrate`, `One`
- **Stable**: No - **Stable**: No
#### `Preserve` (default): #### `Preserve` (default):
@ -2108,6 +2108,23 @@ use super::update::convert_publish_payload;
use crate::models::Event; use crate::models::Event;
``` ```
#### `One`:
Discard existing import groups, and create a single group for everything
```rust
use super::schema::{Context, Payload};
use super::update::convert_publish_payload;
use crate::models::Event;
use alloc::alloc::Layout;
use broker::database::PooledConnection;
use chrono::Utc;
use core::f32;
use juniper::{FieldError, FieldResult};
use std::sync::Arc;
use uuid::Uuid;
```
## `reorder_modules` ## `reorder_modules`
Reorder `mod` declarations alphabetically in group. Reorder `mod` declarations alphabetically in group.

View File

@ -59,7 +59,7 @@ example, the `issue-1111.rs` test file is configured by the file
## Debugging ## Debugging
Some `rewrite_*` methods use the `debug!` macro for printing useful information. Some `rewrite_*` methods use the `debug!` macro for printing useful information.
These messages can be printed by using the environment variable `RUST_LOG=rustfmt=DEBUG`. These messages can be printed by using the environment variable `RUSTFMT_LOG=rustfmt=DEBUG`.
These traces can be helpful in understanding which part of the code was used These traces can be helpful in understanding which part of the code was used
and get a better grasp on the execution flow. and get a better grasp on the execution flow.

View File

@ -47,7 +47,7 @@ cargo +nightly fmt
## Limitations ## Limitations
Rustfmt tries to work on as much Rust code as possible, sometimes, the code Rustfmt tries to work on as much Rust code as possible. Sometimes, the code
doesn't even need to compile! As we approach a 1.0 release we are also looking doesn't even need to compile! As we approach a 1.0 release we are also looking
to limit areas of instability; in particular, post-1.0, the formatting of most to limit areas of instability; in particular, post-1.0, the formatting of most
code should not change as Rustfmt improves. However, there are some things that code should not change as Rustfmt improves. However, there are some things that
@ -102,6 +102,25 @@ read data from stdin. Alternatively, you can use `cargo fmt` to format all
binary and library targets of your crate. binary and library targets of your crate.
You can run `rustfmt --help` for information about available arguments. You can run `rustfmt --help` for information about available arguments.
The easiest way to run rustfmt against a project is with `cargo fmt`. `cargo fmt` works on both
single-crate projects and [cargo workspaces](https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html).
Please see `cargo fmt --help` for usage information.
You can specify the path to your own `rustfmt` binary for cargo to use by setting the`RUSTFMT`
environment variable. This was added in v1.4.22, so you must have this version or newer to leverage this feature (`cargo fmt --version`)
### Running `rustfmt` directly
To format individual files or arbitrary codes from stdin, the `rustfmt` binary should be used. Some
examples follow:
- `rustfmt lib.rs main.rs` will format "lib.rs" and "main.rs" in place
- `rustfmt` will read a code from stdin and write formatting to stdout
- `echo "fn main() {}" | rustfmt` would emit "fn main() {}".
For more information, including arguments and emit options, see `rustfmt --help`.
### Verifying code is formatted
When running with `--check`, Rustfmt will exit with `0` if Rustfmt would not When running with `--check`, Rustfmt will exit with `0` if Rustfmt would not
make any formatting changes to the input, and `1` if Rustfmt would make changes. make any formatting changes to the input, and `1` if Rustfmt would make changes.
@ -129,7 +148,7 @@ rustfmt to exit with an error code if the input is not formatted correctly.
It will also print any found differences. (Older versions of Rustfmt don't It will also print any found differences. (Older versions of Rustfmt don't
support `--check`, use `--write-mode diff`). support `--check`, use `--write-mode diff`).
A minimal Travis setup could look like this (requires Rust 1.24.0 or greater): A minimal Travis setup could look like this (requires Rust 1.31.0 or greater):
```yaml ```yaml
language: rust language: rust

View File

@ -1,8 +0,0 @@
environment:
global:
PROJECT_NAME: rustfmt
build: false
test_script:
- echo Why does no one have access to delete me?

View File

@ -3,19 +3,28 @@
## Installation ## Installation
- Install [CLion](https://www.jetbrains.com/clion/), [IntelliJ Ultimate or CE](https://www.jetbrains.com/idea/) through the direct download link or using the [JetBrains Toolbox](https://www.jetbrains.com/toolbox/). - Install [CLion](https://www.jetbrains.com/clion/), [IntelliJ Ultimate or CE](https://www.jetbrains.com/idea/) through the direct download link or using the [JetBrains Toolbox](https://www.jetbrains.com/toolbox/).
CLion provides a built-in debugger interface but its not free like IntelliJ CE - which does not provide the debugger interface. (IntelliJ seems to lack the toolchain for that, see this discussion [intellij-rust/issues/535](https://github.com/intellij-rust/intellij-rust/issues/535)) CLion and IntelliJ Ultimate [provide a built-in debugger interface](https://github.com/intellij-rust/intellij-rust#compatible-ides) but they are not free like IntelliJ CE.
- Install the [Rust Plugin](https://intellij-rust.github.io/) by navigating to File -> Settings -> Plugins and press "Install JetBrains Plugin" - Install the [Rust Plugin](https://intellij-rust.github.io/) by navigating to File → Settings → Plugins and searching the plugin in the Marketplace
![plugins](https://user-images.githubusercontent.com/1133787/47240861-f40af680-d3e9-11e8-9b82-cdd5c8d5f5b8.png) ![plugins](https://user-images.githubusercontent.com/6505554/83944518-6f1e5c00-a81d-11ea-9c35-e16948811ba8.png)
- Press "Install" on the rust plugin - Press "Install" on the Rust plugin
![install rust](https://user-images.githubusercontent.com/1133787/47240803-c0c86780-d3e9-11e8-9265-22f735e4d7ed.png) ![install rust](https://user-images.githubusercontent.com/6505554/83944533-82c9c280-a81d-11ea-86b3-ee2e31bc7d12.png)
- Restart CLion/IntelliJ - Restart CLion/IntelliJ
## Configuration ## Configuration
- Open the settings window (File -> Settings) and search for "reformat" ### Run Rustfmt on save
- Open Rustfmt settings (File → Settings → Languages & Frameworks → Rust → Rustfmt) and enable "Run rustfmt on Save"
![run_rustfmt_on_save](https://user-images.githubusercontent.com/6505554/83944610-3468f380-a81e-11ea-9c34-0cbd18dd4969.png)
- IntellJ uses autosave, so now your files will always be formatted according to rustfmt. Alternatively you can use Ctrl+S to reformat file manually
### Bind shortcut to "Reformat File with Rustfmt" action
- Open the settings window (File → Settings) and search for "reformat"
![keymap](https://user-images.githubusercontent.com/1133787/47240922-2ae10c80-d3ea-11e8-9d8f-c798d9749240.png) ![keymap](https://user-images.githubusercontent.com/1133787/47240922-2ae10c80-d3ea-11e8-9d8f-c798d9749240.png)
- Right-click on "Reformat File with Rustfmt" and assign a keyboard shortcut - Right-click on "Reformat File with Rustfmt" and assign a keyboard shortcut

View File

@ -1,2 +0,0 @@
indent_style = "Visual"
combine_control_expr = false

View File

@ -1,3 +1,3 @@
[toolchain] [toolchain]
channel = "nightly-2021-10-20" channel = "nightly-2021-11-08"
components = ["rustc-dev"] components = ["rustc-dev"]

View File

@ -451,7 +451,7 @@ impl Rewrite for [ast::Attribute] {
if next.is_doc_comment() { if next.is_doc_comment() {
let snippet = context.snippet(missing_span); let snippet = context.snippet(missing_span);
let (_, mlb) = has_newlines_before_after_comment(snippet); let (_, mlb) = has_newlines_before_after_comment(snippet);
result.push_str(&mlb); result.push_str(mlb);
} }
} }
result.push('\n'); result.push('\n');
@ -484,7 +484,7 @@ impl Rewrite for [ast::Attribute] {
if next.is_doc_comment() { if next.is_doc_comment() {
let snippet = context.snippet(missing_span); let snippet = context.snippet(missing_span);
let (_, mlb) = has_newlines_before_after_comment(snippet); let (_, mlb) = has_newlines_before_after_comment(snippet);
result.push_str(&mlb); result.push_str(mlb);
} }
} }
result.push('\n'); result.push('\n');

View File

@ -77,7 +77,7 @@ mod tests {
) { ) {
assert_eq!( assert_eq!(
expected_comment, expected_comment,
format!("{}", DocCommentFormatter::new(&literal, style)) format!("{}", DocCommentFormatter::new(literal, style))
); );
} }
} }

View File

@ -20,7 +20,7 @@ use crate::rustfmt::{
}; };
fn main() { fn main() {
env_logger::init(); env_logger::Builder::from_env("RUSTFMT_LOG").init();
let opts = make_opts(); let opts = make_opts();
let exit_code = match execute(&opts) { let exit_code = match execute(&opts) {

View File

@ -401,12 +401,12 @@ fn get_targets_root_only(
fn get_targets_recursive( fn get_targets_recursive(
manifest_path: Option<&Path>, manifest_path: Option<&Path>,
mut targets: &mut BTreeSet<Target>, targets: &mut BTreeSet<Target>,
visited: &mut BTreeSet<String>, visited: &mut BTreeSet<String>,
) -> Result<(), io::Error> { ) -> Result<(), io::Error> {
let metadata = get_cargo_metadata(manifest_path)?; let metadata = get_cargo_metadata(manifest_path)?;
for package in &metadata.packages { for package in &metadata.packages {
add_targets(&package.targets, &mut targets); add_targets(&package.targets, targets);
// Look for local dependencies using information available since cargo v1.51 // Look for local dependencies using information available since cargo v1.51
// It's theoretically possible someone could use a newer version of rustfmt with // It's theoretically possible someone could use a newer version of rustfmt with
@ -427,7 +427,7 @@ fn get_targets_recursive(
.any(|p| p.manifest_path.eq(&manifest_path)) .any(|p| p.manifest_path.eq(&manifest_path))
{ {
visited.insert(dependency.name.to_owned()); visited.insert(dependency.name.to_owned());
get_targets_recursive(Some(&manifest_path), &mut targets, visited)?; get_targets_recursive(Some(&manifest_path), targets, visited)?;
} }
} }
} }

View File

@ -568,7 +568,7 @@ impl<'a> ChainFormatterShared<'a> {
} else { } else {
self.rewrites self.rewrites
.iter() .iter()
.map(|rw| utils::unicode_str_width(&rw)) .map(|rw| utils::unicode_str_width(rw))
.sum() .sum()
} + last.tries; } + last.tries;
let one_line_budget = if self.child_count == 1 { let one_line_budget = if self.child_count == 1 {
@ -673,7 +673,7 @@ impl<'a> ChainFormatterShared<'a> {
ChainItemKind::Comment(_, CommentPosition::Top) => result.push_str(&connector), ChainItemKind::Comment(_, CommentPosition::Top) => result.push_str(&connector),
_ => result.push_str(&connector), _ => result.push_str(&connector),
} }
result.push_str(&rewrite); result.push_str(rewrite);
} }
Some(result) Some(result)

View File

@ -405,7 +405,7 @@ impl CodeBlockAttribute {
/// attributes are valid rust attributes /// attributes are valid rust attributes
/// See <https://doc.rust-lang.org/rustdoc/print.html#attributes> /// See <https://doc.rust-lang.org/rustdoc/print.html#attributes>
fn new(attributes: &str) -> CodeBlockAttribute { fn new(attributes: &str) -> CodeBlockAttribute {
for attribute in attributes.split(",") { for attribute in attributes.split(',') {
match attribute.trim() { match attribute.trim() {
"" | "rust" | "should_panic" | "no_run" | "edition2015" | "edition2018" "" | "rust" | "should_panic" | "no_run" | "edition2015" | "edition2018"
| "edition2021" => (), | "edition2021" => (),
@ -563,7 +563,7 @@ impl<'a> CommentRewrite<'a> {
result.push_str(line); result.push_str(line);
result.push_str(match iter.peek() { result.push_str(match iter.peek() {
Some(next_line) if next_line.is_empty() => sep.trim_end(), Some(next_line) if next_line.is_empty() => sep.trim_end(),
Some(..) => &sep, Some(..) => sep,
None => "", None => "",
}); });
} }
@ -622,7 +622,7 @@ impl<'a> CommentRewrite<'a> {
let is_last = i == count_newlines(orig); let is_last = i == count_newlines(orig);
if let Some(ref mut ib) = self.item_block { if let Some(ref mut ib) = self.item_block {
if ib.add_line(&line) { if ib.add_line(line) {
return false; return false;
} }
self.is_prev_line_multi_line = false; self.is_prev_line_multi_line = false;
@ -684,8 +684,8 @@ impl<'a> CommentRewrite<'a> {
self.item_block = None; self.item_block = None;
if let Some(stripped) = line.strip_prefix("```") { if let Some(stripped) = line.strip_prefix("```") {
self.code_block_attr = Some(CodeBlockAttribute::new(stripped)) self.code_block_attr = Some(CodeBlockAttribute::new(stripped))
} else if self.fmt.config.wrap_comments() && ItemizedBlock::is_itemized_line(&line) { } else if self.fmt.config.wrap_comments() && ItemizedBlock::is_itemized_line(line) {
let ib = ItemizedBlock::new(&line); let ib = ItemizedBlock::new(line);
self.item_block = Some(ib); self.item_block = Some(ib);
return false; return false;
} }
@ -941,7 +941,7 @@ fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle<'_>) -> (&'a s
{ {
(&line[4..], true) (&line[4..], true)
} else if let CommentStyle::Custom(opener) = *style { } else if let CommentStyle::Custom(opener) = *style {
if let Some(ref stripped) = line.strip_prefix(opener) { if let Some(stripped) = line.strip_prefix(opener) {
(stripped, true) (stripped, true)
} else { } else {
(&line[opener.trim_end().len()..], false) (&line[opener.trim_end().len()..], false)
@ -1384,7 +1384,7 @@ impl<'a> Iterator for LineClasses<'a> {
None => unreachable!(), None => unreachable!(),
}; };
while let Some((kind, c)) = self.base.next() { for (kind, c) in self.base.by_ref() {
// needed to set the kind of the ending character on the last line // needed to set the kind of the ending character on the last line
self.kind = kind; self.kind = kind;
if c == '\n' { if c == '\n' {
@ -1570,7 +1570,7 @@ pub(crate) fn recover_comment_removed(
context.parse_sess.span_to_filename(span), context.parse_sess.span_to_filename(span),
vec![FormattingError::from_span( vec![FormattingError::from_span(
span, span,
&context.parse_sess, context.parse_sess,
ErrorKind::LostComment, ErrorKind::LostComment,
)], )],
); );
@ -1675,7 +1675,7 @@ impl<'a> Iterator for CommentReducer<'a> {
fn remove_comment_header(comment: &str) -> &str { fn remove_comment_header(comment: &str) -> &str {
if comment.starts_with("///") || comment.starts_with("//!") { if comment.starts_with("///") || comment.starts_with("//!") {
&comment[3..] &comment[3..]
} else if let Some(ref stripped) = comment.strip_prefix("//") { } else if let Some(stripped) = comment.strip_prefix("//") {
stripped stripped
} else if (comment.starts_with("/**") && !comment.starts_with("/**/")) } else if (comment.starts_with("/**") && !comment.starts_with("/**/"))
|| comment.starts_with("/*!") || comment.starts_with("/*!")

View File

@ -20,7 +20,7 @@ pub enum NewlineStyle {
Windows, Windows,
/// Force CR (`\n). /// Force CR (`\n).
Unix, Unix,
/// `\r\n` in Windows, `\n`` on other platforms. /// `\r\n` in Windows, `\n` on other platforms.
Native, Native,
} }
@ -112,6 +112,8 @@ pub enum GroupImportsTactic {
/// 2. other imports /// 2. other imports
/// 3. `self` / `crate` / `super` imports /// 3. `self` / `crate` / `super` imports
StdExternalCrate, StdExternalCrate,
/// Discard existing groups, and create a single group for everything
One,
} }
#[config_type] #[config_type]

View File

@ -121,7 +121,7 @@ mod tests {
format!(r#"<file name="{}">"#, bin_file), format!(r#"<file name="{}">"#, bin_file),
format!( format!(
r#"<error line="2" severity="warning" message="Should be `{}`" />"#, r#"<error line="2" severity="warning" message="Should be `{}`" />"#,
XmlEscaped(&r#" println!("Hello, world!");"#), XmlEscaped(r#" println!("Hello, world!");"#),
), ),
String::from("</file>"), String::from("</file>"),
]; ];
@ -129,7 +129,7 @@ mod tests {
format!(r#"<file name="{}">"#, lib_file), format!(r#"<file name="{}">"#, lib_file),
format!( format!(
r#"<error line="2" severity="warning" message="Should be `{}`" />"#, r#"<error line="2" severity="warning" message="Should be `{}`" />"#,
XmlEscaped(&r#" println!("Greetings!");"#), XmlEscaped(r#" println!("Greetings!");"#),
), ),
String::from("</file>"), String::from("</file>"),
]; ];

View File

@ -23,7 +23,7 @@ impl Emitter for DiffEmitter {
}: FormattedFile<'_>, }: FormattedFile<'_>,
) -> Result<EmitterResult, io::Error> { ) -> Result<EmitterResult, io::Error> {
const CONTEXT_SIZE: usize = 3; const CONTEXT_SIZE: usize = 3;
let mismatch = make_diff(&original_text, formatted_text, CONTEXT_SIZE); let mismatch = make_diff(original_text, formatted_text, CONTEXT_SIZE);
let has_diff = !mismatch.is_empty(); let has_diff = !mismatch.is_empty();
if has_diff { if has_diff {

View File

@ -257,7 +257,7 @@ pub(crate) fn format_expr(
} }
_ => false, _ => false,
}, },
ast::ExprKind::Unary(_, ref expr) => needs_space_before_range(context, &expr), ast::ExprKind::Unary(_, ref expr) => needs_space_before_range(context, expr),
_ => false, _ => false,
} }
} }
@ -423,7 +423,7 @@ fn rewrite_empty_block(
prefix: &str, prefix: &str,
shape: Shape, shape: Shape,
) -> Option<String> { ) -> Option<String> {
if block_has_statements(&block) { if block_has_statements(block) {
return None; return None;
} }
@ -1148,7 +1148,7 @@ pub(crate) fn is_empty_block(
block: &ast::Block, block: &ast::Block,
attrs: Option<&[ast::Attribute]>, attrs: Option<&[ast::Attribute]>,
) -> bool { ) -> bool {
!block_has_statements(&block) !block_has_statements(block)
&& !block_contains_comment(context, block) && !block_contains_comment(context, block)
&& attrs.map_or(true, |a| inner_attributes(a).is_empty()) && attrs.map_or(true, |a| inner_attributes(a).is_empty())
} }
@ -1207,11 +1207,11 @@ fn rewrite_int_lit(context: &RewriteContext<'_>, lit: &ast::Lit, shape: Shape) -
let span = lit.span; let span = lit.span;
let symbol = lit.token.symbol.as_str(); let symbol = lit.token.symbol.as_str();
if symbol.starts_with("0x") { if let Some(symbol_stripped) = symbol.strip_prefix("0x") {
let hex_lit = match context.config.hex_literal_case() { let hex_lit = match context.config.hex_literal_case() {
HexLiteralCase::Preserve => None, HexLiteralCase::Preserve => None,
HexLiteralCase::Upper => Some(symbol[2..].to_ascii_uppercase()), HexLiteralCase::Upper => Some(symbol_stripped.to_ascii_uppercase()),
HexLiteralCase::Lower => Some(symbol[2..].to_ascii_lowercase()), HexLiteralCase::Lower => Some(symbol_stripped.to_ascii_lowercase()),
}; };
if let Some(hex_lit) = hex_lit { if let Some(hex_lit) = hex_lit {
return wrap_str( return wrap_str(
@ -1621,7 +1621,7 @@ fn rewrite_struct_lit<'a>(
}; };
let fields_str = let fields_str =
wrap_struct_field(context, &attrs, &fields_str, shape, v_shape, one_line_width)?; wrap_struct_field(context, attrs, &fields_str, shape, v_shape, one_line_width)?;
Some(format!("{} {{{}}}", path_str, fields_str)) Some(format!("{} {{{}}}", path_str, fields_str))
// FIXME if context.config.indent_style() == Visual, but we run out // FIXME if context.config.indent_style() == Visual, but we run out
@ -1888,7 +1888,7 @@ pub(crate) fn rewrite_assign_rhs_expr<R: Rewrite>(
shape: Shape, shape: Shape,
rhs_tactics: RhsTactics, rhs_tactics: RhsTactics,
) -> Option<String> { ) -> Option<String> {
let last_line_width = last_line_width(&lhs).saturating_sub(if lhs.contains('\n') { let last_line_width = last_line_width(lhs).saturating_sub(if lhs.contains('\n') {
shape.indent.width() shape.indent.width()
} else { } else {
0 0
@ -1947,7 +1947,7 @@ pub(crate) fn rewrite_assign_rhs_with_comments<S: Into<String>, R: Rewrite>(
if contains_comment { if contains_comment {
let rhs = rhs.trim_start(); let rhs = rhs.trim_start();
combine_strs_with_missing_comments(context, &lhs, &rhs, between_span, shape, allow_extend) combine_strs_with_missing_comments(context, &lhs, rhs, between_span, shape, allow_extend)
} else { } else {
Some(lhs + &rhs) Some(lhs + &rhs)
} }
@ -1962,6 +1962,9 @@ fn choose_rhs<R: Rewrite>(
has_rhs_comment: bool, has_rhs_comment: bool,
) -> Option<String> { ) -> Option<String> {
match orig_rhs { match orig_rhs {
Some(ref new_str) if new_str.is_empty() => {
return Some(String::new());
}
Some(ref new_str) Some(ref new_str)
if !new_str.contains('\n') && unicode_str_width(new_str) <= shape.width => if !new_str.contains('\n') && unicode_str_width(new_str) <= shape.width =>
{ {

View File

@ -64,7 +64,7 @@ pub struct Opts {
} }
fn main() { fn main() {
env_logger::init(); env_logger::Builder::from_env("RUSTFMT_LOG").init();
let opts = Opts::from_args(); let opts = Opts::from_args();
if let Err(e) = run(opts) { if let Err(e) = run(opts) {
println!("{}", e); println!("{}", e);

View File

@ -155,7 +155,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> {
let snippet_provider = self.parse_session.snippet_provider(module.span); let snippet_provider = self.parse_session.snippet_provider(module.span);
let mut visitor = FmtVisitor::from_parse_sess( let mut visitor = FmtVisitor::from_parse_sess(
&self.parse_session, &self.parse_session,
&self.config, self.config,
&snippet_provider, &snippet_provider,
self.report.clone(), self.report.clone(),
); );
@ -180,7 +180,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> {
&mut visitor.buffer, &mut visitor.buffer,
&path, &path,
&visitor.skipped_range.borrow(), &visitor.skipped_range.borrow(),
&self.config, self.config,
&self.report, &self.report,
); );

View File

@ -170,7 +170,7 @@ impl Config {
} }
fn main() { fn main() {
env_logger::init(); env_logger::Builder::from_env("RUSTFMT_LOG").init();
let opts = make_opts(); let opts = make_opts();
let matches = opts let matches = opts

View File

@ -275,7 +275,7 @@ impl UseTree {
shape: Shape, shape: Shape,
) -> Option<String> { ) -> Option<String> {
let vis = self.visibility.as_ref().map_or(Cow::from(""), |vis| { let vis = self.visibility.as_ref().map_or(Cow::from(""), |vis| {
crate::utils::format_visibility(context, &vis) crate::utils::format_visibility(context, vis)
}); });
let use_str = self let use_str = self
.rewrite(context, shape.offset_left(vis.len())?) .rewrite(context, shape.offset_left(vis.len())?)
@ -929,7 +929,7 @@ impl Rewrite for UseTree {
fn rewrite(&self, context: &RewriteContext<'_>, mut shape: Shape) -> Option<String> { fn rewrite(&self, context: &RewriteContext<'_>, mut shape: Shape) -> Option<String> {
let mut result = String::with_capacity(256); let mut result = String::with_capacity(256);
let mut iter = self.path.iter().peekable(); let mut iter = self.path.iter().peekable();
while let Some(ref segment) = iter.next() { while let Some(segment) = iter.next() {
let segment_str = segment.rewrite(context, shape)?; let segment_str = segment.rewrite(context, shape)?;
result.push_str(&segment_str); result.push_str(&segment_str);
if iter.peek().is_some() { if iter.peek().is_some() {

View File

@ -226,7 +226,7 @@ impl<'a> FnSig<'a> {
fn to_str(&self, context: &RewriteContext<'_>) -> String { fn to_str(&self, context: &RewriteContext<'_>) -> String {
let mut result = String::with_capacity(128); let mut result = String::with_capacity(128);
// Vis defaultness constness unsafety abi. // Vis defaultness constness unsafety abi.
result.push_str(&*format_visibility(context, &self.visibility)); result.push_str(&*format_visibility(context, self.visibility));
result.push_str(format_defaultness(self.defaultness)); result.push_str(format_defaultness(self.defaultness));
result.push_str(format_constness(self.constness)); result.push_str(format_constness(self.constness));
result.push_str(format_async(&self.is_async)); result.push_str(format_async(&self.is_async));
@ -1127,12 +1127,24 @@ pub(crate) fn format_trait(
} }
} }
let block_span = mk_sp(generics.where_clause.span.hi(), item.span.hi());
let snippet = context.snippet(block_span);
let open_pos = snippet.find_uncommented("{")? + 1;
match context.config.brace_style() { match context.config.brace_style() {
_ if last_line_contains_single_line_comment(&result) _ if last_line_contains_single_line_comment(&result)
|| last_line_width(&result) + 2 > context.budget(offset.width()) => || last_line_width(&result) + 2 > context.budget(offset.width()) =>
{ {
result.push_str(&offset.to_string_with_newline(context.config)); result.push_str(&offset.to_string_with_newline(context.config));
} }
_ if context.config.empty_item_single_line()
&& items.is_empty()
&& !result.contains('\n')
&& !contains_comment(&snippet[open_pos..]) =>
{
result.push_str(" {}");
return Some(result);
}
BraceStyle::AlwaysNextLine => { BraceStyle::AlwaysNextLine => {
result.push_str(&offset.to_string_with_newline(context.config)); result.push_str(&offset.to_string_with_newline(context.config));
} }
@ -1149,9 +1161,6 @@ pub(crate) fn format_trait(
} }
result.push('{'); result.push('{');
let block_span = mk_sp(generics.where_clause.span.hi(), item.span.hi());
let snippet = context.snippet(block_span);
let open_pos = snippet.find_uncommented("{")? + 1;
let outer_indent_str = offset.block_only().to_string_with_newline(context.config); let outer_indent_str = offset.block_only().to_string_with_newline(context.config);
if !items.is_empty() || contains_comment(&snippet[open_pos..]) { if !items.is_empty() || contains_comment(&snippet[open_pos..]) {
@ -1181,18 +1190,6 @@ pub(crate) fn format_trait(
} }
} }
struct OpaqueTypeBounds<'a> {
generic_bounds: &'a ast::GenericBounds,
}
impl<'a> Rewrite for OpaqueTypeBounds<'a> {
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
self.generic_bounds
.rewrite(context, shape)
.map(|s| format!("impl {}", s))
}
}
pub(crate) struct TraitAliasBounds<'a> { pub(crate) struct TraitAliasBounds<'a> {
generic_bounds: &'a ast::GenericBounds, generic_bounds: &'a ast::GenericBounds,
generics: &'a ast::Generics, generics: &'a ast::Generics,
@ -1225,7 +1222,7 @@ impl<'a> Rewrite for TraitAliasBounds<'a> {
} else if fits_single_line { } else if fits_single_line {
Cow::from(" ") Cow::from(" ")
} else { } else {
shape.indent.to_string_with_newline(&context.config) shape.indent.to_string_with_newline(context.config)
}; };
Some(format!("{}{}{}", generic_bounds_str, space, where_str)) Some(format!("{}{}{}", generic_bounds_str, space, where_str))
@ -1243,7 +1240,7 @@ pub(crate) fn format_trait_alias(
let alias = rewrite_ident(context, ident); let alias = rewrite_ident(context, ident);
// 6 = "trait ", 2 = " =" // 6 = "trait ", 2 = " ="
let g_shape = shape.offset_left(6)?.sub_width(2)?; let g_shape = shape.offset_left(6)?.sub_width(2)?;
let generics_str = rewrite_generics(context, &alias, generics, g_shape)?; let generics_str = rewrite_generics(context, alias, generics, g_shape)?;
let vis_str = format_visibility(context, vis); let vis_str = format_visibility(context, vis);
let lhs = format!("{}trait {} =", vis_str, generics_str); let lhs = format!("{}trait {} =", vis_str, generics_str);
// 1 = ";" // 1 = ";"
@ -1391,7 +1388,7 @@ fn format_empty_struct_or_tuple(
closer: &str, closer: &str,
) { ) {
// 3 = " {}" or "();" // 3 = " {}" or "();"
let used_width = last_line_used_width(&result, offset.width()) + 3; let used_width = last_line_used_width(result, offset.width()) + 3;
if used_width > context.config.max_width() { if used_width > context.config.max_width() {
result.push_str(&offset.to_string_with_newline(context.config)) result.push_str(&offset.to_string_with_newline(context.config))
} }
@ -1514,17 +1511,84 @@ fn format_tuple_struct(
Some(result) Some(result)
} }
pub(crate) fn rewrite_type<R: Rewrite>( pub(crate) enum ItemVisitorKind<'a> {
context: &RewriteContext<'_>, Item(&'a ast::Item),
AssocTraitItem(&'a ast::AssocItem),
AssocImplItem(&'a ast::AssocItem),
ForeignItem(&'a ast::ForeignItem),
}
struct TyAliasRewriteInfo<'c, 'g>(
&'c RewriteContext<'c>,
Indent,
&'g ast::Generics,
symbol::Ident,
Span,
);
pub(crate) fn rewrite_type_alias<'a, 'b>(
ty_alias_kind: &ast::TyAlias,
context: &RewriteContext<'a>,
indent: Indent, indent: Indent,
ident: symbol::Ident, visitor_kind: &ItemVisitorKind<'b>,
vis: &ast::Visibility,
generics: &ast::Generics,
generic_bounds_opt: Option<&ast::GenericBounds>,
rhs: Option<&R>,
span: Span, span: Span,
) -> Option<String> {
use ItemVisitorKind::*;
let ast::TyAlias {
defaultness,
ref generics,
ref bounds,
ref ty,
} = *ty_alias_kind;
let ty_opt = ty.as_ref().map(|t| &**t);
let (ident, vis) = match visitor_kind {
Item(i) => (i.ident, &i.vis),
AssocTraitItem(i) | AssocImplItem(i) => (i.ident, &i.vis),
ForeignItem(i) => (i.ident, &i.vis),
};
let rw_info = &TyAliasRewriteInfo(context, indent, generics, ident, span);
// Type Aliases are formatted slightly differently depending on the context
// in which they appear, whether they are opaque, and whether they are associated.
// https://rustc-dev-guide.rust-lang.org/opaque-types-type-alias-impl-trait.html
// https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/items.md#type-aliases
match (visitor_kind, ty_opt) {
(Item(_), None) => {
let op_ty = OpaqueType { bounds };
rewrite_ty(rw_info, Some(bounds), Some(&op_ty), vis)
}
(Item(_), Some(ty)) => rewrite_ty(rw_info, Some(bounds), Some(&*ty), vis),
(AssocImplItem(_), _) => {
let result = if let Some(ast::Ty {
kind: ast::TyKind::ImplTrait(_, ref bounds),
..
}) = ty_opt
{
let op_ty = OpaqueType { bounds };
rewrite_ty(rw_info, None, Some(&op_ty), &DEFAULT_VISIBILITY)
} else {
rewrite_ty(rw_info, None, ty.as_ref(), vis)
}?;
match defaultness {
ast::Defaultness::Default(..) => Some(format!("default {}", result)),
_ => Some(result),
}
}
(AssocTraitItem(_), _) | (ForeignItem(_), _) => {
rewrite_ty(rw_info, Some(bounds), ty.as_ref(), vis)
}
}
}
fn rewrite_ty<R: Rewrite>(
rw_info: &TyAliasRewriteInfo<'_, '_>,
generic_bounds_opt: Option<&ast::GenericBounds>,
rhs: Option<&R>,
vis: &ast::Visibility,
) -> Option<String> { ) -> Option<String> {
let mut result = String::with_capacity(128); let mut result = String::with_capacity(128);
let TyAliasRewriteInfo(context, indent, generics, ident, span) = *rw_info;
result.push_str(&format!("{}type ", format_visibility(context, vis))); result.push_str(&format!("{}type ", format_visibility(context, vis)));
let ident_str = rewrite_ident(context, ident); let ident_str = rewrite_ident(context, ident);
@ -1612,28 +1676,6 @@ pub(crate) fn rewrite_type<R: Rewrite>(
} }
} }
pub(crate) fn rewrite_opaque_type(
context: &RewriteContext<'_>,
indent: Indent,
ident: symbol::Ident,
generic_bounds: &ast::GenericBounds,
generics: &ast::Generics,
vis: &ast::Visibility,
span: Span,
) -> Option<String> {
let opaque_type_bounds = OpaqueTypeBounds { generic_bounds };
rewrite_type(
context,
indent,
ident,
vis,
generics,
Some(generic_bounds),
Some(&opaque_type_bounds),
span,
)
}
fn type_annotation_spacing(config: &Config) -> (&str, &str) { fn type_annotation_spacing(config: &Config) -> (&str, &str) {
( (
if config.space_before_colon() { " " } else { "" }, if config.space_before_colon() { " " } else { "" },
@ -1871,42 +1913,6 @@ impl<'a> Rewrite for OpaqueType<'a> {
} }
} }
pub(crate) fn rewrite_impl_type(
ident: symbol::Ident,
vis: &ast::Visibility,
defaultness: ast::Defaultness,
ty_opt: Option<&ptr::P<ast::Ty>>,
generics: &ast::Generics,
context: &RewriteContext<'_>,
indent: Indent,
span: Span,
) -> Option<String> {
// Opaque type
let result = if let Some(rustc_ast::ast::Ty {
kind: ast::TyKind::ImplTrait(_, ref bounds),
..
}) = ty_opt.map(|t| &**t)
{
rewrite_type(
context,
indent,
ident,
&DEFAULT_VISIBILITY,
generics,
None,
Some(&OpaqueType { bounds }),
span,
)
} else {
rewrite_type(context, indent, ident, vis, generics, None, ty_opt, span)
}?;
match defaultness {
ast::Defaultness::Default(..) => Some(format!("default {}", result)),
_ => Some(result),
}
}
impl Rewrite for ast::FnRetTy { impl Rewrite for ast::FnRetTy {
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
match *self { match *self {
@ -2071,7 +2077,7 @@ fn rewrite_explicit_self(
)?; )?;
Some(combine_strs_with_missing_comments( Some(combine_strs_with_missing_comments(
context, context,
&param_attrs, param_attrs,
&format!("&{} {}self", lifetime_str, mut_str), &format!("&{} {}self", lifetime_str, mut_str),
span, span,
shape, shape,
@ -2080,7 +2086,7 @@ fn rewrite_explicit_self(
} }
None => Some(combine_strs_with_missing_comments( None => Some(combine_strs_with_missing_comments(
context, context,
&param_attrs, param_attrs,
&format!("&{}self", mut_str), &format!("&{}self", mut_str),
span, span,
shape, shape,
@ -2096,7 +2102,7 @@ fn rewrite_explicit_self(
Some(combine_strs_with_missing_comments( Some(combine_strs_with_missing_comments(
context, context,
&param_attrs, param_attrs,
&format!("{}self: {}", format_mutability(mutability), type_str), &format!("{}self: {}", format_mutability(mutability), type_str),
span, span,
shape, shape,
@ -2105,7 +2111,7 @@ fn rewrite_explicit_self(
} }
ast::SelfKind::Value(mutability) => Some(combine_strs_with_missing_comments( ast::SelfKind::Value(mutability) => Some(combine_strs_with_missing_comments(
context, context,
&param_attrs, param_attrs,
&format!("{}self", format_mutability(mutability)), &format!("{}self", format_mutability(mutability)),
span, span,
shape, shape,
@ -2231,7 +2237,7 @@ fn rewrite_fn_base(
} }
// Skip `pub(crate)`. // Skip `pub(crate)`.
let lo_after_visibility = get_bytepos_after_visibility(&fn_sig.visibility, span); let lo_after_visibility = get_bytepos_after_visibility(fn_sig.visibility, span);
// A conservative estimation, the goal is to be over all parens in generics // A conservative estimation, the goal is to be over all parens in generics
let params_start = fn_sig let params_start = fn_sig
.generics .generics
@ -2989,7 +2995,7 @@ fn format_header(
let mut result = String::with_capacity(128); let mut result = String::with_capacity(128);
let shape = Shape::indented(offset, context.config); let shape = Shape::indented(offset, context.config);
result.push_str(&format_visibility(context, vis).trim()); result.push_str(format_visibility(context, vis).trim());
// Check for a missing comment between the visibility and the item name. // Check for a missing comment between the visibility and the item name.
let after_vis = vis.span.hi(); let after_vis = vis.span.hi();
@ -3010,7 +3016,7 @@ fn format_header(
} }
} }
result.push_str(&rewrite_ident(context, ident)); result.push_str(rewrite_ident(context, ident));
result result
} }
@ -3177,23 +3183,9 @@ impl Rewrite for ast::ForeignItem {
// 1 = ; // 1 = ;
rewrite_assign_rhs(context, prefix, &**ty, shape.sub_width(1)?).map(|s| s + ";") rewrite_assign_rhs(context, prefix, &**ty, shape.sub_width(1)?).map(|s| s + ";")
} }
ast::ForeignItemKind::TyAlias(ref ty_alias_kind) => { ast::ForeignItemKind::TyAlias(ref ty_alias) => {
let ast::TyAlias { let (kind, span) = (&ItemVisitorKind::ForeignItem(&self), self.span);
ref generics, rewrite_type_alias(ty_alias, context, shape.indent, kind, span)
ref bounds,
ref ty,
..
} = **ty_alias_kind;
rewrite_type(
&context,
shape.indent,
self.ident,
&self.vis,
generics,
Some(bounds),
ty.as_ref(),
self.span,
)
} }
ast::ForeignItemKind::MacCall(ref mac) => { ast::ForeignItemKind::MacCall(ref mac) => {
rewrite_macro(mac, None, context, shape, MacroPosition::Item) rewrite_macro(mac, None, context, shape, MacroPosition::Item)
@ -3243,7 +3235,7 @@ fn rewrite_attrs(
combine_strs_with_missing_comments( combine_strs_with_missing_comments(
context, context,
&attrs_str, &attrs_str,
&item_str, item_str,
missed_span, missed_span,
shape, shape,
allow_extend, allow_extend,

View File

@ -283,7 +283,7 @@ impl FormatReport {
writeln!( writeln!(
t, t,
"{}", "{}",
FormatReportFormatterBuilder::new(&self) FormatReportFormatterBuilder::new(self)
.enable_colors(true) .enable_colors(true)
.build() .build()
)?; )?;
@ -297,7 +297,7 @@ impl FormatReport {
impl fmt::Display for FormatReport { impl fmt::Display for FormatReport {
// Prints all the formatting errors. // Prints all the formatting errors.
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(fmt, "{}", FormatReportFormatterBuilder::new(&self).build())?; write!(fmt, "{}", FormatReportFormatterBuilder::new(self).build())?;
Ok(()) Ok(())
} }
} }

View File

@ -386,7 +386,7 @@ where
result.push('\n'); result.push('\n');
result.push_str(indent_str); result.push_str(indent_str);
// This is the width of the item (without comments). // This is the width of the item (without comments).
line_len = item.item.as_ref().map_or(0, |s| unicode_str_width(&s)); line_len = item.item.as_ref().map_or(0, |s| unicode_str_width(s));
} }
} else { } else {
result.push(' ') result.push(' ')
@ -820,7 +820,7 @@ where
pub(crate) fn total_item_width(item: &ListItem) -> usize { pub(crate) fn total_item_width(item: &ListItem) -> usize {
comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..])) comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..]))
+ comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) + comment_len(item.post_comment.as_ref().map(|x| &(*x)[..]))
+ item.item.as_ref().map_or(0, |s| unicode_str_width(&s)) + item.item.as_ref().map_or(0, |s| unicode_str_width(s))
} }
fn comment_len(comment: Option<&str>) -> usize { fn comment_len(comment: Option<&str>) -> usize {

View File

@ -186,7 +186,7 @@ fn return_macro_parse_failure_fallback(
}) })
.unwrap_or(false); .unwrap_or(false);
if is_like_block_indent_style { if is_like_block_indent_style {
return trim_left_preserve_layout(context.snippet(span), indent, &context.config); return trim_left_preserve_layout(context.snippet(span), indent, context.config);
} }
context.skipped_range.borrow_mut().push(( context.skipped_range.borrow_mut().push((
@ -437,7 +437,7 @@ fn rewrite_macro_inner(
// the `macro_name!` and `{ /* macro_body */ }` but skip modifying // the `macro_name!` and `{ /* macro_body */ }` but skip modifying
// anything in between the braces (for now). // anything in between the braces (for now).
let snippet = context.snippet(mac.span()).trim_start_matches(|c| c != '{'); let snippet = context.snippet(mac.span()).trim_start_matches(|c| c != '{');
match trim_left_preserve_layout(snippet, shape.indent, &context.config) { match trim_left_preserve_layout(snippet, shape.indent, context.config) {
Some(macro_body) => Some(format!("{} {}", macro_name, macro_body)), Some(macro_body) => Some(format!("{} {}", macro_name, macro_body)),
None => Some(format!("{} {}", macro_name, snippet)), None => Some(format!("{} {}", macro_name, snippet)),
} }
@ -901,7 +901,7 @@ impl MacroArgParser {
break; break;
} }
TokenTree::Token(ref t) => { TokenTree::Token(ref t) => {
buffer.push_str(&pprust::token_to_string(&t)); buffer.push_str(&pprust::token_to_string(t));
} }
_ => return None, _ => return None,
} }
@ -1045,7 +1045,7 @@ fn wrap_macro_args_inner(
let mut iter = args.iter().peekable(); let mut iter = args.iter().peekable();
let indent_str = shape.indent.to_string_with_newline(context.config); let indent_str = shape.indent.to_string_with_newline(context.config);
while let Some(ref arg) = iter.next() { while let Some(arg) = iter.next() {
result.push_str(&arg.rewrite(context, shape, use_multiple_lines)?); result.push_str(&arg.rewrite(context, shape, use_multiple_lines)?);
if use_multiple_lines if use_multiple_lines
@ -1055,7 +1055,7 @@ fn wrap_macro_args_inner(
result.pop(); result.pop();
} }
result.push_str(&indent_str); result.push_str(&indent_str);
} else if let Some(ref next_arg) = iter.peek() { } else if let Some(next_arg) = iter.peek() {
let space_before_dollar = let space_before_dollar =
!arg.kind.ends_with_space() && next_arg.kind.starts_with_dollar(); !arg.kind.ends_with_space() && next_arg.kind.starts_with_dollar();
let space_before_brace = next_arg.kind.starts_with_brace(); let space_before_brace = next_arg.kind.starts_with_brace();
@ -1370,7 +1370,7 @@ impl MacroBranch {
{ {
s += &indent_str; s += &indent_str;
} }
(s + l + "\n", indent_next_line(kind, &l, &config)) (s + l + "\n", indent_next_line(kind, l, &config))
}, },
) )
.0; .0;
@ -1514,11 +1514,11 @@ fn rewrite_macro_with_items(
MacroArg::Item(item) => item, MacroArg::Item(item) => item,
_ => return None, _ => return None,
}; };
visitor.visit_item(&item); visitor.visit_item(item);
} }
let mut result = String::with_capacity(256); let mut result = String::with_capacity(256);
result.push_str(&macro_name); result.push_str(macro_name);
result.push_str(opener); result.push_str(opener);
result.push_str(&visitor.block_indent.to_string_with_newline(context.config)); result.push_str(&visitor.block_indent.to_string_with_newline(context.config));
result.push_str(visitor.buffer.trim()); result.push_str(visitor.buffer.trim());

View File

@ -168,7 +168,7 @@ fn collect_beginning_verts(
.map(|a| { .map(|a| {
context context
.snippet(a.pat.span) .snippet(a.pat.span)
.starts_with("|") .starts_with('|')
.then(|| a.pat.span().lo()) .then(|| a.pat.span().lo())
}) })
.collect() .collect()
@ -319,7 +319,7 @@ fn flatten_arm_body<'a>(
let can_extend = let can_extend =
|expr| !context.config.force_multiline_blocks() && can_flatten_block_around_this(expr); |expr| !context.config.force_multiline_blocks() && can_flatten_block_around_this(expr);
if let Some(ref block) = block_can_be_flattened(context, body) { if let Some(block) = block_can_be_flattened(context, body) {
if let ast::StmtKind::Expr(ref expr) = block.stmts[0].kind { if let ast::StmtKind::Expr(ref expr) = block.stmts[0].kind {
if let ast::ExprKind::Block(..) = expr.kind { if let ast::ExprKind::Block(..) = expr.kind {
flatten_arm_body(context, expr, None) flatten_arm_body(context, expr, None)
@ -393,7 +393,7 @@ fn rewrite_match_body(
if comment_str.is_empty() { if comment_str.is_empty() {
String::new() String::new()
} else { } else {
rewrite_comment(comment_str, false, shape, &context.config)? rewrite_comment(comment_str, false, shape, context.config)?
} }
}; };
@ -408,8 +408,8 @@ fn rewrite_match_body(
result.push_str(&arrow_comment); result.push_str(&arrow_comment);
} }
result.push_str(&nested_indent_str); result.push_str(&nested_indent_str);
result.push_str(&body_str); result.push_str(body_str);
result.push_str(&comma); result.push_str(comma);
return Some(result); return Some(result);
} }
@ -451,7 +451,7 @@ fn rewrite_match_body(
result.push_str(&arrow_comment); result.push_str(&arrow_comment);
} }
result.push_str(&block_sep); result.push_str(&block_sep);
result.push_str(&body_str); result.push_str(body_str);
result.push_str(&body_suffix); result.push_str(&body_suffix);
Some(result) Some(result)
}; };

View File

@ -16,7 +16,7 @@ use crate::syntux::parser::{
Directory, DirectoryOwnership, ModError, ModulePathSuccess, Parser, ParserError, Directory, DirectoryOwnership, ModError, ModulePathSuccess, Parser, ParserError,
}; };
use crate::syntux::session::ParseSess; use crate::syntux::session::ParseSess;
use crate::utils::contains_skip; use crate::utils::{contains_skip, mk_sp};
mod visitor; mod visitor;
@ -135,10 +135,12 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
self.visit_mod_from_ast(&krate.items)?; self.visit_mod_from_ast(&krate.items)?;
} }
let snippet_provider = self.parse_sess.snippet_provider(krate.span);
self.file_map.insert( self.file_map.insert(
root_filename, root_filename,
Module::new( Module::new(
krate.span, mk_sp(snippet_provider.start_pos(), snippet_provider.end_pos()),
None, None,
Cow::Borrowed(&krate.items), Cow::Borrowed(&krate.items),
Cow::Borrowed(&krate.attrs), Cow::Borrowed(&krate.attrs),
@ -197,7 +199,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
/// Visit modules from AST. /// Visit modules from AST.
fn visit_mod_from_ast( fn visit_mod_from_ast(
&mut self, &mut self,
items: &'ast Vec<rustc_ast::ptr::P<ast::Item>>, items: &'ast [rustc_ast::ptr::P<ast::Item>],
) -> Result<(), ModuleResolutionError> { ) -> Result<(), ModuleResolutionError> {
for item in items { for item in items {
if is_cfg_if(item) { if is_cfg_if(item) {
@ -290,7 +292,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
}; };
self.visit_sub_mod_after_directory_update(sub_mod, Some(directory)) self.visit_sub_mod_after_directory_update(sub_mod, Some(directory))
} }
SubModKind::Internal(ref item) => { SubModKind::Internal(item) => {
self.push_inline_mod_directory(item.ident, &item.attrs); self.push_inline_mod_directory(item.ident, &item.attrs);
self.visit_sub_mod_after_directory_update(sub_mod, None) self.visit_sub_mod_after_directory_update(sub_mod, None)
} }
@ -317,9 +319,11 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
} }
match (sub_mod.ast_mod_kind, sub_mod.items) { match (sub_mod.ast_mod_kind, sub_mod.items) {
(Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _))), _) => { (Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _))), _) => {
self.visit_mod_from_ast(&items) self.visit_mod_from_ast(items)
}
(Some(Cow::Owned(ast::ModKind::Loaded(items, _, _))), _) | (_, Cow::Owned(items)) => {
self.visit_mod_outside_ast(items)
} }
(Some(Cow::Owned(..)), Cow::Owned(items)) => self.visit_mod_outside_ast(items),
(_, _) => Ok(()), (_, _) => Ok(()),
} }
} }

View File

@ -394,7 +394,7 @@ impl<'a> Context<'a> {
) -> Option<String> { ) -> Option<String> {
let last_item = self.last_item()?; let last_item = self.last_item()?;
let rewrite = match last_item { let rewrite = match last_item {
OverflowableItem::Expr(ref expr) => { OverflowableItem::Expr(expr) => {
match expr.kind { match expr.kind {
// When overflowing the closure which consists of a single control flow // When overflowing the closure which consists of a single control flow
// expression, force to use block if its condition uses multi line. // expression, force to use block if its condition uses multi line.

View File

@ -55,11 +55,11 @@ fn rewrite_pairs_one_line<T: Rewrite>(
for ((_, rewrite), s) in list.list.iter().zip(list.separators.iter()) { for ((_, rewrite), s) in list.list.iter().zip(list.separators.iter()) {
if let Some(rewrite) = rewrite { if let Some(rewrite) = rewrite {
if !is_single_line(&rewrite) || result.len() > shape.width { if !is_single_line(rewrite) || result.len() > shape.width {
return None; return None;
} }
result.push_str(&rewrite); result.push_str(rewrite);
result.push(' '); result.push(' ');
result.push_str(s); result.push_str(s);
result.push(' '); result.push(' ');
@ -94,18 +94,18 @@ fn rewrite_pairs_multiline<T: Rewrite>(
shape: Shape, shape: Shape,
context: &RewriteContext<'_>, context: &RewriteContext<'_>,
) -> Option<String> { ) -> Option<String> {
let rhs_offset = shape.rhs_overhead(&context.config); let rhs_offset = shape.rhs_overhead(context.config);
let nested_shape = (match context.config.indent_style() { let nested_shape = (match context.config.indent_style() {
IndentStyle::Visual => shape.visual_indent(0), IndentStyle::Visual => shape.visual_indent(0),
IndentStyle::Block => shape.block_indent(context.config.tab_spaces()), IndentStyle::Block => shape.block_indent(context.config.tab_spaces()),
}) })
.with_max_width(&context.config) .with_max_width(context.config)
.sub_width(rhs_offset)?; .sub_width(rhs_offset)?;
let indent_str = nested_shape.indent.to_string_with_newline(context.config); let indent_str = nested_shape.indent.to_string_with_newline(context.config);
let mut result = String::new(); let mut result = String::new();
result.push_str(&list.list[0].1.as_ref()?); result.push_str(list.list[0].1.as_ref()?);
for ((e, default_rw), s) in list.list[1..].iter().zip(list.separators.iter()) { for ((e, default_rw), s) in list.list[1..].iter().zip(list.separators.iter()) {
// The following test checks if we should keep two subexprs on the same // The following test checks if we should keep two subexprs on the same
@ -144,7 +144,7 @@ fn rewrite_pairs_multiline<T: Rewrite>(
} }
} }
result.push_str(&default_rw.as_ref()?); result.push_str(default_rw.as_ref()?);
} }
Some(result) Some(result)
} }
@ -264,12 +264,12 @@ impl FlattenPair for ast::Expr {
return node.rewrite(context, shape); return node.rewrite(context, shape);
} }
let nested_overhead = sep + 1; let nested_overhead = sep + 1;
let rhs_offset = shape.rhs_overhead(&context.config); let rhs_offset = shape.rhs_overhead(context.config);
let nested_shape = (match context.config.indent_style() { let nested_shape = (match context.config.indent_style() {
IndentStyle::Visual => shape.visual_indent(0), IndentStyle::Visual => shape.visual_indent(0),
IndentStyle::Block => shape.block_indent(context.config.tab_spaces()), IndentStyle::Block => shape.block_indent(context.config.tab_spaces()),
}) })
.with_max_width(&context.config) .with_max_width(context.config)
.sub_width(rhs_offset)?; .sub_width(rhs_offset)?;
let default_shape = match context.config.binop_separator() { let default_shape = match context.config.binop_separator() {
SeparatorPlace::Back => nested_shape.sub_width(nested_overhead)?, SeparatorPlace::Back => nested_shape.sub_width(nested_overhead)?,

View File

@ -456,11 +456,11 @@ fn rewrite_tuple_pat(
context: &RewriteContext<'_>, context: &RewriteContext<'_>,
shape: Shape, shape: Shape,
) -> Option<String> { ) -> Option<String> {
let mut pat_vec: Vec<_> = pats.iter().map(|x| TuplePatField::Pat(x)).collect(); if pats.is_empty() {
if pat_vec.is_empty() {
return Some(format!("{}()", path_str.unwrap_or_default())); return Some(format!("{}()", path_str.unwrap_or_default()));
} }
let mut pat_vec: Vec<_> = pats.iter().map(TuplePatField::Pat).collect();
let wildcard_suffix_len = count_wildcard_suffix_len(context, &pat_vec, span, shape); let wildcard_suffix_len = count_wildcard_suffix_len(context, &pat_vec, span, shape);
let (pat_vec, span) = if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2 let (pat_vec, span) = if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2
{ {
@ -482,7 +482,7 @@ fn rewrite_tuple_pat(
let path_str = path_str.unwrap_or_default(); let path_str = path_str.unwrap_or_default();
overflow::rewrite_with_parens( overflow::rewrite_with_parens(
&context, context,
&path_str, &path_str,
pat_vec.iter(), pat_vec.iter(),
shape, shape,

View File

@ -118,7 +118,9 @@ fn rewrite_reorderable_or_regroupable_items(
}; };
let mut regrouped_items = match context.config.group_imports() { let mut regrouped_items = match context.config.group_imports() {
GroupImportsTactic::Preserve => vec![normalized_items], GroupImportsTactic::Preserve | GroupImportsTactic::One => {
vec![normalized_items]
}
GroupImportsTactic::StdExternalCrate => group_imports(normalized_items), GroupImportsTactic::StdExternalCrate => group_imports(normalized_items),
}; };

View File

@ -112,7 +112,7 @@ impl<'a> Parser<'a> {
span: Span, span: Span,
) -> Result<(Vec<ast::Attribute>, Vec<ptr::P<ast::Item>>, Span), ParserError> { ) -> Result<(Vec<ast::Attribute>, Vec<ptr::P<ast::Item>>, Span), ParserError> {
let result = catch_unwind(AssertUnwindSafe(|| { let result = catch_unwind(AssertUnwindSafe(|| {
let mut parser = new_parser_from_file(sess.inner(), &path, Some(span)); let mut parser = new_parser_from_file(sess.inner(), path, Some(span));
match parser.parse_mod(&TokenKind::Eof) { match parser.parse_mod(&TokenKind::Eof) {
Ok(result) => Some(result), Ok(result) => Some(result),
Err(mut e) => { Err(mut e) => {
@ -125,18 +125,12 @@ impl<'a> Parser<'a> {
} }
})); }));
match result { match result {
Ok(Some(m)) => { Ok(Some(m)) if !sess.has_errors() => Ok(m),
if !sess.has_errors() { Ok(Some(m)) if sess.can_reset_errors() => {
return Ok(m); sess.reset_errors();
} Ok(m)
if sess.can_reset_errors() {
sess.reset_errors();
return Ok(m);
}
Err(ParserError::ParseError)
} }
Ok(None) => Err(ParserError::ParseError), Ok(_) => Err(ParserError::ParseError),
Err(..) if path.exists() => Err(ParserError::ParseError), Err(..) if path.exists() => Err(ParserError::ParseError),
Err(_) => Err(ParserError::ParsePanicError), Err(_) => Err(ParserError::ParsePanicError),
} }

View File

@ -164,7 +164,7 @@ impl ParseSess {
} }
pub(crate) fn ignore_file(&self, path: &FileName) -> bool { pub(crate) fn ignore_file(&self, path: &FileName) -> bool {
self.ignore_path_set.as_ref().is_match(&path) self.ignore_path_set.as_ref().is_match(path)
} }
pub(crate) fn set_silent_emitter(&mut self) { pub(crate) fn set_silent_emitter(&mut self) {

View File

@ -535,9 +535,9 @@ fn check_files(files: Vec<PathBuf>, opt_config: &Option<PathBuf>) -> (Vec<Format
debug!("Testing '{}'...", file_name.display()); debug!("Testing '{}'...", file_name.display());
match idempotent_check(&file_name, &opt_config) { match idempotent_check(&file_name, opt_config) {
Ok(ref report) if report.has_warnings() => { Ok(ref report) if report.has_warnings() => {
print!("{}", FormatReportFormatterBuilder::new(&report).build()); print!("{}", FormatReportFormatterBuilder::new(report).build());
fails += 1; fails += 1;
} }
Ok(report) => reports.push(report), Ok(report) => reports.push(report),

View File

@ -5,21 +5,39 @@ use super::read_config;
use crate::{FileName, Input, Session}; use crate::{FileName, Input, Session};
#[test] fn verify_mod_resolution(input_file_name: &str, exp_misformatted_files: &[&str]) {
fn nested_out_of_line_mods_loaded() { let input_file = PathBuf::from(input_file_name);
// See also https://github.com/rust-lang/rustfmt/issues/4874
let filename = "tests/mod-resolver/issue-4874/main.rs";
let input_file = PathBuf::from(filename);
let config = read_config(&input_file); let config = read_config(&input_file);
let mut session = Session::<io::Stdout>::new(config, None); let mut session = Session::<io::Stdout>::new(config, None);
let report = session let report = session
.format(Input::File(filename.into())) .format(Input::File(input_file_name.into()))
.expect("Should not have had any execution errors"); .expect("Should not have had any execution errors");
let errors_by_file = &report.internal.borrow().0; let errors_by_file = &report.internal.borrow().0;
assert!(errors_by_file.contains_key(&FileName::Real(PathBuf::from( for exp_file in exp_misformatted_files {
"tests/mod-resolver/issue-4874/bar/baz.rs", assert!(errors_by_file.contains_key(&FileName::Real(PathBuf::from(exp_file))));
)))); }
assert!(errors_by_file.contains_key(&FileName::Real(PathBuf::from( }
"tests/mod-resolver/issue-4874/foo/qux.rs",
)))); #[test]
fn nested_out_of_line_mods_loaded() {
// See also https://github.com/rust-lang/rustfmt/issues/4874
verify_mod_resolution(
"tests/mod-resolver/issue-4874/main.rs",
&[
"tests/mod-resolver/issue-4874/bar/baz.rs",
"tests/mod-resolver/issue-4874/foo/qux.rs",
],
);
}
#[test]
fn out_of_line_nested_inline_within_out_of_line() {
// See also https://github.com/rust-lang/rustfmt/issues/5063
verify_mod_resolution(
"tests/mod-resolver/issue-5063/main.rs",
&[
"tests/mod-resolver/issue-5063/foo/bar/baz.rs",
"tests/mod-resolver/issue-5063/foo.rs",
],
);
} }

View File

@ -728,7 +728,7 @@ impl Rewrite for ast::Ty {
result = combine_strs_with_missing_comments( result = combine_strs_with_missing_comments(
context, context,
result.trim_end(), result.trim_end(),
&mt.ty.rewrite(&context, shape)?, &mt.ty.rewrite(context, shape)?,
before_ty_span, before_ty_span,
shape, shape,
true, true,
@ -738,7 +738,7 @@ impl Rewrite for ast::Ty {
let budget = shape.width.checked_sub(used_width)?; let budget = shape.width.checked_sub(used_width)?;
let ty_str = mt let ty_str = mt
.ty .ty
.rewrite(&context, Shape::legacy(budget, shape.indent + used_width))?; .rewrite(context, Shape::legacy(budget, shape.indent + used_width))?;
result.push_str(&ty_str); result.push_str(&ty_str);
} }

View File

@ -42,7 +42,7 @@ pub(crate) fn is_same_visibility(a: &Visibility, b: &Visibility) -> bool {
( (
VisibilityKind::Restricted { path: p, .. }, VisibilityKind::Restricted { path: p, .. },
VisibilityKind::Restricted { path: q, .. }, VisibilityKind::Restricted { path: q, .. },
) => pprust::path_to_string(&p) == pprust::path_to_string(&q), ) => pprust::path_to_string(p) == pprust::path_to_string(q),
(VisibilityKind::Public, VisibilityKind::Public) (VisibilityKind::Public, VisibilityKind::Public)
| (VisibilityKind::Inherited, VisibilityKind::Inherited) | (VisibilityKind::Inherited, VisibilityKind::Inherited)
| ( | (
@ -689,7 +689,7 @@ mod test {
#[test] #[test]
fn test_remove_trailing_white_spaces() { fn test_remove_trailing_white_spaces() {
let s = " r#\"\n test\n \"#"; let s = " r#\"\n test\n \"#";
assert_eq!(remove_trailing_white_spaces(&s), s); assert_eq!(remove_trailing_white_spaces(s), s);
} }
#[test] #[test]
@ -698,7 +698,7 @@ mod test {
let config = Config::default(); let config = Config::default();
let indent = Indent::new(4, 0); let indent = Indent::new(4, 0);
assert_eq!( assert_eq!(
trim_left_preserve_layout(&s, indent, &config), trim_left_preserve_layout(s, indent, &config),
Some("aaa\n bbb\n ccc".to_string()) Some("aaa\n bbb\n ccc".to_string())
); );
} }

View File

@ -12,8 +12,7 @@ use crate::config::{BraceStyle, Config};
use crate::coverage::transform_missing_snippet; use crate::coverage::transform_missing_snippet;
use crate::items::{ use crate::items::{
format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_extern_crate, format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_extern_crate,
rewrite_impl_type, rewrite_opaque_type, rewrite_type, FnBraceStyle, FnSig, StaticParts, rewrite_type_alias, FnBraceStyle, FnSig, ItemVisitorKind, StaticParts, StructParts,
StructParts,
}; };
use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition}; use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition};
use crate::modules::Module; use crate::modules::Module;
@ -164,7 +163,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
); );
} else { } else {
let shape = self.shape(); let shape = self.shape();
let rewrite = self.with_context(|ctx| stmt.rewrite(&ctx, shape)); let rewrite = self.with_context(|ctx| stmt.rewrite(ctx, shape));
self.push_rewrite(stmt.span(), rewrite) self.push_rewrite(stmt.span(), rewrite)
} }
} }
@ -273,9 +272,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
let comment_snippet = self.snippet(span); let comment_snippet = self.snippet(span);
let align_to_right = if unindent_comment && contains_comment(&comment_snippet) { let align_to_right = if unindent_comment && contains_comment(comment_snippet) {
let first_lines = comment_snippet.splitn(2, '/').next().unwrap_or(""); let first_lines = comment_snippet.splitn(2, '/').next().unwrap_or("");
last_line_width(first_lines) > last_line_width(&comment_snippet) last_line_width(first_lines) > last_line_width(comment_snippet)
} else { } else {
false false
}; };
@ -439,7 +438,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
let filtered_attrs; let filtered_attrs;
let mut attrs = &item.attrs; let mut attrs = &item.attrs;
let skip_context_saved = self.skip_context.clone(); let skip_context_saved = self.skip_context.clone();
self.skip_context.update_with_attrs(&attrs); self.skip_context.update_with_attrs(attrs);
let should_visit_node_again = match item.kind { let should_visit_node_again = match item.kind {
// For use/extern crate items, skip rewriting attributes but check for a skip attribute. // For use/extern crate items, skip rewriting attributes but check for a skip attribute.
@ -488,12 +487,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
ast::ItemKind::Use(ref tree) => self.format_import(item, tree), ast::ItemKind::Use(ref tree) => self.format_import(item, tree),
ast::ItemKind::Impl { .. } => { ast::ItemKind::Impl { .. } => {
let block_indent = self.block_indent; let block_indent = self.block_indent;
let rw = self.with_context(|ctx| format_impl(&ctx, item, block_indent)); let rw = self.with_context(|ctx| format_impl(ctx, item, block_indent));
self.push_rewrite(item.span, rw); self.push_rewrite(item.span, rw);
} }
ast::ItemKind::Trait(..) => { ast::ItemKind::Trait(..) => {
let block_indent = self.block_indent; let block_indent = self.block_indent;
let rw = self.with_context(|ctx| format_trait(&ctx, item, block_indent)); let rw = self.with_context(|ctx| format_trait(ctx, item, block_indent));
self.push_rewrite(item.span, rw); self.push_rewrite(item.span, rw);
} }
ast::ItemKind::TraitAlias(ref generics, ref generic_bounds) => { ast::ItemKind::TraitAlias(ref generics, ref generic_bounds) => {
@ -568,40 +567,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
self.push_rewrite(item.span, rewrite); self.push_rewrite(item.span, rewrite);
} }
} }
ast::ItemKind::TyAlias(ref alias_kind) => { ast::ItemKind::TyAlias(ref ty_alias) => {
let ast::TyAlias { use ItemVisitorKind::Item;
ref generics, self.visit_ty_alias_kind(ty_alias, &Item(&item), item.span);
ref bounds,
ref ty,
..
} = **alias_kind;
match ty {
Some(ty) => {
let rewrite = rewrite_type(
&self.get_context(),
self.block_indent,
item.ident,
&item.vis,
generics,
Some(bounds),
Some(&*ty),
item.span,
);
self.push_rewrite(item.span, rewrite);
}
None => {
let rewrite = rewrite_opaque_type(
&self.get_context(),
self.block_indent,
item.ident,
bounds,
generics,
&item.vis,
item.span,
);
self.push_rewrite(item.span, rewrite);
}
}
} }
ast::ItemKind::GlobalAsm(..) => { ast::ItemKind::GlobalAsm(..) => {
let snippet = Some(self.snippet(item.span).to_owned()); let snippet = Some(self.snippet(item.span).to_owned());
@ -624,18 +592,46 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
self.skip_context = skip_context_saved; self.skip_context = skip_context_saved;
} }
pub(crate) fn visit_trait_item(&mut self, ti: &ast::AssocItem) { fn visit_ty_alias_kind(
skip_out_of_file_lines_range_visitor!(self, ti.span); &mut self,
ty_kind: &ast::TyAlias,
visitor_kind: &ItemVisitorKind<'_>,
span: Span,
) {
let rewrite = rewrite_type_alias(
ty_kind,
&self.get_context(),
self.block_indent,
visitor_kind,
span,
);
self.push_rewrite(span, rewrite);
}
if self.visit_attrs(&ti.attrs, ast::AttrStyle::Outer) { fn visit_assoc_item(&mut self, visitor_kind: &ItemVisitorKind<'_>) {
self.push_skipped_with_span(ti.attrs.as_slice(), ti.span(), ti.span()); use ItemVisitorKind::*;
// TODO(calebcartwright): Not sure the skip spans are correct
let (ai, skip_span, assoc_ctxt) = match visitor_kind {
AssocTraitItem(ai) => (*ai, ai.span(), visit::AssocCtxt::Trait),
AssocImplItem(ai) => (*ai, ai.span, visit::AssocCtxt::Impl),
_ => unreachable!(),
};
skip_out_of_file_lines_range_visitor!(self, ai.span);
if self.visit_attrs(&ai.attrs, ast::AttrStyle::Outer) {
self.push_skipped_with_span(&ai.attrs.as_slice(), skip_span, skip_span);
return; return;
} }
// TODO(calebcartwright): consider enabling box_patterns feature gate // TODO(calebcartwright): consider enabling box_patterns feature gate
match ti.kind { match (&ai.kind, visitor_kind) {
ast::AssocItemKind::Const(..) => self.visit_static(&StaticParts::from_trait_item(ti)), (ast::AssocItemKind::Const(..), AssocTraitItem(_)) => {
ast::AssocItemKind::Fn(ref fn_kind) => { self.visit_static(&StaticParts::from_trait_item(&ai))
}
(ast::AssocItemKind::Const(..), AssocImplItem(_)) => {
self.visit_static(&StaticParts::from_impl_item(&ai))
}
(ast::AssocItemKind::Fn(ref fn_kind), _) => {
let ast::Fn { let ast::Fn {
defaultness, defaultness,
ref sig, ref sig,
@ -643,108 +639,39 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
ref body, ref body,
} = **fn_kind; } = **fn_kind;
if let Some(ref body) = body { if let Some(ref body) = body {
let inner_attrs = inner_attributes(&ti.attrs); let inner_attrs = inner_attributes(&ai.attrs);
let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Trait); let fn_ctxt = visit::FnCtxt::Assoc(assoc_ctxt);
self.visit_fn( self.visit_fn(
visit::FnKind::Fn(fn_ctxt, ti.ident, sig, &ti.vis, Some(body)), visit::FnKind::Fn(fn_ctxt, ai.ident, sig, &ai.vis, Some(body)),
generics, generics,
&sig.decl, &sig.decl,
ti.span, ai.span,
defaultness, defaultness,
Some(&inner_attrs), Some(&inner_attrs),
); );
} else { } else {
let indent = self.block_indent; let indent = self.block_indent;
let rewrite = let rewrite =
self.rewrite_required_fn(indent, ti.ident, sig, &ti.vis, generics, ti.span); self.rewrite_required_fn(indent, ai.ident, sig, &ai.vis, generics, ai.span);
self.push_rewrite(ti.span, rewrite); self.push_rewrite(ai.span, rewrite);
} }
} }
ast::AssocItemKind::TyAlias(ref ty_alias_kind) => { (ast::AssocItemKind::TyAlias(ref ty_alias), _) => {
let ast::TyAlias { self.visit_ty_alias_kind(ty_alias, visitor_kind, ai.span);
ref generics,
ref bounds,
ref ty,
..
} = **ty_alias_kind;
let rewrite = rewrite_type(
&self.get_context(),
self.block_indent,
ti.ident,
&ti.vis,
generics,
Some(bounds),
ty.as_ref(),
ti.span,
);
self.push_rewrite(ti.span, rewrite);
} }
ast::AssocItemKind::MacCall(ref mac) => { (ast::AssocItemKind::MacCall(ref mac), _) => {
self.visit_mac(mac, Some(ti.ident), MacroPosition::Item); self.visit_mac(mac, Some(ai.ident), MacroPosition::Item);
} }
_ => unreachable!(),
} }
} }
pub(crate) fn visit_trait_item(&mut self, ti: &ast::AssocItem) {
self.visit_assoc_item(&ItemVisitorKind::AssocTraitItem(ti));
}
pub(crate) fn visit_impl_item(&mut self, ii: &ast::AssocItem) { pub(crate) fn visit_impl_item(&mut self, ii: &ast::AssocItem) {
skip_out_of_file_lines_range_visitor!(self, ii.span); self.visit_assoc_item(&ItemVisitorKind::AssocImplItem(ii));
if self.visit_attrs(&ii.attrs, ast::AttrStyle::Outer) {
self.push_skipped_with_span(ii.attrs.as_slice(), ii.span, ii.span);
return;
}
match ii.kind {
ast::AssocItemKind::Fn(ref fn_kind) => {
let ast::Fn {
defaultness,
ref sig,
ref generics,
ref body,
} = **fn_kind;
if let Some(ref body) = body {
let inner_attrs = inner_attributes(&ii.attrs);
let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Impl);
self.visit_fn(
visit::FnKind::Fn(fn_ctxt, ii.ident, sig, &ii.vis, Some(body)),
generics,
&sig.decl,
ii.span,
defaultness,
Some(&inner_attrs),
);
} else {
let indent = self.block_indent;
let rewrite =
self.rewrite_required_fn(indent, ii.ident, sig, &ii.vis, generics, ii.span);
self.push_rewrite(ii.span, rewrite);
}
}
ast::AssocItemKind::Const(..) => self.visit_static(&StaticParts::from_impl_item(ii)),
ast::AssocItemKind::TyAlias(ref ty_alias_kind) => {
let ast::TyAlias {
defaultness,
ref generics,
ref ty,
..
} = **ty_alias_kind;
self.push_rewrite(
ii.span,
rewrite_impl_type(
ii.ident,
&ii.vis,
defaultness,
ty.as_ref(),
&generics,
&self.get_context(),
self.block_indent,
ii.span,
),
);
}
ast::AssocItemKind::MacCall(ref mac) => {
self.visit_mac(mac, Some(ii.ident), MacroPosition::Item);
}
}
} }
fn visit_mac(&mut self, mac: &ast::MacCall, ident: Option<symbol::Ident>, pos: MacroPosition) { fn visit_mac(&mut self, mac: &ast::MacCall, ident: Option<symbol::Ident>, pos: MacroPosition) {
@ -921,7 +848,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
} }
fn walk_mod_items(&mut self, items: &[rustc_ast::ptr::P<ast::Item>]) { fn walk_mod_items(&mut self, items: &[rustc_ast::ptr::P<ast::Item>]) {
self.visit_items_with_reordering(&ptr_vec_to_ref_vec(&items)); self.visit_items_with_reordering(&ptr_vec_to_ref_vec(items));
} }
fn walk_stmts(&mut self, stmts: &[Stmt<'_>], include_current_empty_semi: bool) { fn walk_stmts(&mut self, stmts: &[Stmt<'_>], include_current_empty_semi: bool) {

View File

@ -0,0 +1,2 @@
mod bar {
mod baz;}

View File

@ -0,0 +1 @@
fn baz() { }

View File

@ -0,0 +1,5 @@
fn main() {
println!("Hello, world!");
}
mod foo;

View File

@ -0,0 +1,17 @@
// rustfmt-group_imports: One
// rustfmt-imports_granularity: Crate
use chrono::Utc;
use super::update::convert_publish_payload;
use juniper::{FieldError, FieldResult};
use uuid::Uuid;
use alloc::alloc::Layout;
use std::sync::Arc;
use alloc::vec::Vec;
use broker::database::PooledConnection;
use super::schema::{Context, Payload};
use core::f32;
use crate::models::Event;

View File

@ -0,0 +1,7 @@
// rustfmt-group_imports: One
mod test {
use crate::foo::bar;
use std::path;
use crate::foo::bar2;
}

View File

@ -0,0 +1,16 @@
// rustfmt-group_imports: One
// rustfmt-reorder_imports: false
use chrono::Utc;
use super::update::convert_publish_payload;
use juniper::{FieldError, FieldResult};
use uuid::Uuid;
use alloc::alloc::Layout;
use std::sync::Arc;
use broker::database::PooledConnection;
use super::schema::{Context, Payload};
use core::f32;
use crate::models::Event;

View File

@ -0,0 +1,15 @@
// rustfmt-group_imports: One
use chrono::Utc;
use super::update::convert_publish_payload;
use juniper::{FieldError, FieldResult};
use uuid::Uuid;
use alloc::alloc::Layout;
use std::sync::Arc;
use broker::database::PooledConnection;
use super::schema::{Context, Payload};
use core::f32;
use crate::models::Event;

View File

@ -0,0 +1,46 @@
// rustfmt-brace_style: AlwaysNextLine
// rustfmt-empty_item_single_line: false
fn function()
{
}
struct Struct
{
}
enum Enum
{
}
trait Trait
{
}
impl<T> Trait for T
{
}
trait Trait2<T>
where
T: Copy + Display + Write + Read + FromStr, {}
trait Trait3<T>
where
T: Something
+ SomethingElse
+ Sync
+ Send
+ Display
+ Debug
+ Copy
+ Hash
+ Debug
+ Display
+ Write
+ Read, {}

View File

@ -27,3 +27,38 @@ mod M {
struct D<T> where T: Copy {} struct D<T> where T: Copy {}
} }
fn function()
{
}
trait Trait
{
}
impl<T> Trait for T
{
}
trait Trait2<T>
where
T: Copy + Display + Write + Read + FromStr, {}
trait Trait3<T>
where
T: Something
+ SomethingElse
+ Sync
+ Send
+ Display
+ Debug
+ Copy
+ Hash
+ Debug
+ Display
+ Write
+ Read, {}

View File

@ -0,0 +1,14 @@
// rustfmt-group_imports: One
// rustfmt-imports_granularity: Crate
use super::{
schema::{Context, Payload},
update::convert_publish_payload,
};
use crate::models::Event;
use alloc::{alloc::Layout, vec::Vec};
use broker::database::PooledConnection;
use chrono::Utc;
use core::f32;
use juniper::{FieldError, FieldResult};
use std::sync::Arc;
use uuid::Uuid;

View File

@ -0,0 +1,6 @@
// rustfmt-group_imports: One
mod test {
use crate::foo::bar;
use crate::foo::bar2;
use std::path;
}

View File

@ -0,0 +1,12 @@
// rustfmt-group_imports: One
// rustfmt-reorder_imports: false
use chrono::Utc;
use super::update::convert_publish_payload;
use juniper::{FieldError, FieldResult};
use uuid::Uuid;
use alloc::alloc::Layout;
use std::sync::Arc;
use broker::database::PooledConnection;
use super::schema::{Context, Payload};
use core::f32;
use crate::models::Event;

View File

@ -0,0 +1,11 @@
// rustfmt-group_imports: One
use super::schema::{Context, Payload};
use super::update::convert_publish_payload;
use crate::models::Event;
use alloc::alloc::Layout;
use broker::database::PooledConnection;
use chrono::Utc;
use core::f32;
use juniper::{FieldError, FieldResult};
use std::sync::Arc;
use uuid::Uuid;

View File

@ -0,0 +1,41 @@
// rustfmt-brace_style: AlwaysNextLine
// rustfmt-empty_item_single_line: false
fn function()
{
}
struct Struct {}
enum Enum {}
trait Trait
{
}
impl<T> Trait for T
{
}
trait Trait2<T>
where
T: Copy + Display + Write + Read + FromStr,
{
}
trait Trait3<T>
where
T: Something
+ SomethingElse
+ Sync
+ Send
+ Display
+ Debug
+ Copy
+ Hash
+ Debug
+ Display
+ Write
+ Read,
{
}

View File

@ -0,0 +1,8 @@
// rustfmt-trailing_comma: Always
pub struct Matrix<T, const R: usize, const C: usize,>
where
[T; R * C]:,
{
contents: [T; R * C],
}

View File

@ -0,0 +1,8 @@
// rustfmt-trailing_comma: Never
pub struct Matrix<T, const R: usize, const C: usize>
where
[T; R * C]:
{
contents: [T; R * C]
}

View File

@ -0,0 +1,8 @@
// leading comment
#![rustfmt::skip]
fn main() {
println!("main"); // commented
}
// post comment

View File

@ -0,0 +1,11 @@
#![rustfmt::skip]
mod a {
mod b {
}
// trailing comment b
}
// trailing comment a

View File

@ -0,0 +1,4 @@
impl ThisIsALongStructNameToPushTheWhereToWrapLolololol where
[(); this_is_a_long_const_function_name()]:
{
}

View File

@ -40,3 +40,32 @@ mod M
where where
T: Copy, {} T: Copy, {}
} }
fn function() {}
trait Trait {}
impl<T> Trait for T {}
trait Trait2<T>
where
T: Copy + Display + Write + Read + FromStr,
{
}
trait Trait3<T>
where
T: Something
+ SomethingElse
+ Sync
+ Send
+ Display
+ Debug
+ Copy
+ Hash
+ Debug
+ Display
+ Write
+ Read,
{
}