@@ -8,15 +8,15 @@ use hir_def::{
88 dyn_map::DynMap,
99 keys::{self, Key},
1010 resolver::{HasResolver, Resolver},
11- ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, ImplId, ModuleId, StaticId ,
12- StructFieldId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
11+ ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId ,
12+ StaticId, StructFieldId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
1313};
1414use hir_expand::{AstId, InFile, MacroDefId, MacroDefKind};
1515use ra_prof::profile;
1616use ra_syntax::{ast, match_ast, AstNode, SyntaxNode, TextUnit};
1717use rustc_hash::FxHashMap;
1818
19- use crate::{db::HirDatabase, ModuleSource, SourceAnalyzer};
19+ use crate::{db::HirDatabase, Local, ModuleSource, SourceAnalyzer, TypeParam };
2020
2121pub struct SourceBinder<'a, DB> {
2222 pub db: &'a DB,
@@ -53,8 +53,7 @@ impl<DB: HirDatabase> SourceBinder<'_, DB> {
5353 }
5454
5555 pub fn to_def<T: ToDef>(&mut self, src: InFile<T>) -> Option<T::Def> {
56- let id: T::ID = self.to_id(src)?;
57- Some(id.into())
56+ T::to_def(self, src)
5857 }
5958
6059 fn to_id<T: ToId>(&mut self, src: InFile<T>) -> Option<T::ID> {
@@ -110,20 +109,27 @@ impl<DB: HirDatabase> SourceBinder<'_, DB> {
110109 }
111110}
112111
113- pub trait ToId: Sized + AstNode + 'static {
112+ pub trait ToId: Sized {
114113 type ID: Sized + Copy + 'static;
115114 fn to_id<DB: HirDatabase>(sb: &mut SourceBinder<'_, DB>, src: InFile<Self>)
116115 -> Option<Self::ID>;
117116}
118117
119- pub trait ToDef: ToId {
120- type Def: From<Self::ID>;
118+ pub trait ToDef: Sized + AstNode + 'static {
119+ type Def;
120+ fn to_def<DB: HirDatabase>(
121+ sb: &mut SourceBinder<'_, DB>,
122+ src: InFile<Self>,
123+ ) -> Option<Self::Def>;
121124}
122125
123126macro_rules! to_def_impls {
124127 ($(($def:path, $ast:path)),* ,) => {$(
125128 impl ToDef for $ast {
126129 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) }
127133 }
128134 )*}
129135}
@@ -230,3 +236,54 @@ impl ToId for ast::MacroCall {
230236 Some(MacroDefId { krate, ast_id, kind })
231237 }
232238}
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+ }
0 commit comments