aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/lib.rs1
-rw-r--r--crates/ra_hir/src/source_analyzer.rs2
-rw-r--r--crates/ra_hir/src/source_binder.rs62
3 files changed, 33 insertions, 32 deletions
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index a953eabc7..a2350573c 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -48,6 +48,7 @@ pub use crate::{
48 from_source::FromSource, 48 from_source::FromSource,
49 has_source::HasSource, 49 has_source::HasSource,
50 source_analyzer::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, 50 source_analyzer::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
51 source_binder::SourceBinder,
51}; 52};
52 53
53pub use hir_def::{ 54pub use hir_def::{
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index 90bc93999..186dd2411 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -105,7 +105,7 @@ impl SourceAnalyzer {
105 node: InFile<&SyntaxNode>, 105 node: InFile<&SyntaxNode>,
106 offset: Option<TextUnit>, 106 offset: Option<TextUnit>,
107 ) -> SourceAnalyzer { 107 ) -> SourceAnalyzer {
108 crate::source_binder::SourceBinder::default().analyze(db, node, offset) 108 crate::source_binder::SourceBinder::new(db).analyze(node, offset)
109 } 109 }
110 110
111 pub(crate) fn new_for_body( 111 pub(crate) fn new_for_body(
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index cec3f8c2c..8f002d2ee 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -18,48 +18,52 @@ use rustc_hash::FxHashMap;
18 18
19use crate::{db::HirDatabase, ModuleSource, SourceAnalyzer}; 19use crate::{db::HirDatabase, ModuleSource, SourceAnalyzer};
20 20
21#[derive(Default)] 21pub struct SourceBinder<'a, DB> {
22pub struct SourceBinder { 22 pub db: &'a DB,
23 child_by_source_cache: FxHashMap<ChildContainer, DynMap>, 23 child_by_source_cache: FxHashMap<ChildContainer, DynMap>,
24} 24}
25 25
26impl SourceBinder { 26impl<DB: HirDatabase> SourceBinder<'_, DB> {
27 pub fn new(db: &DB) -> SourceBinder<DB> {
28 SourceBinder { db, child_by_source_cache: FxHashMap::default() }
29 }
30
27 pub fn analyze( 31 pub fn analyze(
28 &mut self, 32 &mut self,
29 db: &impl HirDatabase,
30 src: InFile<&SyntaxNode>, 33 src: InFile<&SyntaxNode>,
31 offset: Option<TextUnit>, 34 offset: Option<TextUnit>,
32 ) -> SourceAnalyzer { 35 ) -> SourceAnalyzer {
33 let _p = profile("SourceBinder::analyzer"); 36 let _p = profile("SourceBinder::analyzer");
34 let container = match self.find_container(db, src) { 37 let container = match self.find_container(src) {
35 Some(it) => it, 38 Some(it) => it,
36 None => return SourceAnalyzer::new_for_resolver(Resolver::default(), src), 39 None => return SourceAnalyzer::new_for_resolver(Resolver::default(), src),
37 }; 40 };
38 41
39 let resolver = match container { 42 let resolver = match container {
40 ChildContainer::DefWithBodyId(def) => { 43 ChildContainer::DefWithBodyId(def) => {
41 return SourceAnalyzer::new_for_body(db, def, src, offset) 44 return SourceAnalyzer::new_for_body(self.db, def, src, offset)
42 } 45 }
43 ChildContainer::TraitId(it) => it.resolver(db), 46 ChildContainer::TraitId(it) => it.resolver(self.db),
44 ChildContainer::ImplId(it) => it.resolver(db), 47 ChildContainer::ImplId(it) => it.resolver(self.db),
45 ChildContainer::ModuleId(it) => it.resolver(db), 48 ChildContainer::ModuleId(it) => it.resolver(self.db),
46 ChildContainer::EnumId(it) => it.resolver(db), 49 ChildContainer::EnumId(it) => it.resolver(self.db),
47 ChildContainer::VariantId(it) => it.resolver(db), 50 ChildContainer::VariantId(it) => it.resolver(self.db),
48 }; 51 };
49 SourceAnalyzer::new_for_resolver(resolver, src) 52 SourceAnalyzer::new_for_resolver(resolver, src)
50 } 53 }
51 54
52 pub fn to_def<D, ID>(&mut self, db: &impl HirDatabase, src: InFile<ID::Ast>) -> Option<D> 55 pub fn to_def<D, ID>(&mut self, src: InFile<ID::Ast>) -> Option<D>
53 where 56 where
54 D: From<ID>, 57 D: From<ID>,
55 ID: ToId, 58 ID: ToId,
56 { 59 {
57 let id: ID = self.to_id(db, src)?; 60 let id: ID = self.to_id(src)?;
58 Some(id.into()) 61 Some(id.into())
59 } 62 }
60 63
61 fn to_id<D: ToId>(&mut self, db: &impl HirDatabase, src: InFile<D::Ast>) -> Option<D> { 64 fn to_id<D: ToId>(&mut self, src: InFile<D::Ast>) -> Option<D> {
62 let container = self.find_container(db, src.as_ref().map(|it| it.syntax()))?; 65 let container = self.find_container(src.as_ref().map(|it| it.syntax()))?;
66 let db = self.db;
63 let dyn_map = 67 let dyn_map =
64 &*self.child_by_source_cache.entry(container).or_insert_with(|| match container { 68 &*self.child_by_source_cache.entry(container).or_insert_with(|| match container {
65 ChildContainer::DefWithBodyId(it) => it.child_by_source(db), 69 ChildContainer::DefWithBodyId(it) => it.child_by_source(db),
@@ -72,44 +76,40 @@ impl SourceBinder {
72 dyn_map[D::KEY].get(&src).copied() 76 dyn_map[D::KEY].get(&src).copied()
73 } 77 }
74 78
75 fn find_container( 79 fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> {
76 &mut self, 80 for container in src.cloned().ancestors_with_macros(self.db).skip(1) {
77 db: &impl HirDatabase,
78 src: InFile<&SyntaxNode>,
79 ) -> Option<ChildContainer> {
80 for container in src.cloned().ancestors_with_macros(db).skip(1) {
81 let res: ChildContainer = match_ast! { 81 let res: ChildContainer = match_ast! {
82 match (container.value) { 82 match (container.value) {
83 ast::TraitDef(it) => { 83 ast::TraitDef(it) => {
84 let def: TraitId = self.to_id(db, container.with_value(it))?; 84 let def: TraitId = self.to_id(container.with_value(it))?;
85 def.into() 85 def.into()
86 }, 86 },
87 ast::ImplBlock(it) => { 87 ast::ImplBlock(it) => {
88 let def: ImplId = self.to_id(db, container.with_value(it))?; 88 let def: ImplId = self.to_id(container.with_value(it))?;
89 def.into() 89 def.into()
90 }, 90 },
91 ast::FnDef(it) => { 91 ast::FnDef(it) => {
92 let def: FunctionId = self.to_id(db, container.with_value(it))?; 92 let def: FunctionId = self.to_id(container.with_value(it))?;
93 DefWithBodyId::from(def).into() 93 DefWithBodyId::from(def).into()
94 }, 94 },
95 ast::StaticDef(it) => { 95 ast::StaticDef(it) => {
96 let def: StaticId = self.to_id(db, container.with_value(it))?; 96 let def: StaticId = self.to_id(container.with_value(it))?;
97 DefWithBodyId::from(def).into() 97 DefWithBodyId::from(def).into()
98 }, 98 },
99 ast::ConstDef(it) => { 99 ast::ConstDef(it) => {
100 let def: ConstId = self.to_id(db, container.with_value(it))?; 100 let def: ConstId = self.to_id(container.with_value(it))?;
101 DefWithBodyId::from(def).into() 101 DefWithBodyId::from(def).into()
102 }, 102 },
103 ast::EnumDef(it) => { 103 ast::EnumDef(it) => {
104 let def: EnumId = self.to_id(db, container.with_value(it))?; 104 let def: EnumId = self.to_id(container.with_value(it))?;
105 def.into() 105 def.into()
106 }, 106 },
107 ast::StructDef(it) => { 107 ast::StructDef(it) => {
108 let def: StructId = self.to_id(db, container.with_value(it))?; 108 let def: StructId = self.to_id(container.with_value(it))?;
109 VariantId::from(def).into() 109 VariantId::from(def).into()
110 }, 110 },
111 ast::UnionDef(it) => { 111 ast::UnionDef(it) => {
112 let def: UnionId = self.to_id(db, container.with_value(it))?; 112 let def: UnionId = self.to_id(container.with_value(it))?;
113 VariantId::from(def).into() 113 VariantId::from(def).into()
114 }, 114 },
115 // FIXME: handle out-of-line modules here 115 // FIXME: handle out-of-line modules here
@@ -119,8 +119,8 @@ impl SourceBinder {
119 return Some(res); 119 return Some(res);
120 } 120 }
121 121
122 let module_source = ModuleSource::from_child_node(db, src); 122 let module_source = ModuleSource::from_child_node(self.db, src);
123 let c = crate::Module::from_definition(db, src.with_value(module_source))?; 123 let c = crate::Module::from_definition(self.db, src.with_value(module_source))?;
124 Some(c.id.into()) 124 Some(c.id.into())
125 } 125 }
126} 126}