Skip to main content

mago_syntax/ast/
trivia.rs

1use serde::Serialize;
2use strum::Display;
3
4use mago_span::HasSpan;
5use mago_span::Span;
6
7use crate::ast::Sequence;
8
9/// Represents the kind of trivia.
10#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord, Display)]
11#[serde(tag = "type", content = "value")]
12pub enum TriviaKind {
13    WhiteSpace,
14    SingleLineComment,
15    MultiLineComment,
16    HashComment,
17    DocBlockComment,
18}
19
20/// Represents a trivia.
21///
22/// A trivia is a piece of information that is not part of the syntax tree,
23/// such as comments and white spaces.
24#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
25pub struct Trivia<'arena> {
26    pub kind: TriviaKind,
27    pub span: Span,
28    pub value: &'arena str,
29}
30
31impl TriviaKind {
32    /// Returns `true` if the trivia kind is a comment.
33    #[inline]
34    #[must_use]
35    pub const fn is_comment(&self) -> bool {
36        matches!(
37            self,
38            TriviaKind::SingleLineComment
39                | TriviaKind::MultiLineComment
40                | TriviaKind::HashComment
41                | TriviaKind::DocBlockComment
42        )
43    }
44
45    #[inline]
46    #[must_use]
47    pub const fn is_docblock(&self) -> bool {
48        matches!(self, TriviaKind::DocBlockComment)
49    }
50
51    #[inline]
52    #[must_use]
53    pub const fn is_block_comment(&self) -> bool {
54        matches!(self, TriviaKind::MultiLineComment | TriviaKind::DocBlockComment)
55    }
56
57    #[inline]
58    #[must_use]
59    pub const fn is_single_line_comment(&self) -> bool {
60        matches!(self, TriviaKind::HashComment | TriviaKind::SingleLineComment)
61    }
62}
63
64impl HasSpan for Trivia<'_> {
65    fn span(&self) -> Span {
66        self.span
67    }
68}
69
70/// Iteration helpers over a trivia [`Sequence`].
71///
72/// `Sequence` lives in [`mago_syntax_core`], so PHP-specific helpers are
73/// exposed as an extension trait. `use crate::ast::*;` imports it.
74pub trait TriviaSequenceExt<'arena> {
75    fn comments<'a>(&'a self) -> impl Iterator<Item = &'a Trivia<'arena>>
76    where
77        'arena: 'a;
78}
79
80impl<'arena> TriviaSequenceExt<'arena> for Sequence<'arena, Trivia<'arena>> {
81    #[inline]
82    fn comments<'a>(&'a self) -> impl Iterator<Item = &'a Trivia<'arena>>
83    where
84        'arena: 'a,
85    {
86        self.iter().filter(|trivia| trivia.kind.is_comment())
87    }
88}