diff options
-rw-r--r-- | crates/ra_hir/src/from_id.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/semantics.rs | 72 | ||||
-rw-r--r-- | crates/ra_hir/src/source_analyzer.rs | 32 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 84 |
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 | ||
53 | pub use hir_def::{ | 53 | pub 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 | ||
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_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 | ||
27 | use crate::{ | 27 | use 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)] | ||
57 | pub struct ScopeEntryWithSyntax { | ||
58 | pub(crate) name: Name, | ||
59 | pub(crate) ptr: Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>, | ||
60 | } | ||
61 | |||
62 | impl 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)] |
73 | pub struct ReferenceDescriptor { | 57 | pub 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 | }; |
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 | ||