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