Support declaring keyword property Gecko coverage as inexhaustive.
draft
Support declaring keyword property Gecko coverage as inexhaustive.
This allows us to control whether the catchall case in the match expression
that maps Gecko const to Servo enum will be generated.
MozReview-Commit-ID: L65IjTONdfl
--- a/servo/components/style/properties/data.py
+++ b/servo/components/style/properties/data.py
@@ -23,44 +23,48 @@ def to_rust_ident(name):
def to_camel_case(ident):
return re.sub("(^|_|-)([a-z])", lambda m: m.group(2).upper(), ident.strip("_").strip("-"))
class Keyword(object):
def __init__(self, name, values, gecko_constant_prefix=None,
gecko_enum_prefix=None, custom_consts=None,
- extra_gecko_values=None, extra_servo_values=None):
+ extra_gecko_values=None, extra_servo_values=None,
+ gecko_strip_moz_prefix=True,
+ gecko_inexhaustive=None):
self.name = name
self.values = values.split()
if gecko_constant_prefix and gecko_enum_prefix:
raise TypeError("Only one of gecko_constant_prefix and gecko_enum_prefix can be specified")
self.gecko_constant_prefix = gecko_constant_prefix or \
"NS_STYLE_" + self.name.upper().replace("-", "_")
self.gecko_enum_prefix = gecko_enum_prefix
self.extra_gecko_values = (extra_gecko_values or "").split()
self.extra_servo_values = (extra_servo_values or "").split()
self.consts_map = {} if custom_consts is None else custom_consts
+ self.gecko_strip_moz_prefix = gecko_strip_moz_prefix
+ self.gecko_inexhaustive = gecko_inexhaustive or (gecko_enum_prefix is None)
def gecko_values(self):
return self.values + self.extra_gecko_values
def servo_values(self):
return self.values + self.extra_servo_values
def values_for(self, product):
if product == "gecko":
return self.gecko_values()
elif product == "servo":
return self.servo_values()
else:
raise Exception("Bad product: " + product)
def gecko_constant(self, value):
- moz_stripped = value.replace("-moz-", '')
+ moz_stripped = value.replace("-moz-", '') if self.gecko_strip_moz_prefix else value
parts = moz_stripped.split('-')
if self.gecko_enum_prefix:
parts = [p.title() for p in parts]
return self.gecko_enum_prefix + "::" + "".join(parts)
else:
mapped = self.consts_map.get(value)
suffix = mapped if mapped else moz_stripped.replace("-", "_")
return self.gecko_constant_prefix + "_" + suffix.upper()
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -250,17 +250,19 @@ def set_gecko_property(ffi_name, expr):
#[allow(non_snake_case)]
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
use properties::longhands::${ident}::computed_value::T as Keyword;
// FIXME(bholley): Align binary representations and ditch |match| for cast + static_asserts
match ${get_gecko_property(gecko_ffi_name)} ${keyword.maybe_cast("u32")} {
% for value in keyword.values_for('gecko'):
structs::${keyword.gecko_constant(value)} => Keyword::${to_rust_ident(value)},
% endfor
+ % if keyword.gecko_inexhaustive:
x => panic!("Found unexpected value in style struct for ${ident} property: {:?}", x),
+ % endif
}
}
</%def>
<%def name="impl_color_setter(ident, gecko_ffi_name, complex_color=True)">
#[allow(unreachable_code)]
#[allow(non_snake_case)]
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
@@ -1022,17 +1024,18 @@ fn static_assert() {
<%self:impl_trait style_struct_name="Box" skip_longhands="${skip_box_longhands}">
// We manually-implement the |display| property until we get general
// infrastructure for preffing certain values.
<% display_keyword = Keyword("display", "inline block inline-block table inline-table table-row-group " +
"table-header-group table-footer-group table-row table-column-group " +
"table-column table-cell table-caption list-item flex none " +
"-moz-box -moz-inline-box",
- gecko_enum_prefix="StyleDisplay") %>
+ gecko_enum_prefix="StyleDisplay",
+ gecko_inexhaustive=True) %>
${impl_keyword('display', 'mDisplay', display_keyword, True)}
// overflow-y is implemented as a newtype of overflow-x, so we need special handling.
// We could generalize this if we run into other newtype keywords.
<% overflow_x = data.longhands_by_name["overflow-x"] %>
pub fn set_overflow_y(&mut self, v: longhands::overflow_y::computed_value::T) {
use properties::longhands::overflow_x::computed_value::T as BaseType;
// FIXME(bholley): Align binary representations and ditch |match| for cast + static_asserts
--- a/servo/components/style/properties/helpers.mako.rs
+++ b/servo/components/style/properties/helpers.mako.rs
@@ -324,17 +324,17 @@
</%call>
</%def>
<%def name="single_keyword_computed(name, values, vector=False, **kwargs)">
<%
keyword_kwargs = {a: kwargs.pop(a, None) for a in [
'gecko_constant_prefix', 'gecko_enum_prefix',
'extra_gecko_values', 'extra_servo_values',
- 'custom_consts',
+ 'custom_consts', 'gecko_inexhaustive',
]}
%>
<%def name="inner_body()">
pub use self::computed_value::T as SpecifiedValue;
pub mod computed_value {
use style_traits::ToCss;
define_css_keyword_enum! { T:
--- a/servo/components/style/properties/longhand/border.mako.rs
+++ b/servo/components/style/properties/longhand/border.mako.rs
@@ -53,21 +53,23 @@
${helpers.predefined_type("border-" + corner + "-radius", "BorderRadiusSize",
"computed::BorderRadiusSize::zero()",
"parse",
animatable=True)}
% endfor
${helpers.single_keyword("box-decoration-break", "slice clone",
gecko_enum_prefix="StyleBoxDecorationBreak",
+ gecko_inexhaustive=true,
products="gecko", animatable=False)}
${helpers.single_keyword("-moz-float-edge", "content-box margin-box",
gecko_ffi_name="mFloatEdge",
gecko_enum_prefix="StyleFloatEdge",
+ gecko_inexhaustive=true,
products="gecko",
animatable=False)}
// https://drafts.csswg.org/css-backgrounds-3/#border-image-source
<%helpers:longhand name="border-image-source" products="gecko" animatable="False">
use std::fmt;
use style_traits::ToCss;
use values::NoViewportPercentage;
--- a/servo/components/style/properties/longhand/box.mako.rs
+++ b/servo/components/style/properties/longhand/box.mako.rs
@@ -87,16 +87,17 @@
${helpers.single_keyword("position", "static absolute relative fixed",
need_clone=True, extra_gecko_values="sticky", animatable=False)}
<%helpers:single_keyword_computed name="float"
values="none left right"
animatable="False"
need_clone="True"
gecko_enum_prefix="StyleFloat"
+ gecko_inexhaustive="True"
gecko_ffi_name="mFloat">
use values::NoViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {}
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
#[inline]
fn to_computed_value(&self, context: &Context) -> computed_value::T {
--- a/servo/components/style/properties/longhand/inherited_svg.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_svg.mako.rs
@@ -30,16 +30,17 @@
gecko_constant_prefix="NS_STYLE_COLOR_INTERPOLATION",
animatable=False)}
${helpers.predefined_type("fill-opacity", "Opacity", "1.0",
products="gecko", animatable=False)}
${helpers.single_keyword("fill-rule", "nonzero evenodd",
gecko_enum_prefix="StyleFillRule",
+ gecko_inexhaustive=true,
products="gecko", animatable=False)}
${helpers.single_keyword("shape-rendering",
"auto optimizeSpeed crispEdges geometricPrecision",
products="gecko",
animatable=False)}
${helpers.single_keyword("stroke-linecap", "butt round square",
@@ -55,9 +56,10 @@
${helpers.predefined_type("stroke-opacity", "Opacity", "1.0",
products="gecko", animatable=False)}
// Section 14 - Clipping, Masking and Compositing
${helpers.single_keyword("clip-rule", "nonzero evenodd",
products="gecko",
gecko_enum_prefix="StyleFillRule",
+ gecko_inexhaustive=true,
animatable=False)}
--- a/servo/components/style/properties/longhand/pointing.mako.rs
+++ b/servo/components/style/properties/longhand/pointing.mako.rs
@@ -146,20 +146,23 @@
// NB: `pointer-events: auto` (and use of `pointer-events` in anything that isn't SVG, in fact)
// is nonstandard, slated for CSS4-UI.
// TODO(pcwalton): SVG-only values.
${helpers.single_keyword("pointer-events", "auto none", animatable=False)}
${helpers.single_keyword("-moz-user-input", "none enabled disabled",
products="gecko", gecko_ffi_name="mUserInput",
gecko_enum_prefix="StyleUserInput",
+ gecko_inexhaustive=true,
animatable=False)}
${helpers.single_keyword("-moz-user-modify", "read-only read-write write-only",
products="gecko", gecko_ffi_name="mUserModify",
gecko_enum_prefix="StyleUserModify",
+ gecko_inexhaustive=true,
animatable=False)}
${helpers.single_keyword("-moz-user-focus",
"ignore normal select-after select-before select-menu select-same select-all none",
products="gecko", gecko_ffi_name="mUserFocus",
gecko_enum_prefix="StyleUserFocus",
+ gecko_inexhaustive=true,
animatable=False)}
--- a/servo/components/style/properties/longhand/ui.mako.rs
+++ b/servo/components/style/properties/longhand/ui.mako.rs
@@ -11,9 +11,10 @@
${helpers.single_keyword("ime-mode", "normal auto active disabled inactive",
products="gecko", gecko_ffi_name="mIMEMode",
animatable=False)}
${helpers.single_keyword("-moz-user-select", "auto text none all", products="gecko",
gecko_ffi_name="mUserSelect",
gecko_enum_prefix="StyleUserSelect",
+ gecko_inexhaustive=true,
animatable=False)}
--- a/servo/components/style/properties/longhand/xul.mako.rs
+++ b/servo/components/style/properties/longhand/xul.mako.rs
@@ -6,14 +6,15 @@
<% from data import Method %>
// Non-standard properties that Gecko uses for XUL elements.
<% data.new_style_struct("XUL", inherited=False) %>
${helpers.single_keyword("-moz-box-align", "stretch start center baseline end",
products="gecko", gecko_ffi_name="mBoxAlign",
gecko_enum_prefix="StyleBoxAlign",
+ gecko_inexhaustive=true,
animatable=False)}
${helpers.predefined_type("-moz-box-flex", "Number", "0.0", "parse_non_negative",
products="gecko", gecko_ffi_name="mBoxFlex",
needs_context=False,
animatable=False)}