aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2020-03-08 14:11:57 +0000
committerFlorian Diebold <[email protected]>2020-03-08 14:15:46 +0000
commit05e1c7b1972a87abe6d352b5d0cd8a58e2b7adc7 (patch)
tree20baf0458f8909b101d5f0fe84bd577b76644058 /crates
parentd9c77c54534fcde7c432c6e11746d636d972a20b (diff)
Handle visibility for assoc item path completion as well
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/code_model.rs48
-rw-r--r--crates/ra_hir_def/src/data.rs31
-rw-r--r--crates/ra_ide/src/completion/complete_path.rs67
3 files changed, 124 insertions, 22 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 4d1e8f921..911c809fd 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -204,19 +204,25 @@ impl Module {
204 } 204 }
205 205
206 /// Returns a `ModuleScope`: a set of items, visible in this module. 206 /// Returns a `ModuleScope`: a set of items, visible in this module.
207 pub fn scope(self, db: &impl HirDatabase, visible_from: Option<Module>) -> Vec<(Name, ScopeDef)> { 207 pub fn scope(
208 self,
209 db: &impl HirDatabase,
210 visible_from: Option<Module>,
211 ) -> Vec<(Name, ScopeDef)> {
208 db.crate_def_map(self.id.krate)[self.id.local_id] 212 db.crate_def_map(self.id.krate)[self.id.local_id]
209 .scope 213 .scope
210 .entries() 214 .entries()
211 .filter_map(|(name, def)| if let Some(m) = visible_from { 215 .filter_map(|(name, def)| {
212 let filtered = def.filter_visibility(|vis| vis.is_visible_from(db, m.id)); 216 if let Some(m) = visible_from {
213 if filtered.is_none() && !def.is_none() { 217 let filtered = def.filter_visibility(|vis| vis.is_visible_from(db, m.id));
214 None 218 if filtered.is_none() && !def.is_none() {
219 None
220 } else {
221 Some((name, filtered))
222 }
215 } else { 223 } else {
216 Some((name, filtered)) 224 Some((name, def))
217 } 225 }
218 } else {
219 Some((name, def))
220 }) 226 })
221 .map(|(name, def)| (name.clone(), def.into())) 227 .map(|(name, def)| (name.clone(), def.into()))
222 .collect() 228 .collect()
@@ -608,6 +614,14 @@ impl Const {
608 } 614 }
609} 615}
610 616
617impl HasVisibility for Const {
618 fn visibility(&self, db: &impl HirDatabase) -> Visibility {
619 let function_data = db.const_data(self.id);
620 let visibility = &function_data.visibility;
621 visibility.resolve(db, &self.id.resolver(db))
622 }
623}
624
611#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 625#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
612pub struct Static { 626pub struct Static {
613 pub(crate) id: StaticId, 627 pub(crate) id: StaticId,
@@ -682,6 +696,14 @@ impl TypeAlias {
682 } 696 }
683} 697}
684 698
699impl HasVisibility for TypeAlias {
700 fn visibility(&self, db: &impl HirDatabase) -> Visibility {
701 let function_data = db.type_alias_data(self.id);
702 let visibility = &function_data.visibility;
703 visibility.resolve(db, &self.id.resolver(db))
704 }
705}
706
685#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 707#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
686pub struct MacroDef { 708pub struct MacroDef {
687 pub(crate) id: MacroDefId, 709 pub(crate) id: MacroDefId,
@@ -769,6 +791,16 @@ impl AssocItem {
769 } 791 }
770} 792}
771 793
794impl HasVisibility for AssocItem {
795 fn visibility(&self, db: &impl HirDatabase) -> Visibility {
796 match self {
797 AssocItem::Function(f) => f.visibility(db),
798 AssocItem::Const(c) => c.visibility(db),
799 AssocItem::TypeAlias(t) => t.visibility(db),
800 }
801 }
802}
803
772#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] 804#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
773pub enum GenericDef { 805pub enum GenericDef {
774 Function(Function), 806 Function(Function),
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index 8b343af9d..a72eb5369 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -97,6 +97,7 @@ fn desugar_future_path(orig: TypeRef) -> Path {
97pub struct TypeAliasData { 97pub struct TypeAliasData {
98 pub name: Name, 98 pub name: Name,
99 pub type_ref: Option<TypeRef>, 99 pub type_ref: Option<TypeRef>,
100 pub visibility: RawVisibility,
100} 101}
101 102
102impl TypeAliasData { 103impl TypeAliasData {
@@ -104,10 +105,11 @@ impl TypeAliasData {
104 db: &impl DefDatabase, 105 db: &impl DefDatabase,
105 typ: TypeAliasId, 106 typ: TypeAliasId,
106 ) -> Arc<TypeAliasData> { 107 ) -> Arc<TypeAliasData> {
107 let node = typ.lookup(db).source(db).value; 108 let node = typ.lookup(db).source(db);
108 let name = node.name().map_or_else(Name::missing, |n| n.as_name()); 109 let name = node.value.name().map_or_else(Name::missing, |n| n.as_name());
109 let type_ref = node.type_ref().map(TypeRef::from_ast); 110 let type_ref = node.value.type_ref().map(TypeRef::from_ast);
110 Arc::new(TypeAliasData { name, type_ref }) 111 let visibility = RawVisibility::from_ast(db, node.map(|n| n.visibility()));
112 Arc::new(TypeAliasData { name, type_ref, visibility })
111 } 113 }
112} 114}
113 115
@@ -223,23 +225,28 @@ pub struct ConstData {
223 /// const _: () = (); 225 /// const _: () = ();
224 pub name: Option<Name>, 226 pub name: Option<Name>,
225 pub type_ref: TypeRef, 227 pub type_ref: TypeRef,
228 pub visibility: RawVisibility,
226} 229}
227 230
228impl ConstData { 231impl ConstData {
229 pub(crate) fn const_data_query(db: &impl DefDatabase, konst: ConstId) -> Arc<ConstData> { 232 pub(crate) fn const_data_query(db: &impl DefDatabase, konst: ConstId) -> Arc<ConstData> {
230 let node = konst.lookup(db).source(db).value; 233 let node = konst.lookup(db).source(db);
231 Arc::new(ConstData::new(&node)) 234 Arc::new(ConstData::new(db, node))
232 } 235 }
233 236
234 pub(crate) fn static_data_query(db: &impl DefDatabase, konst: StaticId) -> Arc<ConstData> { 237 pub(crate) fn static_data_query(db: &impl DefDatabase, konst: StaticId) -> Arc<ConstData> {
235 let node = konst.lookup(db).source(db).value; 238 let node = konst.lookup(db).source(db);
236 Arc::new(ConstData::new(&node)) 239 Arc::new(ConstData::new(db, node))
237 } 240 }
238 241
239 fn new<N: NameOwner + TypeAscriptionOwner + VisibilityOwner>(node: &N) -> ConstData { 242 fn new<N: NameOwner + TypeAscriptionOwner + VisibilityOwner>(
240 let name = node.name().map(|n| n.as_name()); 243 db: &impl DefDatabase,
241 let type_ref = TypeRef::from_ast_opt(node.ascribed_type()); 244 node: InFile<N>,
242 ConstData { name, type_ref } 245 ) -> ConstData {
246 let name = node.value.name().map(|n| n.as_name());
247 let type_ref = TypeRef::from_ast_opt(node.value.ascribed_type());
248 let visibility = RawVisibility::from_ast(db, node.map(|n| n.visibility()));
249 ConstData { name, type_ref, visibility }
243 } 250 }
244} 251}
245 252
diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs
index f99b1c2c4..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, HasVisibility}; 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
@@ -52,9 +52,12 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
52 if let Some(krate) = krate { 52 if let Some(krate) = krate {
53 let traits_in_scope = ctx.scope().traits_in_scope(); 53 let traits_in_scope = ctx.scope().traits_in_scope();
54 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 }
55 match item { 58 match item {
56 hir::AssocItem::Function(func) => { 59 hir::AssocItem::Function(func) => {
57 if !func.has_self_param(ctx.db) && context_module.map_or(true, |m| func.is_visible_from(ctx.db, m)) { 60 if !func.has_self_param(ctx.db) {
58 acc.add_function(ctx, func); 61 acc.add_function(ctx, func);
59 } 62 }
60 } 63 }
@@ -65,6 +68,9 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
65 }); 68 });
66 69
67 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 }
68 match item { 74 match item {
69 hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {} 75 hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {}
70 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), 76 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
@@ -75,6 +81,9 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
75 } 81 }
76 hir::ModuleDef::Trait(t) => { 82 hir::ModuleDef::Trait(t) => {
77 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 }
78 match item { 87 match item {
79 hir::AssocItem::Function(func) => { 88 hir::AssocItem::Function(func) => {
80 if !func.has_self_param(ctx.db) { 89 if !func.has_self_param(ctx.db) {
@@ -538,6 +547,60 @@ mod tests {
538 } 547 }
539 548
540 #[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]
541 fn completes_enum_associated_method() { 604 fn completes_enum_associated_method() {
542 assert_debug_snapshot!( 605 assert_debug_snapshot!(
543 do_reference_completion( 606 do_reference_completion(