aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_assists/src/handlers/extract_type_alias.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_assists/src/handlers/extract_type_alias.rs')
-rw-r--r--crates/ide_assists/src/handlers/extract_type_alias.rs149
1 files changed, 149 insertions, 0 deletions
diff --git a/crates/ide_assists/src/handlers/extract_type_alias.rs b/crates/ide_assists/src/handlers/extract_type_alias.rs
new file mode 100644
index 000000000..442a209b9
--- /dev/null
+++ b/crates/ide_assists/src/handlers/extract_type_alias.rs
@@ -0,0 +1,149 @@
1use syntax::ast::{self, AstNode};
2
3use crate::{AssistContext, AssistId, AssistKind, Assists};
4
5// Assist: extract_type_alias
6//
7// Extracts the selected type as a type alias.
8//
9// ```
10// struct S {
11// field: $0(u8, u8, u8)$0,
12// }
13// ```
14// ->
15// ```
16// type $0Type = (u8, u8, u8);
17//
18// struct S {
19// field: Type,
20// }
21// ```
22pub(crate) fn extract_type_alias(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
23 if ctx.frange.range.is_empty() {
24 return None;
25 }
26
27 let node = ctx.find_node_at_range::<ast::Type>()?;
28 let insert = ctx.find_node_at_offset::<ast::Item>()?.syntax().text_range().start();
29 let target = node.syntax().text_range();
30
31 acc.add(
32 AssistId("extract_type_alias", AssistKind::RefactorExtract),
33 "Extract type as type alias",
34 target,
35 |builder| {
36 builder.edit_file(ctx.frange.file_id);
37 builder.replace(target, "Type");
38 match ctx.config.snippet_cap {
39 Some(cap) => {
40 builder.insert_snippet(cap, insert, format!("type $0Type = {};\n\n", node));
41 }
42 None => {
43 builder.insert(insert, format!("type Type = {};\n\n", node));
44 }
45 }
46 },
47 )
48}
49
50#[cfg(test)]
51mod tests {
52 use crate::tests::{check_assist, check_assist_not_applicable};
53
54 use super::*;
55
56 #[test]
57 fn test_not_applicable_without_selection() {
58 check_assist_not_applicable(
59 extract_type_alias,
60 r"
61struct S {
62 field: $0(u8, u8, u8),
63}
64 ",
65 );
66 }
67
68 #[test]
69 fn test_simple_types() {
70 check_assist(
71 extract_type_alias,
72 r"
73struct S {
74 field: $0u8$0,
75}
76 ",
77 r#"
78type $0Type = u8;
79
80struct S {
81 field: Type,
82}
83 "#,
84 );
85 }
86
87 #[test]
88 fn test_generic_type_arg() {
89 check_assist(
90 extract_type_alias,
91 r"
92fn generic<T>() {}
93
94fn f() {
95 generic::<$0()$0>();
96}
97 ",
98 r#"
99fn generic<T>() {}
100
101type $0Type = ();
102
103fn f() {
104 generic::<Type>();
105}
106 "#,
107 );
108 }
109
110 #[test]
111 fn test_inner_type_arg() {
112 check_assist(
113 extract_type_alias,
114 r"
115struct Vec<T> {}
116struct S {
117 v: Vec<Vec<$0Vec<u8>$0>>,
118}
119 ",
120 r#"
121struct Vec<T> {}
122type $0Type = Vec<u8>;
123
124struct S {
125 v: Vec<Vec<Type>>,
126}
127 "#,
128 );
129 }
130
131 #[test]
132 fn test_extract_inner_type() {
133 check_assist(
134 extract_type_alias,
135 r"
136struct S {
137 field: ($0u8$0,),
138}
139 ",
140 r#"
141type $0Type = u8;
142
143struct S {
144 field: (Type,),
145}
146 "#,
147 );
148 }
149}