diff options
Diffstat (limited to 'crates/ra_hir/src/semantics.rs')
-rw-r--r-- | crates/ra_hir/src/semantics.rs | 72 |
1 files changed, 66 insertions, 6 deletions
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 | } |