aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/completion
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/completion')
-rw-r--r--crates/ra_ide/src/completion/complete_dot.rs20
-rw-r--r--crates/ra_ide/src/completion/complete_path.rs28
-rw-r--r--crates/ra_ide/src/completion/complete_snippet.rs8
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs10
4 files changed, 38 insertions, 28 deletions
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs
index 210a685e4..2ca78c927 100644
--- a/crates/ra_ide/src/completion/complete_dot.rs
+++ b/crates/ra_ide/src/completion/complete_dot.rs
@@ -27,7 +27,7 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
27 complete_methods(acc, ctx, &receiver_ty); 27 complete_methods(acc, ctx, &receiver_ty);
28 28
29 // Suggest .await syntax for types that implement Future trait 29 // Suggest .await syntax for types that implement Future trait
30 if ctx.analyzer.impls_future(ctx.db, receiver_ty) { 30 if receiver_ty.impls_future(ctx.db) {
31 CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await") 31 CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await")
32 .detail("expr.await") 32 .detail("expr.await")
33 .insert_text("await") 33 .insert_text("await")
@@ -53,13 +53,16 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Ty
53} 53}
54 54
55fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) { 55fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) {
56 let mut seen_methods = FxHashSet::default(); 56 if let Some(krate) = ctx.module.map(|it| it.krate()) {
57 ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| { 57 let mut seen_methods = FxHashSet::default();
58 if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) { 58 let traits_in_scope = ctx.analyzer.traits_in_scope(ctx.db);
59 acc.add_function(ctx, func); 59 receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| {
60 } 60 if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) {
61 None::<()> 61 acc.add_function(ctx, func);
62 }); 62 }
63 None::<()>
64 });
65 }
63} 66}
64 67
65#[cfg(test)] 68#[cfg(test)]
@@ -525,6 +528,7 @@ mod tests {
525 528
526 //- /std/lib.rs 529 //- /std/lib.rs
527 pub mod future { 530 pub mod future {
531 #[lang = "future_trait"]
528 pub trait Future {} 532 pub trait Future {}
529 } 533 }
530 "###, CompletionKind::Keyword), 534 "###, CompletionKind::Keyword),
diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs
index cc1f7c830..af24e9f48 100644
--- a/crates/ra_ide/src/completion/complete_path.rs
+++ b/crates/ra_ide/src/completion/complete_path.rs
@@ -26,7 +26,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
26 } 26 }
27 if let ScopeDef::Unknown = def { 27 if let ScopeDef::Unknown = def {
28 if let Some(name_ref) = ctx.name_ref_syntax.as_ref() { 28 if let Some(name_ref) = ctx.name_ref_syntax.as_ref() {
29 if &name_ref.syntax().text() == name.to_string().as_str() { 29 if name_ref.syntax().text() == name.to_string().as_str() {
30 // for `use self::foo<|>`, don't suggest `foo` as a completion 30 // for `use self::foo<|>`, don't suggest `foo` as a completion
31 tested_by!(dont_complete_current_use); 31 tested_by!(dont_complete_current_use);
32 continue; 32 continue;
@@ -49,22 +49,24 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
49 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db), 49 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
50 _ => unreachable!(), 50 _ => unreachable!(),
51 }; 51 };
52 ctx.analyzer.iterate_path_candidates(ctx.db, &ty, None, |_ty, item| {
53 match item {
54 hir::AssocItem::Function(func) => {
55 if !func.has_self_param(ctx.db) {
56 acc.add_function(ctx, func);
57 }
58 }
59 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
60 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
61 }
62 None::<()>
63 });
64 // Iterate assoc types separately 52 // Iterate assoc types separately
65 // FIXME: complete T::AssocType 53 // FIXME: complete T::AssocType
66 let krate = ctx.module.map(|m| m.krate()); 54 let krate = ctx.module.map(|m| m.krate());
67 if let Some(krate) = krate { 55 if let Some(krate) = krate {
56 let traits_in_scope = ctx.analyzer.traits_in_scope(ctx.db);
57 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
58 match item {
59 hir::AssocItem::Function(func) => {
60 if !func.has_self_param(ctx.db) {
61 acc.add_function(ctx, func);
62 }
63 }
64 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
65 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
66 }
67 None::<()>
68 });
69
68 ty.iterate_impl_items(ctx.db, krate, |item| { 70 ty.iterate_impl_items(ctx.db, krate, |item| {
69 match item { 71 match item {
70 hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {} 72 hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {}
diff --git a/crates/ra_ide/src/completion/complete_snippet.rs b/crates/ra_ide/src/completion/complete_snippet.rs
index 1f2988b36..731b4fd82 100644
--- a/crates/ra_ide/src/completion/complete_snippet.rs
+++ b/crates/ra_ide/src/completion/complete_snippet.rs
@@ -36,6 +36,7 @@ fn ${1:feature}() {
36 .lookup_by("tfn") 36 .lookup_by("tfn")
37 .add_to(acc); 37 .add_to(acc);
38 38
39 snippet(ctx, "macro_rules", "macro_rules! $1 {\n\t($2) => {\n\t\t$0\n\t};\n}").add_to(acc);
39 snippet(ctx, "pub(crate)", "pub(crate) $0").add_to(acc); 40 snippet(ctx, "pub(crate)", "pub(crate) $0").add_to(acc);
40} 41}
41 42
@@ -107,6 +108,13 @@ mod tests {
107 lookup: "tfn", 108 lookup: "tfn",
108 }, 109 },
109 CompletionItem { 110 CompletionItem {
111 label: "macro_rules",
112 source_range: [78; 78),
113 delete: [78; 78),
114 insert: "macro_rules! $1 {\n\t($2) => {\n\t\t$0\n\t};\n}",
115 kind: Snippet,
116 },
117 CompletionItem {
110 label: "pub(crate)", 118 label: "pub(crate)",
111 source_range: [78; 78), 119 source_range: [78; 78),
112 delete: [78; 78), 120 delete: [78; 78),
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs
index 48d69f7e5..deaacda6c 100644
--- a/crates/ra_ide/src/completion/completion_context.rs
+++ b/crates/ra_ide/src/completion/completion_context.rs
@@ -52,15 +52,11 @@ impl<'a> CompletionContext<'a> {
52 original_parse: &'a Parse<ast::SourceFile>, 52 original_parse: &'a Parse<ast::SourceFile>,
53 position: FilePosition, 53 position: FilePosition,
54 ) -> Option<CompletionContext<'a>> { 54 ) -> Option<CompletionContext<'a>> {
55 let src = hir::ModuleSource::from_position(db, position); 55 let mut sb = hir::SourceBinder::new(db);
56 let module = hir::Module::from_definition( 56 let module = sb.to_module_def(position.file_id);
57 db,
58 hir::InFile { file_id: position.file_id.into(), value: src },
59 );
60 let token = 57 let token =
61 original_parse.tree().syntax().token_at_offset(position.offset).left_biased()?; 58 original_parse.tree().syntax().token_at_offset(position.offset).left_biased()?;
62 let analyzer = hir::SourceAnalyzer::new( 59 let analyzer = sb.analyze(
63 db,
64 hir::InFile::new(position.file_id.into(), &token.parent()), 60 hir::InFile::new(position.file_id.into(), &token.parent()),
65 Some(position.offset), 61 Some(position.offset),
66 ); 62 );