diff options
-rw-r--r-- | crates/ra_hir/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/source_analyzer.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 62 |
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 | ||
53 | pub use hir_def::{ | 54 | pub 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 | ||
19 | use crate::{db::HirDatabase, ModuleSource, SourceAnalyzer}; | 19 | use crate::{db::HirDatabase, ModuleSource, SourceAnalyzer}; |
20 | 20 | ||
21 | #[derive(Default)] | 21 | pub struct SourceBinder<'a, DB> { |
22 | pub 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 | ||
26 | impl SourceBinder { | 26 | impl<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 | } |