mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Make some attr values case-insensitive in selectors
https://bugzilla.mozilla.org/show_bug.cgi?id=1363531
This commit is contained in:
parent
c5e37f3d2c
commit
94b4a32c18
10 changed files with 167 additions and 30 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -2457,6 +2457,8 @@ dependencies = [
|
||||||
"cssparser 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cssparser 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"precomputed-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"precomputed-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"size_of_test 0.0.1",
|
"size_of_test 0.0.1",
|
||||||
"smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
|
@ -10,6 +10,7 @@ repository = "https://github.com/servo/servo"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
keywords = ["css", "selectors"]
|
keywords = ["css", "selectors"]
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
|
build = "build.rs"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "selectors"
|
name = "selectors"
|
||||||
|
@ -25,8 +26,12 @@ bitflags = "0.7"
|
||||||
matches = "0.1"
|
matches = "0.1"
|
||||||
cssparser = "0.13.3"
|
cssparser = "0.13.3"
|
||||||
fnv = "1.0"
|
fnv = "1.0"
|
||||||
|
phf = "0.7.18"
|
||||||
precomputed-hash = "0.1"
|
precomputed-hash = "0.1"
|
||||||
smallvec = "0.3"
|
smallvec = "0.3"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
size_of_test = {path = "../size_of_test"}
|
size_of_test = {path = "../size_of_test"}
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
phf_codegen = "0.7.18"
|
||||||
|
|
|
@ -119,13 +119,29 @@ pub static SELECTOR_WHITESPACE: &'static [char] = &[' ', '\t', '\n', '\r', '\x0C
|
||||||
pub enum CaseSensitivity {
|
pub enum CaseSensitivity {
|
||||||
CaseSensitive, // Selectors spec says language-defined, but HTML says sensitive.
|
CaseSensitive, // Selectors spec says language-defined, but HTML says sensitive.
|
||||||
AsciiCaseInsensitive,
|
AsciiCaseInsensitive,
|
||||||
|
AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CaseSensitivity {
|
impl CaseSensitivity {
|
||||||
|
pub fn to_definite(self, is_html_element_in_html_document: bool) -> Self {
|
||||||
|
if let CaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument = self {
|
||||||
|
if is_html_element_in_html_document {
|
||||||
|
CaseSensitivity::AsciiCaseInsensitive
|
||||||
|
} else {
|
||||||
|
CaseSensitivity::CaseSensitive
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn eq(self, a: &[u8], b: &[u8]) -> bool {
|
pub fn eq(self, a: &[u8], b: &[u8]) -> bool {
|
||||||
match self {
|
match self {
|
||||||
CaseSensitivity::CaseSensitive => a == b,
|
CaseSensitivity::CaseSensitive => a == b,
|
||||||
CaseSensitivity::AsciiCaseInsensitive => a.eq_ignore_ascii_case(b)
|
CaseSensitivity::AsciiCaseInsensitive => a.eq_ignore_ascii_case(b),
|
||||||
|
CaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {
|
||||||
|
unreachable!("matching.rs should have called case_sensitivity.to_definite()");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,6 +168,9 @@ impl CaseSensitivity {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {
|
||||||
|
unreachable!("matching.rs should have called case_sensitivity.to_definite()");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
75
components/selectors/build.rs
Normal file
75
components/selectors/build.rs
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
extern crate phf_codegen;
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{BufWriter, Write};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let path = Path::new(&env::var("OUT_DIR").unwrap())
|
||||||
|
.join("ascii_case_insensitive_html_attributes.rs");
|
||||||
|
let mut file = BufWriter::new(File::create(&path).unwrap());
|
||||||
|
|
||||||
|
write!(&mut file, "{{ static SET: ::phf::Set<&'static str> = ",
|
||||||
|
).unwrap();
|
||||||
|
let mut set = phf_codegen::Set::new();
|
||||||
|
for name in ASCII_CASE_INSENSITIVE_HTML_ATTRIBUTES.split_whitespace() {
|
||||||
|
set.entry(name);
|
||||||
|
}
|
||||||
|
set.build(&mut file).unwrap();
|
||||||
|
write!(&mut file, "; &SET }}").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#selectors
|
||||||
|
static ASCII_CASE_INSENSITIVE_HTML_ATTRIBUTES: &'static str = r#"
|
||||||
|
accept
|
||||||
|
accept-charset
|
||||||
|
align
|
||||||
|
alink
|
||||||
|
axis
|
||||||
|
bgcolor
|
||||||
|
charset
|
||||||
|
checked
|
||||||
|
clear
|
||||||
|
codetype
|
||||||
|
color
|
||||||
|
compact
|
||||||
|
declare
|
||||||
|
defer
|
||||||
|
dir
|
||||||
|
direction
|
||||||
|
disabled
|
||||||
|
enctype
|
||||||
|
face
|
||||||
|
frame
|
||||||
|
hreflang
|
||||||
|
http-equiv
|
||||||
|
lang
|
||||||
|
language
|
||||||
|
link
|
||||||
|
media
|
||||||
|
method
|
||||||
|
multiple
|
||||||
|
nohref
|
||||||
|
noresize
|
||||||
|
noshade
|
||||||
|
nowrap
|
||||||
|
readonly
|
||||||
|
rel
|
||||||
|
rev
|
||||||
|
rules
|
||||||
|
scope
|
||||||
|
scrolling
|
||||||
|
selected
|
||||||
|
shape
|
||||||
|
target
|
||||||
|
text
|
||||||
|
type
|
||||||
|
valign
|
||||||
|
valuetype
|
||||||
|
vlink
|
||||||
|
"#;
|
|
@ -6,6 +6,7 @@
|
||||||
#[macro_use] extern crate cssparser;
|
#[macro_use] extern crate cssparser;
|
||||||
#[macro_use] extern crate matches;
|
#[macro_use] extern crate matches;
|
||||||
extern crate fnv;
|
extern crate fnv;
|
||||||
|
extern crate phf;
|
||||||
extern crate precomputed_hash;
|
extern crate precomputed_hash;
|
||||||
#[cfg(test)] #[macro_use] extern crate size_of_test;
|
#[cfg(test)] #[macro_use] extern crate size_of_test;
|
||||||
extern crate smallvec;
|
extern crate smallvec;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
use attr::{AttrSelectorOperation, NamespaceConstraint};
|
use attr::{AttrSelectorOperation, NamespaceConstraint};
|
||||||
use bloom::BloomFilter;
|
use bloom::BloomFilter;
|
||||||
use parser::{Combinator, ComplexSelector, Component, LocalName};
|
use parser::{Combinator, ComplexSelector, Component, LocalName};
|
||||||
use parser::{Selector, SelectorInner, SelectorIter, SelectorImpl};
|
use parser::{Selector, SelectorInner, SelectorIter};
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use tree::Element;
|
use tree::Element;
|
||||||
|
|
||||||
|
@ -387,7 +387,8 @@ fn matches_simple_selector<E, F>(
|
||||||
element.match_pseudo_element(pseudo, context)
|
element.match_pseudo_element(pseudo, context)
|
||||||
}
|
}
|
||||||
Component::LocalName(LocalName { ref name, ref lower_name }) => {
|
Component::LocalName(LocalName { ref name, ref lower_name }) => {
|
||||||
element.get_local_name() == select_name(element, name, lower_name).borrow()
|
let is_html = element.is_html_element_in_html_document();
|
||||||
|
element.get_local_name() == select_name(is_html, name, lower_name).borrow()
|
||||||
}
|
}
|
||||||
Component::ExplicitUniversalType |
|
Component::ExplicitUniversalType |
|
||||||
Component::ExplicitAnyNamespace => {
|
Component::ExplicitAnyNamespace => {
|
||||||
|
@ -410,9 +411,10 @@ fn matches_simple_selector<E, F>(
|
||||||
element.has_class(class)
|
element.has_class(class)
|
||||||
}
|
}
|
||||||
Component::AttributeInNoNamespaceExists { ref local_name, ref local_name_lower } => {
|
Component::AttributeInNoNamespaceExists { ref local_name, ref local_name_lower } => {
|
||||||
|
let is_html = element.is_html_element_in_html_document();
|
||||||
element.attr_matches(
|
element.attr_matches(
|
||||||
&NamespaceConstraint::Specific(&::parser::namespace_empty_string::<E::Impl>()),
|
&NamespaceConstraint::Specific(&::parser::namespace_empty_string::<E::Impl>()),
|
||||||
select_name(element, local_name, local_name_lower),
|
select_name(is_html, local_name, local_name_lower),
|
||||||
&AttrSelectorOperation::Exists
|
&AttrSelectorOperation::Exists
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -427,12 +429,13 @@ fn matches_simple_selector<E, F>(
|
||||||
if never_matches {
|
if never_matches {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
|
let is_html = element.is_html_element_in_html_document();
|
||||||
element.attr_matches(
|
element.attr_matches(
|
||||||
&NamespaceConstraint::Specific(&::parser::namespace_empty_string::<E::Impl>()),
|
&NamespaceConstraint::Specific(&::parser::namespace_empty_string::<E::Impl>()),
|
||||||
select_name(element, local_name, local_name_lower),
|
select_name(is_html, local_name, local_name_lower),
|
||||||
&AttrSelectorOperation::WithValue {
|
&AttrSelectorOperation::WithValue {
|
||||||
operator: operator,
|
operator: operator,
|
||||||
case_sensitivity: case_sensitivity,
|
case_sensitivity: case_sensitivity.to_definite(is_html),
|
||||||
expected_value: value,
|
expected_value: value,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -442,9 +445,10 @@ fn matches_simple_selector<E, F>(
|
||||||
if attr_sel.never_matches {
|
if attr_sel.never_matches {
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
|
let is_html = element.is_html_element_in_html_document();
|
||||||
element.attr_matches(
|
element.attr_matches(
|
||||||
&attr_sel.namespace(),
|
&attr_sel.namespace(),
|
||||||
select_name(element, &attr_sel.local_name, &attr_sel.local_name_lower),
|
select_name(is_html, &attr_sel.local_name, &attr_sel.local_name_lower),
|
||||||
&match attr_sel.operation {
|
&match attr_sel.operation {
|
||||||
AttrSelectorOperation::Exists => AttrSelectorOperation::Exists,
|
AttrSelectorOperation::Exists => AttrSelectorOperation::Exists,
|
||||||
AttrSelectorOperation::WithValue {
|
AttrSelectorOperation::WithValue {
|
||||||
|
@ -454,7 +458,7 @@ fn matches_simple_selector<E, F>(
|
||||||
} => {
|
} => {
|
||||||
AttrSelectorOperation::WithValue {
|
AttrSelectorOperation::WithValue {
|
||||||
operator: operator,
|
operator: operator,
|
||||||
case_sensitivity: case_sensitivity,
|
case_sensitivity: case_sensitivity.to_definite(is_html),
|
||||||
expected_value: expected_value,
|
expected_value: expected_value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -512,11 +516,8 @@ fn matches_simple_selector<E, F>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_name<'a, E>(element: &E, local_name: &'a <E::Impl as SelectorImpl>::LocalName,
|
fn select_name<'a, T>(is_html: bool, local_name: &'a T, local_name_lower: &'a T) -> &'a T {
|
||||||
local_name_lower: &'a <E::Impl as SelectorImpl>::LocalName)
|
if is_html {
|
||||||
-> &'a <E::Impl as SelectorImpl>::LocalName
|
|
||||||
where E: Element {
|
|
||||||
if element.is_html_element_in_html_document() {
|
|
||||||
local_name_lower
|
local_name_lower
|
||||||
} else {
|
} else {
|
||||||
local_name
|
local_name
|
||||||
|
|
|
@ -33,6 +33,16 @@ pub trait PseudoElement : Sized + ToCss {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn to_ascii_lowercase(s: &str) -> Cow<str> {
|
||||||
|
if let Some(first_uppercase) = s.bytes().position(|byte| byte >= b'A' && byte <= b'Z') {
|
||||||
|
let mut string = s.to_owned();
|
||||||
|
string[first_uppercase..].make_ascii_lowercase();
|
||||||
|
string.into()
|
||||||
|
} else {
|
||||||
|
s.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! with_all_bounds {
|
macro_rules! with_all_bounds {
|
||||||
(
|
(
|
||||||
[ $( $InSelector: tt )* ]
|
[ $( $InSelector: tt )* ]
|
||||||
|
@ -46,16 +56,6 @@ macro_rules! with_all_bounds {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_ascii_lowercase<T>(s: &str) -> T where T: $($FromStr)* {
|
|
||||||
if let Some(first_uppercase) = s.bytes().position(|byte| byte >= b'A' && byte <= b'Z') {
|
|
||||||
let mut string = s.to_owned();
|
|
||||||
string[first_uppercase..].make_ascii_lowercase();
|
|
||||||
T::from(string)
|
|
||||||
} else {
|
|
||||||
T::from(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This trait allows to define the parser implementation in regards
|
/// This trait allows to define the parser implementation in regards
|
||||||
/// of pseudo-classes/elements
|
/// of pseudo-classes/elements
|
||||||
///
|
///
|
||||||
|
@ -735,7 +735,8 @@ impl<Impl: SelectorImpl> ToCss for Component<Impl> {
|
||||||
write!(CssStringWriter::new(dest), "{}", value)?;
|
write!(CssStringWriter::new(dest), "{}", value)?;
|
||||||
dest.write_char('"')?;
|
dest.write_char('"')?;
|
||||||
match case_sensitivity {
|
match case_sensitivity {
|
||||||
CaseSensitivity::CaseSensitive => {},
|
CaseSensitivity::CaseSensitive |
|
||||||
|
CaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {},
|
||||||
CaseSensitivity::AsciiCaseInsensitive => dest.write_str(" i")?,
|
CaseSensitivity::AsciiCaseInsensitive => dest.write_str(" i")?,
|
||||||
}
|
}
|
||||||
dest.write_char(']')
|
dest.write_char(']')
|
||||||
|
@ -790,7 +791,8 @@ impl<Impl: SelectorImpl> ToCss for AttrSelectorWithNamespace<Impl> {
|
||||||
write!(CssStringWriter::new(dest), "{}", expected_value)?;
|
write!(CssStringWriter::new(dest), "{}", expected_value)?;
|
||||||
dest.write_char('"')?;
|
dest.write_char('"')?;
|
||||||
match case_sensitivity {
|
match case_sensitivity {
|
||||||
CaseSensitivity::CaseSensitive => {},
|
CaseSensitivity::CaseSensitive |
|
||||||
|
CaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {},
|
||||||
CaseSensitivity::AsciiCaseInsensitive => dest.write_str(" i")?,
|
CaseSensitivity::AsciiCaseInsensitive => dest.write_str(" i")?,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1078,7 +1080,7 @@ fn parse_type_selector<P, Impl>(parser: &P, input: &mut CssParser, sequence: &mu
|
||||||
match local_name {
|
match local_name {
|
||||||
Some(name) => {
|
Some(name) => {
|
||||||
sequence.push(Component::LocalName(LocalName {
|
sequence.push(Component::LocalName(LocalName {
|
||||||
lower_name: from_ascii_lowercase(&name),
|
lower_name: from_cow_str(to_ascii_lowercase(&name)),
|
||||||
name: from_cow_str(name),
|
name: from_cow_str(name),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -1190,13 +1192,11 @@ fn parse_attribute_selector<P, Impl>(parser: &P, input: &mut CssParser)
|
||||||
{
|
{
|
||||||
let namespace;
|
let namespace;
|
||||||
let local_name;
|
let local_name;
|
||||||
let local_name_lower;
|
|
||||||
match parse_qualified_name(parser, input, /* in_attr_selector = */ true)? {
|
match parse_qualified_name(parser, input, /* in_attr_selector = */ true)? {
|
||||||
None => return Err(()),
|
None => return Err(()),
|
||||||
Some((_, None)) => unreachable!(),
|
Some((_, None)) => unreachable!(),
|
||||||
Some((ns, Some(ln))) => {
|
Some((ns, Some(ln))) => {
|
||||||
local_name_lower = from_ascii_lowercase(&ln);
|
local_name = ln;
|
||||||
local_name = from_cow_str(ln);
|
|
||||||
namespace = match ns {
|
namespace = match ns {
|
||||||
QNamePrefix::ImplicitNoNamespace |
|
QNamePrefix::ImplicitNoNamespace |
|
||||||
QNamePrefix::ExplicitNoNamespace => {
|
QNamePrefix::ExplicitNoNamespace => {
|
||||||
|
@ -1222,6 +1222,8 @@ fn parse_attribute_selector<P, Impl>(parser: &P, input: &mut CssParser)
|
||||||
match input.next() {
|
match input.next() {
|
||||||
// [foo]
|
// [foo]
|
||||||
Err(()) => {
|
Err(()) => {
|
||||||
|
let local_name_lower = from_cow_str(to_ascii_lowercase(&local_name));
|
||||||
|
let local_name = from_cow_str(local_name);
|
||||||
if let Some(namespace) = namespace {
|
if let Some(namespace) = namespace {
|
||||||
return Ok(Component::AttributeOther(Box::new(AttrSelectorWithNamespace {
|
return Ok(Component::AttributeOther(Box::new(AttrSelectorWithNamespace {
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
|
@ -1277,8 +1279,22 @@ fn parse_attribute_selector<P, Impl>(parser: &P, input: &mut CssParser)
|
||||||
_ => return Err(())
|
_ => return Err(())
|
||||||
}
|
}
|
||||||
|
|
||||||
let case_sensitivity = parse_attribute_flags(input)?;
|
let mut case_sensitivity = parse_attribute_flags(input)?;
|
||||||
|
|
||||||
let value = from_cow_str(value);
|
let value = from_cow_str(value);
|
||||||
|
let local_name_lower;
|
||||||
|
{
|
||||||
|
let local_name_lower_cow = to_ascii_lowercase(&local_name);
|
||||||
|
if let CaseSensitivity::CaseSensitive = case_sensitivity {
|
||||||
|
if include!(concat!(env!("OUT_DIR"), "/ascii_case_insensitive_html_attributes.rs"))
|
||||||
|
.contains(&*local_name_lower_cow)
|
||||||
|
{
|
||||||
|
case_sensitivity = CaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument
|
||||||
|
}
|
||||||
|
}
|
||||||
|
local_name_lower = from_cow_str(local_name_lower_cow);
|
||||||
|
}
|
||||||
|
let local_name = from_cow_str(local_name);
|
||||||
if let Some(namespace) = namespace {
|
if let Some(namespace) = namespace {
|
||||||
Ok(Component::AttributeOther(Box::new(AttrSelectorWithNamespace {
|
Ok(Component::AttributeOther(Box::new(AttrSelectorWithNamespace {
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
|
|
|
@ -72,6 +72,10 @@ impl GeckoElementSnapshot {
|
||||||
let ignore_case = match case_sensitivity {
|
let ignore_case = match case_sensitivity {
|
||||||
CaseSensitivity::CaseSensitive => false,
|
CaseSensitivity::CaseSensitive => false,
|
||||||
CaseSensitivity::AsciiCaseInsensitive => true,
|
CaseSensitivity::AsciiCaseInsensitive => true,
|
||||||
|
CaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {
|
||||||
|
unreachable!("selectors/matching.rs should have \
|
||||||
|
called case_sensitivity.to_definite()");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
// FIXME: case sensitivity for operators other than Equal
|
// FIXME: case sensitivity for operators other than Equal
|
||||||
match operator {
|
match operator {
|
||||||
|
|
|
@ -1162,6 +1162,10 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
||||||
let ignore_case = match case_sensitivity {
|
let ignore_case = match case_sensitivity {
|
||||||
CaseSensitivity::CaseSensitive => false,
|
CaseSensitivity::CaseSensitive => false,
|
||||||
CaseSensitivity::AsciiCaseInsensitive => true,
|
CaseSensitivity::AsciiCaseInsensitive => true,
|
||||||
|
CaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {
|
||||||
|
unreachable!("selectors/matching.rs should have \
|
||||||
|
called case_sensitivity.to_definite()");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
// FIXME: case sensitivity for operators other than Equal
|
// FIXME: case sensitivity for operators other than Equal
|
||||||
match operator {
|
match operator {
|
||||||
|
|
|
@ -447,6 +447,7 @@ def check_rust(file_name, lines):
|
||||||
|
|
||||||
prev_use = None
|
prev_use = None
|
||||||
prev_open_brace = False
|
prev_open_brace = False
|
||||||
|
multi_line_string = False
|
||||||
current_indent = 0
|
current_indent = 0
|
||||||
prev_crate = {}
|
prev_crate = {}
|
||||||
prev_mod = {}
|
prev_mod = {}
|
||||||
|
@ -464,6 +465,15 @@ def check_rust(file_name, lines):
|
||||||
prev_indent = indent
|
prev_indent = indent
|
||||||
indent = len(original_line) - len(line)
|
indent = len(original_line) - len(line)
|
||||||
|
|
||||||
|
# Hack for components/selectors/build.rs
|
||||||
|
if multi_line_string:
|
||||||
|
if line.startswith('"#'):
|
||||||
|
multi_line_string = False
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
if line.endswith('r#"'):
|
||||||
|
multi_line_string = True
|
||||||
|
|
||||||
is_attribute = re.search(r"#\[.*\]", line)
|
is_attribute = re.search(r"#\[.*\]", line)
|
||||||
is_comment = re.search(r"^//|^/\*|^\*", line)
|
is_comment = re.search(r"^//|^/\*|^\*", line)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue