From ddd59b9a9a57c3b013fe298a20db2ab876200f28 Mon Sep 17 00:00:00 2001 From: feniljain Date: Sat, 21 May 2022 18:42:35 +0530 Subject: [PATCH] fix(extract_module): nearby imports deletion causing panic --- .../src/handlers/extract_module.rs | 58 ++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/crates/ide-assists/src/handlers/extract_module.rs b/crates/ide-assists/src/handlers/extract_module.rs index b5ed5699c90..1f20149d6a3 100644 --- a/crates/ide-assists/src/handlers/extract_module.rs +++ b/crates/ide-assists/src/handlers/extract_module.rs @@ -180,6 +180,7 @@ pub(crate) fn extract_module(acc: &mut Assists, ctx: &AssistContext) -> Option<( } for import_path_text_range in import_paths_to_be_removed { + println!("Deleting : {:?}", import_path_text_range); builder.delete(import_path_text_range); } @@ -439,7 +440,28 @@ fn resolve_imports( ctx, ) { - import_paths_to_be_removed.push(import_path); + if import_paths_to_be_removed.len() > 0 { + // Text ranges recieved here for imports are extended to the + // next/previous comma which can cause intersections among them + // and later deletion of these can cause panics similar + // to reported in #11766. So to mitigate it, we + // check for intersection between all current members + // and if it exists we combine both text ranges into + // one + for i in 0..import_paths_to_be_removed.len() { + if let Some(_) = + import_paths_to_be_removed[i].intersect(import_path) + { + import_paths_to_be_removed[i] = + import_paths_to_be_removed[i] + .cover(import_path); + } else { + import_paths_to_be_removed.push(import_path); + } + } + } else { + import_paths_to_be_removed.push(import_path); + } } } } @@ -1495,4 +1517,38 @@ pub(crate) fn foo(x: B) {} ", ) } + + #[test] + fn test_issue_11766() { + //https://github.com/rust-lang/rust-analyzer/issues/11766 + check_assist( + extract_module, + r" + mod x { + pub struct Foo; + pub struct Bar; + } + + use x::{Bar, Foo}; + + $0type A = (Foo, Bar);$0 + ", + r" + mod x { + pub struct Foo; + pub struct Bar; + } + + use x::{}; + + mod modname { + use super::x::Bar; + + use super::x::Foo; + + pub(crate) type A = (Foo, Bar); + } + ", + ) + } }