| #!/usr/bin/env python |
| # Copyright 2014 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import json5_generator |
| from name_utilities import ( |
| upper_camel_case, lower_camel_case, enum_for_css_property, enum_for_css_property_alias |
| ) |
| |
| |
| class CSSProperties(json5_generator.Writer): |
| def __init__(self, file_paths): |
| json5_generator.Writer.__init__(self, file_paths) |
| |
| properties = self.json5_file.name_dictionaries |
| |
| # Sort properties by priority, then alphabetically. |
| for property in properties: |
| # 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']] |
| |
| # 0: CSSPropertyInvalid |
| # 1: CSSPropertyApplyAtRule |
| # 2: CSSPropertyVariable |
| self._first_enum_value = 3 |
| |
| # StylePropertyMetadata additionally assumes there are under 1024 properties. |
| assert self._first_enum_value + len(properties) < 512, 'Property aliasing expects there are under 512 properties.' |
| |
| 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) |
| |
| # 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'] + 512 |
| 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) |
| |
| def properties(self): |
| return self._properties |