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

Side by Side Diff: tools/json_schema_compiler/js_externs_generator.py

Issue 1033223007: [Extension API Extern Generation] Support inline object definitions (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Dan's Created 5 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 # Copyright 2015 The Chromium Authors. All rights reserved. 1 # Copyright 2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 """ 4 """
5 Generator that produces an externs file for the Closure Compiler. 5 Generator that produces an externs file for the Closure Compiler.
6 Note: This is a work in progress, and generated externs may require tweaking. 6 Note: This is a work in progress, and generated externs may require tweaking.
7 7
8 See https://developers.google.com/closure/compiler/docs/api-tutorial3#externs 8 See https://developers.google.com/closure/compiler/docs/api-tutorial3#externs
9 """ 9 """
10 10
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 """ 79 """
80 return any(prop.type_.property_type is PropertyType.FUNCTION 80 return any(prop.type_.property_type is PropertyType.FUNCTION
81 for prop in js_type.properties.values()) 81 for prop in js_type.properties.values())
82 82
83 def _GenerateTypeJsDoc(self, js_type): 83 def _GenerateTypeJsDoc(self, js_type):
84 """Generates the documentation for a type as a Code. 84 """Generates the documentation for a type as a Code.
85 85
86 Returns an empty code object if the object has no documentation. 86 Returns an empty code object if the object has no documentation.
87 """ 87 """
88 c = Code() 88 c = Code()
89 c.Append('/**') 89 c.Sblock(line='/**', line_prefix=' * ')
90 90
91 if js_type.description: 91 if js_type.description:
92 for line in js_type.description.splitlines(): 92 for line in js_type.description.splitlines():
93 c.Comment(line, comment_prefix = ' * ') 93 c.Append(line)
94 94
95 is_constructor = self._IsTypeConstructor(js_type) 95 is_constructor = self._IsTypeConstructor(js_type)
96 if is_constructor: 96 if is_constructor:
97 c.Comment('@constructor', comment_prefix = ' * ', wrap_indent=4) 97 c.Comment('@constructor', comment_prefix = ' * ', wrap_indent=4)
98 else: 98 else:
99 c.Concat(self._GenerateTypedef(js_type.properties)) 99 c.Concat(self._GenerateTypedef(js_type.properties))
100 100
101 c.Append(' */') 101 c.Eblock(' */')
102 102
103 var = 'var ' + js_type.simple_name 103 var = 'var ' + js_type.simple_name
104 if is_constructor: var += ' = function() {}' 104 if is_constructor: var += ' = function() {}'
105 var += ';' 105 var += ';'
106 c.Append(var) 106 c.Append(var)
107 107
108 return c 108 return c
109 109
110 def _GenerateTypedef(self, properties): 110 def _GenerateTypedef(self, properties):
111 """Given an OrderedDict of properties, returns a Code containing a @typedef. 111 """Given an OrderedDict of properties, returns a Code containing a @typedef.
112 """ 112 """
113 if not properties: return Code() 113 if not properties: return Code()
114 114
115 lines = [] 115 c = Code()
116 lines.append('@typedef {{') 116 c.Append('@typedef {')
117 c.Concat(self._GenerateObjectDefinition(properties), new_line=False)
118 c.Append('}', new_line=False)
119 return c
120
121 def _GenerateObjectDefinition(self, properties):
122 """Given an OrderedDict of properties, returns a Code containing the
123 description of an object.
124 """
125 if not properties: return ''
126
127 c = Code()
128 c.Sblock('{')
129 type_descriptions = []
130 first = True
117 for field, prop in properties.items(): 131 for field, prop in properties.items():
132 # Avoid trailing comma.
133 # TODO(devlin): This will be unneeded, if/when
134 # https://github.com/google/closure-compiler/issues/796 is fixed.
135 if not first:
136 c.Append(',', new_line=False)
137 first = False
118 js_type = self._TypeToJsType(prop.type_) 138 js_type = self._TypeToJsType(prop.type_)
119 if prop.optional: 139 if prop.optional:
120 js_type = '(%s|undefined)' % js_type 140 js_type = (Code().
121 lines.append(' %s: %s,' % (field, js_type)) 141 Append('(').
142 Concat(js_type, new_line=False).
143 Append('|undefined)', new_line=False))
144 c.Append('%s: ' % field, strip_right=False)
145 c.Concat(js_type, new_line=False)
122 146
123 # Remove last trailing comma. 147 c.Eblock('}')
124 # TODO(devlin): This will be unneeded, if when
125 # https://github.com/google/closure-compiler/issues/796 is fixed.
126 lines[-1] = lines[-1][:-1]
127 lines.append('}}')
128 # TODO(tbreisacher): Add '@see <link to documentation>'. 148 # TODO(tbreisacher): Add '@see <link to documentation>'.
129 149
130 c = Code()
131 c.Append('\n'.join([' * ' + line for line in lines]))
132 return c 150 return c
133 151
134 def _GenerateFunctionJsDoc(self, function): 152 def _GenerateFunctionJsDoc(self, function):
135 """Generates the documentation for a function as a Code. 153 """Generates the documentation for a function as a Code.
136 154
137 Returns an empty code object if the object has no documentation. 155 Returns an empty code object if the object has no documentation.
138 """ 156 """
139 c = Code() 157 c = Code()
140 c.Append('/**') 158 c.Sblock(line='/**', line_prefix=' * ')
141 159
142 lines = []
143 if function.description: 160 if function.description:
144 for line in function.description.splitlines(): 161 c.Comment(function.description, comment_prefix='')
145 c.Comment(line, comment_prefix=' * ') 162
163 def append_field(c, tag, js_type, name, optional, description):
164 c.Append('@%s {' % tag)
165 c.Concat(js_type, new_line=False)
166 if optional:
167 c.Append('=', new_line=False)
168 c.Append('} %s' % name, new_line=False)
169 if description:
170 c.Comment(' %s' % description, comment_prefix='',
171 wrap_indent=4, new_line=False)
146 172
147 for param in function.params: 173 for param in function.params:
148 js_type = self._TypeToJsType(param.type_) 174 append_field(c, 'param', self._TypeToJsType(param.type_), param.name,
149 if param.optional: 175 param.optional, param.description)
150 js_type += '='
151 lines.append('@param {%s} %s %s' % (js_type,
152 param.name,
153 param.description or ''))
154 176
155 if function.callback: 177 if function.callback:
156 lines.append('@param {%s} %s %s' % ( 178 append_field(c, 'param', self._FunctionToJsFunction(function.callback),
157 self._FunctionToJsFunction(function.callback), 179 function.callback.name, function.callback.optional,
158 function.callback.name, 180 function.callback.description)
159 function.callback.description or ''))
160 181
161 if function.returns: 182 if function.returns:
162 lines.append('@return {%s} %s' % (self._TypeToJsType(function.returns), 183 append_field(c, 'return', self._TypeToJsType(function.returns),
163 function.returns.description or '')) 184 '', False, function.returns.description)
164 185
165 if function.deprecated: 186 if function.deprecated:
166 lines.append('@deprecated %s' % function.deprecated) 187 c.Append('@deprecated %s' % function.deprecated)
167 188
168 for line in lines: 189 c.Eblock(' */')
169 c.Comment(line, comment_prefix=' * ', wrap_indent=4);
170
171 c.Append(' */')
172 return c 190 return c
173 191
174 def _FunctionToJsFunction(self, function): 192 def _FunctionToJsFunction(self, function):
175 """Converts a model.Function to a JS type (i.e., function([params])...)""" 193 """Converts a model.Function to a JS type (i.e., function([params])...)"""
176 params = ', '.join( 194 c = Code()
177 [self._TypeToJsType(param.type_) for param in function.params]) 195 c.Append('function(')
178 return_type = ( 196 for i in range(len(function.params)):
Tyler Breisacher (Chromium) 2015/03/27 23:22:32 for i, param in enumerate(function.params): and t
Devlin 2015/03/27 23:39:46 Oh, nifty. Done (also on line 230)
179 self._TypeToJsType(function.returns) if function.returns else 'void') 197 c.Concat(self._TypeToJsType(function.params[i].type_), new_line=False)
180 optional = '=' if function.optional else '' 198 if i is not len(function.params) - 1:
181 return 'function(%s):%s%s' % (params, return_type, optional) 199 c.Append(', ', new_line=False, strip_right=False)
200 c.Append('):', new_line=False)
201
202 if function.returns:
203 c.Concat(self._TypeToJsType(function.returns), new_line=False)
204 else:
205 c.Append('void', new_line=False)
206
207 return c
182 208
183 def _TypeToJsType(self, js_type): 209 def _TypeToJsType(self, js_type):
184 """Converts a model.Type to a JS type (number, Array, etc.)""" 210 """Converts a model.Type to a JS type (number, Array, etc.)"""
211 c = Code()
185 if js_type.property_type in (PropertyType.INTEGER, PropertyType.DOUBLE): 212 if js_type.property_type in (PropertyType.INTEGER, PropertyType.DOUBLE):
186 return 'number' 213 c.Append('number')
187 elif js_type.property_type is PropertyType.OBJECT: 214 elif js_type.property_type is PropertyType.OBJECT:
188 return 'Object' 215 c = self._GenerateObjectDefinition(js_type.properties)
189 elif js_type.property_type is PropertyType.ARRAY: 216 elif js_type.property_type is PropertyType.ARRAY:
190 return '!Array<%s>' % self._TypeToJsType(js_type.item_type) 217 (c.Append('!Array<').
218 Concat(self._TypeToJsType(js_type.item_type), new_line=False).
219 Append('>', new_line=False))
191 elif js_type.property_type is PropertyType.REF: 220 elif js_type.property_type is PropertyType.REF:
192 ref_type = js_type.ref_type 221 ref_type = js_type.ref_type
193 # Enums are defined as chrome.fooAPI.MyEnum, but types are defined simply 222 # Enums are defined as chrome.fooAPI.MyEnum, but types are defined simply
194 # as MyType. 223 # as MyType.
195 if self._namespace.types[ref_type].property_type is PropertyType.ENUM: 224 if self._namespace.types[ref_type].property_type is PropertyType.ENUM:
196 ref_type = '!chrome.%s.%s' % (self._namespace.name, ref_type) 225 ref_type = '!chrome.%s.%s' % (self._namespace.name, ref_type)
197 return ref_type 226 c.Append(ref_type)
198 elif js_type.property_type is PropertyType.CHOICES: 227 elif js_type.property_type is PropertyType.CHOICES:
199 return '(%s)' % '|'.join( 228 c.Append('(')
200 [self._TypeToJsType(choice) for choice in js_type.choices]) 229 for i in range(len(js_type.choices)):
230 c.Concat(self._TypeToJsType(js_type.choices[i]), new_line=False)
231 if i is not len(js_type.choices) - 1:
232 c.Append('|', new_line=False)
233 c.Append(')', new_line=False)
201 elif js_type.property_type is PropertyType.FUNCTION: 234 elif js_type.property_type is PropertyType.FUNCTION:
202 return self._FunctionToJsFunction(js_type.function) 235 c = self._FunctionToJsFunction(js_type.function)
203 elif js_type.property_type is PropertyType.ANY: 236 elif js_type.property_type is PropertyType.ANY:
204 return '*' 237 c.Append('*')
205 elif js_type.property_type.is_fundamental: 238 elif js_type.property_type.is_fundamental:
206 return js_type.property_type.name 239 c.Append(js_type.property_type.name)
207 else: 240 else:
208 return '?' # TODO(tbreisacher): Make this more specific. 241 c.Append('?') # TODO(tbreisacher): Make this more specific.
242 return c
209 243
210 def _GenerateFunction(self, function): 244 def _GenerateFunction(self, function):
211 """Generates the code representing a function, including its documentation. 245 """Generates the code representing a function, including its documentation.
212 For example: 246 For example:
213 247
214 /** 248 /**
215 * @param {string} title The new title. 249 * @param {string} title The new title.
216 */ 250 */
217 chrome.window.setTitle = function(title) {}; 251 chrome.window.setTitle = function(title) {};
218 """ 252 """
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 * @const 285 * @const
252 */""") 286 */""")
253 .Append('chrome.%s = {};' % self._namespace.name)) 287 .Append('chrome.%s = {};' % self._namespace.name))
254 return c 288 return c
255 289
256 def _GenerateFunctionParams(self, function): 290 def _GenerateFunctionParams(self, function):
257 params = function.params[:] 291 params = function.params[:]
258 if function.callback: 292 if function.callback:
259 params.append(function.callback) 293 params.append(function.callback)
260 return ', '.join(param.name for param in params) 294 return ', '.join(param.name for param in params)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698