aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/adt.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/adt.rs')
-rw-r--r--crates/ra_hir/src/adt.rs108
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 @@
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::{
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
48impl Enum { 53fn 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)]
55pub struct EnumData { 76pub 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
60impl EnumData { 81impl 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)]
115pub struct EnumVariantData {
116 pub(crate) name: Option<Name>,
117 pub(crate) variant_data: Arc<VariantData>,
118 pub(crate) parent_enum: Enum,
119}
120
121impl 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