Skip to main content

css_parse/syntax/
no_block_allowed.rs

1use crate::{CursorSink, Diagnostic, KindSet, Parse, Parser, Peek, Result, SemanticEq, Span, T, ToCursors, ToSpan};
2
3/// A struct to provide to rules to disallow blocks.
4///
5/// Sometimes a rule will not allow a block - for example `@charset`, `@import`. In those case, assigning this struct
6/// to the `Block` can be useful to ensure that the [QualifiedRule][crate::syntax::QualifiedRule] appropriately errors
7/// if it enters the Block parsing context. This captures the `;` token that may optionally end a "statement-style"
8/// at-rule.
9///
10/// The phantom data allows this type to be compatible with different declaration value and metadata types,
11/// even though it doesn't actually use them (since no block is allowed).
12#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
13#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
14pub struct NoBlockAllowed<D = (), M = ()> {
15	semicolon: Option<crate::token_macros::Semicolon>,
16	_phantom: std::marker::PhantomData<(D, M)>,
17}
18
19impl<'a, D, M> Parse<'a> for NoBlockAllowed<D, M> {
20	fn parse<Iter>(p: &mut Parser<'a, Iter>) -> Result<Self>
21	where
22		Iter: Iterator<Item = crate::Cursor> + Clone,
23	{
24		if p.at_end() {
25			Ok(Self { semicolon: None, _phantom: std::marker::PhantomData })
26		} else if let Some(semicolon) = p.parse_if_peek::<T![;]>()? {
27			Ok(Self { semicolon: Some(semicolon), _phantom: std::marker::PhantomData })
28		} else {
29			Err(Diagnostic::new(p.next(), Diagnostic::unexpected))?
30		}
31	}
32}
33
34impl<'a, D, M> Peek<'a> for NoBlockAllowed<D, M> {
35	const PEEK_KINDSET: KindSet = KindSet::NONE;
36}
37
38impl<D, M> ToCursors for NoBlockAllowed<D, M> {
39	fn to_cursors(&self, s: &mut impl CursorSink) {
40		if let Some(semicolon) = self.semicolon {
41			s.append(semicolon.into());
42		}
43	}
44}
45
46impl<D, M> ToSpan for NoBlockAllowed<D, M> {
47	fn to_span(&self) -> Span {
48		self.semicolon.to_span()
49	}
50}
51
52impl<D, M> SemanticEq for NoBlockAllowed<D, M> {
53	fn semantic_eq(&self, other: &Self) -> bool {
54		self.semicolon.semantic_eq(&other.semicolon)
55	}
56}
57
58impl<D, M: crate::NodeMetadata> crate::NodeWithMetadata<M> for NoBlockAllowed<D, M> {
59	fn metadata(&self) -> M {
60		M::default()
61	}
62}
63
64impl<'a, D, M> crate::RuleVariants<'a> for NoBlockAllowed<D, M>
65where
66	D: crate::DeclarationValue<'a, M>,
67	M: crate::NodeMetadata,
68{
69	type DeclarationValue = D;
70	type Metadata = M;
71}