mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-28 04:45:05 +00:00
Use shorthand record syntax when renaming struct initializer field
This commit is contained in:
parent
99fa139bea
commit
e55a44a831
4 changed files with 68 additions and 19 deletions
|
@ -106,7 +106,11 @@ fn find_module_at_offset(
|
||||||
Some(module)
|
Some(module)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn source_edit_from_reference(reference: Reference, new_name: &str) -> SourceFileEdit {
|
fn source_edit_from_reference(
|
||||||
|
sema: &Semantics<RootDatabase>,
|
||||||
|
reference: Reference,
|
||||||
|
new_name: &str,
|
||||||
|
) -> SourceFileEdit {
|
||||||
let mut replacement_text = String::new();
|
let mut replacement_text = String::new();
|
||||||
let file_id = reference.file_range.file_id;
|
let file_id = reference.file_range.file_id;
|
||||||
let range = match reference.kind {
|
let range = match reference.kind {
|
||||||
|
@ -122,6 +126,22 @@ fn source_edit_from_reference(reference: Reference, new_name: &str) -> SourceFil
|
||||||
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 => {
|
||||||
|
replacement_text.push_str(new_name);
|
||||||
|
let mut range = reference.file_range.range;
|
||||||
|
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
|
||||||
|
@ -170,7 +190,7 @@ fn rename_mod(
|
||||||
let ref_edits = refs
|
let ref_edits = refs
|
||||||
.references
|
.references
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|reference| source_edit_from_reference(reference, new_name));
|
.map(|reference| source_edit_from_reference(sema, reference, new_name));
|
||||||
source_file_edits.extend(ref_edits);
|
source_file_edits.extend(ref_edits);
|
||||||
|
|
||||||
Ok(RangeInfo::new(range, SourceChange::from_edits(source_file_edits, file_system_edits)))
|
Ok(RangeInfo::new(range, SourceChange::from_edits(source_file_edits, file_system_edits)))
|
||||||
|
@ -211,7 +231,7 @@ fn rename_to_self(
|
||||||
|
|
||||||
let mut edits = usages
|
let mut edits = usages
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|reference| source_edit_from_reference(reference, "self"))
|
.map(|reference| source_edit_from_reference(sema, reference, "self"))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
edits.push(SourceFileEdit {
|
edits.push(SourceFileEdit {
|
||||||
|
@ -300,7 +320,7 @@ fn rename_reference(
|
||||||
|
|
||||||
let edit = refs
|
let edit = refs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|reference| source_edit_from_reference(reference, new_name))
|
.map(|reference| source_edit_from_reference(sema, reference, new_name))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
if edit.is_empty() {
|
if edit.is_empty() {
|
||||||
|
@ -1094,6 +1114,27 @@ impl Foo {
|
||||||
foo.i
|
foo.i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_initializer_use_field_init_shorthand() {
|
||||||
|
check(
|
||||||
|
"bar",
|
||||||
|
r#"
|
||||||
|
struct Foo { i<|>: i32 }
|
||||||
|
|
||||||
|
fn foo(bar: i32) -> Foo {
|
||||||
|
Foo { i: bar }
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
struct Foo { bar: i32 }
|
||||||
|
|
||||||
|
fn foo(bar: i32) -> Foo {
|
||||||
|
Foo { bar }
|
||||||
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ pub enum ReferenceKind {
|
||||||
FieldShorthandForField,
|
FieldShorthandForField,
|
||||||
FieldShorthandForLocal,
|
FieldShorthandForLocal,
|
||||||
StructLiteral,
|
StructLiteral,
|
||||||
|
RecordExprField,
|
||||||
Other,
|
Other,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,12 +279,15 @@ impl<'a> FindUsages<'a> {
|
||||||
) -> 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 = if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref)
|
let kind =
|
||||||
{
|
if name_ref.syntax().parent().and_then(ast::RecordExprField::cast).is_some() {
|
||||||
ReferenceKind::StructLiteral
|
ReferenceKind::RecordExprField
|
||||||
} else {
|
} else if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref)
|
||||||
ReferenceKind::Other
|
{
|
||||||
};
|
ReferenceKind::StructLiteral
|
||||||
|
} 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()),
|
||||||
|
|
|
@ -22,6 +22,18 @@ impl ast::Expr {
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn name_ref(&self) -> Option<ast::NameRef> {
|
||||||
|
if let ast::Expr::PathExpr(expr) = self {
|
||||||
|
let path = expr.path()?;
|
||||||
|
let segment = path.segment()?;
|
||||||
|
let name_ref = segment.name_ref()?;
|
||||||
|
if path.qualifier().is_none() {
|
||||||
|
return Some(name_ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
|
|
@ -203,15 +203,7 @@ impl ast::RecordExprField {
|
||||||
if let Some(name_ref) = self.name_ref() {
|
if let Some(name_ref) = self.name_ref() {
|
||||||
return Some(name_ref);
|
return Some(name_ref);
|
||||||
}
|
}
|
||||||
if let Some(ast::Expr::PathExpr(expr)) = self.expr() {
|
self.expr()?.name_ref()
|
||||||
let path = expr.path()?;
|
|
||||||
let segment = path.segment()?;
|
|
||||||
let name_ref = segment.name_ref()?;
|
|
||||||
if path.qualifier().is_none() {
|
|
||||||
return Some(name_ref);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue