diff options
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r-- | crates/ra_hir_def/src/adt.rs | 44 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 25 | ||||
-rw-r--r-- | crates/ra_hir_def/src/data.rs | 21 | ||||
-rw-r--r-- | crates/ra_hir_def/src/item_scope.rs | 33 | ||||
-rw-r--r-- | crates/ra_hir_def/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 109 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/path_resolution.rs | 72 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/raw.rs | 35 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/tests.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/tests/globs.rs | 97 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/tests/incremental.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_def/src/path.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir_def/src/per_ns.rs | 50 | ||||
-rw-r--r-- | crates/ra_hir_def/src/resolver.rs | 24 | ||||
-rw-r--r-- | crates/ra_hir_def/src/visibility.rs | 120 |
16 files changed, 542 insertions, 114 deletions
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index d9ea693e3..aac5f3e15 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs | |||
@@ -9,11 +9,12 @@ use hir_expand::{ | |||
9 | }; | 9 | }; |
10 | use ra_arena::{map::ArenaMap, Arena}; | 10 | use ra_arena::{map::ArenaMap, Arena}; |
11 | use ra_prof::profile; | 11 | use ra_prof::profile; |
12 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; | 12 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner}; |
13 | 13 | ||
14 | use crate::{ | 14 | use crate::{ |
15 | db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace, type_ref::TypeRef, EnumId, | 15 | db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace, type_ref::TypeRef, |
16 | LocalEnumVariantId, LocalStructFieldId, Lookup, StructId, UnionId, VariantId, | 16 | visibility::RawVisibility, EnumId, LocalEnumVariantId, LocalStructFieldId, Lookup, StructId, |
17 | UnionId, VariantId, | ||
17 | }; | 18 | }; |
18 | 19 | ||
19 | /// Note that we use `StructData` for unions as well! | 20 | /// Note that we use `StructData` for unions as well! |
@@ -47,13 +48,14 @@ pub enum VariantData { | |||
47 | pub struct StructFieldData { | 48 | pub struct StructFieldData { |
48 | pub name: Name, | 49 | pub name: Name, |
49 | pub type_ref: TypeRef, | 50 | pub type_ref: TypeRef, |
51 | pub visibility: RawVisibility, | ||
50 | } | 52 | } |
51 | 53 | ||
52 | impl StructData { | 54 | impl StructData { |
53 | pub(crate) fn struct_data_query(db: &impl DefDatabase, id: StructId) -> Arc<StructData> { | 55 | pub(crate) fn struct_data_query(db: &impl DefDatabase, id: StructId) -> Arc<StructData> { |
54 | let src = id.lookup(db).source(db); | 56 | let src = id.lookup(db).source(db); |
55 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); | 57 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); |
56 | let variant_data = VariantData::new(src.value.kind()); | 58 | let variant_data = VariantData::new(db, src.map(|s| s.kind())); |
57 | let variant_data = Arc::new(variant_data); | 59 | let variant_data = Arc::new(variant_data); |
58 | Arc::new(StructData { name, variant_data }) | 60 | Arc::new(StructData { name, variant_data }) |
59 | } | 61 | } |
@@ -61,10 +63,12 @@ impl StructData { | |||
61 | let src = id.lookup(db).source(db); | 63 | let src = id.lookup(db).source(db); |
62 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); | 64 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); |
63 | let variant_data = VariantData::new( | 65 | let variant_data = VariantData::new( |
64 | src.value | 66 | db, |
65 | .record_field_def_list() | 67 | src.map(|s| { |
66 | .map(ast::StructKind::Record) | 68 | s.record_field_def_list() |
67 | .unwrap_or(ast::StructKind::Unit), | 69 | .map(ast::StructKind::Record) |
70 | .unwrap_or(ast::StructKind::Unit) | ||
71 | }), | ||
68 | ); | 72 | ); |
69 | let variant_data = Arc::new(variant_data); | 73 | let variant_data = Arc::new(variant_data); |
70 | Arc::new(StructData { name, variant_data }) | 74 | Arc::new(StructData { name, variant_data }) |
@@ -77,7 +81,7 @@ impl EnumData { | |||
77 | let src = e.lookup(db).source(db); | 81 | let src = e.lookup(db).source(db); |
78 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); | 82 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); |
79 | let mut trace = Trace::new_for_arena(); | 83 | let mut trace = Trace::new_for_arena(); |
80 | lower_enum(&mut trace, &src.value); | 84 | lower_enum(db, &mut trace, &src); |
81 | Arc::new(EnumData { name, variants: trace.into_arena() }) | 85 | Arc::new(EnumData { name, variants: trace.into_arena() }) |
82 | } | 86 | } |
83 | 87 | ||
@@ -93,30 +97,31 @@ impl HasChildSource for EnumId { | |||
93 | fn child_source(&self, db: &impl DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> { | 97 | fn child_source(&self, db: &impl DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> { |
94 | let src = self.lookup(db).source(db); | 98 | let src = self.lookup(db).source(db); |
95 | let mut trace = Trace::new_for_map(); | 99 | let mut trace = Trace::new_for_map(); |
96 | lower_enum(&mut trace, &src.value); | 100 | lower_enum(db, &mut trace, &src); |
97 | src.with_value(trace.into_map()) | 101 | src.with_value(trace.into_map()) |
98 | } | 102 | } |
99 | } | 103 | } |
100 | 104 | ||
101 | fn lower_enum( | 105 | fn lower_enum( |
106 | db: &impl DefDatabase, | ||
102 | trace: &mut Trace<LocalEnumVariantId, EnumVariantData, ast::EnumVariant>, | 107 | trace: &mut Trace<LocalEnumVariantId, EnumVariantData, ast::EnumVariant>, |
103 | ast: &ast::EnumDef, | 108 | ast: &InFile<ast::EnumDef>, |
104 | ) { | 109 | ) { |
105 | for var in ast.variant_list().into_iter().flat_map(|it| it.variants()) { | 110 | for var in ast.value.variant_list().into_iter().flat_map(|it| it.variants()) { |
106 | trace.alloc( | 111 | trace.alloc( |
107 | || var.clone(), | 112 | || var.clone(), |
108 | || EnumVariantData { | 113 | || EnumVariantData { |
109 | name: var.name().map_or_else(Name::missing, |it| it.as_name()), | 114 | name: var.name().map_or_else(Name::missing, |it| it.as_name()), |
110 | variant_data: Arc::new(VariantData::new(var.kind())), | 115 | variant_data: Arc::new(VariantData::new(db, ast.with_value(var.kind()))), |
111 | }, | 116 | }, |
112 | ); | 117 | ); |
113 | } | 118 | } |
114 | } | 119 | } |
115 | 120 | ||
116 | impl VariantData { | 121 | impl VariantData { |
117 | fn new(flavor: ast::StructKind) -> Self { | 122 | fn new(db: &impl DefDatabase, flavor: InFile<ast::StructKind>) -> Self { |
118 | let mut trace = Trace::new_for_arena(); | 123 | let mut trace = Trace::new_for_arena(); |
119 | match lower_struct(&mut trace, &flavor) { | 124 | match lower_struct(db, &mut trace, &flavor) { |
120 | StructKind::Tuple => VariantData::Tuple(trace.into_arena()), | 125 | StructKind::Tuple => VariantData::Tuple(trace.into_arena()), |
121 | StructKind::Record => VariantData::Record(trace.into_arena()), | 126 | StructKind::Record => VariantData::Record(trace.into_arena()), |
122 | StructKind::Unit => VariantData::Unit, | 127 | StructKind::Unit => VariantData::Unit, |
@@ -163,7 +168,7 @@ impl HasChildSource for VariantId { | |||
163 | }), | 168 | }), |
164 | }; | 169 | }; |
165 | let mut trace = Trace::new_for_map(); | 170 | let mut trace = Trace::new_for_map(); |
166 | lower_struct(&mut trace, &src.value); | 171 | lower_struct(db, &mut trace, &src); |
167 | src.with_value(trace.into_map()) | 172 | src.with_value(trace.into_map()) |
168 | } | 173 | } |
169 | } | 174 | } |
@@ -175,14 +180,15 @@ enum StructKind { | |||
175 | } | 180 | } |
176 | 181 | ||
177 | fn lower_struct( | 182 | fn lower_struct( |
183 | db: &impl DefDatabase, | ||
178 | trace: &mut Trace< | 184 | trace: &mut Trace< |
179 | LocalStructFieldId, | 185 | LocalStructFieldId, |
180 | StructFieldData, | 186 | StructFieldData, |
181 | Either<ast::TupleFieldDef, ast::RecordFieldDef>, | 187 | Either<ast::TupleFieldDef, ast::RecordFieldDef>, |
182 | >, | 188 | >, |
183 | ast: &ast::StructKind, | 189 | ast: &InFile<ast::StructKind>, |
184 | ) -> StructKind { | 190 | ) -> StructKind { |
185 | match ast { | 191 | match &ast.value { |
186 | ast::StructKind::Tuple(fl) => { | 192 | ast::StructKind::Tuple(fl) => { |
187 | for (i, fd) in fl.fields().enumerate() { | 193 | for (i, fd) in fl.fields().enumerate() { |
188 | trace.alloc( | 194 | trace.alloc( |
@@ -190,6 +196,7 @@ fn lower_struct( | |||
190 | || StructFieldData { | 196 | || StructFieldData { |
191 | name: Name::new_tuple_field(i), | 197 | name: Name::new_tuple_field(i), |
192 | type_ref: TypeRef::from_ast_opt(fd.type_ref()), | 198 | type_ref: TypeRef::from_ast_opt(fd.type_ref()), |
199 | visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), | ||
193 | }, | 200 | }, |
194 | ); | 201 | ); |
195 | } | 202 | } |
@@ -202,6 +209,7 @@ fn lower_struct( | |||
202 | || StructFieldData { | 209 | || StructFieldData { |
203 | name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), | 210 | name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), |
204 | type_ref: TypeRef::from_ast_opt(fd.ascribed_type()), | 211 | type_ref: TypeRef::from_ast_opt(fd.ascribed_type()), |
212 | visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), | ||
205 | }, | 213 | }, |
206 | ); | 214 | ); |
207 | } | 215 | } |
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index d3e4c50ae..142c52d35 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs | |||
@@ -163,6 +163,7 @@ pub struct BodySourceMap { | |||
163 | pat_map: FxHashMap<PatSource, PatId>, | 163 | pat_map: FxHashMap<PatSource, PatId>, |
164 | pat_map_back: ArenaMap<PatId, PatSource>, | 164 | pat_map_back: ArenaMap<PatId, PatSource>, |
165 | field_map: FxHashMap<(ExprId, usize), AstPtr<ast::RecordField>>, | 165 | field_map: FxHashMap<(ExprId, usize), AstPtr<ast::RecordField>>, |
166 | expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>, | ||
166 | } | 167 | } |
167 | 168 | ||
168 | impl Body { | 169 | impl Body { |
@@ -237,6 +238,11 @@ impl BodySourceMap { | |||
237 | self.expr_map.get(&src).cloned() | 238 | self.expr_map.get(&src).cloned() |
238 | } | 239 | } |
239 | 240 | ||
241 | pub fn node_macro_file(&self, node: InFile<&ast::MacroCall>) -> Option<HirFileId> { | ||
242 | let src = node.map(|it| AstPtr::new(it)); | ||
243 | self.expansions.get(&src).cloned() | ||
244 | } | ||
245 | |||
240 | pub fn field_init_shorthand_expr(&self, node: InFile<&ast::RecordField>) -> Option<ExprId> { | 246 | pub fn field_init_shorthand_expr(&self, node: InFile<&ast::RecordField>) -> Option<ExprId> { |
241 | let src = node.map(|it| Either::Right(AstPtr::new(it))); | 247 | let src = node.map(|it| Either::Right(AstPtr::new(it))); |
242 | self.expr_map.get(&src).cloned() | 248 | self.expr_map.get(&src).cloned() |
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 5323af097..e656f9a41 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -446,14 +446,20 @@ where | |||
446 | } | 446 | } |
447 | } | 447 | } |
448 | // FIXME expand to statements in statement position | 448 | // FIXME expand to statements in statement position |
449 | ast::Expr::MacroCall(e) => match self.expander.enter_expand(self.db, e) { | 449 | ast::Expr::MacroCall(e) => { |
450 | Some((mark, expansion)) => { | 450 | let macro_call = self.expander.to_source(AstPtr::new(&e)); |
451 | let id = self.collect_expr(expansion); | 451 | match self.expander.enter_expand(self.db, e.clone()) { |
452 | self.expander.exit(self.db, mark); | 452 | Some((mark, expansion)) => { |
453 | id | 453 | self.source_map |
454 | .expansions | ||
455 | .insert(macro_call, self.expander.current_file_id); | ||
456 | let id = self.collect_expr(expansion); | ||
457 | self.expander.exit(self.db, mark); | ||
458 | id | ||
459 | } | ||
460 | None => self.alloc_expr(Expr::Missing, syntax_ptr), | ||
454 | } | 461 | } |
455 | None => self.alloc_expr(Expr::Missing, syntax_ptr), | 462 | } |
456 | }, | ||
457 | 463 | ||
458 | // FIXME implement HIR for these: | 464 | // FIXME implement HIR for these: |
459 | ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | 465 | ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), |
@@ -543,7 +549,10 @@ where | |||
543 | }; | 549 | }; |
544 | self.body.item_scope.define_def(def); | 550 | self.body.item_scope.define_def(def); |
545 | if let Some(name) = name { | 551 | if let Some(name) = name { |
546 | self.body.item_scope.push_res(name.as_name(), def.into()); | 552 | let vis = crate::visibility::Visibility::Public; // FIXME determine correctly |
553 | self.body | ||
554 | .item_scope | ||
555 | .push_res(name.as_name(), crate::per_ns::PerNs::from_def(def, vis)); | ||
547 | } | 556 | } |
548 | } | 557 | } |
549 | } | 558 | } |
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index 1aa9a9b7d..c900a6a18 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs | |||
@@ -10,8 +10,9 @@ use ra_syntax::ast::{self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAs | |||
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | db::DefDatabase, | 12 | db::DefDatabase, |
13 | path::{path, GenericArgs, Path}, | ||
13 | src::HasSource, | 14 | src::HasSource, |
14 | type_ref::{Mutability, TypeRef}, | 15 | type_ref::{Mutability, TypeBound, TypeRef}, |
15 | AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule, | 16 | AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule, |
16 | ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, | 17 | ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, |
17 | }; | 18 | }; |
@@ -62,11 +63,29 @@ impl FunctionData { | |||
62 | TypeRef::unit() | 63 | TypeRef::unit() |
63 | }; | 64 | }; |
64 | 65 | ||
66 | let ret_type = if src.value.is_async() { | ||
67 | let future_impl = desugar_future_path(ret_type); | ||
68 | let ty_bound = TypeBound::Path(future_impl); | ||
69 | TypeRef::ImplTrait(vec![ty_bound]) | ||
70 | } else { | ||
71 | ret_type | ||
72 | }; | ||
73 | |||
65 | let sig = FunctionData { name, params, ret_type, has_self_param }; | 74 | let sig = FunctionData { name, params, ret_type, has_self_param }; |
66 | Arc::new(sig) | 75 | Arc::new(sig) |
67 | } | 76 | } |
68 | } | 77 | } |
69 | 78 | ||
79 | fn desugar_future_path(orig: TypeRef) -> Path { | ||
80 | let path = path![std::future::Future]; | ||
81 | let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect(); | ||
82 | let mut last = GenericArgs::empty(); | ||
83 | last.bindings.push((name![Output], orig)); | ||
84 | generic_args.push(Some(Arc::new(last))); | ||
85 | |||
86 | Path::from_known_path(path, generic_args) | ||
87 | } | ||
88 | |||
70 | #[derive(Debug, Clone, PartialEq, Eq)] | 89 | #[derive(Debug, Clone, PartialEq, Eq)] |
71 | pub struct TypeAliasData { | 90 | pub struct TypeAliasData { |
72 | pub name: Name, | 91 | pub name: Name, |
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index b0288ee8d..fe7bb9779 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs | |||
@@ -5,7 +5,10 @@ use hir_expand::name::Name; | |||
5 | use once_cell::sync::Lazy; | 5 | use once_cell::sync::Lazy; |
6 | use rustc_hash::FxHashMap; | 6 | use rustc_hash::FxHashMap; |
7 | 7 | ||
8 | use crate::{per_ns::PerNs, AdtId, BuiltinType, ImplId, MacroDefId, ModuleDefId, TraitId}; | 8 | use crate::{ |
9 | per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ImplId, MacroDefId, ModuleDefId, | ||
10 | TraitId, | ||
11 | }; | ||
9 | 12 | ||
10 | #[derive(Debug, Default, PartialEq, Eq)] | 13 | #[derive(Debug, Default, PartialEq, Eq)] |
11 | pub struct ItemScope { | 14 | pub struct ItemScope { |
@@ -30,7 +33,7 @@ pub struct ItemScope { | |||
30 | static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| { | 33 | static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| { |
31 | BuiltinType::ALL | 34 | BuiltinType::ALL |
32 | .iter() | 35 | .iter() |
33 | .map(|(name, ty)| (name.clone(), PerNs::types(ty.clone().into()))) | 36 | .map(|(name, ty)| (name.clone(), PerNs::types(ty.clone().into(), Visibility::Public))) |
34 | .collect() | 37 | .collect() |
35 | }); | 38 | }); |
36 | 39 | ||
@@ -144,8 +147,8 @@ impl ItemScope { | |||
144 | changed | 147 | changed |
145 | } | 148 | } |
146 | 149 | ||
147 | pub(crate) fn collect_resolutions(&self) -> Vec<(Name, PerNs)> { | 150 | pub(crate) fn resolutions<'a>(&'a self) -> impl Iterator<Item = (Name, PerNs)> + 'a { |
148 | self.visible.iter().map(|(name, res)| (name.clone(), res.clone())).collect() | 151 | self.visible.iter().map(|(name, res)| (name.clone(), res.clone())) |
149 | } | 152 | } |
150 | 153 | ||
151 | pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> { | 154 | pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> { |
@@ -153,20 +156,20 @@ impl ItemScope { | |||
153 | } | 156 | } |
154 | } | 157 | } |
155 | 158 | ||
156 | impl From<ModuleDefId> for PerNs { | 159 | impl PerNs { |
157 | fn from(def: ModuleDefId) -> PerNs { | 160 | pub(crate) fn from_def(def: ModuleDefId, v: Visibility) -> PerNs { |
158 | match def { | 161 | match def { |
159 | ModuleDefId::ModuleId(_) => PerNs::types(def), | 162 | ModuleDefId::ModuleId(_) => PerNs::types(def, v), |
160 | ModuleDefId::FunctionId(_) => PerNs::values(def), | 163 | ModuleDefId::FunctionId(_) => PerNs::values(def, v), |
161 | ModuleDefId::AdtId(adt) => match adt { | 164 | ModuleDefId::AdtId(adt) => match adt { |
162 | AdtId::StructId(_) | AdtId::UnionId(_) => PerNs::both(def, def), | 165 | AdtId::StructId(_) | AdtId::UnionId(_) => PerNs::both(def, def, v), |
163 | AdtId::EnumId(_) => PerNs::types(def), | 166 | AdtId::EnumId(_) => PerNs::types(def, v), |
164 | }, | 167 | }, |
165 | ModuleDefId::EnumVariantId(_) => PerNs::both(def, def), | 168 | ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v), |
166 | ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def), | 169 | ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def, v), |
167 | ModuleDefId::TraitId(_) => PerNs::types(def), | 170 | ModuleDefId::TraitId(_) => PerNs::types(def, v), |
168 | ModuleDefId::TypeAliasId(_) => PerNs::types(def), | 171 | ModuleDefId::TypeAliasId(_) => PerNs::types(def, v), |
169 | ModuleDefId::BuiltinType(_) => PerNs::types(def), | 172 | ModuleDefId::BuiltinType(_) => PerNs::types(def, v), |
170 | } | 173 | } |
171 | } | 174 | } |
172 | } | 175 | } |
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index f6c7f38d1..61f044ecf 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs | |||
@@ -36,6 +36,8 @@ pub mod nameres; | |||
36 | pub mod src; | 36 | pub mod src; |
37 | pub mod child_by_source; | 37 | pub mod child_by_source; |
38 | 38 | ||
39 | pub mod visibility; | ||
40 | |||
39 | #[cfg(test)] | 41 | #[cfg(test)] |
40 | mod test_db; | 42 | mod test_db; |
41 | #[cfg(test)] | 43 | #[cfg(test)] |
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index b9f40d3dd..8a22b0585 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -24,6 +24,7 @@ use crate::{ | |||
24 | }, | 24 | }, |
25 | path::{ModPath, PathKind}, | 25 | path::{ModPath, PathKind}, |
26 | per_ns::PerNs, | 26 | per_ns::PerNs, |
27 | visibility::Visibility, | ||
27 | AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern, | 28 | AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern, |
28 | LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, | 29 | LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, |
29 | }; | 30 | }; |
@@ -108,7 +109,7 @@ struct MacroDirective { | |||
108 | struct DefCollector<'a, DB> { | 109 | struct DefCollector<'a, DB> { |
109 | db: &'a DB, | 110 | db: &'a DB, |
110 | def_map: CrateDefMap, | 111 | def_map: CrateDefMap, |
111 | glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, raw::Import)>>, | 112 | glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility)>>, |
112 | unresolved_imports: Vec<ImportDirective>, | 113 | unresolved_imports: Vec<ImportDirective>, |
113 | resolved_imports: Vec<ImportDirective>, | 114 | resolved_imports: Vec<ImportDirective>, |
114 | unexpanded_macros: Vec<MacroDirective>, | 115 | unexpanded_macros: Vec<MacroDirective>, |
@@ -214,7 +215,11 @@ where | |||
214 | // In Rust, `#[macro_export]` macros are unconditionally visible at the | 215 | // In Rust, `#[macro_export]` macros are unconditionally visible at the |
215 | // crate root, even if the parent modules is **not** visible. | 216 | // crate root, even if the parent modules is **not** visible. |
216 | if export { | 217 | if export { |
217 | self.update(self.def_map.root, &[(name, PerNs::macros(macro_))]); | 218 | self.update( |
219 | self.def_map.root, | ||
220 | &[(name, PerNs::macros(macro_, Visibility::Public))], | ||
221 | Visibility::Public, | ||
222 | ); | ||
218 | } | 223 | } |
219 | } | 224 | } |
220 | 225 | ||
@@ -348,9 +353,12 @@ where | |||
348 | 353 | ||
349 | fn record_resolved_import(&mut self, directive: &ImportDirective) { | 354 | fn record_resolved_import(&mut self, directive: &ImportDirective) { |
350 | let module_id = directive.module_id; | 355 | let module_id = directive.module_id; |
351 | let import_id = directive.import_id; | ||
352 | let import = &directive.import; | 356 | let import = &directive.import; |
353 | let def = directive.status.namespaces(); | 357 | let def = directive.status.namespaces(); |
358 | let vis = self | ||
359 | .def_map | ||
360 | .resolve_visibility(self.db, module_id, &directive.import.visibility) | ||
361 | .unwrap_or(Visibility::Public); | ||
354 | 362 | ||
355 | if import.is_glob { | 363 | if import.is_glob { |
356 | log::debug!("glob import: {:?}", import); | 364 | log::debug!("glob import: {:?}", import); |
@@ -366,9 +374,16 @@ where | |||
366 | let scope = &item_map[m.local_id].scope; | 374 | let scope = &item_map[m.local_id].scope; |
367 | 375 | ||
368 | // Module scoped macros is included | 376 | // Module scoped macros is included |
369 | let items = scope.collect_resolutions(); | 377 | let items = scope |
370 | 378 | .resolutions() | |
371 | self.update(module_id, &items); | 379 | // only keep visible names... |
380 | .map(|(n, res)| { | ||
381 | (n, res.filter_visibility(|v| v.is_visible_from_other_crate())) | ||
382 | }) | ||
383 | .filter(|(_, res)| !res.is_none()) | ||
384 | .collect::<Vec<_>>(); | ||
385 | |||
386 | self.update(module_id, &items, vis); | ||
372 | } else { | 387 | } else { |
373 | // glob import from same crate => we do an initial | 388 | // glob import from same crate => we do an initial |
374 | // import, and then need to propagate any further | 389 | // import, and then need to propagate any further |
@@ -376,13 +391,25 @@ where | |||
376 | let scope = &self.def_map[m.local_id].scope; | 391 | let scope = &self.def_map[m.local_id].scope; |
377 | 392 | ||
378 | // Module scoped macros is included | 393 | // Module scoped macros is included |
379 | let items = scope.collect_resolutions(); | 394 | let items = scope |
380 | 395 | .resolutions() | |
381 | self.update(module_id, &items); | 396 | // only keep visible names... |
397 | .map(|(n, res)| { | ||
398 | ( | ||
399 | n, | ||
400 | res.filter_visibility(|v| { | ||
401 | v.is_visible_from_def_map(&self.def_map, module_id) | ||
402 | }), | ||
403 | ) | ||
404 | }) | ||
405 | .filter(|(_, res)| !res.is_none()) | ||
406 | .collect::<Vec<_>>(); | ||
407 | |||
408 | self.update(module_id, &items, vis); | ||
382 | // record the glob import in case we add further items | 409 | // record the glob import in case we add further items |
383 | let glob = self.glob_imports.entry(m.local_id).or_default(); | 410 | let glob = self.glob_imports.entry(m.local_id).or_default(); |
384 | if !glob.iter().any(|it| *it == (module_id, import_id)) { | 411 | if !glob.iter().any(|(mid, _)| *mid == module_id) { |
385 | glob.push((module_id, import_id)); | 412 | glob.push((module_id, vis)); |
386 | } | 413 | } |
387 | } | 414 | } |
388 | } | 415 | } |
@@ -396,11 +423,11 @@ where | |||
396 | .map(|(local_id, variant_data)| { | 423 | .map(|(local_id, variant_data)| { |
397 | let name = variant_data.name.clone(); | 424 | let name = variant_data.name.clone(); |
398 | let variant = EnumVariantId { parent: e, local_id }; | 425 | let variant = EnumVariantId { parent: e, local_id }; |
399 | let res = PerNs::both(variant.into(), variant.into()); | 426 | let res = PerNs::both(variant.into(), variant.into(), vis); |
400 | (name, res) | 427 | (name, res) |
401 | }) | 428 | }) |
402 | .collect::<Vec<_>>(); | 429 | .collect::<Vec<_>>(); |
403 | self.update(module_id, &resolutions); | 430 | self.update(module_id, &resolutions, vis); |
404 | } | 431 | } |
405 | Some(d) => { | 432 | Some(d) => { |
406 | log::debug!("glob import {:?} from non-module/enum {:?}", import, d); | 433 | log::debug!("glob import {:?} from non-module/enum {:?}", import, d); |
@@ -422,21 +449,24 @@ where | |||
422 | } | 449 | } |
423 | } | 450 | } |
424 | 451 | ||
425 | self.update(module_id, &[(name, def)]); | 452 | self.update(module_id, &[(name, def)], vis); |
426 | } | 453 | } |
427 | None => tested_by!(bogus_paths), | 454 | None => tested_by!(bogus_paths), |
428 | } | 455 | } |
429 | } | 456 | } |
430 | } | 457 | } |
431 | 458 | ||
432 | fn update(&mut self, module_id: LocalModuleId, resolutions: &[(Name, PerNs)]) { | 459 | fn update(&mut self, module_id: LocalModuleId, resolutions: &[(Name, PerNs)], vis: Visibility) { |
433 | self.update_recursive(module_id, resolutions, 0) | 460 | self.update_recursive(module_id, resolutions, vis, 0) |
434 | } | 461 | } |
435 | 462 | ||
436 | fn update_recursive( | 463 | fn update_recursive( |
437 | &mut self, | 464 | &mut self, |
438 | module_id: LocalModuleId, | 465 | module_id: LocalModuleId, |
439 | resolutions: &[(Name, PerNs)], | 466 | resolutions: &[(Name, PerNs)], |
467 | // All resolutions are imported with this visibility; the visibilies in | ||
468 | // the `PerNs` values are ignored and overwritten | ||
469 | vis: Visibility, | ||
440 | depth: usize, | 470 | depth: usize, |
441 | ) { | 471 | ) { |
442 | if depth > 100 { | 472 | if depth > 100 { |
@@ -446,7 +476,7 @@ where | |||
446 | let scope = &mut self.def_map.modules[module_id].scope; | 476 | let scope = &mut self.def_map.modules[module_id].scope; |
447 | let mut changed = false; | 477 | let mut changed = false; |
448 | for (name, res) in resolutions { | 478 | for (name, res) in resolutions { |
449 | changed |= scope.push_res(name.clone(), *res); | 479 | changed |= scope.push_res(name.clone(), res.with_visibility(vis)); |
450 | } | 480 | } |
451 | 481 | ||
452 | if !changed { | 482 | if !changed { |
@@ -459,9 +489,13 @@ where | |||
459 | .flat_map(|v| v.iter()) | 489 | .flat_map(|v| v.iter()) |
460 | .cloned() | 490 | .cloned() |
461 | .collect::<Vec<_>>(); | 491 | .collect::<Vec<_>>(); |
462 | for (glob_importing_module, _glob_import) in glob_imports { | 492 | for (glob_importing_module, glob_import_vis) in glob_imports { |
463 | // We pass the glob import so that the tracked import in those modules is that glob import | 493 | // we know all resolutions have the same visibility (`vis`), so we |
464 | self.update_recursive(glob_importing_module, resolutions, depth + 1); | 494 | // just need to check that once |
495 | if !vis.is_visible_from_def_map(&self.def_map, glob_importing_module) { | ||
496 | continue; | ||
497 | } | ||
498 | self.update_recursive(glob_importing_module, resolutions, glob_import_vis, depth + 1); | ||
465 | } | 499 | } |
466 | } | 500 | } |
467 | 501 | ||
@@ -633,9 +667,13 @@ where | |||
633 | let is_macro_use = attrs.by_key("macro_use").exists(); | 667 | let is_macro_use = attrs.by_key("macro_use").exists(); |
634 | match module { | 668 | match module { |
635 | // inline module, just recurse | 669 | // inline module, just recurse |
636 | raw::ModuleData::Definition { name, items, ast_id } => { | 670 | raw::ModuleData::Definition { name, visibility, items, ast_id } => { |
637 | let module_id = | 671 | let module_id = self.push_child_module( |
638 | self.push_child_module(name.clone(), AstId::new(self.file_id, *ast_id), None); | 672 | name.clone(), |
673 | AstId::new(self.file_id, *ast_id), | ||
674 | None, | ||
675 | &visibility, | ||
676 | ); | ||
639 | 677 | ||
640 | ModCollector { | 678 | ModCollector { |
641 | def_collector: &mut *self.def_collector, | 679 | def_collector: &mut *self.def_collector, |
@@ -650,7 +688,7 @@ where | |||
650 | } | 688 | } |
651 | } | 689 | } |
652 | // out of line module, resolve, parse and recurse | 690 | // out of line module, resolve, parse and recurse |
653 | raw::ModuleData::Declaration { name, ast_id } => { | 691 | raw::ModuleData::Declaration { name, visibility, ast_id } => { |
654 | let ast_id = AstId::new(self.file_id, *ast_id); | 692 | let ast_id = AstId::new(self.file_id, *ast_id); |
655 | match self.mod_dir.resolve_declaration( | 693 | match self.mod_dir.resolve_declaration( |
656 | self.def_collector.db, | 694 | self.def_collector.db, |
@@ -659,7 +697,12 @@ where | |||
659 | path_attr, | 697 | path_attr, |
660 | ) { | 698 | ) { |
661 | Ok((file_id, mod_dir)) => { | 699 | Ok((file_id, mod_dir)) => { |
662 | let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id)); | 700 | let module_id = self.push_child_module( |
701 | name.clone(), | ||
702 | ast_id, | ||
703 | Some(file_id), | ||
704 | &visibility, | ||
705 | ); | ||
663 | let raw_items = self.def_collector.db.raw_items(file_id.into()); | 706 | let raw_items = self.def_collector.db.raw_items(file_id.into()); |
664 | ModCollector { | 707 | ModCollector { |
665 | def_collector: &mut *self.def_collector, | 708 | def_collector: &mut *self.def_collector, |
@@ -690,7 +733,13 @@ where | |||
690 | name: Name, | 733 | name: Name, |
691 | declaration: AstId<ast::Module>, | 734 | declaration: AstId<ast::Module>, |
692 | definition: Option<FileId>, | 735 | definition: Option<FileId>, |
736 | visibility: &crate::visibility::RawVisibility, | ||
693 | ) -> LocalModuleId { | 737 | ) -> LocalModuleId { |
738 | let vis = self | ||
739 | .def_collector | ||
740 | .def_map | ||
741 | .resolve_visibility(self.def_collector.db, self.module_id, visibility) | ||
742 | .unwrap_or(Visibility::Public); | ||
694 | let modules = &mut self.def_collector.def_map.modules; | 743 | let modules = &mut self.def_collector.def_map.modules; |
695 | let res = modules.alloc(ModuleData::default()); | 744 | let res = modules.alloc(ModuleData::default()); |
696 | modules[res].parent = Some(self.module_id); | 745 | modules[res].parent = Some(self.module_id); |
@@ -702,7 +751,7 @@ where | |||
702 | let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; | 751 | let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; |
703 | let def: ModuleDefId = module.into(); | 752 | let def: ModuleDefId = module.into(); |
704 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); | 753 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); |
705 | self.def_collector.update(self.module_id, &[(name, def.into())]); | 754 | self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))], vis); |
706 | res | 755 | res |
707 | } | 756 | } |
708 | 757 | ||
@@ -716,6 +765,7 @@ where | |||
716 | 765 | ||
717 | let name = def.name.clone(); | 766 | let name = def.name.clone(); |
718 | let container = ContainerId::ModuleId(module); | 767 | let container = ContainerId::ModuleId(module); |
768 | let vis = &def.visibility; | ||
719 | let def: ModuleDefId = match def.kind { | 769 | let def: ModuleDefId = match def.kind { |
720 | raw::DefKind::Function(ast_id) => FunctionLoc { | 770 | raw::DefKind::Function(ast_id) => FunctionLoc { |
721 | container: container.into(), | 771 | container: container.into(), |
@@ -761,7 +811,12 @@ where | |||
761 | .into(), | 811 | .into(), |
762 | }; | 812 | }; |
763 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); | 813 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); |
764 | self.def_collector.update(self.module_id, &[(name, def.into())]) | 814 | let vis = self |
815 | .def_collector | ||
816 | .def_map | ||
817 | .resolve_visibility(self.def_collector.db, self.module_id, vis) | ||
818 | .unwrap_or(Visibility::Public); | ||
819 | self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))], vis) | ||
765 | } | 820 | } |
766 | 821 | ||
767 | fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) { | 822 | fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) { |
diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs index 695014c7b..fd6422d60 100644 --- a/crates/ra_hir_def/src/nameres/path_resolution.rs +++ b/crates/ra_hir_def/src/nameres/path_resolution.rs | |||
@@ -21,6 +21,7 @@ use crate::{ | |||
21 | nameres::{BuiltinShadowMode, CrateDefMap}, | 21 | nameres::{BuiltinShadowMode, CrateDefMap}, |
22 | path::{ModPath, PathKind}, | 22 | path::{ModPath, PathKind}, |
23 | per_ns::PerNs, | 23 | per_ns::PerNs, |
24 | visibility::{RawVisibility, Visibility}, | ||
24 | AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId, | 25 | AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId, |
25 | }; | 26 | }; |
26 | 27 | ||
@@ -61,7 +62,35 @@ impl ResolvePathResult { | |||
61 | 62 | ||
62 | impl CrateDefMap { | 63 | impl CrateDefMap { |
63 | pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs { | 64 | pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs { |
64 | self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)) | 65 | self.extern_prelude |
66 | .get(name) | ||
67 | .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)) | ||
68 | } | ||
69 | |||
70 | pub(crate) fn resolve_visibility( | ||
71 | &self, | ||
72 | db: &impl DefDatabase, | ||
73 | original_module: LocalModuleId, | ||
74 | visibility: &RawVisibility, | ||
75 | ) -> Option<Visibility> { | ||
76 | match visibility { | ||
77 | RawVisibility::Module(path) => { | ||
78 | let (result, remaining) = | ||
79 | self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module); | ||
80 | if remaining.is_some() { | ||
81 | return None; | ||
82 | } | ||
83 | let types = result.take_types()?; | ||
84 | match types { | ||
85 | ModuleDefId::ModuleId(m) => Some(Visibility::Module(m)), | ||
86 | _ => { | ||
87 | // error: visibility needs to refer to module | ||
88 | None | ||
89 | } | ||
90 | } | ||
91 | } | ||
92 | RawVisibility::Public => Some(Visibility::Public), | ||
93 | } | ||
65 | } | 94 | } |
66 | 95 | ||
67 | // Returns Yes if we are sure that additions to `ItemMap` wouldn't change | 96 | // Returns Yes if we are sure that additions to `ItemMap` wouldn't change |
@@ -88,17 +117,21 @@ impl CrateDefMap { | |||
88 | PathKind::DollarCrate(krate) => { | 117 | PathKind::DollarCrate(krate) => { |
89 | if krate == self.krate { | 118 | if krate == self.krate { |
90 | tested_by!(macro_dollar_crate_self); | 119 | tested_by!(macro_dollar_crate_self); |
91 | PerNs::types(ModuleId { krate: self.krate, local_id: self.root }.into()) | 120 | PerNs::types( |
121 | ModuleId { krate: self.krate, local_id: self.root }.into(), | ||
122 | Visibility::Public, | ||
123 | ) | ||
92 | } else { | 124 | } else { |
93 | let def_map = db.crate_def_map(krate); | 125 | let def_map = db.crate_def_map(krate); |
94 | let module = ModuleId { krate, local_id: def_map.root }; | 126 | let module = ModuleId { krate, local_id: def_map.root }; |
95 | tested_by!(macro_dollar_crate_other); | 127 | tested_by!(macro_dollar_crate_other); |
96 | PerNs::types(module.into()) | 128 | PerNs::types(module.into(), Visibility::Public) |
97 | } | 129 | } |
98 | } | 130 | } |
99 | PathKind::Crate => { | 131 | PathKind::Crate => PerNs::types( |
100 | PerNs::types(ModuleId { krate: self.krate, local_id: self.root }.into()) | 132 | ModuleId { krate: self.krate, local_id: self.root }.into(), |
101 | } | 133 | Visibility::Public, |
134 | ), | ||
102 | // plain import or absolute path in 2015: crate-relative with | 135 | // plain import or absolute path in 2015: crate-relative with |
103 | // fallback to extern prelude (with the simplification in | 136 | // fallback to extern prelude (with the simplification in |
104 | // rust-lang/rust#57745) | 137 | // rust-lang/rust#57745) |
@@ -126,7 +159,10 @@ impl CrateDefMap { | |||
126 | let m = successors(Some(original_module), |m| self.modules[*m].parent) | 159 | let m = successors(Some(original_module), |m| self.modules[*m].parent) |
127 | .nth(lvl as usize); | 160 | .nth(lvl as usize); |
128 | if let Some(local_id) = m { | 161 | if let Some(local_id) = m { |
129 | PerNs::types(ModuleId { krate: self.krate, local_id }.into()) | 162 | PerNs::types( |
163 | ModuleId { krate: self.krate, local_id }.into(), | ||
164 | Visibility::Public, | ||
165 | ) | ||
130 | } else { | 166 | } else { |
131 | log::debug!("super path in root module"); | 167 | log::debug!("super path in root module"); |
132 | return ResolvePathResult::empty(ReachedFixedPoint::Yes); | 168 | return ResolvePathResult::empty(ReachedFixedPoint::Yes); |
@@ -140,7 +176,7 @@ impl CrateDefMap { | |||
140 | }; | 176 | }; |
141 | if let Some(def) = self.extern_prelude.get(&segment) { | 177 | if let Some(def) = self.extern_prelude.get(&segment) { |
142 | log::debug!("absolute path {:?} resolved to crate {:?}", path, def); | 178 | log::debug!("absolute path {:?} resolved to crate {:?}", path, def); |
143 | PerNs::types(*def) | 179 | PerNs::types(*def, Visibility::Public) |
144 | } else { | 180 | } else { |
145 | return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude | 181 | return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude |
146 | } | 182 | } |
@@ -148,7 +184,7 @@ impl CrateDefMap { | |||
148 | }; | 184 | }; |
149 | 185 | ||
150 | for (i, segment) in segments { | 186 | for (i, segment) in segments { |
151 | let curr = match curr_per_ns.take_types() { | 187 | let (curr, vis) = match curr_per_ns.take_types_vis() { |
152 | Some(r) => r, | 188 | Some(r) => r, |
153 | None => { | 189 | None => { |
154 | // we still have path segments left, but the path so far | 190 | // we still have path segments left, but the path so far |
@@ -189,11 +225,11 @@ impl CrateDefMap { | |||
189 | match enum_data.variant(&segment) { | 225 | match enum_data.variant(&segment) { |
190 | Some(local_id) => { | 226 | Some(local_id) => { |
191 | let variant = EnumVariantId { parent: e, local_id }; | 227 | let variant = EnumVariantId { parent: e, local_id }; |
192 | PerNs::both(variant.into(), variant.into()) | 228 | PerNs::both(variant.into(), variant.into(), Visibility::Public) |
193 | } | 229 | } |
194 | None => { | 230 | None => { |
195 | return ResolvePathResult::with( | 231 | return ResolvePathResult::with( |
196 | PerNs::types(e.into()), | 232 | PerNs::types(e.into(), vis), |
197 | ReachedFixedPoint::Yes, | 233 | ReachedFixedPoint::Yes, |
198 | Some(i), | 234 | Some(i), |
199 | Some(self.krate), | 235 | Some(self.krate), |
@@ -211,7 +247,7 @@ impl CrateDefMap { | |||
211 | ); | 247 | ); |
212 | 248 | ||
213 | return ResolvePathResult::with( | 249 | return ResolvePathResult::with( |
214 | PerNs::types(s), | 250 | PerNs::types(s, vis), |
215 | ReachedFixedPoint::Yes, | 251 | ReachedFixedPoint::Yes, |
216 | Some(i), | 252 | Some(i), |
217 | Some(self.krate), | 253 | Some(self.krate), |
@@ -235,11 +271,15 @@ impl CrateDefMap { | |||
235 | // - current module / scope | 271 | // - current module / scope |
236 | // - extern prelude | 272 | // - extern prelude |
237 | // - std prelude | 273 | // - std prelude |
238 | let from_legacy_macro = | 274 | let from_legacy_macro = self[module] |
239 | self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros); | 275 | .scope |
276 | .get_legacy_macro(name) | ||
277 | .map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public)); | ||
240 | let from_scope = self[module].scope.get(name, shadow); | 278 | let from_scope = self[module].scope.get(name, shadow); |
241 | let from_extern_prelude = | 279 | let from_extern_prelude = self |
242 | self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); | 280 | .extern_prelude |
281 | .get(name) | ||
282 | .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)); | ||
243 | let from_prelude = self.resolve_in_prelude(db, name, shadow); | 283 | let from_prelude = self.resolve_in_prelude(db, name, shadow); |
244 | 284 | ||
245 | from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude) | 285 | from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude) |
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index 73dc08745..fac1169ef 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs | |||
@@ -16,12 +16,15 @@ use hir_expand::{ | |||
16 | use ra_arena::{impl_arena_id, Arena, RawId}; | 16 | use ra_arena::{impl_arena_id, Arena, RawId}; |
17 | use ra_prof::profile; | 17 | use ra_prof::profile; |
18 | use ra_syntax::{ | 18 | use ra_syntax::{ |
19 | ast::{self, AttrsOwner, NameOwner}, | 19 | ast::{self, AttrsOwner, NameOwner, VisibilityOwner}, |
20 | AstNode, | 20 | AstNode, |
21 | }; | 21 | }; |
22 | use test_utils::tested_by; | 22 | use test_utils::tested_by; |
23 | 23 | ||
24 | use crate::{attr::Attrs, db::DefDatabase, path::ModPath, FileAstId, HirFileId, InFile}; | 24 | use crate::{ |
25 | attr::Attrs, db::DefDatabase, path::ModPath, visibility::RawVisibility, FileAstId, HirFileId, | ||
26 | InFile, | ||
27 | }; | ||
25 | 28 | ||
26 | /// `RawItems` is a set of top-level items in a file (except for impls). | 29 | /// `RawItems` is a set of top-level items in a file (except for impls). |
27 | /// | 30 | /// |
@@ -122,8 +125,17 @@ impl_arena_id!(Module); | |||
122 | 125 | ||
123 | #[derive(Debug, PartialEq, Eq)] | 126 | #[derive(Debug, PartialEq, Eq)] |
124 | pub(super) enum ModuleData { | 127 | pub(super) enum ModuleData { |
125 | Declaration { name: Name, ast_id: FileAstId<ast::Module> }, | 128 | Declaration { |
126 | Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> }, | 129 | name: Name, |
130 | visibility: RawVisibility, | ||
131 | ast_id: FileAstId<ast::Module>, | ||
132 | }, | ||
133 | Definition { | ||
134 | name: Name, | ||
135 | visibility: RawVisibility, | ||
136 | ast_id: FileAstId<ast::Module>, | ||
137 | items: Vec<RawItem>, | ||
138 | }, | ||
127 | } | 139 | } |
128 | 140 | ||
129 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 141 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -138,6 +150,7 @@ pub struct ImportData { | |||
138 | pub(super) is_prelude: bool, | 150 | pub(super) is_prelude: bool, |
139 | pub(super) is_extern_crate: bool, | 151 | pub(super) is_extern_crate: bool, |
140 | pub(super) is_macro_use: bool, | 152 | pub(super) is_macro_use: bool, |
153 | pub(super) visibility: RawVisibility, | ||
141 | } | 154 | } |
142 | 155 | ||
143 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 156 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -148,6 +161,7 @@ impl_arena_id!(Def); | |||
148 | pub(super) struct DefData { | 161 | pub(super) struct DefData { |
149 | pub(super) name: Name, | 162 | pub(super) name: Name, |
150 | pub(super) kind: DefKind, | 163 | pub(super) kind: DefKind, |
164 | pub(super) visibility: RawVisibility, | ||
151 | } | 165 | } |
152 | 166 | ||
153 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] | 167 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] |
@@ -218,6 +232,7 @@ impl RawItemsCollector { | |||
218 | 232 | ||
219 | fn add_item(&mut self, current_module: Option<Module>, item: ast::ModuleItem) { | 233 | fn add_item(&mut self, current_module: Option<Module>, item: ast::ModuleItem) { |
220 | let attrs = self.parse_attrs(&item); | 234 | let attrs = self.parse_attrs(&item); |
235 | let visibility = RawVisibility::from_ast_with_hygiene(item.visibility(), &self.hygiene); | ||
221 | let (kind, name) = match item { | 236 | let (kind, name) = match item { |
222 | ast::ModuleItem::Module(module) => { | 237 | ast::ModuleItem::Module(module) => { |
223 | self.add_module(current_module, module); | 238 | self.add_module(current_module, module); |
@@ -266,7 +281,7 @@ impl RawItemsCollector { | |||
266 | }; | 281 | }; |
267 | if let Some(name) = name { | 282 | if let Some(name) = name { |
268 | let name = name.as_name(); | 283 | let name = name.as_name(); |
269 | let def = self.raw_items.defs.alloc(DefData { name, kind }); | 284 | let def = self.raw_items.defs.alloc(DefData { name, kind, visibility }); |
270 | self.push_item(current_module, attrs, RawItemKind::Def(def)); | 285 | self.push_item(current_module, attrs, RawItemKind::Def(def)); |
271 | } | 286 | } |
272 | } | 287 | } |
@@ -277,10 +292,12 @@ impl RawItemsCollector { | |||
277 | None => return, | 292 | None => return, |
278 | }; | 293 | }; |
279 | let attrs = self.parse_attrs(&module); | 294 | let attrs = self.parse_attrs(&module); |
295 | let visibility = RawVisibility::from_ast_with_hygiene(module.visibility(), &self.hygiene); | ||
280 | 296 | ||
281 | let ast_id = self.source_ast_id_map.ast_id(&module); | 297 | let ast_id = self.source_ast_id_map.ast_id(&module); |
282 | if module.has_semi() { | 298 | if module.has_semi() { |
283 | let item = self.raw_items.modules.alloc(ModuleData::Declaration { name, ast_id }); | 299 | let item = |
300 | self.raw_items.modules.alloc(ModuleData::Declaration { name, visibility, ast_id }); | ||
284 | self.push_item(current_module, attrs, RawItemKind::Module(item)); | 301 | self.push_item(current_module, attrs, RawItemKind::Module(item)); |
285 | return; | 302 | return; |
286 | } | 303 | } |
@@ -288,6 +305,7 @@ impl RawItemsCollector { | |||
288 | if let Some(item_list) = module.item_list() { | 305 | if let Some(item_list) = module.item_list() { |
289 | let item = self.raw_items.modules.alloc(ModuleData::Definition { | 306 | let item = self.raw_items.modules.alloc(ModuleData::Definition { |
290 | name, | 307 | name, |
308 | visibility, | ||
291 | ast_id, | 309 | ast_id, |
292 | items: Vec::new(), | 310 | items: Vec::new(), |
293 | }); | 311 | }); |
@@ -302,6 +320,7 @@ impl RawItemsCollector { | |||
302 | // FIXME: cfg_attr | 320 | // FIXME: cfg_attr |
303 | let is_prelude = use_item.has_atom_attr("prelude_import"); | 321 | let is_prelude = use_item.has_atom_attr("prelude_import"); |
304 | let attrs = self.parse_attrs(&use_item); | 322 | let attrs = self.parse_attrs(&use_item); |
323 | let visibility = RawVisibility::from_ast_with_hygiene(use_item.visibility(), &self.hygiene); | ||
305 | 324 | ||
306 | let mut buf = Vec::new(); | 325 | let mut buf = Vec::new(); |
307 | ModPath::expand_use_item( | 326 | ModPath::expand_use_item( |
@@ -315,6 +334,7 @@ impl RawItemsCollector { | |||
315 | is_prelude, | 334 | is_prelude, |
316 | is_extern_crate: false, | 335 | is_extern_crate: false, |
317 | is_macro_use: false, | 336 | is_macro_use: false, |
337 | visibility: visibility.clone(), | ||
318 | }; | 338 | }; |
319 | buf.push(import_data); | 339 | buf.push(import_data); |
320 | }, | 340 | }, |
@@ -331,6 +351,8 @@ impl RawItemsCollector { | |||
331 | ) { | 351 | ) { |
332 | if let Some(name_ref) = extern_crate.name_ref() { | 352 | if let Some(name_ref) = extern_crate.name_ref() { |
333 | let path = ModPath::from_name_ref(&name_ref); | 353 | let path = ModPath::from_name_ref(&name_ref); |
354 | let visibility = | ||
355 | RawVisibility::from_ast_with_hygiene(extern_crate.visibility(), &self.hygiene); | ||
334 | let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name()); | 356 | let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name()); |
335 | let attrs = self.parse_attrs(&extern_crate); | 357 | let attrs = self.parse_attrs(&extern_crate); |
336 | // FIXME: cfg_attr | 358 | // FIXME: cfg_attr |
@@ -342,6 +364,7 @@ impl RawItemsCollector { | |||
342 | is_prelude: false, | 364 | is_prelude: false, |
343 | is_extern_crate: true, | 365 | is_extern_crate: true, |
344 | is_macro_use, | 366 | is_macro_use, |
367 | visibility, | ||
345 | }; | 368 | }; |
346 | self.push_import(current_module, attrs, import_data); | 369 | self.push_import(current_module, attrs, import_data); |
347 | } | 370 | } |
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs index ff474b53b..78bcdc850 100644 --- a/crates/ra_hir_def/src/nameres/tests.rs +++ b/crates/ra_hir_def/src/nameres/tests.rs | |||
@@ -12,8 +12,8 @@ use test_utils::covers; | |||
12 | 12 | ||
13 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB, LocalModuleId}; | 13 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB, LocalModuleId}; |
14 | 14 | ||
15 | fn def_map(fixtute: &str) -> String { | 15 | fn def_map(fixture: &str) -> String { |
16 | let dm = compute_crate_def_map(fixtute); | 16 | let dm = compute_crate_def_map(fixture); |
17 | render_crate_def_map(&dm) | 17 | render_crate_def_map(&dm) |
18 | } | 18 | } |
19 | 19 | ||
@@ -32,7 +32,7 @@ fn render_crate_def_map(map: &CrateDefMap) -> String { | |||
32 | *buf += path; | 32 | *buf += path; |
33 | *buf += "\n"; | 33 | *buf += "\n"; |
34 | 34 | ||
35 | let mut entries = map.modules[module].scope.collect_resolutions(); | 35 | let mut entries: Vec<_> = map.modules[module].scope.resolutions().collect(); |
36 | entries.sort_by_key(|(name, _)| name.clone()); | 36 | entries.sort_by_key(|(name, _)| name.clone()); |
37 | 37 | ||
38 | for (name, def) in entries { | 38 | for (name, def) in entries { |
diff --git a/crates/ra_hir_def/src/nameres/tests/globs.rs b/crates/ra_hir_def/src/nameres/tests/globs.rs index 5e24cb94d..71fa0abe8 100644 --- a/crates/ra_hir_def/src/nameres/tests/globs.rs +++ b/crates/ra_hir_def/src/nameres/tests/globs.rs | |||
@@ -74,6 +74,83 @@ fn glob_2() { | |||
74 | } | 74 | } |
75 | 75 | ||
76 | #[test] | 76 | #[test] |
77 | fn glob_privacy_1() { | ||
78 | let map = def_map( | ||
79 | " | ||
80 | //- /lib.rs | ||
81 | mod foo; | ||
82 | use foo::*; | ||
83 | |||
84 | //- /foo/mod.rs | ||
85 | pub mod bar; | ||
86 | pub use self::bar::*; | ||
87 | struct PrivateStructFoo; | ||
88 | |||
89 | //- /foo/bar.rs | ||
90 | pub struct Baz; | ||
91 | struct PrivateStructBar; | ||
92 | pub use super::*; | ||
93 | ", | ||
94 | ); | ||
95 | assert_snapshot!(map, @r###" | ||
96 | crate | ||
97 | Baz: t v | ||
98 | bar: t | ||
99 | foo: t | ||
100 | |||
101 | crate::foo | ||
102 | Baz: t v | ||
103 | PrivateStructFoo: t v | ||
104 | bar: t | ||
105 | |||
106 | crate::foo::bar | ||
107 | Baz: t v | ||
108 | PrivateStructBar: t v | ||
109 | PrivateStructFoo: t v | ||
110 | bar: t | ||
111 | "### | ||
112 | ); | ||
113 | } | ||
114 | |||
115 | #[test] | ||
116 | fn glob_privacy_2() { | ||
117 | let map = def_map( | ||
118 | " | ||
119 | //- /lib.rs | ||
120 | mod foo; | ||
121 | use foo::*; | ||
122 | use foo::bar::*; | ||
123 | |||
124 | //- /foo/mod.rs | ||
125 | mod bar; | ||
126 | fn Foo() {}; | ||
127 | pub struct Foo {}; | ||
128 | |||
129 | //- /foo/bar.rs | ||
130 | pub(super) struct PrivateBaz; | ||
131 | struct PrivateBar; | ||
132 | pub(crate) struct PubCrateStruct; | ||
133 | ", | ||
134 | ); | ||
135 | assert_snapshot!(map, @r###" | ||
136 | crate | ||
137 | Foo: t | ||
138 | PubCrateStruct: t v | ||
139 | foo: t | ||
140 | |||
141 | crate::foo | ||
142 | Foo: t v | ||
143 | bar: t | ||
144 | |||
145 | crate::foo::bar | ||
146 | PrivateBar: t v | ||
147 | PrivateBaz: t v | ||
148 | PubCrateStruct: t v | ||
149 | "### | ||
150 | ); | ||
151 | } | ||
152 | |||
153 | #[test] | ||
77 | fn glob_across_crates() { | 154 | fn glob_across_crates() { |
78 | covers!(glob_across_crates); | 155 | covers!(glob_across_crates); |
79 | let map = def_map( | 156 | let map = def_map( |
@@ -93,6 +170,26 @@ fn glob_across_crates() { | |||
93 | } | 170 | } |
94 | 171 | ||
95 | #[test] | 172 | #[test] |
173 | fn glob_privacy_across_crates() { | ||
174 | covers!(glob_across_crates); | ||
175 | let map = def_map( | ||
176 | " | ||
177 | //- /main.rs crate:main deps:test_crate | ||
178 | use test_crate::*; | ||
179 | |||
180 | //- /lib.rs crate:test_crate | ||
181 | pub struct Baz; | ||
182 | struct Foo; | ||
183 | ", | ||
184 | ); | ||
185 | assert_snapshot!(map, @r###" | ||
186 | â‹®crate | ||
187 | â‹®Baz: t v | ||
188 | "### | ||
189 | ); | ||
190 | } | ||
191 | |||
192 | #[test] | ||
96 | fn glob_enum() { | 193 | fn glob_enum() { |
97 | covers!(glob_enum); | 194 | covers!(glob_enum); |
98 | let map = def_map( | 195 | let map = def_map( |
diff --git a/crates/ra_hir_def/src/nameres/tests/incremental.rs b/crates/ra_hir_def/src/nameres/tests/incremental.rs index ef2e9435c..faeb7aa4d 100644 --- a/crates/ra_hir_def/src/nameres/tests/incremental.rs +++ b/crates/ra_hir_def/src/nameres/tests/incremental.rs | |||
@@ -116,7 +116,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() { | |||
116 | let events = db.log_executed(|| { | 116 | let events = db.log_executed(|| { |
117 | let crate_def_map = db.crate_def_map(krate); | 117 | let crate_def_map = db.crate_def_map(krate); |
118 | let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); | 118 | let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); |
119 | assert_eq!(module_data.scope.collect_resolutions().len(), 1); | 119 | assert_eq!(module_data.scope.resolutions().collect::<Vec<_>>().len(), 1); |
120 | }); | 120 | }); |
121 | assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) | 121 | assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) |
122 | } | 122 | } |
@@ -126,7 +126,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() { | |||
126 | let events = db.log_executed(|| { | 126 | let events = db.log_executed(|| { |
127 | let crate_def_map = db.crate_def_map(krate); | 127 | let crate_def_map = db.crate_def_map(krate); |
128 | let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); | 128 | let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); |
129 | assert_eq!(module_data.scope.collect_resolutions().len(), 1); | 129 | assert_eq!(module_data.scope.resolutions().collect::<Vec<_>>().len(), 1); |
130 | }); | 130 | }); |
131 | assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) | 131 | assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) |
132 | } | 132 | } |
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 8e1294201..107d2d799 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs | |||
@@ -130,6 +130,14 @@ impl Path { | |||
130 | Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] } | 130 | Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] } |
131 | } | 131 | } |
132 | 132 | ||
133 | /// Converts a known mod path to `Path`. | ||
134 | pub(crate) fn from_known_path( | ||
135 | path: ModPath, | ||
136 | generic_args: Vec<Option<Arc<GenericArgs>>>, | ||
137 | ) -> Path { | ||
138 | Path { type_anchor: None, mod_path: path, generic_args } | ||
139 | } | ||
140 | |||
133 | pub fn kind(&self) -> &PathKind { | 141 | pub fn kind(&self) -> &PathKind { |
134 | &self.mod_path.kind | 142 | &self.mod_path.kind |
135 | } | 143 | } |
diff --git a/crates/ra_hir_def/src/per_ns.rs b/crates/ra_hir_def/src/per_ns.rs index 3a5105028..6e435c8c1 100644 --- a/crates/ra_hir_def/src/per_ns.rs +++ b/crates/ra_hir_def/src/per_ns.rs | |||
@@ -5,13 +5,13 @@ | |||
5 | 5 | ||
6 | use hir_expand::MacroDefId; | 6 | use hir_expand::MacroDefId; |
7 | 7 | ||
8 | use crate::ModuleDefId; | 8 | use crate::{visibility::Visibility, ModuleDefId}; |
9 | 9 | ||
10 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | 10 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
11 | pub struct PerNs { | 11 | pub struct PerNs { |
12 | pub types: Option<ModuleDefId>, | 12 | pub types: Option<(ModuleDefId, Visibility)>, |
13 | pub values: Option<ModuleDefId>, | 13 | pub values: Option<(ModuleDefId, Visibility)>, |
14 | pub macros: Option<MacroDefId>, | 14 | pub macros: Option<(MacroDefId, Visibility)>, |
15 | } | 15 | } |
16 | 16 | ||
17 | impl Default for PerNs { | 17 | impl Default for PerNs { |
@@ -25,20 +25,20 @@ impl PerNs { | |||
25 | PerNs { types: None, values: None, macros: None } | 25 | PerNs { types: None, values: None, macros: None } |
26 | } | 26 | } |
27 | 27 | ||
28 | pub fn values(t: ModuleDefId) -> PerNs { | 28 | pub fn values(t: ModuleDefId, v: Visibility) -> PerNs { |
29 | PerNs { types: None, values: Some(t), macros: None } | 29 | PerNs { types: None, values: Some((t, v)), macros: None } |
30 | } | 30 | } |
31 | 31 | ||
32 | pub fn types(t: ModuleDefId) -> PerNs { | 32 | pub fn types(t: ModuleDefId, v: Visibility) -> PerNs { |
33 | PerNs { types: Some(t), values: None, macros: None } | 33 | PerNs { types: Some((t, v)), values: None, macros: None } |
34 | } | 34 | } |
35 | 35 | ||
36 | pub fn both(types: ModuleDefId, values: ModuleDefId) -> PerNs { | 36 | pub fn both(types: ModuleDefId, values: ModuleDefId, v: Visibility) -> PerNs { |
37 | PerNs { types: Some(types), values: Some(values), macros: None } | 37 | PerNs { types: Some((types, v)), values: Some((values, v)), macros: None } |
38 | } | 38 | } |
39 | 39 | ||
40 | pub fn macros(macro_: MacroDefId) -> PerNs { | 40 | pub fn macros(macro_: MacroDefId, v: Visibility) -> PerNs { |
41 | PerNs { types: None, values: None, macros: Some(macro_) } | 41 | PerNs { types: None, values: None, macros: Some((macro_, v)) } |
42 | } | 42 | } |
43 | 43 | ||
44 | pub fn is_none(&self) -> bool { | 44 | pub fn is_none(&self) -> bool { |
@@ -46,15 +46,35 @@ impl PerNs { | |||
46 | } | 46 | } |
47 | 47 | ||
48 | pub fn take_types(self) -> Option<ModuleDefId> { | 48 | pub fn take_types(self) -> Option<ModuleDefId> { |
49 | self.types.map(|it| it.0) | ||
50 | } | ||
51 | |||
52 | pub fn take_types_vis(self) -> Option<(ModuleDefId, Visibility)> { | ||
49 | self.types | 53 | self.types |
50 | } | 54 | } |
51 | 55 | ||
52 | pub fn take_values(self) -> Option<ModuleDefId> { | 56 | pub fn take_values(self) -> Option<ModuleDefId> { |
53 | self.values | 57 | self.values.map(|it| it.0) |
54 | } | 58 | } |
55 | 59 | ||
56 | pub fn take_macros(self) -> Option<MacroDefId> { | 60 | pub fn take_macros(self) -> Option<MacroDefId> { |
57 | self.macros | 61 | self.macros.map(|it| it.0) |
62 | } | ||
63 | |||
64 | pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs { | ||
65 | PerNs { | ||
66 | types: self.types.filter(|(_, v)| f(*v)), | ||
67 | values: self.values.filter(|(_, v)| f(*v)), | ||
68 | macros: self.macros.filter(|(_, v)| f(*v)), | ||
69 | } | ||
70 | } | ||
71 | |||
72 | pub fn with_visibility(self, vis: Visibility) -> PerNs { | ||
73 | PerNs { | ||
74 | types: self.types.map(|(it, _)| (it, vis)), | ||
75 | values: self.values.map(|(it, _)| (it, vis)), | ||
76 | macros: self.macros.map(|(it, _)| (it, vis)), | ||
77 | } | ||
58 | } | 78 | } |
59 | 79 | ||
60 | pub fn or(self, other: PerNs) -> PerNs { | 80 | pub fn or(self, other: PerNs) -> PerNs { |
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index cf3c33d78..5d16dd087 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs | |||
@@ -19,6 +19,7 @@ use crate::{ | |||
19 | nameres::CrateDefMap, | 19 | nameres::CrateDefMap, |
20 | path::{ModPath, PathKind}, | 20 | path::{ModPath, PathKind}, |
21 | per_ns::PerNs, | 21 | per_ns::PerNs, |
22 | visibility::{RawVisibility, Visibility}, | ||
22 | AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, | 23 | AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, |
23 | FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, | 24 | FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, |
24 | StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId, | 25 | StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId, |
@@ -231,6 +232,23 @@ impl Resolver { | |||
231 | Some(res) | 232 | Some(res) |
232 | } | 233 | } |
233 | 234 | ||
235 | pub fn resolve_visibility( | ||
236 | &self, | ||
237 | db: &impl DefDatabase, | ||
238 | visibility: &RawVisibility, | ||
239 | ) -> Option<Visibility> { | ||
240 | match visibility { | ||
241 | RawVisibility::Module(_) => { | ||
242 | let (item_map, module) = match self.module() { | ||
243 | Some(it) => it, | ||
244 | None => return None, | ||
245 | }; | ||
246 | item_map.resolve_visibility(db, module, visibility) | ||
247 | } | ||
248 | RawVisibility::Public => Some(Visibility::Public), | ||
249 | } | ||
250 | } | ||
251 | |||
234 | pub fn resolve_path_in_value_ns( | 252 | pub fn resolve_path_in_value_ns( |
235 | &self, | 253 | &self, |
236 | db: &impl DefDatabase, | 254 | db: &impl DefDatabase, |
@@ -448,10 +466,10 @@ impl Scope { | |||
448 | f(name.clone(), ScopeDef::PerNs(def)); | 466 | f(name.clone(), ScopeDef::PerNs(def)); |
449 | }); | 467 | }); |
450 | m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| { | 468 | m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| { |
451 | f(name.clone(), ScopeDef::PerNs(PerNs::macros(macro_))); | 469 | f(name.clone(), ScopeDef::PerNs(PerNs::macros(macro_, Visibility::Public))); |
452 | }); | 470 | }); |
453 | m.crate_def_map.extern_prelude.iter().for_each(|(name, &def)| { | 471 | m.crate_def_map.extern_prelude.iter().for_each(|(name, &def)| { |
454 | f(name.clone(), ScopeDef::PerNs(PerNs::types(def.into()))); | 472 | f(name.clone(), ScopeDef::PerNs(PerNs::types(def.into(), Visibility::Public))); |
455 | }); | 473 | }); |
456 | if let Some(prelude) = m.crate_def_map.prelude { | 474 | if let Some(prelude) = m.crate_def_map.prelude { |
457 | let prelude_def_map = db.crate_def_map(prelude.krate); | 475 | let prelude_def_map = db.crate_def_map(prelude.krate); |
@@ -626,7 +644,7 @@ impl HasResolver for ContainerId { | |||
626 | fn resolver(self, db: &impl DefDatabase) -> Resolver { | 644 | fn resolver(self, db: &impl DefDatabase) -> Resolver { |
627 | match self { | 645 | match self { |
628 | ContainerId::ModuleId(it) => it.resolver(db), | 646 | ContainerId::ModuleId(it) => it.resolver(db), |
629 | ContainerId::DefWithBodyId(it) => it.resolver(db), | 647 | ContainerId::DefWithBodyId(it) => it.module(db).resolver(db), |
630 | } | 648 | } |
631 | } | 649 | } |
632 | } | 650 | } |
diff --git a/crates/ra_hir_def/src/visibility.rs b/crates/ra_hir_def/src/visibility.rs new file mode 100644 index 000000000..d8296da4b --- /dev/null +++ b/crates/ra_hir_def/src/visibility.rs | |||
@@ -0,0 +1,120 @@ | |||
1 | //! Defines hir-level representation of visibility (e.g. `pub` and `pub(crate)`). | ||
2 | |||
3 | use hir_expand::{hygiene::Hygiene, InFile}; | ||
4 | use ra_syntax::ast; | ||
5 | |||
6 | use crate::{ | ||
7 | db::DefDatabase, | ||
8 | path::{ModPath, PathKind}, | ||
9 | ModuleId, | ||
10 | }; | ||
11 | |||
12 | /// Visibility of an item, not yet resolved. | ||
13 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
14 | pub enum RawVisibility { | ||
15 | /// `pub(in module)`, `pub(crate)` or `pub(super)`. Also private, which is | ||
16 | /// equivalent to `pub(self)`. | ||
17 | Module(ModPath), | ||
18 | /// `pub`. | ||
19 | Public, | ||
20 | } | ||
21 | |||
22 | impl RawVisibility { | ||
23 | const fn private() -> RawVisibility { | ||
24 | let path = ModPath { kind: PathKind::Super(0), segments: Vec::new() }; | ||
25 | RawVisibility::Module(path) | ||
26 | } | ||
27 | |||
28 | pub(crate) fn from_ast( | ||
29 | db: &impl DefDatabase, | ||
30 | node: InFile<Option<ast::Visibility>>, | ||
31 | ) -> RawVisibility { | ||
32 | Self::from_ast_with_hygiene(node.value, &Hygiene::new(db, node.file_id)) | ||
33 | } | ||
34 | |||
35 | pub(crate) fn from_ast_with_hygiene( | ||
36 | node: Option<ast::Visibility>, | ||
37 | hygiene: &Hygiene, | ||
38 | ) -> RawVisibility { | ||
39 | let node = match node { | ||
40 | None => return RawVisibility::private(), | ||
41 | Some(node) => node, | ||
42 | }; | ||
43 | match node.kind() { | ||
44 | ast::VisibilityKind::In(path) => { | ||
45 | let path = ModPath::from_src(path, hygiene); | ||
46 | let path = match path { | ||
47 | None => return RawVisibility::private(), | ||
48 | Some(path) => path, | ||
49 | }; | ||
50 | RawVisibility::Module(path) | ||
51 | } | ||
52 | ast::VisibilityKind::PubCrate => { | ||
53 | let path = ModPath { kind: PathKind::Crate, segments: Vec::new() }; | ||
54 | RawVisibility::Module(path) | ||
55 | } | ||
56 | ast::VisibilityKind::PubSuper => { | ||
57 | let path = ModPath { kind: PathKind::Super(1), segments: Vec::new() }; | ||
58 | RawVisibility::Module(path) | ||
59 | } | ||
60 | ast::VisibilityKind::Pub => RawVisibility::Public, | ||
61 | } | ||
62 | } | ||
63 | |||
64 | pub fn resolve( | ||
65 | &self, | ||
66 | db: &impl DefDatabase, | ||
67 | resolver: &crate::resolver::Resolver, | ||
68 | ) -> Visibility { | ||
69 | // we fall back to public visibility (i.e. fail open) if the path can't be resolved | ||
70 | resolver.resolve_visibility(db, self).unwrap_or(Visibility::Public) | ||
71 | } | ||
72 | } | ||
73 | |||
74 | /// Visibility of an item, with the path resolved. | ||
75 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | ||
76 | pub enum Visibility { | ||
77 | /// Visibility is restricted to a certain module. | ||
78 | Module(ModuleId), | ||
79 | /// Visibility is unrestricted. | ||
80 | Public, | ||
81 | } | ||
82 | |||
83 | impl Visibility { | ||
84 | pub fn is_visible_from(self, db: &impl DefDatabase, from_module: ModuleId) -> bool { | ||
85 | let to_module = match self { | ||
86 | Visibility::Module(m) => m, | ||
87 | Visibility::Public => return true, | ||
88 | }; | ||
89 | // if they're not in the same crate, it can't be visible | ||
90 | if from_module.krate != to_module.krate { | ||
91 | return false; | ||
92 | } | ||
93 | let def_map = db.crate_def_map(from_module.krate); | ||
94 | self.is_visible_from_def_map(&def_map, from_module.local_id) | ||
95 | } | ||
96 | |||
97 | pub(crate) fn is_visible_from_other_crate(self) -> bool { | ||
98 | match self { | ||
99 | Visibility::Module(_) => false, | ||
100 | Visibility::Public => true, | ||
101 | } | ||
102 | } | ||
103 | |||
104 | pub(crate) fn is_visible_from_def_map( | ||
105 | self, | ||
106 | def_map: &crate::nameres::CrateDefMap, | ||
107 | from_module: crate::LocalModuleId, | ||
108 | ) -> bool { | ||
109 | let to_module = match self { | ||
110 | Visibility::Module(m) => m, | ||
111 | Visibility::Public => return true, | ||
112 | }; | ||
113 | // from_module needs to be a descendant of to_module | ||
114 | let mut ancestors = std::iter::successors(Some(from_module), |m| { | ||
115 | let parent_id = def_map[*m].parent?; | ||
116 | Some(parent_id) | ||
117 | }); | ||
118 | ancestors.any(|m| m == to_module.local_id) | ||
119 | } | ||
120 | } | ||