aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/completion/complete_path.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/completion/complete_path.rs')
-rw-r--r--crates/ra_ide/src/completion/complete_path.rs105
1 files changed, 102 insertions, 3 deletions
diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs
index 1a9699466..d2c758571 100644
--- a/crates/ra_ide/src/completion/complete_path.rs
+++ b/crates/ra_ide/src/completion/complete_path.rs
@@ -1,6 +1,6 @@
1//! Completion of paths, including when writing a single name. 1//! Completion of paths, including when writing a single name.
2 2
3use hir::{Adt, PathResolution, ScopeDef}; 3use hir::{Adt, HasVisibility, PathResolution, ScopeDef};
4use ra_syntax::AstNode; 4use ra_syntax::AstNode;
5use test_utils::tested_by; 5use test_utils::tested_by;
6 6
@@ -15,9 +15,10 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
15 Some(PathResolution::Def(def)) => def, 15 Some(PathResolution::Def(def)) => def,
16 _ => return, 16 _ => return,
17 }; 17 };
18 let context_module = ctx.scope().module();
18 match def { 19 match def {
19 hir::ModuleDef::Module(module) => { 20 hir::ModuleDef::Module(module) => {
20 let module_scope = module.scope(ctx.db); 21 let module_scope = module.scope(ctx.db, context_module);
21 for (name, def) in module_scope { 22 for (name, def) in module_scope {
22 if ctx.use_item_syntax.is_some() { 23 if ctx.use_item_syntax.is_some() {
23 if let ScopeDef::Unknown = def { 24 if let ScopeDef::Unknown = def {
@@ -51,6 +52,9 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
51 if let Some(krate) = krate { 52 if let Some(krate) = krate {
52 let traits_in_scope = ctx.scope().traits_in_scope(); 53 let traits_in_scope = ctx.scope().traits_in_scope();
53 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| { 54 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
55 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
56 return None;
57 }
54 match item { 58 match item {
55 hir::AssocItem::Function(func) => { 59 hir::AssocItem::Function(func) => {
56 if !func.has_self_param(ctx.db) { 60 if !func.has_self_param(ctx.db) {
@@ -64,6 +68,9 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
64 }); 68 });
65 69
66 ty.iterate_impl_items(ctx.db, krate, |item| { 70 ty.iterate_impl_items(ctx.db, krate, |item| {
71 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
72 return None;
73 }
67 match item { 74 match item {
68 hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {} 75 hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {}
69 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), 76 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
@@ -74,6 +81,9 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
74 } 81 }
75 hir::ModuleDef::Trait(t) => { 82 hir::ModuleDef::Trait(t) => {
76 for item in t.items(ctx.db) { 83 for item in t.items(ctx.db) {
84 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
85 continue;
86 }
77 match item { 87 match item {
78 hir::AssocItem::Function(func) => { 88 hir::AssocItem::Function(func) => {
79 if !func.has_self_param(ctx.db) { 89 if !func.has_self_param(ctx.db) {
@@ -170,6 +180,41 @@ mod tests {
170 } 180 }
171 181
172 #[test] 182 #[test]
183 fn path_visibility() {
184 assert_debug_snapshot!(
185 do_reference_completion(
186 r"
187 use self::my::<|>;
188
189 mod my {
190 struct Bar;
191 pub struct Foo;
192 pub use Bar as PublicBar;
193 }
194 "
195 ),
196 @r###"
197 [
198 CompletionItem {
199 label: "Foo",
200 source_range: [31; 31),
201 delete: [31; 31),
202 insert: "Foo",
203 kind: Struct,
204 },
205 CompletionItem {
206 label: "PublicBar",
207 source_range: [31; 31),
208 delete: [31; 31),
209 insert: "PublicBar",
210 kind: Struct,
211 },
212 ]
213 "###
214 );
215 }
216
217 #[test]
173 fn completes_use_item_starting_with_self() { 218 fn completes_use_item_starting_with_self() {
174 assert_debug_snapshot!( 219 assert_debug_snapshot!(
175 do_reference_completion( 220 do_reference_completion(
@@ -177,7 +222,7 @@ mod tests {
177 use self::m::<|>; 222 use self::m::<|>;
178 223
179 mod m { 224 mod m {
180 struct Bar; 225 pub struct Bar;
181 } 226 }
182 " 227 "
183 ), 228 ),
@@ -502,6 +547,60 @@ mod tests {
502 } 547 }
503 548
504 #[test] 549 #[test]
550 fn associated_item_visibility() {
551 assert_debug_snapshot!(
552 do_reference_completion(
553 "
554 //- /lib.rs
555 struct S;
556
557 mod m {
558 impl super::S {
559 pub(super) fn public_method() { }
560 fn private_method() { }
561 pub(super) type PublicType = u32;
562 type PrivateType = u32;
563 pub(super) const PUBLIC_CONST: u32 = 1;
564 const PRIVATE_CONST: u32 = 1;
565 }
566 }
567
568 fn foo() { let _ = S::<|> }
569 "
570 ),
571 @r###"
572 [
573 CompletionItem {
574 label: "PUBLIC_CONST",
575 source_range: [302; 302),
576 delete: [302; 302),
577 insert: "PUBLIC_CONST",
578 kind: Const,
579 detail: "pub(super) const PUBLIC_CONST: u32 = 1;",
580 },
581 CompletionItem {
582 label: "PublicType",
583 source_range: [302; 302),
584 delete: [302; 302),
585 insert: "PublicType",
586 kind: TypeAlias,
587 detail: "pub(super) type PublicType = u32;",
588 },
589 CompletionItem {
590 label: "public_method()",
591 source_range: [302; 302),
592 delete: [302; 302),
593 insert: "public_method()$0",
594 kind: Function,
595 lookup: "public_method",
596 detail: "pub(super) fn public_method()",
597 },
598 ]
599 "###
600 );
601 }
602
603 #[test]
505 fn completes_enum_associated_method() { 604 fn completes_enum_associated_method() {
506 assert_debug_snapshot!( 605 assert_debug_snapshot!(
507 do_reference_completion( 606 do_reference_completion(