aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/from_source.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/from_source.rs')
-rw-r--r--crates/ra_hir/src/from_source.rs116
1 files changed, 48 insertions, 68 deletions
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index b35188a21..f7411c5cf 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -1,7 +1,7 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2use hir_def::{ 2use hir_def::{
3 child_by_source::ChildBySource, dyn_map::DynMap, keys, nameres::ModuleSource, AstItemDef, 3 child_by_source::ChildBySource, dyn_map::DynMap, keys, nameres::ModuleSource, EnumVariantId,
4 EnumVariantId, GenericDefId, LocationCtx, ModuleId, VariantId, 4 GenericDefId, ModuleId, VariantId,
5}; 5};
6use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; 6use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
7use ra_syntax::{ 7use ra_syntax::{
@@ -23,35 +23,43 @@ pub trait FromSource: Sized {
23impl FromSource for Struct { 23impl FromSource for Struct {
24 type Ast = ast::StructDef; 24 type Ast = ast::StructDef;
25 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 25 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
26 let id = from_source(db, src)?; 26 analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::STRUCT]
27 Some(Struct { id }) 27 .get(&src)
28 .copied()
29 .map(Struct::from)
28 } 30 }
29} 31}
30impl FromSource for Union { 32impl FromSource for Union {
31 type Ast = ast::UnionDef; 33 type Ast = ast::UnionDef;
32 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 34 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
33 let id = from_source(db, src)?; 35 analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::UNION]
34 Some(Union { id }) 36 .get(&src)
37 .copied()
38 .map(Union::from)
35 } 39 }
36} 40}
37impl FromSource for Enum { 41impl FromSource for Enum {
38 type Ast = ast::EnumDef; 42 type Ast = ast::EnumDef;
39 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 43 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
40 let id = from_source(db, src)?; 44 analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::ENUM]
41 Some(Enum { id }) 45 .get(&src)
46 .copied()
47 .map(Enum::from)
42 } 48 }
43} 49}
44impl FromSource for Trait { 50impl FromSource for Trait {
45 type Ast = ast::TraitDef; 51 type Ast = ast::TraitDef;
46 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 52 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
47 let id = from_source(db, src)?; 53 analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::TRAIT]
48 Some(Trait { id }) 54 .get(&src)
55 .copied()
56 .map(Trait::from)
49 } 57 }
50} 58}
51impl FromSource for Function { 59impl FromSource for Function {
52 type Ast = ast::FnDef; 60 type Ast = ast::FnDef;
53 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 61 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
54 Container::find(db, src.as_ref().map(|it| it.syntax()))?.child_by_source(db)[keys::FUNCTION] 62 analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::FUNCTION]
55 .get(&src) 63 .get(&src)
56 .copied() 64 .copied()
57 .map(Function::from) 65 .map(Function::from)
@@ -61,7 +69,7 @@ impl FromSource for Function {
61impl FromSource for Const { 69impl FromSource for Const {
62 type Ast = ast::ConstDef; 70 type Ast = ast::ConstDef;
63 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 71 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
64 Container::find(db, src.as_ref().map(|it| it.syntax()))?.child_by_source(db)[keys::CONST] 72 analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::CONST]
65 .get(&src) 73 .get(&src)
66 .copied() 74 .copied()
67 .map(Const::from) 75 .map(Const::from)
@@ -70,7 +78,7 @@ impl FromSource for Const {
70impl FromSource for Static { 78impl FromSource for Static {
71 type Ast = ast::StaticDef; 79 type Ast = ast::StaticDef;
72 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 80 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
73 Container::find(db, src.as_ref().map(|it| it.syntax()))?.child_by_source(db)[keys::STATIC] 81 analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::STATIC]
74 .get(&src) 82 .get(&src)
75 .copied() 83 .copied()
76 .map(Static::from) 84 .map(Static::from)
@@ -80,8 +88,7 @@ impl FromSource for Static {
80impl FromSource for TypeAlias { 88impl FromSource for TypeAlias {
81 type Ast = ast::TypeAliasDef; 89 type Ast = ast::TypeAliasDef;
82 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 90 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
83 Container::find(db, src.as_ref().map(|it| it.syntax()))?.child_by_source(db) 91 analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::TYPE_ALIAS]
84 [keys::TYPE_ALIAS]
85 .get(&src) 92 .get(&src)
86 .copied() 93 .copied()
87 .map(TypeAlias::from) 94 .map(TypeAlias::from)
@@ -107,10 +114,10 @@ impl FromSource for MacroDef {
107impl FromSource for ImplBlock { 114impl FromSource for ImplBlock {
108 type Ast = ast::ImplBlock; 115 type Ast = ast::ImplBlock;
109 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 116 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
110 // XXX: use `.parent()` to avoid finding ourselves 117 analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::IMPL]
111 let parent = src.value.syntax().parent()?; 118 .get(&src)
112 let container = Container::find(db, src.with_value(parent).as_ref())?; 119 .copied()
113 container.child_by_source(db)[keys::IMPL].get(&src).copied().map(ImplBlock::from) 120 .map(ImplBlock::from)
114 } 121 }
115} 122}
116 123
@@ -247,57 +254,30 @@ impl Module {
247 } 254 }
248} 255}
249 256
250fn from_source<N, DEF>(db: &(impl DefDatabase + AstDatabase), src: InFile<N>) -> Option<DEF> 257fn analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> DynMap {
251where 258 _analyze_container(db, src).unwrap_or_default()
252 N: AstNode,
253 DEF: AstItemDef<N>,
254{
255 let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax()));
256 let module = Module::from_definition(db, InFile::new(src.file_id, module_src))?;
257 let ctx = LocationCtx::new(db, module.id, src.file_id);
258 let items = db.ast_id_map(src.file_id);
259 let item_id = items.ast_id(&src.value);
260 Some(DEF::from_ast_id(ctx, item_id))
261}
262
263enum Container {
264 Trait(Trait),
265 ImplBlock(ImplBlock),
266 Module(Module),
267} 259}
268 260
269impl Container { 261fn _analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> Option<DynMap> {
270 fn find(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> Option<Container> { 262 // FIXME: this doesn't try to handle nested declarations
271 // FIXME: this doesn't try to handle nested declarations 263 for container in src.value.ancestors().skip(1) {
272 for container in src.value.ancestors() { 264 let res = match_ast! {
273 let res = match_ast! { 265 match container {
274 match container { 266 ast::TraitDef(it) => {
275 ast::TraitDef(it) => { 267 let c = Trait::from_source(db, src.with_value(it))?;
276 let c = Trait::from_source(db, src.with_value(it))?; 268 c.id.child_by_source(db)
277 Container::Trait(c) 269 },
278 }, 270 ast::ImplBlock(it) => {
279 ast::ImplBlock(it) => { 271 let c = ImplBlock::from_source(db, src.with_value(it))?;
280 let c = ImplBlock::from_source(db, src.with_value(it))?; 272 c.id.child_by_source(db)
281 Container::ImplBlock(c) 273 },
282 }, 274 _ => { continue },
283 _ => { continue }, 275 }
284 } 276 };
285 }; 277 return Some(res);
286 return Some(res);
287 }
288
289 let module_source = ModuleSource::from_child_node(db, src);
290 let c = Module::from_definition(db, src.with_value(module_source))?;
291 Some(Container::Module(c))
292 } 278 }
293}
294 279
295impl ChildBySource for Container { 280 let module_source = ModuleSource::from_child_node(db, src);
296 fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { 281 let c = Module::from_definition(db, src.with_value(module_source))?;
297 match self { 282 Some(c.id.child_by_source(db))
298 Container::Trait(it) => it.id.child_by_source(db),
299 Container::ImplBlock(it) => it.id.child_by_source(db),
300 Container::Module(it) => it.id.child_by_source(db),
301 }
302 }
303} 283}