1
1
use hir:: { Function , ModuleDef } ;
2
2
use ide_db:: { RootDatabase , assists:: AssistId , path_transform:: PathTransform } ;
3
3
use itertools:: Itertools ;
4
- use stdx:: to_camel_case;
4
+ use stdx:: { to_camel_case, to_lower_snake_case } ;
5
5
use syntax:: {
6
6
AstNode , SyntaxElement , SyntaxKind , SyntaxNode , T ,
7
7
ast:: {
@@ -18,16 +18,13 @@ use crate::{AssistContext, Assists};
18
18
// Extracts a struct (part) of the signature of a function.
19
19
//
20
20
// ```
21
- // fn foo(bar : u32, baz: u32) { ... }
21
+ // fn foo($0bar : u32, baz: u32) { ... }
22
22
// ```
23
23
// ->
24
24
// ```
25
- // struct FooStruct {
26
- // bar: u32,
27
- // baz: u32,
28
- // }
25
+ // struct FooStruct{ bar: u32, baz: u32 }
29
26
//
30
- // fn foo(FooStruct) { ... }
27
+ // fn foo(foo_struct: FooStruct) { ... }
31
28
// ```
32
29
33
30
pub ( crate ) fn extract_struct_from_function_signature (
@@ -42,9 +39,10 @@ pub(crate) fn extract_struct_from_function_signature(
42
39
// go through the fn, the text_range is the whole function.
43
40
let params_list = ctx. find_node_at_offset :: < ast:: ParamList > ( ) ?;
44
41
let fn_name = fn_ast. name ( ) ?;
42
+ let name = make:: name ( & format ! ( "{}Struct" , to_camel_case( fn_name. text_non_mutable( ) ) ) ) ;
45
43
46
44
let fn_hir = ctx. sema . to_def ( & fn_ast) ?;
47
- if existing_definition ( ctx. db ( ) , & fn_name , & fn_hir) {
45
+ if existing_definition ( ctx. db ( ) , & name , & fn_hir) {
48
46
cov_mark:: hit!( test_extract_function_signature_not_applicable_if_struct_exists) ;
49
47
return None ;
50
48
}
@@ -69,16 +67,16 @@ pub(crate) fn extract_struct_from_function_signature(
69
67
} )
70
68
. collect :: < Option < Vec < _ > > > ( ) ?,
71
69
) ;
72
- let name = make:: name ( & format ! ( "{}Struct" , to_camel_case( fn_name. text_non_mutable( ) ) ) ) ;
73
70
acc. add (
74
71
AssistId :: refactor_rewrite ( "extract_struct_from_function_signature" ) ,
75
72
"Extract struct from signature of a function" ,
76
73
target,
77
74
|builder| {
78
75
// TODO: update calls to the function
79
- let fn_ast = builder. make_mut ( fn_ast) ;
80
76
tracing:: info!( "extract_struct_from_function_signature: starting edit" ) ;
81
77
builder. edit_file ( ctx. vfs_file_id ( ) ) ;
78
+ // this has to be after the edit_file (order matters)
79
+ let fn_ast = builder. make_mut ( fn_ast) ;
82
80
tracing:: info!( "extract_struct_from_function_signature: editing main file" ) ;
83
81
84
82
let generic_params = fn_ast
@@ -154,7 +152,8 @@ fn update_function(
154
152
p. pat ( )
155
153
. is_some_and ( |p| matches ! ( p, ast:: Pat :: IdentPat ( p) if p. mut_token( ) . is_some( ) ) )
156
154
} ) ,
157
- name,
155
+ // TODO: maybe make a method that maps over a name's text
156
+ make:: name ( & to_lower_snake_case ( name. text_non_mutable ( ) ) ) ,
158
157
) ) ,
159
158
ty,
160
159
) ;
@@ -327,3 +326,21 @@ fn existing_definition(db: &RootDatabase, variant_name: &ast::Name, variant: &Fu
327
326
} )
328
327
. any ( |( name, _) | name. as_str ( ) == variant_name. text ( ) . trim_start_matches ( "r#" ) )
329
328
}
329
+
330
+ #[ cfg( test) ]
331
+ mod tests {
332
+ use super :: * ;
333
+ use crate :: tests:: check_assist_not_applicable;
334
+
335
+ #[ test]
336
+ fn test_extract_function_signature_not_applicable_if_struct_exists ( ) {
337
+ cov_mark:: check!( test_extract_function_signature_not_applicable_if_struct_exists) ;
338
+ check_assist_not_applicable (
339
+ extract_struct_from_function_signature,
340
+ r#"
341
+ struct OneStruct;
342
+ fn one($0x: u8, y: u32) {}
343
+ "# ,
344
+ ) ;
345
+ }
346
+ }
0 commit comments