Skip to main content

oxc_css_parser/
error.rs

1//! Error management.
2
3use crate::pos::Span;
4#[cfg(feature = "serialize")]
5use serde::Serialize;
6use std::fmt::Display;
7
8#[derive(Clone, Debug)]
9#[cfg_attr(feature = "serialize", derive(Serialize))]
10#[cfg_attr(feature = "serialize", serde(rename_all = "camelCase"))]
11pub struct Error {
12    pub kind: ErrorKind,
13    pub span: Span,
14}
15
16#[derive(Clone, Debug)]
17#[cfg_attr(feature = "serialize", derive(Serialize))]
18pub enum ErrorKind {
19    Unexpected(
20        /* expected */ &'static str,
21        /* actual */ &'static str,
22    ),
23    ExpectOneOf(
24        /* expected */ Vec<&'static str>,
25        /* actual */ &'static str,
26    ),
27
28    UnknownToken,
29    InvalidNumber,
30    InvalidEscape,
31    InvalidHash,
32    ExpectRightBraceForLessVar,
33    UnexpectedLinebreak,
34    UnexpectedEof,
35    UnterminatedString,
36
37    ExpectRule,
38    UnexpectedWhitespace,
39    UnexpectedWhitespaceOrComments,
40    ExpectSimpleSelector,
41    ExpectTypeSelector,
42    ExpectIdSelector,
43    ExpectWqName,
44    ExpectAttributeSelectorMatcher,
45    ExpectAttributeSelectorValue,
46    ExpectComponentValue,
47    ExpectSassExpression,
48    ExpectDedentOrEof,
49    ExpectString,
50    ExpectUrl,
51    InvalidUrl,
52    UnexpectedTemplateInCss,
53    ExpectMediaFeatureComparison,
54    ExpectMediaAnd,
55    ExpectMediaOr,
56    ExpectMediaNot,
57    ExpectContainerConditionAnd,
58    ExpectContainerConditionOr,
59    ExpectContainerConditionNot,
60    ExpectStyleConditionAnd,
61    ExpectStyleConditionOr,
62    ExpectStyleConditionNot,
63    ExpectStyleQuery,
64    ExpectSassKeyword(&'static str),
65    InvalidAnPlusB,
66    ExpectInteger,
67    ExpectUnsignedInteger,
68    ExpectImportantAnnotation,
69    ExpectSassUseNamespace,
70    InvalidUnicodeRange,
71    UnexpectedSassElseAtRule,
72    ExpectSassAtRootWithOrWithout,
73    ExpectNthOf,
74    ExpectKeyframeBlock,
75    MixedDelimiterKindInLessMixin,
76    ExpectLessKeyword(&'static str),
77    ExpectLessExtendRule,
78    ExpectScopeTo,
79
80    TryParseError,
81    CSSWideKeywordDisallowed,
82    MediaTypeKeywordDisallowed(String),
83    UnknownKeyframeSelectorIdent,
84    InvalidRatioDenominator,
85    ExpectMediaFeatureName,
86    ExpectDashedIdent,
87    InvalidIdSelectorName,
88    ReturnOutsideFunction,
89    MaxCodePointExceeded,
90    UnicodeRangeStartGreaterThanEnd,
91    UnexpectedNthMatcher,
92    InvalidSassFlagName(String),
93    UnexpectedSassFlag(&'static str),
94    DuplicatedSassFlag(&'static str),
95    LessGuardOnMultipleComplexSelectors,
96    UnexpectedLessMixinCall,
97    UnexpectedSemicolonInSass,
98    UnexpectedSimpleBlock,
99    TopLevelDeclaration,
100}
101
102impl Display for ErrorKind {
103    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104        match self {
105            Self::Unexpected(expected, actual) => {
106                write!(f, "expect token `{expected}`, but found `{actual}`")
107            }
108            Self::ExpectOneOf(expected, actual) => {
109                if let [init @ .., last] = &expected[..] {
110                    let joined = init
111                        .iter()
112                        .map(|token| format!("`{token}`"))
113                        .collect::<Vec<_>>()
114                        .join(", ");
115                    write!(
116                        f,
117                        "expect one of {joined} or `{last}`, but found `{actual}`",
118                    )
119                } else {
120                    panic!("the number of expected tokens must be at least 2")
121                }
122            }
123
124            Self::UnknownToken => write!(f, "unknown token"),
125            Self::InvalidNumber => write!(f, "invalid number"),
126            Self::InvalidEscape => write!(f, "invalid escape"),
127            Self::InvalidHash => write!(f, "invalid hash token"),
128            Self::ExpectRightBraceForLessVar => write!(f, "`}}` for Less variable is expected"),
129            Self::UnexpectedLinebreak => write!(f, "unexpected linebreak"),
130            Self::UnexpectedEof => write!(f, "unexpected end of file"),
131            Self::UnterminatedString => write!(f, "unterminated string"),
132
133            Self::ExpectRule => write!(f, "CSS rule is expected"),
134            Self::UnexpectedWhitespace => write!(f, "unexpected whitespace"),
135            Self::UnexpectedWhitespaceOrComments => write!(f, "unexpected whitespace or comments"),
136            Self::ExpectSimpleSelector => write!(f, "simple selector is expected"),
137            Self::ExpectTypeSelector => write!(f, "type selector is expected"),
138            Self::ExpectIdSelector => write!(f, "ID selector is expected"),
139            Self::ExpectWqName => write!(f, "WqName is expected"),
140            Self::ExpectAttributeSelectorMatcher => {
141                write!(f, "attribute selector matcher is expected")
142            }
143            Self::ExpectAttributeSelectorValue => write!(f, "attribute selector value is expected"),
144            Self::ExpectComponentValue => write!(f, "component value is expected"),
145            Self::ExpectSassExpression => write!(f, "Sass expression is expected"),
146            Self::ExpectDedentOrEof => write!(f, "dedentation or end of file is expected"),
147            Self::ExpectString => write!(f, "string is expected"),
148            Self::ExpectUrl => write!(f, "URL is expected"),
149            Self::InvalidUrl => write!(f, "invalid URL"),
150            Self::UnexpectedTemplateInCss => write!(f, "template isn't allowed in CSS"),
151            Self::ExpectMediaFeatureComparison => write!(f, "media feature comparison is expected"),
152            Self::ExpectMediaAnd => write!(f, "media query `and` is expected"),
153            Self::ExpectMediaOr => write!(f, "media query `or` is expected"),
154            Self::ExpectMediaNot => write!(f, "media query `not` is expected"),
155            Self::ExpectContainerConditionAnd => write!(f, "container condition `and` is expected"),
156            Self::ExpectContainerConditionOr => write!(f, "container condition `or` is expected"),
157            Self::ExpectContainerConditionNot => write!(f, "container condition `not` is expected"),
158            Self::ExpectStyleConditionAnd => write!(f, "style condition `and` is expected"),
159            Self::ExpectStyleConditionOr => write!(f, "style condition `or` is expected"),
160            Self::ExpectStyleConditionNot => write!(f, "style condition `not` is expected"),
161            Self::ExpectStyleQuery => write!(f, "style query is expected"),
162            Self::ExpectSassKeyword(keyword) => write!(f, "Sass keyword `{keyword}` is expected"),
163            Self::InvalidAnPlusB => write!(f, "invalid An+B syntax"),
164            Self::ExpectInteger => write!(f, "an integer is expected"),
165            Self::ExpectUnsignedInteger => write!(f, "unsigned integer is expected"),
166            Self::ExpectImportantAnnotation => write!(f, "`!important` is expected"),
167            Self::ExpectSassUseNamespace => {
168                write!(f, "`*` or ident for Sass namespace is expected")
169            }
170            Self::InvalidUnicodeRange => write!(f, "invalid unicode range"),
171            Self::UnexpectedSassElseAtRule => write!(f, "Sass `@else` at-rule is disallowed here"),
172            Self::ExpectSassAtRootWithOrWithout => {
173                write!(f, "Sass identifier `with` or `without` is expected")
174            }
175            Self::ExpectNthOf => write!(f, "`of` is expected"),
176            Self::ExpectKeyframeBlock => write!(f, "keyframe block is expected"),
177            Self::MixedDelimiterKindInLessMixin => write!(
178                f,
179                "using both `;` and `,` as delimiters in the same Less mixin is disallowed"
180            ),
181            Self::ExpectLessKeyword(keyword) => write!(f, "Less keyword `{keyword}` is expected"),
182            Self::ExpectLessExtendRule => write!(f, "Less extend rule is expected"),
183            Self::ExpectScopeTo => write!(f, "keyword `to` of `@scope` at-rule is expected"),
184
185            Self::TryParseError => unreachable!(),
186            Self::CSSWideKeywordDisallowed => {
187                write!(f, "using CSS wide keyword as identifier is disallowed")
188            }
189            Self::MediaTypeKeywordDisallowed(keyword) => {
190                write!(f, "keyword `{keyword}` as media type is disallowed")
191            }
192            Self::UnknownKeyframeSelectorIdent => write!(f, "unknown keyframe selector"),
193            Self::InvalidRatioDenominator => write!(f, "ratio denominator is invalid"),
194            Self::ExpectMediaFeatureName => write!(f, "media feature name is expected"),
195            Self::ExpectDashedIdent => write!(f, "dashed identifier is expected"),
196            Self::InvalidIdSelectorName => write!(f, "invalid ID selector name"),
197            Self::ReturnOutsideFunction => write!(f, "`@return` is disallowed outside function"),
198            Self::MaxCodePointExceeded => {
199                write!(f, "unicode range end value exceeds max allowed code point")
200            }
201            Self::UnicodeRangeStartGreaterThanEnd => {
202                write!(f, "unicode range start value can't greater than end value")
203            }
204            Self::UnexpectedNthMatcher => write!(
205                f,
206                "elements matcher is allowed in `:nth-child` and `:nth-last-child` only"
207            ),
208            Self::InvalidSassFlagName(flag) => write!(f, "invalid Sass flag name `{flag}`"),
209            Self::UnexpectedSassFlag(flag) => write!(f, "Sass flag `!{flag}` is disallowed"),
210            Self::DuplicatedSassFlag(flag) => write!(f, "duplicated Sass flag `!{flag}`"),
211            Self::LessGuardOnMultipleComplexSelectors => write!(
212                f,
213                "Less guards are only allowed on a single complex selector"
214            ),
215            Self::UnexpectedLessMixinCall => write!(f, "Less mixin call is disallowed"),
216            Self::UnexpectedSemicolonInSass => write!(f, "semicolon in Sass is disallowed"),
217            Self::UnexpectedSimpleBlock => write!(f, "simple block is disallowed"),
218            Self::TopLevelDeclaration => write!(f, "declaration at top level is disallowed"),
219        }
220    }
221}
222
223pub type PResult<T> = Result<T, Error>;