2 ast::{self, edit::IndentLevel, AstNode},
6 use crate::{AssistContext, AssistId, AssistKind, Assists};
8 // Assist: extract_type_alias
10 // Extracts the selected type as a type alias.
14 // field: $0(u8, u8, u8)$0,
19 // type $0Type = (u8, u8, u8);
25 pub(crate) fn extract_type_alias(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
26 if ctx.frange.range.is_empty() {
30 let node = ctx.find_node_at_range::<ast::Type>()?;
31 let item = ctx.find_node_at_offset::<ast::Item>()?;
32 let insert = match_ast! {
33 match (item.syntax().parent()?) {
34 ast::AssocItemList(it) => it.syntax().parent()?,
35 _ => item.syntax().clone(),
38 let indent = IndentLevel::from_node(&insert);
39 let insert = insert.text_range().start();
40 let target = node.syntax().text_range();
43 AssistId("extract_type_alias", AssistKind::RefactorExtract),
44 "Extract type as type alias",
47 builder.edit_file(ctx.frange.file_id);
48 builder.replace(target, "Type");
49 match ctx.config.snippet_cap {
51 builder.insert_snippet(
54 format!("type $0Type = {};\n\n{}", node, indent),
58 builder.insert(insert, format!("type Type = {};\n\n{}", node, indent));
67 use crate::tests::{check_assist, check_assist_not_applicable};
72 fn test_not_applicable_without_selection() {
73 check_assist_not_applicable(
77 field: $0(u8, u8, u8),
84 fn test_simple_types() {
103 fn test_generic_type_arg() {
126 fn test_inner_type_arg() {
132 v: Vec<Vec<$0Vec<u8>$0>>,
137 type $0Type = Vec<u8>;
147 fn test_extract_inner_type() {
166 fn extract_from_impl_or_trait() {
167 // When invoked in an impl/trait, extracted type alias should be placed next to the
168 // impl/trait, not inside.
173 fn f() -> $0(u8, u8)$0 {}
177 type $0Type = (u8, u8);
188 fn f() -> $0(u8, u8)$0 {}
192 type $0Type = (u8, u8);