Skip to content

Commit 3d0d8ac

Browse files
committed
migrate generate_deref to SyntaxEditor and SyntaxFactory and remove usage of remove-generate-trail-impl-text-intransitive
1 parent f91b879 commit 3d0d8ac

1 file changed

Lines changed: 94 additions & 32 deletions

File tree

crates/ide-assists/src/handlers/generate_deref.rs

Lines changed: 94 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
use std::fmt::Display;
2-
31
use hir::{ModPath, ModuleDef};
4-
use ide_db::{RootDatabase, famous_defs::FamousDefs};
2+
use ide_db::{FileId, RootDatabase, famous_defs::FamousDefs};
53
use syntax::{
6-
AstNode, Edition, SyntaxNode,
7-
ast::{self, HasName},
4+
Edition,
5+
ast::{self, AstNode, HasName, edit::AstNodeEdit, syntax_factory::SyntaxFactory},
6+
syntax_editor::Position,
87
};
98

109
use crate::{
1110
AssistId,
1211
assist_context::{AssistContext, Assists, SourceChangeBuilder},
13-
utils::generate_trait_impl_text_intransitive,
12+
utils::generate_trait_impl_intransitive_with_item,
1413
};
1514

1615
// Assist: generate_deref
@@ -64,6 +63,7 @@ fn generate_record_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
6463
let field_type = field.ty()?;
6564
let field_name = field.name()?;
6665
let target = field.syntax().text_range();
66+
let file_id = ctx.vfs_file_id();
6767
acc.add(
6868
AssistId::generate("generate_deref"),
6969
format!("Generate `{deref_type_to_generate:?}` impl using `{field_name}`"),
@@ -72,9 +72,10 @@ fn generate_record_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
7272
generate_edit(
7373
ctx.db(),
7474
edit,
75+
file_id,
7576
strukt,
76-
field_type.syntax(),
77-
field_name.syntax(),
77+
field_type,
78+
&field_name.to_string(),
7879
deref_type_to_generate,
7980
trait_path,
8081
module.krate(ctx.db()).edition(ctx.db()),
@@ -105,6 +106,7 @@ fn generate_tuple_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()
105106

106107
let field_type = field.ty()?;
107108
let target = field.syntax().text_range();
109+
let file_id = ctx.vfs_file_id();
108110
acc.add(
109111
AssistId::generate("generate_deref"),
110112
format!("Generate `{deref_type_to_generate:?}` impl using `{field}`"),
@@ -113,9 +115,10 @@ fn generate_tuple_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()
113115
generate_edit(
114116
ctx.db(),
115117
edit,
118+
file_id,
116119
strukt,
117-
field_type.syntax(),
118-
field_list_index,
120+
field_type,
121+
&field_list_index.to_string(),
119122
deref_type_to_generate,
120123
trait_path,
121124
module.krate(ctx.db()).edition(ctx.db()),
@@ -127,35 +130,94 @@ fn generate_tuple_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()
127130
fn generate_edit(
128131
db: &RootDatabase,
129132
edit: &mut SourceChangeBuilder,
133+
file_id: FileId,
130134
strukt: ast::Struct,
131-
field_type_syntax: &SyntaxNode,
132-
field_name: impl Display,
135+
field_type: ast::Type,
136+
field_name: &str,
133137
deref_type: DerefType,
134138
trait_path: ModPath,
135139
edition: Edition,
136140
) {
137-
let start_offset = strukt.syntax().text_range().end();
138-
let impl_code = match deref_type {
139-
DerefType::Deref => format!(
140-
r#" type Target = {field_type_syntax};
141-
142-
fn deref(&self) -> &Self::Target {{
143-
&self.{field_name}
144-
}}"#,
145-
),
146-
DerefType::DerefMut => format!(
147-
r#" fn deref_mut(&mut self) -> &mut Self::Target {{
148-
&mut self.{field_name}
149-
}}"#,
150-
),
141+
let make = SyntaxFactory::with_mappings();
142+
let strukt_adt = ast::Adt::Struct(strukt.clone());
143+
let trait_ty = make.ty(&trait_path.display(db, edition).to_string());
144+
145+
let assoc_items: Vec<ast::AssocItem> = match deref_type {
146+
DerefType::Deref => {
147+
let target_alias = make.ty_alias(
148+
[],
149+
"Target",
150+
None,
151+
None,
152+
None,
153+
Some((field_type, None)),
154+
);
155+
let ret_ty =
156+
make.ty_ref(make.ty_path(make.path_from_text("Self::Target")).into(), false);
157+
let field_expr =
158+
make.expr_field(make.expr_path(make.ident_path("self")), field_name);
159+
let body =
160+
make.block_expr([], Some(make.expr_ref(field_expr.into(), false)));
161+
let fn_ = make
162+
.fn_(
163+
[],
164+
None,
165+
make.name("deref"),
166+
None,
167+
None,
168+
make.param_list(Some(make.self_param()), []),
169+
body,
170+
Some(make.ret_type(ret_ty)),
171+
false,
172+
false,
173+
false,
174+
false,
175+
)
176+
.indent(1.into());
177+
vec![
178+
ast::AssocItem::TypeAlias(target_alias),
179+
ast::AssocItem::Fn(fn_),
180+
]
181+
}
182+
DerefType::DerefMut => {
183+
let ret_ty =
184+
make.ty_ref(make.ty_path(make.path_from_text("Self::Target")).into(), true);
185+
let field_expr =
186+
make.expr_field(make.expr_path(make.ident_path("self")), field_name);
187+
let body =
188+
make.block_expr([], Some(make.expr_ref(field_expr.into(), true)));
189+
let fn_ = make
190+
.fn_(
191+
[],
192+
None,
193+
make.name("deref_mut"),
194+
None,
195+
None,
196+
make.param_list(Some(make.mut_self_param()), []),
197+
body,
198+
Some(make.ret_type(ret_ty)),
199+
false,
200+
false,
201+
false,
202+
false,
203+
)
204+
.indent(1.into());
205+
vec![ast::AssocItem::Fn(fn_)]
206+
}
151207
};
152-
let strukt_adt = ast::Adt::Struct(strukt);
153-
let deref_impl = generate_trait_impl_text_intransitive(
154-
&strukt_adt,
155-
&trait_path.display(db, edition).to_string(),
156-
&impl_code,
208+
209+
let body = make.assoc_item_list(assoc_items);
210+
let indent = strukt.indent_level();
211+
let impl_ = generate_trait_impl_intransitive_with_item(&make, &strukt_adt, trait_ty, body)
212+
.indent(indent);
213+
214+
let mut editor = edit.make_editor(strukt.syntax());
215+
editor.insert_all(
216+
Position::after(strukt.syntax()),
217+
vec![make.whitespace(&format!("\n\n{indent}")).into(), impl_.syntax().clone().into()],
157218
);
158-
edit.insert(start_offset, deref_impl);
219+
editor.add_mappings(make.finish_with_mappings());
220+
edit.add_file_edits(file_id, editor);
159221
}
160222

161223
fn existing_deref_impl(

0 commit comments

Comments
 (0)