Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: import trait if needed for unqualify_method_call assist #15780

Merged
merged 2 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
45 changes: 44 additions & 1 deletion crates/ide-assists/src/handlers/unqualify_method_call.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use ide_db::imports::insert_use::ImportScope;
use syntax::{
ast::{self, make, AstNode, HasArgList},
TextRange,
Expand All @@ -17,6 +18,8 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
// ```
// ->
// ```
// use std::ops::Add;
//
// fn main() {
// 1.add(2);
// }
Expand All @@ -38,7 +41,7 @@ pub(crate) fn unqualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>)
let first_arg = args_iter.next()?;
let second_arg = args_iter.next();

_ = path.qualifier()?;
let qualifier = path.qualifier()?;
let method_name = path.segment()?.name_ref()?;

let res = ctx.sema.resolve_path(&path)?;
Expand Down Expand Up @@ -76,10 +79,44 @@ pub(crate) fn unqualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>)
edit.insert(close, ")");
}
edit.replace(replace_comma, format!(".{method_name}("));
add_import(qualifier, ctx, edit);
},
)
}

fn add_import(
qualifier: ast::Path,
ctx: &AssistContext<'_>,
edit: &mut ide_db::source_change::SourceChangeBuilder,
) {
// for `<i32 as std::ops::Add>`
let path_type =
qualifier.segment().unwrap().syntax().children().filter_map(ast::PathType::cast).last();
Young-Flash marked this conversation as resolved.
Show resolved Hide resolved
let import = match path_type {
Some(it) => it.path().unwrap(),
None => qualifier,
};

// in case for `<_>`
if import.coloncolon_token().is_none() {
return;
}

let scope = ide_db::imports::insert_use::ImportScope::find_insert_use_container(
import.syntax(),
&ctx.sema,
);

if let Some(scope) = scope {
let scope = match scope {
ImportScope::File(it) => ImportScope::File(edit.make_mut(it)),
ImportScope::Module(it) => ImportScope::Module(edit.make_mut(it)),
ImportScope::Block(it) => ImportScope::Block(edit.make_mut(it)),
};
ide_db::imports::insert_use::insert_use(&scope, import, &ctx.config.insert_use);
}
}

fn needs_parens_as_receiver(expr: &ast::Expr) -> bool {
// Make `(expr).dummy()`
let dummy_call = make::expr_method_call(
Expand Down Expand Up @@ -127,6 +164,8 @@ fn f() { S.f(S); }"#,
//- minicore: add
fn f() { <u32 as core::ops::Add>::$0add(2, 2); }"#,
r#"
use core::ops::Add;

fn f() { 2.add(2); }"#,
);

Expand All @@ -136,6 +175,8 @@ fn f() { 2.add(2); }"#,
//- minicore: add
fn f() { core::ops::Add::$0add(2, 2); }"#,
r#"
use core::ops::Add;

fn f() { 2.add(2); }"#,
);

Expand Down Expand Up @@ -179,6 +220,8 @@ impl core::ops::Deref for S {
}
fn f() { core::ops::Deref::$0deref(&S); }"#,
r#"
use core::ops::Deref;

struct S;
impl core::ops::Deref for S {
type Target = S;
Expand Down
2 changes: 2 additions & 0 deletions crates/ide-assists/src/tests/generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2948,6 +2948,8 @@ fn main() {
mod std { pub mod ops { pub trait Add { fn add(self, _: Self) {} } impl Add for i32 {} } }
"#####,
r#####"
use std::ops::Add;

fn main() {
1.add(2);
}
Expand Down