diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-05-15 05:28:50 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-15 05:28:50 -0500 |
commit | 5cd8265f9a279e1cebe84218e691e7f80a541fb9 (patch) | |
tree | 4cf4e29f89ce3c5c5dc1f5095602bb15ee15ec2e /components | |
parent | 94e977efebb93ef411222edc219bc9f30430a3f9 (diff) | |
parent | bc156cfe1c2f52a6f609f1ad1a28dcbfd36a9d4e (diff) | |
download | servo-5cd8265f9a279e1cebe84218e691e7f80a541fb9.tar.gz servo-5cd8265f9a279e1cebe84218e691e7f80a541fb9.zip |
Auto merge of #16835 - ferjm:bug1350175.line.column.css.rules, r=upsuper,SimonSapin
Stylo: Bug 1350175 - Support getting line / column number of CSS rules
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
Bugzilla bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1350175
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/16835)
<!-- Reviewable:end -->
Diffstat (limited to 'components')
-rw-r--r-- | components/style/encoding_support.rs | 3 | ||||
-rw-r--r-- | components/style/font_face.rs | 11 | ||||
-rw-r--r-- | components/style/gecko/generated/bindings.rs | 28 | ||||
-rw-r--r-- | components/style/gecko/rules.rs | 4 | ||||
-rw-r--r-- | components/style/stylesheets.rs | 85 |
5 files changed, 93 insertions, 38 deletions
diff --git a/components/style/encoding_support.rs b/components/style/encoding_support.rs index 92620378b30..af37e20889a 100644 --- a/components/style/encoding_support.rs +++ b/components/style/encoding_support.rs @@ -88,6 +88,7 @@ impl Stylesheet { &string, url_data, stylesheet_loader, - error_reporter) + error_reporter, + 0) } } diff --git a/components/style/font_face.rs b/components/style/font_face.rs index 94dcc61212d..0bd6640488e 100644 --- a/components/style/font_face.rs +++ b/components/style/font_face.rs @@ -12,6 +12,7 @@ use computed_values::{font_style, font_weight, font_stretch}; use computed_values::font_family::FamilyName; use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser}; +use cssparser::SourceLocation; #[cfg(feature = "gecko")] use gecko_bindings::structs::CSSFontFaceDescriptors; #[cfg(feature = "gecko")] use cssparser::UnicodeRange; use parser::{ParserContext, log_css_error, Parse}; @@ -74,8 +75,10 @@ impl ToCss for UrlSource { /// Parse the block inside a `@font-face` rule. /// /// Note that the prelude parsing code lives in the `stylesheets` module. -pub fn parse_font_face_block(context: &ParserContext, input: &mut Parser) -> FontFaceRuleData { +pub fn parse_font_face_block(context: &ParserContext, input: &mut Parser, location: SourceLocation) + -> FontFaceRuleData { let mut rule = FontFaceRuleData::empty(); + rule.source_location = location; { let parser = FontFaceRuleParser { context: context, @@ -186,6 +189,8 @@ macro_rules! font_face_descriptors_common { #[$doc] pub $ident: Option<$ty>, )* + /// Line and column of the @font-face rule source code. + pub source_location: SourceLocation, } impl FontFaceRuleData { @@ -194,6 +199,10 @@ macro_rules! font_face_descriptors_common { $( $ident: None, )* + source_location: SourceLocation { + line: 0, + column: 0, + }, } } diff --git a/components/style/gecko/generated/bindings.rs b/components/style/gecko/generated/bindings.rs index bf386498df9..00e623b931f 100644 --- a/components/style/gecko/generated/bindings.rs +++ b/components/style/gecko/generated/bindings.rs @@ -1255,7 +1255,8 @@ extern "C" { -> *const ::std::os::raw::c_char; } extern "C" { - pub fn Gecko_CSSFontFaceRule_Create() -> *mut nsCSSFontFaceRule; + pub fn Gecko_CSSFontFaceRule_Create(line: u32, column: u32) + -> *mut nsCSSFontFaceRule; } extern "C" { pub fn Gecko_CSSFontFaceRule_GetCssText(rule: *const nsCSSFontFaceRule, @@ -1621,7 +1622,8 @@ extern "C" { media_list: *const RawServoMediaList, extra_data: - *mut RawGeckoURLExtraData) + *mut RawGeckoURLExtraData, + line_number_offset: u32) -> RawServoStyleSheetStrong; } extern "C" { @@ -1636,7 +1638,8 @@ extern "C" { *mut ServoStyleSheet, data: *const nsACString, extra_data: - *mut RawGeckoURLExtraData); + *mut RawGeckoURLExtraData, + line_number_offset: u32); } extern "C" { pub fn Servo_StyleSheet_HasRules(sheet: RawServoStyleSheetBorrowed) @@ -1726,7 +1729,8 @@ extern "C" { } extern "C" { pub fn Servo_CssRules_GetStyleRuleAt(rules: ServoCssRulesBorrowed, - index: u32) + index: u32, line: *mut u32, + column: *mut u32) -> RawServoStyleRuleStrong; } extern "C" { @@ -1739,7 +1743,8 @@ extern "C" { } extern "C" { pub fn Servo_CssRules_GetMediaRuleAt(rules: ServoCssRulesBorrowed, - index: u32) + index: u32, line: *mut u32, + column: *mut u32) -> RawServoMediaRuleStrong; } extern "C" { @@ -1756,7 +1761,8 @@ extern "C" { } extern "C" { pub fn Servo_CssRules_GetNamespaceRuleAt(rules: ServoCssRulesBorrowed, - index: u32) + index: u32, line: *mut u32, + column: *mut u32) -> RawServoNamespaceRuleStrong; } extern "C" { @@ -1769,7 +1775,9 @@ extern "C" { } extern "C" { pub fn Servo_CssRules_GetPageRuleAt(rules: ServoCssRulesBorrowed, - index: u32) -> RawServoPageRuleStrong; + index: u32, line: *mut u32, + column: *mut u32) + -> RawServoPageRuleStrong; } extern "C" { pub fn Servo_PageRule_Debug(rule: RawServoPageRuleBorrowed, @@ -1781,7 +1789,8 @@ extern "C" { } extern "C" { pub fn Servo_CssRules_GetSupportsRuleAt(rules: ServoCssRulesBorrowed, - index: u32) + index: u32, line: *mut u32, + column: *mut u32) -> RawServoSupportsRuleStrong; } extern "C" { @@ -1798,7 +1807,8 @@ extern "C" { } extern "C" { pub fn Servo_CssRules_GetDocumentRuleAt(rules: ServoCssRulesBorrowed, - index: u32) + index: u32, line: *mut u32, + column: *mut u32) -> RawServoDocumentRuleStrong; } extern "C" { diff --git a/components/style/gecko/rules.rs b/components/style/gecko/rules.rs index d2d78de238a..7af5fc599b7 100644 --- a/components/style/gecko/rules.rs +++ b/components/style/gecko/rules.rs @@ -117,7 +117,9 @@ impl ToNsCssValue for Vec<UnicodeRange> { impl From<FontFaceRuleData> for FontFaceRule { fn from(data: FontFaceRuleData) -> FontFaceRule { let mut result = unsafe { - UniqueRefPtr::from_addrefed(bindings::Gecko_CSSFontFaceRule_Create()) + UniqueRefPtr::from_addrefed(bindings::Gecko_CSSFontFaceRule_Create( + data.source_location.line as u32, data.source_location.column as u32 + )) }; data.set_descriptors(&mut result.mDecl.mDescriptors); result.get() diff --git a/components/style/stylesheets.rs b/components/style/stylesheets.rs index 84b5753fb9b..98c13948121 100644 --- a/components/style/stylesheets.rs +++ b/components/style/stylesheets.rs @@ -10,7 +10,7 @@ use {Atom, Prefix, Namespace}; use context::QuirksMode; use counter_style::{CounterStyleRule, parse_counter_style_name, parse_counter_style_body}; use cssparser::{AtRuleParser, Parser, QualifiedRuleParser}; -use cssparser::{AtRuleType, RuleListParser, parse_one_rule}; +use cssparser::{AtRuleType, RuleListParser, parse_one_rule, SourceLocation}; use cssparser::ToCss as ParserToCss; use document_condition::DocumentCondition; use error_reporting::{ParseErrorReporter, NullReporter}; @@ -489,12 +489,22 @@ impl ToCssWithGuard for CssRule { } } +/// Calculates the location of a rule's source given an offset. +fn get_location_with_offset(location: SourceLocation, offset: u64) + -> SourceLocation { + SourceLocation { + line: location.line + offset as usize - 1, + column: location.column, + } +} + #[derive(Debug, PartialEq)] #[allow(missing_docs)] pub struct NamespaceRule { /// `None` for the default Namespace pub prefix: Option<Prefix>, pub url: Namespace, + pub source_location: SourceLocation, } impl ToCssWithGuard for NamespaceRule { @@ -581,6 +591,7 @@ impl ToCssWithGuard for KeyframesRule { pub struct MediaRule { pub media_queries: Arc<Locked<MediaList>>, pub rules: Arc<Locked<CssRules>>, + pub source_location: SourceLocation, } impl ToCssWithGuard for MediaRule { @@ -609,6 +620,8 @@ pub struct SupportsRule { pub rules: Arc<Locked<CssRules>>, /// The result of evaluating the condition pub enabled: bool, + /// The line and column of the rule's source code. + pub source_location: SourceLocation, } impl ToCssWithGuard for SupportsRule { @@ -630,15 +643,19 @@ impl ToCssWithGuard for SupportsRule { /// /// [page]: https://drafts.csswg.org/css2/page.html#page-box /// [page-selectors]: https://drafts.csswg.org/css2/page.html#page-selectors +#[allow(missing_docs)] #[derive(Debug)] -pub struct PageRule(pub Arc<Locked<PropertyDeclarationBlock>>); +pub struct PageRule { + pub block: Arc<Locked<PropertyDeclarationBlock>>, + pub source_location: SourceLocation, +} impl ToCssWithGuard for PageRule { // Serialization of PageRule is not specced, adapted from steps for StyleRule. fn to_css<W>(&self, guard: &SharedRwLockReadGuard, dest: &mut W) -> fmt::Result where W: fmt::Write { dest.write_str("@page { ")?; - let declaration_block = self.0.read_with(guard); + let declaration_block = self.block.read_with(guard); declaration_block.to_css(dest)?; if declaration_block.declarations().len() > 0 { write!(dest, " ")?; @@ -652,6 +669,7 @@ impl ToCssWithGuard for PageRule { pub struct StyleRule { pub selectors: SelectorList<SelectorImpl>, pub block: Arc<Locked<PropertyDeclarationBlock>>, + pub source_location: SourceLocation, } impl ToCssWithGuard for StyleRule { @@ -686,6 +704,8 @@ pub struct DocumentRule { pub condition: DocumentCondition, /// Child rules pub rules: Arc<Locked<CssRules>>, + /// The line and column of the rule's source code. + pub source_location: SourceLocation, } impl ToCssWithGuard for DocumentRule { @@ -708,15 +728,15 @@ impl Stylesheet { css: &str, url_data: &UrlExtraData, stylesheet_loader: Option<&StylesheetLoader>, - error_reporter: &ParseErrorReporter) { + error_reporter: &ParseErrorReporter, + line_number_offset: u64) { let mut namespaces = Namespaces::default(); // FIXME: we really should update existing.url_data with the given url_data, // otherwise newly inserted rule may not have the right base url. let (rules, dirty_on_viewport_size_change) = Stylesheet::parse_rules( css, url_data, existing.origin, &mut namespaces, &existing.shared_lock, stylesheet_loader, error_reporter, - existing.quirks_mode, 0u64); - + existing.quirks_mode, line_number_offset); *existing.namespaces.write() = namespaces; existing.dirty_on_viewport_size_change .store(dirty_on_viewport_size_change, Ordering::Release); @@ -996,21 +1016,21 @@ pub enum VendorPrefix { enum AtRulePrelude { /// A @font-face rule prelude. - FontFace, + FontFace(SourceLocation), /// A @counter-style rule prelude, with its counter style name. CounterStyle(CustomIdent), /// A @media rule prelude, with its media queries. - Media(Arc<Locked<MediaList>>), + Media(Arc<Locked<MediaList>>, SourceLocation), /// An @supports rule, with its conditional - Supports(SupportsCondition), + Supports(SupportsCondition, SourceLocation), /// A @viewport rule prelude. Viewport, /// A @keyframes rule, with its animation name and vendor prefix if exists. Keyframes(KeyframesName, Option<VendorPrefix>), /// A @page rule prelude. - Page, + Page(SourceLocation), /// A @document rule, with its conditional. - Document(DocumentCondition), + Document(DocumentCondition, SourceLocation), } @@ -1066,6 +1086,9 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> { if self.state.get() <= State::Namespaces { self.state.set(State::Namespaces); + let location = get_location_with_offset(input.current_source_location(), + self.context.line_number_offset); + let prefix_result = input.try(|input| input.expect_ident()); let url = Namespace::from(try!(input.expect_url_or_string())); @@ -1082,6 +1105,7 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> { self.shared_lock.wrap(NamespaceRule { prefix: opt_prefix, url: url, + source_location: location, }) )))) } else { @@ -1176,18 +1200,20 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> { fn parse_prelude(&mut self, name: &str, input: &mut Parser) -> Result<AtRuleType<AtRulePrelude, CssRule>, ()> { + let location = get_location_with_offset(input.current_source_location(), + self.context.line_number_offset); match_ignore_ascii_case! { name, "media" => { let media_queries = parse_media_query_list(self.context, input); let arc = Arc::new(self.shared_lock.wrap(media_queries)); - Ok(AtRuleType::WithBlock(AtRulePrelude::Media(arc))) + Ok(AtRuleType::WithBlock(AtRulePrelude::Media(arc, location))) }, "supports" => { let cond = SupportsCondition::parse(input)?; - Ok(AtRuleType::WithBlock(AtRulePrelude::Supports(cond))) + Ok(AtRuleType::WithBlock(AtRulePrelude::Supports(cond, location))) }, "font-face" => { - Ok(AtRuleType::WithBlock(AtRulePrelude::FontFace)) + Ok(AtRuleType::WithBlock(AtRulePrelude::FontFace(location))) }, "counter-style" => { if !cfg!(feature = "gecko") { @@ -1229,7 +1255,7 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> { }, "page" => { if cfg!(feature = "gecko") { - Ok(AtRuleType::WithBlock(AtRulePrelude::Page)) + Ok(AtRuleType::WithBlock(AtRulePrelude::Page(location))) } else { Err(()) } @@ -1237,7 +1263,7 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> { "-moz-document" => { if cfg!(feature = "gecko") { let cond = DocumentCondition::parse(self.context, input)?; - Ok(AtRuleType::WithBlock(AtRulePrelude::Document(cond))) + Ok(AtRuleType::WithBlock(AtRulePrelude::Document(cond, location))) } else { Err(()) } @@ -1248,28 +1274,30 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> { fn parse_block(&mut self, prelude: AtRulePrelude, input: &mut Parser) -> Result<CssRule, ()> { match prelude { - AtRulePrelude::FontFace => { + AtRulePrelude::FontFace(location) => { let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::FontFace)); Ok(CssRule::FontFace(Arc::new(self.shared_lock.wrap( - parse_font_face_block(&context, input).into())))) + parse_font_face_block(&context, input, location).into())))) } AtRulePrelude::CounterStyle(name) => { let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::CounterStyle)); Ok(CssRule::CounterStyle(Arc::new(self.shared_lock.wrap( parse_counter_style_body(name, &context, input)?)))) } - AtRulePrelude::Media(media_queries) => { + AtRulePrelude::Media(media_queries, location) => { Ok(CssRule::Media(Arc::new(self.shared_lock.wrap(MediaRule { media_queries: media_queries, rules: self.parse_nested_rules(input, CssRuleType::Media), + source_location: location, })))) } - AtRulePrelude::Supports(cond) => { + AtRulePrelude::Supports(cond, location) => { let enabled = cond.eval(self.context); Ok(CssRule::Supports(Arc::new(self.shared_lock.wrap(SupportsRule { condition: cond, rules: self.parse_nested_rules(input, CssRuleType::Supports), enabled: enabled, + source_location: location, })))) } AtRulePrelude::Viewport => { @@ -1285,18 +1313,20 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> { vendor_prefix: prefix, })))) } - AtRulePrelude::Page => { + AtRulePrelude::Page(location) => { let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::Page)); let declarations = parse_property_declaration_list(&context, input); - Ok(CssRule::Page(Arc::new(self.shared_lock.wrap(PageRule( - Arc::new(self.shared_lock.wrap(declarations)) - ))))) + Ok(CssRule::Page(Arc::new(self.shared_lock.wrap(PageRule { + block: Arc::new(self.shared_lock.wrap(declarations)), + source_location: location, + })))) } - AtRulePrelude::Document(cond) => { + AtRulePrelude::Document(cond, location) => { if cfg!(feature = "gecko") { Ok(CssRule::Document(Arc::new(self.shared_lock.wrap(DocumentRule { condition: cond, rules: self.parse_nested_rules(input, CssRuleType::Document), + source_location: location, })))) } else { unreachable!() @@ -1320,11 +1350,14 @@ impl<'a, 'b> QualifiedRuleParser for NestedRuleParser<'a, 'b> { fn parse_block(&mut self, prelude: SelectorList<SelectorImpl>, input: &mut Parser) -> Result<CssRule, ()> { + let location = get_location_with_offset(input.current_source_location(), + self.context.line_number_offset); let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::Style)); let declarations = parse_property_declaration_list(&context, input); Ok(CssRule::Style(Arc::new(self.shared_lock.wrap(StyleRule { selectors: prelude, - block: Arc::new(self.shared_lock.wrap(declarations)) + block: Arc::new(self.shared_lock.wrap(declarations)), + source_location: location, })))) } } |