Skip to main content

mago_syntax/cst/
trivia.rs

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