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

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: a fistful of 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
8 import cpp_util
9
10 class CCGenerator(object):
Yoyo Zhou 2012/01/19 02:19:40 General comment: have a read through the style gui
11 """A .cc generator for a namespace.
12 """
13 def __init__(self, namespace, model, root_namespace):
14 self.__cpp_type_generator = cpp_type_generator.CppTypeGenerator(
15 namespace, model)
16 self.__namespace = namespace
17 self.__root_namespace = root_namespace
18
19 def generate(self):
20 """Generates a code.Code object with the .cc for a single namespace.
21 """
22 target_namespace = self.__namespace.target_namespace
23 c = code.Code()
24 (c.append(cpp_util.CHROMIUM_LICENSE)
25 .append()
26 .append(cpp_util.GENERATED_FILE_MESSAGE % self.__namespace.source_file)
27 .append()
28 .append('#include "tools/json_schema_compiler/util.h"')
29 .append('#include "%s/%s.h"' %
30 (self.__namespace.source_file_dir, target_namespace))
31 .append()
32 .append('namespace %s {' % self.__root_namespace)
33 .append('namespace %s {' % target_namespace)
34 .append()
35 .append('//')
36 .append('// Types')
37 .append('//')
38 .append()
39 )
40 for tipe in self.__namespace.types.values():
41 (c.concat(self.__generate_type(tipe))
42 .append()
43 )
44 (c.append('//')
45 .append('// Functions')
46 .append('//')
47 .append()
48 )
49 for function in self.__namespace.functions.values():
50 (c.concat(self.__generate_function(function))
51 .append()
52 )
53 (c.append('} // namespace %s' % self.__root_namespace)
54 .append('} // namespace %s' % target_namespace)
55 .append()
56 )
57 # TODO(calamity): Events
58 return c
59
60 def __generate_type(self, tipe):
Yoyo Zhou 2012/01/19 02:19:40 type_ is preferred over tipe.
calamity 2012/01/20 01:10:25 Done.
61 """Generates the function definitions for a type.
62 """
63 c = code.Code()
64
65 (c.append('%(classname)s::%(classname)s() {}')
66 .append('%(classname)s::~%(classname)s() {}')
67 .append()
68 )
69 c.substitute({'classname': tipe.name})
70
71 c.concat(self.__generate_type_populate(tipe))
72 c.append()
73 # TODO(calamity): deal with non-serializable
74 c.concat(self.__generate_type_tovalue(tipe))
75 c.append()
76
77 return c
78
79 def __generate_type_populate(self, tipe):
80 """Generates the function for populating a type given a pointer to it.
81 """
82 c = code.Code()
83 (c.append('// static')
84 .sblock('bool %(name)s::Populate(const Value& value, %(name)s* out) {')
85 .append('if (!value.IsType(Value::TYPE_DICTIONARY))')
86 .append(' return false;')
87 .append('const DictionaryValue* dict = '
88 'static_cast<const DictionaryValue*>(&value);')
89 .append()
90 )
91 c.substitute({'name': tipe.name})
92
93 # TODO(calamity): this doesn't even handle single properties.
94 # add ALL the types
95 for prop in tipe.properties.values():
96 sub = {'name': prop.name}
97 if prop.type == PropertyType.ARRAY:
98 if prop.item_type.type == PropertyType.REF:
99 if prop.optional:
100 (c.append('if (!json_schema_compiler::util::'
101 'GetOptionalTypes<%(type)s>(*dict,')
102 .append(' "%(name)s", &out->%(name)s))')
103 .append(' return false;')
104 )
105 else:
106 (c.append('if (!json_schema_compiler::util::'
107 'GetTypes<%(type)s>(*dict,')
108 .append(' "%(name)s", &out->%(name)s))')
109 .append(' return false;')
110 )
111 sub['type'] = self.__cpp_type_generator.get_type(prop.item_type,
112 pad_for_generics=True)
113 elif prop.item_type.type == PropertyType.STRING:
114 if prop.optional:
115 (c.append('if (!json_schema_compiler::util::GetOptionalStrings'
116 '(*dict, "%(name)s", &out->%(name)s))')
117 .append(' return false;')
118 )
119 else:
120 (c.append('if (!json_schema_compiler::util::GetStrings'
121 '(*dict, "%(name)s", &out->%(name)s))')
122 .append(' return false;')
123 )
124 else:
125 raise NotImplementedError(prop.item_type.type)
126 elif prop.type.is_fundamental:
127 c.append('if (!dict->%s)' % cpp_util.get_fundamental_value(prop,
128 '&out->%s' % prop.name))
129 c.append(' return false;')
130 else:
131 raise NotImplementedError(prop.type)
132 c.substitute(sub)
133 (c.append('return true;')
134 .eblock('}')
135 )
136 return c
137
138 def __generate_type_tovalue(self, tipe):
139 """Generates a function that serializes the type into a |DictionaryValue|.
140 """
141 c = code.Code()
142 (c.sblock('DictionaryValue* %s::ToValue() const {' % tipe.name)
143 .append('DictionaryValue* value = new DictionaryValue();')
144 .append()
145 )
146 name = tipe.name.lower()
147 for prop in tipe.properties.values():
148 prop_name = name + '_' + prop.name if name else prop.name
149 this_var = prop.name
150 c.concat(self.__create_value_from_property(prop_name, prop, this_var))
151 (c.append()
152 .append('return value;')
153 .eblock('}')
154 )
155 return c
156
157 # TODO(calamity): object and choices proptypes
158 def __create_value_from_property(self, name, prop, var):
159 """Generates code to serialize a single property in a type.
160 """
161 c = code.Code()
162 if prop.type.is_fundamental:
163 c.append('Value* %s_value = %s;' %
164 (name, cpp_util.create_fundamental_value(prop, var)))
165 elif prop.type == PropertyType.ARRAY:
166 if prop.item_type.type == PropertyType.STRING:
167 if prop.optional:
168 c.append('json_schema_compiler::util::'
169 'SetOptionalStrings(%s, "%s", value);' % (var, prop.name))
170 else:
171 c.append('json_schema_compiler::util::'
172 'SetStrings(%s, "%s", value);' % (var, prop.name))
173 else:
174 item_name = name + '_single'
175 (c.append('ListValue* %(name)s_value = new ListValue();')
176 .append('for (%(it_type)s::iterator it = %(var)s->begin();')
177 .sblock(' it != %(var)s->end(); ++it) {')
178 .concat(self.__create_value_from_property(item_name, prop.item_type,
179 '*it'))
180 .append('%(name)s_value->Append(%(prop_val)s_value);')
181 .eblock('}')
182 )
183 c.substitute(
184 {'it_type': self.__cpp_type_generator.get_type(prop),
185 'name': name, 'var': var, 'prop_val': item_name})
186 elif prop.type == PropertyType.REF:
187 c.append('Value* %s_value = %s.ToValue();' % (name, var))
188 else:
Yoyo Zhou 2012/01/19 02:19:40 This also doesn't handle single properties, right?
calamity 2012/01/20 01:10:25 fundamental types and REF types are the single pro
189 raise NotImplementedError
190 return c
191
192 def __generate_function(self, function):
193 """Generates the definitions for function structs.
194 """
195 classname = cpp_util.cpp_name(function.name)
196 c = code.Code()
197
198 # Params::Populate function
199 if function.params:
200 (c.append('%(name)s::Params::Params() {}')
201 .append('%(name)s::Params::~Params() {}')
202 .append()
203 .concat(self.__generate_function_params_populate(function))
204 .append()
205 )
206
207 # Result::Create function
208 c.concat(self.__generate_function_result_create(function))
209
210 c.substitute({'name': classname})
211
212 return c
213
214 def __generate_function_params_populate(self, function):
215 """Generate function to populate an instance of Params given a pointer.
216 """
217 classname = cpp_util.cpp_name(function.name)
218 c = code.Code()
219 c.append('// static')
220 c.append('bool %(classname)s::Params::Populate(const ListValue& args,')
221 c.sblock(' %(classname)s::Params* out) {')
222 c.substitute({'classname': classname})
223 c.append('if (args.GetSize() != %d)' % len(function.params))
224 c.append(' return false;')
225
226 # TODO(calamity): generalize, needs to move to function to do populates for
227 # wider variety of args
228 for i, param in enumerate(function.params):
229 sub = {'name': param.name, 'pos': i}
230 c.append()
231 # TODO(calamity): Make valid for not just objects
232 c.append('DictionaryValue* %(name)s_param = NULL;')
233 c.append('if (!args.GetDictionary(%(pos)d, &%(name)s_param))')
234 c.append(' return false;')
235 if param.type == PropertyType.REF:
236 c.append('if (!%(ctype)s::Populate(*%(name)s_param, &out->%(name)s))')
237 c.append(' return false;')
238 sub['ctype'] = self.__cpp_type_generator.get_type(param)
239 elif param.type.is_fundamental:
240 #XXX THIS IS WRONG
241 c.append('// TODO Needs some sort of casting')
Yoyo Zhou 2012/01/19 02:19:40 Seems like you could raise NotImplementedError her
calamity 2012/01/23 05:14:45 Done.
242 c.append('if (!%(name)s_param->' +
243 cpp_util.get_fundamental_value(param,'&out->%s' % param.name) +');')
244 c.append(' return false;')
245 elif param.type == PropertyType.OBJECT:
246 c.append('if (!%(ctype)s::Populate(*%(name)s_param, &out->%(name)s))')
247 c.append(' return false;')
248 sub['ctype'] = self.__cpp_type_generator.get_type(param)
249 elif param.type == PropertyType.CHOICES:
250 c.append('// TODO handle chocies')
251 else:
252 raise NotImplementedError(param.type)
253 c.substitute(sub)
254 c.append()
255 c.append('return true;')
256 c.eblock('}')
257
258 return c
259
260 def __generate_function_result_create(self, function):
261 """Generate function to create a Result given the return value.
262 """
263 classname = cpp_util.cpp_name(function.name)
264 c = code.Code()
265 c.append('// static')
266 param = function.callback.param
267 arg = ''
268 if param:
269 if param.type == PropertyType.REF:
270 arg = 'const %(type)s& %(name)s'
271 else:
272 arg = 'const %(type)s %(name)s'
273 arg = arg % {'type': self.__cpp_type_generator.get_type(param),
274 'name': param.name}
275 c.sblock('Value* %(classname)s::Result::Create(%(arg)s) {')
276 sub = {'classname': classname, 'arg': arg}
277 # TODO(calamity): Choices
278 if not param:
279 c.append('return Value::CreateNullValue();')
280 else:
281 sub['argname'] = param.name
282 if param.type.is_fundamental:
283 c.append('return %s;' %
284 cpp_util.create_fundamental_value(param, param.name))
285 elif param.type == PropertyType.REF:
286 c.append('DictionaryValue* result = new DictionaryValue();')
287 c.append('result->SetWithoutPathExpansion("%(argname)s",'
288 '%(argname)s.ToValue());')
289 c.append('return result;')
290 elif param.type == PropertyType.OBJECT:
291 c.append('// TODO object stuff')
292 elif param.type == PropertyType.ARRAY:
293 c.append('// TODO array stuff')
294 else:
295 raise NotImplementedError(param.type)
296 c.substitute(sub)
297 c.eblock('}')
298 return c
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698