use ide_db::imports::merge_imports::try_normalize_import; use syntax::{ast, AstNode}; use crate::{ assist_context::{AssistContext, Assists}, AssistId, AssistKind, }; // Assist: normalize_import // // Normalizes an import. // // ``` // use$0 std::{io, {fmt::Formatter}}; // ``` // -> // ``` // use std::{fmt::Formatter, io}; // ``` pub(crate) fn normalize_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let use_item = if ctx.has_empty_selection() { ctx.find_node_at_offset()? } else { ctx.covering_element().ancestors().find_map(ast::Use::cast)? }; let target = use_item.syntax().text_range(); let normalized_use_item = try_normalize_import(&use_item, ctx.config.insert_use.granularity.into())?; acc.add( AssistId("normalize_import", AssistKind::RefactorRewrite), "Normalize import", target, |builder| { builder.replace_ast(use_item, normalized_use_item); }, ) } #[cfg(test)] mod tests { use crate::tests::{ check_assist, check_assist_import_one, check_assist_not_applicable, check_assist_not_applicable_for_import_one, }; use super::*; macro_rules! check_assist_variations { ($fixture: literal, $expected: literal) => { check_assist( normalize_import, concat!("use $0", $fixture, ";"), concat!("use ", $expected, ";"), ); check_assist( normalize_import, concat!("$0use ", $fixture, ";"), concat!("use ", $expected, ";"), ); check_assist_import_one( normalize_import, concat!("use $0", $fixture, ";"), concat!("use {", $expected, "};"), ); check_assist_import_one( normalize_import, concat!("$0use ", $fixture, ";"), concat!("use {", $expected, "};"), ); check_assist_import_one( normalize_import, concat!("use $0{", $fixture, "};"), concat!("use {", $expected, "};"), ); check_assist_import_one( normalize_import, concat!("$0use {", $fixture, "};"), concat!("use {", $expected, "};"), ); check_assist( normalize_import, concat!("use $0", $fixture, "$0;"), concat!("use ", $expected, ";"), ); check_assist( normalize_import, concat!("$0use ", $fixture, ";$0"), concat!("use ", $expected, ";"), ); }; } macro_rules! check_assist_not_applicable_variations { ($fixture: literal) => { check_assist_not_applicable(normalize_import, concat!("use $0", $fixture, ";")); check_assist_not_applicable(normalize_import, concat!("$0use ", $fixture, ";")); check_assist_not_applicable_for_import_one( normalize_import, concat!("use $0{", $fixture, "};"), ); check_assist_not_applicable_for_import_one( normalize_import, concat!("$0use {", $fixture, "};"), ); }; } #[test] fn test_order() { check_assist_variations!( "foo::{*, Qux, bar::{Quux, Bar}, baz, FOO_BAZ, self, Baz}", "foo::{self, bar::{Bar, Quux}, baz, Baz, Qux, FOO_BAZ, *}" ); } #[test] fn test_redundant_braces() { check_assist_variations!("foo::{bar::{baz, Qux}}", "foo::bar::{baz, Qux}"); check_assist_variations!("foo::{bar::{self}}", "foo::bar"); check_assist_variations!("foo::{bar::{*}}", "foo::bar::*"); check_assist_variations!("foo::{bar::{Qux as Quux}}", "foo::bar::Qux as Quux"); check_assist_variations!( "foo::bar::{{FOO_BAZ, Qux, self}, {*, baz}}", "foo::bar::{self, baz, Qux, FOO_BAZ, *}" ); check_assist_variations!( "foo::bar::{{{FOO_BAZ}, {{Qux}, {self}}}, {{*}, {baz}}}", "foo::bar::{self, baz, Qux, FOO_BAZ, *}" ); } #[test] fn test_merge() { check_assist_variations!( "foo::{*, bar, {FOO_BAZ, qux}, bar::{*, baz}, {Quux}}", "foo::{bar::{self, baz, *}, qux, Quux, FOO_BAZ, *}" ); check_assist_variations!( "foo::{*, bar, {FOO_BAZ, qux}, bar::{*, baz}, {Quux, bar::{baz::Foo}}}", "foo::{bar::{self, baz::{self, Foo}, *}, qux, Quux, FOO_BAZ, *}" ); } #[test] fn not_applicable_to_normalized_import() { check_assist_not_applicable_variations!("foo::bar"); check_assist_not_applicable_variations!("foo::bar::*"); check_assist_not_applicable_variations!("foo::bar::Qux as Quux"); check_assist_not_applicable_variations!("foo::bar::{self, baz, Qux, FOO_BAZ, *}"); check_assist_not_applicable_variations!( "foo::{self, bar::{Bar, Quux}, baz, Baz, Qux, FOO_BAZ, *}" ); check_assist_not_applicable_variations!( "foo::{bar::{self, baz, *}, qux, Quux, FOO_BAZ, *}" ); check_assist_not_applicable_variations!( "foo::{bar::{self, baz::{self, Foo}, *}, qux, Quux, FOO_BAZ, *}" ); } }