Esempio n. 1
0
    def generate_css_value_mappings(self):
        mappings = {}
        include_paths = set()
        css_values_dictionary = json5_generator.Json5File.load_from_files(
            [self.css_values_dictionary_file],
            default_parameters=self.default_parameters
        ).name_dictionaries
        name_to_position_dictionary = dict(zip([x['name'].original for x in css_values_dictionary],
                                               range(len(css_values_dictionary))))

        for property_ in self.css_properties.properties_including_aliases:
            include_paths.update(property_['include_paths'])
            if property_['field_template'] == 'multi_keyword':
                mappings[property_['type_name']] = {
                    'default_value': property_['default_value'],
                    'mapping': [(enum_value_name(k), enum_for_css_keyword(k)) for k in property_['keywords']],
                }
            elif property_['field_template'] == 'keyword':
                enum_pair_list, enum_segment, p_segment = _find_enum_longest_continuous_segment(
                    property_, name_to_position_dictionary)
                mappings[property_['type_name']] = {
                    'default_value': property_['default_value'],
                    'mapping': enum_pair_list,
                    'segment': enum_segment,
                    'longest_segment_length': p_segment[1] - p_segment[0],
                    'start_segment': enum_pair_list[p_segment[0]],
                    'end_segment': enum_pair_list[p_segment[1] - 1],
                }

        return {
            'include_paths': list(sorted(include_paths)),
            'input_files': self._input_files,
            'mappings': mappings,
        }
Esempio n. 2
0
def _find_enum_longest_continuous_segment(property_, name_to_position_dictionary):
    """Find the longest continuous segment in the list of keywords
    Finding the continuous segment will allows us to do the subtraction
    between keywords so that the distance between 2 keywords in this
    enum is equal to the distance of corresponding keywords in another
    enum.

    Step 1:
        Convert keyword enums into number.
        Sort and find all continuous segment in the list of enums.

    Step 2:
        Get the longest segment.

    Step 3:
        Compose a list of keyword enums and their respective numbers
        in the sorted order.

    Step 4:
        Build the switch case statements of other enums not in the
        segment. Enums in the segment will be computed in default clause.
    """
    property_enum_order = range(len(property_['keywords']))
    css_enum_order = [name_to_position_dictionary[x] for x in property_['keywords']]
    enum_pair_list = zip(css_enum_order, property_enum_order)
    enum_segment, enum_pair_list = _find_continuous_segment(enum_pair_list)
    longest_segment = _find_largest_segment(enum_segment)

    enum_pair_list = [
        (enum_value_name(property_['keywords'][x[1]]), x[1],
         enum_for_css_keyword(property_['keywords'][x[1]]), x[0]) for x in enum_pair_list
    ]
    return enum_pair_list, enum_segment, longest_segment
def _create_property_field(property_):
    """
    Create a property field.
    """
    name_for_methods = property_['name_for_methods']

    assert property_['default_value'] is not None, \
        ('MakeComputedStyleBase requires an default value for all fields, none specified '
         'for property ' + property_['name'])

    if property_['field_template'] == 'keyword':
        type_name = property_['type_name']
        default_value = type_name + '::' + enum_value_name(property_['default_value'])
        size = int(math.ceil(math.log(len(property_['keywords']), 2)))
    elif property_['field_template'] == 'storage_only':
        # 'storage_only' fields need to specify a size, type_name and default_value
        type_name = property_['type_name']
        default_value = property_['default_value']
        size = property_['field_size']
    elif property_['field_template'] == 'external':
        type_name = property_['type_name']
        default_value = property_['default_value']
        size = None
    elif property_['field_template'] == 'primitive':
        type_name = property_['type_name']
        default_value = property_['default_value']
        size = 1 if type_name == 'bool' else None  # pack bools with 1 bit.
    else:
        assert property_['field_template'] in ('monotonic_flag',)
        type_name = 'bool'
        default_value = 'false'
        size = 1

    if property_['wrapper_pointer_name']:
        assert property_['field_template'] == 'storage_only'
        type_name = '{}<{}>'.format(property_['wrapper_pointer_name'], type_name)

    return Field(
        'property',
        name_for_methods,
        property_name=property_['name'],
        inherited=property_['inherited'],
        independent=property_['independent'],
        type_name=type_name,
        wrapper_pointer_name=property_['wrapper_pointer_name'],
        field_template=property_['field_template'],
        field_group=property_['field_group'],
        size=size,
        default_value=default_value,
        has_custom_compare_and_copy=property_['has_custom_compare_and_copy'],
        getter_method_name=property_['getter'],
        setter_method_name=property_['setter'],
        initial_method_name=property_['initial'],
    )
    def generate_css_value_mappings(self):
        mappings = {}
        include_paths = []
        for property_ in self._properties.values():
            if property_['field_template'] == 'keyword':
                if property_['field_type_path']:
                    type_name = property_['field_type_path'].split('/')[-1]
                    include_paths.append(property_['field_type_path'] + '.h')
                else:
                    type_name = property_['type_name']

                mappings[type_name] = {
                    'default_value':
                    enum_value_name(property_['default_value']),
                    'mapping': [(enum_value_name(k), enum_for_css_keyword(k))
                                for k in property_['keywords']],
                }

        return {
            'include_paths': list(sorted(include_paths)),
            'mappings': mappings,
        }
def _create_enums(properties):
    """
    Returns an OrderedDict of enums to be generated, enum name -> [list of enum values]
    """
    enums = {}
    for property_ in properties:
        # Only generate enums for keyword properties that use the default field_type_path.
        if property_['field_template'] == 'keyword' and property_['field_type_path'] is None:
            enum_name = property_['type_name']
            enum_values = [enum_value_name(k) for k in property_['keywords']]

            if enum_name in enums:
                # There's an enum with the same name, check if the enum values are the same
                assert set(enums[enum_name]) == set(enum_values), \
                    ("'" + property_['name'] + "' can't have type_name '" + enum_name + "' "
                     "because it was used by a previous property, but with a different set of keywords. "
                     "Either give it a different name or ensure the keywords are the same.")

            enums[enum_name] = enum_values

    # Return the enums sorted by key (enum name)
    return OrderedDict(sorted(enums.items(), key=lambda t: t[0]))
Esempio n. 6
0
 def __init__(self, type_name, keywords, is_set):
     self.type_name = type_name
     self.values = [enum_value_name(keyword) for keyword in keywords]
     self.is_set = is_set
Esempio n. 7
0
def _create_property_field(property_, alias_dictionary):
    """
    Create a property field.
    """
    name_for_methods = property_['name_for_methods']

    assert property_['default_value'] is not None, \
        ('MakeComputedStyleBase requires an default value for all fields, none specified '
         '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']
        default_value = type_name + '::' + enum_value_name(
            property_['default_value'])
        assert property_['field_size'] is None, \
            ("'" + property_['name'] + "' is a keyword field, "
             "so it should not specify a field_size")
        size = int(math.ceil(math.log(len(property_['keywords']), 2)))
    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
    elif property_['field_template'] == 'external':
        type_name = property_['type_name']
        default_value = property_['default_value']
        size = None
    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.
    elif property_['field_template'] == 'pointer':
        type_name = property_['type_name']
        default_value = property_['default_value']
        size = None
    else:
        assert property_[
            'field_template'] == 'monotonic_flag', "Please put a valid value for field_template"
        type_name = 'bool'
        default_value = 'false'
        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(
        'property',
        name_for_methods,
        property_name=property_['name'],
        inherited=property_['inherited'],
        independent=property_['independent'],
        type_name=type_name,
        wrapper_pointer_name=property_['wrapper_pointer_name'],
        field_template=property_['field_template'],
        size=size,
        default_value=default_value,
        custom_copy=property_['custom_copy'],
        custom_compare=property_['custom_compare'],
        mutable=property_['mutable'],
        getter_method_name=property_['getter'],
        setter_method_name=property_['setter'],
        initial_method_name=property_['initial'],
        computed_style_custom_functions=property_[
            'computed_style_custom_functions'],
    )
def _create_property_field(property_):
    """
    Create a property field.
    """
    name_for_methods = property_['name_for_methods']

    assert property_['default_value'] is not None, \
        ('MakeComputedStyleBase requires an default value for all fields, none specified '
         'for property ' + property_['name'])

    if property_['field_template'] == 'keyword':
        type_name = property_['type_name']
        default_value = type_name + '::' + enum_value_name(
            property_['default_value'])
        assert property_['field_size'] is None, \
            ("'" + property_['name'] + "' is a keyword field, "
             "so it should not specify a field_size")
        size = int(math.ceil(math.log(len(property_['keywords']), 2)))
    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
    elif property_['field_template'] == 'storage_only':
        type_name = property_['type_name']
        default_value = property_['default_value']
        size = None
        if type_name == 'bool':
            size = 1
        elif len(property_["keywords"]) > 0 and len(
                property_["include_paths"]) == 0:
            # Assume that no property will ever have one keyword.
            assert len(
                property_['keywords']
            ) > 1, "There must be more than 1 keywords in a CSS property"
            # Each keyword is represented as a number and the number of bit
            # to represent the maximum number is calculated here
            size = int(math.ceil(math.log(len(property_['keywords']), 2)))
        else:
            size = property_["field_size"]
    elif property_['field_template'] == 'external':
        type_name = property_['type_name']
        default_value = property_['default_value']
        size = None
    elif property_['field_template'] == 'primitive':
        type_name = property_['type_name']
        default_value = property_['default_value']
        size = 1 if type_name == 'bool' else None  # pack bools with 1 bit.
    elif property_['field_template'] == 'pointer':
        type_name = property_['type_name']
        default_value = property_['default_value']
        size = None
    elif property_['field_template'] == '<length>':
        property_['field_template'] = 'external'
        property_['type_name'] = type_name = 'Length'
        default_value = property_['default_value']
        property_['include_paths'] = ["platform/Length.h"]
        size = None
    else:
        assert property_['field_template'] in ('monotonic_flag', )
        type_name = 'bool'
        default_value = 'false'
        size = 1

    if property_['wrapper_pointer_name']:
        assert property_['field_template'] in ['storage_only', 'pointer']
        if property_['field_template'] == 'storage_only':
            type_name = '{}<{}>'.format(property_['wrapper_pointer_name'],
                                        type_name)

    return Field(
        'property',
        name_for_methods,
        property_name=property_['name'],
        inherited=property_['inherited'],
        independent=property_['independent'],
        type_name=type_name,
        wrapper_pointer_name=property_['wrapper_pointer_name'],
        field_template=property_['field_template'],
        size=size,
        default_value=default_value,
        custom_copy=property_['custom_copy'],
        custom_compare=property_['custom_compare'],
        mutable=property_['mutable'],
        getter_method_name=property_['getter'],
        setter_method_name=property_['setter'],
        initial_method_name=property_['initial'],
        default_generated_functions=property_['default_generated_functions'],
    )
Esempio n. 9
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)