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

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

Issue 2756113002: Move naming related code in make_computed_style_base to name_utilities. (Closed)
Patch Set: Created 3 years, 9 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
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
11 import make_style_builder 11 import make_style_builder
12 12
13 from name_utilities import camel_case, lower_first, upper_first_letter, enum_for _css_keyword 13 from name_utilities import (
14 enum_for_css_keyword, enumerator_name, class_member_name, method_name
15 )
14 16
15 17
16 # Temporary hard-coded list of fields that are not CSS properties. 18 # Temporary hard-coded list of fields that are not CSS properties.
17 # Ideally these would be specified in a .json5 file. 19 # Ideally these would be specified in a .json5 file.
18 NONPROPERTY_FIELDS = [ 20 NONPROPERTY_FIELDS = [
19 {'name': 'isLink', 'field_template': 'monotonic_flag'}, 21 {'name': 'IsLink', 'field_template': 'monotonic_flag'},
20 # Style can not be shared. 22 # Style can not be shared.
21 {'name': 'unique', 'field_template': 'monotonic_flag'}, 23 {'name': 'Unique', 'field_template': 'monotonic_flag'},
22 # Whether this style is affected by these pseudo-classes. 24 # Whether this style is affected by these pseudo-classes.
23 {'name': 'affectedByFocus', 'field_template': 'monotonic_flag'}, 25 {'name': 'AffectedByFocus', 'field_template': 'monotonic_flag'},
24 {'name': 'affectedByHover', 'field_template': 'monotonic_flag'}, 26 {'name': 'AffectedByHover', 'field_template': 'monotonic_flag'},
25 {'name': 'affectedByActive', 'field_template': 'monotonic_flag'}, 27 {'name': 'AffectedByActive', 'field_template': 'monotonic_flag'},
26 {'name': 'affectedByDrag', 'field_template': 'monotonic_flag'}, 28 {'name': 'AffectedByDrag', 'field_template': 'monotonic_flag'},
27 # A non-inherited property references a variable or @apply is used 29 # A non-inherited property references a variable or @apply is used
28 {'name': 'hasVariableReferenceFromNonInheritedProperty', 'field_template': ' monotonic_flag'}, 30 {'name': 'HasVariableReferenceFromNonInheritedProperty', 'field_template': ' monotonic_flag'},
29 # Explicitly inherits a non-inherited property 31 # Explicitly inherits a non-inherited property
30 {'name': 'hasExplicitlyInheritedProperties', 'field_template': 'monotonic_fl ag'} 32 {'name': 'HasExplicitlyInheritedProperties', 'field_template': 'monotonic_fl ag'}
31 ] 33 ]
32 34
33 35
34 class Field(object): 36 class Field(object):
35 """ 37 """
36 The generated ComputedStyle object is made up of a series of Fields. 38 The generated ComputedStyle object is made up of a series of Fields.
37 Each Field has a name, size, type, etc, and a bunch of attributes to 39 Each Field has a name, size, type, etc, and a bunch of attributes to
38 determine which methods it will be used in. 40 determine which methods it will be used in.
39 41
40 A Field also has enough information to use any storage type in C++, such as 42 A Field also has enough information to use any storage type in C++, such as
41 regular member variables, or more complex storage like vectors or hashmaps. 43 regular member variables, or more complex storage like vectors or hashmaps.
42 Almost all properties will have at least one Field, often more than one. 44 Almost all properties will have at least one Field, often more than one.
43 45
44 Fields also fall into various roles, which determine the logic that is 46 Most attributes in this class correspond to parameters in CSSProperties.json 5.
45 used to generate them. The available field roles are: 47 See that file for a more detailed explanation of each attribute.
46 - 'property', for fields that store CSS properties 48
47 - 'inherited_flag', for single-bit flags that store whether a property is 49 Attributes:
48 inherited by this style or set explicitly 50 field_role: The semantic role of the field. Can be:
49 - 'nonproperty', for fields that are not CSS properties 51 - 'property': for fields that store CSS properties
52 - 'inherited_flag': for single-bit flags that store whether a proper ty is
53 inherited by this style or set explicitly
54 - 'nonproperty': for fields that are not CSS properties
55 name_for_methods: String used to form the names of getters and setters.
56 Should be in upper camel case.
57 property_name: Name of the property that the field is part of.
58 type_name: Name of the C++ type exposed by the generated interface (e.g. EClear, int).
59 'field_template': Determines the interface generated for the field. Can be one of:
60 keyword, flag, or monotonic_flag.
61 'size': Number of bits needed for storage.
62 'default_value': Default value for this field when it is first initializ ed.
50 """ 63 """
51 64
52 # List of required attributes for a field which need to be passed in by 65 def __init__(self, field_role, name_for_methods, property_name, type_name,
53 # keyword arguments. See CSSProperties.json5 for an explanation of each 66 field_template, size, default_value, **kwargs):
54 # attribute. 67 """Creates a new field."""
55 REQUIRED_ATTRIBUTES = set([ 68 self.name = class_member_name(name_for_methods)
56 # Name of field 69 self.property_name = property_name
57 'name', 70 self.type_name = type_name
58 # Name of property field is for 71 self.field_template = field_template
59 'property_name', 72 self.size = size
60 # Name of the type (e.g. EClear, int) 73 self.default_value = default_value
61 'type_name',
62 # Affects how the field is generated (keyword, flag, monotonic_flag)
63 'field_template',
64 # Bits needed for storage
65 'size',
66 # Default value for field
67 'default_value',
68 # Method names
69 'getter_method_name',
70 'setter_method_name',
71 'initial_method_name',
72 'resetter_method_name',
73 ])
74
75 def __init__(self, field_role, **kwargs):
76 # Values common to all fields
77 # Set attributes from the keyword arguments
78 for attrib in Field.REQUIRED_ATTRIBUTES:
79 setattr(self, attrib, kwargs.pop(attrib))
80 74
81 # Field role: one of these must be true 75 # Field role: one of these must be true
82 self.is_property = field_role == 'property' 76 self.is_property = field_role == 'property'
83 self.is_inherited_flag = field_role == 'inherited_flag' 77 self.is_inherited_flag = field_role == 'inherited_flag'
84 self.is_nonproperty = field_role == 'nonproperty' 78 self.is_nonproperty = field_role == 'nonproperty'
85 assert (self.is_property, self.is_inherited_flag, self.is_nonproperty).c ount(True) == 1, \ 79 assert (self.is_property, self.is_inherited_flag, self.is_nonproperty).c ount(True) == 1, \
86 'Field role has to be exactly one of: property, inherited_flag, nonp roperty' 80 'Field role has to be exactly one of: property, inherited_flag, nonp roperty'
87 81
88 if self.is_property: 82 if self.is_property:
89 self.is_inherited = kwargs.pop('inherited') 83 self.is_inherited = kwargs.pop('inherited')
90 self.is_independent = kwargs.pop('independent') 84 self.is_independent = kwargs.pop('independent')
91 assert self.is_inherited or not self.is_independent, 'Only inherited fields can be independent' 85 assert self.is_inherited or not self.is_independent, 'Only inherited fields can be independent'
92 86
93 self.is_inherited_method_name = kwargs.pop('is_inherited_method_name ') 87 self.is_inherited_method_name = method_name(name_for_methods + 'IsIn herited')
94 elif self.is_inherited_flag: 88
95 # Inherited flag-only fields 89 # Method names
96 pass 90 getter_prefix = 'Get' if name_for_methods == self.type_name else ''
91 self.getter_method_name = method_name(getter_prefix + name_for_methods)
92 self.setter_method_name = method_name('Set' + name_for_methods)
93 self.initial_method_name = method_name('Initial' + name_for_methods)
94 self.resetter_method_name = method_name('Reset' + name_for_methods)
97 95
98 assert len(kwargs) == 0, 'Unexpected arguments provided to Field: ' + st r(kwargs) 96 assert len(kwargs) == 0, 'Unexpected arguments provided to Field: ' + st r(kwargs)
99 97
100 98
101 def _get_include_paths(properties): 99 def _get_include_paths(properties):
102 """ 100 """
103 Get a list of paths that need to be included for ComputedStyleBase. 101 Get a list of paths that need to be included for ComputedStyleBase.
104 """ 102 """
105 include_paths = set() 103 include_paths = set()
106 for property_ in properties: 104 for property_ in properties:
107 if property_['field_type_path'] is not None: 105 if property_['field_type_path'] is not None:
108 include_paths.add(property_['field_type_path'] + '.h') 106 include_paths.add(property_['field_type_path'] + '.h')
109 return list(sorted(include_paths)) 107 return list(sorted(include_paths))
110 108
111 109
112 def _create_enums(properties): 110 def _create_enums(properties):
113 """ 111 """
114 Returns a dictionary of enums to be generated, enum name -> [list of enum va lues] 112 Returns a dictionary of enums to be generated, enum name -> [list of enum va lues]
115 """ 113 """
116 enums = {} 114 enums = {}
117 for property_ in properties: 115 for property_ in properties:
118 # Only generate enums for keyword properties that use the default field_ type_path. 116 # Only generate enums for keyword properties that use the default field_ type_path.
119 if property_['field_template'] == 'keyword' and property_['field_type_pa th'] is None: 117 if property_['field_template'] == 'keyword' and property_['field_type_pa th'] is None:
120 enum_name = property_['type_name'] 118 enum_name = property_['type_name']
121 # From the Blink style guide: Enum members should use InterCaps with an initial capital letter. [names-enum-members] 119 enum_values = [enumerator_name(k) for k in property_['keywords']]
122 enum_values = [('k' + camel_case(k)) for k in property_['keywords']]
123 120
124 if enum_name in enums: 121 if enum_name in enums:
125 # There's an enum with the same name, check if the enum values a re the same 122 # There's an enum with the same name, check if the enum values a re the same
126 assert set(enums[enum_name]) == set(enum_values), \ 123 assert set(enums[enum_name]) == set(enum_values), \
127 ("'" + property_['name'] + "' can't have type_name '" + enum _name + "' " 124 ("'" + property_['name'] + "' can't have type_name '" + enum _name + "' "
128 "because it was used by a previous property, but with a dif ferent set of keywords. " 125 "because it was used by a previous property, but with a dif ferent set of keywords. "
129 "Either give it a different name or ensure the keywords are the same.") 126 "Either give it a different name or ensure the keywords are the same.")
130 127
131 enums[enum_name] = enum_values 128 enums[enum_name] = enum_values
132 129
133 return enums 130 return enums
134 131
135 132
136 def _create_property_field(property_): 133 def _create_property_field(property_):
137 """ 134 """
138 Create a property field from a CSS property and return the Field object. 135 Create a property field from a CSS property and return the Field object.
139 """ 136 """
140 property_name = property_['name_for_methods'] 137 name_for_methods = property_['name_for_methods']
141 property_name_lower = lower_first(property_name)
142 138
143 # From the Blink style guide: Other data members should be prefixed by "m_". [names-data-members]
144 field_name = 'm_' + property_name_lower
145 bits_needed = math.log(len(property_['keywords']), 2) # TODO: implement for non-enums 139 bits_needed = math.log(len(property_['keywords']), 2) # TODO: implement for non-enums
146 type_name = property_['type_name'] 140 type_name = property_['type_name']
147 141
148 # For now, the getter name should match the field name. Later, getter names
149 # will start with an uppercase letter, so if they conflict with the type nam e,
150 # add 'get' to the front.
151 getter_method_name = property_name_lower
152 if type_name == property_name:
153 getter_method_name = 'get' + property_name
154
155 assert property_['initial_keyword'] is not None, \ 142 assert property_['initial_keyword'] is not None, \
156 ('MakeComputedStyleBase requires an initial keyword for keyword fields, none specified ' 143 ('MakeComputedStyleBase requires an initial keyword for keyword fields, none specified '
157 'for property ' + property_['name']) 144 'for property ' + property_['name'])
158 default_value = type_name + '::k' + camel_case(property_['initial_keyword']) 145 default_value = type_name + '::' + enumerator_name(property_['initial_keywor d'])
159 146
160 return Field( 147 return Field(
161 'property', 148 'property',
162 name=field_name, 149 name_for_methods,
163 property_name=property_['name'], 150 property_name=property_['name'],
164 inherited=property_['inherited'], 151 inherited=property_['inherited'],
165 independent=property_['independent'], 152 independent=property_['independent'],
166 type_name=type_name, 153 type_name=type_name,
167 field_template=property_['field_template'], 154 field_template=property_['field_template'],
168 size=int(math.ceil(bits_needed)), 155 size=int(math.ceil(bits_needed)),
169 default_value=default_value, 156 default_value=default_value,
170 getter_method_name=getter_method_name,
171 setter_method_name='set' + property_name,
172 initial_method_name='initial' + property_name,
173 resetter_method_name='reset' + property_name,
174 is_inherited_method_name=property_name_lower + 'IsInherited',
175 ) 157 )
176 158
177 159
178 def _create_inherited_flag_field(property_): 160 def _create_inherited_flag_field(property_):
179 """ 161 """
180 Create the field used for an inheritance fast path from an independent CSS p roperty, 162 Create the field used for an inheritance fast path from an independent CSS p roperty,
181 and return the Field object. 163 and return the Field object.
182 """ 164 """
183 property_name = property_['name_for_methods']
184 property_name_lower = lower_first(property_name)
185
186 field_name_suffix_upper = property_name + 'IsInherited'
187 field_name_suffix_lower = property_name_lower + 'IsInherited'
188
189 return Field( 165 return Field(
190 'inherited_flag', 166 'inherited_flag',
191 name='m_' + field_name_suffix_lower, 167 property_['name_for_methods'] + 'IsInherited',
192 property_name=property_['name'], 168 property_name=property_['name'],
193 type_name='bool', 169 type_name='bool',
194 field_template='flag', 170 field_template='flag',
195 size=1, 171 size=1,
196 default_value='true', 172 default_value='true',
197 getter_method_name=field_name_suffix_lower,
198 setter_method_name='set' + field_name_suffix_upper,
199 initial_method_name='initial' + field_name_suffix_upper,
200 resetter_method_name='reset' + field_name_suffix_upper,
201 ) 173 )
202 174
203 175
204 def _create_nonproperty_field(property_): 176 def _create_nonproperty_field(property_):
205 """ 177 """
206 Create a nonproperty field from an entry in NONPROPERTY_FIELDS and return th e Field object. 178 Create a nonproperty field from an entry in NONPROPERTY_FIELDS and return th e Field object.
207 """ 179 """
208 # TODO(shend): Make this work for nonflags 180 # TODO(shend): Make this work for nonflags
209 assert property_['field_template'] in ('flag', 'monotonic_flag'), \ 181 assert property_['field_template'] in ('flag', 'monotonic_flag'), \
210 "Nonproperties with arbitrary templates are not yet supported" 182 "Nonproperties with arbitrary templates are not yet supported"
211 member_name = 'm_' + property_['name']
212 field_name_upper = upper_first_letter(property_['name'])
213 183
214 return Field( 184 return Field(
215 'nonproperty', 185 'nonproperty',
216 name=member_name, 186 property_['name'],
217 property_name=property_['name'], 187 property_name=property_['name'],
218 type_name='bool', 188 type_name='bool',
219 field_template=property_['field_template'], 189 field_template=property_['field_template'],
220 size=1, 190 size=1,
221 default_value='false', 191 default_value='false',
222 getter_method_name=property_['name'],
223 setter_method_name='set' + field_name_upper,
224 initial_method_name='initial' + field_name_upper,
225 resetter_method_name='reset' + field_name_upper,
226 ) 192 )
227 193
228 194
229 def _create_fields(properties): 195 def _create_fields(properties):
230 """ 196 """
231 Create ComputedStyle fields from CSS properties and return a list of Field o bjects. 197 Create ComputedStyle fields from CSS properties and return a list of Field o bjects.
232 """ 198 """
233 fields = [] 199 fields = []
234 for property_ in properties: 200 for property_ in properties:
235 # Only generate properties that have a field template 201 # Only generate properties that have a field template
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 'expected_total_field_bytes': self._expected_total_field_bytes, 331 'expected_total_field_bytes': self._expected_total_field_bytes,
366 } 332 }
367 333
368 @template_expander.use_jinja('CSSValueIDMappingsGenerated.h.tmpl') 334 @template_expander.use_jinja('CSSValueIDMappingsGenerated.h.tmpl')
369 def generate_css_value_mappings(self): 335 def generate_css_value_mappings(self):
370 mappings = {} 336 mappings = {}
371 337
372 for property_ in self._properties.values(): 338 for property_ in self._properties.values():
373 if property_['field_template'] == 'keyword': 339 if property_['field_template'] == 'keyword':
374 mappings[property_['type_name']] = { 340 mappings[property_['type_name']] = {
375 'default_value': 'k' + camel_case(property_['initial_keyword ']), 341 'default_value': enumerator_name(property_['initial_keyword' ]),
376 'mapping': [('k' + camel_case(k), enum_for_css_keyword(k)) f or k in property_['keywords']], 342 'mapping': [(enumerator_name(k), enum_for_css_keyword(k)) fo r k in property_['keywords']],
377 } 343 }
378 344
379 return { 345 return {
380 'include_paths': self._include_paths, 346 'include_paths': self._include_paths,
381 'mappings': mappings, 347 'mappings': mappings,
382 } 348 }
383 349
384 if __name__ == '__main__': 350 if __name__ == '__main__':
385 json5_generator.Maker(ComputedStyleBaseWriter).main() 351 json5_generator.Maker(ComputedStyleBaseWriter).main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698