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

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

Issue 9114036: Code generation for extensions api (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: added generated files, removed trailing whitespace 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) 2011 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
8 class CC_Generator(object):
9 """A .cc generator for a namespace."""
10
11 def __init__(self, namespace, model):
12 self.type_manager = code.TypeManager(namespace, model)
13 self.namespace = namespace
14
15 def generate(self):
16 """Generates the .cc code for a single namespace.
17
18 Returns a code.Code object.
19 """
20 include_path = self.namespace.parent_dir
21 filename = self.namespace.filename
22 c = code.Code()
23 c.append(code.CHROMIUM_LICENSE).append()
24 c.append(code.WARNING_MESSAGE % self.namespace.parent_path)
25 c.append()
26 c.append('#include "tools/json_schema_compiler/util.h"')
27 c.append('#include "%s/%s.h"' % (include_path, filename))
28 # c.append('#include "base/json/json_converter.h"')
not at google - send to devlin 2012/01/12 06:01:05 what's this?
calamity 2012/01/12 22:59:20 Don't know, it was in the original spec. You said
not at google - send to devlin 2012/01/13 00:07:27 Oh yeah, never mind about that. Sorry.
29 c.append()
30 c.append('namespace extensions {')
31 c.append('namespace %s {' % filename)
32 c.append()
33 c.append('//')
34 c.append('// Types')
35 c.append('//')
36 c.append()
37 for tipe in self.namespace.types.values():
38 c.add(self.generate_type(tipe))
39 c.append('//')
40 c.append('// Functions')
41 c.append('//')
42 c.append()
43 for function in self.namespace.functions.values():
44 c.add(self.generate_function(function))
45 c.append('} // namespace extensions')
46 c.append('} // namespace %s' % filename)
47 # TODO(calamity): Events
not at google - send to devlin 2012/01/12 06:01:05 TODO should be before the end of the namespaces
calamity 2012/01/16 04:01:06 ??? So move this TODO up?
not at google - send to devlin 2012/01/17 01:59:24 Well you'd generate the events after the functions
48 return c
49
50 def generate_type(self, tipe):
51 """Generates the function definitions for a type in the namespace."""
52 c = code.Code()
53 classname = '%s' % (tipe.name)
54
55 c.append('%(classname)s::%(classname)s() {}')
56 c.append('%(classname)s::~%(classname)s() {}')
57 c.substitute({'classname': classname})
58 c.append()
59
60 c.add(self.generate_type_populate(tipe))
61 # TODO(calamity): deal with non-serializable
62 c.add(self.generate_type_tovalue(tipe))
63 c.append()
64
65 return c
66
67 def generate_type_populate(self, tipe):
68 """Generates the function for populating a type given a pointer to it."""
69 c = code.Code()
70 c.append('// static')
71 c.sblock('bool %(name)s::Populate(const Value& value, %(name)s* out) {')
72 c.substitute({'name': tipe.name})
73 c.append('if (!value.IsType(Value::TYPE_DICTIONARY))')
74 c.append(' return false;')
75 c.append('const DictionaryValue* dict = '
76 'static_cast<const DictionaryValue*>(&value);')
77
78 c.append()
79 # TODO(calamity): this doesn't even handle single properties.
80 # add ALL the types
81 for prop in tipe.properties.values():
82 sub = {'name': prop.name}
83 if prop.type == PropertyType.ARRAY:
84 if prop.item_type.type == PropertyType.REF:
85 if prop.optional:
86 c.append('if (!api_util::GetOptionalTypes<%(type)s>(*dict,')
87 c.append(' "%(name)s", &out->%(name)s))')
88 c.append(' return false;')
89 else:
90 c.append('if (!api_util::GetTypes<%(type)s>(*dict,')
91 c.append(' "%(name)s", &out->%(name)s))')
92 c.append(' return false;')
93 sub['type'] = self.type_manager.get_generic_type(prop.item_type)
94 elif prop.item_type.json_type == 'string':
95 if prop.optional:
96 c.append('if (!api_util::GetOptionalStrings'
97 '(*dict, "%(name)s", &out->%(name)s))')
98 c.append(' return false;')
99 else:
100 c.append('if (!api_util::GetStrings'
101 '(*dict, "%(name)s", &out->%(name)s))')
102 c.append(' return false;')
103 else:
104 raise NotImplementedError(prop.item_type.json_type)
105 elif prop.type == PropertyType.FUNDAMENTAL:
106 c.append('if(!dict->%s)' % get_fundamental_value(prop,
107 '&out->%s' % prop.name))
108 c.append(' return false;')
109 else:
110 raise NotImplementedError(prop.type)
111 c.substitute(sub)
112 c.append('return true;')
113 c.eblock('}')
114 c.append()
115 return c
116
117 def generate_type_tovalue(self, tipe):
118 """Generates a function that serializes the type into a
119 |DictionaryValue|."""
120 c = code.Code()
121 c.sblock('Value* %s::ToValue() const {' % tipe.name)
122 name = tipe.name.lower()
123 c.append('DictionaryValue* value = new DictionaryValue();')
124 c.append()
125 for prop in tipe.properties.values():
126 prop_name = name + '_' + prop.name if name else prop.name
127 this_var = prop.name
128 c.add(self.create_value_from_property(prop_name, prop, this_var))
129 c.append()
130 c.append('return value;')
131
132 c.eblock('}')
133 return c
134
135 # TODO(calamity): object and choices proptypes
136 def create_value_from_property(self, name, prop, var):
137 """Generates code to serialize a single property in a type."""
138 c = code.Code()
139 if prop.type == PropertyType.FUNDAMENTAL:
140 c.append(
141 'Value* %s_value = %s;' % (name, create_fundamental_value(prop, var)))
142 elif prop.type == PropertyType.ARRAY:
143 if prop.item_type.json_type == 'string':
144 if prop.optional:
145 c.append('api_util::SetOptionalStrings(%s, "%s", value);' % (var,
146 prop.name))
147 else:
148 c.append('api_util::SetStrings(%s, "%s", value);' % (var, prop.name))
149 else:
150 item_name = name + '_single'
151 c.append('ListValue* %(name)s_value = new ListValue();')
152 c.append('for (%(it_type)s::iterator it = %(var)s->begin();')
153 c.sblock(' it != %(var)s->end(); ++it) {')
154 c.add(self.create_value_from_property(item_name, prop.item_type, '*it'))
155 c.append('%(name)s_value->Append(%(prop_val)s_value);')
156 c.substitute(
157 {'it_type': self.type_manager.get_type(prop),
158 'name': name, 'var': var, 'prop_val': item_name})
159 c.eblock('}')
160 elif prop.type == PropertyType.REF:
161 c.append('Value* %s_value = %s.ToValue();' % (name, var))
162 else:
163 raise NotImplementedError
164 return c
165
166 def generate_function(self, function):
167 """Generates the definitions for function structs."""
168 classname = code.cpp_name(function.name)
169 c = code.Code()
170
171 # Params::Populate function
172 if function.params:
173 c.append('%(name)s::Params::Params() {}')
174 c.append('%(name)s::Params::~Params() {}')
175 c.append()
176 c.add(self.generate_function_params_populate(function))
177
178 # Result::Create function
179 c.add(self.generate_function_result_create(function))
180
181 c.substitute({'name': classname})
182
183 return c
184
185 def generate_function_params_populate(self, function):
186 """Generate function to populate an instance of Params given a pointer."""
187 classname = code.cpp_name(function.name)
188 c = code.Code()
189 c.append('// static')
190 c.append('bool %(classname)s::Params::Populate(const ListValue& args,')
191 c.sblock(' %(classname)s::Params* out) {')
192 c.substitute({'classname': classname})
193 c.append('if (args.GetSize() != %d)' % len(function.params))
194 c.append(' return false;')
195
196 # TODO(calamity): generalize, needs to move to function to do populates for
197 # wider variety of args
198 for i, param in enumerate(function.params):
199 sub = {'name': param.name, 'pos': i}
200 c.append()
201 # TODO(calamity): Make valid for not just objects
202 c.append('DictionaryValue* %(name)s_param = NULL;')
203 c.append('if (!args.GetDictionary(%(pos)d, &%(name)s_param))')
204 c.append(' return false;')
205 if param.type == PropertyType.REF:
206 c.append('if (!%(ctype)s::Populate(*%(name)s_param, &out->%(name)s))')
207 c.append(' return false;')
208 sub['ctype'] = self.type_manager.get_type(param)
209 elif param.type == PropertyType.FUNDAMENTAL:
210 #XXX THIS IS WRONG
211 c.append('// TODO Needs some sort of casting')
212 c.append('if (!%(name)s_param->' +
213 get_fundamental_value(param,'&out->%s' % param.name) +');')
214 c.append(' return false;')
215 elif param.type == PropertyType.OBJECT:
216 c.append('if(!%(ctype)s::Populate(*%(name)s_param, &out->%(name)s))')
217 c.append(' return false;')
218 sub['ctype'] = self.type_manager.get_type(param)
219 elif param.type == PropertyType.CHOICES:
220 c.append('// TODO handle chocies')
221 else:
222 raise NotImplementedError(param.type)
223 c.substitute(sub)
224 c.append()
225 c.append('return true;')
226 c.eblock('}')
227 c.append()
228
229 return c
230
231 def generate_function_result_create(self, function):
232 """Generate function to create a Result given the return value."""
233 classname = code.cpp_name(function.name)
234 c = code.Code()
235 c.append('// static')
236 param = function.callback.param
237 arg = ''
238 if param:
239 arg = 'const ' + self.type_manager.parameter_declaration(param,
240 type_modifiers={PropertyType.REF: code.ParamFormat.REFERENCE})
241 c.sblock('Value* %(classname)s::Result::Create(%(arg)s) {')
242 sub = {'classname': classname, 'arg': arg}
243 # TODO(calamity): Choices
244 if not param:
245 c.append('return Value::CreateNullValue();')
246 else:
247 sub['argname'] = param.name
248 if param.type == PropertyType.FUNDAMENTAL:
249 c.append('return %s;' % create_fundamental_value(param, param.name))
250 elif param.type == PropertyType.REF:
251 c.append('DictionaryValue* result = new DictionaryValue();')
252 c.append('result->Set("%(argname)s", %(argname)s.ToValue());')
253 c.append('return result;')
254 elif param.type == PropertyType.OBJECT:
255 c.append('// TODO object stuff')
256 elif param.type == PropertyType.ARRAY:
257 c.append('// TODO array stuff')
258 else:
259 raise NotImplementedError(param.type)
260 c.substitute(sub)
261 c.eblock('}')
262 c.append()
263 return c
264
265 def create_fundamental_value(prop, var):
266 """Returns the C++ code for creating a value of the given property type
267 using the given variable."""
268 return {
269 'string': 'Value::CreateStringValue(%s)',
270 'boolean': 'Value::CreateBooleanValue(%s)',
271 'integer': 'Value::CreateIntegerValue(%s)',
272 'double': 'Value::CreateDoubleValue(%s)',
273 }[prop.json_type] % var
274
275
276 def get_fundamental_value(prop, var):
277 """Returns the C++ code for retrieving a fundamental type from a Value
278 into a variable."""
279 return {
280 'string': 'GetAsString(%s)',
281 'boolean': 'GetAsBoolean(%s)',
282 'integer': 'GetAsInteger(%s)',
283 'double': 'GetAsDouble(%s)',
284 }[prop.json_type] % var
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698