Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-db/src/path_transform.rs')
| -rw-r--r-- | crates/ide-db/src/path_transform.rs | 167 |
1 files changed, 104 insertions, 63 deletions
diff --git a/crates/ide-db/src/path_transform.rs b/crates/ide-db/src/path_transform.rs index b7432d89c7..4a27035afd 100644 --- a/crates/ide-db/src/path_transform.rs +++ b/crates/ide-db/src/path_transform.rs @@ -3,7 +3,7 @@ use crate::helpers::mod_path_to_ast; use either::Either; use hir::{ - AsAssocItem, HirDisplay, HirFileId, ImportPathConfig, ModuleDef, SemanticsScope, + AsAssocItem, FindPathConfig, HirDisplay, HirFileId, ModuleDef, SemanticsScope, prettify_macro_expansion, }; use itertools::Itertools; @@ -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}, }; @@ -193,13 +193,12 @@ impl<'a> PathTransform<'a> { } } (Either::Right(k), None) => { - if let Some(default) = k.default(db) { - if let Some(default) = + if let Some(default) = k.default(db) + && let Some(default) = &default.display_source_code(db, source_module.into(), false).ok() - { - type_substs.insert(k, make::ty(default).clone_for_update()); - defaulted_params.push(Either::Left(k)); - } + { + type_substs.insert(k, make::ty(default).clone_for_update()); + defaulted_params.push(Either::Left(k)); } } (Either::Left(k), Some(TypeOrConst::Either(v))) => { @@ -221,11 +220,10 @@ impl<'a> PathTransform<'a> { (Either::Left(k), None) => { if let Some(default) = k.default(db, target_module.krate().to_display_target(db)) + && let Some(default) = default.expr() { - if let Some(default) = default.expr() { - const_substs.insert(k, default.syntax().clone_for_update()); - defaulted_params.push(Either::Right(k)); - } + const_substs.insert(k, default.syntax().clone_for_update()); + defaulted_params.push(Either::Right(k)); } } _ => (), // ignore mismatching params @@ -317,32 +315,49 @@ impl Ctx<'_> { } fn transform_path(&self, path: &SyntaxNode) -> SyntaxNode { - fn find_child_paths(root_path: &SyntaxNode) -> Vec<ast::Path> { - let mut result = Vec::new(); + fn find_child_paths_and_ident_pats( + root_path: &SyntaxNode, + ) -> Vec<Either<ast::Path, ast::IdentPat>> { + let mut result: Vec<Either<ast::Path, ast::IdentPat>> = 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<ast::Path, ast::IdentPat>, + ) -> 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() { @@ -377,7 +392,7 @@ impl Ctx<'_> { parent.segment()?.name_ref()?, ) .and_then(|trait_ref| { - let cfg = ImportPathConfig { + let cfg = FindPathConfig { prefer_no_std: false, prefer_prelude: true, prefer_absolute: false, @@ -427,17 +442,17 @@ impl Ctx<'_> { } } hir::PathResolution::Def(def) if def.as_assoc_item(self.source_scope.db).is_none() => { - if let hir::ModuleDef::Trait(_) = def { - if matches!(path.segment()?.kind()?, ast::PathSegmentKind::Type { .. }) { - // `speculative_resolve` resolves segments like `<T as - // Trait>` into `Trait`, but just the trait name should - // not be used as the replacement of the original - // segment. - return None; - } + if let hir::ModuleDef::Trait(_) = def + && matches!(path.segment()?.kind()?, ast::PathSegmentKind::Type { .. }) + { + // `speculative_resolve` resolves segments like `<T as + // Trait>` into `Trait`, but just the trait name should + // not be used as the replacement of the original + // segment. + return None; } - let cfg = ImportPathConfig { + let cfg = FindPathConfig { prefer_no_std: false, prefer_prelude: true, prefer_absolute: false, @@ -446,19 +461,17 @@ impl Ctx<'_> { 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(); let mut res_editor = SyntaxEditor::new(res.syntax().clone_subtree()); - if let Some(args) = path.segment().and_then(|it| it.generic_arg_list()) { - if let Some(segment) = res.segment() { - if let Some(old) = segment.generic_arg_list() { - res_editor.replace( - old.syntax(), - args.clone_subtree().syntax().clone_for_update(), - ) - } else { - res_editor.insert( - syntax_editor::Position::last_child_of(segment.syntax()), - args.clone_subtree().syntax().clone_for_update(), - ); - } + if let Some(args) = path.segment().and_then(|it| it.generic_arg_list()) + && let Some(segment) = res.segment() + { + if let Some(old) = segment.generic_arg_list() { + res_editor + .replace(old.syntax(), args.clone_subtree().syntax().clone_for_update()) + } else { + res_editor.insert( + syntax_editor::Position::last_child_of(segment.syntax()), + args.clone_subtree().syntax().clone_for_update(), + ); } } let res = res_editor.finish().new_root().clone(); @@ -485,27 +498,27 @@ impl Ctx<'_> { .ok()?; let ast_ty = make::ty(ty_str).clone_for_update(); - if let Some(adt) = ty.as_adt() { - if let ast::Type::PathType(path_ty) = &ast_ty { - 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, - ModuleDef::from(adt), - cfg, - )?; - - if let Some(qual) = - mod_path_to_ast(&found_path, self.target_edition).qualifier() - { - let res = make::path_concat(qual, path_ty.path()?).clone_for_update(); - editor.replace(path.syntax(), res.syntax()); - return Some(()); - } + if let Some(adt) = ty.as_adt() + && let ast::Type::PathType(path_ty) = &ast_ty + { + let cfg = FindPathConfig { + 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, + ModuleDef::from(adt), + cfg, + )?; + + if let Some(qual) = + mod_path_to_ast(&found_path, self.target_edition).qualifier() + { + let res = make::path_concat(qual, path_ty.path()?).clone_for_update(); + editor.replace(path.syntax(), res.syntax()); + return Some(()); } } @@ -519,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 = FindPathConfig { + 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 |