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 2692803002: Clean up type handling in make_computed_style_base.py. (Closed)
Patch Set: Update comments Created 3 years, 10 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/ComputedStyleBase.h.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 13 matching lines...) Expand all
24 class Field(object): 24 class Field(object):
25 """ 25 """
26 The generated ComputedStyle object is made up of a series of Fields. 26 The generated ComputedStyle object is made up of a series of Fields.
27 Each Field has a name, size, type, etc, and a bunch of attributes to 27 Each Field has a name, size, type, etc, and a bunch of attributes to
28 determine which methods it will be used in. 28 determine which methods it will be used in.
29 29
30 A Field also has enough information to use any storage type in C++, such as 30 A Field also has enough information to use any storage type in C++, such as
31 regular member variables, or more complex storage like vectors or hashmaps. 31 regular member variables, or more complex storage like vectors or hashmaps.
32 Almost all properties will have at least one Field, often more than one. 32 Almost all properties will have at least one Field, often more than one.
33 33
34 Fields also fall into various families, which determine the logic that is 34 Fields also fall into various roles, which determine the logic that is
35 used to generate them. The available field families are: 35 used to generate them. The available field roles are:
36 - 'property', for fields that store CSS properties 36 - 'property', for fields that store CSS properties
37 - 'inherited_flag', for single-bit flags that store whether a property is 37 - 'inherited_flag', for single-bit flags that store whether a property is
38 inherited by this style or set explicitly 38 inherited by this style or set explicitly
39 - 'nonproperty', for fields that are not CSS properties
39 """ 40 """
40 41
41 # List of required attributes for a field which need to be passed in by 42 # List of required attributes for a field which need to be passed in by
42 # keyword arguments 43 # keyword arguments. See CSSProperties.json5 for an explanation of each
44 # attribute.
43 REQUIRED_ATTRIBUTES = set([ 45 REQUIRED_ATTRIBUTES = set([
44 # Name of field 46 # Name of field
45 'name', 47 'name',
46 # Name of property field is for 48 # Name of property field is for
47 'property_name', 49 'property_name',
48 # Internal field storage type (storage_type_path can be None) 50 # Name of the type (e.g. EClear, int)
49 'storage_type', 51 'type_name',
50 'storage_type_path', 52 # Path to predefined class for overriding generated types.
53 'field_type_path',
54 # Affects how the field is generated (keyword, flag)
55 'field_template',
51 # Bits needed for storage 56 # Bits needed for storage
52 'size', 57 'size',
53 # Default value for field 58 # Default value for field
54 'default_value', 59 'default_value',
55 # Method names 60 # Method names
56 'getter_method_name', 61 'getter_method_name',
57 'setter_method_name', 62 'setter_method_name',
58 'initial_method_name', 63 'initial_method_name',
59 'resetter_method_name', 64 'resetter_method_name',
60 ]) 65 ])
61 66
62 def __init__(self, field_family, **kwargs): 67 def __init__(self, field_role, **kwargs):
63 # Values common to all fields 68 # Values common to all fields
64 # Set attributes from the keyword arguments 69 # Set attributes from the keyword arguments
65 for attrib in Field.REQUIRED_ATTRIBUTES: 70 for attrib in Field.REQUIRED_ATTRIBUTES:
66 setattr(self, attrib, kwargs.pop(attrib)) 71 setattr(self, attrib, kwargs.pop(attrib))
67 72
68 # Field family: one of these must be true 73 # Field role: one of these must be true
69 self.is_property = field_family == 'property' 74 self.is_property = field_role == 'property'
70 self.is_inherited_flag = field_family == 'inherited_flag' 75 self.is_inherited_flag = field_role == 'inherited_flag'
71 self.is_nonproperty = field_family == 'nonproperty' 76 self.is_nonproperty = field_role == 'nonproperty'
72 assert (self.is_property, self.is_inherited_flag, self.is_nonproperty).c ount(True) == 1, \ 77 assert (self.is_property, self.is_inherited_flag, self.is_nonproperty).c ount(True) == 1, \
73 'Field family has to be exactly one of: property, inherited_flag, no nproperty' 78 'Field role has to be exactly one of: property, inherited_flag, nonp roperty'
74 79
75 if self.is_property: 80 if self.is_property:
76 self.is_inherited = kwargs.pop('inherited') 81 self.is_inherited = kwargs.pop('inherited')
77 self.is_independent = kwargs.pop('independent') 82 self.is_independent = kwargs.pop('independent')
78 assert self.is_inherited or not self.is_independent, 'Only inherited fields can be independent' 83 assert self.is_inherited or not self.is_independent, 'Only inherited fields can be independent'
79 84
80 self.is_inherited_method_name = kwargs.pop('is_inherited_method_name ') 85 self.is_inherited_method_name = kwargs.pop('is_inherited_method_name ')
81 elif self.is_inherited_flag: 86 elif self.is_inherited_flag:
82 # Inherited flag-only fields 87 # Inherited flag-only fields
83 pass 88 pass
84 89
85 assert len(kwargs) == 0, 'Unexpected arguments provided to Field: ' + st r(kwargs) 90 assert len(kwargs) == 0, 'Unexpected arguments provided to Field: ' + st r(kwargs)
86 91
87 92
88 def _create_enums(properties): 93 def _create_enums(properties):
89 """ 94 """
90 Returns a dictionary of enums to be generated, enum name -> [list of enum va lues] 95 Returns a dictionary of enums to be generated, enum name -> [list of enum va lues]
91 """ 96 """
92 enums = {} 97 enums = {}
93 for property_ in properties: 98 for property_ in properties:
94 # Only generate enums for keyword properties that use the default field_ storage_type. 99 # Only generate enums for keyword properties that use the default field_ type_path.
95 if property_['keyword_only'] and property_['field_storage_type'] is None : 100 if property_['field_template'] == 'keyword' and property_['field_type_pa th'] is None:
96 enum_name = property_['type_name'] 101 enum_name = property_['type_name']
97 # From the Blink style guide: Enum members should use InterCaps with an initial capital letter. [names-enum-members] 102 # From the Blink style guide: Enum members should use InterCaps with an initial capital letter. [names-enum-members]
98 enum_values = [('k' + camel_case(k)) for k in property_['keywords']] 103 enum_values = [('k' + camel_case(k)) for k in property_['keywords']]
99 104
100 if enum_name in enums: 105 if enum_name in enums:
101 # There's an enum with the same name, check if the enum values a re the same 106 # There's an enum with the same name, check if the enum values a re the same
102 assert set(enums[enum_name]) == set(enum_values), \ 107 assert set(enums[enum_name]) == set(enum_values), \
103 ("'" + property_['name'] + "' can't have type_name '" + enum _name + "' " 108 ("'" + property_['name'] + "' can't have type_name '" + enum _name + "' "
104 "because it was used by a previous property, but with a dif ferent set of keywords. " 109 "because it was used by a previous property, but with a dif ferent set of keywords. "
105 "Either give it a different name or ensure the keywords are the same.") 110 "Either give it a different name or ensure the keywords are the same.")
106 111
107 enums[enum_name] = enum_values 112 enums[enum_name] = enum_values
108 113
109 return enums 114 return enums
110 115
111 116
112 def _create_property_field(property_): 117 def _create_property_field(property_):
113 """ 118 """
114 Create a property field from a CSS property and return the Field object. 119 Create a property field from a CSS property and return the Field object.
115 """ 120 """
116 property_name = property_['name_for_methods'] 121 property_name = property_['name_for_methods']
117 property_name_lower = lower_first(property_name) 122 property_name_lower = lower_first(property_name)
118 123
119 # From the Blink style guide: Other data members should be prefixed by "m_". [names-data-members] 124 # From the Blink style guide: Other data members should be prefixed by "m_". [names-data-members]
120 field_name = 'm_' + property_name_lower 125 field_name = 'm_' + property_name_lower
121 bits_needed = math.log(len(property_['keywords']), 2) 126 bits_needed = math.log(len(property_['keywords']), 2) # TODO: implement for non-enums
122 127
123 # Separate the type path from the type name, if specified. 128 # Separate the type path from the type name, if specified.
124 if property_['field_storage_type']: 129 if property_['field_type_path']:
125 type_path = property_['field_storage_type'] 130 field_type_path = property_['field_type_path']
126 type_name = type_path.split('/')[-1] 131 type_name = field_type_path.split('/')[-1]
127 else: 132 else:
133 field_type_path = None
128 type_name = property_['type_name'] 134 type_name = property_['type_name']
129 type_path = None
130 135
131 # For now, the getter name should match the field name. Later, getter names 136 # For now, the getter name should match the field name. Later, getter names
132 # will start with an uppercase letter, so if they conflict with the type nam e, 137 # will start with an uppercase letter, so if they conflict with the type nam e,
133 # add 'get' to the front. 138 # add 'get' to the front.
134 getter_method_name = property_name_lower 139 getter_method_name = property_name_lower
135 if type_name == property_name: 140 if type_name == property_name:
136 getter_method_name = 'get' + property_name 141 getter_method_name = 'get' + property_name
137 142
138 assert property_['initial_keyword'] is not None, \ 143 assert property_['initial_keyword'] is not None, \
139 ('MakeComputedStyleBase requires an initial keyword for keyword_only val ues, none specified ' 144 ('MakeComputedStyleBase requires an initial keyword for keyword fields, none specified '
140 'for property ' + property_['name']) 145 'for property ' + property_['name'])
141 default_value = type_name + '::k' + camel_case(property_['initial_keyword']) 146 default_value = type_name + '::k' + camel_case(property_['initial_keyword'])
142 147
143 # Add the property itself as a member variable.
144 return Field( 148 return Field(
145 'property', 149 'property',
146 name=field_name, 150 name=field_name,
147 property_name=property_['name'], 151 property_name=property_['name'],
148 inherited=property_['inherited'], 152 inherited=property_['inherited'],
149 independent=property_['independent'], 153 independent=property_['independent'],
150 storage_type=type_name, 154 type_name=type_name,
151 storage_type_path=type_path, 155 field_type_path=field_type_path,
156 field_template=property_['field_template'],
152 size=int(math.ceil(bits_needed)), 157 size=int(math.ceil(bits_needed)),
153 default_value=default_value, 158 default_value=default_value,
154 getter_method_name=getter_method_name, 159 getter_method_name=getter_method_name,
155 setter_method_name='set' + property_name, 160 setter_method_name='set' + property_name,
156 initial_method_name='initial' + property_name, 161 initial_method_name='initial' + property_name,
157 resetter_method_name='reset' + property_name, 162 resetter_method_name='reset' + property_name,
158 is_inherited_method_name=property_name_lower + 'IsInherited', 163 is_inherited_method_name=property_name_lower + 'IsInherited',
159 ) 164 )
160 165
161 166
162 def _create_inherited_flag_field(property_): 167 def _create_inherited_flag_field(property_):
163 """ 168 """
164 Create the field used for an inheritance fast path from an independent CSS p roperty, 169 Create the field used for an inheritance fast path from an independent CSS p roperty,
165 and return the Field object. 170 and return the Field object.
166 """ 171 """
167 property_name = property_['name_for_methods'] 172 property_name = property_['name_for_methods']
168 property_name_lower = lower_first(property_name) 173 property_name_lower = lower_first(property_name)
169 174
170 field_name_suffix_upper = property_name + 'IsInherited' 175 field_name_suffix_upper = property_name + 'IsInherited'
171 field_name_suffix_lower = property_name_lower + 'IsInherited' 176 field_name_suffix_lower = property_name_lower + 'IsInherited'
172 177
173 return Field( 178 return Field(
174 'inherited_flag', 179 'inherited_flag',
175 name='m_' + field_name_suffix_lower, 180 name='m_' + field_name_suffix_lower,
176 property_name=property_['name'], 181 property_name=property_['name'],
177 storage_type='bool', 182 type_name='bool',
178 storage_type_path=None, 183 field_type_path=None,
184 field_template='flag',
179 size=1, 185 size=1,
180 default_value='true', 186 default_value='true',
181 getter_method_name=field_name_suffix_lower, 187 getter_method_name=field_name_suffix_lower,
182 setter_method_name='set' + field_name_suffix_upper, 188 setter_method_name='set' + field_name_suffix_upper,
183 initial_method_name='initial' + field_name_suffix_upper, 189 initial_method_name='initial' + field_name_suffix_upper,
184 resetter_method_name='reset' + field_name_suffix_upper, 190 resetter_method_name='reset' + field_name_suffix_upper,
185 ) 191 )
186 192
187 193
188 def _create_nonproperty_field(field_name): 194 def _create_nonproperty_field(field_name):
189 """ 195 """
190 Create a nonproperty field from its name and return the Field object. 196 Create a nonproperty field from its name and return the Field object.
191 """ 197 """
192 member_name = 'm_' + field_name 198 member_name = 'm_' + field_name
193 field_name_upper = upper_first_letter(field_name) 199 field_name_upper = upper_first_letter(field_name)
194 200
195 return Field( 201 return Field(
196 'nonproperty', 202 'nonproperty',
197 name=member_name, 203 name=member_name,
198 property_name=field_name, 204 property_name=field_name,
199 storage_type='bool', 205 type_name='bool',
200 storage_type_path=None, 206 field_type_path=None,
207 field_template='flag',
201 size=1, 208 size=1,
202 default_value='false', 209 default_value='false',
203 getter_method_name=field_name, 210 getter_method_name=field_name,
204 setter_method_name='set' + field_name_upper, 211 setter_method_name='set' + field_name_upper,
205 initial_method_name='initial' + field_name_upper, 212 initial_method_name='initial' + field_name_upper,
206 resetter_method_name='reset' + field_name_upper, 213 resetter_method_name='reset' + field_name_upper,
207 ) 214 )
208 215
209 216
210 def _create_fields(properties): 217 def _create_fields(properties):
211 """ 218 """
212 Create ComputedStyle fields from CSS properties and return a list of Field o bjects. 219 Create ComputedStyle fields from CSS properties and return a list of Field o bjects.
213 """ 220 """
214 fields = [] 221 fields = []
215 for property_ in properties: 222 for property_ in properties:
216 # Keywords only means we generate an enum field. 223 # Only generate properties that have a field template
217 if property_['keyword_only']: 224 if property_['field_template'] is not None:
218 # If the property is independent, add the single-bit sized isInherit ed flag 225 # If the property is independent, add the single-bit sized isInherit ed flag
219 # to the list of Fields as well. 226 # to the list of Fields as well.
220 if property_['independent']: 227 if property_['independent']:
221 fields.append(_create_inherited_flag_field(property_)) 228 fields.append(_create_inherited_flag_field(property_))
222 229
223 fields.append(_create_property_field(property_)) 230 fields.append(_create_property_field(property_))
224 231
225 for field_name in NONPROPERTY_FIELDS: 232 for field_name in NONPROPERTY_FIELDS:
226 fields.append(_create_nonproperty_field(field_name)) 233 fields.append(_create_nonproperty_field(field_name))
227 234
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 def generate_base_computed_style_constants(self): 335 def generate_base_computed_style_constants(self):
329 return { 336 return {
330 'properties': self._properties, 337 'properties': self._properties,
331 'enums': self._generated_enums, 338 'enums': self._generated_enums,
332 'fields': self._fields, 339 'fields': self._fields,
333 'expected_total_field_bytes': self._expected_total_field_bytes, 340 'expected_total_field_bytes': self._expected_total_field_bytes,
334 } 341 }
335 342
336 if __name__ == '__main__': 343 if __name__ == '__main__':
337 json5_generator.Maker(ComputedStyleBaseWriter).main() 344 json5_generator.Maker(ComputedStyleBaseWriter).main()
OLDNEW
« no previous file with comments | « no previous file | third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.h.tmpl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698