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