| 
 | 1 | +use hir::AsAssocItem;  | 
1 | 2 | use syntax::{  | 
2 | 3 |     TextRange,  | 
3 | 4 |     ast::{self, AstNode, HasArgList, prec::ExprPrecedence},  | 
@@ -43,6 +44,7 @@ pub(crate) fn unqualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>)  | 
43 | 44 |     let qualifier = path.qualifier()?;  | 
44 | 45 |     let method_name = path.segment()?.name_ref()?;  | 
45 | 46 | 
 
  | 
 | 47 | +    let scope = ctx.sema.scope(path.syntax())?;  | 
46 | 48 |     let res = ctx.sema.resolve_path(&path)?;  | 
47 | 49 |     let hir::PathResolution::Def(hir::ModuleDef::Function(fun)) = res else { return None };  | 
48 | 50 |     if !fun.has_self_param(ctx.sema.db) {  | 
@@ -78,7 +80,14 @@ pub(crate) fn unqualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>)  | 
78 | 80 |                 edit.insert(close, ")");  | 
79 | 81 |             }  | 
80 | 82 |             edit.replace(replace_comma, format!(".{method_name}("));  | 
81 |  | -            add_import(qualifier, ctx, edit);  | 
 | 83 | + | 
 | 84 | +            if let Some(fun) = fun.as_assoc_item(ctx.db())  | 
 | 85 | +                && let Some(trait_) = fun.container_or_implemented_trait(ctx.db())  | 
 | 86 | +                && !scope.can_use_trait_methods(trait_)  | 
 | 87 | +            {  | 
 | 88 | +                // Only add an import for trait methods that are not already imported.  | 
 | 89 | +                add_import(qualifier, ctx, edit);  | 
 | 90 | +            }  | 
82 | 91 |         },  | 
83 | 92 |     )  | 
84 | 93 | }  | 
@@ -235,4 +244,111 @@ impl S { fn assoc(S: S, S: S) {} }  | 
235 | 244 | fn f() { S::assoc$0(S, S); }"#,  | 
236 | 245 |         );  | 
237 | 246 |     }  | 
 | 247 | + | 
 | 248 | +    #[test]  | 
 | 249 | +    fn inherent_method() {  | 
 | 250 | +        check_assist(  | 
 | 251 | +            unqualify_method_call,  | 
 | 252 | +            r#"  | 
 | 253 | +mod foo {  | 
 | 254 | +    pub struct Bar;  | 
 | 255 | +    impl Bar {  | 
 | 256 | +        pub fn bar(self) {}  | 
 | 257 | +    }  | 
 | 258 | +}  | 
 | 259 | +
  | 
 | 260 | +fn baz() {  | 
 | 261 | +    foo::Bar::b$0ar(foo::Bar);  | 
 | 262 | +}  | 
 | 263 | +        "#,  | 
 | 264 | +            r#"  | 
 | 265 | +mod foo {  | 
 | 266 | +    pub struct Bar;  | 
 | 267 | +    impl Bar {  | 
 | 268 | +        pub fn bar(self) {}  | 
 | 269 | +    }  | 
 | 270 | +}  | 
 | 271 | +
  | 
 | 272 | +fn baz() {  | 
 | 273 | +    foo::Bar.bar();  | 
 | 274 | +}  | 
 | 275 | +        "#,  | 
 | 276 | +        );  | 
 | 277 | +    }  | 
 | 278 | + | 
 | 279 | +    #[test]  | 
 | 280 | +    fn trait_method_in_impl() {  | 
 | 281 | +        check_assist(  | 
 | 282 | +            unqualify_method_call,  | 
 | 283 | +            r#"  | 
 | 284 | +mod foo {  | 
 | 285 | +    pub trait Bar {  | 
 | 286 | +        pub fn bar(self) {}  | 
 | 287 | +    }  | 
 | 288 | +}  | 
 | 289 | +
  | 
 | 290 | +struct Baz;  | 
 | 291 | +impl foo::Bar for Baz {  | 
 | 292 | +    fn bar(self) {  | 
 | 293 | +        foo::Bar::b$0ar(Baz);  | 
 | 294 | +    }  | 
 | 295 | +}  | 
 | 296 | +        "#,  | 
 | 297 | +            r#"  | 
 | 298 | +mod foo {  | 
 | 299 | +    pub trait Bar {  | 
 | 300 | +        pub fn bar(self) {}  | 
 | 301 | +    }  | 
 | 302 | +}  | 
 | 303 | +
  | 
 | 304 | +struct Baz;  | 
 | 305 | +impl foo::Bar for Baz {  | 
 | 306 | +    fn bar(self) {  | 
 | 307 | +        Baz.bar();  | 
 | 308 | +    }  | 
 | 309 | +}  | 
 | 310 | +        "#,  | 
 | 311 | +        );  | 
 | 312 | +    }  | 
 | 313 | + | 
 | 314 | +    #[test]  | 
 | 315 | +    fn trait_method_already_imported() {  | 
 | 316 | +        check_assist(  | 
 | 317 | +            unqualify_method_call,  | 
 | 318 | +            r#"  | 
 | 319 | +mod foo {  | 
 | 320 | +    pub struct Foo;  | 
 | 321 | +    pub trait Bar {  | 
 | 322 | +        pub fn bar(self) {}  | 
 | 323 | +    }  | 
 | 324 | +    impl Bar for Foo {  | 
 | 325 | +        pub fn bar(self) {}  | 
 | 326 | +    }  | 
 | 327 | +}  | 
 | 328 | +
  | 
 | 329 | +use foo::Bar;  | 
 | 330 | +
  | 
 | 331 | +fn baz() {  | 
 | 332 | +    foo::Bar::b$0ar(foo::Foo);  | 
 | 333 | +}  | 
 | 334 | +        "#,  | 
 | 335 | +            r#"  | 
 | 336 | +mod foo {  | 
 | 337 | +    pub struct Foo;  | 
 | 338 | +    pub trait Bar {  | 
 | 339 | +        pub fn bar(self) {}  | 
 | 340 | +    }  | 
 | 341 | +    impl Bar for Foo {  | 
 | 342 | +        pub fn bar(self) {}  | 
 | 343 | +    }  | 
 | 344 | +}  | 
 | 345 | +
  | 
 | 346 | +use foo::Bar;  | 
 | 347 | +
  | 
 | 348 | +fn baz() {  | 
 | 349 | +    foo::Foo.bar();  | 
 | 350 | +}  | 
 | 351 | +        "#,  | 
 | 352 | +        );  | 
 | 353 | +    }  | 
238 | 354 | }  | 
0 commit comments