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 => unreachable!(),
189 Self::CSSWideKeywordDisallowed => {
190 write!(f, "using CSS wide keyword as identifier is disallowed")
191 }
192 Self::MediaTypeKeywordDisallowed(keyword) => {
193 write!(f, "keyword `{keyword}` as media type is disallowed")
194 }
195 Self::UnknownKeyframeSelectorIdent => write!(f, "unknown keyframe selector"),
196 Self::InvalidRatioDenominator => write!(f, "ratio denominator is invalid"),
197 Self::ExpectMediaFeatureName => write!(f, "media feature name is expected"),
198 Self::ExpectDashedIdent => write!(f, "dashed identifier is expected"),
199 Self::InvalidIdSelectorName => write!(f, "invalid ID selector name"),
200 Self::ReturnOutsideFunction => write!(f, "`@return` is disallowed outside function"),
201 Self::MaxCodePointExceeded => {
202 write!(f, "unicode range end value exceeds max allowed code point")
203 }
204 Self::UnicodeRangeStartGreaterThanEnd => {
205 write!(f, "unicode range start value can't greater than end value")
206 }
207 Self::UnexpectedNthMatcher => {
208 write!(f, "elements matcher is allowed in `:nth-child` and `:nth-last-child` only")
209 }
210 Self::InvalidSassFlagName(flag) => write!(f, "invalid Sass flag name `{flag}`"),
211 Self::UnexpectedSassFlag(flag) => write!(f, "Sass flag `!{flag}` is disallowed"),
212 Self::DuplicatedSassFlag(flag) => write!(f, "duplicated Sass flag `!{flag}`"),
213 Self::LessGuardOnMultipleComplexSelectors => {
214 write!(f, "Less guards are only allowed on a single complex selector")
215 }
216 Self::UnexpectedLessMixinCall => write!(f, "Less mixin call is disallowed"),
217 Self::UnexpectedSimpleBlock => write!(f, "simple block is disallowed"),
218 Self::TopLevelDeclaration => write!(f, "declaration at top level is disallowed"),
219
220 Self::EofInBlock => write!(f, "unclosed block before end of file"),
221 Self::BadString => write!(f, "unterminated string before line break"),
222 Self::UnclosedParen => write!(f, "unclosed parenthesis before end of file"),
223 }
224 }
225}
226
227pub type PResult<T> = Result<T, Error>;