use cairo_lang_defs::db::DefsGroup;
use cairo_lang_defs::ids::ModuleId;
use cairo_lang_syntax::node::{Terminal, TypedSyntaxNode, ast};
use salsa::Database;
use crate::diagnostic::{SemanticDiagnosticKind, SemanticDiagnostics, SemanticDiagnosticsBuilder};
#[derive(Copy, Clone, Debug, PartialEq, Eq, salsa::Update)]
pub enum Visibility {
Public,
PublicInCrate,
Private,
}
impl Visibility {
pub fn from_ast<'db>(
db: &'db dyn Database,
diagnostics: &mut SemanticDiagnostics<'db>,
visibility: &ast::Visibility<'db>,
) -> Self {
match visibility {
ast::Visibility::Pub(visibility_pub) => match visibility_pub.argument_clause(db) {
ast::OptionVisibilityPubArgumentClause::Empty(_) => Self::Public,
ast::OptionVisibilityPubArgumentClause::VisibilityPubArgumentClause(argument) => {
if argument.argument(db).text(db).long(db) == "crate" {
Self::PublicInCrate
} else {
diagnostics.report(
argument.stable_ptr(db),
SemanticDiagnosticKind::UnsupportedPubArgument,
);
Self::Public
}
}
},
ast::Visibility::Default(_) => Self::Private,
}
}
}
pub fn peek_visible_in<'db>(
db: &dyn Database,
visibility_in_module: Visibility,
containing_module_id: ModuleId<'db>,
user_module_id: ModuleId<'db>,
) -> bool {
if containing_module_id == user_module_id {
return true;
}
match visibility_in_module {
Visibility::Public => true,
Visibility::PublicInCrate => {
user_module_id.owning_crate(db) == containing_module_id.owning_crate(db)
}
Visibility::Private => db
.module_ancestors(user_module_id)
.contains(&db.module_perceived_module(containing_module_id)),
}
}