diff options
Diffstat (limited to 'crates/ra_hir/src/source_binder.rs')
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 111 |
1 files changed, 75 insertions, 36 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 01f51ba5d..66cb4b357 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -12,7 +12,7 @@ use hir_expand::name::AsName; | |||
12 | use ra_db::FileId; | 12 | use ra_db::FileId; |
13 | use ra_syntax::{ | 13 | use ra_syntax::{ |
14 | ast::{self, AstNode}, | 14 | ast::{self, AstNode}, |
15 | AstPtr, | 15 | match_ast, AstPtr, |
16 | SyntaxKind::*, | 16 | SyntaxKind::*, |
17 | SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, | 17 | SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, |
18 | }; | 18 | }; |
@@ -27,9 +27,9 @@ use crate::{ | |||
27 | }, | 27 | }, |
28 | ids::LocationCtx, | 28 | ids::LocationCtx, |
29 | resolve::{ScopeDef, TypeNs, ValueNs}, | 29 | resolve::{ScopeDef, TypeNs, ValueNs}, |
30 | ty::method_resolution::implements_trait, | 30 | ty::method_resolution::{self, implements_trait}, |
31 | Const, DefWithBody, Either, Enum, FromSource, Function, HasBody, HirFileId, MacroDef, Module, | 31 | AssocItem, Const, DefWithBody, Either, Enum, FromSource, Function, HasBody, HirFileId, |
32 | Name, Path, Resolver, Static, Struct, Ty, | 32 | MacroDef, Module, Name, Path, Resolver, Static, Struct, Ty, |
33 | }; | 33 | }; |
34 | 34 | ||
35 | fn try_get_resolver_for_node( | 35 | fn try_get_resolver_for_node( |
@@ -37,24 +37,34 @@ fn try_get_resolver_for_node( | |||
37 | file_id: FileId, | 37 | file_id: FileId, |
38 | node: &SyntaxNode, | 38 | node: &SyntaxNode, |
39 | ) -> Option<Resolver> { | 39 | ) -> Option<Resolver> { |
40 | if let Some(module) = ast::Module::cast(node.clone()) { | 40 | match_ast! { |
41 | let src = crate::Source { file_id: file_id.into(), ast: module }; | 41 | match node { |
42 | Some(crate::Module::from_declaration(db, src)?.resolver(db)) | 42 | ast::Module(it) => { |
43 | } else if let Some(file) = ast::SourceFile::cast(node.clone()) { | 43 | let src = crate::Source { file_id: file_id.into(), ast: it }; |
44 | let src = | 44 | Some(crate::Module::from_declaration(db, src)?.resolver(db)) |
45 | crate::Source { file_id: file_id.into(), ast: crate::ModuleSource::SourceFile(file) }; | 45 | }, |
46 | Some(crate::Module::from_definition(db, src)?.resolver(db)) | 46 | ast::SourceFile(it) => { |
47 | } else if let Some(s) = ast::StructDef::cast(node.clone()) { | 47 | let src = |
48 | let src = crate::Source { file_id: file_id.into(), ast: s }; | 48 | crate::Source { file_id: file_id.into(), ast: crate::ModuleSource::SourceFile(it) }; |
49 | Some(Struct::from_source(db, src)?.resolver(db)) | 49 | Some(crate::Module::from_definition(db, src)?.resolver(db)) |
50 | } else if let Some(e) = ast::EnumDef::cast(node.clone()) { | 50 | }, |
51 | let src = crate::Source { file_id: file_id.into(), ast: e }; | 51 | ast::StructDef(it) => { |
52 | Some(Enum::from_source(db, src)?.resolver(db)) | 52 | let src = crate::Source { file_id: file_id.into(), ast: it }; |
53 | } else if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF { | 53 | Some(Struct::from_source(db, src)?.resolver(db)) |
54 | Some(def_with_body_from_child_node(db, file_id, node)?.resolver(db)) | 54 | }, |
55 | } else { | 55 | ast::EnumDef(it) => { |
56 | // FIXME add missing cases | 56 | let src = crate::Source { file_id: file_id.into(), ast: it }; |
57 | None | 57 | Some(Enum::from_source(db, src)?.resolver(db)) |
58 | }, | ||
59 | _ => { | ||
60 | if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF { | ||
61 | Some(def_with_body_from_child_node(db, file_id, node)?.resolver(db)) | ||
62 | } else { | ||
63 | // FIXME add missing cases | ||
64 | None | ||
65 | } | ||
66 | }, | ||
67 | } | ||
58 | } | 68 | } |
59 | } | 69 | } |
60 | 70 | ||
@@ -68,16 +78,14 @@ fn def_with_body_from_child_node( | |||
68 | let ctx = LocationCtx::new(db, module.id, file_id.into()); | 78 | let ctx = LocationCtx::new(db, module.id, file_id.into()); |
69 | 79 | ||
70 | node.ancestors().find_map(|node| { | 80 | node.ancestors().find_map(|node| { |
71 | if let Some(def) = ast::FnDef::cast(node.clone()) { | 81 | match_ast! { |
72 | return Some(Function { id: ctx.to_def(&def) }.into()); | 82 | match node { |
73 | } | 83 | ast::FnDef(def) => { Some(Function {id: ctx.to_def(&def) }.into()) }, |
74 | if let Some(def) = ast::ConstDef::cast(node.clone()) { | 84 | ast::ConstDef(def) => { Some(Const { id: ctx.to_def(&def) }.into()) }, |
75 | return Some(Const { id: ctx.to_def(&def) }.into()); | 85 | ast::StaticDef(def) => { Some(Static { id: ctx.to_def(&def) }.into()) }, |
76 | } | 86 | _ => { None }, |
77 | if let Some(def) = ast::StaticDef::cast(node) { | 87 | } |
78 | return Some(Static { id: ctx.to_def(&def) }.into()); | ||
79 | } | 88 | } |
80 | None | ||
81 | }) | 89 | }) |
82 | } | 90 | } |
83 | 91 | ||
@@ -245,9 +253,14 @@ impl SourceAnalyzer { | |||
245 | Some(res) | 253 | Some(res) |
246 | }); | 254 | }); |
247 | 255 | ||
248 | let items = | 256 | let items = self |
249 | self.resolver.resolve_module_path(db, &path).take_types().map(PathResolution::Def); | 257 | .resolver |
250 | types.or(values).or(items) | 258 | .resolve_module_path(db, &path) |
259 | .take_types() | ||
260 | .map(|it| PathResolution::Def(it.into())); | ||
261 | types.or(values).or(items).or_else(|| { | ||
262 | self.resolver.resolve_path_as_macro(db, &path).map(|def| PathResolution::Macro(def)) | ||
263 | }) | ||
251 | } | 264 | } |
252 | 265 | ||
253 | pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option<PathResolution> { | 266 | pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option<PathResolution> { |
@@ -317,16 +330,42 @@ impl SourceAnalyzer { | |||
317 | db: &impl HirDatabase, | 330 | db: &impl HirDatabase, |
318 | ty: Ty, | 331 | ty: Ty, |
319 | name: Option<&Name>, | 332 | name: Option<&Name>, |
320 | callback: impl FnMut(&Ty, Function) -> Option<T>, | 333 | mut callback: impl FnMut(&Ty, Function) -> Option<T>, |
334 | ) -> Option<T> { | ||
335 | // There should be no inference vars in types passed here | ||
336 | // FIXME check that? | ||
337 | // FIXME replace Unknown by bound vars here | ||
338 | let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; | ||
339 | method_resolution::iterate_method_candidates( | ||
340 | &canonical, | ||
341 | db, | ||
342 | &self.resolver, | ||
343 | name, | ||
344 | method_resolution::LookupMode::MethodCall, | ||
345 | |ty, it| match it { | ||
346 | AssocItem::Function(f) => callback(ty, f), | ||
347 | _ => None, | ||
348 | }, | ||
349 | ) | ||
350 | } | ||
351 | |||
352 | pub fn iterate_path_candidates<T>( | ||
353 | &self, | ||
354 | db: &impl HirDatabase, | ||
355 | ty: Ty, | ||
356 | name: Option<&Name>, | ||
357 | callback: impl FnMut(&Ty, AssocItem) -> Option<T>, | ||
321 | ) -> Option<T> { | 358 | ) -> Option<T> { |
322 | // There should be no inference vars in types passed here | 359 | // There should be no inference vars in types passed here |
323 | // FIXME check that? | 360 | // FIXME check that? |
361 | // FIXME replace Unknown by bound vars here | ||
324 | let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; | 362 | let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; |
325 | crate::ty::method_resolution::iterate_method_candidates( | 363 | method_resolution::iterate_method_candidates( |
326 | &canonical, | 364 | &canonical, |
327 | db, | 365 | db, |
328 | &self.resolver, | 366 | &self.resolver, |
329 | name, | 367 | name, |
368 | method_resolution::LookupMode::Path, | ||
330 | callback, | 369 | callback, |
331 | ) | 370 | ) |
332 | } | 371 | } |