aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/from_source.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-12-06 20:28:28 +0000
committerGitHub <[email protected]>2019-12-06 20:28:28 +0000
commitf18b7e18c479144325ec150be00837aae3329ae2 (patch)
tree2c8fbda35c5d9f43b70fe3c6e91ce3e4a8bb3226 /crates/ra_hir/src/from_source.rs
parentd3702c02cdff158f05d2af1bd7106cca8a3e4ba9 (diff)
parent8c86963d47953045f2f33ee6620d305a6589641e (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/from_source.rs')
-rw-r--r--crates/ra_hir/src/from_source.rs74
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
2use either::Either;
3
4use hir_def::{ 2use 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};
8use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; 6use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
9use ra_syntax::{ 7use ra_syntax::{
@@ -53,8 +51,9 @@ impl FromSource for Trait {
53impl FromSource for Function { 51impl 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 {
62impl FromSource for Const { 61impl 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}
70impl FromSource for Static { 70impl 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
80impl FromSource for TypeAlias { 80impl 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
123impl FromSource for StructField { 128impl 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
258impl<CHILD, SOURCE> ChildFromSource<CHILD, SOURCE> for Container 269impl ChildBySource for Container {
259where 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}