diff options
Diffstat (limited to 'crates/ide_completion/src/completions.rs')
-rw-r--r-- | crates/ide_completion/src/completions.rs | 62 |
1 files changed, 57 insertions, 5 deletions
diff --git a/crates/ide_completion/src/completions.rs b/crates/ide_completion/src/completions.rs index 151bf3783..0f0553a65 100644 --- a/crates/ide_completion/src/completions.rs +++ b/crates/ide_completion/src/completions.rs | |||
@@ -18,8 +18,10 @@ pub(crate) mod unqualified_path; | |||
18 | 18 | ||
19 | use std::iter; | 19 | use std::iter; |
20 | 20 | ||
21 | use hir::known; | 21 | use either::Either; |
22 | use hir::{known, HasVisibility}; | ||
22 | use ide_db::SymbolKind; | 23 | use ide_db::SymbolKind; |
24 | use rustc_hash::FxHashSet; | ||
23 | 25 | ||
24 | use crate::{ | 26 | use crate::{ |
25 | item::{Builder, CompletionKind}, | 27 | item::{Builder, CompletionKind}, |
@@ -69,18 +71,25 @@ impl Completions { | |||
69 | items.into_iter().for_each(|item| self.add(item.into())) | 71 | items.into_iter().for_each(|item| self.add(item.into())) |
70 | } | 72 | } |
71 | 73 | ||
72 | pub(crate) fn add_field(&mut self, ctx: &CompletionContext, field: hir::Field, ty: &hir::Type) { | 74 | pub(crate) fn add_field( |
73 | let item = render_field(RenderContext::new(ctx), field, ty); | 75 | &mut self, |
76 | ctx: &CompletionContext, | ||
77 | receiver: Option<String>, | ||
78 | field: hir::Field, | ||
79 | ty: &hir::Type, | ||
80 | ) { | ||
81 | let item = render_field(RenderContext::new(ctx), receiver, field, ty); | ||
74 | self.add(item); | 82 | self.add(item); |
75 | } | 83 | } |
76 | 84 | ||
77 | pub(crate) fn add_tuple_field( | 85 | pub(crate) fn add_tuple_field( |
78 | &mut self, | 86 | &mut self, |
79 | ctx: &CompletionContext, | 87 | ctx: &CompletionContext, |
88 | receiver: Option<String>, | ||
80 | field: usize, | 89 | field: usize, |
81 | ty: &hir::Type, | 90 | ty: &hir::Type, |
82 | ) { | 91 | ) { |
83 | let item = render_tuple_field(RenderContext::new(ctx), field, ty); | 92 | let item = render_tuple_field(RenderContext::new(ctx), receiver, field, ty); |
84 | self.add(item); | 93 | self.add(item); |
85 | } | 94 | } |
86 | 95 | ||
@@ -132,9 +141,11 @@ impl Completions { | |||
132 | &mut self, | 141 | &mut self, |
133 | ctx: &CompletionContext, | 142 | ctx: &CompletionContext, |
134 | func: hir::Function, | 143 | func: hir::Function, |
144 | receiver: Option<String>, | ||
135 | local_name: Option<hir::Name>, | 145 | local_name: Option<hir::Name>, |
136 | ) { | 146 | ) { |
137 | if let Some(item) = render_method(RenderContext::new(ctx), None, local_name, func) { | 147 | if let Some(item) = render_method(RenderContext::new(ctx), None, receiver, local_name, func) |
148 | { | ||
138 | self.add(item) | 149 | self.add(item) |
139 | } | 150 | } |
140 | } | 151 | } |
@@ -243,3 +254,44 @@ fn complete_enum_variants( | |||
243 | } | 254 | } |
244 | } | 255 | } |
245 | } | 256 | } |
257 | |||
258 | fn complete_fields( | ||
259 | ctx: &CompletionContext, | ||
260 | receiver: &hir::Type, | ||
261 | mut f: impl FnMut(Either<hir::Field, usize>, hir::Type), | ||
262 | ) { | ||
263 | for receiver in receiver.autoderef(ctx.db) { | ||
264 | for (field, ty) in receiver.fields(ctx.db) { | ||
265 | if ctx.scope.module().map_or(false, |m| !field.is_visible_from(ctx.db, m)) { | ||
266 | // Skip private field. FIXME: If the definition location of the | ||
267 | // field is editable, we should show the completion | ||
268 | continue; | ||
269 | } | ||
270 | f(Either::Left(field), ty); | ||
271 | } | ||
272 | for (i, ty) in receiver.tuple_fields(ctx.db).into_iter().enumerate() { | ||
273 | // FIXME: Handle visibility | ||
274 | f(Either::Right(i), ty); | ||
275 | } | ||
276 | } | ||
277 | } | ||
278 | |||
279 | fn complete_methods( | ||
280 | ctx: &CompletionContext, | ||
281 | receiver: &hir::Type, | ||
282 | mut f: impl FnMut(hir::Function), | ||
283 | ) { | ||
284 | if let Some(krate) = ctx.krate { | ||
285 | let mut seen_methods = FxHashSet::default(); | ||
286 | let traits_in_scope = ctx.scope.traits_in_scope(); | ||
287 | receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| { | ||
288 | if func.self_param(ctx.db).is_some() | ||
289 | && ctx.scope.module().map_or(true, |m| func.is_visible_from(ctx.db, m)) | ||
290 | && seen_methods.insert(func.name(ctx.db)) | ||
291 | { | ||
292 | f(func); | ||
293 | } | ||
294 | None::<()> | ||
295 | }); | ||
296 | } | ||
297 | } | ||