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

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

Issue 2601333002: Update json_schema_compiler to handle the Automation extension API (Closed)
Patch Set: Better solution Created 3 years, 11 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
11 from code import Code 11 from code import Code
12 from js_util import JsUtil 12 from js_util import JsUtil
13 from model import * 13 from model import *
14 from schema_util import * 14 from schema_util import *
15 15
16 import os 16 import os
17 import sys 17 import sys
18 import re 18 import re
19 19
20 NOTE = """// NOTE: The format of types has changed. 'FooType' is now 20 NOTE = """// NOTE: The format of types has changed. 'FooType' is now
21 // 'chrome.%s.FooType'. 21 // 'chrome.%s.FooType'.
22 // Please run the closure compiler before committing changes. 22 // Please run the closure compiler before committing changes.
23 // See https://chromium.googlesource.com/chromium/src/+/master/docs/closure_comp ilation.md 23 // See https://chromium.googlesource.com/chromium/src/+/master/docs/closure_comp ilation.md
24 """ 24 """
25 25
26 class JsExternsGenerator(object): 26 class JsExternsGenerator(object):
27 def __init__(self, no_normalize_enums):
28 self._no_normalize_enums = no_normalize_enums
29
27 def Generate(self, namespace): 30 def Generate(self, namespace):
28 return _Generator(namespace).Generate() 31 return _Generator(namespace, self._no_normalize_enums).Generate()
29 32
30 class _Generator(object): 33 class _Generator(object):
31 def __init__(self, namespace): 34 def __init__(self, namespace, no_normalize_enums):
32 self._namespace = namespace 35 self._namespace = namespace
36 self._class_name = None
33 self._js_util = JsUtil() 37 self._js_util = JsUtil()
38 self._no_normalize_enums = no_normalize_enums
34 39
35 def Generate(self): 40 def Generate(self):
36 """Generates a Code object with the schema for the entire namespace. 41 """Generates a Code object with the schema for the entire namespace.
37 """ 42 """
38 c = Code() 43 c = Code()
39 (c.Append(self._GetHeader(sys.argv[0], self._namespace.name)) 44 (c.Append(self._GetHeader(sys.argv[0], self._namespace.name))
40 .Append()) 45 .Append())
41 46
42 self._AppendNamespaceObject(c) 47 self._AppendNamespaceObject(c)
43 48
44 for js_type in self._namespace.types.values(): 49 for js_type in self._namespace.types.values():
45 self._AppendType(c, js_type) 50 self._AppendType(c, js_type)
46 51
47 for function in self._namespace.functions.values(): 52 for function in self._namespace.functions.values():
48 self._AppendFunction(c, function) 53 self._AppendFunction(c, function)
49 54
50 for event in self._namespace.events.values(): 55 for event in self._namespace.events.values():
51 self._AppendEvent(c, event) 56 self._AppendEvent(c, event)
52 57
53 c.TrimTrailingNewlines() 58 c.TrimTrailingNewlines()
54 59
55 return c 60 return c
56 61
57 def _GetHeader(self, tool, namespace): 62 def _GetHeader(self, tool, namespace):
58 """Returns the file header text. 63 """Returns the file header text.
59 """ 64 """
60 return (self._js_util.GetLicense() + '\n' + 65 return (self._js_util.GetLicense() + '\n' +
61 self._js_util.GetInfo(tool) + (NOTE % namespace) + '\n' + 66 self._js_util.GetInfo(tool) + (NOTE % namespace) + '\n' +
Dan Beam 2017/01/04 03:19:49 nit: maybe update tool += ' --no-normalize-enums'
62 ('/** @fileoverview Externs generated from namespace: %s */' % 67 ('/** @fileoverview Externs generated from namespace: %s */' %
63 namespace)) 68 namespace))
64 69
65 def _AppendType(self, c, js_type): 70 def _AppendType(self, c, js_type):
66 """Given a Type object, generates the Code for this type's definition. 71 """Given a Type object, generates the Code for this type's definition.
67 """ 72 """
68 if js_type.property_type is PropertyType.ENUM: 73 if js_type.property_type is PropertyType.ENUM:
69 self._AppendEnumJsDoc(c, js_type) 74 self._AppendEnumJsDoc(c, js_type)
70 else: 75 else:
71 self._AppendTypeJsDoc(c, js_type) 76 self._AppendTypeJsDoc(c, js_type)
72 c.Append() 77 c.Append()
73 78
74 def _AppendEnumJsDoc(self, c, js_type): 79 def _AppendEnumJsDoc(self, c, js_type):
75 """ Given an Enum Type object, generates the Code for the enum's definition. 80 """ Given an Enum Type object, generates the Code for the enum's definition.
76 """ 81 """
77 (c.Sblock(line='/**', line_prefix=' * ') 82 (c.Sblock(line='/**', line_prefix=' * ')
78 .Append('@enum {string}') 83 .Append('@enum {string}')
79 .Append(self._js_util.GetSeeLink(self._namespace.name, 'type', 84 .Append(self._js_util.GetSeeLink(self._namespace.name, 'type',
80 js_type.simple_name)) 85 js_type.simple_name))
81 .Eblock(' */')) 86 .Eblock(' */'))
82 c.Append('chrome.%s.%s = {' % (self._namespace.name, js_type.name)) 87 c.Append('%s.%s = {' % (self._GetNamespace(), js_type.name))
83 88
84 def get_property_name(e): 89 def get_property_name(e):
90 if self._no_normalize_enums:
91 return e
85 # Enum properties are normified to be in ALL_CAPS_STYLE. 92 # Enum properties are normified to be in ALL_CAPS_STYLE.
86 # Assume enum '1ring-rulesThemAll'. 93 # Assume enum '1ring-rulesThemAll'.
87 # Transform to '1ring-rules_Them_All'. 94 # Transform to '1ring-rules_Them_All'.
88 e = re.sub(r'([a-z])([A-Z])', r'\1_\2', e) 95 e = re.sub(r'([a-z])([A-Z])', r'\1_\2', e)
89 # Transform to '1ring_rules_Them_All'. 96 # Transform to '1ring_rules_Them_All'.
90 e = re.sub(r'\W', '_', e) 97 e = re.sub(r'\W', '_', e)
91 # Transform to '_1ring_rules_Them_All'. 98 # Transform to '_1ring_rules_Them_All'.
92 e = re.sub(r'^(\d)', r'_\1', e) 99 e = re.sub(r'^(\d)', r'_\1', e)
93 # Transform to '_1RING_RULES_THEM_ALL'. 100 # Transform to '_1RING_RULES_THEM_ALL'.
94 return e.upper() 101 return e.upper()
(...skipping 13 matching lines...) Expand all
108 def _AppendTypeJsDoc(self, c, js_type): 115 def _AppendTypeJsDoc(self, c, js_type):
109 """Appends the documentation for a type as a Code. 116 """Appends the documentation for a type as a Code.
110 """ 117 """
111 c.Sblock(line='/**', line_prefix=' * ') 118 c.Sblock(line='/**', line_prefix=' * ')
112 119
113 if js_type.description: 120 if js_type.description:
114 for line in js_type.description.splitlines(): 121 for line in js_type.description.splitlines():
115 c.Append(line) 122 c.Append(line)
116 123
117 is_constructor = self._IsTypeConstructor(js_type) 124 is_constructor = self._IsTypeConstructor(js_type)
118 if is_constructor: 125 if js_type.property_type is not PropertyType.OBJECT:
119 c.Comment('@constructor', comment_prefix = ' * ', wrap_indent=4) 126 self._js_util.AppendTypeJsDoc(c, self._namespace.name, js_type)
127 elif is_constructor:
128 c.Comment('@constructor', comment_prefix = '', wrap_indent=4)
120 else: 129 else:
121 self._AppendTypedef(c, js_type.properties) 130 self._AppendTypedef(c, js_type.properties)
122 131
123 c.Append(self._js_util.GetSeeLink(self._namespace.name, 'type', 132 c.Append(self._js_util.GetSeeLink(self._namespace.name, 'type',
124 js_type.simple_name)) 133 js_type.simple_name))
125 c.Eblock(' */') 134 c.Eblock(' */')
126 135
127 var = 'chrome.%s.%s' % (js_type.namespace.name, js_type.simple_name) 136 var = '%s.%s' % (self._GetNamespace(), js_type.simple_name)
128 if is_constructor: var += ' = function() {}' 137 if is_constructor: var += ' = function() {}'
129 var += ';' 138 var += ';'
130 c.Append(var) 139 c.Append(var)
131 140
141 if is_constructor:
142 c.Append()
143 self._class_name = js_type.name
Devlin 2017/01/04 23:54:21 given this is designed to be popped on/off, maybe
144 for prop in js_type.properties.values():
145 if prop.type_.property_type is PropertyType.FUNCTION:
146 self._AppendFunction(c, prop.type_.function)
147 else:
148 self._AppendTypeJsDoc(c, prop.type_)
149 c.Append()
150 self._class_name = None
151
132 def _AppendTypedef(self, c, properties): 152 def _AppendTypedef(self, c, properties):
133 """Given an OrderedDict of properties, Appends code containing a @typedef. 153 """Given an OrderedDict of properties, Appends code containing a @typedef.
134 """ 154 """
135 if not properties: return 155 if not properties: return
136 156
137 c.Append('@typedef {') 157 c.Append('@typedef {')
138 self._js_util.AppendObjectDefinition(c, self._namespace.name, properties, 158 self._js_util.AppendObjectDefinition(c, self._namespace.name, properties,
139 new_line=False) 159 new_line=False)
140 c.Append('}', new_line=False) 160 c.Append('}', new_line=False)
141 161
142 def _AppendFunction(self, c, function): 162 def _AppendFunction(self, c, function):
143 """Appends the code representing a function, including its documentation. 163 """Appends the code representing a function, including its documentation.
144 For example: 164 For example:
145 165
146 /** 166 /**
147 * @param {string} title The new title. 167 * @param {string} title The new title.
148 */ 168 */
149 chrome.window.setTitle = function(title) {}; 169 chrome.window.setTitle = function(title) {};
150 """ 170 """
151 self._js_util.AppendFunctionJsDoc(c, self._namespace.name, function) 171 self._js_util.AppendFunctionJsDoc(c, self._namespace.name, function)
152 params = self._GetFunctionParams(function) 172 params = self._GetFunctionParams(function)
153 c.Append('chrome.%s.%s = function(%s) {};' % (self._namespace.name, 173 c.Append('%s.%s = function(%s) {};' % (self._GetNamespace(),
154 function.name, params)) 174 function.name, params))
155 c.Append() 175 c.Append()
156 176
157 def _AppendEvent(self, c, event): 177 def _AppendEvent(self, c, event):
158 """Appends the code representing an event. 178 """Appends the code representing an event.
159 For example: 179 For example:
160 180
161 /** @type {!ChromeEvent} */ 181 /** @type {!ChromeEvent} */
162 chrome.bookmarks.onChildrenReordered; 182 chrome.bookmarks.onChildrenReordered;
163 """ 183 """
164 c.Sblock(line='/**', line_prefix=' * ') 184 c.Sblock(line='/**', line_prefix=' * ')
165 if (event.description): 185 if (event.description):
166 c.Comment(event.description, comment_prefix='') 186 c.Comment(event.description, comment_prefix='')
167 c.Append('@type {!ChromeEvent}') 187 c.Append('@type {!ChromeEvent}')
168 c.Append(self._js_util.GetSeeLink(self._namespace.name, 'event', 188 c.Append(self._js_util.GetSeeLink(self._namespace.name, 'event',
169 event.name)) 189 event.name))
170 c.Eblock(' */') 190 c.Eblock(' */')
171 c.Append('chrome.%s.%s;' % (self._namespace.name, event.name)) 191 c.Append('%s.%s;' % (self._GetNamespace(), event.name))
172 c.Append() 192 c.Append()
173 193
174 def _AppendNamespaceObject(self, c): 194 def _AppendNamespaceObject(self, c):
175 """Appends the code creating namespace object. 195 """Appends the code creating namespace object.
176 For example: 196 For example:
177 197
178 /** 198 /**
179 * @const 199 * @const
180 */ 200 */
181 chrome.bookmarks = {}; 201 chrome.bookmarks = {};
182 """ 202 """
183 c.Append("""/** 203 c.Append("""/**
184 * @const 204 * @const
185 */""") 205 */""")
186 c.Append('chrome.%s = {};' % self._namespace.name) 206 c.Append('chrome.%s = {};' % self._namespace.name)
187 c.Append() 207 c.Append()
188 208
189 def _GetFunctionParams(self, function): 209 def _GetFunctionParams(self, function):
190 """Returns the function params string for function. 210 """Returns the function params string for function.
191 """ 211 """
192 params = function.params[:] 212 params = function.params[:]
193 if function.callback: 213 if function.callback:
194 params.append(function.callback) 214 params.append(function.callback)
195 return ', '.join(param.name for param in params) 215 return ', '.join(param.name for param in params)
216
217 def _GetNamespace(self):
218 """Returns the namespace to be prepended to a top-level typedef.
219
220 For example, it might return "chrome.namespace".
221
222 Also optionally includes the class name if this is in the context
223 of outputting the members of a class.
224
225 For example, "chrome.namespace.ClassName.prototype"
226 """
227 if self._class_name:
228 return 'chrome.%s.%s.prototype' % (self._namespace.name, self._class_name)
229 else:
230 return 'chrome.%s' % self._namespace.name
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698