Use shorthand field syntax in destructures
This commit is contained in:
parent
924eecf4af
commit
cb60708274
@ -622,7 +622,7 @@ fn foo() {
|
|||||||
expect![[r#"
|
expect![[r#"
|
||||||
f RECORD_FIELD FileId(0) 15..21 15..16 Other
|
f RECORD_FIELD FileId(0) 15..21 15..16 Other
|
||||||
|
|
||||||
FileId(0) 55..56 Other Read
|
FileId(0) 55..56 RecordFieldExprOrPat Read
|
||||||
FileId(0) 68..69 Other Write
|
FileId(0) 68..69 Other Write
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
@ -757,7 +757,7 @@ fn f() -> m::En {
|
|||||||
expect![[r#"
|
expect![[r#"
|
||||||
field RECORD_FIELD FileId(0) 56..65 56..61 Other
|
field RECORD_FIELD FileId(0) 56..65 56..61 Other
|
||||||
|
|
||||||
FileId(0) 125..130 Other Read
|
FileId(0) 125..130 RecordFieldExprOrPat Read
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! FIXME: write short doc here
|
//! FIXME: write short doc here
|
||||||
|
|
||||||
use hir::{Module, ModuleDef, ModuleSource, Semantics};
|
use hir::{Module, ModuleDef, ModuleSource, Semantics};
|
||||||
use ide_db::base_db::SourceDatabaseExt;
|
use ide_db::base_db::{FileRange, SourceDatabaseExt};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
defs::{Definition, NameClass, NameRefClass},
|
defs::{Definition, NameClass, NameRefClass},
|
||||||
RootDatabase,
|
RootDatabase,
|
||||||
@ -112,7 +112,6 @@ fn source_edit_from_reference(
|
|||||||
new_name: &str,
|
new_name: &str,
|
||||||
) -> SourceFileEdit {
|
) -> SourceFileEdit {
|
||||||
let mut replacement_text = String::new();
|
let mut replacement_text = String::new();
|
||||||
let file_id = reference.file_range.file_id;
|
|
||||||
let range = match reference.kind {
|
let range = match reference.kind {
|
||||||
ReferenceKind::FieldShorthandForField => {
|
ReferenceKind::FieldShorthandForField => {
|
||||||
mark::hit!(test_rename_struct_field_for_shorthand);
|
mark::hit!(test_rename_struct_field_for_shorthand);
|
||||||
@ -126,28 +125,49 @@ fn source_edit_from_reference(
|
|||||||
replacement_text.push_str(new_name);
|
replacement_text.push_str(new_name);
|
||||||
TextRange::new(reference.file_range.range.end(), reference.file_range.range.end())
|
TextRange::new(reference.file_range.range.end(), reference.file_range.range.end())
|
||||||
}
|
}
|
||||||
ReferenceKind::RecordExprField => {
|
ReferenceKind::RecordFieldExprOrPat => {
|
||||||
replacement_text.push_str(new_name);
|
replacement_text.push_str(new_name);
|
||||||
let mut range = reference.file_range.range;
|
edit_text_range_for_record_field_expr_or_pat(sema, reference.file_range, new_name)
|
||||||
if let Some(field_expr) = syntax::algo::find_node_at_range::<ast::RecordExprField>(
|
|
||||||
sema.parse(file_id).syntax(),
|
|
||||||
reference.file_range.range,
|
|
||||||
) {
|
|
||||||
// use shorthand initializer if we were to write foo: foo
|
|
||||||
if let Some(name) = field_expr.expr().and_then(|e| e.name_ref()) {
|
|
||||||
if &name.to_string() == new_name {
|
|
||||||
range = field_expr.syntax().text_range();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
range
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
replacement_text.push_str(new_name);
|
replacement_text.push_str(new_name);
|
||||||
reference.file_range.range
|
reference.file_range.range
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
SourceFileEdit { file_id, edit: TextEdit::replace(range, replacement_text) }
|
SourceFileEdit {
|
||||||
|
file_id: reference.file_range.file_id,
|
||||||
|
edit: TextEdit::replace(range, replacement_text),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn edit_text_range_for_record_field_expr_or_pat(
|
||||||
|
sema: &Semantics<RootDatabase>,
|
||||||
|
file_range: FileRange,
|
||||||
|
new_name: &str,
|
||||||
|
) -> TextRange {
|
||||||
|
let mut range = file_range.range;
|
||||||
|
let source_file = sema.parse(file_range.file_id);
|
||||||
|
let file_syntax = source_file.syntax();
|
||||||
|
if let Some(field_expr) =
|
||||||
|
syntax::algo::find_node_at_range::<ast::RecordExprField>(file_syntax, range)
|
||||||
|
{
|
||||||
|
match field_expr.expr().and_then(|e| e.name_ref()) {
|
||||||
|
Some(name) if &name.to_string() == new_name => range = field_expr.syntax().text_range(),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
} else if let Some(field_pat) =
|
||||||
|
syntax::algo::find_node_at_range::<ast::RecordPatField>(file_syntax, range)
|
||||||
|
{
|
||||||
|
match field_pat.pat() {
|
||||||
|
Some(ast::Pat::IdentPat(pat))
|
||||||
|
if pat.name().map(|n| n.to_string()).as_deref() == Some(new_name) =>
|
||||||
|
{
|
||||||
|
range = field_pat.syntax().text_range()
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
range
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rename_mod(
|
fn rename_mod(
|
||||||
@ -1189,6 +1209,29 @@ fn foo(foo: Foo) {
|
|||||||
let Foo { i: bar } = foo;
|
let Foo { i: bar } = foo;
|
||||||
let _ = bar;
|
let _ = bar;
|
||||||
}
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_struct_field_destructure_into_shorthand() {
|
||||||
|
check(
|
||||||
|
"baz",
|
||||||
|
r#"
|
||||||
|
struct Foo { i<|>: i32 }
|
||||||
|
|
||||||
|
fn foo(foo: Foo) {
|
||||||
|
let Foo { i: baz } = foo;
|
||||||
|
let _ = baz;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
struct Foo { baz: i32 }
|
||||||
|
|
||||||
|
fn foo(foo: Foo) {
|
||||||
|
let Foo { baz } = foo;
|
||||||
|
let _ = baz;
|
||||||
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ pub enum ReferenceKind {
|
|||||||
FieldShorthandForField,
|
FieldShorthandForField,
|
||||||
FieldShorthandForLocal,
|
FieldShorthandForLocal,
|
||||||
StructLiteral,
|
StructLiteral,
|
||||||
RecordExprField,
|
RecordFieldExprOrPat,
|
||||||
Other,
|
Other,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,15 +279,13 @@ fn found_name_ref(
|
|||||||
) -> bool {
|
) -> bool {
|
||||||
match NameRefClass::classify(self.sema, &name_ref) {
|
match NameRefClass::classify(self.sema, &name_ref) {
|
||||||
Some(NameRefClass::Definition(def)) if &def == self.def => {
|
Some(NameRefClass::Definition(def)) if &def == self.def => {
|
||||||
let kind =
|
let kind = if is_record_field_expr_or_pat(&name_ref) {
|
||||||
if name_ref.syntax().parent().and_then(ast::RecordExprField::cast).is_some() {
|
ReferenceKind::RecordFieldExprOrPat
|
||||||
ReferenceKind::RecordExprField
|
} else if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref) {
|
||||||
} else if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref)
|
ReferenceKind::StructLiteral
|
||||||
{
|
} else {
|
||||||
ReferenceKind::StructLiteral
|
ReferenceKind::Other
|
||||||
} else {
|
};
|
||||||
ReferenceKind::Other
|
|
||||||
};
|
|
||||||
|
|
||||||
let reference = Reference {
|
let reference = Reference {
|
||||||
file_range: self.sema.original_range(name_ref.syntax()),
|
file_range: self.sema.original_range(name_ref.syntax()),
|
||||||
@ -389,3 +387,17 @@ fn is_record_lit_name_ref(name_ref: &ast::NameRef) -> bool {
|
|||||||
.map(|p| p.name_ref().as_ref() == Some(name_ref))
|
.map(|p| p.name_ref().as_ref() == Some(name_ref))
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_record_field_expr_or_pat(name_ref: &ast::NameRef) -> bool {
|
||||||
|
if let Some(parent) = name_ref.syntax().parent() {
|
||||||
|
match_ast! {
|
||||||
|
match parent {
|
||||||
|
ast::RecordExprField(it) => true,
|
||||||
|
ast::RecordPatField(_it) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user