From cb60708274dc7c8cff281364507d23047cd482cd Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 14 Nov 2020 19:57:47 +0100 Subject: Use shorthand field syntax in destructures --- crates/ide/src/references.rs | 4 +- crates/ide/src/references/rename.rs | 77 +++++++++++++++++++++++++++++-------- 2 files changed, 62 insertions(+), 19 deletions(-) (limited to 'crates/ide/src') diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index 10cd42032..5693dd400 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -622,7 +622,7 @@ fn foo() { expect![[r#" 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 "#]], ); @@ -757,7 +757,7 @@ fn f() -> m::En { expect![[r#" field RECORD_FIELD FileId(0) 56..65 56..61 Other - FileId(0) 125..130 Other Read + FileId(0) 125..130 RecordFieldExprOrPat Read "#]], ); } diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs index bc4aa25bf..449cfa4ae 100644 --- a/crates/ide/src/references/rename.rs +++ b/crates/ide/src/references/rename.rs @@ -1,7 +1,7 @@ //! FIXME: write short doc here use hir::{Module, ModuleDef, ModuleSource, Semantics}; -use ide_db::base_db::SourceDatabaseExt; +use ide_db::base_db::{FileRange, SourceDatabaseExt}; use ide_db::{ defs::{Definition, NameClass, NameRefClass}, RootDatabase, @@ -112,7 +112,6 @@ fn source_edit_from_reference( new_name: &str, ) -> SourceFileEdit { let mut replacement_text = String::new(); - let file_id = reference.file_range.file_id; let range = match reference.kind { ReferenceKind::FieldShorthandForField => { mark::hit!(test_rename_struct_field_for_shorthand); @@ -126,28 +125,49 @@ fn source_edit_from_reference( replacement_text.push_str(new_name); TextRange::new(reference.file_range.range.end(), reference.file_range.range.end()) } - ReferenceKind::RecordExprField => { + ReferenceKind::RecordFieldExprOrPat => { replacement_text.push_str(new_name); - let mut range = reference.file_range.range; - if let Some(field_expr) = syntax::algo::find_node_at_range::( - 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 + edit_text_range_for_record_field_expr_or_pat(sema, reference.file_range, new_name) } _ => { replacement_text.push_str(new_name); 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, + 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::(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::(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( @@ -1189,6 +1209,29 @@ fn foo(foo: Foo) { let Foo { i: bar } = foo; 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; +} "#, ); } -- cgit v1.2.3