diff options
author | Florian Diebold <[email protected]> | 2020-03-08 14:11:57 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2020-03-08 14:15:46 +0000 |
commit | 05e1c7b1972a87abe6d352b5d0cd8a58e2b7adc7 (patch) | |
tree | 20baf0458f8909b101d5f0fe84bd577b76644058 /crates | |
parent | d9c77c54534fcde7c432c6e11746d636d972a20b (diff) |
Handle visibility for assoc item path completion as well
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 48 | ||||
-rw-r--r-- | crates/ra_hir_def/src/data.rs | 31 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_path.rs | 67 |
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 | ||
617 | impl 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)] |
612 | pub struct Static { | 626 | pub struct Static { |
613 | pub(crate) id: StaticId, | 627 | pub(crate) id: StaticId, |
@@ -682,6 +696,14 @@ impl TypeAlias { | |||
682 | } | 696 | } |
683 | } | 697 | } |
684 | 698 | ||
699 | impl 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)] |
686 | pub struct MacroDef { | 708 | pub struct MacroDef { |
687 | pub(crate) id: MacroDefId, | 709 | pub(crate) id: MacroDefId, |
@@ -769,6 +791,16 @@ impl AssocItem { | |||
769 | } | 791 | } |
770 | } | 792 | } |
771 | 793 | ||
794 | impl 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)] |
773 | pub enum GenericDef { | 805 | pub 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 { | |||
97 | pub struct TypeAliasData { | 97 | pub 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 | ||
102 | impl TypeAliasData { | 103 | impl 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 | ||
228 | impl ConstData { | 231 | impl 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 | ||
3 | use hir::{Adt, PathResolution, ScopeDef, HasVisibility}; | 3 | use hir::{Adt, HasVisibility, PathResolution, ScopeDef}; |
4 | use ra_syntax::AstNode; | 4 | use ra_syntax::AstNode; |
5 | use test_utils::tested_by; | 5 | use 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( |