1+ use ide_db:: imports:: insert_use:: ImportScope ;
12use syntax:: {
23 ast:: { self , make, AstNode , HasArgList } ,
34 TextRange ,
@@ -17,6 +18,8 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
1718// ```
1819// ->
1920// ```
21+ // use std::ops::Add;
22+ //
2023// fn main() {
2124// 1.add(2);
2225// }
@@ -38,7 +41,7 @@ pub(crate) fn unqualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>)
3841 let first_arg = args_iter. next ( ) ?;
3942 let second_arg = args_iter. next ( ) ;
4043
41- _ = path. qualifier ( ) ?;
44+ let qualifier = path. qualifier ( ) ?;
4245 let method_name = path. segment ( ) ?. name_ref ( ) ?;
4346
4447 let res = ctx. sema . resolve_path ( & path) ?;
@@ -76,10 +79,51 @@ pub(crate) fn unqualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>)
7679 edit. insert ( close, ")" ) ;
7780 }
7881 edit. replace ( replace_comma, format ! ( ".{method_name}(" ) ) ;
82+ add_import ( qualifier, ctx, edit) ;
7983 } ,
8084 )
8185}
8286
87+ fn add_import (
88+ qualifier : ast:: Path ,
89+ ctx : & AssistContext < ' _ > ,
90+ edit : & mut ide_db:: source_change:: SourceChangeBuilder ,
91+ ) {
92+ if let Some ( path_segment) = qualifier. segment ( ) {
93+ // for `<i32 as std::ops::Add>`
94+ let path_type = path_segment. syntax ( ) . children ( ) . filter_map ( ast:: PathType :: cast) . last ( ) ;
95+ let import = match path_type {
96+ Some ( it) => {
97+ if let Some ( path) = it. path ( ) {
98+ path
99+ } else {
100+ return ;
101+ }
102+ }
103+ None => qualifier,
104+ } ;
105+
106+ // in case for `<_>`
107+ if import. coloncolon_token ( ) . is_none ( ) {
108+ return ;
109+ }
110+
111+ let scope = ide_db:: imports:: insert_use:: ImportScope :: find_insert_use_container (
112+ import. syntax ( ) ,
113+ & ctx. sema ,
114+ ) ;
115+
116+ if let Some ( scope) = scope {
117+ let scope = match scope {
118+ ImportScope :: File ( it) => ImportScope :: File ( edit. make_mut ( it) ) ,
119+ ImportScope :: Module ( it) => ImportScope :: Module ( edit. make_mut ( it) ) ,
120+ ImportScope :: Block ( it) => ImportScope :: Block ( edit. make_mut ( it) ) ,
121+ } ;
122+ ide_db:: imports:: insert_use:: insert_use ( & scope, import, & ctx. config . insert_use ) ;
123+ }
124+ }
125+ }
126+
83127fn needs_parens_as_receiver ( expr : & ast:: Expr ) -> bool {
84128 // Make `(expr).dummy()`
85129 let dummy_call = make:: expr_method_call (
@@ -127,6 +171,8 @@ fn f() { S.f(S); }"#,
127171//- minicore: add
128172fn f() { <u32 as core::ops::Add>::$0add(2, 2); }"# ,
129173 r#"
174+ use core::ops::Add;
175+
130176fn f() { 2.add(2); }"# ,
131177 ) ;
132178
@@ -136,6 +182,8 @@ fn f() { 2.add(2); }"#,
136182//- minicore: add
137183fn f() { core::ops::Add::$0add(2, 2); }"# ,
138184 r#"
185+ use core::ops::Add;
186+
139187fn f() { 2.add(2); }"# ,
140188 ) ;
141189
@@ -179,6 +227,8 @@ impl core::ops::Deref for S {
179227}
180228fn f() { core::ops::Deref::$0deref(&S); }"# ,
181229 r#"
230+ use core::ops::Deref;
231+
182232struct S;
183233impl core::ops::Deref for S {
184234 type Target = S;
0 commit comments