aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/adt.rs
diff options
context:
space:
mode:
authorMarcus Klaas de Vries <[email protected]>2019-01-08 15:01:19 +0000
committerMarcus Klaas de Vries <[email protected]>2019-01-10 13:32:56 +0000
commit978de5cf8bfd2ff82696fc8d5369b41e147431c3 (patch)
tree27a25a5f2fb20a4afffed97cbb5b678b251d254b /crates/ra_hir/src/adt.rs
parentaca14c591fea40b2f803bbf5f02c1571732348fb (diff)
Implement type inference for enum variants
Diffstat (limited to 'crates/ra_hir/src/adt.rs')
-rw-r--r--crates/ra_hir/src/adt.rs105
1 files changed, 85 insertions, 20 deletions
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index d30390f25..f1b98cdd7 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -1,10 +1,19 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_db::Cancelable; 3use ra_db::Cancelable;
4use ra_syntax::ast::{self, NameOwner, StructFlavor, AstNode}; 4use ra_syntax::{
5 SyntaxNode,
6 ast::{self, NameOwner, StructFlavor, AstNode}
7};
5 8
6use crate::{ 9use crate::{
10<<<<<<< HEAD
7 DefId, Name, AsName, Struct, Enum, HirDatabase, DefKind, 11 DefId, Name, AsName, Struct, Enum, HirDatabase, DefKind,
12=======
13 DefId, DefLoc, Name, AsName, Struct, Enum, EnumVariant,
14 VariantData, StructField, HirDatabase, DefKind,
15 SourceItemId,
16>>>>>>> 95ac72a3... Implement type inference for enum variants
8 type_ref::TypeRef, 17 type_ref::TypeRef,
9}; 18};
10 19
@@ -45,33 +54,39 @@ impl StructData {
45 } 54 }
46} 55}
47 56
48impl Enum { 57fn get_def_id(
49 pub(crate) fn new(def_id: DefId) -> Self { 58 db: &impl HirDatabase,
50 Enum { def_id } 59 same_file_loc: &DefLoc,
51 } 60 node: &SyntaxNode,
61 expected_kind: DefKind,
62) -> DefId {
63 let file_id = same_file_loc.source_item_id.file_id;
64 let file_items = db.file_items(file_id);
65
66 let item_id = file_items.id_of(file_id, node);
67 let source_item_id = SourceItemId {
68 item_id: Some(item_id),
69 ..same_file_loc.source_item_id
70 };
71 let loc = DefLoc {
72 kind: expected_kind,
73 source_item_id: source_item_id,
74 ..*same_file_loc
75 };
76 loc.id(db)
52} 77}
53 78
54#[derive(Debug, Clone, PartialEq, Eq)] 79#[derive(Debug, Clone, PartialEq, Eq)]
55pub struct EnumData { 80pub struct EnumData {
56 pub(crate) name: Option<Name>, 81 pub(crate) name: Option<Name>,
57 pub(crate) variants: Vec<(Name, Arc<VariantData>)>, 82 // TODO: keep track of names also since we already have them?
83 // then we won't need additional db lookups
84 pub(crate) variants: Option<Vec<EnumVariant>>,
58} 85}
59 86
60impl EnumData { 87impl EnumData {
61 fn new(enum_def: &ast::EnumDef) -> Self { 88 fn new(enum_def: &ast::EnumDef, variants: Option<Vec<EnumVariant>>) -> Self {
62 let name = enum_def.name().map(|n| n.as_name()); 89 let name = enum_def.name().map(|n| n.as_name());
63 let variants = if let Some(evl) = enum_def.variant_list() {
64 evl.variants()
65 .map(|v| {
66 (
67 v.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
68 Arc::new(VariantData::new(v.flavor())),
69 )
70 })
71 .collect()
72 } else {
73 Vec::new()
74 };
75 EnumData { name, variants } 90 EnumData { name, variants }
76 } 91 }
77 92
@@ -83,7 +98,57 @@ impl EnumData {
83 assert!(def_loc.kind == DefKind::Enum); 98 assert!(def_loc.kind == DefKind::Enum);
84 let syntax = db.file_item(def_loc.source_item_id); 99 let syntax = db.file_item(def_loc.source_item_id);
85 let enum_def = ast::EnumDef::cast(&syntax).expect("enum def should point to EnumDef node"); 100 let enum_def = ast::EnumDef::cast(&syntax).expect("enum def should point to EnumDef node");
86 Ok(Arc::new(EnumData::new(enum_def))) 101 let variants = enum_def.variant_list().map(|vl| {
102 vl.variants()
103 .map(|ev| {
104 let def_id = get_def_id(db, &def_loc, ev.syntax(), DefKind::EnumVariant);
105 EnumVariant::new(def_id)
106 })
107 .collect()
108 });
109 Ok(Arc::new(EnumData::new(enum_def, variants)))
110 }
111}
112
113#[derive(Debug, Clone, PartialEq, Eq)]
114pub struct EnumVariantData {
115 pub(crate) name: Option<Name>,
116 pub(crate) variant_data: Arc<VariantData>,
117 pub(crate) parent_enum: Enum,
118}
119
120impl EnumVariantData {
121 fn new(variant_def: &ast::EnumVariant, parent_enum: Enum) -> EnumVariantData {
122 let name = variant_def.name().map(|n| n.as_name());
123 let variant_data = VariantData::new(variant_def.flavor());
124 let variant_data = Arc::new(variant_data);
125 EnumVariantData {
126 name,
127 variant_data,
128 parent_enum,
129 }
130 }
131
132 pub(crate) fn enum_variant_data_query(
133 db: &impl HirDatabase,
134 def_id: DefId,
135 ) -> Cancelable<Arc<EnumVariantData>> {
136 let def_loc = def_id.loc(db);
137 assert!(def_loc.kind == DefKind::EnumVariant);
138 let syntax = db.file_item(def_loc.source_item_id);
139 let variant_def = ast::EnumVariant::cast(&syntax)
140 .expect("enum variant def should point to EnumVariant node");
141 let enum_node = syntax
142 .parent()
143 .expect("enum variant should have enum variant list ancestor")
144 .parent()
145 .expect("enum variant list should have enum ancestor");
146 let enum_def_id = get_def_id(db, &def_loc, enum_node, DefKind::Enum);
147
148 Ok(Arc::new(EnumVariantData::new(
149 variant_def,
150 Enum::new(enum_def_id),
151 )))
87 } 152 }
88} 153}
89 154