diff options
Diffstat (limited to 'crates/ra_assists/src/assists/add_new.rs')
-rw-r--r-- | crates/ra_assists/src/assists/add_new.rs | 86 |
1 files changed, 40 insertions, 46 deletions
diff --git a/crates/ra_assists/src/assists/add_new.rs b/crates/ra_assists/src/assists/add_new.rs index 8f68bd5fb..b2f946fac 100644 --- a/crates/ra_assists/src/assists/add_new.rs +++ b/crates/ra_assists/src/assists/add_new.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use format_buf::format; | 1 | use format_buf::format; |
2 | use hir::{db::HirDatabase, FromSource}; | 2 | use hir::{db::HirDatabase, FromSource, InFile}; |
3 | use join_to_string::join; | 3 | use join_to_string::join; |
4 | use ra_syntax::{ | 4 | use ra_syntax::{ |
5 | ast::{ | 5 | ast::{ |
@@ -56,42 +56,39 @@ pub(crate) fn add_new(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | |||
56 | let vis = vis.as_ref().map(String::as_str).unwrap_or(""); | 56 | let vis = vis.as_ref().map(String::as_str).unwrap_or(""); |
57 | write!(&mut buf, " {}fn new(", vis).unwrap(); | 57 | write!(&mut buf, " {}fn new(", vis).unwrap(); |
58 | 58 | ||
59 | join(field_list.fields().map(|f| { | 59 | join(field_list.fields().filter_map(|f| { |
60 | format!( | 60 | Some(format!("{}: {}", f.name()?.syntax().text(), f.ascribed_type()?.syntax().text())) |
61 | "{}: {}", | ||
62 | f.name().unwrap().syntax().text(), | ||
63 | f.ascribed_type().unwrap().syntax().text() | ||
64 | ) | ||
65 | })) | 61 | })) |
66 | .separator(", ") | 62 | .separator(", ") |
67 | .to_buf(&mut buf); | 63 | .to_buf(&mut buf); |
68 | 64 | ||
69 | buf.push_str(") -> Self { Self {"); | 65 | buf.push_str(") -> Self { Self {"); |
70 | 66 | ||
71 | join(field_list.fields().map(|f| f.name().unwrap().syntax().text())) | 67 | join(field_list.fields().filter_map(|f| Some(f.name()?.syntax().text()))) |
72 | .separator(", ") | 68 | .separator(", ") |
73 | .surround_with(" ", " ") | 69 | .surround_with(" ", " ") |
74 | .to_buf(&mut buf); | 70 | .to_buf(&mut buf); |
75 | 71 | ||
76 | buf.push_str("} }"); | 72 | buf.push_str("} }"); |
77 | 73 | ||
78 | let (start_offset, end_offset) = if let Some(impl_block) = impl_block { | 74 | let (start_offset, end_offset) = impl_block |
79 | buf.push('\n'); | 75 | .and_then(|impl_block| { |
80 | let start = impl_block | 76 | buf.push('\n'); |
81 | .syntax() | 77 | let start = impl_block |
82 | .descendants_with_tokens() | 78 | .syntax() |
83 | .find(|t| t.kind() == T!['{']) | 79 | .descendants_with_tokens() |
84 | .unwrap() | 80 | .find(|t| t.kind() == T!['{'])? |
85 | .text_range() | 81 | .text_range() |
86 | .end(); | 82 | .end(); |
87 | 83 | ||
88 | (start, TextUnit::from_usize(1)) | 84 | Some((start, TextUnit::from_usize(1))) |
89 | } else { | 85 | }) |
90 | buf = generate_impl_text(&strukt, &buf); | 86 | .unwrap_or_else(|| { |
91 | let start = strukt.syntax().text_range().end(); | 87 | buf = generate_impl_text(&strukt, &buf); |
92 | 88 | let start = strukt.syntax().text_range().end(); | |
93 | (start, TextUnit::from_usize(3)) | 89 | |
94 | }; | 90 | (start, TextUnit::from_usize(3)) |
91 | }); | ||
95 | 92 | ||
96 | edit.set_cursor(start_offset + TextUnit::of_str(&buf) - end_offset); | 93 | edit.set_cursor(start_offset + TextUnit::of_str(&buf) - end_offset); |
97 | edit.insert(start_offset, buf); | 94 | edit.insert(start_offset, buf); |
@@ -141,44 +138,41 @@ fn find_struct_impl( | |||
141 | })?; | 138 | })?; |
142 | 139 | ||
143 | let struct_ty = { | 140 | let struct_ty = { |
144 | let src = hir::Source { file_id: ctx.frange.file_id.into(), value: strukt.clone() }; | 141 | let src = InFile { file_id: ctx.frange.file_id.into(), value: strukt.clone() }; |
145 | hir::Struct::from_source(db, src).unwrap().ty(db) | 142 | hir::Struct::from_source(db, src)?.ty(db) |
146 | }; | 143 | }; |
147 | 144 | ||
148 | let mut found_new_fn = false; | 145 | let block = module.descendants().filter_map(ast::ImplBlock::cast).find_map(|impl_blk| { |
149 | 146 | let src = InFile { file_id: ctx.frange.file_id.into(), value: impl_blk.clone() }; | |
150 | let block = module.descendants().filter_map(ast::ImplBlock::cast).find(|impl_blk| { | 147 | let blk = hir::ImplBlock::from_source(db, src)?; |
151 | if found_new_fn { | ||
152 | return false; | ||
153 | } | ||
154 | |||
155 | let src = hir::Source { file_id: ctx.frange.file_id.into(), value: impl_blk.clone() }; | ||
156 | let blk = hir::ImplBlock::from_source(db, src).unwrap(); | ||
157 | 148 | ||
158 | let same_ty = blk.target_ty(db) == struct_ty; | 149 | let same_ty = blk.target_ty(db) == struct_ty; |
159 | let not_trait_impl = blk.target_trait(db).is_none(); | 150 | let not_trait_impl = blk.target_trait(db).is_none(); |
160 | 151 | ||
161 | if !(same_ty && not_trait_impl) { | 152 | if !(same_ty && not_trait_impl) { |
162 | return false; | 153 | None |
154 | } else { | ||
155 | Some(impl_blk) | ||
163 | } | 156 | } |
164 | |||
165 | found_new_fn = has_new_fn(impl_blk); | ||
166 | true | ||
167 | }); | 157 | }); |
168 | 158 | ||
169 | if found_new_fn { | 159 | if let Some(ref impl_blk) = block { |
170 | None | 160 | if has_new_fn(impl_blk) { |
171 | } else { | 161 | return None; |
172 | Some(block) | 162 | } |
173 | } | 163 | } |
164 | |||
165 | Some(block) | ||
174 | } | 166 | } |
175 | 167 | ||
176 | fn has_new_fn(imp: &ast::ImplBlock) -> bool { | 168 | fn has_new_fn(imp: &ast::ImplBlock) -> bool { |
177 | if let Some(il) = imp.item_list() { | 169 | if let Some(il) = imp.item_list() { |
178 | for item in il.impl_items() { | 170 | for item in il.impl_items() { |
179 | if let ast::ImplItem::FnDef(f) = item { | 171 | if let ast::ImplItem::FnDef(f) = item { |
180 | if f.name().unwrap().text().eq_ignore_ascii_case("new") { | 172 | if let Some(name) = f.name() { |
181 | return true; | 173 | if name.text().eq_ignore_ascii_case("new") { |
174 | return true; | ||
175 | } | ||
182 | } | 176 | } |
183 | } | 177 | } |
184 | } | 178 | } |