diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-10 19:12:40 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-10 19:12:40 +0000 |
commit | dc2a8d5acc53054c86ad17260b69d4bf4f14dbc6 (patch) | |
tree | ddf2dbe793448d3e913f869c7dab91ce7175b623 /crates/ra_hir/src/adt.rs | |
parent | a95536301c346e68a109915e6d54136cae875ab0 (diff) | |
parent | e78286c8e88d31045d354320a1d29bbd75405027 (diff) |
Merge #470
470: Type inference for enum variants r=flodiebold a=marcusklaas
Opened a new PR instead of https://github.com/rust-analyzer/rust-analyzer/pull/461. Totally botched that one.
I think I resolved all the issues mentioned there.
Co-authored-by: Marcus Klaas de Vries <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/adt.rs')
-rw-r--r-- | crates/ra_hir/src/adt.rs | 108 |
1 files changed, 87 insertions, 21 deletions
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index d30390f25..bcb705c24 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs | |||
@@ -1,10 +1,15 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_db::Cancelable; | 3 | use ra_db::Cancelable; |
4 | use ra_syntax::ast::{self, NameOwner, StructFlavor, AstNode}; | 4 | use ra_syntax::{ |
5 | SyntaxNode, | ||
6 | ast::{self, NameOwner, StructFlavor, AstNode} | ||
7 | }; | ||
5 | 8 | ||
6 | use crate::{ | 9 | use crate::{ |
7 | DefId, Name, AsName, Struct, Enum, HirDatabase, DefKind, | 10 | DefId, DefLoc, Name, AsName, Struct, Enum, EnumVariant, |
11 | HirDatabase, DefKind, | ||
12 | SourceItemId, | ||
8 | type_ref::TypeRef, | 13 | type_ref::TypeRef, |
9 | }; | 14 | }; |
10 | 15 | ||
@@ -45,33 +50,37 @@ impl StructData { | |||
45 | } | 50 | } |
46 | } | 51 | } |
47 | 52 | ||
48 | impl Enum { | 53 | fn get_def_id( |
49 | pub(crate) fn new(def_id: DefId) -> Self { | 54 | db: &impl HirDatabase, |
50 | Enum { def_id } | 55 | same_file_loc: &DefLoc, |
51 | } | 56 | node: &SyntaxNode, |
57 | expected_kind: DefKind, | ||
58 | ) -> DefId { | ||
59 | let file_id = same_file_loc.source_item_id.file_id; | ||
60 | let file_items = db.file_items(file_id); | ||
61 | |||
62 | let item_id = file_items.id_of(file_id, node); | ||
63 | let source_item_id = SourceItemId { | ||
64 | item_id: Some(item_id), | ||
65 | ..same_file_loc.source_item_id | ||
66 | }; | ||
67 | let loc = DefLoc { | ||
68 | kind: expected_kind, | ||
69 | source_item_id: source_item_id, | ||
70 | ..*same_file_loc | ||
71 | }; | ||
72 | loc.id(db) | ||
52 | } | 73 | } |
53 | 74 | ||
54 | #[derive(Debug, Clone, PartialEq, Eq)] | 75 | #[derive(Debug, Clone, PartialEq, Eq)] |
55 | pub struct EnumData { | 76 | pub struct EnumData { |
56 | pub(crate) name: Option<Name>, | 77 | pub(crate) name: Option<Name>, |
57 | pub(crate) variants: Vec<(Name, Arc<VariantData>)>, | 78 | pub(crate) variants: Vec<(Name, EnumVariant)>, |
58 | } | 79 | } |
59 | 80 | ||
60 | impl EnumData { | 81 | impl EnumData { |
61 | fn new(enum_def: &ast::EnumDef) -> Self { | 82 | fn new(enum_def: &ast::EnumDef, variants: Vec<(Name, EnumVariant)>) -> Self { |
62 | let name = enum_def.name().map(|n| n.as_name()); | 83 | 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 } | 84 | EnumData { name, variants } |
76 | } | 85 | } |
77 | 86 | ||
@@ -83,7 +92,64 @@ impl EnumData { | |||
83 | assert!(def_loc.kind == DefKind::Enum); | 92 | assert!(def_loc.kind == DefKind::Enum); |
84 | let syntax = db.file_item(def_loc.source_item_id); | 93 | 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"); | 94 | let enum_def = ast::EnumDef::cast(&syntax).expect("enum def should point to EnumDef node"); |
86 | Ok(Arc::new(EnumData::new(enum_def))) | 95 | let variants = if let Some(vl) = enum_def.variant_list() { |
96 | vl.variants() | ||
97 | .filter_map(|variant_def| { | ||
98 | let name = variant_def.name().map(|n| n.as_name()); | ||
99 | |||
100 | name.map(|n| { | ||
101 | let def_id = | ||
102 | get_def_id(db, &def_loc, variant_def.syntax(), DefKind::EnumVariant); | ||
103 | (n, EnumVariant::new(def_id)) | ||
104 | }) | ||
105 | }) | ||
106 | .collect() | ||
107 | } else { | ||
108 | Vec::new() | ||
109 | }; | ||
110 | Ok(Arc::new(EnumData::new(enum_def, variants))) | ||
111 | } | ||
112 | } | ||
113 | |||
114 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
115 | pub struct EnumVariantData { | ||
116 | pub(crate) name: Option<Name>, | ||
117 | pub(crate) variant_data: Arc<VariantData>, | ||
118 | pub(crate) parent_enum: Enum, | ||
119 | } | ||
120 | |||
121 | impl EnumVariantData { | ||
122 | fn new(variant_def: &ast::EnumVariant, parent_enum: Enum) -> EnumVariantData { | ||
123 | let name = variant_def.name().map(|n| n.as_name()); | ||
124 | let variant_data = VariantData::new(variant_def.flavor()); | ||
125 | let variant_data = Arc::new(variant_data); | ||
126 | EnumVariantData { | ||
127 | name, | ||
128 | variant_data, | ||
129 | parent_enum, | ||
130 | } | ||
131 | } | ||
132 | |||
133 | pub(crate) fn enum_variant_data_query( | ||
134 | db: &impl HirDatabase, | ||
135 | def_id: DefId, | ||
136 | ) -> Cancelable<Arc<EnumVariantData>> { | ||
137 | let def_loc = def_id.loc(db); | ||
138 | assert!(def_loc.kind == DefKind::EnumVariant); | ||
139 | let syntax = db.file_item(def_loc.source_item_id); | ||
140 | let variant_def = ast::EnumVariant::cast(&syntax) | ||
141 | .expect("enum variant def should point to EnumVariant node"); | ||
142 | let enum_node = syntax | ||
143 | .parent() | ||
144 | .expect("enum variant should have enum variant list ancestor") | ||
145 | .parent() | ||
146 | .expect("enum variant list should have enum ancestor"); | ||
147 | let enum_def_id = get_def_id(db, &def_loc, enum_node, DefKind::Enum); | ||
148 | |||
149 | Ok(Arc::new(EnumVariantData::new( | ||
150 | variant_def, | ||
151 | Enum::new(enum_def_id), | ||
152 | ))) | ||
87 | } | 153 | } |
88 | } | 154 | } |
89 | 155 | ||