aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/from_source.rs59
-rw-r--r--crates/ra_hir/src/source_binder.rs73
-rw-r--r--crates/ra_ide/src/references/classify.rs4
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
4use hir_def::{ 4use hir_def::{nameres::ModuleSource, ModuleId};
5 child_by_source::ChildBySource, keys, nameres::ModuleSource, GenericDefId, ModuleId,
6};
7use hir_expand::name::AsName; 5use hir_expand::name::AsName;
8use ra_db::FileId; 6use ra_db::FileId;
9use ra_prof::profile; 7use ra_prof::profile;
10use ra_syntax::{ 8use ra_syntax::ast::{self, AstNode, NameOwner};
11 ast::{self, AstNode, NameOwner},
12 match_ast,
13};
14 9
15use crate::{ 10use crate::{db::DefDatabase, InFile, Module};
16 db::{DefDatabase, HirDatabase},
17 DefWithBody, InFile, Local, Module, SourceBinder, TypeParam,
18};
19
20impl 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
42impl 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
65impl Module { 12impl 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};
14use hir_expand::{AstId, InFile, MacroDefId, MacroDefKind}; 14use hir_expand::{AstId, InFile, MacroDefId, MacroDefKind};
15use ra_prof::profile; 15use ra_prof::profile;
16use ra_syntax::{ast, match_ast, AstNode, SyntaxNode, TextUnit}; 16use ra_syntax::{ast, match_ast, AstNode, SyntaxNode, TextUnit};
17use rustc_hash::FxHashMap; 17use rustc_hash::FxHashMap;
18 18
19use crate::{db::HirDatabase, ModuleSource, SourceAnalyzer}; 19use crate::{db::HirDatabase, Local, ModuleSource, SourceAnalyzer, TypeParam};
20 20
21pub struct SourceBinder<'a, DB> { 21pub 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
113pub trait ToId: Sized + AstNode + 'static { 112pub 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
119pub trait ToDef: ToId { 118pub 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
123macro_rules! to_def_impls { 126macro_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
240impl 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
263impl 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),