Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-assists/src/handlers/destructure_tuple_binding.rs')
| -rw-r--r-- | crates/ide-assists/src/handlers/destructure_tuple_binding.rs | 88 |
1 files changed, 52 insertions, 36 deletions
diff --git a/crates/ide-assists/src/handlers/destructure_tuple_binding.rs b/crates/ide-assists/src/handlers/destructure_tuple_binding.rs index d51a3a26a3..23c11b258c 100644 --- a/crates/ide-assists/src/handlers/destructure_tuple_binding.rs +++ b/crates/ide-assists/src/handlers/destructure_tuple_binding.rs @@ -14,7 +14,7 @@ use syntax::{ use crate::{ assist_context::{AssistContext, Assists, SourceChangeBuilder}, - utils::ref_field_expr::determine_ref_and_parens, + utils::{cover_edit_range, ref_field_expr::determine_ref_and_parens}, }; // Assist: destructure_tuple_binding @@ -98,7 +98,9 @@ fn destructure_tuple_edit_impl( assignment_edit.apply(&mut syntax_editor, &syntax_factory); if let Some(usages_edit) = current_file_usages_edit { - usages_edit.into_iter().for_each(|usage_edit| usage_edit.apply(edit, &mut syntax_editor)) + usages_edit + .into_iter() + .for_each(|usage_edit| usage_edit.apply(ctx, edit, &mut syntax_editor)) } syntax_editor.add_mappings(syntax_factory.finish_with_mappings()); @@ -311,14 +313,25 @@ enum EditTupleUsage { } impl EditTupleUsage { - fn apply(self, edit: &mut SourceChangeBuilder, syntax_editor: &mut SyntaxEditor) { + fn apply( + self, + ctx: &AssistContext<'_>, + edit: &mut SourceChangeBuilder, + syntax_editor: &mut SyntaxEditor, + ) { match self { EditTupleUsage::NoIndex(range) => { edit.insert(range.start(), "/*"); edit.insert(range.end(), "*/"); } EditTupleUsage::ReplaceExpr(target_expr, replace_with) => { - syntax_editor.replace(target_expr.syntax(), replace_with.syntax()) + if let Some(range) = ctx.sema.original_range_opt(target_expr.syntax()) { + let source = ctx.source_file().syntax(); + syntax_editor.replace_all( + cover_edit_range(source, range.range), + vec![replace_with.syntax().clone().into()], + ); + } } } } @@ -349,24 +362,6 @@ fn detect_tuple_index(usage: &FileReference, data: &TupleData) -> Option<TupleIn if let Some(field_expr) = ast::FieldExpr::cast(node) { let idx = field_expr.name_ref()?.as_tuple_field()?; if idx < data.field_names.len() { - // special case: in macro call -> range of `field_expr` in applied macro, NOT range in actual file! - if field_expr.syntax().ancestors().any(|a| ast::MacroStmts::can_cast(a.kind())) { - cov_mark::hit!(destructure_tuple_macro_call); - - // issue: cannot differentiate between tuple index passed into macro or tuple index as result of macro: - // ```rust - // macro_rules! m { - // ($t1:expr, $t2:expr) => { $t1; $t2.0 } - // } - // let t = (1,2); - // m!(t.0, t) - // ``` - // -> 2 tuple index usages detected! - // - // -> only handle `t` - return None; - } - Some(TupleIndex { index: idx, field_expr }) } else { // tuple index out of range @@ -1437,7 +1432,6 @@ fn main() { #[test] fn detect_macro_call() { - cov_mark::check!(destructure_tuple_macro_call); check_in_place_assist( r#" macro_rules! m { @@ -1456,7 +1450,7 @@ macro_rules! m { fn main() { let ($0_0, _1) = (1,2); - m!(/*t*/.0); + m!(_0); } "#, ) @@ -1548,7 +1542,6 @@ fn main() { m!(t.0); } "#, - // FIXME: replace `t.0` with `_0` (cannot detect range of tuple index in macro call) r#" macro_rules! m { ($e:expr) => { "foo"; $e }; @@ -1556,10 +1549,9 @@ macro_rules! m { fn main() { let ($0_0, _1) = (1,2); - m!(/*t*/.0); + m!(_0); } "#, - // FIXME: replace `t.0` with `_0` r#" macro_rules! m { ($e:expr) => { "foo"; $e }; @@ -1567,7 +1559,7 @@ macro_rules! m { fn main() { let t @ ($0_0, _1) = (1,2); - m!(t.0); + m!(_0); } "#, ) @@ -1586,7 +1578,6 @@ fn main() { m!((t).0); } "#, - // FIXME: replace `(t).0` with `_0` r#" macro_rules! m { ($e:expr) => { "foo"; $e }; @@ -1594,10 +1585,9 @@ macro_rules! m { fn main() { let ($0_0, _1) = (1,2); - m!((/*t*/).0); + m!(_0); } "#, - // FIXME: replace `(t).0` with `_0` r#" macro_rules! m { ($e:expr) => { "foo"; $e }; @@ -1605,7 +1595,7 @@ macro_rules! m { fn main() { let t @ ($0_0, _1) = (1,2); - m!((t).0); + m!(_0); } "#, ) @@ -1653,7 +1643,6 @@ fn main() { m!(t, t.0); } "#, - // FIXME: replace `t.0` in macro call (not IN macro) with `_0` r#" macro_rules! m { ($t:expr, $i:expr) => { $t.0 + $i }; @@ -1661,10 +1650,9 @@ macro_rules! m { fn main() { let ($0_0, _1) = (1,2); - m!(/*t*/, /*t*/.0); + m!(t, _0); } "#, - // FIXME: replace `t.0` in macro call with `_0` r#" macro_rules! m { ($t:expr, $i:expr) => { $t.0 + $i }; @@ -1672,13 +1660,41 @@ macro_rules! m { fn main() { let t @ ($0_0, _1) = (1,2); - m!(t, t.0); + m!(t, _0); } "#, ) } } + mod in_macro_expr { + use super::assist::*; + + // exact repro from #20716: tuple index inside write! must not panic + #[test] + fn tuple_index_in_write_macro() { + check_in_place_assist( + r#" +//- minicore: write, fmt +use core::fmt::Write; +fn main() { + let mut s = String::new(); + let $0x = (2i32, 3i32); + write!(s, "{}", x.0).unwrap(); +} +"#, + r#" +use core::fmt::Write; +fn main() { + let mut s = String::new(); + let ($0_0, _1) = (2i32, 3i32); + write!(s, "{}", _0).unwrap(); +} +"#, + ) + } + } + mod refs { use super::assist::*; |