aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-12-24 19:32:42 +0000
committerFlorian Diebold <[email protected]>2019-12-26 15:23:40 +0000
commit069bf55cca1e1be1f6cdd28b638f691e059858dc (patch)
treeb929d8e84c26e00827a2f507a528ef31e651ecc8
parent97f01396eda7eb3e6ec5056f3f72d98e5739f829 (diff)
Add infrastructure for visibility on syntax and hir_def level
-rw-r--r--crates/ra_hir_def/src/db.rs6
-rw-r--r--crates/ra_hir_def/src/lib.rs25
-rw-r--r--crates/ra_hir_def/src/visibility.rs101
-rw-r--r--crates/ra_syntax/src/ast.rs4
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs29
5 files changed, 163 insertions, 2 deletions
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index c55fd4111..1761e2187 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -14,9 +14,10 @@ use crate::{
14 generics::GenericParams, 14 generics::GenericParams,
15 lang_item::{LangItemTarget, LangItems}, 15 lang_item::{LangItemTarget, LangItems},
16 nameres::{raw::RawItems, CrateDefMap}, 16 nameres::{raw::RawItems, CrateDefMap},
17 visibility::Visibility,
17 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, 18 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc,
18 GenericDefId, ImplId, ImplLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId, 19 GenericDefId, ImplId, ImplLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId,
19 TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, 20 TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, VisibilityDefId,
20}; 21};
21 22
22#[salsa::query_group(InternDatabaseStorage)] 23#[salsa::query_group(InternDatabaseStorage)]
@@ -90,6 +91,9 @@ pub trait DefDatabase: InternDatabase + AstDatabase {
90 #[salsa::invoke(Attrs::attrs_query)] 91 #[salsa::invoke(Attrs::attrs_query)]
91 fn attrs(&self, def: AttrDefId) -> Attrs; 92 fn attrs(&self, def: AttrDefId) -> Attrs;
92 93
94 #[salsa::invoke(Visibility::visibility_query)]
95 fn visibility(&self, def: VisibilityDefId) -> Visibility;
96
93 #[salsa::invoke(LangItems::module_lang_items_query)] 97 #[salsa::invoke(LangItems::module_lang_items_query)]
94 fn module_lang_items(&self, module: ModuleId) -> Option<Arc<LangItems>>; 98 fn module_lang_items(&self, module: ModuleId) -> Option<Arc<LangItems>>;
95 99
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index f6c7f38d1..72a59d867 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -36,6 +36,8 @@ pub mod nameres;
36pub mod src; 36pub mod src;
37pub mod child_by_source; 37pub mod child_by_source;
38 38
39pub mod visibility;
40
39#[cfg(test)] 41#[cfg(test)]
40mod test_db; 42mod test_db;
41#[cfg(test)] 43#[cfg(test)]
@@ -323,6 +325,29 @@ impl_froms!(
323 ImplId 325 ImplId
324); 326);
325 327
328#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
329pub enum VisibilityDefId {
330 ModuleId(ModuleId),
331 StructFieldId(StructFieldId),
332 AdtId(AdtId),
333 FunctionId(FunctionId),
334 StaticId(StaticId),
335 ConstId(ConstId),
336 TraitId(TraitId),
337 TypeAliasId(TypeAliasId),
338}
339
340impl_froms!(
341 VisibilityDefId: ModuleId,
342 StructFieldId,
343 AdtId(StructId, EnumId, UnionId),
344 StaticId,
345 ConstId,
346 FunctionId,
347 TraitId,
348 TypeAliasId
349);
350
326#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 351#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
327pub enum VariantId { 352pub enum VariantId {
328 EnumVariantId(EnumVariantId), 353 EnumVariantId(EnumVariantId),
diff --git a/crates/ra_hir_def/src/visibility.rs b/crates/ra_hir_def/src/visibility.rs
new file mode 100644
index 000000000..7d881911d
--- /dev/null
+++ b/crates/ra_hir_def/src/visibility.rs
@@ -0,0 +1,101 @@
1use std::sync::Arc;
2
3use either::Either;
4
5use hir_expand::InFile;
6use ra_syntax::ast::{self, VisibilityOwner};
7
8use crate::{
9 db::DefDatabase,
10 path::{ModPath, PathKind},
11 src::{HasChildSource, HasSource},
12 AdtId, Lookup, VisibilityDefId,
13};
14
15/// Visibility of an item, not yet resolved.
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub enum Visibility {
18 // FIXME: We could avoid the allocation in many cases by special-casing
19 // pub(crate), pub(super) and private. Alternatively, `ModPath` could be
20 // made to contain an Arc<[Segment]> instead of a Vec?
21 /// `pub(in module)`, `pub(crate)` or `pub(super)`. Also private, which is
22 /// equivalent to `pub(self)`.
23 Module(Arc<ModPath>),
24 /// `pub`.
25 Public,
26}
27
28impl Visibility {
29 pub(crate) fn visibility_query(db: &impl DefDatabase, def: VisibilityDefId) -> Visibility {
30 match def {
31 VisibilityDefId::ModuleId(module) => {
32 let def_map = db.crate_def_map(module.krate);
33 let src = match def_map[module.local_id].declaration_source(db) {
34 Some(it) => it,
35 None => return Visibility::private(),
36 };
37 Visibility::from_ast(db, src.map(|it| it.visibility()))
38 }
39 VisibilityDefId::StructFieldId(it) => {
40 let src = it.parent.child_source(db);
41 // TODO: enum variant fields should be public by default
42 let vis_node = src.map(|m| match &m[it.local_id] {
43 Either::Left(tuple) => tuple.visibility(),
44 Either::Right(record) => record.visibility(),
45 });
46 Visibility::from_ast(db, vis_node)
47 }
48 VisibilityDefId::AdtId(it) => match it {
49 AdtId::StructId(it) => visibility_from_loc(it.lookup(db), db),
50 AdtId::EnumId(it) => visibility_from_loc(it.lookup(db), db),
51 AdtId::UnionId(it) => visibility_from_loc(it.lookup(db), db),
52 },
53 VisibilityDefId::TraitId(it) => visibility_from_loc(it.lookup(db), db),
54 VisibilityDefId::ConstId(it) => visibility_from_loc(it.lookup(db), db),
55 VisibilityDefId::StaticId(it) => visibility_from_loc(it.lookup(db), db),
56 VisibilityDefId::FunctionId(it) => visibility_from_loc(it.lookup(db), db),
57 VisibilityDefId::TypeAliasId(it) => visibility_from_loc(it.lookup(db), db),
58 }
59 }
60
61 fn private() -> Visibility {
62 let path = ModPath { kind: PathKind::Super(0), segments: Vec::new() };
63 Visibility::Module(Arc::new(path))
64 }
65
66 fn from_ast(db: &impl DefDatabase, node: InFile<Option<ast::Visibility>>) -> Visibility {
67 let file_id = node.file_id;
68 let node = match node.value {
69 None => return Visibility::private(),
70 Some(node) => node,
71 };
72 match node.kind() {
73 ast::VisibilityKind::In(path) => {
74 let path = ModPath::from_src(path, &hir_expand::hygiene::Hygiene::new(db, file_id));
75 let path = match path {
76 None => return Visibility::private(),
77 Some(path) => path,
78 };
79 Visibility::Module(Arc::new(path))
80 }
81 ast::VisibilityKind::PubCrate => {
82 let path = ModPath { kind: PathKind::Crate, segments: Vec::new() };
83 Visibility::Module(Arc::new(path))
84 }
85 ast::VisibilityKind::PubSuper => {
86 let path = ModPath { kind: PathKind::Super(1), segments: Vec::new() };
87 Visibility::Module(Arc::new(path))
88 }
89 ast::VisibilityKind::Pub => Visibility::Public,
90 }
91 }
92}
93
94fn visibility_from_loc<T>(node: T, db: &impl DefDatabase) -> Visibility
95where
96 T: HasSource,
97 T::Value: ast::VisibilityOwner,
98{
99 let src = node.source(db);
100 Visibility::from_ast(db, src.map(|n| n.visibility()))
101}
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 277532a8c..89cb9a9f3 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -17,7 +17,9 @@ use crate::{
17 17
18pub use self::{ 18pub use self::{
19 expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp, RangeOp}, 19 expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp, RangeOp},
20 extensions::{FieldKind, PathSegmentKind, SelfParamKind, StructKind, TypeBoundKind}, 20 extensions::{
21 FieldKind, PathSegmentKind, SelfParamKind, StructKind, TypeBoundKind, VisibilityKind,
22 },
21 generated::*, 23 generated::*,
22 tokens::*, 24 tokens::*,
23 traits::*, 25 traits::*,
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index baaef3023..d9666cdca 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -413,3 +413,32 @@ impl ast::TraitDef {
413 self.syntax().children_with_tokens().any(|t| t.kind() == T![auto]) 413 self.syntax().children_with_tokens().any(|t| t.kind() == T![auto])
414 } 414 }
415} 415}
416
417pub enum VisibilityKind {
418 In(ast::Path),
419 PubCrate,
420 PubSuper,
421 Pub,
422}
423
424impl ast::Visibility {
425 pub fn kind(&self) -> VisibilityKind {
426 if let Some(path) = children(self).next() {
427 VisibilityKind::In(path)
428 } else if self.is_pub_crate() {
429 VisibilityKind::PubCrate
430 } else if self.is_pub_super() {
431 VisibilityKind::PubSuper
432 } else {
433 VisibilityKind::Pub
434 }
435 }
436
437 fn is_pub_crate(&self) -> bool {
438 self.syntax().children_with_tokens().any(|it| it.kind() == T![crate])
439 }
440
441 fn is_pub_super(&self) -> bool {
442 self.syntax().children_with_tokens().any(|it| it.kind() == T![super])
443 }
444}