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

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

Issue 9114036: Code generation for extensions api (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: switched namespaces, various rework Created 8 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
(Empty)
1 # Copyright (c) 2012 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 from model import PropertyType
6 import code
7 import cpp_type_generator
Yoyo Zhou 2012/01/23 23:16:42 Looks like you're not using this import. (Same in
calamity 2012/01/24 22:57:22 Done.
8 import cpp_util
9
10 class CCGenerator(object):
11 """A .cc generator for a namespace.
12 """
13 def __init__(self, namespace, model, cpp_type_generator):
14 self._cpp_type_generator = cpp_type_generator
15 self._namespace = namespace
16 self._target_namespace = (
17 self._cpp_type_generator.getCppNamespaceName(self._namespace))
18
19 def generate(self):
Yoyo Zhou 2012/01/23 23:16:42 Method names should start with caps.
calamity 2012/01/24 22:57:22 Done.
20 """Generates a code.Code object with the .cc for a single namespace.
21 """
22 c = code.Code()
23 (c.append(cpp_util.CHROMIUM_LICENSE)
24 .append()
25 .append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file)
26 .append()
27 .append('#include "tools/json_schema_compiler/util.h"')
28 .append('#include "%s/%s.h"' %
29 (self._namespace.source_file_dir, self._target_namespace))
30 .append()
31 .concat(self._cpp_type_generator.getCppNamespaceStart())
32 .append()
33 .append('//')
34 .append('// Types')
35 .append('//')
36 .append()
37 )
38 for type_ in self._namespace.types.values():
39 (c.concat(self._generateType(type_))
40 .append()
41 )
42 (c.append('//')
43 .append('// Functions')
44 .append('//')
45 .append()
46 )
47 for function in self._namespace.functions.values():
48 (c.concat(self._generateFunction(function))
49 .append()
50 )
51 (c.concat(self._cpp_type_generator.getCppNamespaceEnd())
52 .append()
53 )
54 # TODO(calamity): Events
55 return c
56
57 def _generateType(self, type_):
58 """Generates the function definitions for a type.
59 """
60 c = code.Code()
61
62 (c.append('%(classname)s::%(classname)s() {}')
63 .append('%(classname)s::~%(classname)s() {}')
64 .append()
65 )
66 c.substitute({'classname': type_.name})
67
68 c.concat(self._generateTypePopulate(type_))
69 c.append()
70 # TODO(calamity): deal with non-serializable
71 c.concat(self._generateTypeTovalue(type_))
72 c.append()
73
74 return c
75
76 def _generateTypePopulate(self, type_):
77 """Generates the function for populating a type given a pointer to it.
78 """
79 c = code.Code()
80 (c.append('// static')
81 .sblock('bool %(name)s::Populate(const Value& value, %(name)s* out) {')
82 .append('if (!value.IsType(Value::TYPE_DICTIONARY))')
83 .append(' return false;')
84 .append('const DictionaryValue* dict = '
85 'static_cast<const DictionaryValue*>(&value);')
86 .append()
87 )
88 c.substitute({'name': type_.name})
89
90 # TODO(calamity): this handle single PropertyType.REF properties.
Yoyo Zhou 2012/01/23 23:16:42 This comment seems incomplete.
calamity 2012/01/24 22:57:22 Done.
91 # add ALL the types
92 for prop in type_.properties.values():
93 sub = {'name': prop.name}
94 if prop.type_ == PropertyType.ARRAY:
95 if prop.item_type.type_ == PropertyType.REF:
96 if prop.optional:
97 (c.append('if (!json_schema_compiler::util::'
98 'GetOptionalTypes<%(type)s>(*dict,')
99 .append(' "%(name)s", &out->%(name)s))')
100 .append(' return false;')
101 )
102 else:
103 (c.append('if (!json_schema_compiler::util::'
104 'GetTypes<%(type)s>(*dict,')
105 .append(' "%(name)s", &out->%(name)s))')
106 .append(' return false;')
107 )
108 sub['type'] = self._cpp_type_generator.getType(prop.item_type,
109 pad_for_generics=True)
110 elif prop.item_type.type_ == PropertyType.STRING:
111 if prop.optional:
112 (c.append('if (!json_schema_compiler::util::GetOptionalStrings'
113 '(*dict, "%(name)s", &out->%(name)s))')
114 .append(' return false;')
115 )
116 else:
117 (c.append('if (!json_schema_compiler::util::GetStrings'
118 '(*dict, "%(name)s", &out->%(name)s))')
119 .append(' return false;')
120 )
121 else:
122 raise NotImplementedError(prop.item_type.type_)
123 elif proptype_.is_fundamental:
Yoyo Zhou 2012/01/23 23:16:42 prop.type_?
calamity 2012/01/24 22:57:22 Done.
124 c.append('if (!dict->%s)' %
125 cpp_util.getFundamentalValue(prop, '&out->%s' % prop.name))
126 c.append(' return false;')
127 else:
128 raise NotImplementedError(prop.type_)
129 c.substitute(sub)
130 (c.append('return true;')
131 .eblock('}')
132 )
133 return c
134
135 def _generateTypeTovalue(self, type_):
Yoyo Zhou 2012/01/23 23:16:42 ToValue
calamity 2012/01/24 22:57:22 Done.
136 """Generates a function that serializes the type into a |DictionaryValue|.
137 """
138 c = code.Code()
139 (c.sblock('DictionaryValue* %s::ToValue() const {' % type_.name)
140 .append('DictionaryValue* value = new DictionaryValue();')
141 .append()
142 )
143 name = type_.name.lower()
144 for prop in type_.properties.values():
145 prop_name = name + '_' + prop.name if name else prop.name
146 this_var = prop.name
147 c.concat(self._createValueFromProperty(prop_name, prop, this_var))
148 (c.append()
149 .append('return value;')
150 .eblock('}')
151 )
152 return c
153
154 # TODO(calamity): object and choices proptypes
155 def _createValueFromProperty(self, name, prop, var):
156 """Generates code to serialize a single property in a type.
157 """
158 c = code.Code()
159 if prop.type_.is_fundamental:
160 c.append('Value* %s_value = %s;' %
161 (name, cpp_util.createFundamentalValue(prop, var)))
162 elif prop.type_ == PropertyType.ARRAY:
163 if prop.item_type.type_ == PropertyType.STRING:
164 if prop.optional:
165 c.append('json_schema_compiler::util::'
166 'SetOptionalStrings(%s, "%s", value);' % (var, prop.name))
167 else:
168 c.append('json_schema_compiler::util::'
169 'SetStrings(%s, "%s", value);' % (var, prop.name))
170 else:
171 item_name = name + '_single'
172 (c.append('ListValue* %(name)s_value = new ListValue();')
173 .append('for (%(it_type)s::iterator it = %(var)s->begin();')
174 .sblock(' it != %(var)s->end(); ++it) {')
175 .concat(self._createValueFromProperty(item_name, prop.item_type,
176 '*it'))
177 .append('%(name)s_value->Append(%(prop_val)s_value);')
178 .eblock('}')
179 )
180 c.substitute(
181 {'it_type': self._cpp_type_generator.getType(prop),
182 'name': name, 'var': var, 'prop_val': item_name})
183 elif prop.type_ == PropertyType.REF:
184 c.append('Value* %s_value = %s.ToValue();' % (name, var))
185 else:
186 raise NotImplementedError
187 return c
188
189 def _generateFunction(self, function):
190 """Generates the definitions for function structs.
191 """
192 classname = cpp_util.cppName(function.name)
193 c = code.Code()
194
195 # Params::Populate function
196 if function.params:
197 (c.append('%(name)s::Params::Params() {}')
198 .append('%(name)s::Params::~Params() {}')
199 .append()
200 .concat(self._generateFunctionParamsCreate(function))
201 .append()
202 )
203
204 # Result::Create function
205 c.concat(self._generateFunctionResultCreate(function))
206
207 c.substitute({'name': classname})
208
209 return c
210
211 def _generateFunctionParamsCreate(self, function):
212 """Generate function to create an instance of Params given a pointer.
213 """
214 classname = cpp_util.cppName(function.name)
215 c = code.Code()
216 c.append('// static')
217 c.append('%(classname)s::Params* %(classname)s::Params::Create'
218 '(const ListValue& args) {')
219 c.substitute({'classname': classname})
220 c.append('if (args.GetSize() != %d)' % len(function.params))
221 c.append(' return NULL;')
222
223 # TODO(calamity): generalize, needs to move to function to do populates for
224 # wider variety of args
225 for i, param in enumerate(function.params):
226 sub = {'name': param.name, 'pos': i}
227 c.append()
228 # TODO(calamity): Make valid for not just objects
229 c.append('DictionaryValue* %(name)s_param = NULL;')
230 c.append('if (!args.GetDictionary(%(pos)d, &%(name)s_param))')
231 c.append(' return NULL;')
232 c.append('scoped_ptr<Params> out;')
Yoyo Zhou 2012/01/23 23:16:42 Should this be outside the for loop? Why not use
calamity 2012/01/24 22:57:22 Done. I made it a scoped_ptr so it would clean up
233 if param.type_ == PropertyType.REF:
234 c.append('if (!%(ctype)s::Populate(*%(name)s_param, &out->%(name)s))')
235 c.append(' return NULL;')
236 sub['ctype'] = self._cpp_type_generator.getType(param)
237 elif param.type_.is_fundamental:
238 raise NotImplementedError('Fundamental types are unimplemented')
239 elif param.type_ == PropertyType.OBJECT:
240 c.append('if (!%(ctype)s::Populate(*%(name)s_param, &out->%(name)s))')
241 c.append(' return NULL;')
242 sub['ctype'] = self._cpp_type_generator.getType(param)
243 elif param.type_ == PropertyType.CHOICES:
244 raise NotImplementedError('Choices is unimplemented')
245 else:
246 raise NotImplementedError(param.type_)
247 c.substitute(sub)
248 c.append()
249 c.append('return out.release();')
250 c.eblock('}')
251
252 return c
253
254 def _generateFunctionResultCreate(self, function):
255 """Generate function to create a Result given the return value.
256 """
257 classname = cpp_util.cppName(function.name)
258 c = code.Code()
259 c.append('// static')
260 param = function.callback.param
261 arg = ''
262 if param:
263 if param.type_ == PropertyType.REF:
264 arg = 'const %(type)s& %(name)s'
265 else:
266 arg = 'const %(type)s %(name)s'
267 arg = arg % {
268 'type': self._cpp_type_generator.getType(param),
269 'name': param.name
270 }
271 c.sblock('Value* %(classname)s::Result::Create(%(arg)s) {')
272 sub = {'classname': classname, 'arg': arg}
273 # TODO(calamity): Choices
274 if not param:
275 c.append('return Value::CreateNullValue();')
276 else:
277 sub['argname'] = param.name
278 if param.type_.is_fundamental:
279 c.append('return %s;' %
280 cpp_util.createFundamentalValue(param, param.name))
281 elif param.type_ == PropertyType.REF:
282 c.append('DictionaryValue* result = new DictionaryValue();')
283 c.append('result->SetWithoutPathExpansion("%(argname)s",'
284 '%(argname)s.ToValue());')
285 c.append('return result;')
286 elif param.type_ == PropertyType.OBJECT:
287 raise NotImplementedError('Objects not implemented')
288 elif param.type_ == PropertyType.ARRAY:
289 raise NotImplementedError('Arrays not implemented')
290 else:
291 raise NotImplementedError(param.type_)
292 c.substitute(sub)
293 c.eblock('}')
294 return c
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698