From 3100de842b3cc33c9ad364f10c7f740ac760f564 Mon Sep 17 00:00:00 2001 From: David Lattimore Date: Wed, 5 Aug 2020 19:48:52 +1000 Subject: Structured search replace now handles UFCS calls to trait methods --- crates/ra_ssr/src/resolving.rs | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) (limited to 'crates/ra_ssr/src/resolving.rs') diff --git a/crates/ra_ssr/src/resolving.rs b/crates/ra_ssr/src/resolving.rs index 7e7585c8b..bfc20705b 100644 --- a/crates/ra_ssr/src/resolving.rs +++ b/crates/ra_ssr/src/resolving.rs @@ -25,7 +25,7 @@ pub(crate) struct ResolvedPattern { pub(crate) node: SyntaxNode, // Paths in `node` that we've resolved. pub(crate) resolved_paths: FxHashMap, - pub(crate) ufcs_function_calls: FxHashMap, + pub(crate) ufcs_function_calls: FxHashMap, pub(crate) contains_self: bool, } @@ -35,6 +35,12 @@ pub(crate) struct ResolvedPath { pub(crate) depth: u32, } +pub(crate) struct UfcsCallInfo { + pub(crate) call_expr: ast::CallExpr, + pub(crate) function: hir::Function, + pub(crate) qualifier_type: Option, +} + impl ResolvedRule { pub(crate) fn new( rule: parsing::ParsedRule, @@ -70,6 +76,7 @@ struct Resolver<'a, 'db> { impl Resolver<'_, '_> { fn resolve_pattern_tree(&self, pattern: SyntaxNode) -> Result { + use syntax::ast::AstNode; use syntax::{SyntaxElement, T}; let mut resolved_paths = FxHashMap::default(); self.resolve(pattern.clone(), 0, &mut resolved_paths)?; @@ -77,11 +84,15 @@ impl Resolver<'_, '_> { .iter() .filter_map(|(path_node, resolved)| { if let Some(grandparent) = path_node.parent().and_then(|parent| parent.parent()) { - if grandparent.kind() == SyntaxKind::CALL_EXPR { + if let Some(call_expr) = ast::CallExpr::cast(grandparent.clone()) { if let hir::PathResolution::AssocItem(hir::AssocItem::Function(function)) = - &resolved.resolution + resolved.resolution { - return Some((grandparent, *function)); + let qualifier_type = self.resolution_scope.qualifier_type(path_node); + return Some(( + grandparent, + UfcsCallInfo { call_expr, function, qualifier_type }, + )); } } } @@ -226,6 +237,20 @@ impl<'db> ResolutionScope<'db> { None } } + + fn qualifier_type(&self, path: &SyntaxNode) -> Option { + use syntax::ast::AstNode; + if let Some(path) = ast::Path::cast(path.clone()) { + if let Some(qualifier) = path.qualifier() { + if let Some(resolved_qualifier) = self.resolve_path(&qualifier) { + if let hir::PathResolution::Def(hir::ModuleDef::Adt(adt)) = resolved_qualifier { + return Some(adt.ty(self.scope.db)); + } + } + } + } + None + } } fn is_self(path: &ast::Path) -> bool { -- cgit v1.2.3