Skip to content

Commit

Permalink
fix: use original range to deal with macros in promote_local_to_const
Browse files Browse the repository at this point in the history
  • Loading branch information
rmehri01 authored and Veykril committed Jan 2, 2024
1 parent 9f6a2c4 commit b105e9b
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 30 deletions.
27 changes: 6 additions & 21 deletions crates/ide-assists/src/handlers/bool_to_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ use syntax::{
};
use text_edit::TextRange;

use crate::assist_context::{AssistContext, Assists};
use crate::{
assist_context::{AssistContext, Assists},
utils,
};

// Assist: bool_to_enum
//
Expand Down Expand Up @@ -238,7 +241,7 @@ fn replace_usages(
cov_mark::hit!(replaces_record_expr);

let enum_expr = bool_expr_to_enum_expr(initializer);
replace_record_field_expr(ctx, edit, record_field, enum_expr);
utils::replace_record_field_expr(ctx, edit, record_field, enum_expr);
} else if let Some(pat) = find_record_pat_field_usage(&name) {
match pat {
ast::Pat::IdentPat(ident_pat) => {
Expand Down Expand Up @@ -281,7 +284,7 @@ fn replace_usages(
|record_field| record_field.expr().map(|expr| (record_field, expr)),
)
{
replace_record_field_expr(
utils::replace_record_field_expr(
ctx,
edit,
record_field,
Expand Down Expand Up @@ -310,24 +313,6 @@ fn replace_usages(
}
}

/// Replaces the record expression, handling field shorthands.
fn replace_record_field_expr(
ctx: &AssistContext<'_>,
edit: &mut SourceChangeBuilder,
record_field: ast::RecordExprField,
initializer: ast::Expr,
) {
if let Some(ast::Expr::PathExpr(path_expr)) = record_field.expr() {
// replace field shorthand
let file_range = ctx.sema.original_range(path_expr.syntax());
edit.insert(file_range.range.end(), format!(": {}", initializer.syntax().text()))
} else if let Some(expr) = record_field.expr() {
// just replace expr
let file_range = ctx.sema.original_range(expr.syntax());
edit.replace(file_range.range, initializer.syntax().text());
}
}

struct FileReferenceWithImport {
range: TextRange,
name: ast::NameLike,
Expand Down
89 changes: 80 additions & 9 deletions crates/ide-assists/src/handlers/promote_local_to_const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ use syntax::{
ted, AstNode, WalkEvent,
};

use crate::assist_context::{AssistContext, Assists};
use crate::{
assist_context::{AssistContext, Assists},
utils,
};

// Assist: promote_local_to_const
//
Expand Down Expand Up @@ -79,15 +82,13 @@ pub(crate) fn promote_local_to_const(acc: &mut Assists, ctx: &AssistContext<'_>)
let name_ref = make::name_ref(&name);

for usage in usages {
let Some(usage) = usage.name.as_name_ref().cloned() else { continue };
if let Some(record_field) = ast::RecordExprField::for_name_ref(&usage) {
let record_field = edit.make_mut(record_field);
let name_expr =
make::expr_path(make::path_from_text(&name)).clone_for_update();
record_field.replace_expr(name_expr);
let Some(usage_name) = usage.name.as_name_ref().cloned() else { continue };
if let Some(record_field) = ast::RecordExprField::for_name_ref(&usage_name) {
let name_expr = make::expr_path(make::path_from_text(&name));
utils::replace_record_field_expr(ctx, edit, record_field, name_expr);
} else {
let usage = edit.make_mut(usage);
ted::replace(usage.syntax(), name_ref.clone_for_update().syntax());
let usage_range = usage.range;
edit.replace(usage_range, name_ref.syntax().text());
}
}
}
Expand Down Expand Up @@ -212,6 +213,76 @@ fn main() {
)
}

#[test]
fn usage_in_macro() {
check_assist(
promote_local_to_const,
r"
macro_rules! identity {
($body:expr) => {
$body
}
}
fn baz() -> usize {
let $0foo = 2;
identity![foo]
}
",
r"
macro_rules! identity {
($body:expr) => {
$body
}
}
fn baz() -> usize {
const $0FOO: usize = 2;
identity![FOO]
}
",
)
}

#[test]
fn usage_shorthand_in_macro() {
check_assist(
promote_local_to_const,
r"
struct Foo {
foo: usize,
}
macro_rules! identity {
($body:expr) => {
$body
};
}
fn baz() -> Foo {
let $0foo = 2;
identity![Foo { foo }]
}
",
r"
struct Foo {
foo: usize,
}
macro_rules! identity {
($body:expr) => {
$body
};
}
fn baz() -> Foo {
const $0FOO: usize = 2;
identity![Foo { foo: FOO }]
}
",
)
}

#[test]
fn not_applicable_non_const_meth_call() {
cov_mark::check!(promote_local_non_const);
Expand Down
18 changes: 18 additions & 0 deletions crates/ide-assists/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -813,3 +813,21 @@ fn test_required_hashes() {
assert_eq!(3, required_hashes("#ab\"##c"));
assert_eq!(5, required_hashes("#ab\"##\"####c"));
}

/// Replaces the record expression, handling field shorthands including inside macros.
pub(crate) fn replace_record_field_expr(
ctx: &AssistContext<'_>,
edit: &mut SourceChangeBuilder,
record_field: ast::RecordExprField,
initializer: ast::Expr,
) {
if let Some(ast::Expr::PathExpr(path_expr)) = record_field.expr() {
// replace field shorthand
let file_range = ctx.sema.original_range(path_expr.syntax());
edit.insert(file_range.range.end(), format!(": {}", initializer.syntax().text()))
} else if let Some(expr) = record_field.expr() {
// just replace expr
let file_range = ctx.sema.original_range(expr.syntax());
edit.replace(file_range.range, initializer.syntax().text());
}
}

0 comments on commit b105e9b

Please sign in to comment.