Skip to content

Commit 8b7c029

Browse files
committed
feat: extract_struct_from_function_signature
fixed issue with resolving generics (I think) started writing the code to update the original function
1 parent 644fd3d commit 8b7c029

File tree

1 file changed

+44
-5
lines changed

1 file changed

+44
-5
lines changed

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

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ pub(crate) fn extract_struct_from_function_signature(
6161
Some(make::record_field(
6262
fn_ast.visibility(),
6363
param.pat().and_then(pat_to_name)?,
64+
// TODO: how are we going to handle references without explicit lifetimes
6465
param.ty()?,
6566
))
6667
})
@@ -72,23 +73,27 @@ pub(crate) fn extract_struct_from_function_signature(
7273
"Extract struct from signature of a function",
7374
target,
7475
|builder| {
76+
// TODO: update calls to the function
7577
let fn_ast = builder.make_mut(fn_ast);
78+
let params = builder.make_mut(params);
7679
tracing::info!("extract_struct_from_function_signature: starting edit");
7780
builder.edit_file(ctx.vfs_file_id());
7881
tracing::info!("extract_struct_from_function_signature: editing main file");
7982

8083
let generic_params = fn_ast
8184
.generic_param_list()
82-
.and_then(|known_generics| extract_generic_params(&known_generics, &field_list));
85+
.and_then(|known_generics| extract_generic_params(&known_generics, &field_list));
8386
tracing::info!("extract_struct_from_function_signature: collecting generics");
8487
let generics = generic_params.as_ref().map(|generics| generics.clone_for_update());
8588

8689
// resolve GenericArg in field_list to actual type
87-
// we are getting a query error from salsa, I think it is because the field list is
88-
// constructed in new generation, so maybe do the resolving while its still param list
89-
// and then convert it into record list after
90+
// we would get a query error from salsa, if we would use the field_list
91+
// I think it is because the field list is
92+
// constructed in new generation.
93+
// So I do the resolving while its still param list
94+
// and then apply it into record list after
9095
let field_list = if let Some((target_scope, source_scope)) =
91-
ctx.sema.scope(fn_ast.syntax()).zip(ctx.sema.scope(field_list.syntax()))
96+
ctx.sema.scope(fn_ast.syntax()).zip(ctx.sema.scope(params.syntax()))
9297
{
9398
let field_list = field_list.reset_indent();
9499
let field_list =
@@ -118,10 +123,44 @@ pub(crate) fn extract_struct_from_function_signature(
118123
],
119124
);
120125
tracing::info!("extract_struct_from_function_signature: inserting struct {def}");
126+
update_function(name, &fn_ast, generic_params.map(|g| g.clone_for_update()));
121127
},
122128
)
123129
}
124130

131+
fn update_function(
132+
name: ast::Name,
133+
fn_ast: &ast::Fn,
134+
generics: Option<ast::GenericParamList>,
135+
) -> Option<()> {
136+
let generic_args = generics
137+
.filter(|generics| generics.generic_params().count() > 0)
138+
.map(|generics| generics.to_generic_args());
139+
// FIXME: replace with a `ast::make` constructor
140+
let ty = match generic_args {
141+
Some(generic_args) => make::ty(&format!("{name}{generic_args}")),
142+
None => make::ty(&name.text()),
143+
};
144+
145+
let param = make::param(
146+
// TODO: do we want to destructure the struct
147+
ast::Pat::IdentPat(make::ident_pat(
148+
false,
149+
fn_ast.param_list()?.params().any(|p| {
150+
p.pat()
151+
.is_some_and(|p| matches!(p, ast::Pat::IdentPat(p) if p.mut_token().is_some()))
152+
}),
153+
name,
154+
)),
155+
ty,
156+
);
157+
// TODO: will eventually need to handle self to
158+
let param_list = make::param_list(None, std::iter::once(param)).clone_for_update();
159+
ted::replace(fn_ast.param_list()?.syntax(), param_list.syntax());
160+
// TODO: update uses of parameters in function, if we do not destructure
161+
Some(())
162+
}
163+
125164
fn pat_to_name(pat: ast::Pat) -> Option<ast::Name> {
126165
match pat {
127166
ast::Pat::IdentPat(ident_pat) => ident_pat.name(),

0 commit comments

Comments
 (0)