diff options
author | Florian Diebold <[email protected]> | 2018-12-25 12:54:38 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2018-12-25 14:16:42 +0000 |
commit | 55c941cd9fb90c9340f01981e113aabd058b185b (patch) | |
tree | f07828a8eaabab7c20b2b4d3b98519956b981f17 | |
parent | 07a72859650254d8ba326e2c9683ae52164cb3b5 (diff) |
Type field accesses
-rw-r--r-- | crates/ra_hir/src/adt.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 32 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests/data/0004_struct.txt | 6 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/generated.rs | 10 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar.ron | 2 |
5 files changed, 54 insertions, 5 deletions
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index b44f59f0b..03770ed7d 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs | |||
@@ -22,6 +22,10 @@ impl Struct { | |||
22 | self.def_id | 22 | self.def_id |
23 | } | 23 | } |
24 | 24 | ||
25 | pub fn variant_data(&self, db: &impl HirDatabase) -> Cancelable<Arc<VariantData>> { | ||
26 | Ok(db.struct_data(self.def_id)?.variant_data.clone()) | ||
27 | } | ||
28 | |||
25 | pub fn struct_data(&self, db: &impl HirDatabase) -> Cancelable<Arc<StructData>> { | 29 | pub fn struct_data(&self, db: &impl HirDatabase) -> Cancelable<Arc<StructData>> { |
26 | Ok(db.struct_data(self.def_id)?) | 30 | Ok(db.struct_data(self.def_id)?) |
27 | } | 31 | } |
@@ -162,6 +166,11 @@ impl VariantData { | |||
162 | StructFlavor::Unit => VariantData::Unit, | 166 | StructFlavor::Unit => VariantData::Unit, |
163 | }) | 167 | }) |
164 | } | 168 | } |
169 | |||
170 | pub(crate) fn get_field_ty(&self, field_name: &str) -> Option<Ty> { | ||
171 | self.fields().iter().find(|f| f.name == field_name).map(|f| f.ty.clone()) | ||
172 | } | ||
173 | |||
165 | pub fn fields(&self) -> &[StructField] { | 174 | pub fn fields(&self) -> &[StructField] { |
166 | match *self { | 175 | match *self { |
167 | VariantData::Struct(ref fields) | VariantData::Tuple(ref fields) => fields, | 176 | VariantData::Struct(ref fields) | VariantData::Tuple(ref fields) => fields, |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index e2428a37f..f931f3c87 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -384,6 +384,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
384 | }) | 384 | }) |
385 | } | 385 | } |
386 | 386 | ||
387 | fn infer_expr_opt(&mut self, expr: Option<ast::Expr>) -> Cancelable<Ty> { | ||
388 | if let Some(e) = expr { | ||
389 | self.infer_expr(e) | ||
390 | } else { | ||
391 | Ok(Ty::Unknown) | ||
392 | } | ||
393 | } | ||
394 | |||
387 | fn infer_expr(&mut self, expr: ast::Expr) -> Cancelable<Ty> { | 395 | fn infer_expr(&mut self, expr: ast::Expr) -> Cancelable<Ty> { |
388 | let ty = match expr { | 396 | let ty = match expr { |
389 | ast::Expr::IfExpr(e) => { | 397 | ast::Expr::IfExpr(e) => { |
@@ -559,7 +567,29 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
559 | Ty::Unknown | 567 | Ty::Unknown |
560 | } | 568 | } |
561 | ast::Expr::IndexExpr(_e) => Ty::Unknown, | 569 | ast::Expr::IndexExpr(_e) => Ty::Unknown, |
562 | ast::Expr::FieldExpr(_e) => Ty::Unknown, | 570 | ast::Expr::FieldExpr(e) => { |
571 | let receiver_ty = self.infer_expr_opt(e.expr())?; | ||
572 | if let Some(nr) = e.name_ref() { | ||
573 | let text = nr.text(); | ||
574 | match receiver_ty { | ||
575 | Ty::Tuple(fields) => { | ||
576 | let i = text.parse::<usize>().ok(); | ||
577 | i.and_then(|i| fields.get(i).cloned()).unwrap_or(Ty::Unknown) | ||
578 | } | ||
579 | Ty::Adt { def_id, .. } => { | ||
580 | let field_ty = match def_id.resolve(self.db)? { | ||
581 | Def::Struct(s) => s.variant_data(self.db)?.get_field_ty(&text), | ||
582 | // TODO unions | ||
583 | _ => None, | ||
584 | }; | ||
585 | field_ty.unwrap_or(Ty::Unknown) | ||
586 | } | ||
587 | _ => Ty::Unknown, | ||
588 | } | ||
589 | } else { | ||
590 | Ty::Unknown | ||
591 | } | ||
592 | }, | ||
563 | ast::Expr::TryExpr(e) => { | 593 | ast::Expr::TryExpr(e) => { |
564 | let _inner_ty = if let Some(e) = e.expr() { | 594 | let _inner_ty = if let Some(e) = e.expr() { |
565 | self.infer_expr(e)? | 595 | self.infer_expr(e)? |
diff --git a/crates/ra_hir/src/ty/tests/data/0004_struct.txt b/crates/ra_hir/src/ty/tests/data/0004_struct.txt index 41357749f..cc8f3665b 100644 --- a/crates/ra_hir/src/ty/tests/data/0004_struct.txt +++ b/crates/ra_hir/src/ty/tests/data/0004_struct.txt | |||
@@ -4,9 +4,11 @@ | |||
4 | [129; 130) '1': [unknown] | 4 | [129; 130) '1': [unknown] |
5 | [107; 108) 'a': A | 5 | [107; 108) 'a': A |
6 | [127; 128) 'C': [unknown] | 6 | [127; 128) 'C': [unknown] |
7 | [139; 142) 'a.b': [unknown] | 7 | [139; 142) 'a.b': B |
8 | [114; 133) 'A { b:...C(1) }': A | 8 | [114; 133) 'A { b:...C(1) }': A |
9 | [148; 151) 'a.c': [unknown] | 9 | [148; 151) 'a.c': C |
10 | [148; 149) 'a': A | ||
11 | [139; 140) 'a': A | ||
10 | [72; 154) '{ ...a.c; }': () | 12 | [72; 154) '{ ...a.c; }': () |
11 | [96; 97) 'B': [unknown] | 13 | [96; 97) 'B': [unknown] |
12 | [88; 89) '1': [unknown] | 14 | [88; 89) '1': [unknown] |
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 35a9770a6..4e0550487 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs | |||
@@ -1123,7 +1123,15 @@ impl<R: TreeRoot<RaTypes>> FieldExprNode<R> { | |||
1123 | } | 1123 | } |
1124 | 1124 | ||
1125 | 1125 | ||
1126 | impl<'a> FieldExpr<'a> {} | 1126 | impl<'a> FieldExpr<'a> { |
1127 | pub fn expr(self) -> Option<Expr<'a>> { | ||
1128 | super::child_opt(self) | ||
1129 | } | ||
1130 | |||
1131 | pub fn name_ref(self) -> Option<NameRef<'a>> { | ||
1132 | super::child_opt(self) | ||
1133 | } | ||
1134 | } | ||
1127 | 1135 | ||
1128 | // FieldPatList | 1136 | // FieldPatList |
1129 | #[derive(Debug, Clone, Copy,)] | 1137 | #[derive(Debug, Clone, Copy,)] |
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index e4e41d077..923da0324 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron | |||
@@ -406,7 +406,7 @@ Grammar( | |||
406 | options: [ "Expr" ], | 406 | options: [ "Expr" ], |
407 | ), | 407 | ), |
408 | "IndexExpr": (), | 408 | "IndexExpr": (), |
409 | "FieldExpr": (), | 409 | "FieldExpr": (options: ["Expr", "NameRef"]), |
410 | "TryExpr": (options: ["Expr"]), | 410 | "TryExpr": (options: ["Expr"]), |
411 | "CastExpr": (options: ["Expr", "TypeRef"]), | 411 | "CastExpr": (options: ["Expr", "TypeRef"]), |
412 | "RefExpr": (options: ["Expr"]), | 412 | "RefExpr": (options: ["Expr"]), |