aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_assists/src/handlers
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_assists/src/handlers')
-rw-r--r--crates/ide_assists/src/handlers/generate_enum_projection_method.rs108
1 files changed, 66 insertions, 42 deletions
diff --git a/crates/ide_assists/src/handlers/generate_enum_projection_method.rs b/crates/ide_assists/src/handlers/generate_enum_projection_method.rs
index 71447f310..871bcab50 100644
--- a/crates/ide_assists/src/handlers/generate_enum_projection_method.rs
+++ b/crates/ide_assists/src/handlers/generate_enum_projection_method.rs
@@ -8,9 +8,9 @@ use crate::{
8 AssistContext, AssistId, AssistKind, Assists, 8 AssistContext, AssistId, AssistKind, Assists,
9}; 9};
10 10
11// Assist: generate_enum_into_method 11// Assist: generate_enum_try_into_method
12// 12//
13// Generate an `into_` method for an enum variant. 13// Generate an `try_into_` method for an enum variant.
14// 14//
15// ``` 15// ```
16// enum Value { 16// enum Value {
@@ -26,23 +26,29 @@ use crate::{
26// } 26// }
27// 27//
28// impl Value { 28// impl Value {
29// fn into_text(self) -> Option<String> { 29// fn try_into_text(self) -> Result<String, Self> {
30// if let Self::Text(v) = self { 30// if let Self::Text(v) = self {
31// Some(v) 31// Ok(v)
32// } else { 32// } else {
33// None 33// Err(self)
34// } 34// }
35// } 35// }
36// } 36// }
37// ``` 37// ```
38pub(crate) fn generate_enum_into_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 38pub(crate) fn generate_enum_try_into_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
39 generate_enum_projection_method( 39 generate_enum_projection_method(
40 acc, 40 acc,
41 ctx, 41 ctx,
42 "generate_enum_into_method", 42 "generate_enum_try_into_method",
43 "Generate an `into_` method for an enum variant", 43 "Generate an `try_into_` method for an enum variant",
44 "into", 44 ProjectionProps {
45 "", 45 fn_name_prefix: "try_into",
46 self_param: "self",
47 return_prefix: "Result<",
48 return_suffix: ", Self>",
49 happy_case: "Ok",
50 sad_case: "Err(self)",
51 },
46 ) 52 )
47} 53}
48 54
@@ -79,18 +85,32 @@ pub(crate) fn generate_enum_as_method(acc: &mut Assists, ctx: &AssistContext) ->
79 ctx, 85 ctx,
80 "generate_enum_as_method", 86 "generate_enum_as_method",
81 "Generate an `as_` method for an enum variant", 87 "Generate an `as_` method for an enum variant",
82 "as", 88 ProjectionProps {
83 "&", 89 fn_name_prefix: "as",
90 self_param: "&self",
91 return_prefix: "Option<&",
92 return_suffix: ">",
93 happy_case: "Some",
94 sad_case: "None",
95 },
84 ) 96 )
85} 97}
86 98
87pub(crate) fn generate_enum_projection_method( 99struct ProjectionProps {
100 fn_name_prefix: &'static str,
101 self_param: &'static str,
102 return_prefix: &'static str,
103 return_suffix: &'static str,
104 happy_case: &'static str,
105 sad_case: &'static str,
106}
107
108fn generate_enum_projection_method(
88 acc: &mut Assists, 109 acc: &mut Assists,
89 ctx: &AssistContext, 110 ctx: &AssistContext,
90 assist_id: &'static str, 111 assist_id: &'static str,
91 assist_description: &str, 112 assist_description: &str,
92 fn_name_prefix: &str, 113 props: ProjectionProps,
93 ref_prefix: &str,
94) -> Option<()> { 114) -> Option<()> {
95 let variant = ctx.find_node_at_offset::<ast::Variant>()?; 115 let variant = ctx.find_node_at_offset::<ast::Variant>()?;
96 let variant_name = variant.name()?; 116 let variant_name = variant.name()?;
@@ -112,7 +132,7 @@ pub(crate) fn generate_enum_projection_method(
112 ast::StructKind::Unit => return None, 132 ast::StructKind::Unit => return None,
113 }; 133 };
114 134
115 let fn_name = format!("{}_{}", fn_name_prefix, &to_lower_snake_case(variant_name.text())); 135 let fn_name = format!("{}_{}", props.fn_name_prefix, &to_lower_snake_case(variant_name.text()));
116 136
117 // Return early if we've found an existing new fn 137 // Return early if we've found an existing new fn
118 let impl_def = find_struct_impl(&ctx, &parent_enum, &fn_name)?; 138 let impl_def = find_struct_impl(&ctx, &parent_enum, &fn_name)?;
@@ -121,20 +141,24 @@ pub(crate) fn generate_enum_projection_method(
121 acc.add(AssistId(assist_id, AssistKind::Generate), assist_description, target, |builder| { 141 acc.add(AssistId(assist_id, AssistKind::Generate), assist_description, target, |builder| {
122 let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{} ", v)); 142 let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{} ", v));
123 let method = format!( 143 let method = format!(
124 " {0}fn {1}({2}self) -> Option<{2}{3}> {{ 144 " {0}fn {1}({2}) -> {3}{4}{5} {{
125 if let Self::{4}{5} = self {{ 145 if let Self::{6}{7} = self {{
126 Some({6}) 146 {8}({9})
127 }} else {{ 147 }} else {{
128 None 148 {10}
129 }} 149 }}
130 }}", 150 }}",
131 vis, 151 vis,
132 fn_name, 152 fn_name,
133 ref_prefix, 153 props.self_param,
154 props.return_prefix,
134 field_type.syntax(), 155 field_type.syntax(),
156 props.return_suffix,
135 variant_name, 157 variant_name,
136 pattern_suffix, 158 pattern_suffix,
159 props.happy_case,
137 bound_name, 160 bound_name,
161 props.sad_case,
138 ); 162 );
139 163
140 add_method_to_adt(builder, &parent_enum, impl_def, &method); 164 add_method_to_adt(builder, &parent_enum, impl_def, &method);
@@ -148,9 +172,9 @@ mod tests {
148 use super::*; 172 use super::*;
149 173
150 #[test] 174 #[test]
151 fn test_generate_enum_into_tuple_variant() { 175 fn test_generate_enum_try_into_tuple_variant() {
152 check_assist( 176 check_assist(
153 generate_enum_into_method, 177 generate_enum_try_into_method,
154 r#" 178 r#"
155enum Value { 179enum Value {
156 Number(i32), 180 Number(i32),
@@ -162,11 +186,11 @@ enum Value {
162} 186}
163 187
164impl Value { 188impl Value {
165 fn into_text(self) -> Option<String> { 189 fn try_into_text(self) -> Result<String, Self> {
166 if let Self::Text(v) = self { 190 if let Self::Text(v) = self {
167 Some(v) 191 Ok(v)
168 } else { 192 } else {
169 None 193 Err(self)
170 } 194 }
171 } 195 }
172}"#, 196}"#,
@@ -174,20 +198,20 @@ impl Value {
174 } 198 }
175 199
176 #[test] 200 #[test]
177 fn test_generate_enum_into_already_implemented() { 201 fn test_generate_enum_try_into_already_implemented() {
178 check_assist_not_applicable( 202 check_assist_not_applicable(
179 generate_enum_into_method, 203 generate_enum_try_into_method,
180 r#"enum Value { 204 r#"enum Value {
181 Number(i32), 205 Number(i32),
182 Text(String)$0, 206 Text(String)$0,
183} 207}
184 208
185impl Value { 209impl Value {
186 fn into_text(self) -> Option<String> { 210 fn try_into_text(self) -> Result<String, Self> {
187 if let Self::Text(v) = self { 211 if let Self::Text(v) = self {
188 Some(v) 212 Ok(v)
189 } else { 213 } else {
190 None 214 Err(self)
191 } 215 }
192 } 216 }
193}"#, 217}"#,
@@ -195,9 +219,9 @@ impl Value {
195 } 219 }
196 220
197 #[test] 221 #[test]
198 fn test_generate_enum_into_unit_variant() { 222 fn test_generate_enum_try_into_unit_variant() {
199 check_assist_not_applicable( 223 check_assist_not_applicable(
200 generate_enum_into_method, 224 generate_enum_try_into_method,
201 r#"enum Value { 225 r#"enum Value {
202 Number(i32), 226 Number(i32),
203 Text(String), 227 Text(String),
@@ -207,9 +231,9 @@ impl Value {
207 } 231 }
208 232
209 #[test] 233 #[test]
210 fn test_generate_enum_into_record_with_multiple_fields() { 234 fn test_generate_enum_try_into_record_with_multiple_fields() {
211 check_assist_not_applicable( 235 check_assist_not_applicable(
212 generate_enum_into_method, 236 generate_enum_try_into_method,
213 r#"enum Value { 237 r#"enum Value {
214 Number(i32), 238 Number(i32),
215 Text(String), 239 Text(String),
@@ -219,9 +243,9 @@ impl Value {
219 } 243 }
220 244
221 #[test] 245 #[test]
222 fn test_generate_enum_into_tuple_with_multiple_fields() { 246 fn test_generate_enum_try_into_tuple_with_multiple_fields() {
223 check_assist_not_applicable( 247 check_assist_not_applicable(
224 generate_enum_into_method, 248 generate_enum_try_into_method,
225 r#"enum Value { 249 r#"enum Value {
226 Number(i32), 250 Number(i32),
227 Text(String, String)$0, 251 Text(String, String)$0,
@@ -230,9 +254,9 @@ impl Value {
230 } 254 }
231 255
232 #[test] 256 #[test]
233 fn test_generate_enum_into_record_variant() { 257 fn test_generate_enum_try_into_record_variant() {
234 check_assist( 258 check_assist(
235 generate_enum_into_method, 259 generate_enum_try_into_method,
236 r#"enum Value { 260 r#"enum Value {
237 Number(i32), 261 Number(i32),
238 Text { text: String }$0, 262 Text { text: String }$0,
@@ -243,11 +267,11 @@ impl Value {
243} 267}
244 268
245impl Value { 269impl Value {
246 fn into_text(self) -> Option<String> { 270 fn try_into_text(self) -> Result<String, Self> {
247 if let Self::Text { text } = self { 271 if let Self::Text { text } = self {
248 Some(text) 272 Ok(text)
249 } else { 273 } else {
250 None 274 Err(self)
251 } 275 }
252 } 276 }
253}"#, 277}"#,