aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion/src/render.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_completion/src/render.rs')
-rw-r--r--crates/ide_completion/src/render.rs143
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
11mod builder_ext; 11mod builder_ext;
12 12
13use hir::{ 13use hir::{AsAssocItem, HasAttrs, HirDisplay};
14 AsAssocItem, Documentation, HasAttrs, HirDisplay, ModuleDef, Mutability, ScopeDef, Type,
15};
16use ide_db::{ 14use 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
22use crate::{ 20use 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
27use crate::render::{enum_variant::render_variant, function::render_fn, macro_::render_macro};
28
29pub(crate) fn render_field<'a>( 26pub(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
37pub(crate) fn render_tuple_field<'a>( 34pub(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
45pub(crate) fn render_resolution<'a>( 42pub(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
330fn compute_exact_name_match(ctx: &CompletionContext, completion_name: impl Into<String>) -> bool { 337fn 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
335fn compute_ref_match(ctx: &CompletionContext, completion_ty: &hir::Type) -> Option<Mutability> { 341fn 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 };