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(
20 &'static str,
21 &'static str,
22 ),
23 ExpectOneOf(
24 Vec<&'static str>,
25 &'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>;