aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/from_id.rs1
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_hir/src/semantics.rs72
-rw-r--r--crates/ra_hir/src/source_analyzer.rs32
-rw-r--r--crates/ra_hir/src/source_binder.rs84
5 files changed, 90 insertions, 101 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/lib.rs b/crates/ra_hir/src/lib.rs
index 004a2185f..4a85e7e36 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -47,7 +47,7 @@ pub use crate::{
47 }, 47 },
48 has_source::HasSource, 48 has_source::HasSource,
49 semantics::{original_range, Semantics, SemanticsScope}, 49 semantics::{original_range, Semantics, SemanticsScope},
50 source_analyzer::{PathResolution, ScopeEntryWithSyntax}, 50 source_analyzer::PathResolution,
51}; 51};
52 52
53pub use hir_def::{ 53pub use hir_def::{
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_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index bff1ecd14..b655e2c32 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -25,8 +25,8 @@ use ra_syntax::{
25}; 25};
26 26
27use crate::{ 27use crate::{
28 db::HirDatabase, Adt, Const, EnumVariant, Function, Local, MacroDef, Name, Path, Static, 28 db::HirDatabase, Adt, Const, EnumVariant, Function, Local, MacroDef, Path, Static, Struct,
29 Struct, Trait, Type, TypeAlias, TypeParam, 29 Trait, Type, TypeAlias, TypeParam,
30}; 30};
31 31
32/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of 32/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
@@ -53,22 +53,6 @@ pub enum PathResolution {
53 AssocItem(crate::AssocItem), 53 AssocItem(crate::AssocItem),
54} 54}
55 55
56#[derive(Debug, Clone, PartialEq, Eq)]
57pub struct ScopeEntryWithSyntax {
58 pub(crate) name: Name,
59 pub(crate) ptr: Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>,
60}
61
62impl ScopeEntryWithSyntax {
63 pub fn name(&self) -> &Name {
64 &self.name
65 }
66
67 pub fn ptr(&self) -> Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>> {
68 self.ptr
69 }
70}
71
72#[derive(Debug)] 56#[derive(Debug)]
73pub struct ReferenceDescriptor { 57pub struct ReferenceDescriptor {
74 pub range: TextRange, 58 pub range: TextRange,
@@ -235,16 +219,16 @@ impl SourceAnalyzer {
235 resolve_hir_path(db, &self.resolver, &hir_path) 219 resolve_hir_path(db, &self.resolver, &hir_path)
236 } 220 }
237 221
238 fn resolve_local_name(&self, name_ref: &ast::NameRef) -> Option<ScopeEntryWithSyntax> { 222 fn resolve_local_name(
223 &self,
224 name_ref: &ast::NameRef,
225 ) -> Option<Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>> {
239 let name = name_ref.as_name(); 226 let name = name_ref.as_name();
240 let source_map = self.body_source_map.as_ref()?; 227 let source_map = self.body_source_map.as_ref()?;
241 let scopes = self.scopes.as_ref()?; 228 let scopes = self.scopes.as_ref()?;
242 let scope = scope_for(scopes, source_map, InFile::new(self.file_id, name_ref.syntax()))?; 229 let scope = scope_for(scopes, source_map, InFile::new(self.file_id, name_ref.syntax()))?;
243 let entry = scopes.resolve_name_in_scope(scope, &name)?; 230 let entry = scopes.resolve_name_in_scope(scope, &name)?;
244 Some(ScopeEntryWithSyntax { 231 Some(source_map.pat_syntax(entry.pat())?.value)
245 name: entry.name().clone(),
246 ptr: source_map.pat_syntax(entry.pat())?.value,
247 })
248 } 232 }
249 233
250 // FIXME: we only use this in `inline_local_variable` assist, ideally, we 234 // FIXME: we only use this in `inline_local_variable` assist, ideally, we
@@ -258,7 +242,7 @@ impl SourceAnalyzer {
258 .filter_map(ast::NameRef::cast) 242 .filter_map(ast::NameRef::cast)
259 .filter(|name_ref| match self.resolve_local_name(&name_ref) { 243 .filter(|name_ref| match self.resolve_local_name(&name_ref) {
260 None => false, 244 None => false,
261 Some(entry) => entry.ptr() == ptr, 245 Some(d_ptr) => d_ptr == ptr,
262 }) 246 })
263 .map(|name_ref| ReferenceDescriptor { 247 .map(|name_ref| ReferenceDescriptor {
264 name: name_ref.text().to_string(), 248 name: name_ref.text().to_string(),
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