diff options
Diffstat (limited to 'crates/ide_completion/src/render.rs')
-rw-r--r-- | crates/ide_completion/src/render.rs | 143 |
1 files changed, 76 insertions, 67 deletions
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs index 91300c56e..425dd0247 100644 --- a/crates/ide_completion/src/render.rs +++ b/crates/ide_completion/src/render.rs | |||
@@ -10,9 +10,7 @@ pub(crate) mod type_alias; | |||
10 | 10 | ||
11 | mod builder_ext; | 11 | mod builder_ext; |
12 | 12 | ||
13 | use hir::{ | 13 | use hir::{AsAssocItem, HasAttrs, HirDisplay}; |
14 | AsAssocItem, Documentation, HasAttrs, HirDisplay, ModuleDef, Mutability, ScopeDef, Type, | ||
15 | }; | ||
16 | use ide_db::{ | 14 | use ide_db::{ |
17 | helpers::{item_name, SnippetCap}, | 15 | helpers::{item_name, SnippetCap}, |
18 | RootDatabase, SymbolKind, | 16 | RootDatabase, SymbolKind, |
@@ -21,31 +19,30 @@ use syntax::TextRange; | |||
21 | 19 | ||
22 | use crate::{ | 20 | use crate::{ |
23 | item::{CompletionRelevanceTypeMatch, ImportEdit}, | 21 | item::{CompletionRelevanceTypeMatch, ImportEdit}, |
22 | render::{enum_variant::render_variant, function::render_fn, macro_::render_macro}, | ||
24 | CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, CompletionRelevance, | 23 | CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, CompletionRelevance, |
25 | }; | 24 | }; |
26 | 25 | ||
27 | use crate::render::{enum_variant::render_variant, function::render_fn, macro_::render_macro}; | ||
28 | |||
29 | pub(crate) fn render_field<'a>( | 26 | pub(crate) fn render_field<'a>( |
30 | ctx: RenderContext<'a>, | 27 | ctx: RenderContext<'a>, |
31 | field: hir::Field, | 28 | field: hir::Field, |
32 | ty: &Type, | 29 | ty: &hir::Type, |
33 | ) -> CompletionItem { | 30 | ) -> CompletionItem { |
34 | Render::new(ctx).add_field(field, ty) | 31 | Render::new(ctx).render_field(field, ty) |
35 | } | 32 | } |
36 | 33 | ||
37 | pub(crate) fn render_tuple_field<'a>( | 34 | pub(crate) fn render_tuple_field<'a>( |
38 | ctx: RenderContext<'a>, | 35 | ctx: RenderContext<'a>, |
39 | field: usize, | 36 | field: usize, |
40 | ty: &Type, | 37 | ty: &hir::Type, |
41 | ) -> CompletionItem { | 38 | ) -> CompletionItem { |
42 | Render::new(ctx).add_tuple_field(field, ty) | 39 | Render::new(ctx).render_tuple_field(field, ty) |
43 | } | 40 | } |
44 | 41 | ||
45 | pub(crate) fn render_resolution<'a>( | 42 | pub(crate) fn render_resolution<'a>( |
46 | ctx: RenderContext<'a>, | 43 | ctx: RenderContext<'a>, |
47 | local_name: String, | 44 | local_name: hir::Name, |
48 | resolution: &ScopeDef, | 45 | resolution: &hir::ScopeDef, |
49 | ) -> Option<CompletionItem> { | 46 | ) -> Option<CompletionItem> { |
50 | Render::new(ctx).render_resolution(local_name, None, resolution) | 47 | Render::new(ctx).render_resolution(local_name, None, resolution) |
51 | } | 48 | } |
@@ -54,12 +51,12 @@ pub(crate) fn render_resolution_with_import<'a>( | |||
54 | ctx: RenderContext<'a>, | 51 | ctx: RenderContext<'a>, |
55 | import_edit: ImportEdit, | 52 | import_edit: ImportEdit, |
56 | ) -> Option<CompletionItem> { | 53 | ) -> Option<CompletionItem> { |
57 | let resolution = ScopeDef::from(import_edit.import.original_item); | 54 | let resolution = hir::ScopeDef::from(import_edit.import.original_item); |
58 | let local_name = match resolution { | 55 | let local_name = match resolution { |
59 | ScopeDef::ModuleDef(ModuleDef::Function(f)) => f.name(ctx.completion.db).to_string(), | 56 | hir::ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db), |
60 | ScopeDef::ModuleDef(ModuleDef::Const(c)) => c.name(ctx.completion.db)?.to_string(), | 57 | hir::ScopeDef::ModuleDef(hir::ModuleDef::Const(c)) => c.name(ctx.completion.db)?, |
61 | ScopeDef::ModuleDef(ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db).to_string(), | 58 | hir::ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db), |
62 | _ => item_name(ctx.db(), import_edit.import.original_item)?.to_string(), | 59 | _ => item_name(ctx.db(), import_edit.import.original_item)?, |
63 | }; | 60 | }; |
64 | Render::new(ctx).render_resolution(local_name, Some(import_edit), &resolution).map( | 61 | Render::new(ctx).render_resolution(local_name, Some(import_edit), &resolution).map( |
65 | |mut item| { | 62 | |mut item| { |
@@ -113,7 +110,7 @@ impl<'a> RenderContext<'a> { | |||
113 | || assoc.containing_trait(db).map(|trait_| self.is_deprecated(trait_)).unwrap_or(false) | 110 | || assoc.containing_trait(db).map(|trait_| self.is_deprecated(trait_)).unwrap_or(false) |
114 | } | 111 | } |
115 | 112 | ||
116 | fn docs(&self, node: impl HasAttrs) -> Option<Documentation> { | 113 | fn docs(&self, node: impl HasAttrs) -> Option<hir::Documentation> { |
117 | node.docs(self.db()) | 114 | node.docs(self.db()) |
118 | } | 115 | } |
119 | } | 116 | } |
@@ -129,14 +126,11 @@ impl<'a> Render<'a> { | |||
129 | Render { ctx } | 126 | Render { ctx } |
130 | } | 127 | } |
131 | 128 | ||
132 | fn add_field(&mut self, field: hir::Field, ty: &Type) -> CompletionItem { | 129 | fn render_field(&self, field: hir::Field, ty: &hir::Type) -> CompletionItem { |
133 | let is_deprecated = self.ctx.is_deprecated(field); | 130 | let is_deprecated = self.ctx.is_deprecated(field); |
134 | let name = field.name(self.ctx.db()); | 131 | let name = field.name(self.ctx.db()).to_string(); |
135 | let mut item = CompletionItem::new( | 132 | let mut item = |
136 | CompletionKind::Reference, | 133 | CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), name.clone()); |
137 | self.ctx.source_range(), | ||
138 | name.to_string(), | ||
139 | ); | ||
140 | item.kind(SymbolKind::Field) | 134 | item.kind(SymbolKind::Field) |
141 | .detail(ty.display(self.ctx.db()).to_string()) | 135 | .detail(ty.display(self.ctx.db()).to_string()) |
142 | .set_documentation(field.docs(self.ctx.db())) | 136 | .set_documentation(field.docs(self.ctx.db())) |
@@ -144,7 +138,7 @@ impl<'a> Render<'a> { | |||
144 | 138 | ||
145 | item.set_relevance(CompletionRelevance { | 139 | item.set_relevance(CompletionRelevance { |
146 | type_match: compute_type_match(self.ctx.completion, ty), | 140 | type_match: compute_type_match(self.ctx.completion, ty), |
147 | exact_name_match: compute_exact_name_match(self.ctx.completion, name.to_string()), | 141 | exact_name_match: compute_exact_name_match(self.ctx.completion, &name), |
148 | ..CompletionRelevance::default() | 142 | ..CompletionRelevance::default() |
149 | }); | 143 | }); |
150 | 144 | ||
@@ -157,7 +151,7 @@ impl<'a> Render<'a> { | |||
157 | item.build() | 151 | item.build() |
158 | } | 152 | } |
159 | 153 | ||
160 | fn add_tuple_field(&mut self, field: usize, ty: &Type) -> CompletionItem { | 154 | fn render_tuple_field(&self, field: usize, ty: &hir::Type) -> CompletionItem { |
161 | let mut item = CompletionItem::new( | 155 | let mut item = CompletionItem::new( |
162 | CompletionKind::Reference, | 156 | CompletionKind::Reference, |
163 | self.ctx.source_range(), | 157 | self.ctx.source_range(), |
@@ -171,71 +165,82 @@ impl<'a> Render<'a> { | |||
171 | 165 | ||
172 | fn render_resolution( | 166 | fn render_resolution( |
173 | self, | 167 | self, |
174 | local_name: String, | 168 | local_name: hir::Name, |
175 | import_to_add: Option<ImportEdit>, | 169 | import_to_add: Option<ImportEdit>, |
176 | resolution: &ScopeDef, | 170 | resolution: &hir::ScopeDef, |
177 | ) -> Option<CompletionItem> { | 171 | ) -> Option<CompletionItem> { |
178 | let _p = profile::span("render_resolution"); | 172 | let _p = profile::span("render_resolution"); |
179 | use hir::ModuleDef::*; | 173 | use hir::ModuleDef::*; |
180 | 174 | ||
181 | let completion_kind = match resolution { | 175 | let completion_kind = match resolution { |
182 | ScopeDef::ModuleDef(BuiltinType(..)) => CompletionKind::BuiltinType, | 176 | hir::ScopeDef::ModuleDef(BuiltinType(..)) => CompletionKind::BuiltinType, |
183 | _ => CompletionKind::Reference, | 177 | _ => CompletionKind::Reference, |
184 | }; | 178 | }; |
185 | 179 | ||
186 | let kind = match resolution { | 180 | let kind = match resolution { |
187 | ScopeDef::ModuleDef(Function(func)) => { | 181 | hir::ScopeDef::ModuleDef(Function(func)) => { |
188 | return render_fn(self.ctx, import_to_add, Some(local_name), *func); | 182 | return render_fn(self.ctx, import_to_add, Some(local_name), *func); |
189 | } | 183 | } |
190 | ScopeDef::ModuleDef(Variant(_)) if self.ctx.completion.is_pat_or_const.is_some() => { | 184 | hir::ScopeDef::ModuleDef(Variant(_)) |
185 | if self.ctx.completion.is_pat_or_const.is_some() => | ||
186 | { | ||
191 | CompletionItemKind::SymbolKind(SymbolKind::Variant) | 187 | CompletionItemKind::SymbolKind(SymbolKind::Variant) |
192 | } | 188 | } |
193 | ScopeDef::ModuleDef(Variant(var)) => { | 189 | hir::ScopeDef::ModuleDef(Variant(var)) => { |
194 | let item = render_variant(self.ctx, import_to_add, Some(local_name), *var, None); | 190 | let item = render_variant(self.ctx, import_to_add, Some(local_name), *var, None); |
195 | return Some(item); | 191 | return Some(item); |
196 | } | 192 | } |
197 | ScopeDef::MacroDef(mac) => { | 193 | hir::ScopeDef::MacroDef(mac) => { |
198 | let item = render_macro(self.ctx, import_to_add, local_name, *mac); | 194 | let item = render_macro(self.ctx, import_to_add, local_name, *mac); |
199 | return item; | 195 | return item; |
200 | } | 196 | } |
201 | 197 | ||
202 | ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::SymbolKind(SymbolKind::Module), | 198 | hir::ScopeDef::ModuleDef(Module(..)) => { |
203 | ScopeDef::ModuleDef(Adt(adt)) => CompletionItemKind::SymbolKind(match adt { | 199 | CompletionItemKind::SymbolKind(SymbolKind::Module) |
200 | } | ||
201 | hir::ScopeDef::ModuleDef(Adt(adt)) => CompletionItemKind::SymbolKind(match adt { | ||
204 | hir::Adt::Struct(_) => SymbolKind::Struct, | 202 | hir::Adt::Struct(_) => SymbolKind::Struct, |
205 | hir::Adt::Union(_) => SymbolKind::Union, | 203 | hir::Adt::Union(_) => SymbolKind::Union, |
206 | hir::Adt::Enum(_) => SymbolKind::Enum, | 204 | hir::Adt::Enum(_) => SymbolKind::Enum, |
207 | }), | 205 | }), |
208 | ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::SymbolKind(SymbolKind::Const), | 206 | hir::ScopeDef::ModuleDef(Const(..)) => { |
209 | ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::SymbolKind(SymbolKind::Static), | 207 | CompletionItemKind::SymbolKind(SymbolKind::Const) |
210 | ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::SymbolKind(SymbolKind::Trait), | 208 | } |
211 | ScopeDef::ModuleDef(TypeAlias(..)) => { | 209 | hir::ScopeDef::ModuleDef(Static(..)) => { |
210 | CompletionItemKind::SymbolKind(SymbolKind::Static) | ||
211 | } | ||
212 | hir::ScopeDef::ModuleDef(Trait(..)) => { | ||
213 | CompletionItemKind::SymbolKind(SymbolKind::Trait) | ||
214 | } | ||
215 | hir::ScopeDef::ModuleDef(TypeAlias(..)) => { | ||
212 | CompletionItemKind::SymbolKind(SymbolKind::TypeAlias) | 216 | CompletionItemKind::SymbolKind(SymbolKind::TypeAlias) |
213 | } | 217 | } |
214 | ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType, | 218 | hir::ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType, |
215 | ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param { | 219 | hir::ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param { |
216 | hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam, | 220 | hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam, |
217 | hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam, | 221 | hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam, |
218 | hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam, | 222 | hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam, |
219 | }), | 223 | }), |
220 | ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local), | 224 | hir::ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local), |
221 | ScopeDef::Label(..) => CompletionItemKind::SymbolKind(SymbolKind::Label), | 225 | hir::ScopeDef::Label(..) => CompletionItemKind::SymbolKind(SymbolKind::Label), |
222 | ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => { | 226 | hir::ScopeDef::AdtSelfType(..) | hir::ScopeDef::ImplSelfType(..) => { |
223 | CompletionItemKind::SymbolKind(SymbolKind::SelfParam) | 227 | CompletionItemKind::SymbolKind(SymbolKind::SelfParam) |
224 | } | 228 | } |
225 | ScopeDef::Unknown => { | 229 | hir::ScopeDef::Unknown => { |
226 | let mut item = CompletionItem::new( | 230 | let mut item = CompletionItem::new( |
227 | CompletionKind::Reference, | 231 | CompletionKind::Reference, |
228 | self.ctx.source_range(), | 232 | self.ctx.source_range(), |
229 | local_name, | 233 | local_name.to_string(), |
230 | ); | 234 | ); |
231 | item.kind(CompletionItemKind::UnresolvedReference).add_import(import_to_add); | 235 | item.kind(CompletionItemKind::UnresolvedReference).add_import(import_to_add); |
232 | return Some(item.build()); | 236 | return Some(item.build()); |
233 | } | 237 | } |
234 | }; | 238 | }; |
235 | 239 | ||
240 | let local_name = local_name.to_string(); | ||
236 | let mut item = | 241 | let mut item = |
237 | CompletionItem::new(completion_kind, self.ctx.source_range(), local_name.clone()); | 242 | CompletionItem::new(completion_kind, self.ctx.source_range(), local_name.clone()); |
238 | if let ScopeDef::Local(local) = resolution { | 243 | if let hir::ScopeDef::Local(local) = resolution { |
239 | let ty = local.ty(self.ctx.db()); | 244 | let ty = local.ty(self.ctx.db()); |
240 | if !ty.is_unknown() { | 245 | if !ty.is_unknown() { |
241 | item.detail(ty.display(self.ctx.db()).to_string()); | 246 | item.detail(ty.display(self.ctx.db()).to_string()); |
@@ -260,8 +265,10 @@ impl<'a> Render<'a> { | |||
260 | { | 265 | { |
261 | if let Some(cap) = self.ctx.snippet_cap() { | 266 | if let Some(cap) = self.ctx.snippet_cap() { |
262 | let has_non_default_type_params = match resolution { | 267 | let has_non_default_type_params = match resolution { |
263 | ScopeDef::ModuleDef(Adt(it)) => it.has_non_default_type_params(self.ctx.db()), | 268 | hir::ScopeDef::ModuleDef(Adt(it)) => { |
264 | ScopeDef::ModuleDef(TypeAlias(it)) => { | 269 | it.has_non_default_type_params(self.ctx.db()) |
270 | } | ||
271 | hir::ScopeDef::ModuleDef(TypeAlias(it)) => { | ||
265 | it.has_non_default_type_params(self.ctx.db()) | 272 | it.has_non_default_type_params(self.ctx.db()) |
266 | } | 273 | } |
267 | _ => false, | 274 | _ => false, |
@@ -281,26 +288,26 @@ impl<'a> Render<'a> { | |||
281 | Some(item.build()) | 288 | Some(item.build()) |
282 | } | 289 | } |
283 | 290 | ||
284 | fn docs(&self, resolution: &ScopeDef) -> Option<Documentation> { | 291 | fn docs(&self, resolution: &hir::ScopeDef) -> Option<hir::Documentation> { |
285 | use hir::ModuleDef::*; | 292 | use hir::ModuleDef::*; |
286 | match resolution { | 293 | match resolution { |
287 | ScopeDef::ModuleDef(Module(it)) => it.docs(self.ctx.db()), | 294 | hir::ScopeDef::ModuleDef(Module(it)) => it.docs(self.ctx.db()), |
288 | ScopeDef::ModuleDef(Adt(it)) => it.docs(self.ctx.db()), | 295 | hir::ScopeDef::ModuleDef(Adt(it)) => it.docs(self.ctx.db()), |
289 | ScopeDef::ModuleDef(Variant(it)) => it.docs(self.ctx.db()), | 296 | hir::ScopeDef::ModuleDef(Variant(it)) => it.docs(self.ctx.db()), |
290 | ScopeDef::ModuleDef(Const(it)) => it.docs(self.ctx.db()), | 297 | hir::ScopeDef::ModuleDef(Const(it)) => it.docs(self.ctx.db()), |
291 | ScopeDef::ModuleDef(Static(it)) => it.docs(self.ctx.db()), | 298 | hir::ScopeDef::ModuleDef(Static(it)) => it.docs(self.ctx.db()), |
292 | ScopeDef::ModuleDef(Trait(it)) => it.docs(self.ctx.db()), | 299 | hir::ScopeDef::ModuleDef(Trait(it)) => it.docs(self.ctx.db()), |
293 | ScopeDef::ModuleDef(TypeAlias(it)) => it.docs(self.ctx.db()), | 300 | hir::ScopeDef::ModuleDef(TypeAlias(it)) => it.docs(self.ctx.db()), |
294 | _ => None, | 301 | _ => None, |
295 | } | 302 | } |
296 | } | 303 | } |
297 | 304 | ||
298 | fn is_deprecated(&self, resolution: &ScopeDef) -> bool { | 305 | fn is_deprecated(&self, resolution: &hir::ScopeDef) -> bool { |
299 | match resolution { | 306 | match resolution { |
300 | ScopeDef::ModuleDef(it) => self.ctx.is_deprecated_assoc_item(*it), | 307 | hir::ScopeDef::ModuleDef(it) => self.ctx.is_deprecated_assoc_item(*it), |
301 | ScopeDef::MacroDef(it) => self.ctx.is_deprecated(*it), | 308 | hir::ScopeDef::MacroDef(it) => self.ctx.is_deprecated(*it), |
302 | ScopeDef::GenericParam(it) => self.ctx.is_deprecated(*it), | 309 | hir::ScopeDef::GenericParam(it) => self.ctx.is_deprecated(*it), |
303 | ScopeDef::AdtSelfType(it) => self.ctx.is_deprecated(*it), | 310 | hir::ScopeDef::AdtSelfType(it) => self.ctx.is_deprecated(*it), |
304 | _ => false, | 311 | _ => false, |
305 | } | 312 | } |
306 | } | 313 | } |
@@ -327,21 +334,23 @@ fn compute_type_match( | |||
327 | } | 334 | } |
328 | } | 335 | } |
329 | 336 | ||
330 | fn compute_exact_name_match(ctx: &CompletionContext, completion_name: impl Into<String>) -> bool { | 337 | fn compute_exact_name_match(ctx: &CompletionContext, completion_name: &str) -> bool { |
331 | let completion_name = completion_name.into(); | ||
332 | ctx.expected_name.as_ref().map_or(false, |name| name.text() == completion_name) | 338 | ctx.expected_name.as_ref().map_or(false, |name| name.text() == completion_name) |
333 | } | 339 | } |
334 | 340 | ||
335 | fn compute_ref_match(ctx: &CompletionContext, completion_ty: &hir::Type) -> Option<Mutability> { | 341 | fn compute_ref_match( |
342 | ctx: &CompletionContext, | ||
343 | completion_ty: &hir::Type, | ||
344 | ) -> Option<hir::Mutability> { | ||
336 | let expected_type = ctx.expected_type.as_ref()?; | 345 | let expected_type = ctx.expected_type.as_ref()?; |
337 | if completion_ty != expected_type { | 346 | if completion_ty != expected_type { |
338 | let expected_type_without_ref = expected_type.remove_ref()?; | 347 | let expected_type_without_ref = expected_type.remove_ref()?; |
339 | if completion_ty.autoderef(ctx.db).any(|deref_ty| deref_ty == expected_type_without_ref) { | 348 | if completion_ty.autoderef(ctx.db).any(|deref_ty| deref_ty == expected_type_without_ref) { |
340 | cov_mark::hit!(suggest_ref); | 349 | cov_mark::hit!(suggest_ref); |
341 | let mutability = if expected_type.is_mutable_reference() { | 350 | let mutability = if expected_type.is_mutable_reference() { |
342 | Mutability::Mut | 351 | hir::Mutability::Mut |
343 | } else { | 352 | } else { |
344 | Mutability::Shared | 353 | hir::Mutability::Shared |
345 | }; | 354 | }; |
346 | return Some(mutability); | 355 | return Some(mutability); |
347 | }; | 356 | }; |