Exemplo n.º 1
0
    def __init__(self, json5_file_paths, output_dir):
        super(AtRuleNamesWriter, self).__init__(json5_file_paths, output_dir)

        self._outputs = {
            'at_rule_descriptors.h': self.generate_header,
            'at_rule_descriptors.cc': self.generate_implementation
        }

        self._descriptors = self.json5_file.name_dictionaries
        self._character_offsets = []

        # AtRuleDescriptorID::Invalid is 0.
        first_descriptor_id = 1
        # Aliases are resolved immediately at parse time, and thus don't appear
        # in the enum.
        self._descriptors_count = len(self._descriptors) + first_descriptor_id
        chars_used = 0
        self._longest_name_length = 0
        for offset, descriptor in enumerate(self._descriptors):
            descriptor['upper_camel_name'] = upper_camel_case(
                descriptor['name'])
            descriptor['enum_value'] = first_descriptor_id + offset
            self._character_offsets.append(chars_used)
            chars_used += len(descriptor['name'])
            self._longest_name_length = max(len(descriptor['name']),
                                            len(descriptor['alias']),
                                            self._longest_name_length)
Exemplo n.º 2
0
def apply_property_naming_defaults(property_):
    def set_if_none(property_, key, value):
        if property_[key] is None:
            property_[key] = value

    # TODO(shend): Use name_utilities for manipulating names.
    # TODO(shend): Rearrange the code below to separate assignment and set_if_none
    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_['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'] = not property_['use_handlers_for'] and not property_['longhands'] \
        and not property_['direction_aware'] and not property_['builder_skip'] \
        and property_['is_property']
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'] \
        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'
Exemplo n.º 4
0
def apply_property_naming_defaults(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'] = \
        not property_['use_handlers_for'] \
        and not property_['longhands'] \
        and not property_['direction_aware'] \
        and not property_['builder_skip'] \
        and property_['is_property']
    # Functions should only be used in StyleBuilder if the CSSPropertyAPI
    # class is shared or not implemented yet (shared classes are denoted by
    # api_class = "some string").
    property_['use_api_in_stylebuilder'] = \
        property_['should_declare_functions'] \
        and not (property_['custom_initial'] or
                 property_['custom_inherit'] or
                 property_['custom_value']) \
        and property_['api_class'] \
        and isinstance(property_['api_class'], types.BooleanType)
Exemplo n.º 5
0
 def expand_aliases(self):
     for i, alias in enumerate(self._aliases):
         assert not alias['runtime_flag'], \
             "Property '{}' is an alias with a runtime_flag, "\
             "but runtime flags do not currently work for aliases.".format(
                 alias['name'])
         aliased_property = self._properties_by_id[
             enum_for_css_property(alias['alias_for'])]
         updated_alias = aliased_property.copy()
         updated_alias['name'] = alias['name']
         updated_alias['alias_for'] = alias['alias_for']
         updated_alias['aliased_property'] = aliased_property['upper_camel_name']
         updated_alias['property_id'] = enum_for_css_property_alias(
             alias['name'].original)
         updated_alias['enum_value'] = aliased_property['enum_value'] + \
             self._alias_offset
         updated_alias['upper_camel_name'] = upper_camel_case(alias['name'].original)
         self._aliases[i] = updated_alias
Exemplo n.º 6
0
    def __init__(self, file_paths):
        json5_generator.Writer.__init__(self, file_paths)

        # StylePropertyMetadata assumes that there are at most 1024 properties + aliases.
        self._alias_offset = 512
        # 0: CSSPropertyInvalid
        # 1: CSSPropertyApplyAtRule
        # 2: CSSPropertyVariable
        self._first_enum_value = 3

        properties = self.json5_file.name_dictionaries

        # Sort properties by priority, then alphabetically.
        for property in properties:
            check_property_parameters(property)
            # This order must match the order in CSSPropertyPriority.h.
            priority_numbers = {'Animation': 0, 'High': 1, 'Low': 2}
            priority = priority_numbers[property['priority']]
            name_without_leading_dash = property['name']
            if property['name'].startswith('-'):
                name_without_leading_dash = property['name'][1:]
            property['sorting_key'] = (priority, name_without_leading_dash)

        # Assert there are no key collisions.
        sorting_keys = [p['sorting_key'] for p in properties]
        assert len(sorting_keys) == len(set(sorting_keys)), \
            ('Collision detected - two properties have the same name and priority, '
             'a potentially non-deterministic ordering can occur.')
        properties.sort(key=lambda p: p['sorting_key'])

        self._aliases = [
            property for property in properties if property['alias_for']
        ]
        properties = [
            property for property in properties if not property['alias_for']
        ]

        assert (
            self._first_enum_value + len(properties) < self._alias_offset), (
                'Property aliasing expects there are under %d properties.' %
                self._alias_offset)

        for property in properties:
            assert property['is_descriptor'] or property['is_property'], \
                property['name'] + ' must be either a property, a descriptor' +\
                ' 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['is_internal'] = property['name'].startswith('-internal-')

        self._properties_including_aliases = properties
        self._properties = {
            property['property_id']: property
            for property in properties
        }

        # The generated code will only work with at most one alias per property.
        assert len({property['alias_for']
                    for property in self._aliases}) == len(self._aliases)

        # Check that alias_for is not being used with a runtime flag.
        for property_ in self._aliases:
            assert not property_['runtime_flag'], \
                ("Property '" + property_['name'] + "' is an alias with a runtime_flag, "
                 "but runtime flags do not currently work for aliases.")

        # Update property aliases to include the fields of the property being aliased.
        for i, alias in enumerate(self._aliases):
            aliased_property = self._properties[enum_for_css_property(
                alias['alias_for'])]
            updated_alias = aliased_property.copy()
            updated_alias['name'] = alias['name']
            updated_alias['alias_for'] = alias['alias_for']
            updated_alias['property_id'] = enum_for_css_property_alias(
                alias['name'])
            updated_alias['enum_value'] = aliased_property[
                'enum_value'] + self._alias_offset
            updated_alias['upper_camel_name'] = upper_camel_case(alias['name'])
            updated_alias['lower_camel_name'] = lower_camel_case(alias['name'])
            self._aliases[i] = updated_alias
        self._properties_including_aliases += self._aliases

        self.last_unresolved_property_id = max(
            property["enum_value"]
            for property in self._properties_including_aliases)
Exemplo n.º 7
0
    def expand_parameters(self, property_):
        def set_if_none(property_, key, value):
            if key not in property_ or property_[key] is None:
                property_[key] = value

        # Basic info.
        name = property_['name'].original
        property_['property_id'] = enum_for_css_property(name)
        property_['upper_camel_name'] = upper_camel_case(name)
        property_['is_internal'] = name.startswith('-internal-')
        method_name = property_['name_for_methods']
        if not method_name:
            method_name = upper_camel_case(name).replace('Webkit', '')
        set_if_none(property_, 'inherited', False)

        # Initial function, Getters and Setters for ComputedStyle.
        property_['initial'] = 'Initial' + method_name
        simple_type_name = str(property_['type_name']).split('::')[-1]
        set_if_none(property_, 'name_for_methods', method_name)
        set_if_none(property_, 'type_name', 'E' + method_name)
        set_if_none(
            property_,
            'getter',
            method_name if simple_type_name != method_name else 'Get' + method_name)
        set_if_none(property_, 'setter', 'Set' + method_name)
        if property_['inherited']:
            property_['is_inherited_setter'] = 'Set' + method_name + 'IsInherited'

        # Figure out whether we should generate style builder implementations.
        for x in ['initial', 'inherit', 'value']:
            suppressed = x in property_['style_builder_custom_functions']
            property_['style_builder_generate_%s' % x] = not suppressed

        # Expand StyleBuilderConverter params where necessary.
        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 property_['field_template']:
            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

            property_['unwrapped_type_name'] = property_['type_name']
            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)

        # Default values for extra parameters in ComputedStyleExtraFields.json5.
        set_if_none(property_, 'custom_copy', False)
        set_if_none(property_, 'custom_compare', False)
        set_if_none(property_, 'mutable', False)