Skip to content

- formatting of import long lines #5612

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 75 additions & 19 deletions src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crate::rewrite::{Rewrite, RewriteContext};
use crate::shape::Shape;
use crate::source_map::SpanUtils;
use crate::spanned::Spanned;
use crate::utils::{is_same_visibility, mk_sp, rewrite_ident};
use crate::utils::{first_line_width, is_same_visibility, mk_sp, rewrite_ident};
use crate::visitor::FmtVisitor;

/// Returns a name imported by a `use` declaration.
Expand All @@ -36,6 +36,12 @@ impl<'a> FmtVisitor<'a> {
pub(crate) fn format_import(&mut self, item: &ast::Item, tree: &ast::UseTree) {
let span = item.span();
let shape = self.shape();
// 4 = "use ", 1 = ";"
let nested_shape = shape
.offset_left(4)
.unwrap_or(shape)
.sub_width(1)
.unwrap_or(shape);
let rw = UseTree::from_ast(
&self.get_context(),
tree,
Expand All @@ -44,7 +50,7 @@ impl<'a> FmtVisitor<'a> {
Some(item.span.lo()),
Some(item.attrs.clone()),
)
.rewrite_top_level(&self.get_context(), shape);
.rewrite_top_level(&self.get_context(), nested_shape);
match rw {
Some(ref s) if s.is_empty() => {
// Format up to last newline
Expand Down Expand Up @@ -1030,22 +1036,7 @@ fn rewrite_nested_use_tree(
.preserve_newline(true)
.nested(has_nested_list);

let list_str = write_list(&list_items, &fmt)?;

let result = if (list_str.contains('\n') || list_str.len() > remaining_width)
&& context.config.imports_indent() == IndentStyle::Block
{
format!(
"{{\n{}{}\n{}}}",
nested_shape.indent.to_string(context.config),
list_str,
shape.indent.to_string(context.config)
)
} else {
format!("{{{}}}", list_str)
};

Some(result)
Some(write_list(&list_items, &fmt)?)
}

impl Rewrite for UseSegment {
Expand All @@ -1072,20 +1063,85 @@ impl Rewrite for UseSegment {
}
}

fn rewrite_use_segment_for_path(
segment: &UseSegment,
context: &RewriteContext<'_>,
shape: Shape,
newline_in_path: bool,
) -> Option<String> {
let nested_shape = match context.config.imports_indent() {
IndentStyle::Block => shape
.block_indent(context.config.tab_spaces())
.with_max_width(context.config)
.sub_width(1)?,
IndentStyle::Visual => shape.visual_indent(0),
};

let segment_str = segment.rewrite(context, shape)?;
let remaining_width = shape.width.saturating_sub(2);
let result = match segment.kind {
UseSegmentKind::List(_) => {
if (segment_str.contains('\n')
|| newline_in_path
|| segment_str.len() > remaining_width)
&& context.config.imports_indent() == IndentStyle::Block
{
format!(
"{{\n{}{}\n{}}}",
nested_shape.indent.to_string(context.config),
segment_str,
shape.indent.to_string(context.config)
)
} else {
format!("{{{}}}", segment_str)
}
}
_ => segment_str,
};

Some(result)
}

impl Rewrite for UseTree {
// This does NOT format attributes and visibility or add a trailing `;`.
fn rewrite(&self, context: &RewriteContext<'_>, mut shape: Shape) -> Option<String> {
let mut result = String::with_capacity(256);
let mut iter = self.path.iter().peekable();
let start_shape = shape;
let mut newline_in_path = false;
let tab_spaces = context.config.tab_spaces();

while let Some(segment) = iter.next() {
let segment_str = segment.rewrite(context, shape)?;
let new_shape = if !newline_in_path {
shape
} else {
match context.config.imports_indent() {
IndentStyle::Block => {
start_shape.block_indent(tab_spaces).sub_width(tab_spaces)?
}
IndentStyle::Visual => start_shape.visual_indent(0),
}
};
let segment_str =
rewrite_use_segment_for_path(segment, context, new_shape, newline_in_path)?;
let mut added_len = first_line_width(&segment_str);
if iter.peek().is_some() {
added_len += 2; // 2 == "::"
}
if added_len > shape.width {
result.push_str(&start_shape.to_string_with_newline(context.config));
shape = start_shape;
newline_in_path = true;
}

result.push_str(&segment_str);
if iter.peek().is_some() {
result.push_str("::");
// 2 = "::"
shape = shape.offset_left(2 + segment_str.len())?;
}
}

Some(result)
}
}
Expand Down
66 changes: 66 additions & 0 deletions tests/source/issue-4746/crate_no_reorder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// rustfmt-imports_granularity: Crate
// rustfmt-reorder_imports: false

// Long imports with different sizes - based on original issue
use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::asdf;
use a1;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::a;
use a2;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567;
use a3;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z12345678::z1234567;
use a4;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567890123456::z1234567;
use a5;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z12345678901234567::z1234567;
use a6;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::asdf;
use a7;

// Very long (two lines) imports
use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567;
use a8;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::{baz, foo};
use a9;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::{foo, baz};
use a10;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::{
baz, foo
};
use a11;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z123456::{
baz, foo
};
use a12;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z12345678::{
baz, foo
};
use a13;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::{
z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::{
baz, foo
}
};
use a14;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::{
foo::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567,
baz::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567};
use a16;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::{
foo::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567,
baz::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567};
use a17;
96 changes: 96 additions & 0 deletions tests/source/issue-4746/crate_reorder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// rustfmt-imports_granularity: Crate
// rustfmt-reorder_imports: true

// Long imports with reordering - from original issue
use foo::bar;
use foo::{foo, baz};
use abaadfsasdfdsfdfas::aasdffjsioejr::abc::sdsdf::sdfsdfsdf::sdfsdfdsf::{
asdfasdefasdasdfsdfdfasdf::asdfasdasedfafasdfasdf,
};

use foo::bar;
use foo::{foo, baz};
use abaadfsasdfdsfdfas::aasdffjsioejr::abc::sdsdf::sdfsdfsdf::sdfsdfds::{
asdfasdefasdasdfsdfdfasdf::asdfasdasedfafasdfasdf,
};

// Long imports with different sizes - based on original issue
use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::asdf;
use a1;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::a;
use a2;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567;
use a3;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z12345678::z1234567;
use a4;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567890123456::z1234567;
use a5;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z12345678901234567::z1234567;
use a6;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::asdf;
use a7;

// Very long (two lines) imports
use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567;
use a8;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::{baz, foo};
use a9;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::{foo, baz};
use a10;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::{
baz, foo
};
use a11;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z123456::{
baz, foo
};
use a12;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z12345678::{
baz, foo
};
use a13;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::{
z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::{
baz, foo
}
};
use a14;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::foo;
use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::baz;
use a15;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::{
foo::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567,
baz::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567};
use a16;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::{
foo::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567,
baz::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567};
use a17;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::{
z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::foo,
z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::baz};
use a18;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::foo::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567;
use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::baz::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567;
use a19;

use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::foo;
use z123::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::z1234567::baz;
use a20;
Loading