diff --git a/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/crates/ide-assists/src/handlers/add_missing_impl_members.rs index 11201afb8a7f..7e03eb30304b 100644 --- a/crates/ide-assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ide-assists/src/handlers/add_missing_impl_members.rs @@ -2418,6 +2418,55 @@ pub struct MyStruct; impl other_file_2::Trait for MyStruct { $0type Iter; +}"#, + ); + } + + #[test] + fn test_qualify_ident_pat_in_default_members() { + check_assist( + add_missing_default_members, + r#" +//- /lib.rs crate:b new_source_root:library +pub enum State { + Active, + Inactive, +} + +use State::*; + +pub trait Checker { + fn check(&self) -> State; + + fn is_active(&self) -> bool { + match self.check() { + Active => true, + Inactive => false, + } + } +} +//- /main.rs crate:a deps:b +struct MyChecker; + +impl b::Checker for MyChecker { + fn check(&self) -> b::State { + todo!(); + }$0 +}"#, + r#" +struct MyChecker; + +impl b::Checker for MyChecker { + fn check(&self) -> b::State { + todo!(); + } + + $0fn is_active(&self) -> bool { + match self.check() { + b::State::Active => true, + b::State::Inactive => false, + } + } }"#, ); } diff --git a/crates/ide-db/src/path_transform.rs b/crates/ide-db/src/path_transform.rs index 5d88afec5095..a76a0551dd8d 100644 --- a/crates/ide-db/src/path_transform.rs +++ b/crates/ide-db/src/path_transform.rs @@ -11,7 +11,7 @@ use rustc_hash::FxHashMap; use span::Edition; use syntax::{ NodeOrToken, SyntaxNode, - ast::{self, AstNode, HasGenericArgs, make}, + ast::{self, AstNode, HasGenericArgs, HasName, make}, syntax_editor::{self, SyntaxEditor}, }; @@ -315,32 +315,49 @@ impl Ctx<'_> { } fn transform_path(&self, path: &SyntaxNode) -> SyntaxNode { - fn find_child_paths(root_path: &SyntaxNode) -> Vec { - let mut result = Vec::new(); + fn find_child_paths_and_ident_pats( + root_path: &SyntaxNode, + ) -> Vec> { + let mut result: Vec> = Vec::new(); for child in root_path.children() { if let Some(child_path) = ast::Path::cast(child.clone()) { - result.push(child_path); + result.push(either::Left(child_path)); + } else if let Some(child_ident_pat) = ast::IdentPat::cast(child.clone()) { + result.push(either::Right(child_ident_pat)); } else { - result.extend(find_child_paths(&child)); + result.extend(find_child_paths_and_ident_pats(&child)); } } result } + let root_path = path.clone_subtree(); - let result = find_child_paths(&root_path); + + let result = find_child_paths_and_ident_pats(&root_path); let mut editor = SyntaxEditor::new(root_path.clone()); for sub_path in result { let new = self.transform_path(sub_path.syntax()); editor.replace(sub_path.syntax(), new); } + let update_sub_item = editor.finish().new_root().clone().clone_subtree(); - let item = find_child_paths(&update_sub_item); + let item = find_child_paths_and_ident_pats(&update_sub_item); let mut editor = SyntaxEditor::new(update_sub_item); for sub_path in item { - self.transform_path_(&mut editor, &sub_path); + self.transform_path_or_ident_pat(&mut editor, &sub_path); } editor.finish().new_root().clone() } + fn transform_path_or_ident_pat( + &self, + editor: &mut SyntaxEditor, + item: &Either, + ) -> Option<()> { + match item { + Either::Left(path) => self.transform_path_(editor, path), + Either::Right(ident_pat) => self.transform_ident_pat(editor, ident_pat), + } + } fn transform_path_(&self, editor: &mut SyntaxEditor, path: &ast::Path) -> Option<()> { if path.qualifier().is_some() { @@ -515,6 +532,34 @@ impl Ctx<'_> { } Some(()) } + + fn transform_ident_pat( + &self, + editor: &mut SyntaxEditor, + ident_pat: &ast::IdentPat, + ) -> Option<()> { + let name = ident_pat.name()?; + + let temp_path = make::path_from_text(&name.text()); + + let resolution = self.source_scope.speculative_resolve(&temp_path)?; + + match resolution { + hir::PathResolution::Def(def) if def.as_assoc_item(self.source_scope.db).is_none() => { + let cfg = ImportPathConfig { + prefer_no_std: false, + prefer_prelude: true, + prefer_absolute: false, + allow_unstable: true, + }; + let found_path = self.target_module.find_path(self.source_scope.db, def, cfg)?; + let res = mod_path_to_ast(&found_path, self.target_edition).clone_for_update(); + editor.replace(ident_pat.syntax(), res.syntax()); + Some(()) + } + _ => None, + } + } } // FIXME: It would probably be nicer if we could get this via HIR (i.e. get the