diff options
Diffstat (limited to 'crates/ra_ssr/src/resolving.rs')
-rw-r--r-- | crates/ra_ssr/src/resolving.rs | 33 |
1 files changed, 29 insertions, 4 deletions
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 { | |||
25 | pub(crate) node: SyntaxNode, | 25 | pub(crate) node: SyntaxNode, |
26 | // Paths in `node` that we've resolved. | 26 | // Paths in `node` that we've resolved. |
27 | pub(crate) resolved_paths: FxHashMap<SyntaxNode, ResolvedPath>, | 27 | pub(crate) resolved_paths: FxHashMap<SyntaxNode, ResolvedPath>, |
28 | pub(crate) ufcs_function_calls: FxHashMap<SyntaxNode, hir::Function>, | 28 | pub(crate) ufcs_function_calls: FxHashMap<SyntaxNode, UfcsCallInfo>, |
29 | pub(crate) contains_self: bool, | 29 | pub(crate) contains_self: bool, |
30 | } | 30 | } |
31 | 31 | ||
@@ -35,6 +35,12 @@ pub(crate) struct ResolvedPath { | |||
35 | pub(crate) depth: u32, | 35 | pub(crate) depth: u32, |
36 | } | 36 | } |
37 | 37 | ||
38 | pub(crate) struct UfcsCallInfo { | ||
39 | pub(crate) call_expr: ast::CallExpr, | ||
40 | pub(crate) function: hir::Function, | ||
41 | pub(crate) qualifier_type: Option<hir::Type>, | ||
42 | } | ||
43 | |||
38 | impl ResolvedRule { | 44 | impl ResolvedRule { |
39 | pub(crate) fn new( | 45 | pub(crate) fn new( |
40 | rule: parsing::ParsedRule, | 46 | rule: parsing::ParsedRule, |
@@ -70,6 +76,7 @@ struct Resolver<'a, 'db> { | |||
70 | 76 | ||
71 | impl Resolver<'_, '_> { | 77 | impl Resolver<'_, '_> { |
72 | fn resolve_pattern_tree(&self, pattern: SyntaxNode) -> Result<ResolvedPattern, SsrError> { | 78 | fn resolve_pattern_tree(&self, pattern: SyntaxNode) -> Result<ResolvedPattern, SsrError> { |
79 | use syntax::ast::AstNode; | ||
73 | use syntax::{SyntaxElement, T}; | 80 | use syntax::{SyntaxElement, T}; |
74 | let mut resolved_paths = FxHashMap::default(); | 81 | let mut resolved_paths = FxHashMap::default(); |
75 | self.resolve(pattern.clone(), 0, &mut resolved_paths)?; | 82 | self.resolve(pattern.clone(), 0, &mut resolved_paths)?; |
@@ -77,11 +84,15 @@ impl Resolver<'_, '_> { | |||
77 | .iter() | 84 | .iter() |
78 | .filter_map(|(path_node, resolved)| { | 85 | .filter_map(|(path_node, resolved)| { |
79 | if let Some(grandparent) = path_node.parent().and_then(|parent| parent.parent()) { | 86 | if let Some(grandparent) = path_node.parent().and_then(|parent| parent.parent()) { |
80 | if grandparent.kind() == SyntaxKind::CALL_EXPR { | 87 | if let Some(call_expr) = ast::CallExpr::cast(grandparent.clone()) { |
81 | if let hir::PathResolution::AssocItem(hir::AssocItem::Function(function)) = | 88 | if let hir::PathResolution::AssocItem(hir::AssocItem::Function(function)) = |
82 | &resolved.resolution | 89 | resolved.resolution |
83 | { | 90 | { |
84 | return Some((grandparent, *function)); | 91 | let qualifier_type = self.resolution_scope.qualifier_type(path_node); |
92 | return Some(( | ||
93 | grandparent, | ||
94 | UfcsCallInfo { call_expr, function, qualifier_type }, | ||
95 | )); | ||
85 | } | 96 | } |
86 | } | 97 | } |
87 | } | 98 | } |
@@ -226,6 +237,20 @@ impl<'db> ResolutionScope<'db> { | |||
226 | None | 237 | None |
227 | } | 238 | } |
228 | } | 239 | } |
240 | |||
241 | fn qualifier_type(&self, path: &SyntaxNode) -> Option<hir::Type> { | ||
242 | use syntax::ast::AstNode; | ||
243 | if let Some(path) = ast::Path::cast(path.clone()) { | ||
244 | if let Some(qualifier) = path.qualifier() { | ||
245 | if let Some(resolved_qualifier) = self.resolve_path(&qualifier) { | ||
246 | if let hir::PathResolution::Def(hir::ModuleDef::Adt(adt)) = resolved_qualifier { | ||
247 | return Some(adt.ty(self.scope.db)); | ||
248 | } | ||
249 | } | ||
250 | } | ||
251 | } | ||
252 | None | ||
253 | } | ||
229 | } | 254 | } |
230 | 255 | ||
231 | fn is_self(path: &ast::Path) -> bool { | 256 | fn is_self(path: &ast::Path) -> bool { |