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

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

Issue 1488773003: Add js_interface_generator for generating extensions interfaces (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years 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 2015 The Chromium Authors. All rights reserved.
Devlin 2015/12/02 17:58:28 Do we really need a new generator, rather than jus
stevenjb 2015/12/02 18:07:40 See below :) I started on that path, but there ar
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 interface file for the Closure Compiler.
6 Note: This is a work in progress, and generated externs may require tweaking.
7 """
8
9 from code import Code
10 from model import *
11 from schema_util import *
12
13 import os
14 import sys
15 from datetime import datetime
16 import re
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 INFO = """// This file was generated by:
24 // %s.
25 """
26
27 class JsInterfaceGenerator(object):
28 def Generate(self, namespace):
29 return _Generator(namespace).Generate()
30
31 def GetHeader(tool, namespace):
32 """Returns the file header text.
33 """
34 return (LICENSE + '\n' + (INFO % tool) + '\n' +
35 ('/** @fileoverview Interface for %s that can be overriden. */' %
36 namespace))
37 GetHeader = staticmethod(GetHeader)
michaelpg 2015/12/02 19:39:45 i'm pretty sure python 2.3 came out before i was b
stevenjb 2015/12/02 20:30:06 apparantly.
38
39 class _Generator(object):
40 def __init__(self, namespace):
41 self._namespace = namespace
42 first = namespace.name[0].upper()
43 rest = namespace.name[1:]
44 self._interface = first + rest
45
46 def Generate(self):
47 """Generates a Code object with the schema for the entire namespace.
48 """
49 c = Code()
50 c.Append(JsInterfaceGenerator.GetHeader(
51 (sys.argv[0]), self._namespace.name)).Append()
michaelpg 2015/12/02 19:39:45 4-space indent
stevenjb 2015/12/02 20:30:06 Done.
52
53 c.Cblock(self._GenerateInterfaceObject())
54
55 c.Sblock('%s.prototype = {' % self._interface)
56
57 for function in self._namespace.functions.values():
58 c.Cblock(self._GenerateFunction(function))
59
60 for event in self._namespace.events.values():
61 c.Cblock(self._GenerateEvent(event))
62
63 c.Eblock('};')
64
65 return c
66
67 def _GenerateInterfaceObject(self):
68 """Generates the code creating the interface object.
69 For example:
70 /** @interface */
71 function SettingsPrivate() {}
72 """
73 c = Code()
74 (c.Append('/** @interface */')
75 .Append('function %s() {}' % self._interface))
76 return c
77
78 def _GenerateFunctionJsDoc(self, function):
79 """Generates the documentation for a function as a Code.
80 """
81 c = Code()
82
83 c.Sblock(line='/**', line_prefix=' * ')
84
85 if function.description:
86 c.Comment(function.description, comment_prefix='')
87
88 def append_field(c, tag, js_type, name, optional, description):
89 c.Append('@%s {' % tag)
90 c.Concat(js_type, new_line=False)
91 if optional:
92 c.Append('=', new_line=False)
93 c.Append('} %s' % name, new_line=False)
94 if description:
95 c.Comment(' %s' % description, comment_prefix='',
96 wrap_indent=4, new_line=False)
97
98 for param in function.params:
99 append_field(c, 'param', self._TypeToJsType(param.type_), param.name,
100 param.optional, param.description)
101
102 if function.callback:
103 append_field(c, 'param', self._FunctionToJsFunction(function.callback),
104 function.callback.name, function.callback.optional,
105 function.callback.description)
106
107 if function.returns:
108 append_field(c, 'return', self._TypeToJsType(function.returns),
109 '', False, function.returns.description)
110
111 c.Eblock(' */')
112 return c
113
114 def _GenerateFunction(self, function):
115 """Generates the inteface for a function, including a JSDoc comment.
116 """
117 c = Code()
118 if function.deprecated:
119 return c
120
121 (c.Concat(self._GenerateFunctionJsDoc(function))
122 .Append('%s: assertNotReached,' % (function.name)))
123
124 return c
125
126 def _GenerateEvent(self, event):
127 """Generates the interface for an event.
128 """
129 c = Code()
130 c.Sblock(line='/**', line_prefix=' * ')
131 if (event.description):
132 c.Comment(event.description, comment_prefix='')
133 c.Append('@type {!ChromeEvent}')
134 c.Eblock(' */')
135 c.Append('%s: new ChromeEvent(),' % (event.name))
136 return c
137
138 def _FunctionToJsFunction(self, function):
139 """Converts a model.Function to a JS type (i.e., function([params])...)"""
140 c = Code()
141 c.Append('function(')
142 for i, param in enumerate(function.params):
143 c.Concat(self._TypeToJsType(param.type_), new_line=False)
144 if i is not len(function.params) - 1:
145 c.Append(', ', new_line=False, strip_right=False)
146 c.Append('):', new_line=False)
147
148 if function.returns:
149 c.Concat(self._TypeToJsType(function.returns), new_line=False)
150 else:
151 c.Append('void', new_line=False)
152
153 return c
154
155 def _TypeToJsType(self, js_type):
156 """Converts a model.Type to a JS type (number, Array, etc.)"""
157 if js_type.property_type in (PropertyType.INTEGER, PropertyType.DOUBLE):
158 return Code().Append('number')
159 if js_type.property_type is PropertyType.OBJECT:
160 if js_type.properties:
161 return self._GenerateObjectDefinition(js_type.properties)
162 return Code().Append('Object')
163 if js_type.property_type is PropertyType.ARRAY:
164 return (Code().Append('!Array<').
165 Concat(self._TypeToJsType(js_type.item_type), new_line=False).
166 Append('>', new_line=False))
167 if js_type.property_type is PropertyType.REF:
168 ref_type = '!chrome.%s.%s' % (self._namespace.name, js_type.ref_type)
169 return Code().Append(ref_type)
170 if js_type.property_type is PropertyType.CHOICES:
171 c = Code()
172 c.Append('(')
173 for i, choice in enumerate(js_type.choices):
174 c.Concat(self._TypeToJsType(choice), new_line=False)
175 if i is not len(js_type.choices) - 1:
176 c.Append('|', new_line=False)
177 c.Append(')', new_line=False)
178 return c
179 if js_type.property_type is PropertyType.FUNCTION:
180 return self._FunctionToJsFunction(js_type.function)
181 if js_type.property_type is PropertyType.ANY:
182 return Code().Append('*')
183 if js_type.property_type.is_fundamental:
184 return Code().Append(js_type.property_type.name)
185 return Code().Append('?') # TODO(tbreisacher): Make this more specific.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698