Skip to content

Commit 3abcb4c

Browse files
committed
feat: extract_struct_from_function_signature
fixed compilation all most done replace replacing ted
1 parent 7676177 commit 3abcb4c

File tree

1 file changed

+48
-44
lines changed

1 file changed

+48
-44
lines changed

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

Lines changed: 48 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use syntax::{
1919
AstNode, Edition, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, T,
2020
algo::find_node_at_range,
2121
ast::{
22-
self, HasArgList, HasGenericParams, HasName, HasVisibility,
22+
self, HasArgList, HasAttrs, HasGenericParams, HasName, HasVisibility,
2323
edit::{AstNodeEdit, IndentLevel},
2424
make,
2525
syntax_factory::SyntaxFactory,
@@ -38,7 +38,7 @@ use crate::{AssistContext, Assists};
3838
// ```
3939
// ->
4040
// ```
41-
// struct FooStruct{ bar: u32, baz: u32 }
41+
// struct FooStruct { bar: u32, baz: u32 }
4242
//
4343
// fn foo(FooStruct { bar, baz, .. }: FooStruct) { ... }
4444
// ```
@@ -158,7 +158,6 @@ pub(crate) fn extract_struct_from_function_signature(
158158
let field_list = if let Some((target_scope, source_scope)) =
159159
ctx.sema.scope(func.syntax()).zip(ctx.sema.scope(param_list.syntax()))
160160
{
161-
let field_list = field_list.reset_indent();
162161
let field_list =
163162
PathTransform::generic_transformation(&target_scope, &source_scope)
164163
.apply(field_list.syntax());
@@ -171,9 +170,9 @@ pub(crate) fn extract_struct_from_function_signature(
171170
} else {
172171
field_list
173172
};
174-
field_list.fields().filter_map(|f|f.ty()).try_for_each(|t|generate_new_lifetimes(&mut editor, &t, &mut generics));
173+
field_list.fields().filter_map(|f|f.ty()).try_for_each(|t|generate_new_lifetimes(builder, &t, &mut generics, ctx.vfs_file_id()));
175174
tracing::info!("extract_struct_from_function_signature: collecting fields");
176-
let def = create_struct_def(& make, name.clone(), &func, &used_param_list, &field_list, generics);
175+
let def = create_struct_def( builder, name.clone(), &func, &used_param_list, &field_list, generics, ctx.vfs_file_id());
177176
tracing::info!("extract_struct_from_function_signature: creating struct");
178177
let def = def.indent(indent);
179178
editor.insert_all(
@@ -272,49 +271,47 @@ fn pat_to_name(pat: ast::Pat) -> Option<ast::Name> {
272271
}
273272
}
274273
fn create_struct_def(
275-
editor: &SyntaxFactory,
274+
builder: &mut SourceChangeBuilder,
276275
name: ast::Name,
277276
func: &ast::Fn,
278277
param_ast: &[ast::Param],
279278
field_list: &ast::RecordFieldList,
280279
generics: Option<ast::GenericParamList>,
280+
_file_id: FileId,
281281
) -> ast::Struct {
282282
let fn_vis = func.visibility();
283283

284284
// if we do not expleictly copy over comments/attribures they just get lost
285285
// TODO: what about comments/attributes in between parameters
286-
// param_ast.iter().zip(field_list.fields()).for_each(|(param, field)| {
287-
// editor.attr_inner(meta)
288-
// let elements = take_all_comments(param.clone());
289-
// editor.insert_all(Position::first_child_of(field.syntax()), elements);
290-
// editor.insert_all(
291-
// Position::first_child_of(field.syntax()),
292-
// param
293-
// .attrs()
294-
// .flat_map(|it| [it.syntax().clone().into(), make::tokens::single_newline().into()])
295-
// .collect(),
296-
// );
297-
// });
286+
param_ast.iter().zip(field_list.fields()).for_each(|(param, field)| {
287+
let mut editor = builder.make_editor(field.syntax());
288+
let elements = take_all_comments(param.clone());
289+
editor.insert_all(Position::first_child_of(field.syntax()), elements);
290+
editor.insert_all(
291+
Position::first_child_of(field.syntax()),
292+
param
293+
.attrs()
294+
.flat_map(|it| [it.syntax().clone().into(), make::tokens::single_newline().into()])
295+
.collect(),
296+
);
297+
// this panics
298+
// builder.add_file_edits(file_id, editor);
299+
});
298300
let field_list = field_list.indent(IndentLevel::single());
299301

300302
make::struct_(fn_vis, name, generics, field_list.into()).clone_for_update()
301303
}
302-
// Note: this also detaches whitespace after comments,
303-
// since `SyntaxNode::splice_children` (and by extension `ted::insert_all_raw`)
304-
// detaches nodes. If we only took the comments, we'd leave behind the old whitespace.
305304
fn take_all_comments(node: impl ast::AstNode) -> Vec<SyntaxElement> {
306305
let mut remove_next_ws = false;
307306
node.syntax()
308307
.children_with_tokens()
309308
.filter_map(move |child| match child.kind() {
310309
SyntaxKind::COMMENT => {
311310
remove_next_ws = true;
312-
child.detach();
313311
Some(child)
314312
}
315313
SyntaxKind::WHITESPACE if remove_next_ws => {
316314
remove_next_ws = false;
317-
child.detach();
318315
Some(make::tokens::single_newline().into())
319316
}
320317
_ => {
@@ -367,30 +364,38 @@ fn contains_impl_trait(ty: &ast::Type) -> bool {
367364
ty.syntax().descendants().any(|ty| ty.kind() == ast::ImplTraitType::kind())
368365
}
369366
fn generate_new_lifetimes(
370-
editor: &mut SyntaxEditor,
367+
builder: &mut SourceChangeBuilder,
371368
ty: &ast::Type,
372369
existing_type_param_list: &mut Option<ast::GenericParamList>,
370+
_file_id: FileId,
373371
) -> Option<()> {
374372
for token in ty.syntax().descendants() {
375373
// we do not have to worry about for<'a> because we are only looking at '_ or &Type
376374
// if you have an unbound lifetime thats on you
377375
if let Some(lt) = ast::Lifetime::cast(token.clone())
378376
&& lt.text() == "'_"
379377
{
378+
let mut editor = builder.make_editor(lt.syntax());
380379
let new_lt = generate_unique_lifetime_param_name(existing_type_param_list)?;
380+
editor.replace(lt.syntax(), new_lt.syntax());
381381
existing_type_param_list
382382
.get_or_insert(make::generic_param_list(std::iter::empty()).clone_for_update())
383+
// TODO: used TED
383384
.add_generic_param(make::lifetime_param(new_lt.clone()).clone_for_update().into());
384-
385-
// editor.replace(lt.syntax(), new_lt.clone_for_update().syntax());
385+
// this panics
386+
// builder.add_file_edits(file_id, editor);
386387
} else if let Some(r) = ast::RefType::cast(token.clone())
387388
&& r.lifetime().is_none()
388389
{
390+
let mut editor = builder.make_editor(r.syntax());
389391
let new_lt = generate_unique_lifetime_param_name(existing_type_param_list)?;
392+
editor.insert(Position::after(r.amp_token()?), new_lt.syntax());
390393
existing_type_param_list
391394
.get_or_insert(make::generic_param_list(std::iter::empty()).clone_for_update())
395+
// TODO: used TED
392396
.add_generic_param(make::lifetime_param(new_lt.clone()).clone_for_update().into());
393-
// editor.insert(Position::after(r.amp_token()?), new_lt.clone_for_update().syntax());
397+
// this panics
398+
// builder.add_file_edits(file_id, editor);
394399
}
395400
// TODO: nominal types that have only lifetimes
396401
// struct Bar<'a, 'b> { f: &'a &'b i32 }
@@ -488,7 +493,7 @@ fn process_references(
488493
ctx.sema.db,
489494
*function_module_def,
490495
ctx.config.insert_use.prefix_kind,
491-
ctx.config.import_path_config(),
496+
ctx.config.find_path_confg(ctx.sema.is_nightly(module.krate())),
492497
);
493498
if let Some(mut mod_path) = mod_path {
494499
mod_path.pop_segment();
@@ -532,7 +537,6 @@ fn apply_references(
532537
name: ast::Name,
533538
file_id: impl Into<FileId>,
534539
) -> Option<()> {
535-
let make = SyntaxFactory::with_mappings();
536540
let mut editor = builder.make_editor(call.syntax());
537541
if let Some((scope, path)) = import {
538542
let scope = builder.make_import_scope_mut(scope);
@@ -642,7 +646,7 @@ fn one($0x: u8, y: u32) {}
642646
fn foo($0bar: i32$0, baz: i32) {}
643647
"#,
644648
r#"
645-
struct FooStruct{ bar: i32 }
649+
struct FooStruct { bar: i32 }
646650
647651
fn foo(FooStruct { bar, .. }: FooStruct, baz: i32) {}
648652
"#,
@@ -656,7 +660,7 @@ fn foo(FooStruct { bar, .. }: FooStruct, baz: i32) {}
656660
fn foo($0bar: i32, baz: i32$0) {}
657661
"#,
658662
r#"
659-
struct FooStruct{ bar: i32, baz: i32 }
663+
struct FooStruct { bar: i32, baz: i32 }
660664
661665
fn foo(FooStruct { bar, baz, .. }: FooStruct) {}
662666
"#,
@@ -674,7 +678,7 @@ fn main() {
674678
}
675679
"#,
676680
r#"
677-
struct FooStruct{ bar: i32, baz: i32 }
681+
struct FooStruct { bar: i32, baz: i32 }
678682
679683
fn foo(FooStruct { bar, baz, .. }: FooStruct) {}
680684
@@ -705,15 +709,15 @@ mod b {
705709
"#,
706710
r#"
707711
mod a {
708-
pub struct FooStruct{ pub bar: i32 }
712+
pub struct FooStruct { pub bar: i32 }
709713
710714
pub fn foo(FooStruct { bar, .. }: FooStruct, baz: i32) {
711715
foo(FooStruct { bar: 1 }, 2)
712716
}
713717
}
714718
715719
mod b {
716-
use crate::a::{foo, FooStruct};
720+
use crate::a::{FooStruct, foo};
717721
718722
fn main() {
719723
foo(FooStruct { bar: 1 }, 2)
@@ -734,7 +738,7 @@ mod b {
734738
}
735739
"#,
736740
r#"
737-
struct FooStruct{ bar: i32 }
741+
struct FooStruct { bar: i32 }
738742
739743
fn foo(FooStruct { bar, .. }: FooStruct, baz: i32) {}
740744
@@ -753,7 +757,7 @@ mod b {
753757
fn foo<'a, A>($0bar: &'a A$0, baz: i32) {}
754758
"#,
755759
r#"
756-
struct FooStruct<'a, A>{ bar: &'a A }
760+
struct FooStruct<'a, A> { bar: &'a A }
757761
758762
fn foo<'a, A>(FooStruct { bar, .. }: FooStruct<'a, A>, baz: i32) {}
759763
"#,
@@ -769,7 +773,7 @@ fn foo<'a, A>($0bar: &'a A$0, baz: i32) {
769773
}
770774
"#,
771775
r#"
772-
struct FooStruct<'a, A>{ bar: &'a A }
776+
struct FooStruct<'a, A> { bar: &'a A }
773777
774778
fn foo<'a, A>(FooStruct { bar, .. }: FooStruct<'a, A>, baz: i32) {
775779
foo(FooStruct { bar: 1 }, 2)
@@ -786,7 +790,7 @@ fn foo<'a, A>(FooStruct { bar, .. }: FooStruct<'a, A>, baz: i32) {
786790
fn foo($0bar: &'_ i32$0, baz: i32) {}
787791
"#,
788792
r#"
789-
struct FooStruct<'a>{ bar: &'a i32 }
793+
struct FooStruct<'a> { bar: &'a i32 }
790794
791795
fn foo(FooStruct { bar, .. }: FooStruct<'_>, baz: i32) {}
792796
"#,
@@ -801,7 +805,7 @@ fn foo(FooStruct { bar, .. }: FooStruct<'_>, baz: i32) {}
801805
fn foo($0bar: &i32$0, baz: i32) {}
802806
"#,
803807
r#"
804-
struct FooStruct<'a>{ bar: &'a i32 }
808+
struct FooStruct<'a> { bar: &'a i32 }
805809
806810
fn foo(FooStruct { bar, .. }: FooStruct<'_>, baz: i32) {}
807811
"#,
@@ -815,7 +819,7 @@ fn foo(FooStruct { bar, .. }: FooStruct<'_>, baz: i32) {}
815819
fn foo<'a>($0bar: &'_ &'a i32$0, baz: i32) {}
816820
"#,
817821
r#"
818-
struct FooStruct<'a, 'b>{ bar: &'b &'a i32 }
822+
struct FooStruct<'a, 'b> { bar: &'b &'a i32 }
819823
820824
fn foo<'a>(FooStruct { bar, .. }: FooStruct<'a, '_>, baz: i32) {}
821825
"#,
@@ -833,7 +837,7 @@ fn foo<'a>($0bar: &'_ &'a i32$0, baz: i32) {
833837
}
834838
"#,
835839
r#"
836-
struct FooStruct<'a, 'b>{ bar: &'b &'a i32 }
840+
struct FooStruct<'a, 'b> { bar: &'b &'a i32 }
837841
838842
fn foo<'a>(FooStruct { bar, .. }: FooStruct<'a, '_>, baz: i32) {
839843
foo(FooStruct { bar: bar }, baz)
@@ -864,7 +868,7 @@ fn bar() {
864868
"#,
865869
r#"
866870
struct Foo
867-
struct FooStruct{ j: i32, i: i32 }
871+
struct FooStruct { j: i32, i: i32 }
868872
869873
impl Foo {
870874
fn foo(&self, FooStruct { j, i, .. }: FooStruct, z:i32) { }
@@ -895,7 +899,7 @@ fn bar() {
895899
"#,
896900
r#"
897901
struct Foo
898-
struct FooStruct{ j: i32, i: i32 }
902+
struct FooStruct { j: i32, i: i32 }
899903
900904
impl Foo {
901905
fn foo(&self, FooStruct { j, i, .. }: FooStruct, z:i32) { }
@@ -922,7 +926,7 @@ fn foo(
922926
) { }
923927
"#,
924928
r#"
925-
struct FooStruct{ #[foo]
929+
struct FooStruct { #[foo]
926930
// gag
927931
f: i32 }
928932

0 commit comments

Comments
 (0)