1
+ use hir:: TypeInfo ;
1
2
use stdx:: format_to;
2
3
use syntax:: {
3
4
ast:: { self , AstNode } ,
@@ -46,21 +47,24 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
46
47
. take_while ( |it| ctx. selection_trimmed ( ) . contains_range ( it. text_range ( ) ) )
47
48
. find_map ( valid_target_expr) ?;
48
49
49
- if let Some ( ty_info) = ctx. sema . type_of_expr ( & to_extract) {
50
- if ty_info. adjusted ( ) . is_unit ( ) {
51
- return None ;
52
- }
50
+ let ty = ctx. sema . type_of_expr ( & to_extract) . map ( TypeInfo :: adjusted) ;
51
+ if matches ! ( & ty, Some ( ty_info) if ty_info. is_unit( ) ) {
52
+ return None ;
53
53
}
54
54
55
- let reference_modifier = match get_receiver_type ( ctx, & to_extract) {
55
+ let parent = to_extract. syntax ( ) . parent ( ) . and_then ( ast:: Expr :: cast) ;
56
+ let needs_adjust = parent
57
+ . as_ref ( )
58
+ . map_or ( false , |it| matches ! ( it, ast:: Expr :: FieldExpr ( _) | ast:: Expr :: MethodCallExpr ( _) ) ) ;
59
+
60
+ let reference_modifier = match ty. filter ( |_| needs_adjust) {
56
61
Some ( receiver_type) if receiver_type. is_mutable_reference ( ) => "&mut " ,
57
62
Some ( receiver_type) if receiver_type. is_reference ( ) => "&" ,
58
63
_ => "" ,
59
64
} ;
60
65
61
- let parent_ref_expr = to_extract. syntax ( ) . parent ( ) . and_then ( ast:: RefExpr :: cast) ;
62
- let var_modifier = match parent_ref_expr {
63
- Some ( expr) if expr. mut_token ( ) . is_some ( ) => "mut " ,
66
+ let var_modifier = match parent {
67
+ Some ( ast:: Expr :: RefExpr ( expr) ) if expr. mut_token ( ) . is_some ( ) => "mut " ,
64
68
_ => "" ,
65
69
} ;
66
70
@@ -164,22 +168,6 @@ fn valid_target_expr(node: SyntaxNode) -> Option<ast::Expr> {
164
168
}
165
169
}
166
170
167
- fn get_receiver_type ( ctx : & AssistContext < ' _ > , expression : & ast:: Expr ) -> Option < hir:: Type > {
168
- let receiver = get_receiver ( expression. clone ( ) ) ?;
169
- Some ( ctx. sema . type_of_expr ( & receiver) ?. original ( ) )
170
- }
171
-
172
- /// In the expression `a.b.c.x()`, find `a`
173
- fn get_receiver ( expression : ast:: Expr ) -> Option < ast:: Expr > {
174
- match expression {
175
- ast:: Expr :: FieldExpr ( field) if field. expr ( ) . is_some ( ) => {
176
- let nested_expression = & field. expr ( ) ?;
177
- get_receiver ( nested_expression. to_owned ( ) )
178
- }
179
- _ => Some ( expression) ,
180
- }
181
- }
182
-
183
171
#[ derive( Debug ) ]
184
172
enum Anchor {
185
173
Before ( SyntaxNode ) ,
@@ -944,6 +932,11 @@ struct S {
944
932
vec: Vec<u8>
945
933
}
946
934
935
+ struct Vec<T>;
936
+ impl<T> Vec<T> {
937
+ fn push(&mut self, _:usize) {}
938
+ }
939
+
947
940
fn foo(s: &mut S) {
948
941
$0s.vec$0.push(0);
949
942
}"# ,
@@ -952,6 +945,11 @@ struct S {
952
945
vec: Vec<u8>
953
946
}
954
947
948
+ struct Vec<T>;
949
+ impl<T> Vec<T> {
950
+ fn push(&mut self, _:usize) {}
951
+ }
952
+
955
953
fn foo(s: &mut S) {
956
954
let $0vec = &mut s.vec;
957
955
vec.push(0);
@@ -973,6 +971,10 @@ struct X {
973
971
struct S {
974
972
vec: Vec<u8>
975
973
}
974
+ struct Vec<T>;
975
+ impl<T> Vec<T> {
976
+ fn push(&mut self, _:usize) {}
977
+ }
976
978
977
979
fn foo(f: &mut Y) {
978
980
$0f.field.field.vec$0.push(0);
@@ -987,6 +989,10 @@ struct X {
987
989
struct S {
988
990
vec: Vec<u8>
989
991
}
992
+ struct Vec<T>;
993
+ impl<T> Vec<T> {
994
+ fn push(&mut self, _:usize) {}
995
+ }
990
996
991
997
fn foo(f: &mut Y) {
992
998
let $0vec = &mut f.field.field.vec;
@@ -1123,7 +1129,7 @@ struct S {
1123
1129
}
1124
1130
1125
1131
fn foo(s: S) {
1126
- let $0x = s.sub;
1132
+ let $0x = & s.sub;
1127
1133
x.do_thing();
1128
1134
}"# ,
1129
1135
) ;
@@ -1189,7 +1195,7 @@ impl X {
1189
1195
1190
1196
fn foo() {
1191
1197
let local = &mut S::new();
1192
- let $0x = &mut local.sub;
1198
+ let $0x = &local.sub;
1193
1199
x.do_thing();
1194
1200
}"# ,
1195
1201
) ;
0 commit comments