cairo_lang_semantic/items/
visibility.rs

1use cairo_lang_defs::db::DefsGroup;
2use cairo_lang_defs::diagnostic_utils::StableLocation;
3use cairo_lang_defs::ids::ModuleId;
4use cairo_lang_diagnostics::DiagnosticsBuilder;
5use cairo_lang_syntax::node::db::SyntaxGroup;
6use cairo_lang_syntax::node::{Terminal, ast};
7
8use crate::SemanticDiagnostic;
9use crate::diagnostic::SemanticDiagnosticKind;
10
11/// Visibility of an item.
12#[derive(Copy, Clone, Debug, PartialEq, Eq)]
13pub enum Visibility {
14    Public,
15    PublicInCrate,
16    Private,
17}
18impl Visibility {
19    pub fn from_ast(
20        db: &dyn SyntaxGroup,
21        diagnostics: &mut DiagnosticsBuilder<SemanticDiagnostic>,
22        visibility: &ast::Visibility,
23    ) -> Self {
24        match visibility {
25            ast::Visibility::Pub(visibility_pub) => match visibility_pub.argument_clause(db) {
26                ast::OptionVisibilityPubArgumentClause::Empty(_) => Self::Public,
27                ast::OptionVisibilityPubArgumentClause::VisibilityPubArgumentClause(argument) => {
28                    if argument.argument(db).text(db) == "crate" {
29                        Self::PublicInCrate
30                    } else {
31                        diagnostics.add(SemanticDiagnostic::new(
32                            StableLocation::from_ast(&argument),
33                            SemanticDiagnosticKind::UnsupportedPubArgument,
34                        ));
35                        Self::Public
36                    }
37                }
38            },
39            ast::Visibility::Default(_) => Self::Private,
40        }
41    }
42}
43
44/// Determine whether a module member is visible to user module given the visibility within it,
45/// ignoring or forgetting the visibility of the ancestors of the containing module for a moment.
46pub fn peek_visible_in(
47    db: &dyn DefsGroup,
48    visibility_in_module: Visibility,
49    containing_module_id: ModuleId,
50    user_module_id: ModuleId,
51) -> bool {
52    if containing_module_id == user_module_id {
53        return true;
54    }
55    match visibility_in_module {
56        Visibility::Public => true,
57        Visibility::PublicInCrate => {
58            user_module_id.owning_crate(db) == containing_module_id.owning_crate(db)
59        }
60        Visibility::Private => db.module_ancestors(user_module_id).contains(&containing_module_id),
61    }
62}