11865: Fix: Select correct insert position for disabled group import r=jonasbb a=jonasbb

The logic for importing with and without `group_imports` differed
significantly when no previous group existed. This lead to the problem
of using the wrong position when importing inside a module (#11585) or
when inner attributes are involved.
The existing code for grouped imports is better and takes these things
into account.

This PR changes the flow to use the pre-existing code for adding a new
import group even for the non-grouped import settings.
Some coverage markers are updated and the `group` is removed, since they
are now invoked in both cases (grouping and no grouping).

Tests are updated and two tests (empty module and inner attribute) are
added.

Fixes #11585

Co-authored-by: Jonas Bushart <jonas@bushart.org>
This commit is contained in:
bors[bot] 2022-04-03 18:46:45 +00:00 committed by GitHub
commit 46d7ee68f2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 116 additions and 83 deletions

View file

@ -337,18 +337,7 @@ fn insert_use_(
Some((path, has_tl, node))
});
if !group_imports {
if let Some((_, _, node)) = path_node_iter.last() {
cov_mark::hit!(insert_no_grouping_last);
ted::insert(ted::Position::after(node), use_item.syntax());
} else {
cov_mark::hit!(insert_no_grouping_last2);
ted::insert(ted::Position::first_child_of(scope_syntax), make::tokens::blank_line());
ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax());
}
return;
}
if group_imports {
// Iterator that discards anything thats not in the required grouping
// This implementation allows the user to rearrange their import groups as this only takes the first group that fits
let group_iter = path_node_iter
@ -398,6 +387,15 @@ fn insert_use_(
ted::insert(ted::Position::after(node), make::tokens::single_newline());
return;
}
} else {
// There exists a group, so append to the end of it
if let Some((_, _, node)) = path_node_iter.last() {
cov_mark::hit!(insert_no_grouping_last);
ted::insert(ted::Position::after(node), use_item.syntax());
return;
}
}
// there are no imports in this file at all
if let Some(last_inner_element) = scope_syntax
.children_with_tokens()
@ -407,14 +405,14 @@ fn insert_use_(
})
.last()
{
cov_mark::hit!(insert_group_empty_inner_attr);
cov_mark::hit!(insert_empty_inner_attr);
ted::insert(ted::Position::after(&last_inner_element), use_item.syntax());
ted::insert(ted::Position::after(last_inner_element), make::tokens::single_newline());
return;
}
let l_curly = match scope {
ImportScope::File(_) => {
cov_mark::hit!(insert_group_empty_file);
cov_mark::hit!(insert_empty_file);
ted::insert(ted::Position::first_child_of(scope_syntax), make::tokens::blank_line());
ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax());
return;
@ -426,7 +424,7 @@ fn insert_use_(
};
match l_curly {
Some(b) => {
cov_mark::hit!(insert_group_empty_module);
cov_mark::hit!(insert_empty_module);
ted::insert(ted::Position::after(&b), make::tokens::single_newline());
ted::insert(ted::Position::after(&b), use_item.syntax());
}

View file

@ -84,25 +84,6 @@ use external_crate2::bar::A;",
);
}
#[test]
fn insert_not_group_empty() {
cov_mark::check!(insert_no_grouping_last2);
check_with_config(
"use external_crate2::bar::A",
r"",
r"use external_crate2::bar::A;
",
&InsertUseConfig {
granularity: ImportGranularity::Item,
enforce_granularity: true,
prefix_kind: PrefixKind::Plain,
group: false,
skip_glob_imports: true,
},
);
}
#[test]
fn insert_existing() {
check_crate("std::fs", "use std::fs;", "use std::fs;")
@ -321,7 +302,9 @@ fn main() {}",
#[test]
fn insert_empty_file() {
cov_mark::check!(insert_group_empty_file);
cov_mark::check_count!(insert_empty_file, 2);
// Default configuration
// empty files will get two trailing newlines
// this is due to the test case insert_no_imports above
check_crate(
@ -330,12 +313,30 @@ fn insert_empty_file() {
r"use foo::bar;
",
)
);
// "not group" configuration
check_with_config(
"use external_crate2::bar::A",
r"",
r"use external_crate2::bar::A;
",
&InsertUseConfig {
granularity: ImportGranularity::Item,
enforce_granularity: true,
prefix_kind: PrefixKind::Plain,
group: false,
skip_glob_imports: true,
},
);
}
#[test]
fn insert_empty_module() {
cov_mark::check!(insert_group_empty_module);
cov_mark::check_count!(insert_empty_module, 2);
// Default configuration
check(
"foo::bar",
r"
@ -347,19 +348,53 @@ mod x {
}
",
ImportGranularity::Item,
)
);
// "not group" configuration
check_with_config(
"foo::bar",
r"mod x {$0}",
r"mod x {
use foo::bar;
}",
&InsertUseConfig {
granularity: ImportGranularity::Item,
enforce_granularity: true,
prefix_kind: PrefixKind::Plain,
group: false,
skip_glob_imports: true,
},
);
}
#[test]
fn insert_after_inner_attr() {
cov_mark::check!(insert_group_empty_inner_attr);
cov_mark::check_count!(insert_empty_inner_attr, 2);
// Default configuration
check_crate(
"foo::bar",
r"#![allow(unused_imports)]",
r"#![allow(unused_imports)]
use foo::bar;",
)
);
// "not group" configuration
check_with_config(
"foo::bar",
r"#![allow(unused_imports)]",
r"#![allow(unused_imports)]
use foo::bar;",
&InsertUseConfig {
granularity: ImportGranularity::Item,
enforce_granularity: true,
prefix_kind: PrefixKind::Plain,
group: false,
skip_glob_imports: true,
},
);
}
#[test]