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

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

Issue 511943003: Generate externs automatically from json/idl files: minor changes. Base URL: https://chromium.googlesource.com/chromium/src.git@true_master
Patch Set: Created 6 years, 3 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
(Empty)
1 # Copyright (c) 2013 The Chromium Authors. All rights reserved.
hirono 2014/10/03 10:10:42 nit: 2014?
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4 """
5 Generator that produces an externs file for the Closure Compiler.
6
7 See https://developers.google.com/closure/compiler/docs/api-tutorial3#externs
8 """
9
10 from code import Code
11 from model import *
12 from schema_util import *
13
14 import os
15 from datetime import datetime
16
17 LICENSE = ("""// Copyright %s The Chromium Authors. All rights reserved.
18 // Use of this source code is governed by a BSD-style license that can be
19 // found in the LICENSE file.
20 """ % datetime.now().year)
21
22 class JsExternsGenerator(object):
23 def __init__(self):
24 pass
25
26 def Generate(self, namespace):
27 return _Generator(namespace).Generate()
28
29 class _Generator(object):
30 def __init__(self, namespace):
31 self._namespace = namespace
32
33 def Generate(self):
34 """Generates a Code object with the .dart for the entire namespace.
35 """
36 c = Code()
37 (c.Append(LICENSE)
38 .Append()
39 .Append('/** @fileoverview Externs generated from namespace: %s */' %
40 self._namespace.name)
41 .Append())
42
43 for type_ in self._namespace.types.values():
44 c.Cblock(self._GenerateType(type_))
45
46 c.Cblock(self._GenerateNamespaceObject())
47
48 for function in self._namespace.functions.values():
49 c.Cblock(self._GenerateFunction(function))
50
51 for event in self._namespace.events.values():
52 c.Cblock(self._GenerateEvent(event))
53
54 return c
55
56 def _GenerateType(self, type_):
57 """Given a Type object, returns the Code for this type's definition.
58
59 """
60 c = Code()
61
62 # Since enums are just treated as strings for now, don't generate their
63 # type.
64 if type_.property_type is PropertyType.ENUM:
65 return c
66
67 c.Concat(self._GenerateTypeJsDoc(type_))
68
69 if self._IsTypeConstructor(type_):
70 c.Append('var ' + type_.simple_name + ' = function();')
hirono 2014/10/03 10:10:42 Is it OK dropping arguments of constructor?
Vitaly Pavlenko 2014/10/03 23:33:44 You're right, that's a mistake. By the way, will y
71 else:
72 c.Append('var ' + type_.simple_name + ';')
73
74 return c
75
76 def _IsTypeConstructor(self, type_):
77 """Returns true if the given type should be a @constructor. If this returns
78 false, the type is a typedef.
79 """
80 return any(prop.type_.property_type is PropertyType.FUNCTION
81 for prop in type_.properties.values())
82
83 def _GenerateTypeJsDoc(self, type_):
84 """Generates the documentation for a type as a Code.
85
86 Returns an empty code object if the object has no documentation.
87 """
88 c = Code()
89 c.Append('/**')
90
91 if type_.description:
92 for line in type_.description.split('\n'):
93 c.Comment(line, comment_prefix=' * ')
94
95 if self._IsTypeConstructor(type_):
96 c.Comment('@constructor', comment_prefix = ' * ')
97 else:
98 c.Concat(self._GenerateTypedef(type_.properties))
99
100 c.Append(' */')
101 return c
102
103 def _GenerateTypedef(self, properties):
104 """Given an OrderedDict of properties, returns a Code containing a @typedef.
105 """
106 if not properties: return Code()
107
108 lines = []
109 lines.append('@typedef {{')
110 for field, property_ in properties.items():
111 js_type = self._TypeToJsType(property_.type_)
112 if property_.optional:
113 js_type = '(%s|undefined)' % js_type
114 lines.append(' %s: %s,' % (field, js_type))
115
116 # remove last trailing comma
117 lines[-1] = lines[-1][:-1]
118 lines.append('}}')
119 # TODO(tbreisacher): Add '@see <link to documentation>'.
120
121 lines = [' * ' + line for line in lines]
122 codeString = '\n'.join(lines)
Tyler Breisacher (Chromium) 2015/02/25 00:22:05 Can probably inline this? codeString = '\n'.join(
123 c = Code()
124 c.Append(codeString)
125 return c
126
127 def _GenerateFunctionJsDoc(self, function):
128 """Generates the documentation for a function as a Code.
129
130 Returns an empty code object if the object has no documentation.
131 """
132 c = Code()
133 c.Append('/**')
134
135 if function.description:
136 for line in function.description.split('\n'):
137 c.Comment(line, comment_prefix=' * ')
138
139 for param in function.params:
140 js_type = self._TypeToJsType(param.type_)
141
142 if param.optional:
143 js_type += '='
144
145 param_doc = '@param {%s} %s %s' % (js_type,
146 param.name,
147 param.description or '')
148 c.Comment(param_doc, comment_prefix=' * ')
149
150 if function.callback:
151 # TODO(tbreisacher): Convert Function to function() for better
152 # typechecking.
153 js_type = 'Function'
154 if function.callback.optional:
155 js_type += '='
156 param_doc = '@param {%s} %s %s' % (js_type,
157 function.callback.name,
158 function.callback.description or '')
159 c.Comment(param_doc, comment_prefix=' * ')
160
161 if function.returns:
162 return_doc = '@return {%s} %s' % (self._TypeToJsType(function.returns),
163 function.returns.description)
164 c.Comment(return_doc, comment_prefix=' * ')
165
166 c.Append(' */')
167 return c
168
169 def _TypeToJsType(self, type_):
170 """Converts a model.Type to a JS type (number, Array, etc.)"""
171 if type_.property_type in (PropertyType.INTEGER, PropertyType.DOUBLE):
172 return 'number'
173 elif type_.property_type is PropertyType.OBJECT:
174 return 'Object'
175 elif type_.property_type is PropertyType.ARRAY:
176 return 'Array'
177 elif type_.property_type is PropertyType.REF:
178 return type_.ref_type
179 elif type_.property_type.is_fundamental:
180 return type_.property_type.name
181 else:
182 return '?' # TODO make this more specific
Tyler Breisacher (Chromium) 2015/02/25 00:22:05 put someone's name on this TODO. I reluctantly vol
183
184 def _GenerateFunction(self, function):
185 """Generates the code representing a function, including its documentation.
186 For example:
187
188 /**
189 * @param {string} title The new title.
190 */
191 chrome.window.setTitle = function(title) {};
192 """
193 c = Code()
194 params = self._GenerateFunctionParams(function)
195 (c.Concat(self._GenerateFunctionJsDoc(function))
196 .Append('chrome.%s.%s = function(%s) {};' % (self._namespace.name,
197 function.name,
198 params))
199 )
200 return c
201
202 def _GenerateEvent(self, event):
203 """Generates the code representing an event.
204 For example:
205
206 /** @type {!ChromeEvent} */
207 chrome.bookmarks.onChildrenReordered;
208 """
209 c = Code()
210 (c.Append('/** @type {!ChromeEvent} */')
211 .Append('chrome.%s.%s;' % (self._namespace.name, event.name)))
212 return c
213
214 def _GenerateNamespaceObject(self):
215 """Generates the code creating namespace object.
216 For example:
217
218 /**
219 * @const
220 */
221 chrome.bookmarks = {};
222 """
223 c = Code()
224 (c.Append("""/**
225 * @const
226 */""")
227 .Append('chrome.%s = {};' % self._namespace.name))
228 return c
229
230 def _GenerateFunctionParams(self, function):
231 params = function.params[:]
232 if function.callback:
233 params.append(function.callback)
234 return ', '.join(param.name for param in params)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698