diff options
Diffstat (limited to 'crates/ra_hir/src/from_source.rs')
-rw-r--r-- | crates/ra_hir/src/from_source.rs | 116 |
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 |
2 | use hir_def::{ | 2 | use 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 | }; |
6 | use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; | 6 | use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; |
7 | use ra_syntax::{ | 7 | use ra_syntax::{ |
@@ -23,35 +23,43 @@ pub trait FromSource: Sized { | |||
23 | impl FromSource for Struct { | 23 | impl 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 | } |
30 | impl FromSource for Union { | 32 | impl 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 | } |
37 | impl FromSource for Enum { | 41 | impl 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 | } |
44 | impl FromSource for Trait { | 50 | impl 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 | } |
51 | impl FromSource for Function { | 59 | impl 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 { | |||
61 | impl FromSource for Const { | 69 | impl 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 { | |||
70 | impl FromSource for Static { | 78 | impl 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 { | |||
80 | impl FromSource for TypeAlias { | 88 | impl 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 { | |||
107 | impl FromSource for ImplBlock { | 114 | impl 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 | ||
250 | fn from_source<N, DEF>(db: &(impl DefDatabase + AstDatabase), src: InFile<N>) -> Option<DEF> | 257 | fn analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> DynMap { |
251 | where | 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 | |||
263 | enum Container { | ||
264 | Trait(Trait), | ||
265 | ImplBlock(ImplBlock), | ||
266 | Module(Module), | ||
267 | } | 259 | } |
268 | 260 | ||
269 | impl Container { | 261 | fn _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 | ||
295 | impl 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 | } |