aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion/src/completions/dot.rs
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2021-05-28 13:02:53 +0100
committerLukas Wirth <[email protected]>2021-05-31 13:52:55 +0100
commitca49fbe0a1f6acc1352f6628c36bb7dfe3a950e5 (patch)
treece49d1f51186dd6f455bccadb73a577988ff457a /crates/ide_completion/src/completions/dot.rs
parentd7cbb49057c4495307d91f5db32465c29c175124 (diff)
Complete `self.` prefixed fields and methods inside methods
Diffstat (limited to 'crates/ide_completion/src/completions/dot.rs')
-rw-r--r--crates/ide_completion/src/completions/dot.rs41
1 files changed, 5 insertions, 36 deletions
diff --git a/crates/ide_completion/src/completions/dot.rs b/crates/ide_completion/src/completions/dot.rs
index fd9738743..93f7bd6d4 100644
--- a/crates/ide_completion/src/completions/dot.rs
+++ b/crates/ide_completion/src/completions/dot.rs
@@ -1,7 +1,6 @@
1//! Completes references after dot (fields and method calls). 1//! Completes references after dot (fields and method calls).
2 2
3use hir::{HasVisibility, Type}; 3use either::Either;
4use rustc_hash::FxHashSet;
5 4
6use crate::{context::CompletionContext, Completions}; 5use crate::{context::CompletionContext, Completions};
7 6
@@ -20,42 +19,12 @@ pub(crate) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
20 if ctx.is_call { 19 if ctx.is_call {
21 cov_mark::hit!(test_no_struct_field_completion_for_method_call); 20 cov_mark::hit!(test_no_struct_field_completion_for_method_call);
22 } else { 21 } else {
23 complete_fields(acc, ctx, &receiver_ty); 22 super::complete_fields(ctx, &receiver_ty, |field, ty| match field {
24 } 23 Either::Left(field) => acc.add_field(ctx, None, field, &ty),
25 complete_methods(acc, ctx, &receiver_ty); 24 Either::Right(tuple_idx) => acc.add_tuple_field(ctx, None, tuple_idx, &ty),
26}
27
28fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) {
29 for receiver in receiver.autoderef(ctx.db) {
30 for (field, ty) in receiver.fields(ctx.db) {
31 if ctx.scope.module().map_or(false, |m| !field.is_visible_from(ctx.db, m)) {
32 // Skip private field. FIXME: If the definition location of the
33 // field is editable, we should show the completion
34 continue;
35 }
36 acc.add_field(ctx, field, &ty);
37 }
38 for (i, ty) in receiver.tuple_fields(ctx.db).into_iter().enumerate() {
39 // FIXME: Handle visibility
40 acc.add_tuple_field(ctx, i, &ty);
41 }
42 }
43}
44
45fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) {
46 if let Some(krate) = ctx.krate {
47 let mut seen_methods = FxHashSet::default();
48 let traits_in_scope = ctx.scope.traits_in_scope();
49 receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| {
50 if func.self_param(ctx.db).is_some()
51 && ctx.scope.module().map_or(true, |m| func.is_visible_from(ctx.db, m))
52 && seen_methods.insert(func.name(ctx.db))
53 {
54 acc.add_method(ctx, func, None);
55 }
56 None::<()>
57 }); 25 });
58 } 26 }
27 super::complete_methods(ctx, &receiver_ty, |func| acc.add_method(ctx, func, None, None));
59} 28}
60 29
61#[cfg(test)] 30#[cfg(test)]