aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/adt.rs55
-rw-r--r--crates/ra_hir/src/code_model_api.rs67
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_ide_api/src/completion/complete_dot.rs14
-rw-r--r--crates/ra_ide_api/src/completion/completion_item.rs11
5 files changed, 88 insertions, 61 deletions
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index 602e7db74..d30390f25 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -4,7 +4,7 @@ use ra_db::Cancelable;
4use ra_syntax::ast::{self, NameOwner, StructFlavor, AstNode}; 4use ra_syntax::ast::{self, NameOwner, StructFlavor, AstNode};
5 5
6use crate::{ 6use crate::{
7 DefId, Name, AsName, Struct, Enum, VariantData, StructField, HirDatabase, DefKind, 7 DefId, Name, AsName, Struct, Enum, HirDatabase, DefKind,
8 type_ref::TypeRef, 8 type_ref::TypeRef,
9}; 9};
10 10
@@ -12,6 +12,10 @@ impl Struct {
12 pub(crate) fn new(def_id: DefId) -> Self { 12 pub(crate) fn new(def_id: DefId) -> Self {
13 Struct { def_id } 13 Struct { def_id }
14 } 14 }
15
16 pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Cancelable<Arc<VariantData>> {
17 Ok(db.struct_data(self.def_id)?.variant_data.clone())
18 }
15} 19}
16 20
17#[derive(Debug, Clone, PartialEq, Eq)] 21#[derive(Debug, Clone, PartialEq, Eq)]
@@ -83,6 +87,51 @@ impl EnumData {
83 } 87 }
84} 88}
85 89
90/// A single field of an enum variant or struct
91#[derive(Debug, Clone, PartialEq, Eq)]
92pub struct StructField {
93 pub(crate) name: Name,
94 pub(crate) type_ref: TypeRef,
95}
96
97/// Fields of an enum variant or struct
98#[derive(Debug, Clone, PartialEq, Eq)]
99pub enum VariantData {
100 Struct(Vec<StructField>),
101 Tuple(Vec<StructField>),
102 Unit,
103}
104
105impl VariantData {
106 pub fn fields(&self) -> &[StructField] {
107 match self {
108 VariantData::Struct(fields) | VariantData::Tuple(fields) => fields,
109 _ => &[],
110 }
111 }
112
113 pub fn is_struct(&self) -> bool {
114 match self {
115 VariantData::Struct(..) => true,
116 _ => false,
117 }
118 }
119
120 pub fn is_tuple(&self) -> bool {
121 match self {
122 VariantData::Tuple(..) => true,
123 _ => false,
124 }
125 }
126
127 pub fn is_unit(&self) -> bool {
128 match self {
129 VariantData::Unit => true,
130 _ => false,
131 }
132 }
133}
134
86impl VariantData { 135impl VariantData {
87 fn new(flavor: StructFlavor) -> Self { 136 fn new(flavor: StructFlavor) -> Self {
88 match flavor { 137 match flavor {
@@ -114,7 +163,7 @@ impl VariantData {
114 pub(crate) fn get_field_type_ref(&self, field_name: &Name) -> Option<&TypeRef> { 163 pub(crate) fn get_field_type_ref(&self, field_name: &Name) -> Option<&TypeRef> {
115 self.fields() 164 self.fields()
116 .iter() 165 .iter()
117 .find(|f| f.name() == field_name) 166 .find(|f| f.name == *field_name)
118 .map(|f| f.type_ref()) 167 .map(|f| &f.type_ref)
119 } 168 }
120} 169}
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 66c016180..fa3e4baa7 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -5,12 +5,13 @@ use ra_db::{CrateId, Cancelable, FileId};
5use ra_syntax::{ast, TreePtr, SyntaxNode}; 5use ra_syntax::{ast, TreePtr, SyntaxNode};
6 6
7use crate::{ 7use crate::{
8 Name, DefId, Path, PerNs, ScopesWithSyntaxMapping, 8 Name, DefId, Path, PerNs, ScopesWithSyntaxMapping, Ty,
9 type_ref::TypeRef, 9 type_ref::TypeRef,
10 nameres::ModuleScope, 10 nameres::ModuleScope,
11 db::HirDatabase, 11 db::HirDatabase,
12 expr::BodySyntaxMapping, 12 expr::BodySyntaxMapping,
13 ty::InferenceResult, 13 ty::InferenceResult,
14 adt::VariantData,
14}; 15};
15 16
16/// hir::Crate describes a single crate. It's the main interface with which 17/// hir::Crate describes a single crate. It's the main interface with which
@@ -137,58 +138,18 @@ impl Module {
137 } 138 }
138} 139}
139 140
140/// A single field of an enum variant or struct 141#[derive(Debug, Clone, PartialEq, Eq, Hash)]
141#[derive(Debug, Clone, PartialEq, Eq)]
142pub struct StructField { 142pub struct StructField {
143 pub(crate) name: Name, 143 struct_: Struct,
144 pub(crate) type_ref: TypeRef, 144 name: Name,
145} 145}
146 146
147impl StructField { 147impl StructField {
148 pub fn name(&self) -> &Name { 148 pub fn name(&self) -> &Name {
149 &self.name 149 &self.name
150 } 150 }
151 151 pub fn ty(&self, db: &impl HirDatabase) -> Cancelable<Option<Ty>> {
152 pub fn type_ref(&self) -> &TypeRef { 152 db.type_for_field(self.struct_.def_id, self.name.clone())
153 &self.type_ref
154 }
155}
156
157/// Fields of an enum variant or struct
158#[derive(Debug, Clone, PartialEq, Eq)]
159pub enum VariantData {
160 Struct(Vec<StructField>),
161 Tuple(Vec<StructField>),
162 Unit,
163}
164
165impl VariantData {
166 pub fn fields(&self) -> &[StructField] {
167 match self {
168 VariantData::Struct(fields) | VariantData::Tuple(fields) => fields,
169 _ => &[],
170 }
171 }
172
173 pub fn is_struct(&self) -> bool {
174 match self {
175 VariantData::Struct(..) => true,
176 _ => false,
177 }
178 }
179
180 pub fn is_tuple(&self) -> bool {
181 match self {
182 VariantData::Tuple(..) => true,
183 _ => false,
184 }
185 }
186
187 pub fn is_unit(&self) -> bool {
188 match self {
189 VariantData::Unit => true,
190 _ => false,
191 }
192 } 153 }
193} 154}
194 155
@@ -206,8 +167,18 @@ impl Struct {
206 Ok(db.struct_data(self.def_id)?.name.clone()) 167 Ok(db.struct_data(self.def_id)?.name.clone())
207 } 168 }
208 169
209 pub fn variant_data(&self, db: &impl HirDatabase) -> Cancelable<Arc<VariantData>> { 170 pub fn fields(&self, db: &impl HirDatabase) -> Cancelable<Vec<StructField>> {
210 Ok(db.struct_data(self.def_id)?.variant_data.clone()) 171 let res = db
172 .struct_data(self.def_id)?
173 .variant_data
174 .fields()
175 .iter()
176 .map(|it| StructField {
177 struct_: self.clone(),
178 name: it.name.clone(),
179 })
180 .collect();
181 Ok(res)
211 } 182 }
212} 183}
213 184
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index ca7f395a8..1b6b72c98 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -56,6 +56,6 @@ pub use self::code_model_api::{
56 Crate, CrateDependency, 56 Crate, CrateDependency,
57 Def, 57 Def,
58 Module, ModuleSource, Problem, 58 Module, ModuleSource, Problem,
59 Struct, Enum, VariantData, StructField, 59 Struct, Enum,
60 Function, FnSignature, 60 Function, FnSignature,
61}; 61};
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs
index 5d4e60dc5..65bba6dc7 100644
--- a/crates/ra_ide_api/src/completion/complete_dot.rs
+++ b/crates/ra_ide_api/src/completion/complete_dot.rs
@@ -28,13 +28,13 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
28 Ty::Adt { def_id, .. } => { 28 Ty::Adt { def_id, .. } => {
29 match def_id.resolve(ctx.db)? { 29 match def_id.resolve(ctx.db)? {
30 Def::Struct(s) => { 30 Def::Struct(s) => {
31 let variant_data = s.variant_data(ctx.db)?; 31 for field in s.fields(ctx.db)? {
32 for field in variant_data.fields() {
33 CompletionItem::new( 32 CompletionItem::new(
34 CompletionKind::Reference, 33 CompletionKind::Reference,
35 field.name().to_string(), 34 field.name().to_string(),
36 ) 35 )
37 .kind(CompletionItemKind::Field) 36 .kind(CompletionItemKind::Field)
37 .set_detail(field.ty(ctx.db)?.map(|ty| ty.to_string()))
38 .add_to(acc); 38 .add_to(acc);
39 } 39 }
40 } 40 }
@@ -72,7 +72,7 @@ mod tests {
72 a.<|> 72 a.<|>
73 } 73 }
74 ", 74 ",
75 r#"the_field"#, 75 r#"the_field "u32""#,
76 ); 76 );
77 } 77 }
78 78
@@ -80,14 +80,14 @@ mod tests {
80 fn test_struct_field_completion_self() { 80 fn test_struct_field_completion_self() {
81 check_ref_completion( 81 check_ref_completion(
82 r" 82 r"
83 struct A { the_field: u32 } 83 struct A { the_field: (u32,) }
84 impl A { 84 impl A {
85 fn foo(self) { 85 fn foo(self) {
86 self.<|> 86 self.<|>
87 } 87 }
88 } 88 }
89 ", 89 ",
90 r#"the_field"#, 90 r#"the_field "(u32,)""#,
91 ); 91 );
92 } 92 }
93 93
@@ -95,14 +95,14 @@ mod tests {
95 fn test_struct_field_completion_autoderef() { 95 fn test_struct_field_completion_autoderef() {
96 check_ref_completion( 96 check_ref_completion(
97 r" 97 r"
98 struct A { the_field: u32 } 98 struct A { the_field: (u32, i32) }
99 impl A { 99 impl A {
100 fn foo(&self) { 100 fn foo(&self) {
101 self.<|> 101 self.<|>
102 } 102 }
103 } 103 }
104 ", 104 ",
105 r#"the_field"#, 105 r#"the_field "(u32, i32)""#,
106 ); 106 );
107 } 107 }
108 108
diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs
index d707a84ef..334449fae 100644
--- a/crates/ra_ide_api/src/completion/completion_item.rs
+++ b/crates/ra_ide_api/src/completion/completion_item.rs
@@ -126,8 +126,12 @@ impl Builder {
126 self.kind = Some(kind); 126 self.kind = Some(kind);
127 self 127 self
128 } 128 }
129 pub(crate) fn detail(mut self, detail: impl Into<String>) -> Builder { 129 #[allow(unused)]
130 self.detail = Some(detail.into()); 130 pub(crate) fn detail(self, detail: impl Into<String>) -> Builder {
131 self.set_detail(Some(detail))
132 }
133 pub(crate) fn set_detail(mut self, detail: Option<impl Into<String>>) -> Builder {
134 self.detail = detail.map(Into::into);
131 self 135 self
132 } 136 }
133 pub(super) fn from_resolution( 137 pub(super) fn from_resolution(
@@ -239,6 +243,9 @@ impl Completions {
239 } else { 243 } else {
240 res.push_str(&c.label); 244 res.push_str(&c.label);
241 } 245 }
246 if let Some(detail) = &c.detail {
247 res.push_str(&format!(" {:?}", detail));
248 }
242 if let Some(snippet) = &c.snippet { 249 if let Some(snippet) = &c.snippet {
243 res.push_str(&format!(" {:?}", snippet)); 250 res.push_str(&format!(" {:?}", snippet));
244 } 251 }