diff options
-rw-r--r-- | crates/syntax/src/ast/edit_in_place.rs | 99 |
1 files changed, 94 insertions, 5 deletions
diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs index 27350e2b9..04f97f368 100644 --- a/crates/syntax/src/ast/edit_in_place.rs +++ b/crates/syntax/src/ast/edit_in_place.rs | |||
@@ -23,7 +23,15 @@ impl GenericParamsOwnerEdit for ast::Fn { | |||
23 | match self.generic_param_list() { | 23 | match self.generic_param_list() { |
24 | Some(it) => it, | 24 | Some(it) => it, |
25 | None => { | 25 | None => { |
26 | let position = Position::after(self.name().unwrap().syntax); | 26 | let position = if let Some(name) = self.name() { |
27 | Position::after(name.syntax) | ||
28 | } else if let Some(fn_token) = self.fn_token() { | ||
29 | Position::after(fn_token) | ||
30 | } else if let Some(param_list) = self.param_list() { | ||
31 | Position::before(param_list.syntax) | ||
32 | } else { | ||
33 | Position::last_child_of(self.syntax()) | ||
34 | }; | ||
27 | create_generic_param_list(position) | 35 | create_generic_param_list(position) |
28 | } | 36 | } |
29 | } | 37 | } |
@@ -49,7 +57,11 @@ impl GenericParamsOwnerEdit for ast::Impl { | |||
49 | match self.generic_param_list() { | 57 | match self.generic_param_list() { |
50 | Some(it) => it, | 58 | Some(it) => it, |
51 | None => { | 59 | None => { |
52 | let position = Position::after(self.impl_token().unwrap()); | 60 | let position = if let Some(imp_token) = self.impl_token() { |
61 | Position::after(imp_token) | ||
62 | } else { | ||
63 | Position::last_child_of(self.syntax()) | ||
64 | }; | ||
53 | create_generic_param_list(position) | 65 | create_generic_param_list(position) |
54 | } | 66 | } |
55 | } | 67 | } |
@@ -70,7 +82,19 @@ impl GenericParamsOwnerEdit for ast::Impl { | |||
70 | 82 | ||
71 | impl GenericParamsOwnerEdit for ast::Trait { | 83 | impl GenericParamsOwnerEdit for ast::Trait { |
72 | fn get_or_create_generic_param_list(&self) -> ast::GenericParamList { | 84 | fn get_or_create_generic_param_list(&self) -> ast::GenericParamList { |
73 | todo!() | 85 | match self.generic_param_list() { |
86 | Some(it) => it, | ||
87 | None => { | ||
88 | let position = if let Some(name) = self.name() { | ||
89 | Position::after(name.syntax) | ||
90 | } else if let Some(trait_token) = self.trait_token() { | ||
91 | Position::after(trait_token) | ||
92 | } else { | ||
93 | Position::last_child_of(self.syntax()) | ||
94 | }; | ||
95 | create_generic_param_list(position) | ||
96 | } | ||
97 | } | ||
74 | } | 98 | } |
75 | 99 | ||
76 | fn get_or_create_where_clause(&self) -> WhereClause { | 100 | fn get_or_create_where_clause(&self) -> WhereClause { |
@@ -88,7 +112,19 @@ impl GenericParamsOwnerEdit for ast::Trait { | |||
88 | 112 | ||
89 | impl GenericParamsOwnerEdit for ast::Struct { | 113 | impl GenericParamsOwnerEdit for ast::Struct { |
90 | fn get_or_create_generic_param_list(&self) -> ast::GenericParamList { | 114 | fn get_or_create_generic_param_list(&self) -> ast::GenericParamList { |
91 | todo!() | 115 | match self.generic_param_list() { |
116 | Some(it) => it, | ||
117 | None => { | ||
118 | let position = if let Some(name) = self.name() { | ||
119 | Position::after(name.syntax) | ||
120 | } else if let Some(struct_token) = self.struct_token() { | ||
121 | Position::after(struct_token) | ||
122 | } else { | ||
123 | Position::last_child_of(self.syntax()) | ||
124 | }; | ||
125 | create_generic_param_list(position) | ||
126 | } | ||
127 | } | ||
92 | } | 128 | } |
93 | 129 | ||
94 | fn get_or_create_where_clause(&self) -> WhereClause { | 130 | fn get_or_create_where_clause(&self) -> WhereClause { |
@@ -114,7 +150,19 @@ impl GenericParamsOwnerEdit for ast::Struct { | |||
114 | 150 | ||
115 | impl GenericParamsOwnerEdit for ast::Enum { | 151 | impl GenericParamsOwnerEdit for ast::Enum { |
116 | fn get_or_create_generic_param_list(&self) -> ast::GenericParamList { | 152 | fn get_or_create_generic_param_list(&self) -> ast::GenericParamList { |
117 | todo!() | 153 | match self.generic_param_list() { |
154 | Some(it) => it, | ||
155 | None => { | ||
156 | let position = if let Some(name) = self.name() { | ||
157 | Position::after(name.syntax) | ||
158 | } else if let Some(enum_token) = self.enum_token() { | ||
159 | Position::after(enum_token) | ||
160 | } else { | ||
161 | Position::last_child_of(self.syntax()) | ||
162 | }; | ||
163 | create_generic_param_list(position) | ||
164 | } | ||
165 | } | ||
118 | } | 166 | } |
119 | 167 | ||
120 | fn get_or_create_where_clause(&self) -> WhereClause { | 168 | fn get_or_create_where_clause(&self) -> WhereClause { |
@@ -228,3 +276,44 @@ impl ast::Use { | |||
228 | ted::remove(self.syntax()) | 276 | ted::remove(self.syntax()) |
229 | } | 277 | } |
230 | } | 278 | } |
279 | |||
280 | #[cfg(test)] | ||
281 | mod tests { | ||
282 | use std::fmt; | ||
283 | |||
284 | use crate::SourceFile; | ||
285 | |||
286 | use super::*; | ||
287 | |||
288 | fn ast_mut_from_text<N: AstNode>(text: &str) -> N { | ||
289 | let parse = SourceFile::parse(text); | ||
290 | parse.tree().syntax().descendants().find_map(N::cast).unwrap().clone_for_update() | ||
291 | } | ||
292 | |||
293 | #[test] | ||
294 | fn test_create_generic_param_list() { | ||
295 | fn check_create_gpl<N: GenericParamsOwnerEdit + fmt::Display>(before: &str, after: &str) { | ||
296 | let gpl_owner = ast_mut_from_text::<N>(before); | ||
297 | gpl_owner.get_or_create_generic_param_list(); | ||
298 | assert_eq!(gpl_owner.to_string(), after); | ||
299 | } | ||
300 | |||
301 | check_create_gpl::<ast::Fn>("fn foo", "fn foo<>"); | ||
302 | check_create_gpl::<ast::Fn>("fn foo() {}", "fn foo<>() {}"); | ||
303 | |||
304 | check_create_gpl::<ast::Impl>("impl", "impl<>"); | ||
305 | check_create_gpl::<ast::Impl>("impl Struct {}", "impl<> Struct {}"); | ||
306 | check_create_gpl::<ast::Impl>("impl Trait for Struct {}", "impl<> Trait for Struct {}"); | ||
307 | |||
308 | check_create_gpl::<ast::Trait>("trait Trait<>", "trait Trait<>"); | ||
309 | check_create_gpl::<ast::Trait>("trait Trait<> {}", "trait Trait<> {}"); | ||
310 | |||
311 | check_create_gpl::<ast::Struct>("struct A", "struct A<>"); | ||
312 | check_create_gpl::<ast::Struct>("struct A;", "struct A<>;"); | ||
313 | check_create_gpl::<ast::Struct>("struct A();", "struct A<>();"); | ||
314 | check_create_gpl::<ast::Struct>("struct A {}", "struct A<> {}"); | ||
315 | |||
316 | check_create_gpl::<ast::Enum>("enum E", "enum E<>"); | ||
317 | check_create_gpl::<ast::Enum>("enum E {", "enum E<> {"); | ||
318 | } | ||
319 | } | ||