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,
95 BlockInDeclarationValue,
99
100 EofInBlock,
107 BadString,
110 UnclosedParen,
112}
113
114impl Display for ErrorKind {
115 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
116 match self {
117 Self::Unexpected(expected, actual) => {
118 write!(f, "expect token `{expected}`, but found `{actual}`")
119 }
120 Self::ExpectOneOf(expected, actual) => {
121 if let [init @ .., last] = &expected[..] {
122 let joined = init
123 .iter()
124 .map(|token| format!("`{token}`"))
125 .collect::<Vec<_>>()
126 .join(", ");
127 write!(f, "expect one of {joined} or `{last}`, but found `{actual}`",)
128 } else {
129 panic!("the number of expected tokens must be at least 2")
130 }
131 }
132
133 Self::UnknownToken => write!(f, "unknown token"),
134 Self::InvalidNumber => write!(f, "invalid number"),
135 Self::InvalidEscape => write!(f, "invalid escape"),
136 Self::InvalidHash => write!(f, "invalid hash token"),
137 Self::ExpectRightBraceForLessVar => write!(f, "`}}` for Less variable is expected"),
138 Self::UnexpectedLinebreak => write!(f, "unexpected linebreak"),
139 Self::UnexpectedEof => write!(f, "unexpected end of file"),
140 Self::UnterminatedString => write!(f, "unterminated string"),
141
142 Self::ExpectRule => write!(f, "CSS rule is expected"),
143 Self::UnexpectedWhitespace => write!(f, "unexpected whitespace"),
144 Self::UnexpectedWhitespaceOrComments => write!(f, "unexpected whitespace or comments"),
145 Self::ExpectSimpleSelector => write!(f, "simple selector is expected"),
146 Self::ExpectTypeSelector => write!(f, "type selector is expected"),
147 Self::ExpectIdSelector => write!(f, "ID selector is expected"),
148 Self::ExpectWqName => write!(f, "WqName is expected"),
149 Self::ExpectAttributeSelectorMatcher => {
150 write!(f, "attribute selector matcher is expected")
151 }
152 Self::ExpectAttributeSelectorValue => write!(f, "attribute selector value is expected"),
153 Self::ExpectComponentValue => write!(f, "component value is expected"),
154 Self::ExpectSassExpression => write!(f, "Sass expression is expected"),
155 Self::ExpectDedentOrEof => write!(f, "dedentation or end of file is expected"),
156 Self::ExpectString => write!(f, "string is expected"),
157 Self::ExpectUrl => write!(f, "URL is expected"),
158 Self::InvalidUrl => write!(f, "invalid URL"),
159 Self::UnexpectedTemplateInCss => write!(f, "template isn't allowed in CSS"),
160 Self::ExpectMediaFeatureComparison => write!(f, "media feature comparison is expected"),
161 Self::ExpectMediaAnd => write!(f, "media query `and` is expected"),
162 Self::ExpectMediaOr => write!(f, "media query `or` is expected"),
163 Self::ExpectMediaNot => write!(f, "media query `not` is expected"),
164 Self::ExpectContainerConditionAnd => write!(f, "container condition `and` is expected"),
165 Self::ExpectContainerConditionOr => write!(f, "container condition `or` is expected"),
166 Self::ExpectContainerConditionNot => write!(f, "container condition `not` is expected"),
167 Self::ExpectStyleConditionAnd => write!(f, "style condition `and` is expected"),
168 Self::ExpectStyleConditionOr => write!(f, "style condition `or` is expected"),
169 Self::ExpectStyleConditionNot => write!(f, "style condition `not` is expected"),
170 Self::ExpectStyleQuery => write!(f, "style query is expected"),
171 Self::ExpectSassKeyword(keyword) => write!(f, "Sass keyword `{keyword}` is expected"),
172 Self::InvalidAnPlusB => write!(f, "invalid An+B syntax"),
173 Self::ExpectInteger => write!(f, "an integer is expected"),
174 Self::ExpectUnsignedInteger => write!(f, "unsigned integer is expected"),
175 Self::ExpectImportantAnnotation => write!(f, "`!important` is expected"),
176 Self::ExpectSassUseNamespace => {
177 write!(f, "`*` or ident for Sass namespace is expected")
178 }
179 Self::InvalidUnicodeRange => write!(f, "invalid unicode range"),
180 Self::UnexpectedSassElseAtRule => write!(f, "Sass `@else` at-rule is disallowed here"),
181 Self::ExpectSassAtRootWithOrWithout => {
182 write!(f, "Sass identifier `with` or `without` is expected")
183 }
184 Self::ExpectNthOf => write!(f, "`of` is expected"),
185 Self::ExpectKeyframeBlock => write!(f, "keyframe block is expected"),
186 Self::MixedDelimiterKindInLessMixin => write!(
187 f,
188 "using both `;` and `,` as delimiters in the same Less mixin is disallowed"
189 ),
190 Self::ExpectLessKeyword(keyword) => write!(f, "Less keyword `{keyword}` is expected"),
191 Self::ExpectLessExtendRule => write!(f, "Less extend rule is expected"),
192 Self::ExpectScopeTo => write!(f, "keyword `to` of `@scope` at-rule is expected"),
193
194 Self::TryParseError => write!(f, "syntax error"),
198 Self::CSSWideKeywordDisallowed => {
199 write!(f, "using CSS wide keyword as identifier is disallowed")
200 }
201 Self::MediaTypeKeywordDisallowed(keyword) => {
202 write!(f, "keyword `{keyword}` as media type is disallowed")
203 }
204 Self::UnknownKeyframeSelectorIdent => write!(f, "unknown keyframe selector"),
205 Self::InvalidRatioDenominator => write!(f, "ratio denominator is invalid"),
206 Self::ExpectMediaFeatureName => write!(f, "media feature name is expected"),
207 Self::ExpectDashedIdent => write!(f, "dashed identifier is expected"),
208 Self::InvalidIdSelectorName => write!(f, "invalid ID selector name"),
209 Self::ReturnOutsideFunction => write!(f, "`@return` is disallowed outside function"),
210 Self::MaxCodePointExceeded => {
211 write!(f, "unicode range end value exceeds max allowed code point")
212 }
213 Self::UnicodeRangeStartGreaterThanEnd => {
214 write!(f, "unicode range start value can't greater than end value")
215 }
216 Self::UnexpectedNthMatcher => {
217 write!(f, "elements matcher is allowed in `:nth-child` and `:nth-last-child` only")
218 }
219 Self::InvalidSassFlagName(flag) => write!(f, "invalid Sass flag name `{flag}`"),
220 Self::UnexpectedSassFlag(flag) => write!(f, "Sass flag `!{flag}` is disallowed"),
221 Self::DuplicatedSassFlag(flag) => write!(f, "duplicated Sass flag `!{flag}`"),
222 Self::LessGuardOnMultipleComplexSelectors => {
223 write!(f, "Less guards are only allowed on a single complex selector")
224 }
225 Self::UnexpectedLessMixinCall => write!(f, "Less mixin call is disallowed"),
226 Self::UnexpectedSimpleBlock => write!(f, "simple block is disallowed"),
227 Self::TopLevelDeclaration => write!(f, "declaration at top level is disallowed"),
228 Self::BlockInDeclarationValue => {
229 write!(f, "a top-level `{{}}` block is disallowed in a declaration value")
230 }
231
232 Self::EofInBlock => write!(f, "unclosed block before end of file"),
233 Self::BadString => write!(f, "unterminated string before line break"),
234 Self::UnclosedParen => write!(f, "unclosed parenthesis before end of file"),
235 }
236 }
237}
238
239pub type PResult<T> = Result<T, Error>;