Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(166)

Side by Side Diff: third_party/WebKit/Source/build/scripts/make_computed_style_base.py

Issue 2938553002: Refactor make_computed_style_base.py Field class to link to a Group. (Closed)
Patch Set: Rebase Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | third_party/WebKit/Source/build/scripts/templates/fields/external.tmpl » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright 2016 The Chromium Authors. All rights reserved. 2 # Copyright 2016 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 import math 6 import math
7 import sys 7 import sys
8 8
9 import json5_generator 9 import json5_generator
10 import template_expander 10 import template_expander
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 self.fields = fields 66 self.fields = fields
67 self.type_name = class_name(join_name('style', name, 'data')) 67 self.type_name = class_name(join_name('style', name, 'data'))
68 self.member_name = class_member_name(join_name(name, 'data')) 68 self.member_name = class_member_name(join_name(name, 'data'))
69 self.num_32_bit_words_for_bit_fields = _num_32_bit_words_for_bit_fields( 69 self.num_32_bit_words_for_bit_fields = _num_32_bit_words_for_bit_fields(
70 field for field in fields if field.is_bit_field 70 field for field in fields if field.is_bit_field
71 ) 71 )
72 72
73 # Recursively get all the fields in the subgroups as well 73 # Recursively get all the fields in the subgroups as well
74 self.all_fields = _flatten_list(subgroup.all_fields for subgroup in subg roups) + fields 74 self.all_fields = _flatten_list(subgroup.all_fields for subgroup in subg roups) + fields
75 75
76 # Link group
77 for field in fields:
78 field.group = self
79
76 80
77 class DiffGroup(object): 81 class DiffGroup(object):
78 """Represents a group of expressions and subgroups that need to be diffed 82 """Represents a group of expressions and subgroups that need to be diffed
79 for a function in ComputedStyle. 83 for a function in ComputedStyle.
80 84
81 Attributes: 85 Attributes:
82 subgroups: List of DiffGroup instances that are stored as subgroups unde r this group. 86 subgroups: List of DiffGroup instances that are stored as subgroups unde r this group.
83 expressions: List of expression that are on this group that need to be d iffed. 87 expressions: List of expression that are on this group that need to be d iffed.
84 """ 88 """
85 def __init__(self, group_name): 89 def __init__(self, group_name):
86 self.group_name = group_name 90 self.group_name = group_name
87 self.subgroups = [] 91 self.subgroups = []
92 self.fields = []
88 self.expressions = [] 93 self.expressions = []
89 self.predicates = [] 94 self.predicates = []
90 95
91 96
92 class Field(object): 97 class Field(object):
93 """ 98 """
94 The generated ComputedStyle object is made up of a series of Fields. 99 The generated ComputedStyle object is made up of a series of Fields.
95 Each Field has a name, size, type, etc, and a bunch of attributes to 100 Each Field has a name, size, type, etc, and a bunch of attributes to
96 determine which methods it will be used in. 101 determine which methods it will be used in.
97 102
98 A Field also has enough information to use any storage type in C++, such as 103 A Field also has enough information to use any storage type in C++, such as
99 regular member variables, or more complex storage like vectors or hashmaps. 104 regular member variables, or more complex storage like vectors or hashmaps.
100 Almost all properties will have at least one Field, often more than one. 105 Almost all properties will have at least one Field, often more than one.
101 106
102 Most attributes in this class correspond to parameters in CSSProperties.json 5. 107 Most attributes in this class correspond to parameters in CSSProperties.json 5.
103 See that file for a more detailed explanation of each attribute. 108 See that file for a more detailed explanation of each attribute.
104 109
105 Attributes: 110 Attributes:
106 field_role: The semantic role of the field. Can be: 111 field_role: The semantic role of the field. Can be:
107 - 'property': for fields that store CSS properties 112 - 'property': for fields that store CSS properties
108 - 'inherited_flag': for single-bit flags that store whether a proper ty is 113 - 'inherited_flag': for single-bit flags that store whether a proper ty is
109 inherited by this style or set explicitly 114 inherited by this style or set explicitly
110 name_for_methods: String used to form the names of getters and setters. 115 name_for_methods: String used to form the names of getters and setters.
111 Should be in upper camel case. 116 Should be in upper camel case.
112 property_name: Name of the property that the field is part of. 117 property_name: Name of the property that the field is part of.
113 type_name: Name of the C++ type exposed by the generated interface (e.g. EClear, int). 118 type_name: Name of the C++ type exposed by the generated interface (e.g. EClear, int).
114 wrapper_pointer_name: Name of the pointer type that wraps this field (e. g. RefPtr). 119 wrapper_pointer_name: Name of the pointer type that wraps this field (e. g. RefPtr).
115 field_template: Determines the interface generated for the field. Can be one of: 120 field_template: Determines the interface generated for the field. Can be one of:
116 keyword, flag, or monotonic_flag. 121 keyword, flag, or monotonic_flag.
117 field_group: The name of the group that this field is inside.
118 size: Number of bits needed for storage. 122 size: Number of bits needed for storage.
119 default_value: Default value for this field when it is first initialized . 123 default_value: Default value for this field when it is first initialized .
120 """ 124 """
121 125
122 def __init__(self, field_role, name_for_methods, property_name, type_name, w rapper_pointer_name, 126 def __init__(self, field_role, name_for_methods, property_name, type_name, w rapper_pointer_name,
123 field_template, field_group, size, default_value, custom_copy, custom_compare, 127 field_template, size, default_value, custom_copy, custom_compar e,
124 getter_method_name, setter_method_name, initial_method_name, ** kwargs): 128 getter_method_name, setter_method_name, initial_method_name, ** kwargs):
125 """Creates a new field.""" 129 """Creates a new field."""
126 self.name = class_member_name(name_for_methods) 130 self.name = class_member_name(name_for_methods)
127 self.property_name = property_name 131 self.property_name = property_name
128 self.type_name = type_name 132 self.type_name = type_name
129 self.wrapper_pointer_name = wrapper_pointer_name 133 self.wrapper_pointer_name = wrapper_pointer_name
130 self.alignment_type = self.wrapper_pointer_name or self.type_name 134 self.alignment_type = self.wrapper_pointer_name or self.type_name
131 self.field_template = field_template 135 self.field_template = field_template
132 self.group_name = field_group
133 self.group_member_name = class_member_name(join_name(field_group, 'data' )) if field_group else None
134 self.size = size 136 self.size = size
135 self.default_value = default_value 137 self.default_value = default_value
136 self.custom_copy = custom_copy 138 self.custom_copy = custom_copy
137 self.custom_compare = custom_compare 139 self.custom_compare = custom_compare
140 self.group = None
138 141
139 # Field role: one of these must be true 142 # Field role: one of these must be true
140 self.is_property = field_role == 'property' 143 self.is_property = field_role == 'property'
141 self.is_inherited_flag = field_role == 'inherited_flag' 144 self.is_inherited_flag = field_role == 'inherited_flag'
142 assert (self.is_property, self.is_inherited_flag).count(True) == 1, \ 145 assert (self.is_property, self.is_inherited_flag).count(True) == 1, \
143 'Field role has to be exactly one of: property, inherited_flag' 146 'Field role has to be exactly one of: property, inherited_flag'
144 147
145 if not self.is_inherited_flag: 148 if not self.is_inherited_flag:
146 self.is_inherited = kwargs.pop('inherited') 149 self.is_inherited = kwargs.pop('inherited')
147 self.is_independent = kwargs.pop('independent') 150 self.is_independent = kwargs.pop('independent')
148 assert self.is_inherited or not self.is_independent, 'Only inherited fields can be independent' 151 assert self.is_inherited or not self.is_independent, 'Only inherited fields can be independent'
149 152
150 self.is_inherited_method_name = method_name(join_name(name_for_metho ds, 'is inherited')) 153 self.is_inherited_method_name = method_name(join_name(name_for_metho ds, 'is inherited'))
151 154
152 # Method names 155 # Method names
153 # TODO(nainar): Method name generation is inconsistent. Fix. 156 # TODO(nainar): Method name generation is inconsistent. Fix.
154 self.getter_method_name = getter_method_name 157 self.getter_method_name = getter_method_name
155 self.setter_method_name = setter_method_name 158 self.setter_method_name = setter_method_name
156 self.internal_getter_method_name = method_name(join_name(self.name, 'Int ernal')) 159 self.internal_getter_method_name = method_name(join_name(self.name, 'Int ernal'))
157 self.internal_mutable_method_name = method_name(join_name('Mutable', nam e_for_methods, 'Internal')) 160 self.internal_mutable_method_name = method_name(join_name('Mutable', nam e_for_methods, 'Internal'))
158 self.internal_setter_method_name = method_name(join_name(setter_method_n ame, 'Internal')) 161 self.internal_setter_method_name = method_name(join_name(setter_method_n ame, 'Internal'))
159 self.initial_method_name = initial_method_name 162 self.initial_method_name = initial_method_name
160 self.resetter_method_name = method_name(join_name('Reset', name_for_meth ods)) 163 self.resetter_method_name = method_name(join_name('Reset', name_for_meth ods))
161 if self.group_name:
162 self.getter_expression = self.group_member_name + '->' + class_membe r_name(self.name)
163 else:
164 self.getter_expression = class_member_name(self.name)
165 164
166 # If the size of the field is not None, it means it is a bit field 165 # If the size of the field is not None, it means it is a bit field
167 self.is_bit_field = self.size is not None 166 self.is_bit_field = self.size is not None
168 167
169 assert len(kwargs) == 0, 'Unexpected arguments provided to Field: ' + st r(kwargs) 168 assert len(kwargs) == 0, 'Unexpected arguments provided to Field: ' + st r(kwargs)
170 169
171 170
172 def _get_include_paths(properties): 171 def _get_include_paths(properties):
173 """ 172 """
174 Get a list of paths that need to be included for ComputedStyleBase. 173 Get a list of paths that need to be included for ComputedStyleBase.
175 """ 174 """
176 include_paths = set() 175 include_paths = set()
177 for property_ in properties: 176 for property_ in properties:
178 include_paths.update(property_['include_paths']) 177 include_paths.update(property_['include_paths'])
179 return list(sorted(include_paths)) 178 return list(sorted(include_paths))
180 179
181 180
182 def _group_fields(fields): 181 def _create_groups(properties):
183 """Groups a list of fields by their group_name and returns the root group."" " 182 """Groups a list of fields by their group_name and returns the root group."" "
184 groups = defaultdict(list) 183 groups = defaultdict(list)
185 for field in fields: 184 for property_ in properties:
186 groups[field.group_name].append(field) 185 groups[property_['field_group']].extend(_create_fields(property_))
187 186
188 no_group = groups.pop(None) 187 no_group = groups.pop(None)
189 subgroups = [Group(group_name, [], _reorder_fields(fields)) for group_name, fields in groups.items()] 188 subgroups = [Group(group_name, [], _reorder_fields(fields)) for group_name, fields in groups.items()]
190 return Group('', subgroups=subgroups, fields=_reorder_fields(no_group)) 189 return Group('', subgroups=subgroups, fields=_reorder_fields(no_group))
191 190
192 191
193 def _create_diff_groups_map(diff_function_inputs, root_group): 192 def _create_diff_groups_map(diff_function_inputs, root_group):
194 diff_functions_map = {} 193 diff_functions_map = {}
195 for entry in diff_function_inputs: 194 for entry in diff_function_inputs:
196 diff_functions_map[entry['name']] = _create_diff_groups(entry['fields_to _diff'], 195 diff_functions_map[entry['name']] = _create_diff_groups(entry['fields_to _diff'],
(...skipping 10 matching lines...) Expand all
207 206
208 def _create_diff_groups(fields_to_diff, methods_to_diff, predicates_to_test, roo t_group): 207 def _create_diff_groups(fields_to_diff, methods_to_diff, predicates_to_test, roo t_group):
209 diff_group = DiffGroup(root_group.member_name) 208 diff_group = DiffGroup(root_group.member_name)
210 field_dependencies = _list_field_dependencies(methods_to_diff + predicates_t o_test) 209 field_dependencies = _list_field_dependencies(methods_to_diff + predicates_t o_test)
211 for subgroup in root_group.subgroups: 210 for subgroup in root_group.subgroups:
212 if any(field.property_name in (fields_to_diff + field_dependencies) for field in subgroup.all_fields): 211 if any(field.property_name in (fields_to_diff + field_dependencies) for field in subgroup.all_fields):
213 diff_group.subgroups.append(_create_diff_groups(fields_to_diff, meth ods_to_diff, predicates_to_test, subgroup)) 212 diff_group.subgroups.append(_create_diff_groups(fields_to_diff, meth ods_to_diff, predicates_to_test, subgroup))
214 for entry in fields_to_diff: 213 for entry in fields_to_diff:
215 for field in root_group.fields: 214 for field in root_group.fields:
216 if not field.is_inherited_flag and entry == field.property_name: 215 if not field.is_inherited_flag and entry == field.property_name:
217 diff_group.expressions.append(field.getter_expression) 216 diff_group.fields.append(field)
218 for entry in methods_to_diff: 217 for entry in methods_to_diff:
219 for field in root_group.fields: 218 for field in root_group.fields:
220 if not field.is_inherited_flag and field.property_name in entry['fie ld_dependencies']: 219 if not field.is_inherited_flag and field.property_name in entry['fie ld_dependencies']:
221 diff_group.expressions.append(entry['method']) 220 diff_group.expressions.append(entry['method'])
222 for entry in predicates_to_test: 221 for entry in predicates_to_test:
223 for field in root_group.fields: 222 for field in root_group.fields:
224 if not field.is_inherited_flag and field.property_name in entry['fie ld_dependencies']: 223 if not field.is_inherited_flag and field.property_name in entry['fie ld_dependencies']:
225 diff_group.predicates.append(entry['predicate']) 224 diff_group.predicates.append(entry['predicate'])
226 return diff_group 225 return diff_group
227 226
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 288
290 return Field( 289 return Field(
291 'property', 290 'property',
292 name_for_methods, 291 name_for_methods,
293 property_name=property_['name'], 292 property_name=property_['name'],
294 inherited=property_['inherited'], 293 inherited=property_['inherited'],
295 independent=property_['independent'], 294 independent=property_['independent'],
296 type_name=type_name, 295 type_name=type_name,
297 wrapper_pointer_name=property_['wrapper_pointer_name'], 296 wrapper_pointer_name=property_['wrapper_pointer_name'],
298 field_template=property_['field_template'], 297 field_template=property_['field_template'],
299 field_group=property_['field_group'],
300 size=size, 298 size=size,
301 default_value=default_value, 299 default_value=default_value,
302 custom_copy=property_['custom_copy'], 300 custom_copy=property_['custom_copy'],
303 custom_compare=property_['custom_compare'], 301 custom_compare=property_['custom_compare'],
304 getter_method_name=property_['getter'], 302 getter_method_name=property_['getter'],
305 setter_method_name=property_['setter'], 303 setter_method_name=property_['setter'],
306 initial_method_name=property_['initial'], 304 initial_method_name=property_['initial'],
307 ) 305 )
308 306
309 307
310 def _create_inherited_flag_field(property_): 308 def _create_inherited_flag_field(property_):
311 """ 309 """
312 Create the field used for an inheritance fast path from an independent CSS p roperty, 310 Create the field used for an inheritance fast path from an independent CSS p roperty,
313 and return the Field object. 311 and return the Field object.
314 """ 312 """
315 name_for_methods = join_name(property_['name_for_methods'], 'is inherited') 313 name_for_methods = join_name(property_['name_for_methods'], 'is inherited')
316 return Field( 314 return Field(
317 'inherited_flag', 315 'inherited_flag',
318 name_for_methods, 316 name_for_methods,
319 property_name=property_['name'], 317 property_name=property_['name'],
320 type_name='bool', 318 type_name='bool',
321 wrapper_pointer_name=None, 319 wrapper_pointer_name=None,
322 field_template='primitive', 320 field_template='primitive',
323 field_group=property_['field_group'],
324 size=1, 321 size=1,
325 default_value='true', 322 default_value='true',
326 custom_copy=False, 323 custom_copy=False,
327 custom_compare=False, 324 custom_compare=False,
328 getter_method_name=method_name(name_for_methods), 325 getter_method_name=method_name(name_for_methods),
329 setter_method_name=method_name(join_name('set', name_for_methods)), 326 setter_method_name=method_name(join_name('set', name_for_methods)),
330 initial_method_name=method_name(join_name('initial', name_for_methods)), 327 initial_method_name=method_name(join_name('initial', name_for_methods)),
331 ) 328 )
332 329
333 330
334 def _create_fields(properties): 331 def _create_fields(property_):
335 """ 332 """
336 Create ComputedStyle fields from properties and return a list of Field objec ts. 333 Create ComputedStyle fields from a property and return a list of Field objec ts.
337 """ 334 """
338 fields = [] 335 fields = []
339 for property_ in properties: 336 # Only generate properties that have a field template
340 # Only generate properties that have a field template 337 if property_['field_template'] is not None:
341 if property_['field_template'] is not None: 338 # If the property is independent, add the single-bit sized isInherited f lag
342 # If the property is independent, add the single-bit sized isInherit ed flag 339 # to the list of Fields as well.
343 # to the list of Fields as well. 340 if property_['independent']:
344 if property_['independent']: 341 fields.append(_create_inherited_flag_field(property_))
345 fields.append(_create_inherited_flag_field(property_))
346 342
347 fields.append(_create_property_field(property_)) 343 fields.append(_create_property_field(property_))
348 344
349 return fields 345 return fields
350 346
351 347
352 def _reorder_bit_fields(bit_fields): 348 def _reorder_bit_fields(bit_fields):
353 # Since fields cannot cross word boundaries, in order to minimize 349 # Since fields cannot cross word boundaries, in order to minimize
354 # padding, group fields into buckets so that as many buckets as possible 350 # padding, group fields into buckets so that as many buckets as possible
355 # are exactly 32 bits. Although this greedy approach may not always 351 # are exactly 32 bits. Although this greedy approach may not always
356 # produce the optimal solution, we add a static_assert to the code to 352 # produce the optimal solution, we add a static_assert to the code to
357 # ensure ComputedStyleBase results in the expected size. If that 353 # ensure ComputedStyleBase results in the expected size. If that
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 default_parameters=self.json5_file.parameters 419 default_parameters=self.json5_file.parameters
424 ).name_dictionaries 420 ).name_dictionaries
425 421
426 for property_ in extra_fields: 422 for property_ in extra_fields:
427 make_style_builder.apply_property_naming_defaults(property_) 423 make_style_builder.apply_property_naming_defaults(property_)
428 424
429 all_properties = css_properties + extra_fields 425 all_properties = css_properties + extra_fields
430 426
431 self._generated_enums = _create_enums(all_properties) 427 self._generated_enums = _create_enums(all_properties)
432 428
433 all_fields = _create_fields(all_properties)
434
435 # Organise fields into a tree structure where the root group 429 # Organise fields into a tree structure where the root group
436 # is ComputedStyleBase. 430 # is ComputedStyleBase.
437 self._root_group = _group_fields(all_fields) 431 self._root_group = _create_groups(all_properties)
438 self._diff_functions_map = _create_diff_groups_map(json5_generator.Json5 File.load_from_files( 432 self._diff_functions_map = _create_diff_groups_map(json5_generator.Json5 File.load_from_files(
439 [json5_file_paths[2]] 433 [json5_file_paths[2]]
440 ).name_dictionaries, self._root_group) 434 ).name_dictionaries, self._root_group)
441 435
442 self._include_paths = _get_include_paths(all_properties) 436 self._include_paths = _get_include_paths(all_properties)
443 self._outputs = { 437 self._outputs = {
444 'ComputedStyleBase.h': self.generate_base_computed_style_h, 438 'ComputedStyleBase.h': self.generate_base_computed_style_h,
445 'ComputedStyleBase.cpp': self.generate_base_computed_style_cpp, 439 'ComputedStyleBase.cpp': self.generate_base_computed_style_cpp,
446 'ComputedStyleBaseConstants.h': self.generate_base_computed_style_co nstants, 440 'ComputedStyleBaseConstants.h': self.generate_base_computed_style_co nstants,
447 } 441 }
(...skipping 20 matching lines...) Expand all
468 462
469 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') 463 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl')
470 def generate_base_computed_style_constants(self): 464 def generate_base_computed_style_constants(self):
471 return { 465 return {
472 'properties': self._properties, 466 'properties': self._properties,
473 'enums': self._generated_enums, 467 'enums': self._generated_enums,
474 } 468 }
475 469
476 if __name__ == '__main__': 470 if __name__ == '__main__':
477 json5_generator.Maker(ComputedStyleBaseWriter).main() 471 json5_generator.Maker(ComputedStyleBaseWriter).main()
OLDNEW
« no previous file with comments | « no previous file | third_party/WebKit/Source/build/scripts/templates/fields/external.tmpl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698