|
| 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