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 /// A never-matching `:host` selector was found. 58 NeverMatchingHostSelector(String), 59 } 60 61 impl<'a> fmt::Display for ContextualParseError<'a> { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result62 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 63 fn token_to_str(t: &Token, f: &mut fmt::Formatter) -> fmt::Result { 64 match *t { 65 Token::Ident(ref i) => write!(f, "identifier {}", i), 66 Token::AtKeyword(ref kw) => write!(f, "keyword @{}", kw), 67 Token::Hash(ref h) => write!(f, "hash #{}", h), 68 Token::IDHash(ref h) => write!(f, "id selector #{}", h), 69 Token::QuotedString(ref s) => write!(f, "quoted string \"{}\"", s), 70 Token::UnquotedUrl(ref u) => write!(f, "url {}", u), 71 Token::Delim(ref d) => write!(f, "delimiter {}", d), 72 Token::Number { 73 int_value: Some(i), .. 74 } => write!(f, "number {}", i), 75 Token::Number { value, .. } => write!(f, "number {}", value), 76 Token::Percentage { 77 int_value: Some(i), .. 78 } => write!(f, "percentage {}", i), 79 Token::Percentage { unit_value, .. } => { 80 write!(f, "percentage {}", unit_value * 100.) 81 }, 82 Token::Dimension { 83 value, ref unit, .. 84 } => write!(f, "dimension {}{}", value, unit), 85 Token::WhiteSpace(_) => write!(f, "whitespace"), 86 Token::Comment(_) => write!(f, "comment"), 87 Token::Colon => write!(f, "colon (:)"), 88 Token::Semicolon => write!(f, "semicolon (;)"), 89 Token::Comma => write!(f, "comma (,)"), 90 Token::IncludeMatch => write!(f, "include match (~=)"), 91 Token::DashMatch => write!(f, "dash match (|=)"), 92 Token::PrefixMatch => write!(f, "prefix match (^=)"), 93 Token::SuffixMatch => write!(f, "suffix match ($=)"), 94 Token::SubstringMatch => write!(f, "substring match (*=)"), 95 Token::CDO => write!(f, "CDO (<!--)"), 96 Token::CDC => write!(f, "CDC (-->)"), 97 Token::Function(ref name) => write!(f, "function {}", name), 98 Token::ParenthesisBlock => write!(f, "parenthesis ("), 99 Token::SquareBracketBlock => write!(f, "square bracket ["), 100 Token::CurlyBracketBlock => write!(f, "curly bracket {{"), 101 Token::BadUrl(ref _u) => write!(f, "bad url parse error"), 102 Token::BadString(ref _s) => write!(f, "bad string parse error"), 103 Token::CloseParenthesis => write!(f, "unmatched close parenthesis"), 104 Token::CloseSquareBracket => write!(f, "unmatched close square bracket"), 105 Token::CloseCurlyBracket => write!(f, "unmatched close curly bracket"), 106 } 107 } 108 109 fn parse_error_to_str(err: &ParseError, f: &mut fmt::Formatter) -> fmt::Result { 110 match err.kind { 111 ParseErrorKind::Basic(BasicParseErrorKind::UnexpectedToken(ref t)) => { 112 write!(f, "found unexpected ")?; 113 token_to_str(t, f) 114 }, 115 ParseErrorKind::Basic(BasicParseErrorKind::EndOfInput) => { 116 write!(f, "unexpected end of input") 117 }, 118 ParseErrorKind::Basic(BasicParseErrorKind::AtRuleInvalid(ref i)) => { 119 write!(f, "@ rule invalid: {}", i) 120 }, 121 ParseErrorKind::Basic(BasicParseErrorKind::AtRuleBodyInvalid) => { 122 write!(f, "@ rule invalid") 123 }, 124 ParseErrorKind::Basic(BasicParseErrorKind::QualifiedRuleInvalid) => { 125 write!(f, "qualified rule invalid") 126 }, 127 ParseErrorKind::Custom(ref err) => write!(f, "{:?}", err), 128 } 129 } 130 131 match *self { 132 ContextualParseError::UnsupportedPropertyDeclaration(decl, ref err, _selectors) => { 133 write!(f, "Unsupported property declaration: '{}', ", decl)?; 134 parse_error_to_str(err, f) 135 }, 136 ContextualParseError::UnsupportedFontFaceDescriptor(decl, ref err) => { 137 write!( 138 f, 139 "Unsupported @font-face descriptor declaration: '{}', ", 140 decl 141 )?; 142 parse_error_to_str(err, f) 143 }, 144 ContextualParseError::UnsupportedFontFeatureValuesDescriptor(decl, ref err) => { 145 write!( 146 f, 147 "Unsupported @font-feature-values descriptor declaration: '{}', ", 148 decl 149 )?; 150 parse_error_to_str(err, f) 151 }, 152 ContextualParseError::InvalidKeyframeRule(rule, ref err) => { 153 write!(f, "Invalid keyframe rule: '{}', ", rule)?; 154 parse_error_to_str(err, f) 155 }, 156 ContextualParseError::InvalidFontFeatureValuesRule(rule, ref err) => { 157 write!(f, "Invalid font feature value rule: '{}', ", rule)?; 158 parse_error_to_str(err, f) 159 }, 160 ContextualParseError::UnsupportedKeyframePropertyDeclaration(decl, ref err) => { 161 write!(f, "Unsupported keyframe property declaration: '{}', ", decl)?; 162 parse_error_to_str(err, f) 163 }, 164 ContextualParseError::InvalidRule(rule, ref err) => { 165 write!(f, "Invalid rule: '{}', ", rule)?; 166 parse_error_to_str(err, f) 167 }, 168 ContextualParseError::UnsupportedRule(rule, ref err) => { 169 write!(f, "Unsupported rule: '{}', ", rule)?; 170 parse_error_to_str(err, f) 171 }, 172 ContextualParseError::UnsupportedViewportDescriptorDeclaration(decl, ref err) => { 173 write!( 174 f, 175 "Unsupported @viewport descriptor declaration: '{}', ", 176 decl 177 )?; 178 parse_error_to_str(err, f) 179 }, 180 ContextualParseError::UnsupportedCounterStyleDescriptorDeclaration(decl, ref err) => { 181 write!( 182 f, 183 "Unsupported @counter-style descriptor declaration: '{}', ", 184 decl 185 )?; 186 parse_error_to_str(err, f) 187 }, 188 ContextualParseError::InvalidCounterStyleWithoutSymbols(ref system) => write!( 189 f, 190 "Invalid @counter-style rule: 'system: {}' without 'symbols'", 191 system 192 ), 193 ContextualParseError::InvalidCounterStyleNotEnoughSymbols(ref system) => write!( 194 f, 195 "Invalid @counter-style rule: 'system: {}' less than two 'symbols'", 196 system 197 ), 198 ContextualParseError::InvalidCounterStyleWithoutAdditiveSymbols => write!( 199 f, 200 "Invalid @counter-style rule: 'system: additive' without 'additive-symbols'" 201 ), 202 ContextualParseError::InvalidCounterStyleExtendsWithSymbols => write!( 203 f, 204 "Invalid @counter-style rule: 'system: extends …' with 'symbols'" 205 ), 206 ContextualParseError::InvalidCounterStyleExtendsWithAdditiveSymbols => write!( 207 f, 208 "Invalid @counter-style rule: 'system: extends …' with 'additive-symbols'" 209 ), 210 ContextualParseError::InvalidMediaRule(media_rule, ref err) => { 211 write!(f, "Invalid media rule: {}, ", media_rule)?; 212 parse_error_to_str(err, f) 213 }, 214 ContextualParseError::UnsupportedValue(_value, ref err) => parse_error_to_str(err, f), 215 ContextualParseError::NeverMatchingHostSelector(ref selector) => { 216 write!(f, ":host selector is not featureless: {}", selector) 217 }, 218 } 219 } 220 } 221 222 /// A generic trait for an error reporter. 223 pub trait ParseErrorReporter { 224 /// Called when the style engine detects an error. 225 /// 226 /// Returns the current input being parsed, the source location it was 227 /// reported from, and a message. report_error( &self, url: &UrlExtraData, location: SourceLocation, error: ContextualParseError, )228 fn report_error( 229 &self, 230 url: &UrlExtraData, 231 location: SourceLocation, 232 error: ContextualParseError, 233 ); 234 } 235 236 /// An error reporter that uses [the `log` crate](https://github.com/rust-lang-nursery/log) 237 /// at `info` level. 238 /// 239 /// This logging is silent by default, and can be enabled with a `RUST_LOG=style=info` 240 /// environment variable. 241 /// (See [`env_logger`](https://rust-lang-nursery.github.io/log/env_logger/).) 242 #[cfg(feature = "servo")] 243 pub struct RustLogReporter; 244 245 #[cfg(feature = "servo")] 246 impl ParseErrorReporter for RustLogReporter { report_error( &self, url: &UrlExtraData, location: SourceLocation, error: ContextualParseError, )247 fn report_error( 248 &self, 249 url: &UrlExtraData, 250 location: SourceLocation, 251 error: ContextualParseError, 252 ) { 253 if log_enabled!(log::Level::Info) { 254 info!( 255 "Url:\t{}\n{}:{} {}", 256 url.as_str(), 257 location.line, 258 location.column, 259 error 260 ) 261 } 262 } 263 } 264