Skip to content
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

imports_granularity = "Module" with path contains self #4716

Merged
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
14 changes: 13 additions & 1 deletion src/formatting/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,19 @@ pub(crate) fn merge_use_trees(use_trees: Vec<UseTree>, merge_by: SharedPrefix) -
continue;
}

for flattened in use_tree.flatten() {
for mut flattened in use_tree.flatten() {
if merge_by == SharedPrefix::Module {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any ideas why this isn't needed for the Crate variant?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I understand, the following code transforms ahead foo::self to foo:

// Normalise foo::self -> foo.
if let UseSegment::Slf(None) = last {
if !self.path.is_empty() {
return self;

Therefore, the only reason foo::self can be present in the code you asked about, is that flatten() created foo::self from foo::{self, bar}, in addition to creating foo::bar. For SharedPrefix::Module these too imports will remain separate, so {} should be added to self. However for SharedPrefix::Crate they will be merged again. This is because how share_prefix() identify shared prefix:
match shared_prefix {
SharedPrefix::Crate => self.path[0] == other.path[0],
SharedPrefix::Module => {
self.path[..self.path.len() - 1] == other.path[..other.path.len() - 1]

When checking this I found two examples of imports formatting which I am not sure are correct. The first is when using imports_granularity = "Crate":

use foo;
use foo::{self};

is formatted as:

use foo::{
    self, {self},
};

Is that o.k. or it should have been use foo::{self}?

The second possible formatting issue is when using imports_granularity = "Module":

use foo;
use bar;

is formatted as:

use {bar, foo};

Is this o.k.?

// If a path ends in `::self`, rewrite it to `::{self}`.
if let Some(UseSegment::Slf(..)) = flattened.path.last() {
let self_segment = flattened.path.pop().unwrap();
flattened
.path
.push(UseSegment::List(vec![UseTree::from_path(
vec![self_segment],
DUMMY_SP,
)]));
}
}
if let Some(tree) = result
.iter_mut()
.find(|tree| tree.share_prefix(&flattened, merge_by))
Expand Down
6 changes: 6 additions & 0 deletions tests/source/issue-4681-imports_granularity_default.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use crate::lexer;
use crate::lexer::tokens::TokenData;
use crate::lexer::{tokens::TokenData};
use crate::lexer::self;
use crate::lexer::{self};
use crate::lexer::{self, tokens::TokenData};
5 changes: 5 additions & 0 deletions tests/source/issue-4681-imports_granularity_module.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// rustfmt-imports_granularity: Module

use crate::lexer;
use crate::lexer::self;
use crate::lexer::{self, tokens::TokenData};
6 changes: 6 additions & 0 deletions tests/target/issue-4681-imports_granularity_default.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use crate::lexer;
use crate::lexer;
use crate::lexer::tokens::TokenData;
use crate::lexer::tokens::TokenData;
use crate::lexer::{self};
use crate::lexer::{self, tokens::TokenData};
5 changes: 5 additions & 0 deletions tests/target/issue-4681-imports_granularity_module.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// rustfmt-imports_granularity: Module

use crate::lexer;
use crate::lexer::tokens::TokenData;
use crate::lexer::{self};