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

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

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

Powered by Google App Engine
This is Rietveld 408576698