diff options
-rw-r--r-- | crates/ra_hir/src/from_id.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/semantics.rs | 72 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 84 |
3 files changed, 81 insertions, 76 deletions
diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs index c16c17072..3aa7c4870 100644 --- a/crates/ra_hir/src/from_id.rs +++ b/crates/ra_hir/src/from_id.rs | |||
@@ -40,6 +40,7 @@ from_id![ | |||
40 | (hir_def::ConstId, crate::Const), | 40 | (hir_def::ConstId, crate::Const), |
41 | (hir_def::FunctionId, crate::Function), | 41 | (hir_def::FunctionId, crate::Function), |
42 | (hir_def::ImplId, crate::ImplBlock), | 42 | (hir_def::ImplId, crate::ImplBlock), |
43 | (hir_def::TypeParamId, crate::TypeParam), | ||
43 | (hir_expand::MacroDefId, crate::MacroDef) | 44 | (hir_expand::MacroDefId, crate::MacroDef) |
44 | ]; | 45 | ]; |
45 | 46 | ||
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index 22a7e7588..9fedb7657 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs | |||
@@ -4,16 +4,16 @@ use std::{cell::RefCell, fmt, iter::successors}; | |||
4 | 4 | ||
5 | use hir_def::{ | 5 | use hir_def::{ |
6 | resolver::{self, HasResolver, Resolver}, | 6 | resolver::{self, HasResolver, Resolver}, |
7 | TraitId, | 7 | DefWithBodyId, TraitId, |
8 | }; | 8 | }; |
9 | use ra_db::{FileId, FileRange}; | 9 | use ra_db::{FileId, FileRange}; |
10 | use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxToken, TextRange, TextUnit}; | 10 | use ra_syntax::{ast, match_ast, AstNode, SyntaxNode, SyntaxToken, TextRange, TextUnit}; |
11 | use rustc_hash::{FxHashMap, FxHashSet}; | 11 | use rustc_hash::{FxHashMap, FxHashSet}; |
12 | 12 | ||
13 | use crate::{ | 13 | use crate::{ |
14 | db::HirDatabase, | 14 | db::HirDatabase, |
15 | source_analyzer::{resolve_hir_path, ReferenceDescriptor, SourceAnalyzer}, | 15 | source_analyzer::{resolve_hir_path, ReferenceDescriptor, SourceAnalyzer}, |
16 | source_binder::{ChildContainer, SourceBinder, ToDef}, | 16 | source_binder::{ChildContainer, SourceBinder}, |
17 | Function, HirFileId, InFile, Local, MacroDef, Module, Name, Origin, Path, PathResolution, | 17 | Function, HirFileId, InFile, Local, MacroDef, Module, Name, Origin, Path, PathResolution, |
18 | ScopeDef, StructField, Trait, Type, TypeParam, VariantDef, | 18 | ScopeDef, StructField, Trait, Type, TypeParam, VariantDef, |
19 | }; | 19 | }; |
@@ -129,9 +129,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
129 | // pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option<???>; | 129 | // pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option<???>; |
130 | 130 | ||
131 | pub fn to_def<T: ToDef + Clone>(&self, src: &T) -> Option<T::Def> { | 131 | pub fn to_def<T: ToDef + Clone>(&self, src: &T) -> Option<T::Def> { |
132 | let src = self.find_file(src.syntax().clone()).with_value(src.clone()); | 132 | T::to_def(self, src) |
133 | let mut sb = self.sb.borrow_mut(); | ||
134 | T::to_def(self.db, &mut sb, src) | ||
135 | } | 133 | } |
136 | 134 | ||
137 | pub fn to_module_def(&self, file: FileId) -> Option<Module> { | 135 | pub fn to_module_def(&self, file: FileId) -> Option<Module> { |
@@ -227,6 +225,68 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
227 | } | 225 | } |
228 | } | 226 | } |
229 | 227 | ||
228 | pub trait ToDef: Sized + AstNode + 'static { | ||
229 | type Def; | ||
230 | fn to_def<DB: HirDatabase>(sema: &Semantics<DB>, src: &Self) -> Option<Self::Def>; | ||
231 | } | ||
232 | |||
233 | macro_rules! to_def_impls { | ||
234 | ($(($def:path, $ast:path)),* ,) => {$( | ||
235 | impl ToDef for $ast { | ||
236 | type Def = $def; | ||
237 | fn to_def<DB: HirDatabase>(sema: &Semantics<DB>, src: &Self) | ||
238 | -> Option<Self::Def> | ||
239 | { | ||
240 | let src = sema.find_file(src.syntax().clone()).with_value(src); | ||
241 | sema.sb.borrow_mut().to_id(sema.db, src.cloned()).map(Into::into) | ||
242 | } | ||
243 | } | ||
244 | )*} | ||
245 | } | ||
246 | |||
247 | to_def_impls![ | ||
248 | (crate::Module, ast::Module), | ||
249 | (crate::Struct, ast::StructDef), | ||
250 | (crate::Enum, ast::EnumDef), | ||
251 | (crate::Union, ast::UnionDef), | ||
252 | (crate::Trait, ast::TraitDef), | ||
253 | (crate::ImplBlock, ast::ImplBlock), | ||
254 | (crate::TypeAlias, ast::TypeAliasDef), | ||
255 | (crate::Const, ast::ConstDef), | ||
256 | (crate::Static, ast::StaticDef), | ||
257 | (crate::Function, ast::FnDef), | ||
258 | (crate::StructField, ast::RecordFieldDef), | ||
259 | (crate::EnumVariant, ast::EnumVariant), | ||
260 | (crate::TypeParam, ast::TypeParam), | ||
261 | (crate::MacroDef, ast::MacroCall), // this one is dubious, not all calls are macros | ||
262 | ]; | ||
263 | |||
264 | impl ToDef for ast::BindPat { | ||
265 | type Def = Local; | ||
266 | |||
267 | fn to_def<DB: HirDatabase>(sema: &Semantics<DB>, src: &Self) -> Option<Local> { | ||
268 | let src = sema.find_file(src.syntax().clone()).with_value(src); | ||
269 | let file_id = src.file_id; | ||
270 | let mut sb = sema.sb.borrow_mut(); | ||
271 | let db = sema.db; | ||
272 | let parent: DefWithBodyId = src.value.syntax().ancestors().find_map(|it| { | ||
273 | let res = match_ast! { | ||
274 | match it { | ||
275 | ast::ConstDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, | ||
276 | ast::StaticDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, | ||
277 | ast::FnDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, | ||
278 | _ => return None, | ||
279 | } | ||
280 | }; | ||
281 | Some(res) | ||
282 | })?; | ||
283 | let (_body, source_map) = db.body_with_source_map(parent); | ||
284 | let src = src.cloned().map(ast::Pat::from); | ||
285 | let pat_id = source_map.node_pat(src.as_ref())?; | ||
286 | Some(Local { parent: parent.into(), pat_id }) | ||
287 | } | ||
288 | } | ||
289 | |||
230 | fn find_root(node: &SyntaxNode) -> SyntaxNode { | 290 | fn find_root(node: &SyntaxNode) -> SyntaxNode { |
231 | node.ancestors().last().unwrap() | 291 | node.ancestors().last().unwrap() |
232 | } | 292 | } |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 0b8a641f9..4353e25ac 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -6,7 +6,7 @@ use hir_def::{ | |||
6 | dyn_map::DynMap, | 6 | dyn_map::DynMap, |
7 | keys::{self, Key}, | 7 | keys::{self, Key}, |
8 | ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, | 8 | ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, |
9 | StaticId, StructFieldId, StructId, TraitId, TypeAliasId, UnionId, VariantId, | 9 | StaticId, StructFieldId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, VariantId, |
10 | }; | 10 | }; |
11 | use hir_expand::{name::AsName, AstId, InFile, MacroDefId, MacroDefKind}; | 11 | use hir_expand::{name::AsName, AstId, InFile, MacroDefId, MacroDefKind}; |
12 | use ra_db::FileId; | 12 | use ra_db::FileId; |
@@ -17,9 +17,9 @@ use ra_syntax::{ | |||
17 | }; | 17 | }; |
18 | use rustc_hash::FxHashMap; | 18 | use rustc_hash::FxHashMap; |
19 | 19 | ||
20 | use crate::{db::HirDatabase, Local, Module, TypeParam}; | 20 | use crate::{db::HirDatabase, Module}; |
21 | 21 | ||
22 | pub struct SourceBinder { | 22 | pub(crate) struct SourceBinder { |
23 | child_by_source_cache: FxHashMap<ChildContainer, DynMap>, | 23 | child_by_source_cache: FxHashMap<ChildContainer, DynMap>, |
24 | } | 24 | } |
25 | 25 | ||
@@ -38,7 +38,11 @@ impl SourceBinder { | |||
38 | Some(Module { id: ModuleId { krate, local_id } }) | 38 | Some(Module { id: ModuleId { krate, local_id } }) |
39 | } | 39 | } |
40 | 40 | ||
41 | fn to_id<T: ToId>(&mut self, db: &impl HirDatabase, src: InFile<T>) -> Option<T::ID> { | 41 | pub(crate) fn to_id<T: ToId>( |
42 | &mut self, | ||
43 | db: &impl HirDatabase, | ||
44 | src: InFile<T>, | ||
45 | ) -> Option<T::ID> { | ||
42 | T::to_id(db, self, src) | 46 | T::to_id(db, self, src) |
43 | } | 47 | } |
44 | 48 | ||
@@ -118,42 +122,6 @@ pub(crate) trait ToId: Sized { | |||
118 | ) -> Option<Self::ID>; | 122 | ) -> Option<Self::ID>; |
119 | } | 123 | } |
120 | 124 | ||
121 | pub trait ToDef: Sized + AstNode + 'static { | ||
122 | type Def; | ||
123 | fn to_def<DB: HirDatabase>( | ||
124 | db: &DB, | ||
125 | sb: &mut SourceBinder, | ||
126 | src: InFile<Self>, | ||
127 | ) -> Option<Self::Def>; | ||
128 | } | ||
129 | |||
130 | macro_rules! to_def_impls { | ||
131 | ($(($def:path, $ast:path)),* ,) => {$( | ||
132 | impl ToDef for $ast { | ||
133 | type Def = $def; | ||
134 | fn to_def<DB: HirDatabase>(db: &DB, sb: &mut SourceBinder, src: InFile<Self>) | ||
135 | -> Option<Self::Def> | ||
136 | { sb.to_id(db, src).map(Into::into) } | ||
137 | } | ||
138 | )*} | ||
139 | } | ||
140 | |||
141 | to_def_impls![ | ||
142 | (crate::Module, ast::Module), | ||
143 | (crate::Struct, ast::StructDef), | ||
144 | (crate::Enum, ast::EnumDef), | ||
145 | (crate::Union, ast::UnionDef), | ||
146 | (crate::Trait, ast::TraitDef), | ||
147 | (crate::ImplBlock, ast::ImplBlock), | ||
148 | (crate::TypeAlias, ast::TypeAliasDef), | ||
149 | (crate::Const, ast::ConstDef), | ||
150 | (crate::Static, ast::StaticDef), | ||
151 | (crate::Function, ast::FnDef), | ||
152 | (crate::StructField, ast::RecordFieldDef), | ||
153 | (crate::EnumVariant, ast::EnumVariant), | ||
154 | (crate::MacroDef, ast::MacroCall), // this one is dubious, not all calls are macros | ||
155 | ]; | ||
156 | |||
157 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | 125 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] |
158 | pub(crate) enum ChildContainer { | 126 | pub(crate) enum ChildContainer { |
159 | DefWithBodyId(DefWithBodyId), | 127 | DefWithBodyId(DefWithBodyId), |
@@ -245,37 +213,14 @@ impl ToId for ast::MacroCall { | |||
245 | } | 213 | } |
246 | } | 214 | } |
247 | 215 | ||
248 | impl ToDef for ast::BindPat { | 216 | impl ToId for ast::TypeParam { |
249 | type Def = Local; | 217 | type ID = TypeParamId; |
250 | 218 | ||
251 | fn to_def<DB: HirDatabase>(db: &DB, sb: &mut SourceBinder, src: InFile<Self>) -> Option<Local> { | 219 | fn to_id<DB: HirDatabase>( |
252 | let file_id = src.file_id; | ||
253 | let parent: DefWithBodyId = src.value.syntax().ancestors().find_map(|it| { | ||
254 | let res = match_ast! { | ||
255 | match it { | ||
256 | ast::ConstDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, | ||
257 | ast::StaticDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, | ||
258 | ast::FnDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, | ||
259 | _ => return None, | ||
260 | } | ||
261 | }; | ||
262 | Some(res) | ||
263 | })?; | ||
264 | let (_body, source_map) = db.body_with_source_map(parent); | ||
265 | let src = src.map(ast::Pat::from); | ||
266 | let pat_id = source_map.node_pat(src.as_ref())?; | ||
267 | Some(Local { parent: parent.into(), pat_id }) | ||
268 | } | ||
269 | } | ||
270 | |||
271 | impl ToDef for ast::TypeParam { | ||
272 | type Def = TypeParam; | ||
273 | |||
274 | fn to_def<DB: HirDatabase>( | ||
275 | db: &DB, | 220 | db: &DB, |
276 | sb: &mut SourceBinder, | 221 | sb: &mut SourceBinder, |
277 | src: InFile<ast::TypeParam>, | 222 | src: InFile<Self>, |
278 | ) -> Option<TypeParam> { | 223 | ) -> Option<Self::ID> { |
279 | let file_id = src.file_id; | 224 | let file_id = src.file_id; |
280 | let parent: GenericDefId = src.value.syntax().ancestors().find_map(|it| { | 225 | let parent: GenericDefId = src.value.syntax().ancestors().find_map(|it| { |
281 | let res = match_ast! { | 226 | let res = match_ast! { |
@@ -291,8 +236,7 @@ impl ToDef for ast::TypeParam { | |||
291 | }; | 236 | }; |
292 | Some(res) | 237 | Some(res) |
293 | })?; | 238 | })?; |
294 | let &id = sb.child_by_source(db, parent.into())[keys::TYPE_PARAM].get(&src)?; | 239 | sb.child_by_source(db, parent.into())[keys::TYPE_PARAM].get(&src).copied() |
295 | Some(TypeParam { id }) | ||
296 | } | 240 | } |
297 | } | 241 | } |
298 | 242 | ||