Source code

Revision control

Other Tools

1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
* License, v. 2.0. If a copy of the MPL was not distributed with this
3
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5
//! Types used to report parsing errors.
6
7
#![deny(missing_docs)]
8
9
use crate::selector_parser::SelectorImpl;
10
use crate::stylesheets::UrlExtraData;
11
use cssparser::{BasicParseErrorKind, ParseErrorKind, SourceLocation, Token};
12
use selectors::SelectorList;
13
use std::fmt;
14
use style_traits::ParseError;
15
16
/// Errors that can be encountered while parsing CSS.
17
#[derive(Debug)]
18
pub enum ContextualParseError<'a> {
19
/// A property declaration was not recognized.
20
UnsupportedPropertyDeclaration(
21
&'a str,
22
ParseError<'a>,
23
Option<&'a SelectorList<SelectorImpl>>,
24
),
25
/// A font face descriptor was not recognized.
26
UnsupportedFontFaceDescriptor(&'a str, ParseError<'a>),
27
/// A font feature values descriptor was not recognized.
28
UnsupportedFontFeatureValuesDescriptor(&'a str, ParseError<'a>),
29
/// A keyframe rule was not valid.
30
InvalidKeyframeRule(&'a str, ParseError<'a>),
31
/// A font feature values rule was not valid.
32
InvalidFontFeatureValuesRule(&'a str, ParseError<'a>),
33
/// A keyframe property declaration was not recognized.
34
UnsupportedKeyframePropertyDeclaration(&'a str, ParseError<'a>),
35
/// A rule was invalid for some reason.
36
InvalidRule(&'a str, ParseError<'a>),
37
/// A rule was not recognized.
38
UnsupportedRule(&'a str, ParseError<'a>),
39
/// A viewport descriptor declaration was not recognized.
40
UnsupportedViewportDescriptorDeclaration(&'a str, ParseError<'a>),
41
/// A counter style descriptor declaration was not recognized.
42
UnsupportedCounterStyleDescriptorDeclaration(&'a str, ParseError<'a>),
43
/// A counter style rule had no symbols.
44
InvalidCounterStyleWithoutSymbols(String),
45
/// A counter style rule had less than two symbols.
46
InvalidCounterStyleNotEnoughSymbols(String),
47
/// A counter style rule did not have additive-symbols.
48
InvalidCounterStyleWithoutAdditiveSymbols,
49
/// A counter style rule had extends with symbols.
50
InvalidCounterStyleExtendsWithSymbols,
51
/// A counter style rule had extends with additive-symbols.
52
InvalidCounterStyleExtendsWithAdditiveSymbols,
53
/// A media rule was invalid for some reason.
54
InvalidMediaRule(&'a str, ParseError<'a>),
55
/// A value was not recognized.
56
UnsupportedValue(&'a str, ParseError<'a>),
57
}
58
59
impl<'a> fmt::Display for ContextualParseError<'a> {
60
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61
fn token_to_str(t: &Token, f: &mut fmt::Formatter) -> fmt::Result {
62
match *t {
63
Token::Ident(ref i) => write!(f, "identifier {}", i),
64
Token::AtKeyword(ref kw) => write!(f, "keyword @{}", kw),
65
Token::Hash(ref h) => write!(f, "hash #{}", h),
66
Token::IDHash(ref h) => write!(f, "id selector #{}", h),
67
Token::QuotedString(ref s) => write!(f, "quoted string \"{}\"", s),
68
Token::UnquotedUrl(ref u) => write!(f, "url {}", u),
69
Token::Delim(ref d) => write!(f, "delimiter {}", d),
70
Token::Number {
71
int_value: Some(i), ..
72
} => write!(f, "number {}", i),
73
Token::Number { value, .. } => write!(f, "number {}", value),
74
Token::Percentage {
75
int_value: Some(i), ..
76
} => write!(f, "percentage {}", i),
77
Token::Percentage { unit_value, .. } => {
78
write!(f, "percentage {}", unit_value * 100.)
79
},
80
Token::Dimension {
81
value, ref unit, ..
82
} => write!(f, "dimension {}{}", value, unit),
83
Token::WhiteSpace(_) => write!(f, "whitespace"),
84
Token::Comment(_) => write!(f, "comment"),
85
Token::Colon => write!(f, "colon (:)"),
86
Token::Semicolon => write!(f, "semicolon (;)"),
87
Token::Comma => write!(f, "comma (,)"),
88
Token::IncludeMatch => write!(f, "include match (~=)"),
89
Token::DashMatch => write!(f, "dash match (|=)"),
90
Token::PrefixMatch => write!(f, "prefix match (^=)"),
91
Token::SuffixMatch => write!(f, "suffix match ($=)"),
92
Token::SubstringMatch => write!(f, "substring match (*=)"),
93
Token::CDO => write!(f, "CDO (<!--)"),
94
Token::CDC => write!(f, "CDC (-->)"),
95
Token::Function(ref name) => write!(f, "function {}", name),
96
Token::ParenthesisBlock => write!(f, "parenthesis ("),
97
Token::SquareBracketBlock => write!(f, "square bracket ["),
98
Token::CurlyBracketBlock => write!(f, "curly bracket {{"),
99
Token::BadUrl(ref _u) => write!(f, "bad url parse error"),
100
Token::BadString(ref _s) => write!(f, "bad string parse error"),
101
Token::CloseParenthesis => write!(f, "unmatched close parenthesis"),
102
Token::CloseSquareBracket => write!(f, "unmatched close square bracket"),
103
Token::CloseCurlyBracket => write!(f, "unmatched close curly bracket"),
104
}
105
}
106
107
fn parse_error_to_str(err: &ParseError, f: &mut fmt::Formatter) -> fmt::Result {
108
match err.kind {
109
ParseErrorKind::Basic(BasicParseErrorKind::UnexpectedToken(ref t)) => {
110
write!(f, "found unexpected ")?;
111
token_to_str(t, f)
112
},
113
ParseErrorKind::Basic(BasicParseErrorKind::EndOfInput) => {
114
write!(f, "unexpected end of input")
115
},
116
ParseErrorKind::Basic(BasicParseErrorKind::AtRuleInvalid(ref i)) => {
117
write!(f, "@ rule invalid: {}", i)
118
},
119
ParseErrorKind::Basic(BasicParseErrorKind::AtRuleBodyInvalid) => {
120
write!(f, "@ rule invalid")
121
},
122
ParseErrorKind::Basic(BasicParseErrorKind::QualifiedRuleInvalid) => {
123
write!(f, "qualified rule invalid")
124
},
125
ParseErrorKind::Custom(ref err) => write!(f, "{:?}", err),
126
}
127
}
128
129
match *self {
130
ContextualParseError::UnsupportedPropertyDeclaration(decl, ref err, _selectors) => {
131
write!(f, "Unsupported property declaration: '{}', ", decl)?;
132
parse_error_to_str(err, f)
133
},
134
ContextualParseError::UnsupportedFontFaceDescriptor(decl, ref err) => {
135
write!(
136
f,
137
"Unsupported @font-face descriptor declaration: '{}', ",
138
decl
139
)?;
140
parse_error_to_str(err, f)
141
},
142
ContextualParseError::UnsupportedFontFeatureValuesDescriptor(decl, ref err) => {
143
write!(
144
f,
145
"Unsupported @font-feature-values descriptor declaration: '{}', ",
146
decl
147
)?;
148
parse_error_to_str(err, f)
149
},
150
ContextualParseError::InvalidKeyframeRule(rule, ref err) => {
151
write!(f, "Invalid keyframe rule: '{}', ", rule)?;
152
parse_error_to_str(err, f)
153
},
154
ContextualParseError::InvalidFontFeatureValuesRule(rule, ref err) => {
155
write!(f, "Invalid font feature value rule: '{}', ", rule)?;
156
parse_error_to_str(err, f)
157
},
158
ContextualParseError::UnsupportedKeyframePropertyDeclaration(decl, ref err) => {
159
write!(f, "Unsupported keyframe property declaration: '{}', ", decl)?;
160
parse_error_to_str(err, f)
161
},
162
ContextualParseError::InvalidRule(rule, ref err) => {
163
write!(f, "Invalid rule: '{}', ", rule)?;
164
parse_error_to_str(err, f)
165
},
166
ContextualParseError::UnsupportedRule(rule, ref err) => {
167
write!(f, "Unsupported rule: '{}', ", rule)?;
168
parse_error_to_str(err, f)
169
},
170
ContextualParseError::UnsupportedViewportDescriptorDeclaration(decl, ref err) => {
171
write!(
172
f,
173
"Unsupported @viewport descriptor declaration: '{}', ",
174
decl
175
)?;
176
parse_error_to_str(err, f)
177
},
178
ContextualParseError::UnsupportedCounterStyleDescriptorDeclaration(decl, ref err) => {
179
write!(
180
f,
181
"Unsupported @counter-style descriptor declaration: '{}', ",
182
decl
183
)?;
184
parse_error_to_str(err, f)
185
},
186
ContextualParseError::InvalidCounterStyleWithoutSymbols(ref system) => write!(
187
f,
188
"Invalid @counter-style rule: 'system: {}' without 'symbols'",
189
system
190
),
191
ContextualParseError::InvalidCounterStyleNotEnoughSymbols(ref system) => write!(
192
f,
193
"Invalid @counter-style rule: 'system: {}' less than two 'symbols'",
194
system
195
),
196
ContextualParseError::InvalidCounterStyleWithoutAdditiveSymbols => write!(
197
f,
198
"Invalid @counter-style rule: 'system: additive' without 'additive-symbols'"
199
),
200
ContextualParseError::InvalidCounterStyleExtendsWithSymbols => write!(
201
f,
202
"Invalid @counter-style rule: 'system: extends …' with 'symbols'"
203
),
204
ContextualParseError::InvalidCounterStyleExtendsWithAdditiveSymbols => write!(
205
f,
206
"Invalid @counter-style rule: 'system: extends …' with 'additive-symbols'"
207
),
208
ContextualParseError::InvalidMediaRule(media_rule, ref err) => {
209
write!(f, "Invalid media rule: {}, ", media_rule)?;
210
parse_error_to_str(err, f)
211
},
212
ContextualParseError::UnsupportedValue(_value, ref err) => parse_error_to_str(err, f),
213
}
214
}
215
}
216
217
/// A generic trait for an error reporter.
218
pub trait ParseErrorReporter {
219
/// Called when the style engine detects an error.
220
///
221
/// Returns the current input being parsed, the source location it was
222
/// reported from, and a message.
223
fn report_error(
224
&self,
225
url: &UrlExtraData,
226
location: SourceLocation,
227
error: ContextualParseError,
228
);
229
}
230
231
/// An error reporter that uses [the `log` crate](https://github.com/rust-lang-nursery/log)
232
/// at `info` level.
233
///
234
/// This logging is silent by default, and can be enabled with a `RUST_LOG=style=info`
235
/// environment variable.
237
#[cfg(feature = "servo")]
238
pub struct RustLogReporter;
239
240
#[cfg(feature = "servo")]
241
impl ParseErrorReporter for RustLogReporter {
242
fn report_error(
243
&self,
244
url: &UrlExtraData,
245
location: SourceLocation,
246
error: ContextualParseError,
247
) {
248
if log_enabled!(log::Level::Info) {
249
info!(
250
"Url:\t{}\n{}:{} {}",
251
url.as_str(),
252
location.line,
253
location.column,
254
error
255
)
256
}
257
}
258
}