diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-12-06 20:28:28 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2019-12-06 20:28:28 +0000 |
commit | f18b7e18c479144325ec150be00837aae3329ae2 (patch) | |
tree | 2c8fbda35c5d9f43b70fe3c6e91ce3e4a8bb3226 /crates/ra_hir/src | |
parent | d3702c02cdff158f05d2af1bd7106cca8a3e4ba9 (diff) | |
parent | 8c86963d47953045f2f33ee6620d305a6589641e (diff) |
Merge #2484
2484: DynMap r=matklad a=matklad
Implement a `DynMap` a semi-dynamic, semi-static map, which helps to thread heterogeneously typed info in a uniform way. Totally inspired by https://github.com/JetBrains/kotlin/blob/df3bee30384787d8951ea548a4257c2cb52a16a3/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java.
@flodiebold wdyt? Seems like a potentially useful pattern for various source-map-like things.
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/from_source.rs | 74 |
1 files changed, 38 insertions, 36 deletions
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 5cb222bd3..437f800c1 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs | |||
@@ -1,9 +1,7 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | use either::Either; | ||
3 | |||
4 | use hir_def::{ | 2 | use hir_def::{ |
5 | child_from_source::ChildFromSource, nameres::ModuleSource, AstItemDef, EnumVariantId, ImplId, | 3 | child_by_source::ChildBySource, dyn_map::DynMap, keys, nameres::ModuleSource, AstItemDef, |
6 | LocationCtx, ModuleId, TraitId, VariantId, | 4 | EnumVariantId, LocationCtx, ModuleId, VariantId, |
7 | }; | 5 | }; |
8 | use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; | 6 | use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; |
9 | use ra_syntax::{ | 7 | use ra_syntax::{ |
@@ -53,8 +51,9 @@ impl FromSource for Trait { | |||
53 | impl FromSource for Function { | 51 | impl FromSource for Function { |
54 | type Ast = ast::FnDef; | 52 | type Ast = ast::FnDef; |
55 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { | 53 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { |
56 | Container::find(db, src.as_ref().map(|it| it.syntax()))? | 54 | Container::find(db, src.as_ref().map(|it| it.syntax()))?.child_by_source(db)[keys::FUNCTION] |
57 | .child_from_source(db, src) | 55 | .get(&src) |
56 | .copied() | ||
58 | .map(Function::from) | 57 | .map(Function::from) |
59 | } | 58 | } |
60 | } | 59 | } |
@@ -62,26 +61,29 @@ impl FromSource for Function { | |||
62 | impl FromSource for Const { | 61 | impl FromSource for Const { |
63 | type Ast = ast::ConstDef; | 62 | type Ast = ast::ConstDef; |
64 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { | 63 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { |
65 | Container::find(db, src.as_ref().map(|it| it.syntax()))? | 64 | Container::find(db, src.as_ref().map(|it| it.syntax()))?.child_by_source(db)[keys::CONST] |
66 | .child_from_source(db, src) | 65 | .get(&src) |
66 | .copied() | ||
67 | .map(Const::from) | 67 | .map(Const::from) |
68 | } | 68 | } |
69 | } | 69 | } |
70 | impl FromSource for Static { | 70 | impl FromSource for Static { |
71 | type Ast = ast::StaticDef; | 71 | type Ast = ast::StaticDef; |
72 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { | 72 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { |
73 | match Container::find(db, src.as_ref().map(|it| it.syntax()))? { | 73 | Container::find(db, src.as_ref().map(|it| it.syntax()))?.child_by_source(db)[keys::STATIC] |
74 | Container::Module(it) => it.id.child_from_source(db, src).map(Static::from), | 74 | .get(&src) |
75 | Container::Trait(_) | Container::ImplBlock(_) => None, | 75 | .copied() |
76 | } | 76 | .map(Static::from) |
77 | } | 77 | } |
78 | } | 78 | } |
79 | 79 | ||
80 | impl FromSource for TypeAlias { | 80 | impl FromSource for TypeAlias { |
81 | type Ast = ast::TypeAliasDef; | 81 | type Ast = ast::TypeAliasDef; |
82 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { | 82 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { |
83 | Container::find(db, src.as_ref().map(|it| it.syntax()))? | 83 | Container::find(db, src.as_ref().map(|it| it.syntax()))?.child_by_source(db) |
84 | .child_from_source(db, src) | 84 | [keys::TYPE_ALIAS] |
85 | .get(&src) | ||
86 | .copied() | ||
85 | .map(TypeAlias::from) | 87 | .map(TypeAlias::from) |
86 | } | 88 | } |
87 | } | 89 | } |
@@ -116,32 +118,41 @@ impl FromSource for EnumVariant { | |||
116 | let parent_enum = src.value.parent_enum(); | 118 | let parent_enum = src.value.parent_enum(); |
117 | let src_enum = InFile { file_id: src.file_id, value: parent_enum }; | 119 | let src_enum = InFile { file_id: src.file_id, value: parent_enum }; |
118 | let parent_enum = Enum::from_source(db, src_enum)?; | 120 | let parent_enum = Enum::from_source(db, src_enum)?; |
119 | parent_enum.id.child_from_source(db, src).map(EnumVariant::from) | 121 | parent_enum.id.child_by_source(db)[keys::ENUM_VARIANT] |
122 | .get(&src) | ||
123 | .copied() | ||
124 | .map(EnumVariant::from) | ||
120 | } | 125 | } |
121 | } | 126 | } |
122 | 127 | ||
123 | impl FromSource for StructField { | 128 | impl FromSource for StructField { |
124 | type Ast = FieldSource; | 129 | type Ast = FieldSource; |
125 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { | 130 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { |
131 | let src = src.as_ref(); | ||
132 | |||
133 | // FIXME this is buggy | ||
126 | let variant_id: VariantId = match src.value { | 134 | let variant_id: VariantId = match src.value { |
127 | FieldSource::Named(ref field) => { | 135 | FieldSource::Named(field) => { |
128 | let value = field.syntax().ancestors().find_map(ast::StructDef::cast)?; | 136 | let value = field.syntax().ancestors().find_map(ast::StructDef::cast)?; |
129 | let src = InFile { file_id: src.file_id, value }; | 137 | let src = InFile { file_id: src.file_id, value }; |
130 | let def = Struct::from_source(db, src)?; | 138 | let def = Struct::from_source(db, src)?; |
131 | def.id.into() | 139 | def.id.into() |
132 | } | 140 | } |
133 | FieldSource::Pos(ref field) => { | 141 | FieldSource::Pos(field) => { |
134 | let value = field.syntax().ancestors().find_map(ast::EnumVariant::cast)?; | 142 | let value = field.syntax().ancestors().find_map(ast::EnumVariant::cast)?; |
135 | let src = InFile { file_id: src.file_id, value }; | 143 | let src = InFile { file_id: src.file_id, value }; |
136 | let def = EnumVariant::from_source(db, src)?; | 144 | let def = EnumVariant::from_source(db, src)?; |
137 | EnumVariantId::from(def).into() | 145 | EnumVariantId::from(def).into() |
138 | } | 146 | } |
139 | }; | 147 | }; |
140 | let src = src.map(|field_source| match field_source { | 148 | |
141 | FieldSource::Pos(it) => Either::Left(it), | 149 | let dyn_map = variant_id.child_by_source(db); |
142 | FieldSource::Named(it) => Either::Right(it), | 150 | match src.value { |
143 | }); | 151 | FieldSource::Pos(it) => dyn_map[keys::TUPLE_FIELD].get(&src.with_value(it.clone())), |
144 | variant_id.child_from_source(db, src).map(StructField::from) | 152 | FieldSource::Named(it) => dyn_map[keys::RECORD_FIELD].get(&src.with_value(it.clone())), |
153 | } | ||
154 | .copied() | ||
155 | .map(StructField::from) | ||
145 | } | 156 | } |
146 | } | 157 | } |
147 | 158 | ||
@@ -255,21 +266,12 @@ impl Container { | |||
255 | } | 266 | } |
256 | } | 267 | } |
257 | 268 | ||
258 | impl<CHILD, SOURCE> ChildFromSource<CHILD, SOURCE> for Container | 269 | impl ChildBySource for Container { |
259 | where | 270 | fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { |
260 | TraitId: ChildFromSource<CHILD, SOURCE>, | ||
261 | ImplId: ChildFromSource<CHILD, SOURCE>, | ||
262 | ModuleId: ChildFromSource<CHILD, SOURCE>, | ||
263 | { | ||
264 | fn child_from_source( | ||
265 | &self, | ||
266 | db: &impl DefDatabase, | ||
267 | child_source: InFile<SOURCE>, | ||
268 | ) -> Option<CHILD> { | ||
269 | match self { | 271 | match self { |
270 | Container::Trait(it) => it.id.child_from_source(db, child_source), | 272 | Container::Trait(it) => it.id.child_by_source(db), |
271 | Container::ImplBlock(it) => it.id.child_from_source(db, child_source), | 273 | Container::ImplBlock(it) => it.id.child_by_source(db), |
272 | Container::Module(it) => it.id.child_from_source(db, child_source), | 274 | Container::Module(it) => it.id.child_by_source(db), |
273 | } | 275 | } |
274 | } | 276 | } |
275 | } | 277 | } |