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