aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/from_id.rs1
-rw-r--r--crates/ra_hir/src/semantics.rs72
-rw-r--r--crates/ra_hir/src/source_binder.rs84
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
5use hir_def::{ 5use hir_def::{
6 resolver::{self, HasResolver, Resolver}, 6 resolver::{self, HasResolver, Resolver},
7 TraitId, 7 DefWithBodyId, TraitId,
8}; 8};
9use ra_db::{FileId, FileRange}; 9use ra_db::{FileId, FileRange};
10use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxToken, TextRange, TextUnit}; 10use ra_syntax::{ast, match_ast, AstNode, SyntaxNode, SyntaxToken, TextRange, TextUnit};
11use rustc_hash::{FxHashMap, FxHashSet}; 11use rustc_hash::{FxHashMap, FxHashSet};
12 12
13use crate::{ 13use 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
228pub trait ToDef: Sized + AstNode + 'static {
229 type Def;
230 fn to_def<DB: HirDatabase>(sema: &Semantics<DB>, src: &Self) -> Option<Self::Def>;
231}
232
233macro_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
247to_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
264impl 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
230fn find_root(node: &SyntaxNode) -> SyntaxNode { 290fn 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};
11use hir_expand::{name::AsName, AstId, InFile, MacroDefId, MacroDefKind}; 11use hir_expand::{name::AsName, AstId, InFile, MacroDefId, MacroDefKind};
12use ra_db::FileId; 12use ra_db::FileId;
@@ -17,9 +17,9 @@ use ra_syntax::{
17}; 17};
18use rustc_hash::FxHashMap; 18use rustc_hash::FxHashMap;
19 19
20use crate::{db::HirDatabase, Local, Module, TypeParam}; 20use crate::{db::HirDatabase, Module};
21 21
22pub struct SourceBinder { 22pub(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
121pub 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
130macro_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
141to_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)]
158pub(crate) enum ChildContainer { 126pub(crate) enum ChildContainer {
159 DefWithBodyId(DefWithBodyId), 127 DefWithBodyId(DefWithBodyId),
@@ -245,37 +213,14 @@ impl ToId for ast::MacroCall {
245 } 213 }
246} 214}
247 215
248impl ToDef for ast::BindPat { 216impl 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
271impl 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