mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 21:05:02 +00:00
fix: Fix receiver adjustments for extract_variable assist
This commit is contained in:
parent
fa3db447d7
commit
72d47144e8
2 changed files with 32 additions and 27 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
use hir::TypeInfo;
|
||||||
use stdx::format_to;
|
use stdx::format_to;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, AstNode},
|
ast::{self, AstNode},
|
||||||
|
@ -46,21 +47,24 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
|
||||||
.take_while(|it| ctx.selection_trimmed().contains_range(it.text_range()))
|
.take_while(|it| ctx.selection_trimmed().contains_range(it.text_range()))
|
||||||
.find_map(valid_target_expr)?;
|
.find_map(valid_target_expr)?;
|
||||||
|
|
||||||
if let Some(ty_info) = ctx.sema.type_of_expr(&to_extract) {
|
let ty = ctx.sema.type_of_expr(&to_extract).map(TypeInfo::adjusted);
|
||||||
if ty_info.adjusted().is_unit() {
|
if matches!(&ty, Some(ty_info) if ty_info.is_unit()) {
|
||||||
return None;
|
return None;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let reference_modifier = match get_receiver_type(ctx, &to_extract) {
|
let parent = to_extract.syntax().parent().and_then(ast::Expr::cast);
|
||||||
|
let needs_adjust = parent
|
||||||
|
.as_ref()
|
||||||
|
.map_or(false, |it| matches!(it, ast::Expr::FieldExpr(_) | ast::Expr::MethodCallExpr(_)));
|
||||||
|
|
||||||
|
let reference_modifier = match ty.filter(|_| needs_adjust) {
|
||||||
Some(receiver_type) if receiver_type.is_mutable_reference() => "&mut ",
|
Some(receiver_type) if receiver_type.is_mutable_reference() => "&mut ",
|
||||||
Some(receiver_type) if receiver_type.is_reference() => "&",
|
Some(receiver_type) if receiver_type.is_reference() => "&",
|
||||||
_ => "",
|
_ => "",
|
||||||
};
|
};
|
||||||
|
|
||||||
let parent_ref_expr = to_extract.syntax().parent().and_then(ast::RefExpr::cast);
|
let var_modifier = match parent {
|
||||||
let var_modifier = match parent_ref_expr {
|
Some(ast::Expr::RefExpr(expr)) if expr.mut_token().is_some() => "mut ",
|
||||||
Some(expr) if expr.mut_token().is_some() => "mut ",
|
|
||||||
_ => "",
|
_ => "",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -164,22 +168,6 @@ fn valid_target_expr(node: SyntaxNode) -> Option<ast::Expr> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_receiver_type(ctx: &AssistContext<'_>, expression: &ast::Expr) -> Option<hir::Type> {
|
|
||||||
let receiver = get_receiver(expression.clone())?;
|
|
||||||
Some(ctx.sema.type_of_expr(&receiver)?.original())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// In the expression `a.b.c.x()`, find `a`
|
|
||||||
fn get_receiver(expression: ast::Expr) -> Option<ast::Expr> {
|
|
||||||
match expression {
|
|
||||||
ast::Expr::FieldExpr(field) if field.expr().is_some() => {
|
|
||||||
let nested_expression = &field.expr()?;
|
|
||||||
get_receiver(nested_expression.to_owned())
|
|
||||||
}
|
|
||||||
_ => Some(expression),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Anchor {
|
enum Anchor {
|
||||||
Before(SyntaxNode),
|
Before(SyntaxNode),
|
||||||
|
@ -944,6 +932,11 @@ struct S {
|
||||||
vec: Vec<u8>
|
vec: Vec<u8>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Vec<T>;
|
||||||
|
impl<T> Vec<T> {
|
||||||
|
fn push(&mut self, _:usize) {}
|
||||||
|
}
|
||||||
|
|
||||||
fn foo(s: &mut S) {
|
fn foo(s: &mut S) {
|
||||||
$0s.vec$0.push(0);
|
$0s.vec$0.push(0);
|
||||||
}"#,
|
}"#,
|
||||||
|
@ -952,6 +945,11 @@ struct S {
|
||||||
vec: Vec<u8>
|
vec: Vec<u8>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Vec<T>;
|
||||||
|
impl<T> Vec<T> {
|
||||||
|
fn push(&mut self, _:usize) {}
|
||||||
|
}
|
||||||
|
|
||||||
fn foo(s: &mut S) {
|
fn foo(s: &mut S) {
|
||||||
let $0vec = &mut s.vec;
|
let $0vec = &mut s.vec;
|
||||||
vec.push(0);
|
vec.push(0);
|
||||||
|
@ -973,6 +971,10 @@ struct X {
|
||||||
struct S {
|
struct S {
|
||||||
vec: Vec<u8>
|
vec: Vec<u8>
|
||||||
}
|
}
|
||||||
|
struct Vec<T>;
|
||||||
|
impl<T> Vec<T> {
|
||||||
|
fn push(&mut self, _:usize) {}
|
||||||
|
}
|
||||||
|
|
||||||
fn foo(f: &mut Y) {
|
fn foo(f: &mut Y) {
|
||||||
$0f.field.field.vec$0.push(0);
|
$0f.field.field.vec$0.push(0);
|
||||||
|
@ -987,6 +989,10 @@ struct X {
|
||||||
struct S {
|
struct S {
|
||||||
vec: Vec<u8>
|
vec: Vec<u8>
|
||||||
}
|
}
|
||||||
|
struct Vec<T>;
|
||||||
|
impl<T> Vec<T> {
|
||||||
|
fn push(&mut self, _:usize) {}
|
||||||
|
}
|
||||||
|
|
||||||
fn foo(f: &mut Y) {
|
fn foo(f: &mut Y) {
|
||||||
let $0vec = &mut f.field.field.vec;
|
let $0vec = &mut f.field.field.vec;
|
||||||
|
@ -1123,7 +1129,7 @@ struct S {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn foo(s: S) {
|
fn foo(s: S) {
|
||||||
let $0x = s.sub;
|
let $0x = &s.sub;
|
||||||
x.do_thing();
|
x.do_thing();
|
||||||
}"#,
|
}"#,
|
||||||
);
|
);
|
||||||
|
@ -1189,7 +1195,7 @@ impl X {
|
||||||
|
|
||||||
fn foo() {
|
fn foo() {
|
||||||
let local = &mut S::new();
|
let local = &mut S::new();
|
||||||
let $0x = &mut local.sub;
|
let $0x = &local.sub;
|
||||||
x.do_thing();
|
x.do_thing();
|
||||||
}"#,
|
}"#,
|
||||||
);
|
);
|
||||||
|
|
|
@ -415,7 +415,6 @@ impl WorkspaceBuildScripts {
|
||||||
let dir_entry = entry.ok()?;
|
let dir_entry = entry.ok()?;
|
||||||
if dir_entry.file_type().ok()?.is_file() {
|
if dir_entry.file_type().ok()?.is_file() {
|
||||||
let path = dir_entry.path();
|
let path = dir_entry.path();
|
||||||
tracing::info!("p{:?}", path);
|
|
||||||
let extension = path.extension()?;
|
let extension = path.extension()?;
|
||||||
if extension == std::env::consts::DLL_EXTENSION {
|
if extension == std::env::consts::DLL_EXTENSION {
|
||||||
let name = path.file_stem()?.to_str()?.split_once('-')?.0.to_owned();
|
let name = path.file_stem()?.to_str()?.split_once('-')?.0.to_owned();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue