15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import os
65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from code import Code
858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)from model import PropertyType
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import cpp_util
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import schema_util
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class HGenerator(object):
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  def __init__(self, type_generator):
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._type_generator = type_generator
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def Generate(self, namespace):
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return _Generator(namespace, self._type_generator).Generate()
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class _Generator(object):
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """A .h generator for a namespace.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  def __init__(self, namespace, cpp_type_generator):
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._namespace = namespace
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._type_helper = cpp_type_generator
26c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch    self._generate_error_messages = namespace.compiler_options.get(
27c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        'generate_error_messages', False)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Generate(self):
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generates a Code object with the .h for a single namespace.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (c.Append(cpp_util.CHROMIUM_LICENSE)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append()
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append()
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    )
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # Hack: for the purpose of gyp the header file will always be the source
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    # file with its file extension replaced by '.h'. Assume so.
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    output_file = os.path.splitext(self._namespace.source_file)[0] + '.h'
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ifndef_name = cpp_util.GenerateIfndefName(output_file)
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (c.Append('#ifndef %s' % ifndef_name)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append('#define %s' % ifndef_name)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append()
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Append('#include <map>')
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append('#include <string>')
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append('#include <vector>')
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append()
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append('#include "base/basictypes.h"')
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append('#include "base/logging.h"')
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append('#include "base/memory/linked_ptr.h"')
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append('#include "base/memory/scoped_ptr.h"')
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append('#include "base/values.h"')
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Cblock(self._type_helper.GenerateIncludes())
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append()
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    )
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # TODO(calamity): These forward declarations should be #includes to allow
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # $ref types from other files to be used as required params. This requires
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # some detangling of windows and tabs which will currently lead to circular
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # #includes.
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    c.Cblock(self._type_helper.GenerateForwardDeclarations())
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    cpp_namespace = cpp_util.GetCppNamespace(
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        self._namespace.environment.namespace_pattern,
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        self._namespace.unix_name)
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    c.Concat(cpp_util.OpenNamespace(cpp_namespace))
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c.Append()
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if self._namespace.properties:
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (c.Append('//')
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append('// Properties')
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append('//')
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append()
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      )
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for property in self._namespace.properties.values():
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        property_code = self._type_helper.GeneratePropertyValues(
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            property,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            'extern const %(type)s %(name)s;')
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if property_code:
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          c.Cblock(property_code)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if self._namespace.types:
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (c.Append('//')
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append('// Types')
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append('//')
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append()
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .Cblock(self._GenerateTypes(self._FieldDependencyOrder(),
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    is_toplevel=True,
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    generate_typedefs=True))
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      )
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if self._namespace.functions:
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (c.Append('//')
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append('// Functions')
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append('//')
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append()
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      )
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for function in self._namespace.functions.values():
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        c.Cblock(self._GenerateFunction(function))
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if self._namespace.events:
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (c.Append('//')
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append('// Events')
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append('//')
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append()
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      )
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for event in self._namespace.events.values():
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        c.Cblock(self._GenerateEvent(event))
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    (c.Concat(cpp_util.CloseNamespace(cpp_namespace))
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append('#endif  // %s' % ifndef_name)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append()
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    )
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _FieldDependencyOrder(self):
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generates the list of types in the current namespace in an order in which
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    depended-upon types appear before types which depend on them.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dependency_order = []
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def ExpandType(path, type_):
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if type_ in path:
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        raise ValueError("Illegal circular dependency via cycle " +
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         ", ".join(map(lambda x: x.name, path + [type_])))
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for prop in type_.properties.values():
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (prop.type_ == PropertyType.REF and
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            schema_util.GetNamespace(prop.ref_type) == self._namespace.name):
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ExpandType(path + [type_], self._namespace.types[prop.ref_type])
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not type_ in dependency_order:
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dependency_order.append(type_)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for type_ in self._namespace.types.values():
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ExpandType([], type_)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return dependency_order
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def _GenerateEnumDeclaration(self, enum_name, type_):
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    """Generate a code object with the  declaration of a C++ enum.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c.Sblock('enum %s {' % enum_name)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    c.Append(self._type_helper.GetEnumNoneValue(type_) + ',')
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for value in type_.enum_values:
142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      current_enum_string = self._type_helper.GetEnumValue(type_, value)
143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      c.Append(current_enum_string + ',')
144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    c.Append('%s = %s,' % (
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        self._type_helper.GetEnumLastValue(type_), current_enum_string))
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    c.Eblock('};')
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return c
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _GenerateFields(self, props):
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generates the field declarations when declaring a type.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    needs_blank_line = False
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for prop in props:
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if needs_blank_line:
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        c.Append()
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      needs_blank_line = True
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if prop.description:
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        c.Comment(prop.description)
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      # ANY is a base::Value which is abstract and cannot be a direct member, so
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      # we always need to wrap it in a scoped_ptr.
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      is_ptr = prop.optional or prop.type_.property_type == PropertyType.ANY
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (c.Append('%s %s;' % (
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           self._type_helper.GetCppType(prop.type_, is_ptr=is_ptr),
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           prop.unix_name))
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      )
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def _GenerateType(self, type_, is_toplevel=False, generate_typedefs=False):
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Generates a struct for |type_|.
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    |is_toplevel|       implies that the type was declared in the "types" field
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        of an API schema. This determines the correct function
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        modifier(s).
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    |generate_typedefs| controls whether primitive types should be generated as
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        a typedef. This may not always be desired. If false,
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        primitive types are ignored.
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if type_.functions:
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      # Wrap functions within types in the type's namespace.
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (c.Append('namespace %s {' % classname)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .Append()
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      )
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for function in type_.functions.values():
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        c.Cblock(self._GenerateFunction(function))
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      c.Append('}  // namespace %s' % classname)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    elif type_.property_type == PropertyType.ARRAY:
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if generate_typedefs and type_.description:
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        c.Comment(type_.description)
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      c.Cblock(self._GenerateType(type_.item_type))
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if generate_typedefs:
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (c.Append('typedef std::vector<%s > %s;' % (
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       self._type_helper.GetCppType(type_.item_type),
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       classname))
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        )
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    elif type_.property_type == PropertyType.STRING:
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if generate_typedefs:
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if type_.description:
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          c.Comment(type_.description)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        c.Append('typedef std::string %(classname)s;')
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    elif type_.property_type == PropertyType.ENUM:
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if type_.description:
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        c.Comment(type_.description)
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      c.Cblock(self._GenerateEnumDeclaration(classname, type_));
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      # Top level enums are in a namespace scope so the methods shouldn't be
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      # static. On the other hand, those declared inline (e.g. in an object) do.
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      maybe_static = '' if is_toplevel else 'static '
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      (c.Append()
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .Append('%sstd::string ToString(%s as_enum);' %
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                (maybe_static, classname))
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .Append('%s%s Parse%s(const std::string& as_string);' %
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                (maybe_static, classname, classname))
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      )
2177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    elif type_.property_type in (PropertyType.CHOICES,
2187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                 PropertyType.OBJECT):
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if type_.description:
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        c.Comment(type_.description)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (c.Sblock('struct %(classname)s {')
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          .Append('%(classname)s();')
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          .Append('~%(classname)s();')
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      )
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if type_.origin.from_json:
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (c.Append()
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          .Comment('Populates a %s object from a base::Value. Returns'
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   ' whether |out| was successfully populated.' % classname)
229c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          .Append('static bool Populate(%s);' % self._GenerateParams(
230c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch              ('const base::Value& value', '%s* out' % classname)))
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        )
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if is_toplevel:
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          (c.Append()
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            .Comment('Creates a %s object from a base::Value, or NULL on '
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     'failure.' % classname)
236c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch            .Append('static scoped_ptr<%s> FromValue(%s);' % (
237c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch                classname, self._GenerateParams(('const base::Value& value',))))
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          )
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if type_.origin.from_client:
2407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        value_type = ('base::Value'
2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                      if type_.property_type is PropertyType.CHOICES else
2427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                      'base::DictionaryValue')
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (c.Append()
2447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          .Comment('Returns a new %s representing the serialized form of this '
2457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                   '%s object.' % (value_type, classname))
2467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          .Append('scoped_ptr<%s> ToValue() const;' % value_type)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        )
2487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      if type_.property_type == PropertyType.CHOICES:
2497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        # Choices are modelled with optional fields for each choice. Exactly one
2507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        # field of the choice is guaranteed to be set by the compiler.
2517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        c.Cblock(self._GenerateTypes(type_.choices))
2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        c.Append('// Choices:')
2537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        for choice_type in type_.choices:
2547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          c.Append('%s as_%s;' % (
2557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              self._type_helper.GetCppType(choice_type, is_ptr=True),
2567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              choice_type.unix_name))
2577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      else:
2587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        properties = type_.properties.values()
2597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        (c.Append()
2607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          .Cblock(self._GenerateTypes(p.type_ for p in properties))
2617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          .Cblock(self._GenerateFields(properties)))
2627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if type_.additional_properties is not None:
2637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          # Most additionalProperties actually have type "any", which is better
2647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          # modelled as a DictionaryValue rather than a map of string -> Value.
2657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          if type_.additional_properties.property_type == PropertyType.ANY:
2667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            c.Append('base::DictionaryValue additional_properties;')
2677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          else:
2687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            (c.Cblock(self._GenerateType(type_.additional_properties))
2697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              .Append('std::map<std::string, %s> additional_properties;' %
2707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                  cpp_util.PadForGenerics(
2717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                      self._type_helper.GetCppType(type_.additional_properties,
2727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                                   is_in_container=True)))
2737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            )
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (c.Eblock()
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .Append()
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Sblock(' private:')
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          .Append('DISALLOW_COPY_AND_ASSIGN(%(classname)s);')
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Eblock('};')
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      )
2807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return c.Substitute({'classname': classname})
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _GenerateEvent(self, event):
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generates the namespaces for an event.
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # TODO(kalman): use event.unix_name not Classname.
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event_namespace = cpp_util.Classname(event.name)
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (c.Append('namespace %s {' % event_namespace)
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Append()
2902385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      .Concat(self._GenerateEventNameConstant(event))
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Concat(self._GenerateCreateCallbackArguments(event))
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Eblock('}  // namespace %s' % event_namespace)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    )
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _GenerateFunction(self, function):
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generates the namespaces and structs for a function.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # TODO(kalman): Use function.unix_name not Classname here.
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    function_namespace = cpp_util.Classname(function.name)
30258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    # Windows has a #define for SendMessage, so to avoid any issues, we need
30358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    # to not use the name.
30490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if function_namespace == 'SendMessage':
30590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      function_namespace = 'PassMessage'
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (c.Append('namespace %s {' % function_namespace)
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Append()
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Cblock(self._GenerateFunctionParams(function))
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    )
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if function.callback:
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      c.Cblock(self._GenerateFunctionResults(function.callback))
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    c.Append('}  // namespace %s' % function_namespace)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _GenerateFunctionParams(self, function):
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generates the struct for passing parameters from JSON to a function.
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if not function.params:
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return Code()
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    c = Code()
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (c.Sblock('struct Params {')
323c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      .Append('static scoped_ptr<Params> Create(%s);' % self._GenerateParams(
324c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          ('const base::ListValue& args',)))
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Append('~Params();')
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Append()
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Cblock(self._GenerateTypes(p.type_ for p in function.params))
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Cblock(self._GenerateFields(function.params))
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Eblock()
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Append()
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Sblock(' private:')
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .Append('Params();')
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .Append()
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .Append('DISALLOW_COPY_AND_ASSIGN(Params);')
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Eblock('};')
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    )
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def _GenerateTypes(self, types, is_toplevel=False, generate_typedefs=False):
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generate the structures required by a property such as OBJECT classes
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    and enums.
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for type_ in types:
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      c.Cblock(self._GenerateType(type_,
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  is_toplevel=is_toplevel,
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  generate_typedefs=generate_typedefs))
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def _GenerateCreateCallbackArguments(self, function):
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Generates functions for passing parameters to a callback.
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    params = function.params
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    c.Cblock(self._GenerateTypes((p.type_ for p in params), is_toplevel=True))
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    declaration_list = []
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for param in params:
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if param.description:
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        c.Comment(param.description)
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      declaration_list.append(cpp_util.GetParameterDeclaration(
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          param, self._type_helper.GetCppType(param.type_)))
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    c.Append('scoped_ptr<base::ListValue> Create(%s);' %
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             ', '.join(declaration_list))
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3672385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  def _GenerateEventNameConstant(self, event):
3682385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    """Generates a constant string array for the event name.
3692385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    """
3702385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    c = Code()
3712385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    c.Append('extern const char kEventName[];  // "%s.%s"' % (
3722385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                 self._namespace.name, event.name))
3732385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    c.Append()
3742385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    return c
3752385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _GenerateFunctionResults(self, callback):
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generates namespace for passing a function's result back.
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (c.Append('namespace Results {')
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Append()
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Concat(self._GenerateCreateCallbackArguments(callback))
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Append('}  // namespace Results')
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    )
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c
386c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch
387c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  def _GenerateParams(self, params):
388c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch    """Builds the parameter list for a function, given an array of parameters.
389c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch    """
390a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    # |error| is populated with warnings and/or errors found during parsing.
391a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    # |error| being set does not necessarily imply failure and may be
392a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    # recoverable.
393a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    # For example, optional properties may have failed to parse, but the
394a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    # parser was able to continue.
395c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch    if self._generate_error_messages:
396010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      params += ('base::string16* error',)
397c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch    return ', '.join(str(p) for p in params)
398