Skip to main content

mago_syntax/ast/ast/
namespace.rs

1use serde::Serialize;
2use strum::Display;
3
4use mago_span::HasSpan;
5use mago_span::Span;
6
7use crate::ast::ast::block::Block;
8use crate::ast::ast::identifier::Identifier;
9use crate::ast::ast::keyword::Keyword;
10use crate::ast::ast::statement::Statement;
11use crate::ast::ast::terminator::Terminator;
12
13use crate::ast::sequence::Sequence;
14
15/// Represents a PHP `namespace` declaration.
16///
17/// # Examples
18///
19/// ```php
20/// <?php
21///
22/// namespace Foo\Bar {
23///    // ...
24/// }
25/// ```
26#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
27pub struct Namespace<'arena> {
28    pub namespace: Keyword<'arena>,
29    pub name: Option<Identifier<'arena>>,
30    pub body: NamespaceBody<'arena>,
31}
32
33/// Represents the body of a PHP `namespace` declaration.
34#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord, Display)]
35#[serde(tag = "type", content = "value")]
36pub enum NamespaceBody<'arena> {
37    Implicit(NamespaceImplicitBody<'arena>),
38    BraceDelimited(Block<'arena>),
39}
40
41/// Represents an implicit body of a PHP `namespace` declaration.
42///
43/// # Examples
44///
45/// ```php
46/// <?php
47///
48/// namespace Foo\Bar;
49///
50/// // ...
51/// ```
52#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
53pub struct NamespaceImplicitBody<'arena> {
54    pub terminator: Terminator<'arena>,
55    pub statements: Sequence<'arena, Statement<'arena>>,
56}
57
58impl<'arena> Namespace<'arena> {
59    #[must_use]
60    pub fn statements(&self) -> &Sequence<'arena, Statement<'arena>> {
61        match &self.body {
62            NamespaceBody::Implicit(body) => &body.statements,
63            NamespaceBody::BraceDelimited(body) => &body.statements,
64        }
65    }
66}
67
68impl HasSpan for Namespace<'_> {
69    fn span(&self) -> Span {
70        self.namespace.span().join(self.body.span())
71    }
72}
73
74impl HasSpan for NamespaceBody<'_> {
75    fn span(&self) -> Span {
76        match self {
77            NamespaceBody::Implicit(body) => body.span(),
78            NamespaceBody::BraceDelimited(body) => body.span(),
79        }
80    }
81}
82
83impl HasSpan for NamespaceImplicitBody<'_> {
84    fn span(&self) -> Span {
85        let terminator_span = self.terminator.span();
86
87        terminator_span.join(self.statements.span(terminator_span.file_id, terminator_span.end))
88    }
89}