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, }
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]))
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
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'], )
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)