diff options
-rw-r--r-- | crates/ra_hir/src/from_source.rs | 59 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 73 | ||||
-rw-r--r-- | crates/ra_ide/src/references/classify.rs | 4 |
3 files changed, 70 insertions, 66 deletions
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index caaff012a..c766c3f0b 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs | |||
@@ -1,66 +1,13 @@ | |||
1 | //! Finds a corresponding hir data structure for a syntax node in a specific | 1 | //! Finds a corresponding hir data structure for a syntax node in a specific |
2 | //! file. | 2 | //! file. |
3 | 3 | ||
4 | use hir_def::{ | 4 | use hir_def::{nameres::ModuleSource, ModuleId}; |
5 | child_by_source::ChildBySource, keys, nameres::ModuleSource, GenericDefId, ModuleId, | ||
6 | }; | ||
7 | use hir_expand::name::AsName; | 5 | use hir_expand::name::AsName; |
8 | use ra_db::FileId; | 6 | use ra_db::FileId; |
9 | use ra_prof::profile; | 7 | use ra_prof::profile; |
10 | use ra_syntax::{ | 8 | use ra_syntax::ast::{self, AstNode, NameOwner}; |
11 | ast::{self, AstNode, NameOwner}, | ||
12 | match_ast, | ||
13 | }; | ||
14 | 9 | ||
15 | use crate::{ | 10 | use crate::{db::DefDatabase, InFile, Module}; |
16 | db::{DefDatabase, HirDatabase}, | ||
17 | DefWithBody, InFile, Local, Module, SourceBinder, TypeParam, | ||
18 | }; | ||
19 | |||
20 | impl Local { | ||
21 | pub fn from_source(db: &impl HirDatabase, src: InFile<ast::BindPat>) -> Option<Self> { | ||
22 | let mut sb = SourceBinder::new(db); | ||
23 | let file_id = src.file_id; | ||
24 | let parent: DefWithBody = src.value.syntax().ancestors().find_map(|it| { | ||
25 | let res = match_ast! { | ||
26 | match it { | ||
27 | ast::ConstDef(value) => { sb.to_def(InFile { value, file_id})?.into() }, | ||
28 | ast::StaticDef(value) => { sb.to_def(InFile { value, file_id})?.into() }, | ||
29 | ast::FnDef(value) => { sb.to_def(InFile { value, file_id})?.into() }, | ||
30 | _ => return None, | ||
31 | } | ||
32 | }; | ||
33 | Some(res) | ||
34 | })?; | ||
35 | let (_body, source_map) = db.body_with_source_map(parent.into()); | ||
36 | let src = src.map(ast::Pat::from); | ||
37 | let pat_id = source_map.node_pat(src.as_ref())?; | ||
38 | Some(Local { parent, pat_id }) | ||
39 | } | ||
40 | } | ||
41 | |||
42 | impl TypeParam { | ||
43 | pub fn from_source(db: &impl HirDatabase, src: InFile<ast::TypeParam>) -> Option<Self> { | ||
44 | let mut sb = SourceBinder::new(db); | ||
45 | let file_id = src.file_id; | ||
46 | let parent: GenericDefId = src.value.syntax().ancestors().find_map(|it| { | ||
47 | let res = match_ast! { | ||
48 | match it { | ||
49 | ast::FnDef(value) => { sb.to_def(InFile { value, file_id})?.id.into() }, | ||
50 | ast::StructDef(value) => { sb.to_def(InFile { value, file_id})?.id.into() }, | ||
51 | ast::EnumDef(value) => { sb.to_def(InFile { value, file_id})?.id.into() }, | ||
52 | ast::TraitDef(value) => { sb.to_def(InFile { value, file_id})?.id.into() }, | ||
53 | ast::TypeAliasDef(value) => { sb.to_def(InFile { value, file_id})?.id.into() }, | ||
54 | ast::ImplBlock(value) => { sb.to_def(InFile { value, file_id})?.id.into() }, | ||
55 | _ => return None, | ||
56 | } | ||
57 | }; | ||
58 | Some(res) | ||
59 | })?; | ||
60 | let &id = parent.child_by_source(db)[keys::TYPE_PARAM].get(&src)?; | ||
61 | Some(TypeParam { id }) | ||
62 | } | ||
63 | } | ||
64 | 11 | ||
65 | impl Module { | 12 | impl Module { |
66 | pub fn from_declaration(db: &impl DefDatabase, src: InFile<ast::Module>) -> Option<Self> { | 13 | pub fn from_declaration(db: &impl DefDatabase, src: InFile<ast::Module>) -> Option<Self> { |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index c02175c06..97e3aef34 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -8,15 +8,15 @@ use hir_def::{ | |||
8 | dyn_map::DynMap, | 8 | dyn_map::DynMap, |
9 | keys::{self, Key}, | 9 | keys::{self, Key}, |
10 | resolver::{HasResolver, Resolver}, | 10 | resolver::{HasResolver, Resolver}, |
11 | ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, ImplId, ModuleId, StaticId, | 11 | ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, |
12 | StructFieldId, StructId, TraitId, TypeAliasId, UnionId, VariantId, | 12 | StaticId, StructFieldId, StructId, TraitId, TypeAliasId, UnionId, VariantId, |
13 | }; | 13 | }; |
14 | use hir_expand::{AstId, InFile, MacroDefId, MacroDefKind}; | 14 | use hir_expand::{AstId, InFile, MacroDefId, MacroDefKind}; |
15 | use ra_prof::profile; | 15 | use ra_prof::profile; |
16 | use ra_syntax::{ast, match_ast, AstNode, SyntaxNode, TextUnit}; | 16 | use ra_syntax::{ast, match_ast, AstNode, SyntaxNode, TextUnit}; |
17 | use rustc_hash::FxHashMap; | 17 | use rustc_hash::FxHashMap; |
18 | 18 | ||
19 | use crate::{db::HirDatabase, ModuleSource, SourceAnalyzer}; | 19 | use crate::{db::HirDatabase, Local, ModuleSource, SourceAnalyzer, TypeParam}; |
20 | 20 | ||
21 | pub struct SourceBinder<'a, DB> { | 21 | pub struct SourceBinder<'a, DB> { |
22 | pub db: &'a DB, | 22 | pub db: &'a DB, |
@@ -53,8 +53,7 @@ impl<DB: HirDatabase> SourceBinder<'_, DB> { | |||
53 | } | 53 | } |
54 | 54 | ||
55 | pub fn to_def<T: ToDef>(&mut self, src: InFile<T>) -> Option<T::Def> { | 55 | pub fn to_def<T: ToDef>(&mut self, src: InFile<T>) -> Option<T::Def> { |
56 | let id: T::ID = self.to_id(src)?; | 56 | T::to_def(self, src) |
57 | Some(id.into()) | ||
58 | } | 57 | } |
59 | 58 | ||
60 | fn to_id<T: ToId>(&mut self, src: InFile<T>) -> Option<T::ID> { | 59 | fn to_id<T: ToId>(&mut self, src: InFile<T>) -> Option<T::ID> { |
@@ -110,20 +109,27 @@ impl<DB: HirDatabase> SourceBinder<'_, DB> { | |||
110 | } | 109 | } |
111 | } | 110 | } |
112 | 111 | ||
113 | pub trait ToId: Sized + AstNode + 'static { | 112 | pub trait ToId: Sized { |
114 | type ID: Sized + Copy + 'static; | 113 | type ID: Sized + Copy + 'static; |
115 | fn to_id<DB: HirDatabase>(sb: &mut SourceBinder<'_, DB>, src: InFile<Self>) | 114 | fn to_id<DB: HirDatabase>(sb: &mut SourceBinder<'_, DB>, src: InFile<Self>) |
116 | -> Option<Self::ID>; | 115 | -> Option<Self::ID>; |
117 | } | 116 | } |
118 | 117 | ||
119 | pub trait ToDef: ToId { | 118 | pub trait ToDef: Sized + AstNode + 'static { |
120 | type Def: From<Self::ID>; | 119 | type Def; |
120 | fn to_def<DB: HirDatabase>( | ||
121 | sb: &mut SourceBinder<'_, DB>, | ||
122 | src: InFile<Self>, | ||
123 | ) -> Option<Self::Def>; | ||
121 | } | 124 | } |
122 | 125 | ||
123 | macro_rules! to_def_impls { | 126 | macro_rules! to_def_impls { |
124 | ($(($def:path, $ast:path)),* ,) => {$( | 127 | ($(($def:path, $ast:path)),* ,) => {$( |
125 | impl ToDef for $ast { | 128 | impl ToDef for $ast { |
126 | type Def = $def; | 129 | type Def = $def; |
130 | fn to_def<DB: HirDatabase>(sb: &mut SourceBinder<'_, DB>, src: InFile<Self>) | ||
131 | -> Option<Self::Def> | ||
132 | { sb.to_id(src).map(Into::into) } | ||
127 | } | 133 | } |
128 | )*} | 134 | )*} |
129 | } | 135 | } |
@@ -230,3 +236,54 @@ impl ToId for ast::MacroCall { | |||
230 | Some(MacroDefId { krate, ast_id, kind }) | 236 | Some(MacroDefId { krate, ast_id, kind }) |
231 | } | 237 | } |
232 | } | 238 | } |
239 | |||
240 | impl ToDef for ast::BindPat { | ||
241 | type Def = Local; | ||
242 | |||
243 | fn to_def<DB: HirDatabase>(sb: &mut SourceBinder<'_, DB>, src: InFile<Self>) -> Option<Local> { | ||
244 | let file_id = src.file_id; | ||
245 | let parent: DefWithBodyId = src.value.syntax().ancestors().find_map(|it| { | ||
246 | let res = match_ast! { | ||
247 | match it { | ||
248 | ast::ConstDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | ||
249 | ast::StaticDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | ||
250 | ast::FnDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | ||
251 | _ => return None, | ||
252 | } | ||
253 | }; | ||
254 | Some(res) | ||
255 | })?; | ||
256 | let (_body, source_map) = sb.db.body_with_source_map(parent); | ||
257 | let src = src.map(ast::Pat::from); | ||
258 | let pat_id = source_map.node_pat(src.as_ref())?; | ||
259 | Some(Local { parent: parent.into(), pat_id }) | ||
260 | } | ||
261 | } | ||
262 | |||
263 | impl ToDef for ast::TypeParam { | ||
264 | type Def = TypeParam; | ||
265 | |||
266 | fn to_def<DB: HirDatabase>( | ||
267 | sb: &mut SourceBinder<'_, DB>, | ||
268 | src: InFile<ast::TypeParam>, | ||
269 | ) -> Option<TypeParam> { | ||
270 | let mut sb = SourceBinder::new(sb.db); | ||
271 | let file_id = src.file_id; | ||
272 | let parent: GenericDefId = src.value.syntax().ancestors().find_map(|it| { | ||
273 | let res = match_ast! { | ||
274 | match it { | ||
275 | ast::FnDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | ||
276 | ast::StructDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | ||
277 | ast::EnumDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | ||
278 | ast::TraitDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | ||
279 | ast::TypeAliasDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | ||
280 | ast::ImplBlock(value) => { sb.to_id(InFile { value, file_id})?.into() }, | ||
281 | _ => return None, | ||
282 | } | ||
283 | }; | ||
284 | Some(res) | ||
285 | })?; | ||
286 | let &id = parent.child_by_source(sb.db)[keys::TYPE_PARAM].get(&src)?; | ||
287 | Some(TypeParam { id }) | ||
288 | } | ||
289 | } | ||
diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs index dcffc3df2..82a18a0a5 100644 --- a/crates/ra_ide/src/references/classify.rs +++ b/crates/ra_ide/src/references/classify.rs | |||
@@ -22,7 +22,7 @@ pub(crate) fn classify_name( | |||
22 | match parent { | 22 | match parent { |
23 | ast::BindPat(it) => { | 23 | ast::BindPat(it) => { |
24 | let src = name.with_value(it); | 24 | let src = name.with_value(it); |
25 | let local = hir::Local::from_source(sb.db, src)?; | 25 | let local = sb.to_def(src)?; |
26 | Some(NameDefinition { | 26 | Some(NameDefinition { |
27 | visibility: None, | 27 | visibility: None, |
28 | container: local.module(sb.db), | 28 | container: local.module(sb.db), |
@@ -114,7 +114,7 @@ pub(crate) fn classify_name( | |||
114 | }, | 114 | }, |
115 | ast::TypeParam(it) => { | 115 | ast::TypeParam(it) => { |
116 | let src = name.with_value(it); | 116 | let src = name.with_value(it); |
117 | let def = hir::TypeParam::from_source(sb.db, src)?; | 117 | let def = sb.to_def(src)?; |
118 | Some(NameDefinition { | 118 | Some(NameDefinition { |
119 | visibility: None, | 119 | visibility: None, |
120 | container: def.module(sb.db), | 120 | container: def.module(sb.db), |