use crate::module_tree::{LocalModuleId, ModuleTree};
use crate::{ids::ModuleId, DefDatabase, HirDatabase, Resolver};
use mun_syntax::ast;
use std::iter::successors;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RawVisibility {
This,
Super,
Package,
Public,
}
impl RawVisibility {
const fn private() -> RawVisibility {
RawVisibility::This
}
pub(crate) fn from_ast(node: Option<ast::Visibility>) -> RawVisibility {
let node = match node {
None => return RawVisibility::private(),
Some(node) => node,
};
match node.kind() {
ast::VisibilityKind::Pub => RawVisibility::Public,
ast::VisibilityKind::PubSuper => RawVisibility::Super,
ast::VisibilityKind::PubPackage => RawVisibility::Package,
}
}
pub fn resolve(&self, db: &dyn DefDatabase, resolver: &Resolver) -> Visibility {
resolver
.resolve_visibility(db, self)
.unwrap_or(Visibility::Public)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Visibility {
Module(ModuleId),
Public,
}
impl Visibility {
pub(crate) fn is_visible_from_module_tree(
self,
module_tree: &ModuleTree,
from_module: LocalModuleId,
) -> bool {
let to_module = match self {
Visibility::Module(m) => m,
Visibility::Public => return true,
};
let mut ancestors = successors(Some(from_module), |m| module_tree[*m].parent);
ancestors.any(|m| m == to_module.local_id)
}
pub fn is_visible_from(self, db: &dyn HirDatabase, from_module: ModuleId) -> bool {
let to_module = match self {
Visibility::Module(m) => m,
Visibility::Public => return true,
};
let module_tree = db.module_tree(from_module.package);
let mut ancestors = successors(Some(from_module.local_id), |m| module_tree[*m].parent);
ancestors.any(|m| m == to_module.local_id)
}
pub fn is_externally_visible(self) -> bool {
match self {
Visibility::Module(_) => false,
Visibility::Public => true,
}
}
}
pub trait HasVisibility {
fn visibility(&self, db: &dyn HirDatabase) -> Visibility;
}