Commit 0c0df22d authored by Eddy Mead's avatar Eddy Mead Committed by Commit Bot

Move field_alias expansion up into css_properties.py

This allows us to remove some duplicate code, and prepares the way
for generating ComputedStyle's Initial* functions elsewhere.

This ended up reducing the number of includes in each APO subclass
header. Gist diff:
https://gist.github.com/wilddamon/5bfa127e71e9c7993104bbfa602b3f97/revisions

Bug: 763306
Change-Id: Icaacee6abe218b73a460311eb1ffcbff5c81d4c5
Reviewed-on: https://chromium-review.googlesource.com/716442
Commit-Queue: meade_UTC10 <meade@chromium.org>
Reviewed-by: default avatarDarren Shen <shend@chromium.org>
Cr-Commit-Position: refs/heads/master@{#509698}
parent 4d501600
...@@ -5,8 +5,26 @@ ...@@ -5,8 +5,26 @@
import json5_generator import json5_generator
from name_utilities import ( from name_utilities import (
upper_camel_case, lower_camel_case, enum_for_css_property, enum_for_css_property_alias upper_camel_case,
lower_camel_case,
enum_value_name,
enum_for_css_property,
enum_for_css_property_alias
) )
from core.css.field_alias_expander import FieldAliasExpander
# These values are converted using CSSPrimitiveValue in the setter function,
# if applicable.
PRIMITIVE_TYPES = [
'short',
'unsigned short',
'int',
'unsigned int',
'unsigned',
'float',
'LineClampValue'
]
# Check properties parameters are valid. # Check properties parameters are valid.
...@@ -28,11 +46,13 @@ def check_property_parameters(property_to_check): ...@@ -28,11 +46,13 @@ def check_property_parameters(property_to_check):
'should not implement parseShorthand' 'should not implement parseShorthand'
class CSSProperties(json5_generator.Writer): class CSSProperties(json5_generator.Writer):
def __init__(self, file_paths): def __init__(self, file_paths):
json5_generator.Writer.__init__(self, file_paths) json5_generator.Writer.__init__(self, [file_paths[0]])
# StylePropertyMetadata assumes that there are at most 1024 properties + aliases. # StylePropertyMetadata assumes that there are at most 1024 properties
# + aliases.
self._alias_offset = 512 self._alias_offset = 512
# 0: CSSPropertyInvalid # 0: CSSPropertyInvalid
# 1: CSSPropertyApplyAtRule # 1: CSSPropertyApplyAtRule
...@@ -53,10 +73,14 @@ class CSSProperties(json5_generator.Writer): ...@@ -53,10 +73,14 @@ class CSSProperties(json5_generator.Writer):
property_['sorting_key'] = (priority, name_without_leading_dash) property_['sorting_key'] = (priority, name_without_leading_dash)
# Assert there are no key collisions. # Assert there are no key collisions.
sorting_keys = [p['sorting_key'] for p in properties] sorting_keys = {}
assert len(sorting_keys) == len(set(sorting_keys)), \ for property_ in properties:
('Collision detected - two properties have the same name and priority, ' key = property_['sorting_key']
'a potentially non-deterministic ordering can occur.') assert key not in sorting_keys, \
('Collision detected - two properties have the same name and '
'priority, a potentially non-deterministic ordering can '
'occur: {}'.format(key))
sorting_keys[key] = property_['name']
properties.sort(key=lambda p: p['sorting_key']) properties.sort(key=lambda p: p['sorting_key'])
self._aliases = [property_ for property_ in properties if property_['alias_for']] self._aliases = [property_ for property_ in properties if property_['alias_for']]
...@@ -65,17 +89,13 @@ class CSSProperties(json5_generator.Writer): ...@@ -65,17 +89,13 @@ class CSSProperties(json5_generator.Writer):
assert (self._first_enum_value + len(properties) < self._alias_offset), ( assert (self._first_enum_value + len(properties) < self._alias_offset), (
'Property aliasing expects there are under %d properties.' % self._alias_offset) 'Property aliasing expects there are under %d properties.' % self._alias_offset)
for property_ in properties: self._field_alias_expander = FieldAliasExpander(file_paths[1])
for offset, property_ in enumerate(properties):
assert property_['is_descriptor'] or property_['is_property'], \ assert property_['is_descriptor'] or property_['is_property'], \
property_['name'] + ' must be either a property, a descriptor' +\ property_['name'] + ' must be either a property, a descriptor' +\
' or both' ' or both'
for offset, property_ in enumerate(properties):
property_['property_id'] = enum_for_css_property(property_['name'])
property_['upper_camel_name'] = upper_camel_case(property_['name'])
property_['lower_camel_name'] = lower_camel_case(property_['name'])
property_['enum_value'] = self._first_enum_value + offset property_['enum_value'] = self._first_enum_value + offset
property_['is_internal'] = property_['name'].startswith('-internal-') self.expand_parameters(property_)
self._properties_including_aliases = properties self._properties_including_aliases = properties
self._properties = {property_['property_id']: property_ for property_ in properties} self._properties = {property_['property_id']: property_ for property_ in properties}
...@@ -107,3 +127,72 @@ class CSSProperties(json5_generator.Writer): ...@@ -107,3 +127,72 @@ class CSSProperties(json5_generator.Writer):
def properties(self): def properties(self):
return self._properties return self._properties
def expand_parameters(self, property_):
def set_if_none(property_, key, value):
if property_[key] is None:
property_[key] = value
# Basic info.
property_['property_id'] = enum_for_css_property(property_['name'])
property_['upper_camel_name'] = upper_camel_case(property_['name'])
property_['lower_camel_name'] = lower_camel_case(property_['name'])
property_['is_internal'] = property_['name'].startswith('-internal-')
name = property_['name_for_methods']
if not name:
name = upper_camel_case(property_['name']).replace('Webkit', '')
set_if_none(property_, 'inherited', False)
# Initial function, Getters and Setters for ComputedStyle.
set_if_none(property_, 'initial', 'Initial' + name)
simple_type_name = str(property_['type_name']).split('::')[-1]
set_if_none(property_, 'name_for_methods', name)
set_if_none(property_, 'type_name', 'E' + name)
set_if_none(
property_,
'getter',
name if simple_type_name != name else 'Get' + name)
set_if_none(property_, 'setter', 'Set' + name)
if property_['inherited']:
property_['is_inherited_setter'] = 'Set' + name + 'IsInherited'
# Expand whether there are custom StyleBuilder methods.
if property_['custom_all']:
property_['custom_initial'] = True
property_['custom_inherit'] = True
property_['custom_value'] = True
# Expand StyleBuilderConverter params where ncessary.
if property_['type_name'] in PRIMITIVE_TYPES:
set_if_none(property_, 'converter', 'CSSPrimitiveValue')
else:
set_if_none(property_, 'converter', 'CSSIdentifierValue')
# Expand out field templates.
if not property_['field_template']:
return
self._field_alias_expander.expand_field_alias(property_)
type_name = property_['type_name']
if (property_['field_template'] == 'keyword' or
property_['field_template'] == 'multi_keyword'):
default_value = type_name + '::' + \
enum_value_name(property_['default_value'])
elif (property_['field_template'] == 'external' or
property_['field_template'] == 'primitive' or
property_['field_template'] == 'pointer'):
default_value = property_['default_value']
else:
assert property_['field_template'] == 'monotonic_flag', \
"Please put a valid value for field_template; got " + \
str(property_['field_template'])
property_['type_name'] = 'bool'
default_value = 'false'
property_['default_value'] = default_value
if property_['wrapper_pointer_name']:
assert property_['field_template'] in ['pointer', 'external']
if property_['field_template'] == 'external':
property_['type_name'] = '{}<{}>'.format(
property_['wrapper_pointer_name'], type_name)
# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import json5_generator
class FieldAliasExpander(object):
"""
A helper for expanding the "field_template" parameter in CSSProperties.json5
It takes the list of aliases and expansions from the given file_path, (it
should point to core/css/ComputedStyleFieldAliases.json5) and uses that to
inform which fields in a given property should be set.
"""
def __init__(self, file_path):
loaded_file = json5_generator.Json5File.load_from_files([file_path])
self._field_aliases = dict([(alias["name"], alias)
for alias in loaded_file.name_dictionaries])
def expand_field_alias(self, property_):
"""
Does expansion based on the value of field_template of a given property.
"""
if property_['field_template'] in self._field_aliases:
alias_template = property_['field_template']
for field in self._field_aliases[alias_template]:
if field == 'name':
continue
property_[field] = self._field_aliases[alias_template][field]
...@@ -20,8 +20,8 @@ class CSSOMTypesWriter(css_properties.CSSProperties): ...@@ -20,8 +20,8 @@ class CSSOMTypesWriter(css_properties.CSSProperties):
CSSKeywordValue is valid for a given CSS property. The header files live in CSSKeywordValue is valid for a given CSS property. The header files live in
core/css/cssom. core/css/cssom.
""" """
def __init__(self, json5_file_path): def __init__(self, json5_file_paths):
super(CSSOMTypesWriter, self).__init__(json5_file_path) super(CSSOMTypesWriter, self).__init__(json5_file_paths)
for property_ in self._properties.values(): for property_ in self._properties.values():
types = [] types = []
......
...@@ -41,8 +41,8 @@ import template_expander ...@@ -41,8 +41,8 @@ import template_expander
class StylePropertyShorthandWriter(css_properties.CSSProperties): class StylePropertyShorthandWriter(css_properties.CSSProperties):
class_name = 'StylePropertyShorthand' class_name = 'StylePropertyShorthand'
def __init__(self, json5_file_path): def __init__(self, json5_file_paths):
super(StylePropertyShorthandWriter, self).__init__(json5_file_path) super(StylePropertyShorthandWriter, self).__init__(json5_file_paths)
self._outputs = { self._outputs = {
('StylePropertyShorthand.cpp'): self.generate_style_property_shorthand_cpp, ('StylePropertyShorthand.cpp'): self.generate_style_property_shorthand_cpp,
('StylePropertyShorthand.h'): self.generate_style_property_shorthand_h} ('StylePropertyShorthand.h'): self.generate_style_property_shorthand_h}
......
...@@ -21,7 +21,7 @@ class ApiClassData( ...@@ -21,7 +21,7 @@ class ApiClassData(
class CSSPropertyAPIWriter(css_properties.CSSProperties): class CSSPropertyAPIWriter(css_properties.CSSProperties):
def __init__(self, json5_file_paths): def __init__(self, json5_file_paths):
super(CSSPropertyAPIWriter, self).__init__([json5_file_paths[0]]) super(CSSPropertyAPIWriter, self).__init__(json5_file_paths)
self._outputs = { self._outputs = {
'CSSPropertyAPI.h': self.generate_property_api_header, 'CSSPropertyAPI.h': self.generate_property_api_header,
'CSSPropertyAPI.cpp': self.generate_property_api_implementation, 'CSSPropertyAPI.cpp': self.generate_property_api_implementation,
......
...@@ -13,84 +13,23 @@ import template_expander ...@@ -13,84 +13,23 @@ import template_expander
from collections import namedtuple, Counter from collections import namedtuple, Counter
from make_css_property_api_base import CSSPropertyAPIWriter from make_css_property_api_base import CSSPropertyAPIWriter
from name_utilities import upper_camel_case
class ApiMethod(namedtuple('ApiMethod', 'name,return_type,parameters')): class ApiMethod(namedtuple('ApiMethod', 'name,return_type,parameters')):
pass pass
def apply_computed_style_builder_function_parameters(property_):
"""Generate function parameters for generated implementations of Apply*
"""
def set_if_none(property_, key, value):
if property_[key] is None:
property_[key] = value
# These values are converted using CSSPrimitiveValue in the setter function,
# if applicable.
primitive_types = [
'short',
'unsigned short',
'int',
'unsigned int',
'unsigned',
'float',
'LineClampValue'
]
# Functions should only be declared on the API classes if they are
# implemented and not shared (denoted by api_class = true. Shared classes
# are denoted by api_class = "some string").
property_['should_declare_application_functions'] = \
property_['api_class'] \
and isinstance(property_['api_class'], types.BooleanType) \
and property_['is_property'] \
and not property_['use_handlers_for'] \
and not property_['longhands'] \
and not property_['direction_aware_options'] \
and not property_['builder_skip']
if not property_['should_declare_application_functions']:
return
if property_['custom_all']:
property_['custom_initial'] = True
property_['custom_inherit'] = True
property_['custom_value'] = True
name = property_['name_for_methods']
if not name:
name = upper_camel_case(property_['name']).replace('Webkit', '')
simple_type_name = str(property_['type_name']).split('::')[-1]
set_if_none(property_, 'name_for_methods', name)
set_if_none(property_, 'type_name', 'E' + name)
set_if_none(property_, 'setter', 'Set' + name)
if property_['type_name'] in primitive_types:
set_if_none(property_, 'converter', 'CSSPrimitiveValue')
else:
set_if_none(property_, 'converter', 'CSSIdentifierValue')
set_if_none(
property_, 'getter', name if simple_type_name != name else 'Get' + name)
set_if_none(property_, 'inherited', False)
set_if_none(property_, 'initial', 'Initial' + name)
if property_['inherited']:
property_['is_inherited_setter'] = 'Set' + name + 'IsInherited'
class CSSPropertyAPIHeadersWriter(CSSPropertyAPIWriter): class CSSPropertyAPIHeadersWriter(CSSPropertyAPIWriter):
def __init__(self, json5_file_paths): def __init__(self, json5_file_paths):
super(CSSPropertyAPIHeadersWriter, self).__init__([json5_file_paths[0]]) super(CSSPropertyAPIHeadersWriter, self).__init__(json5_file_paths)
assert len(json5_file_paths) == 2,\ assert len(json5_file_paths) == 3,\
('CSSPropertyAPIHeadersWriter requires 2 input json5 files, ' + ('CSSPropertyAPIHeadersWriter requires 3 input json5 files, ' +
'got {}.'.format(len(json5_file_paths))) 'got {}.'.format(len(json5_file_paths)))
# Map of API method name -> (return_type, parameters) # Map of API method name -> (return_type, parameters)
self._api_methods = {} self._api_methods = {}
api_methods = json5_generator.Json5File.load_from_files( api_methods = json5_generator.Json5File.load_from_files(
[json5_file_paths[1]]) [json5_file_paths[2]])
for api_method in api_methods.name_dictionaries: for api_method in api_methods.name_dictionaries:
self._api_methods[api_method['name']] = ApiMethod( self._api_methods[api_method['name']] = ApiMethod(
name=api_method['name'], name=api_method['name'],
...@@ -109,7 +48,17 @@ class CSSPropertyAPIHeadersWriter(CSSPropertyAPIWriter): ...@@ -109,7 +48,17 @@ class CSSPropertyAPIHeadersWriter(CSSPropertyAPIWriter):
property_['api_methods'] = methods property_['api_methods'] = methods
classname = self.get_classname(property_) classname = self.get_classname(property_)
assert classname is not None assert classname is not None
apply_computed_style_builder_function_parameters(property_) # Functions should only be declared on the API classes if they are
# implemented and not shared (denoted by api_class = true. Shared
# classes are denoted by api_class = "some string").
property_['should_declare_application_functions'] = \
property_['api_class'] \
and isinstance(property_['api_class'], types.BooleanType) \
and property_['is_property'] \
and not property_['use_handlers_for'] \
and not property_['longhands'] \
and not property_['direction_aware_options'] \
and not property_['builder_skip']
self._outputs[classname + '.h'] = ( self._outputs[classname + '.h'] = (
self.generate_property_api_h_builder(classname, property_)) self.generate_property_api_h_builder(classname, property_))
......
...@@ -12,28 +12,27 @@ ...@@ -12,28 +12,27 @@
{% if property.direction_aware_options %} {% if property.direction_aware_options %}
#include "core/StylePropertyShorthand.h" #include "core/StylePropertyShorthand.h"
{% endif %} {% endif %}
#include "core/css/CSSPrimitiveValueMappings.h"
#include "core/css/properties/CSSPropertyAPI.h" #include "core/css/properties/CSSPropertyAPI.h"
#include "core/css/resolver/StyleResolverState.h"
{# conditional includes - only used in some APIs #} {# conditional includes - only used in some APIs #}
{% if property.converter == "CSSPrimitiveValue" %} {% if property.should_declare_application_functions %}
#include "core/css/resolver/StyleResolverState.h"
{% if property.converter == "CSSPrimitiveValue" %}
#include "core/css/CSSPrimitiveValue.h" #include "core/css/CSSPrimitiveValue.h"
{% elif property.converter == "CSSIdentifierValue" %} #include "core/css/CSSPrimitiveValueMappings.h"
{% elif property.converter == "CSSIdentifierValue" %}
#include "core/css/CSSIdentifierValue.h" #include "core/css/CSSIdentifierValue.h"
{% elif property.converter %} {% elif property.converter %}
#include "core/css/CSSPrimitiveValueMappings.h"
#include "core/css/resolver/StyleBuilderConverter.h" #include "core/css/resolver/StyleBuilderConverter.h"
{% endif %} {% endif %}
{% if property.font %} {% if property.font %}
#include "core/css/resolver/FontBuilder.h" #include "core/css/resolver/FontBuilder.h"
{% else %} {% elif property.svg %}
#include "core/style/ComputedStyle.h" #include "core/style/ComputedStyle.h"
#include "core/style/SVGComputedStyle.h" #include "core/style/SVGComputedStyle.h"
{% endif %} {% else %}
{% if property.runtime_flag %} #include "core/style/ComputedStyle.h"
#include "platform/runtime_enabled_features.h" {% endif %}
{% endif %}
{% if property.svg %}
#include "core/style/SVGComputedStyle.h"
{% endif %} {% endif %}
{% if property.runtime_flag %} {% if property.runtime_flag %}
#include "platform/runtime_enabled_features.h" #include "platform/runtime_enabled_features.h"
......
# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import json5_generator import json5_generator
......
...@@ -12,8 +12,7 @@ import keyword_utils ...@@ -12,8 +12,7 @@ import keyword_utils
import bisect import bisect
from name_utilities import ( from name_utilities import (
enum_for_css_keyword, enum_type_name, enum_value_name, class_member_name, method_name, enum_value_name, class_member_name, method_name, class_name, join_names
class_name, join_names
) )
from itertools import chain from itertools import chain
...@@ -165,7 +164,6 @@ class Field(object): ...@@ -165,7 +164,6 @@ class Field(object):
def __init__(self, field_role, name_for_methods, property_name, type_name, wrapper_pointer_name, def __init__(self, field_role, name_for_methods, property_name, type_name, wrapper_pointer_name,
field_template, size, default_value, custom_copy, custom_compare, mutable, field_template, size, default_value, custom_copy, custom_compare, mutable,
getter_method_name, setter_method_name, initial_method_name, computed_style_custom_functions, **kwargs): getter_method_name, setter_method_name, initial_method_name, computed_style_custom_functions, **kwargs):
"""Creates a new field."""
self.name = class_member_name(name_for_methods) self.name = class_member_name(name_for_methods)
self.property_name = property_name self.property_name = property_name
self.type_name = type_name self.type_name = type_name
...@@ -218,7 +216,7 @@ def _get_include_paths(properties): ...@@ -218,7 +216,7 @@ def _get_include_paths(properties):
return list(sorted(include_paths)) return list(sorted(include_paths))
def _create_groups(properties, alias_dictionary): def _create_groups(properties):
"""Create a tree of groups from a list of properties. """Create a tree of groups from a list of properties.
Returns: Returns:
...@@ -251,7 +249,7 @@ def _create_groups(properties, alias_dictionary): ...@@ -251,7 +249,7 @@ def _create_groups(properties, alias_dictionary):
for group_name in property_['field_group'].split('->'): for group_name in property_['field_group'].split('->'):
current_group_dict[group_name] = current_group_dict.get(group_name, {None: []}) current_group_dict[group_name] = current_group_dict.get(group_name, {None: []})
current_group_dict = current_group_dict[group_name] current_group_dict = current_group_dict[group_name]
current_group_dict[None].extend(_create_fields(property_, alias_dictionary)) current_group_dict[None].extend(_create_fields(property_))
return _dict_to_group(None, root_group_dict) return _dict_to_group(None, root_group_dict)
...@@ -326,7 +324,7 @@ def _create_enums(properties): ...@@ -326,7 +324,7 @@ def _create_enums(properties):
return list(sorted(enums.values(), key=lambda e: e.type_name)) return list(sorted(enums.values(), key=lambda e: e.type_name))
def _create_property_field(property_, alias_dictionary): def _create_property_field(property_):
""" """
Create a property field. Create a property field.
""" """
...@@ -336,57 +334,35 @@ def _create_property_field(property_, alias_dictionary): ...@@ -336,57 +334,35 @@ def _create_property_field(property_, alias_dictionary):
('MakeComputedStyleBase requires an default value for all fields, none specified ' ('MakeComputedStyleBase requires an default value for all fields, none specified '
'for property ' + property_['name']) 'for property ' + property_['name'])
if property_['field_template'] in alias_dictionary:
alias_template = property_['field_template']
for field in alias_dictionary[alias_template]:
if field != 'name':
property_[field] = alias_dictionary[alias_template][field]
if property_['field_template'] == 'keyword':
type_name = property_['type_name'] type_name = property_['type_name']
default_value = type_name + '::' + enum_value_name(property_['default_value']) if property_['field_template'] == 'keyword':
assert property_['field_size'] is None, \ assert property_['field_size'] is None, \
("'" + property_['name'] + "' is a keyword field, " ("'" + property_['name'] + "' is a keyword field, "
"so it should not specify a field_size") "so it should not specify a field_size")
size = int(math.ceil(math.log(len(property_['keywords']), 2))) size = int(math.ceil(math.log(len(property_['keywords']), 2)))
elif property_['field_template'] == 'multi_keyword': elif property_['field_template'] == 'multi_keyword':
type_name = property_['type_name']
default_value = type_name + '::' + enum_value_name(property_['default_value'])
size = len(property_['keywords']) - 1 # Subtract 1 for 'none' keyword size = len(property_['keywords']) - 1 # Subtract 1 for 'none' keyword
elif property_['field_template'] == 'external': elif property_['field_template'] == 'external':
type_name = property_['type_name']
default_value = property_['default_value']
size = None size = None
elif property_['field_template'] == 'primitive': elif property_['field_template'] == 'primitive':
type_name = property_['type_name']
default_value = property_['default_value']
size = 1 if type_name == 'bool' else property_["field_size"] # pack bools with 1 bit. size = 1 if type_name == 'bool' else property_["field_size"] # pack bools with 1 bit.
elif property_['field_template'] == 'pointer': elif property_['field_template'] == 'pointer':
type_name = property_['type_name']
default_value = property_['default_value']
size = None size = None
else: else:
assert property_['field_template'] == 'monotonic_flag', "Please put a valid value for field_template" assert property_['field_template'] == 'monotonic_flag', "Please put a valid value for field_template"
type_name = 'bool'
default_value = 'false'
size = 1 size = 1
if property_['wrapper_pointer_name']:
assert property_['field_template'] in ['pointer', 'external']
if property_['field_template'] == 'external':
type_name = '{}<{}>'.format(property_['wrapper_pointer_name'], type_name)
return Field( return Field(
'property', 'property',
name_for_methods, name_for_methods,
property_name=property_['name'], property_name=property_['name'],
inherited=property_['inherited'], inherited=property_['inherited'],
independent=property_['independent'], independent=property_['independent'],
type_name=type_name, type_name=property_['type_name'],
wrapper_pointer_name=property_['wrapper_pointer_name'], wrapper_pointer_name=property_['wrapper_pointer_name'],
field_template=property_['field_template'], field_template=property_['field_template'],
size=size, size=size,
default_value=default_value, default_value=property_['default_value'],
custom_copy=property_['custom_copy'], custom_copy=property_['custom_copy'],
custom_compare=property_['custom_compare'], custom_compare=property_['custom_compare'],
mutable=property_['mutable'], mutable=property_['mutable'],
...@@ -422,7 +398,7 @@ def _create_inherited_flag_field(property_): ...@@ -422,7 +398,7 @@ def _create_inherited_flag_field(property_):
) )
def _create_fields(property_, alias_dictionary): def _create_fields(property_):
""" """
Create ComputedStyle fields from a property and return a list of Field objects. Create ComputedStyle fields from a property and return a list of Field objects.
""" """
...@@ -434,7 +410,7 @@ def _create_fields(property_, alias_dictionary): ...@@ -434,7 +410,7 @@ def _create_fields(property_, alias_dictionary):
if property_['independent']: if property_['independent']:
fields.append(_create_inherited_flag_field(property_)) fields.append(_create_inherited_flag_field(property_))
fields.append(_create_property_field(property_, alias_dictionary)) fields.append(_create_property_field(property_))
return fields return fields
...@@ -580,8 +556,8 @@ def _evaluate_rare_inherit_group(all_properties, properties_ranking_file, ...@@ -580,8 +556,8 @@ def _evaluate_rare_inherit_group(all_properties, properties_ranking_file,
class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter): class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter):
def __init__(self, json5_file_paths): def __init__(self, json5_file_paths):
# Read CSSProperties.json5 # Reads CSSProperties.json5
super(ComputedStyleBaseWriter, self).__init__([json5_file_paths[0]]) super(ComputedStyleBaseWriter, self).__init__(json5_file_paths)
# Ignore shorthand properties # Ignore shorthand properties
for property_ in self._properties.values(): for property_ in self._properties.values():
...@@ -596,9 +572,8 @@ class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter): ...@@ -596,9 +572,8 @@ class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter):
# the generated enum will have the same order and continuity as # the generated enum will have the same order and continuity as
# CSSProperties.json5 and we can get the longest continuous segment. # CSSProperties.json5 and we can get the longest continuous segment.
# Thereby reduce the switch case statement to the minimum. # Thereby reduce the switch case statement to the minimum.
css_properties = keyword_utils.sort_keyword_properties_by_canonical_order(css_properties, css_properties = keyword_utils.sort_keyword_properties_by_canonical_order(
json5_file_paths[3], css_properties, json5_file_paths[4], self.json5_file.parameters)
self.json5_file.parameters)
for property_ in css_properties: for property_ in css_properties:
# Set default values for extra parameters in ComputedStyleExtraFields.json5. # Set default values for extra parameters in ComputedStyleExtraFields.json5.
...@@ -608,7 +583,7 @@ class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter): ...@@ -608,7 +583,7 @@ class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter):
# Read ComputedStyleExtraFields.json5 using the parameter specification from the CSS properties file. # Read ComputedStyleExtraFields.json5 using the parameter specification from the CSS properties file.
extra_fields = json5_generator.Json5File.load_from_files( extra_fields = json5_generator.Json5File.load_from_files(
[json5_file_paths[1]], [json5_file_paths[2]],
default_parameters=self.json5_file.parameters default_parameters=self.json5_file.parameters
).name_dictionaries ).name_dictionaries
...@@ -616,7 +591,7 @@ class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter): ...@@ -616,7 +591,7 @@ class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter):
if property_['mutable']: if property_['mutable']:
assert property_['field_template'] == 'monotonic_flag', \ assert property_['field_template'] == 'monotonic_flag', \
'mutable keyword only implemented for monotonic_flag' 'mutable keyword only implemented for monotonic_flag'
make_style_builder.apply_property_naming_defaults(property_) self.expand_parameters(property_)
all_properties = css_properties + extra_fields all_properties = css_properties + extra_fields
...@@ -625,19 +600,17 @@ class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter): ...@@ -625,19 +600,17 @@ class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter):
# Organise fields into a tree structure where the root group # Organise fields into a tree structure where the root group
# is ComputedStyleBase. # is ComputedStyleBase.
group_parameters = dict([(conf["name"], conf["cumulative_distribution"]) for conf in group_parameters = dict([(conf["name"], conf["cumulative_distribution"]) for conf in
json5_generator.Json5File.load_from_files([json5_file_paths[5]]).name_dictionaries]) json5_generator.Json5File.load_from_files([json5_file_paths[6]]).name_dictionaries])
_evaluate_rare_non_inherited_group(all_properties, json5_file_paths[4], _evaluate_rare_non_inherited_group(all_properties, json5_file_paths[5],
len(group_parameters["rare_non_inherited_properties_rule"]), len(group_parameters["rare_non_inherited_properties_rule"]),
group_parameters["rare_non_inherited_properties_rule"]) group_parameters["rare_non_inherited_properties_rule"])
_evaluate_rare_inherit_group(all_properties, json5_file_paths[4], _evaluate_rare_inherit_group(all_properties, json5_file_paths[5],
len(group_parameters["rare_inherited_properties_rule"]), len(group_parameters["rare_inherited_properties_rule"]),
group_parameters["rare_inherited_properties_rule"]) group_parameters["rare_inherited_properties_rule"])
alias_dictionary = dict([(alias["name"], alias) for alias in self._root_group = _create_groups(all_properties)
json5_generator.Json5File.load_from_files([json5_file_paths[6]]).name_dictionaries])
self._root_group = _create_groups(all_properties, alias_dictionary)
self._diff_functions_map = _create_diff_groups_map(json5_generator.Json5File.load_from_files( self._diff_functions_map = _create_diff_groups_map(json5_generator.Json5File.load_from_files(
[json5_file_paths[2]] [json5_file_paths[3]]
).name_dictionaries, self._root_group) ).name_dictionaries, self._root_group)
self._include_paths = _get_include_paths(all_properties) self._include_paths = _get_include_paths(all_properties)
......
...@@ -97,12 +97,12 @@ def _find_enum_longest_continuous_segment(property_, name_to_position_dictionary ...@@ -97,12 +97,12 @@ def _find_enum_longest_continuous_segment(property_, name_to_position_dictionary
class CSSValueIDMappingsWriter(make_style_builder.StyleBuilderWriter): class CSSValueIDMappingsWriter(make_style_builder.StyleBuilderWriter):
def __init__(self, json5_file_path): def __init__(self, json5_file_paths):
super(CSSValueIDMappingsWriter, self).__init__([json5_file_path[0]]) super(CSSValueIDMappingsWriter, self).__init__(json5_file_paths)
self._outputs = { self._outputs = {
'CSSValueIDMappingsGenerated.h': self.generate_css_value_mappings, 'CSSValueIDMappingsGenerated.h': self.generate_css_value_mappings,
} }
self.css_values_dictionary_file = json5_file_path[1] self.css_values_dictionary_file = json5_file_paths[2]
css_properties = [value for value in self._properties.values() if not value['longhands']] css_properties = [value for value in self._properties.values() if not value['longhands']]
# We sort the enum values based on each value's position in # We sort the enum values based on each value's position in
# the keywords as listed in CSSProperties.json5. This will ensure that if there is a continuous # the keywords as listed in CSSProperties.json5. This will ensure that if there is a continuous
...@@ -110,9 +110,8 @@ class CSSValueIDMappingsWriter(make_style_builder.StyleBuilderWriter): ...@@ -110,9 +110,8 @@ class CSSValueIDMappingsWriter(make_style_builder.StyleBuilderWriter):
# the generated enum will have the same order and continuity as # the generated enum will have the same order and continuity as
# CSSProperties.json5 and we can get the longest continuous segment. # CSSProperties.json5 and we can get the longest continuous segment.
# Thereby reduce the switch case statement to the minimum. # Thereby reduce the switch case statement to the minimum.
css_properties = keyword_utils.sort_keyword_properties_by_canonical_order(css_properties, css_properties = keyword_utils.sort_keyword_properties_by_canonical_order(
json5_file_path[1], css_properties, json5_file_paths[2], self.json5_file.parameters)
self.json5_file.parameters)
@template_expander.use_jinja('templates/CSSValueIDMappingsGenerated.h.tmpl') @template_expander.use_jinja('templates/CSSValueIDMappingsGenerated.h.tmpl')
...@@ -129,14 +128,14 @@ class CSSValueIDMappingsWriter(make_style_builder.StyleBuilderWriter): ...@@ -129,14 +128,14 @@ class CSSValueIDMappingsWriter(make_style_builder.StyleBuilderWriter):
include_paths.update(property_['include_paths']) include_paths.update(property_['include_paths'])
if property_['field_template'] == 'multi_keyword': if property_['field_template'] == 'multi_keyword':
mappings[property_['type_name']] = { mappings[property_['type_name']] = {
'default_value': enum_value_name(property_['default_value']), 'default_value': property_['default_value'],
'mapping': [(enum_value_name(k), enum_for_css_keyword(k)) for k in property_['keywords']], 'mapping': [(enum_value_name(k), enum_for_css_keyword(k)) for k in property_['keywords']],
} }
elif property_['field_template'] == 'keyword': elif property_['field_template'] == 'keyword':
enum_pair_list, enum_segment, p_segment = _find_enum_longest_continuous_segment( enum_pair_list, enum_segment, p_segment = _find_enum_longest_continuous_segment(
property_, name_to_position_dictionary) property_, name_to_position_dictionary)
mappings[property_['type_name']] = { mappings[property_['type_name']] = {
'default_value': enum_value_name(property_['default_value']), 'default_value': property_['default_value'],
'mapping': enum_pair_list, 'mapping': enum_pair_list,
'segment': enum_segment, 'segment': enum_segment,
'longest_segment_length': p_segment[1] - p_segment[0], 'longest_segment_length': p_segment[1] - p_segment[0],
......
...@@ -32,50 +32,11 @@ import types ...@@ -32,50 +32,11 @@ import types
from core.css import css_properties from core.css import css_properties
import json5_generator import json5_generator
from name_utilities import lower_first, upper_camel_case from name_utilities import lower_first
import template_expander import template_expander
def apply_property_naming_defaults(property_): def calculate_functions_to_declare(property_):
def set_if_none(property_, key, value):
if property_[key] is None:
property_[key] = value
# These values are converted using CSSPrimitiveValue in the setter function,
# if applicable.
primitive_types = [
'short',
'unsigned short',
'int',
'unsigned int',
'unsigned',
'float',
'LineClampValue'
]
# TODO(meade): Delete this once all methods are moved to CSSPropertyAPIs.
upper_camel = upper_camel_case(property_['name'])
set_if_none(
property_, 'name_for_methods', upper_camel.replace('Webkit', ''))
name = property_['name_for_methods']
simple_type_name = str(property_['type_name']).split('::')[-1]
set_if_none(property_, 'type_name', 'E' + name)
set_if_none(
property_, 'getter', name if simple_type_name != name else 'Get' + name)
set_if_none(property_, 'setter', 'Set' + name)
set_if_none(property_, 'inherited', False)
set_if_none(property_, 'initial', 'Initial' + name)
if property_['type_name'] in primitive_types:
set_if_none(property_, 'converter', 'CSSPrimitiveValue')
else:
set_if_none(property_, 'converter', 'CSSIdentifierValue')
if property_['custom_all']:
property_['custom_initial'] = True
property_['custom_inherit'] = True
property_['custom_value'] = True
if property_['inherited']:
property_['is_inherited_setter'] = 'Set' + name + 'IsInherited'
property_['should_declare_functions'] = \ property_['should_declare_functions'] = \
not property_['use_handlers_for'] \ not property_['use_handlers_for'] \
and not property_['longhands'] \ and not property_['longhands'] \
...@@ -99,15 +60,16 @@ class StyleBuilderWriter(css_properties.CSSProperties): ...@@ -99,15 +60,16 @@ class StyleBuilderWriter(css_properties.CSSProperties):
'lower_first': lower_first, 'lower_first': lower_first,
} }
def __init__(self, json5_file_path): def __init__(self, json5_file_paths):
super(StyleBuilderWriter, self).__init__(json5_file_path) super(StyleBuilderWriter, self).__init__(json5_file_paths)
self._outputs = {('StyleBuilderFunctions.h'): self.generate_style_builder_functions_h, self._outputs = {
('StyleBuilderFunctions.h'): self.generate_style_builder_functions_h,
('StyleBuilderFunctions.cpp'): self.generate_style_builder_functions_cpp, ('StyleBuilderFunctions.cpp'): self.generate_style_builder_functions_cpp,
('StyleBuilder.cpp'): self.generate_style_builder, ('StyleBuilder.cpp'): self.generate_style_builder,
} }
for property in self._properties.values(): for property_ in self._properties.values():
apply_property_naming_defaults(property) calculate_functions_to_declare(property_)
@template_expander.use_jinja('templates/StyleBuilderFunctions.h.tmpl', @template_expander.use_jinja('templates/StyleBuilderFunctions.h.tmpl',
filters=filters) filters=filters)
......
...@@ -20,6 +20,7 @@ scripts_for_json5_files = [ ...@@ -20,6 +20,7 @@ scripts_for_json5_files = [
"$_scripts_dir/name_utilities.py", "$_scripts_dir/name_utilities.py",
"$_scripts_dir/template_expander.py", "$_scripts_dir/template_expander.py",
"$_scripts_dir/templates/macros.tmpl", "$_scripts_dir/templates/macros.tmpl",
"$_scripts_dir/core/css/field_alias_expander.py",
"$_scripts_dir/core/css/properties/templates/application_macros.tmpl", "$_scripts_dir/core/css/properties/templates/application_macros.tmpl",
] ]
...@@ -187,7 +188,10 @@ template("code_generator") { ...@@ -187,7 +188,10 @@ template("code_generator") {
template("css_properties") { template("css_properties") {
process_json5_files(target_name) { process_json5_files(target_name) {
script = invoker.script script = invoker.script
in_files = [ "css/CSSProperties.json5" ] in_files = [
"css/CSSProperties.json5",
"css/ComputedStyleFieldAliases.json5",
]
if (defined(invoker.in_files)) { if (defined(invoker.in_files)) {
in_files += invoker.in_files in_files += invoker.in_files
} }
......
...@@ -37,7 +37,7 @@ inline {{enum_name}} cssValueIDToPlatformEnumGenerated(CSSValueID v) { ...@@ -37,7 +37,7 @@ inline {{enum_name}} cssValueIDToPlatformEnumGenerated(CSSValueID v) {
{% endfor %} {% endfor %}
default: default:
NOTREACHED(); NOTREACHED();
return {{enum_name}}::{{mapping['default_value']}}; return {{mapping['default_value']}};
} }
} }
......
...@@ -469,7 +469,6 @@ css_properties("make_core_generated_computed_style_base") { ...@@ -469,7 +469,6 @@ css_properties("make_core_generated_computed_style_base") {
"css/CSSValueKeywords.json5", "css/CSSValueKeywords.json5",
"css/CSSPropertiesRanking.json5", "css/CSSPropertiesRanking.json5",
"css/CSSGroupConfig.json5", "css/CSSGroupConfig.json5",
"css/ComputedStyleFieldAliases.json5",
] ]
other_inputs = [ other_inputs = [
"../build/scripts/templates/fields/field.tmpl", "../build/scripts/templates/fields/field.tmpl",
...@@ -517,14 +516,11 @@ css_properties("make_core_generated_css_property_api_baseclass") { ...@@ -517,14 +516,11 @@ css_properties("make_core_generated_css_property_api_baseclass") {
} }
# TODO(shend): Need a better way to specify generated output files # TODO(shend): Need a better way to specify generated output files
code_generator("make_core_generated_css_property_apis") { css_properties("make_core_generated_css_property_apis") {
script = script =
"../build/scripts/core/css/properties/make_css_property_api_headers.py" "../build/scripts/core/css/properties/make_css_property_api_headers.py"
json_inputs = [ in_files = [ "css/properties/CSSPropertyAPIMethods.json5" ]
"css/CSSProperties.json5", other_inputs = [ "../build/scripts/core/css/properties/templates/CSSPropertyAPISubclass.h.tmpl" ]
"css/properties/CSSPropertyAPIMethods.json5",
]
templates = [ "../build/scripts/core/css/properties/templates/CSSPropertyAPISubclass.h.tmpl" ]
outputs = [ outputs = [
"$blink_core_output_dir/css/properties/CSSPropertyAPIAlignItems.h", "$blink_core_output_dir/css/properties/CSSPropertyAPIAlignItems.h",
"$blink_core_output_dir/css/properties/CSSPropertyAPIAlignOrJustifyContent.h", "$blink_core_output_dir/css/properties/CSSPropertyAPIAlignOrJustifyContent.h",
...@@ -814,14 +810,12 @@ code_generator("make_core_generated_media_features") { ...@@ -814,14 +810,12 @@ code_generator("make_core_generated_media_features") {
] ]
} }
code_generator("make_core_generated_style_property_shorthand") { css_properties("make_core_generated_style_property_shorthand") {
script = "../build/scripts/core/css/make_style_shorthands.py" script = "../build/scripts/core/css/make_style_shorthands.py"
json_inputs = [ "css/CSSProperties.json5" ] other_inputs = [
templates = [
"../build/scripts/core/css/templates/StylePropertyShorthand.cpp.tmpl", "../build/scripts/core/css/templates/StylePropertyShorthand.cpp.tmpl",
"../build/scripts/core/css/templates/StylePropertyShorthand.h.tmpl", "../build/scripts/core/css/templates/StylePropertyShorthand.h.tmpl",
] ]
other_inputs = [ "../build/scripts/core/css/css_properties.py" ]
outputs = [ outputs = [
"$blink_core_output_dir/StylePropertyShorthand.cpp", "$blink_core_output_dir/StylePropertyShorthand.cpp",
"$blink_core_output_dir/StylePropertyShorthand.h", "$blink_core_output_dir/StylePropertyShorthand.h",
...@@ -842,10 +836,9 @@ css_properties("make_core_generated_style_builder") { ...@@ -842,10 +836,9 @@ css_properties("make_core_generated_style_builder") {
] ]
} }
code_generator("make_core_generated_cssom_types") { css_properties("make_core_generated_cssom_types") {
script = "../build/scripts/core/css/make_cssom_types.py" script = "../build/scripts/core/css/make_cssom_types.py"
json_inputs = [ "css/CSSProperties.json5" ] other_inputs = [
templates = [
"../build/scripts/core/css/templates/CSSOMKeywords.cpp.tmpl", "../build/scripts/core/css/templates/CSSOMKeywords.cpp.tmpl",
"../build/scripts/core/css/templates/CSSOMTypes.cpp.tmpl", "../build/scripts/core/css/templates/CSSOMTypes.cpp.tmpl",
] ]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment