aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/source_binder.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/source_binder.rs')
-rw-r--r--crates/ra_hir/src/source_binder.rs111
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;
12use ra_db::FileId; 12use ra_db::FileId;
13use ra_syntax::{ 13use 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
35fn try_get_resolver_for_node( 35fn 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 }