Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 from model import PropertyType | 5 from model import PropertyType |
| 6 import any_helper | |
| 6 import code | 7 import code |
| 7 import cpp_util | 8 import cpp_util |
| 8 import util_cc_helper | 9 import util_cc_helper |
| 9 | 10 |
| 10 class CCGenerator(object): | 11 class CCGenerator(object): |
| 11 """A .cc generator for a namespace. | 12 """A .cc generator for a namespace. |
| 12 """ | 13 """ |
| 13 def __init__(self, namespace, cpp_type_generator): | 14 def __init__(self, namespace, cpp_type_generator): |
| 14 self._cpp_type_generator = cpp_type_generator | 15 self._cpp_type_generator = cpp_type_generator |
| 15 self._namespace = namespace | 16 self._namespace = namespace |
| 16 self._target_namespace = ( | 17 self._target_namespace = ( |
| 17 self._cpp_type_generator.GetCppNamespaceName(self._namespace)) | 18 self._cpp_type_generator.GetCppNamespaceName(self._namespace)) |
| 18 self._util_cc_helper = ( | 19 self._util_cc_helper = ( |
| 19 util_cc_helper.UtilCCHelper(self._cpp_type_generator)) | 20 util_cc_helper.UtilCCHelper(self._cpp_type_generator)) |
| 21 self._any_helper = any_helper.AnyHelper() | |
| 20 | 22 |
| 21 def Generate(self): | 23 def Generate(self): |
| 22 """Generates a code.Code object with the .cc for a single namespace. | 24 """Generates a code.Code object with the .cc for a single namespace. |
| 23 """ | 25 """ |
| 24 c = code.Code() | 26 c = code.Code() |
| 25 (c.Append(cpp_util.CHROMIUM_LICENSE) | 27 (c.Append(cpp_util.CHROMIUM_LICENSE) |
| 26 .Append() | 28 .Append() |
| 27 .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file) | 29 .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file) |
| 28 .Append() | 30 .Append() |
| 29 .Append(self._util_cc_helper.GetIncludePath()) | 31 .Append(self._util_cc_helper.GetIncludePath()) |
| 30 .Append('#include "%s/%s.h"' % | 32 .Append('#include "%s/%s.h"' % |
| 31 (self._namespace.source_file_dir, self._namespace.name)) | 33 (self._namespace.source_file_dir, self._namespace.name)) |
| 32 ) | 34 ) |
| 33 includes = self._cpp_type_generator.GenerateIncludes() | 35 includes = self._cpp_type_generator.GenerateIncludes() |
| 34 if not includes.IsEmpty(): | 36 if not includes.IsEmpty(): |
| 35 (c.Concat(includes) | 37 (c.Concat(includes) |
| 36 .Append() | 38 .Append() |
| 37 ) | 39 ) |
| 38 | 40 |
| 39 (c.Append() | 41 (c.Append() |
| 40 .Append('using base::Value;') | 42 .Append('using base::Value;') |
| 41 .Append('using base::DictionaryValue;') | 43 .Append('using base::DictionaryValue;') |
| 42 .Append('using base::ListValue;') | 44 .Append('using base::ListValue;') |
| 45 .Append('using %s;' % any_helper.ANY_CLASS) | |
| 43 .Append() | 46 .Append() |
| 44 .Concat(self._cpp_type_generator.GetRootNamespaceStart()) | 47 .Concat(self._cpp_type_generator.GetRootNamespaceStart()) |
| 45 .Concat(self._cpp_type_generator.GetNamespaceStart()) | 48 .Concat(self._cpp_type_generator.GetNamespaceStart()) |
| 46 .Append() | 49 .Append() |
| 47 ) | 50 ) |
| 48 if self._namespace.types: | 51 if self._namespace.types: |
| 49 (c.Append('//') | 52 (c.Append('//') |
| 50 .Append('// Types') | 53 .Append('// Types') |
| 51 .Append('//') | 54 .Append('//') |
| 52 .Append() | 55 .Append() |
| 53 ) | 56 ) |
| 54 for type_ in self._namespace.types.values(): | 57 for type_ in self._namespace.types.values(): |
| 55 (c.Concat(self._GenerateType(type_.name, type_)) | 58 (c.Concat(self._GenerateType(type_.name, type_)) |
| 56 .Append() | 59 .Append() |
| 57 ) | 60 ) |
| 58 if self._namespace.functions: | 61 if self._namespace.functions: |
| 59 (c.Append('//') | 62 (c.Append('//') |
| 60 .Append('// Functions') | 63 .Append('// Functions') |
| 61 .Append('//') | 64 .Append('//') |
| 62 .Append() | 65 .Append() |
| 63 ) | 66 ) |
| 64 for function in self._namespace.functions.values(): | 67 for function in self._namespace.functions.values(): |
| 65 (c.Concat(self._GenerateFunction(function)) | 68 (c.Concat(self._GenerateFunction( |
| 69 cpp_util.Classname(function.name), function)) | |
| 66 .Append() | 70 .Append() |
| 67 ) | 71 ) |
| 68 (c.Concat(self._cpp_type_generator.GetNamespaceEnd()) | 72 (c.Concat(self._cpp_type_generator.GetNamespaceEnd()) |
| 69 .Concat(self._cpp_type_generator.GetRootNamespaceEnd()) | 73 .Concat(self._cpp_type_generator.GetRootNamespaceEnd()) |
| 70 .Append() | 74 .Append() |
| 71 ) | 75 ) |
| 72 # TODO(calamity): Events | 76 # TODO(calamity): Events |
| 73 return c | 77 return c |
| 74 | 78 |
| 75 def _GenerateType(self, cpp_namespace, type_): | 79 def _GenerateType(self, cpp_namespace, type_): |
| 76 """Generates the function definitions for a type. | 80 """Generates the function definitions for a type. |
| 77 """ | 81 """ |
| 78 classname = cpp_util.Classname(type_.name) | 82 classname = cpp_util.Classname(type_.name) |
| 79 c = code.Code() | 83 c = code.Code() |
| 80 | 84 |
| 81 (c.Concat(self._GeneratePropertyFunctions( | 85 # Functions on types cannot have properties on them and are not |
| 82 cpp_namespace, type_.properties.values())) | 86 # instantiable because they're dealt with renderer side. |
| 83 .Append('%(namespace)s::%(classname)s() {}') | 87 if type_.functions: |
| 84 .Append('%(namespace)s::~%(classname)s() {}') | 88 assert not type_.properties |
| 85 .Append() | 89 for function in type_.functions.values(): |
| 86 ) | 90 (c.Concat( |
| 87 if type_.from_json: | 91 self._GenerateFunction( |
| 88 (c.Concat(self._GenerateTypePopulate(cpp_namespace, type_)) | 92 cpp_namespace + '::' + cpp_util.Classname(function.name), |
| 93 function)) | |
| 94 .Append() | |
| 95 ) | |
| 96 else: | |
| 97 (c.Concat(self._GeneratePropertyFunctions( | |
| 98 cpp_namespace, type_.properties.values())) | |
| 99 .Append('%(namespace)s::%(classname)s() {}') | |
| 100 .Append('%(namespace)s::~%(classname)s() {}') | |
| 89 .Append() | 101 .Append() |
| 90 ) | 102 ) |
| 91 if type_.from_client: | 103 if type_.from_json: |
| 92 c.Concat(self._GenerateTypeToValue(cpp_namespace, type_)) | 104 (c.Concat(self._GenerateTypePopulate(cpp_namespace, type_)) |
| 93 c.Append() | 105 .Append() |
| 106 ) | |
| 107 if type_.from_client: | |
| 108 (c.Concat(self._GenerateTypeToValue(cpp_namespace, type_)) | |
| 109 .Append() | |
| 110 ) | |
| 94 c.Substitute({'classname': classname, 'namespace': cpp_namespace}) | 111 c.Substitute({'classname': classname, 'namespace': cpp_namespace}) |
| 95 | 112 |
| 96 return c | 113 return c |
| 97 | 114 |
| 98 def _GenerateTypePopulate(self, cpp_namespace, type_): | 115 def _GenerateTypePopulate(self, cpp_namespace, type_): |
| 99 """Generates the function for populating a type given a pointer to it. | 116 """Generates the function for populating a type given a pointer to it. |
| 117 | |
| 118 E.g for type "Foo", generates Foo::Populate() | |
| 100 """ | 119 """ |
| 101 classname = cpp_util.Classname(type_.name) | 120 classname = cpp_util.Classname(type_.name) |
| 102 c = code.Code() | 121 c = code.Code() |
| 103 (c.Append('// static') | 122 (c.Append('// static') |
| 104 .Sblock('bool %(namespace)s::Populate' | 123 .Sblock('bool %(namespace)s::Populate' |
| 105 '(const Value& value, %(name)s* out) {') | 124 '(const Value& value, %(name)s* out) {') |
| 106 .Append('if (!value.IsType(Value::TYPE_DICTIONARY))') | 125 .Append('if (!value.IsType(Value::TYPE_DICTIONARY))') |
| 107 .Append(' return false;') | 126 .Append(' return false;') |
| 108 .Append('const DictionaryValue* dict = ' | 127 .Append('const DictionaryValue* dict = ' |
| 109 'static_cast<const DictionaryValue*>(&value);') | 128 'static_cast<const DictionaryValue*>(&value);') |
| 110 .Append() | 129 .Append() |
| 111 ) | 130 ) |
| 112 for prop in type_.properties.values(): | 131 for prop in type_.properties.values(): |
| 113 c.Concat(self._InitializePropertyToDefault(prop, 'out')) | 132 c.Concat(self._InitializePropertyToDefault(prop, 'out')) |
| 114 for prop in type_.properties.values(): | 133 for prop in type_.properties.values(): |
| 115 c.Concat(self._GenerateTypePopulateProperty(prop, 'dict', 'out')) | 134 if prop.type_ == PropertyType.ADDITIONAL_PROPERTIES: |
| 135 c.Append('out->additional_properties.MergeDictionary(dict);') | |
| 136 # remove all keys that are actual properties | |
| 137 for key in type_.properties: | |
| 138 if prop.name != key: | |
| 139 c.Append('out->additional_properties' | |
|
Yoyo Zhou
2012/02/28 22:23:41
The additional properties can't have any name conf
calamity
2012/03/01 04:47:09
The additional properties are the keys in the dict
not at google - send to devlin
2012/03/01 07:09:37
I think he meant what I pointed out, that if you h
| |
| 140 '.RemoveWithoutPathExpansion("%s", NULL);' % key) | |
| 141 c.Append() | |
| 142 else: | |
| 143 c.Concat(self._GenerateTypePopulateProperty(prop, 'dict', 'out')) | |
| 116 (c.Append('return true;') | 144 (c.Append('return true;') |
| 117 .Eblock('}') | 145 .Eblock('}') |
| 118 ) | 146 ) |
| 119 c.Substitute({'namespace': cpp_namespace, 'name': classname}) | 147 c.Substitute({'namespace': cpp_namespace, 'name': classname}) |
| 120 return c | 148 return c |
| 121 | 149 |
| 122 def _GenerateTypePopulateProperty(self, prop, src, dst): | 150 def _GenerateTypePopulateProperty(self, prop, src, dst): |
| 123 """Generate the code to populate a single property in a type. | 151 """Generate the code to populate a single property in a type. |
| 124 | 152 |
| 125 src: DictionaryValue* | 153 src: DictionaryValue* |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 142 .Append(' return false;') | 170 .Append(' return false;') |
| 143 .Concat(self._GeneratePopulatePropertyFromValue( | 171 .Concat(self._GeneratePopulatePropertyFromValue( |
| 144 prop, value_var, dst, 'false')) | 172 prop, value_var, dst, 'false')) |
| 145 ) | 173 ) |
| 146 c.Append() | 174 c.Append() |
| 147 c.Substitute({'value_var': value_var, 'key': prop.name, 'src': src}) | 175 c.Substitute({'value_var': value_var, 'key': prop.name, 'src': src}) |
| 148 return c | 176 return c |
| 149 | 177 |
| 150 def _GenerateTypeToValue(self, cpp_namespace, type_): | 178 def _GenerateTypeToValue(self, cpp_namespace, type_): |
| 151 """Generates a function that serializes the type into a |DictionaryValue|. | 179 """Generates a function that serializes the type into a |DictionaryValue|. |
| 180 | |
| 181 E.g. for type "Foo" generates Foo::ToValue() | |
| 152 """ | 182 """ |
| 153 c = code.Code() | 183 c = code.Code() |
| 154 (c.Sblock('scoped_ptr<DictionaryValue> %s::ToValue() const {' % | 184 (c.Sblock('scoped_ptr<DictionaryValue> %s::ToValue() const {' % |
| 155 cpp_namespace) | 185 cpp_namespace) |
| 156 .Append('scoped_ptr<DictionaryValue> value(new DictionaryValue());') | 186 .Append('scoped_ptr<DictionaryValue> value(new DictionaryValue());') |
| 157 .Append() | 187 .Append() |
| 158 ) | 188 ) |
| 159 for prop in type_.properties.values(): | 189 for prop in type_.properties.values(): |
| 160 if prop.optional: | 190 if prop.type_ == PropertyType.ADDITIONAL_PROPERTIES: |
| 161 if prop.type_ == PropertyType.ENUM: | 191 c.Append('value->MergeDictionary(&%s);' % prop.unix_name) |
| 162 c.Sblock('if (%s != %s)' % | 192 else: |
| 163 (prop.unix_name, self._cpp_type_generator.GetEnumNoneValue(prop))) | 193 if prop.optional: |
| 164 else: | 194 if prop.type_ == PropertyType.ENUM: |
| 165 c.Sblock('if (%s.get())' % prop.unix_name) | 195 c.Sblock('if (%s != %s)' % |
| 166 c.Append('value->SetWithoutPathExpansion("%s", %s);' % ( | 196 (prop.unix_name, |
| 167 prop.name, | 197 self._cpp_type_generator.GetEnumNoneValue(prop))) |
| 168 self._CreateValueFromProperty(prop, prop.unix_name))) | 198 else: |
| 169 if prop.optional: | 199 c.Sblock('if (%s.get())' % prop.unix_name) |
| 170 c.Eblock(); | 200 c.Append('value->SetWithoutPathExpansion("%s", %s);' % ( |
| 201 prop.name, | |
| 202 self._CreateValueFromProperty(prop, prop.unix_name))) | |
| 203 if prop.optional: | |
| 204 c.Eblock(); | |
| 171 (c.Append() | 205 (c.Append() |
| 172 .Append('return value.Pass();') | 206 .Append('return value.Pass();') |
| 173 .Eblock('}') | 207 .Eblock('}') |
| 174 ) | 208 ) |
| 175 return c | 209 return c |
| 176 | 210 |
| 177 def _GenerateFunction(self, function): | 211 def _GenerateFunction(self, cpp_namespace, function): |
| 178 """Generates the definitions for function structs. | 212 """Generates the definitions for function structs. |
| 179 """ | 213 """ |
| 180 classname = cpp_util.Classname(function.name) | |
| 181 c = code.Code() | 214 c = code.Code() |
| 182 | 215 |
| 183 # Params::Populate function | 216 # Params::Populate function |
| 184 if function.params: | 217 if function.params: |
| 185 c.Concat(self._GeneratePropertyFunctions(classname + '::Params', | 218 c.Concat(self._GeneratePropertyFunctions(cpp_namespace + '::Params', |
| 186 function.params)) | 219 function.params)) |
| 187 (c.Append('%(name)s::Params::Params() {}') | 220 (c.Append('%(cpp_namespace)s::Params::Params() {}') |
| 188 .Append('%(name)s::Params::~Params() {}') | 221 .Append('%(cpp_namespace)s::Params::~Params() {}') |
| 189 .Append() | 222 .Append() |
| 190 .Concat(self._GenerateFunctionParamsCreate(function)) | 223 .Concat(self._GenerateFunctionParamsCreate(cpp_namespace, function)) |
| 191 .Append() | 224 .Append() |
| 192 ) | 225 ) |
| 193 | 226 |
| 194 # Result::Create function | 227 # Result::Create function |
| 195 if function.callback: | 228 if function.callback: |
| 196 c.Concat(self._GenerateFunctionResultCreate(function)) | 229 c.Concat(self._GenerateFunctionResultCreate(cpp_namespace, function)) |
| 197 | 230 |
| 198 c.Substitute({'name': classname}) | 231 c.Substitute({'cpp_namespace': cpp_namespace}) |
| 199 | 232 |
| 200 return c | 233 return c |
| 201 | 234 |
| 202 def _GenerateCreateEnumValue(self, cpp_namespace, prop): | 235 def _GenerateCreateEnumValue(self, cpp_namespace, prop): |
| 203 """Generates a function that returns the |StringValue| representation of an | 236 """Generates CreateEnumValue() that returns the |StringValue| |
| 204 enum. | 237 representation of an enum. |
| 205 """ | 238 """ |
| 206 c = code.Code() | 239 c = code.Code() |
| 207 c.Append('// static') | 240 c.Append('// static') |
| 208 c.Sblock('scoped_ptr<Value> %(cpp_namespace)s::CreateEnumValue(%(arg)s) {') | 241 c.Sblock('scoped_ptr<Value> %(cpp_namespace)s::CreateEnumValue(%(arg)s) {') |
| 209 c.Sblock('switch (%s) {' % prop.unix_name) | 242 c.Sblock('switch (%s) {' % prop.unix_name) |
| 210 if prop.optional: | 243 if prop.optional: |
| 211 (c.Append('case %s: {' % self._cpp_type_generator.GetEnumNoneValue(prop)) | 244 (c.Append('case %s: {' % self._cpp_type_generator.GetEnumNoneValue(prop)) |
| 212 .Append(' return scoped_ptr<Value>();') | 245 .Append(' return scoped_ptr<Value>();') |
| 213 .Append('}') | 246 .Append('}') |
| 214 ) | 247 ) |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 226 c.Eblock('}') | 259 c.Eblock('}') |
| 227 c.Eblock('}') | 260 c.Eblock('}') |
| 228 c.Substitute({ | 261 c.Substitute({ |
| 229 'cpp_namespace': cpp_namespace, | 262 'cpp_namespace': cpp_namespace, |
| 230 'arg': cpp_util.GetParameterDeclaration( | 263 'arg': cpp_util.GetParameterDeclaration( |
| 231 prop, self._cpp_type_generator.GetType(prop)) | 264 prop, self._cpp_type_generator.GetType(prop)) |
| 232 }) | 265 }) |
| 233 return c | 266 return c |
| 234 | 267 |
| 235 def _CreateValueFromProperty(self, prop, var): | 268 def _CreateValueFromProperty(self, prop, var): |
| 236 """Creates a Value given a single property. Generated code passes ownership | 269 """Creates a Value given a property. Generated code passes ownership |
| 237 to caller. | 270 to caller. |
| 238 | 271 |
| 239 var: variable or variable* | 272 var: variable or variable* |
| 273 | |
| 274 E.g for std::string, generate Value::CreateStringValue(var) | |
| 240 """ | 275 """ |
| 241 if prop.type_ == PropertyType.CHOICES: | 276 if prop.type_ == PropertyType.CHOICES: |
| 242 # CHOICES conversion not implemented because it's not used. If needed, | 277 # CHOICES conversion not implemented. If needed, write something to |
| 243 # write something to generate a function that returns a scoped_ptr<Value> | 278 # generate a function that returns a scoped_ptr<Value> and put it in |
| 244 # and put it in _GeneratePropertyFunctions. | 279 # _GeneratePropertyFunctions, then use it here. Look at CreateEnumValue() |
| 280 # for reference. | |
| 245 raise NotImplementedError( | 281 raise NotImplementedError( |
| 246 'Conversion of CHOICES to Value not implemented') | 282 'Conversion of CHOICES to Value not implemented') |
| 247 if prop.type_ in (PropertyType.REF, PropertyType.OBJECT): | 283 if prop.type_ in (PropertyType.REF, PropertyType.OBJECT): |
| 248 if prop.optional: | 284 if prop.optional: |
| 249 return '%s->ToValue().release()' % var | 285 return '%s->ToValue().release()' % var |
| 250 else: | 286 else: |
| 251 return '%s.ToValue().release()' % var | 287 return '%s.ToValue().release()' % var |
| 288 elif prop.type_ == PropertyType.ANY: | |
| 289 return '%s.DeepCopy()' % self._any_helper.GetValue(prop, var) | |
| 290 elif prop.type_ == PropertyType.ADDITIONAL_PROPERTIES: | |
| 291 return '%s.DeepCopy()' % var | |
| 252 elif prop.type_ == PropertyType.ENUM: | 292 elif prop.type_ == PropertyType.ENUM: |
| 253 return 'CreateEnumValue(%s).release()' % var | 293 return 'CreateEnumValue(%s).release()' % var |
| 254 elif prop.type_ == PropertyType.ARRAY: | 294 elif prop.type_ == PropertyType.ARRAY: |
| 255 return '%s.release()' % self._util_cc_helper.CreateValueFromArray( | 295 return '%s.release()' % self._util_cc_helper.CreateValueFromArray( |
| 256 prop, var) | 296 prop, var) |
| 257 elif prop.type_.is_fundamental: | 297 elif prop.type_.is_fundamental: |
| 258 if prop.optional: | 298 if prop.optional: |
| 259 var = '*' + var | 299 var = '*' + var |
| 260 return { | 300 return { |
| 261 PropertyType.STRING: 'Value::CreateStringValue(%s)', | 301 PropertyType.STRING: 'Value::CreateStringValue(%s)', |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 284 c.Append('if (%(var)s.GetSize() < %(required)d' | 324 c.Append('if (%(var)s.GetSize() < %(required)d' |
| 285 ' || %(var)s.GetSize() > %(total)d)') | 325 ' || %(var)s.GetSize() > %(total)d)') |
| 286 c.Append(' return scoped_ptr<Params>();') | 326 c.Append(' return scoped_ptr<Params>();') |
| 287 c.Substitute({ | 327 c.Substitute({ |
| 288 'var': var, | 328 'var': var, |
| 289 'required': num_required, | 329 'required': num_required, |
| 290 'total': len(function.params), | 330 'total': len(function.params), |
| 291 }) | 331 }) |
| 292 return c | 332 return c |
| 293 | 333 |
| 294 def _GenerateFunctionParamsCreate(self, function): | 334 def _GenerateFunctionParamsCreate(self, cpp_namespace, function): |
| 295 """Generate function to create an instance of Params. The generated | 335 """Generate function to create an instance of Params. The generated |
| 296 function takes a ListValue of arguments. | 336 function takes a ListValue of arguments. |
| 337 | |
| 338 E.g for function "Bar", generate Bar::Params::Create() | |
| 297 """ | 339 """ |
| 298 classname = cpp_util.Classname(function.name) | |
| 299 c = code.Code() | 340 c = code.Code() |
| 300 (c.Append('// static') | 341 (c.Append('// static') |
| 301 .Sblock('scoped_ptr<%(classname)s::Params> %(classname)s::Params::Create' | 342 .Sblock('scoped_ptr<%(cpp_namespace)s::Params> ' |
| 302 '(const ListValue& args) {') | 343 '%(cpp_namespace)s::Params::Create(const ListValue& args) {') |
| 303 .Concat(self._GenerateParamsCheck(function, 'args')) | 344 .Concat(self._GenerateParamsCheck(function, 'args')) |
| 304 .Append('scoped_ptr<Params> params(new Params());') | 345 .Append('scoped_ptr<Params> params(new Params());') |
| 305 ) | 346 ) |
| 306 c.Substitute({'classname': classname}) | 347 c.Substitute({'cpp_namespace': cpp_namespace}) |
| 307 | 348 |
| 308 for param in function.params: | 349 for param in function.params: |
| 309 c.Concat(self._InitializePropertyToDefault(param, 'params')) | 350 c.Concat(self._InitializePropertyToDefault(param, 'params')) |
| 310 | 351 |
| 311 for i, param in enumerate(function.params): | 352 for i, param in enumerate(function.params): |
| 312 # Any failure will cause this function to return. If any argument is | 353 # Any failure will cause this function to return. If any argument is |
| 313 # incorrect or missing, those following it are not processed. Note that | 354 # incorrect or missing, those following it are not processed. Note that |
| 314 # this is still correct in the case of multiple optional arguments as an | 355 # this is still correct in the case of multiple optional arguments as an |
| 315 # optional argument at position 4 cannot exist without an argument at | 356 # optional argument at position 4 cannot exist without an argument at |
| 316 # position 3. | 357 # position 3. |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 346 prop: the property the code is populating. | 387 prop: the property the code is populating. |
| 347 value_var: a Value* that should represent |prop|. | 388 value_var: a Value* that should represent |prop|. |
| 348 dst: the object with |prop| as a member. | 389 dst: the object with |prop| as a member. |
| 349 failure_value: the value to return if |prop| cannot be extracted from | 390 failure_value: the value to return if |prop| cannot be extracted from |
| 350 |value_var| | 391 |value_var| |
| 351 check_type: if true, will check if |value_var| is the correct Value::Type | 392 check_type: if true, will check if |value_var| is the correct Value::Type |
| 352 """ | 393 """ |
| 353 c = code.Code() | 394 c = code.Code() |
| 354 c.Sblock('{') | 395 c.Sblock('{') |
| 355 | 396 |
| 356 if check_type and prop.type_ != PropertyType.CHOICES: | 397 if check_type and prop.type_ not in ( |
| 398 PropertyType.CHOICES, PropertyType.ANY): | |
| 357 (c.Append('if (!%(value_var)s->IsType(%(value_type)s))') | 399 (c.Append('if (!%(value_var)s->IsType(%(value_type)s))') |
| 358 .Append(' return %(failure_value)s;') | 400 .Append(' return %(failure_value)s;') |
| 359 ) | 401 ) |
| 360 | 402 |
| 361 if prop.type_.is_fundamental: | 403 if prop.type_.is_fundamental: |
| 362 if prop.optional: | 404 if prop.optional: |
| 363 (c.Append('%(ctype)s temp;') | 405 (c.Append('%(ctype)s temp;') |
| 364 .Append('if (%s)' % | 406 .Append('if (%s)' % |
| 365 cpp_util.GetAsFundamentalValue(prop, value_var, '&temp')) | 407 cpp_util.GetAsFundamentalValue(prop, value_var, '&temp')) |
| 366 .Append(' %(dst)s->%(name)s.reset(new %(ctype)s(temp));') | 408 .Append(' %(dst)s->%(name)s.reset(new %(ctype)s(temp));') |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 382 .Append('%(dst)s->%(name)s = temp.Pass();') | 424 .Append('%(dst)s->%(name)s = temp.Pass();') |
| 383 ) | 425 ) |
| 384 else: | 426 else: |
| 385 (c.Append('DictionaryValue* dictionary = NULL;') | 427 (c.Append('DictionaryValue* dictionary = NULL;') |
| 386 .Append('if (!%(value_var)s->GetAsDictionary(&dictionary))') | 428 .Append('if (!%(value_var)s->GetAsDictionary(&dictionary))') |
| 387 .Append(' return %(failure_value)s;') | 429 .Append(' return %(failure_value)s;') |
| 388 .Append( | 430 .Append( |
| 389 'if (!%(ctype)s::Populate(*dictionary, &%(dst)s->%(name)s))') | 431 'if (!%(ctype)s::Populate(*dictionary, &%(dst)s->%(name)s))') |
| 390 .Append(' return %(failure_value)s;') | 432 .Append(' return %(failure_value)s;') |
| 391 ) | 433 ) |
| 434 elif prop.type_ == PropertyType.ANY: | |
| 435 if prop.optional: | |
| 436 c.Append('%(dst)s->%(name)s.reset(new Any());') | |
| 437 c.Append(self._any_helper.CopyInto(prop, value_var, dst) + ';') | |
| 392 elif prop.type_ == PropertyType.ARRAY: | 438 elif prop.type_ == PropertyType.ARRAY: |
| 393 # util_cc_helper deals with optional and required arrays | 439 # util_cc_helper deals with optional and required arrays |
| 394 (c.Append('ListValue* list = NULL;') | 440 (c.Append('ListValue* list = NULL;') |
| 395 .Append('if (!%(value_var)s->GetAsList(&list))') | 441 .Append('if (!%(value_var)s->GetAsList(&list))') |
| 396 .Append(' return %(failure_value)s;') | 442 .Append(' return %(failure_value)s;') |
| 397 .Append('if (!%s)' % self._util_cc_helper.PopulateArrayFromList( | 443 .Append('if (!%s)' % self._util_cc_helper.PopulateArrayFromList( |
| 398 prop, 'list', dst + '->' + prop.unix_name)) | 444 prop, 'list', dst + '->' + prop.unix_name)) |
| 399 .Append(' return %(failure_value)s;') | 445 .Append(' return %(failure_value)s;') |
| 400 ) | 446 ) |
| 401 elif prop.type_ == PropertyType.CHOICES: | 447 elif prop.type_ == PropertyType.CHOICES: |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 435 ) | 481 ) |
| 436 else: | 482 else: |
| 437 raise NotImplementedError(prop.type_) | 483 raise NotImplementedError(prop.type_) |
| 438 c.Eblock('}') | 484 c.Eblock('}') |
| 439 sub = { | 485 sub = { |
| 440 'value_var': value_var, | 486 'value_var': value_var, |
| 441 'name': prop.unix_name, | 487 'name': prop.unix_name, |
| 442 'dst': dst, | 488 'dst': dst, |
| 443 'failure_value': failure_value, | 489 'failure_value': failure_value, |
| 444 } | 490 } |
| 445 if prop.type_ != PropertyType.CHOICES: | 491 if prop.type_ not in (PropertyType.CHOICES, PropertyType.ANY): |
| 446 sub['ctype'] = self._cpp_type_generator.GetType(prop) | 492 sub['ctype'] = self._cpp_type_generator.GetType(prop) |
| 447 sub['value_type'] = cpp_util.GetValueType(prop) | 493 sub['value_type'] = cpp_util.GetValueType(prop) |
| 448 c.Substitute(sub) | 494 c.Substitute(sub) |
| 449 return c | 495 return c |
| 450 | 496 |
| 451 def _GeneratePropertyFunctions(self, param_namespace, params): | 497 def _GeneratePropertyFunctions(self, param_namespace, params): |
| 452 """Generate the functions for structures generated by a property such as | 498 """Generate the functions for structures generated by a property such as |
| 453 CreateEnumValue for ENUMs and Populate/ToValue for Params/Result objects. | 499 CreateEnumValue for ENUMs and Populate/ToValue for Params/Result objects. |
| 454 """ | 500 """ |
| 455 c = code.Code() | 501 c = code.Code() |
| 456 for param in params: | 502 for param in params: |
| 457 if param.type_ == PropertyType.OBJECT: | 503 if param.type_ == PropertyType.OBJECT: |
| 458 c.Concat(self._GenerateType( | 504 c.Concat(self._GenerateType( |
| 459 param_namespace + '::' + cpp_util.Classname(param.name), | 505 param_namespace + '::' + cpp_util.Classname(param.name), |
| 460 param)) | 506 param)) |
| 461 c.Append() | 507 c.Append() |
| 462 elif param.type_ == PropertyType.ENUM: | 508 elif param.type_ == PropertyType.ENUM: |
| 463 c.Concat(self._GenerateCreateEnumValue(param_namespace, param)) | 509 c.Concat(self._GenerateCreateEnumValue(param_namespace, param)) |
| 464 c.Append() | 510 c.Append() |
| 465 return c | 511 return c |
| 466 | 512 |
| 467 def _GenerateFunctionResultCreate(self, function): | 513 def _GenerateFunctionResultCreate(self, cpp_namespace, function): |
| 468 """Generate function to create a Result given the return value. | 514 """Generate function to create a Result given the return value. |
| 515 | |
| 516 E.g for function "Bar", generate Bar::Result::Create | |
| 469 """ | 517 """ |
| 470 classname = cpp_util.Classname(function.name) | |
| 471 c = code.Code() | 518 c = code.Code() |
| 472 params = function.callback.params | 519 params = function.callback.params |
| 473 | 520 |
| 474 if not params: | 521 if not params: |
| 475 (c.Append('Value* %s::Result::Create() {' % classname) | 522 (c.Append('Value* %s::Result::Create() {' % cpp_namespace) |
| 476 .Append(' return Value::CreateNullValue();') | 523 .Append(' return Value::CreateNullValue();') |
| 477 .Append('}') | 524 .Append('}') |
| 478 ) | 525 ) |
| 479 else: | 526 else: |
| 480 expanded_params = self._cpp_type_generator.GetExpandedChoicesInParams( | 527 expanded_params = self._cpp_type_generator.GetExpandedChoicesInParams( |
| 481 params) | 528 params) |
| 482 c.Concat(self._GeneratePropertyFunctions( | 529 c.Concat(self._GeneratePropertyFunctions( |
| 483 classname + '::Result', expanded_params)) | 530 cpp_namespace + '::Result', expanded_params)) |
| 484 | 531 |
| 485 # If there is a single parameter, this is straightforward. However, if | 532 # If there is a single parameter, this is straightforward. However, if |
| 486 # the callback parameter is of 'choices', this generates a Create method | 533 # the callback parameter is of 'choices', this generates a Create method |
| 487 # for each choice. This works because only 1 choice can be returned at a | 534 # for each choice. This works because only 1 choice can be returned at a |
| 488 # time. | 535 # time. |
| 489 for param in expanded_params: | 536 for param in expanded_params: |
| 537 if param.type_ == PropertyType.ANY: | |
| 538 # Generation of Value* Create(Value*) is redundant. | |
| 539 continue | |
| 490 # We treat this argument as 'required' to avoid wrapping it in a | 540 # We treat this argument as 'required' to avoid wrapping it in a |
| 491 # scoped_ptr if it's optional. | 541 # scoped_ptr if it's optional. |
| 492 param_copy = param.Copy() | 542 param_copy = param.Copy() |
| 493 param_copy.optional = False | 543 param_copy.optional = False |
| 494 c.Sblock('Value* %(classname)s::Result::Create(const %(arg)s) {') | 544 c.Sblock('Value* %(cpp_namespace)s::Result::Create(const %(arg)s) {') |
| 495 c.Append('return %s;' % | 545 c.Append('return %s;' % |
| 496 self._CreateValueFromProperty(param_copy, param_copy.unix_name)) | 546 self._CreateValueFromProperty(param_copy, param_copy.unix_name)) |
| 497 c.Eblock('}') | 547 c.Eblock('}') |
| 498 c.Substitute({'classname': classname, | 548 c.Substitute({ |
| 549 'cpp_namespace': cpp_namespace, | |
| 499 'arg': cpp_util.GetParameterDeclaration( | 550 'arg': cpp_util.GetParameterDeclaration( |
| 500 param_copy, self._cpp_type_generator.GetType(param_copy)) | 551 param_copy, self._cpp_type_generator.GetType(param_copy)) |
| 501 }) | 552 }) |
| 502 | 553 |
| 503 return c | 554 return c |
| 504 | 555 |
| 505 def _InitializePropertyToDefault(self, prop, dst): | 556 def _InitializePropertyToDefault(self, prop, dst): |
| 506 """Initialize a model.Property to its default value inside an object. | 557 """Initialize a model.Property to its default value inside an object. |
| 507 | 558 |
| 559 E.g for optional enum "state", generate dst->state = STATE_NONE; | |
| 560 | |
| 508 dst: Type* | 561 dst: Type* |
| 509 """ | 562 """ |
| 510 c = code.Code() | 563 c = code.Code() |
| 511 if prop.type_ in (PropertyType.ENUM, PropertyType.CHOICES): | 564 if prop.type_ in (PropertyType.ENUM, PropertyType.CHOICES): |
| 512 if prop.optional: | 565 if prop.optional: |
| 513 prop_name = prop.unix_name | 566 prop_name = prop.unix_name |
| 514 if prop.type_ == PropertyType.CHOICES: | 567 if prop.type_ == PropertyType.CHOICES: |
| 515 prop_name = prop.unix_name + '_type' | 568 prop_name = prop.unix_name + '_type' |
| 516 c.Append('%s->%s = %s;' % ( | 569 c.Append('%s->%s = %s;' % ( |
| 517 dst, | 570 dst, |
| 518 prop_name, | 571 prop_name, |
| 519 self._cpp_type_generator.GetEnumNoneValue(prop))) | 572 self._cpp_type_generator.GetEnumNoneValue(prop))) |
| 520 return c | 573 return c |
| 521 | 574 |
| OLD | NEW |