| OLD | NEW |
| 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 | |
| 8 | 7 |
| 9 import json5_generator | 8 import json5_generator |
| 10 import template_expander | 9 import template_expander |
| 11 import make_style_builder | 10 import make_style_builder |
| 12 | 11 |
| 13 from name_utilities import ( | 12 from name_utilities import ( |
| 14 enum_for_css_keyword, enum_type_name, enum_value_name, class_member_name, me
thod_name, | 13 enum_for_css_keyword, enum_type_name, enum_value_name, class_member_name, me
thod_name, |
| 15 class_name, join_name | 14 class_name, join_name |
| 16 ) | 15 ) |
| 17 from collections import defaultdict, OrderedDict | |
| 18 from itertools import chain | 16 from itertools import chain |
| 19 | 17 |
| 20 # Heuristic ordering of types from largest to smallest, used to sort fields by t
heir alignment sizes. | 18 # Heuristic ordering of types from largest to smallest, used to sort fields by t
heir alignment sizes. |
| 21 # Specifying the exact alignment sizes for each type is impossible because it's
platform specific, | 19 # Specifying the exact alignment sizes for each type is impossible because it's
platform specific, |
| 22 # so we define an ordering instead. | 20 # so we define an ordering instead. |
| 23 # The ordering comes from the data obtained in: | 21 # The ordering comes from the data obtained in: |
| 24 # https://codereview.chromium.org/2841413002 | 22 # https://codereview.chromium.org/2841413002 |
| 25 # TODO(shend): Put alignment sizes into code form, rather than linking to a CL w
hich may disappear. | 23 # TODO(shend): Put alignment sizes into code form, rather than linking to a CL w
hich may disappear. |
| 26 ALIGNMENT_ORDER = [ | 24 ALIGNMENT_ORDER = [ |
| 27 # Aligns like double | 25 # Aligns like double |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 and so on. | 100 and so on. |
| 103 """ | 101 """ |
| 104 group_path = [] | 102 group_path = [] |
| 105 current_group = self | 103 current_group = self |
| 106 while current_group.name: | 104 while current_group.name: |
| 107 group_path.insert(0, current_group) | 105 group_path.insert(0, current_group) |
| 108 current_group = current_group.parent | 106 current_group = current_group.parent |
| 109 return group_path | 107 return group_path |
| 110 | 108 |
| 111 | 109 |
| 110 class Enum(object): |
| 111 """Represents a generated enum in ComputedStyleBaseConstants.""" |
| 112 def __init__(self, type_name, keywords, is_set): |
| 113 self.type_name = type_name |
| 114 self.values = [enum_value_name(keyword) for keyword in keywords] |
| 115 self.is_set = is_set |
| 116 |
| 117 |
| 112 class DiffGroup(object): | 118 class DiffGroup(object): |
| 113 """Represents a group of expressions and subgroups that need to be diffed | 119 """Represents a group of expressions and subgroups that need to be diffed |
| 114 for a function in ComputedStyle. | 120 for a function in ComputedStyle. |
| 115 | 121 |
| 116 Attributes: | 122 Attributes: |
| 117 subgroups: List of DiffGroup instances that are stored as subgroups unde
r this group. | 123 subgroups: List of DiffGroup instances that are stored as subgroups unde
r this group. |
| 118 expressions: List of expression that are on this group that need to be d
iffed. | 124 expressions: List of expression that are on this group that need to be d
iffed. |
| 119 """ | 125 """ |
| 120 def __init__(self, group): | 126 def __init__(self, group): |
| 121 self.group = group | 127 self.group = group |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 diff_group.expressions.append(entry['method']) | 293 diff_group.expressions.append(entry['method']) |
| 288 for entry in predicates_to_test: | 294 for entry in predicates_to_test: |
| 289 for field in root_group.fields: | 295 for field in root_group.fields: |
| 290 if (not field.is_inherited_flag and field.property_name in entry['fi
eld_dependencies'] | 296 if (not field.is_inherited_flag and field.property_name in entry['fi
eld_dependencies'] |
| 291 and entry['predicate'] not in diff_group.predicates): | 297 and entry['predicate'] not in diff_group.predicates): |
| 292 diff_group.predicates.append(entry['predicate']) | 298 diff_group.predicates.append(entry['predicate']) |
| 293 return diff_group | 299 return diff_group |
| 294 | 300 |
| 295 | 301 |
| 296 def _create_enums(properties): | 302 def _create_enums(properties): |
| 297 """ | 303 """Returns a list of Enums to be generated""" |
| 298 Returns an OrderedDict of enums to be generated, enum name -> [list of enum
values] | |
| 299 """ | |
| 300 enums = {} | 304 enums = {} |
| 301 for property_ in properties: | 305 for property_ in properties: |
| 302 # Only generate enums for keyword properties that do not require include
s. | 306 # Only generate enums for keyword properties that do not require include
s. |
| 303 if property_['field_template'] == 'keyword' and len(property_['include_p
aths']) == 0: | 307 if property_['field_template'] in ('keyword', 'multi_keyword') and len(p
roperty_['include_paths']) == 0: |
| 304 enum_name = property_['type_name'] | 308 enum = Enum(property_['type_name'], property_['keywords'], |
| 305 enum_values = [enum_value_name(k) for k in property_['keywords']] | 309 is_set=(property_['field_template'] == 'multi_keyword')) |
| 306 | 310 |
| 307 if enum_name in enums: | 311 if property_['field_template'] == 'multi_keyword': |
| 312 assert property_['keywords'][0] == 'none', \ |
| 313 "First keyword in a 'multi_keyword' field must be 'none' in
'{}'.".format(property_['name']) |
| 314 |
| 315 if enum.type_name in enums: |
| 308 # There's an enum with the same name, check if the enum values a
re the same | 316 # There's an enum with the same name, check if the enum values a
re the same |
| 309 assert set(enums[enum_name]) == set(enum_values), \ | 317 assert set(enums[enum.type_name].values) == set(enum.values), \ |
| 310 ("'" + property_['name'] + "' can't have type_name '" + enum
_name + "' " | 318 ("'" + property_['name'] + "' can't have type_name '" + enum
.type_name + "' " |
| 311 "because it was used by a previous property, but with a dif
ferent set of keywords. " | 319 "because it was used by a previous property, but with a dif
ferent set of keywords. " |
| 312 "Either give it a different name or ensure the keywords are
the same.") | 320 "Either give it a different name or ensure the keywords are
the same.") |
| 313 | 321 |
| 314 enums[enum_name] = enum_values | 322 enums[enum.type_name] = enum |
| 315 | 323 |
| 316 # Return the enums sorted by key (enum name) | 324 # Return the enums sorted by type name |
| 317 return OrderedDict(sorted(enums.items(), key=lambda t: t[0])) | 325 return list(sorted(enums.values(), key=lambda e: e.type_name)) |
| 318 | 326 |
| 319 | 327 |
| 320 def _create_property_field(property_): | 328 def _create_property_field(property_): |
| 321 """ | 329 """ |
| 322 Create a property field. | 330 Create a property field. |
| 323 """ | 331 """ |
| 324 name_for_methods = property_['name_for_methods'] | 332 name_for_methods = property_['name_for_methods'] |
| 325 | 333 |
| 326 assert property_['default_value'] is not None, \ | 334 assert property_['default_value'] is not None, \ |
| 327 ('MakeComputedStyleBase requires an default value for all fields, none s
pecified ' | 335 ('MakeComputedStyleBase requires an default value for all fields, none s
pecified ' |
| 328 'for property ' + property_['name']) | 336 'for property ' + property_['name']) |
| 329 | 337 |
| 330 if property_['field_template'] == 'keyword': | 338 if property_['field_template'] == 'keyword': |
| 331 type_name = property_['type_name'] | 339 type_name = property_['type_name'] |
| 332 default_value = type_name + '::' + enum_value_name(property_['default_va
lue']) | 340 default_value = type_name + '::' + enum_value_name(property_['default_va
lue']) |
| 333 assert property_['field_size'] is None, \ | 341 assert property_['field_size'] is None, \ |
| 334 ("'" + property_['name'] + "' is a keyword field, " | 342 ("'" + property_['name'] + "' is a keyword field, " |
| 335 "so it should not specify a field_size") | 343 "so it should not specify a field_size") |
| 336 size = int(math.ceil(math.log(len(property_['keywords']), 2))) | 344 size = int(math.ceil(math.log(len(property_['keywords']), 2))) |
| 345 elif property_['field_template'] == 'multi_keyword': |
| 346 type_name = property_['type_name'] |
| 347 default_value = type_name + '::' + enum_value_name(property_['default_va
lue']) |
| 348 size = len(property_['keywords']) - 1 # Subtract 1 for 'none' keyword |
| 337 elif property_['field_template'] == 'storage_only': | 349 elif property_['field_template'] == 'storage_only': |
| 338 type_name = property_['type_name'] | 350 type_name = property_['type_name'] |
| 339 default_value = property_['default_value'] | 351 default_value = property_['default_value'] |
| 340 size = 1 if type_name == 'bool' else property_['field_size'] | 352 size = 1 if type_name == 'bool' else property_['field_size'] |
| 341 elif property_['field_template'] == 'external': | 353 elif property_['field_template'] == 'external': |
| 342 type_name = property_['type_name'] | 354 type_name = property_['type_name'] |
| 343 default_value = property_['default_value'] | 355 default_value = property_['default_value'] |
| 344 size = None | 356 size = None |
| 345 elif property_['field_template'] == 'primitive': | 357 elif property_['field_template'] == 'primitive': |
| 346 type_name = property_['type_name'] | 358 type_name = property_['type_name'] |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 | 555 |
| 544 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') | 556 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') |
| 545 def generate_base_computed_style_constants(self): | 557 def generate_base_computed_style_constants(self): |
| 546 return { | 558 return { |
| 547 'properties': self._properties, | 559 'properties': self._properties, |
| 548 'enums': self._generated_enums, | 560 'enums': self._generated_enums, |
| 549 } | 561 } |
| 550 | 562 |
| 551 if __name__ == '__main__': | 563 if __name__ == '__main__': |
| 552 json5_generator.Maker(ComputedStyleBaseWriter).main() | 564 json5_generator.Maker(ComputedStyleBaseWriter).main() |
| OLD | NEW |