# Copyright 2012 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from code_util import Code
from model import PropertyType, Property, Type
import cpp_util
import schema_util
import util_cc_helper
from cpp_namespace_environment import CppNamespaceEnvironment


class CCGenerator(object):

  def __init__(self, type_generator):
    self._type_generator = type_generator

  def Generate(self, namespace):
    return _Generator(namespace, self._type_generator).Generate()


class _Generator(object):
  """A .cc generator for a namespace.
  """

  def __init__(self, namespace, cpp_type_generator):
    assert type(namespace.environment) is CppNamespaceEnvironment
    self._namespace = namespace
    self._type_helper = cpp_type_generator
    self._util_cc_helper = (util_cc_helper.UtilCCHelper(self._type_helper))
    self._generate_error_messages = namespace.compiler_options.get(
        'generate_error_messages', False)

  def Generate(self):
    """Generates a Code object with the .cc for a single namespace.
    """
    cpp_namespace = cpp_util.GetCppNamespace(
        self._namespace.environment.namespace_pattern,
        self._namespace.unix_name)

    c = Code()
    (c.Append(cpp_util.CHROMIUM_LICENSE) \
      .Append() \
      .Append(cpp_util.GENERATED_FILE_MESSAGE %
              cpp_util.ToPosixPath(self._namespace.source_file)) \
      .Append() \
      .Append('#include "%s/%s.h"' %
              (cpp_util.ToPosixPath(self._namespace.source_file_dir),
               self._namespace.short_filename)) \
      .Append() \
      .Append('#include <memory>') \
      .Append('#include <optional>') \
      .Append('#include <ostream>') \
      .Append('#include <string>') \
      .Append('#include <string_view>') \
      .Append('#include <utility>') \
      .Append('#include <vector>') \
      .Append() \
      .Append('#include "base/check.h"') \
      .Append('#include "base/check_op.h"') \
      .Append('#include "base/notreached.h"') \
      .Append('#include "base/strings/string_number_conversions.h"') \
      .Append('#include "base/strings/utf_string_conversions.h"') \
      .Append('#include "base/values.h"') \
      .Append(self._util_cc_helper.GetIncludePath()) \
      .Cblock(self._GenerateManifestKeysIncludes()) \
      .Cblock(self._type_helper.GenerateIncludes(include_soft=True,
          generate_error_messages=self._generate_error_messages)) \
      .Append() \
      .Append('using base::UTF8ToUTF16;') \
      .Append() \
      .Concat(cpp_util.OpenNamespace(cpp_namespace))
    )
    if self._namespace.properties:
      (c.Append('//') \
        .Append('// Properties') \
        .Append('//') \
        .Append()
      )
      for prop in self._namespace.properties.values():
        property_code = self._type_helper.GeneratePropertyValues(
            prop, 'const %(type)s %(name)s = %(value)s;', nodoc=True)
        if property_code:
          c.Cblock(property_code)
    if self._namespace.types:
      (c.Append('//') \
        .Append('// Types') \
        .Append('//') \
        .Append() \
        .Cblock(self._GenerateTypes(None, self._namespace.types.values()))
      )
    if self._namespace.manifest_keys:
      (c.Append('//') \
        .Append('// Manifest Keys') \
        .Append('//') \
        .Append() \
        .Cblock(self._GenerateManifestKeys())
      )
    if self._namespace.functions:
      (c.Append('//') \
        .Append('// Functions') \
        .Append('//') \
        .Append()
      )
    for function in self._namespace.functions.values():
      c.Cblock(self._GenerateFunction(function))
    if self._namespace.events:
      (c.Append('//') \
        .Append('// Events') \
        .Append('//') \
        .Append()
      )
      for event in self._namespace.events.values():
        c.Cblock(self._GenerateEvent(event))
    c.Cblock(cpp_util.CloseNamespace(cpp_namespace))
    c.Append()
    return c

  def _GenerateType(self, cpp_namespace, type_):
    """Generates the function definitions for a type.
    """
    classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))
    c = Code()

    if type_.functions:
      # Wrap functions within types in the type's namespace.
      (c.Append('namespace %s {' % classname) \
        .Append())
      for function in type_.functions.values():
        c.Cblock(self._GenerateFunction(function))
      c.Append('}  // namespace %s' % classname)
    elif type_.property_type == PropertyType.ARRAY:
      c.Cblock(self._GenerateType(cpp_namespace, type_.item_type))
    elif type_.property_type in (PropertyType.CHOICES, PropertyType.OBJECT):
      if cpp_namespace is None:
        classname_in_namespace = classname
      else:
        classname_in_namespace = '%s::%s' % (cpp_namespace, classname)

      if type_.property_type == PropertyType.OBJECT:
        c.Cblock(
            self._GeneratePropertyFunctions(classname_in_namespace,
                                            type_.properties.values()))
      else:
        c.Cblock(self._GenerateTypes(classname_in_namespace, type_.choices))

      (c.Append('%s::%s()' % (classname_in_namespace, classname)) \
        .Cblock(self._GenerateInitializersAndBody(type_)) \
        .Append('%s::~%s() = default;' % (classname_in_namespace, classname))
      )
      # Note: we use 'rhs' because some API objects have a member 'other'.
      (c.Append('%s::%s(%s&& rhs) noexcept = default;' %
                    (classname_in_namespace, classname, classname)) \
        .Append('%s& %s::operator=(%s&& rhs) noexcept = default;' %
                    (classname_in_namespace, classname_in_namespace,
                     classname))
      )

      if type_.origin.from_manifest_keys:
        c.Cblock(
            self._GenerateManifestKeyConstants(classname_in_namespace,
                                               type_.properties.values()))
        # Manifest key parsing for CHOICES types relies on the Populate()
        # method. Thus, if it wouldn't be generated below, ensure it's
        # created here.
        # TODO(devlin): This gets precarious. Instead of having complex if-
        # branches determining which values to construct here, we should pull
        # this out to a helper that just returns a set of method categories to
        # generate.
        if (type_.property_type is PropertyType.CHOICES
            and not type_.origin.from_json):
          c.Cblock(
              self._GenerateTypePopulateFromValue(classname_in_namespace,
                                                  type_))

      if type_.origin.from_json:
        c.Cblock(self._GenerateClone(classname_in_namespace, type_))
        if type_.property_type is not PropertyType.CHOICES:
          c.Cblock(self._GenerateTypePopulate(classname_in_namespace, type_))
        c.Cblock(
            self._GenerateTypePopulateFromValue(classname_in_namespace, type_))

        if type_.property_type is not PropertyType.CHOICES:
          c.Cblock(
              self._GenerateTypeFromValue(classname_in_namespace,
                                          type_,
                                          is_dict=True))

        c.Cblock(
            self._GenerateTypeFromValue(classname_in_namespace,
                                        type_,
                                        is_dict=False))
      if type_.origin.from_client:
        c.Cblock(self._GenerateTypeToValue(classname_in_namespace, type_))

      if type_.origin.from_manifest_keys:
        c.Cblock(
            self._GenerateParseFromDictionary(classname, classname_in_namespace,
                                              type_))
    elif type_.property_type == PropertyType.ENUM:
      (c.Cblock(self._GenerateEnumToString(cpp_namespace, type_)) \
        .Cblock(self._GenerateEnumFromString(cpp_namespace, type_)) \
        .Cblock(self._GenerateEnumParseErrorMessage(cpp_namespace, type_))
      )

    return c

  def _GenerateInitializersAndBody(self, type_):
    items = []
    for prop in type_.properties.values():
      t = prop.type_

      real_t = self._type_helper.FollowRef(t)
      if real_t.property_type == PropertyType.ENUM:
        items.append('{var_name}()'.format(var_name=prop.unix_name))
      elif prop.optional:
        continue
      elif t.property_type == PropertyType.INTEGER:
        items.append('%s(0)' % prop.unix_name)
      elif t.property_type == PropertyType.DOUBLE:
        items.append('%s(0.0)' % prop.unix_name)
      elif t.property_type == PropertyType.BOOLEAN:
        items.append('%s(false)' % prop.unix_name)
      elif (t.property_type == PropertyType.ANY
            or t.property_type == PropertyType.ARRAY
            or t.property_type == PropertyType.BINARY
            or t.property_type == PropertyType.CHOICES
            or t.property_type == PropertyType.OBJECT
            or t.property_type == PropertyType.FUNCTION
            or t.property_type == PropertyType.REF
            or t.property_type == PropertyType.STRING):
        # TODO(miket): It would be nice to initialize CHOICES, but we
        # don't presently have the semantics to indicate which one of a set
        # should be the default.
        continue
      else:
        raise TypeError(t)

    if items:
      s = ': %s' % (',\n'.join(items))
    else:
      s = ''
    s = s + ' {}'
    return Code().Append(s)

  def _GenerateCloneItem(self, type_, field_name, is_optional):
    """Generates the cloning statement for an individual data member.
    """

    underlying_type = self._type_helper.FollowRef(type_)
    c = Code()

    if (type_.property_type == PropertyType.ARRAY
        and self._type_helper.FollowRef(type_.item_type).property_type
        in (PropertyType.ANY, PropertyType.OBJECT)):
      if is_optional:
        (c.Sblock('if (%(name)s) {') \
            .Append('out.%(name)s.emplace();') \
            .Append('out.%(name)s->reserve(%(name)s->size());') \
            .Sblock('for (const auto& element : *%(name)s) {') \
              .Append(self._util_cc_helper.AppendToContainer(
                '*out.%(name)s', 'element.Clone()')) \
            .Eblock('}') \
          .Eblock('}'))
      else:
        (c.Append('out.%(name)s.reserve(%(name)s.size());') \
          .Sblock('for (const auto& element : %(name)s) {') \
            .Append(self._util_cc_helper.AppendToContainer(
              'out.%(name)s', 'element.Clone()')) \
          .Eblock('}'))
    elif (underlying_type.property_type == PropertyType.OBJECT
          or underlying_type.property_type == PropertyType.ANY
          or underlying_type.property_type == PropertyType.CHOICES
          or (underlying_type.property_type == PropertyType.FUNCTION
              and not type_.is_serializable_function)):
      if is_optional:
        (c.Sblock('if (%(name)s) {') \
          .Append('out.%(name)s = %(name)s->Clone();') \
          .Eblock('}'))
      else:
        c.Append('out.%(name)s = %(name)s.Clone();')
    else:
      c.Append('out.%(name)s = %(name)s;')

    c.Substitute({'name': field_name})
    return c

  def _GenerateClone(self, cpp_namespace, type_):
    """Generates the function for cloning a type.
    """
    classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))
    c = Code()
    c.Sblock('%(namespace)s %(namespace)s::Clone() const {')
    c.Append('%(classname)s out;')

    if type_.property_type is PropertyType.CHOICES:
      for choice in type_.choices:
        c.Concat(
            self._GenerateCloneItem(choice,
                                    'as_%s' % choice.unix_name,
                                    is_optional=True))
    else:
      if type_.additional_properties is not None:
        if type_.additional_properties.property_type == PropertyType.ANY:
          c.Append('out.additional_properties = additional_properties.Clone();')
      else:
        for prop in type_.properties.values():
          c.Concat(
              self._GenerateCloneItem(prop.type_,
                                      prop.type_.unix_name,
                                      is_optional=prop.optional))

    (c.Append('return out;') \
      .Eblock('}') \
      .Substitute({'namespace': cpp_namespace, 'classname': classname}))
    return c

  def _GenerateTypePopulate(self, cpp_namespace, type_):
    """Generates the function for populating a type given a pointer to it.

    E.g for type "Foo", generates:
        bool Foo::Populate(const base::Value::Dict& dict, Foo& out)
    """
    classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))
    c = Code()
    (c.Append('// static') \
      .Append('bool %(namespace)s::Populate(') \
      .Sblock('    %s) {' % self._GenerateParams(
          ('const base::Value::Dict& dict', '%(name)s& out'))))

    # TODO(crbug.com/40729306): The generated code here will ignore
    # unrecognized keys, but the parsing code for types passed to APIs in the
    # renderer will hard-error on them. We should probably be consistent with
    # the renderer here (at least for types also parsed in the renderer).
    for prop in type_.properties.values():
      c.Concat(self._InitializePropertyToDefault(prop, 'out'))
    for prop in type_.properties.values():
      c.Concat(self._GenerateTypePopulateProperty(prop, 'dict', 'out'))
    if type_.additional_properties is not None:
      if type_.additional_properties.property_type == PropertyType.ANY:
        c.Append('out.additional_properties.Merge(dict.Clone());')
      else:
        cpp_type = self._type_helper.GetCppType(type_.additional_properties)
        (c.Sblock('for (const auto item : dict) {') \
            .Append('%s tmp;' % cpp_type) \
            .Concat(self._GeneratePopulateVariableFromValue(
                type_.additional_properties,
                'item.second',
                'tmp',
                'false')) \
            .Append('out.additional_properties[item.first] = tmp;') \
          .Eblock('}')
        )
    c.Append('return true;')
    (c.Eblock('}') \
      .Substitute({'namespace': cpp_namespace, 'name': classname}))
    return c

  def _GenerateTypePopulateFromValue(self, cpp_namespace, type_):
    """Generates the function for populating a type receiving a base::Value
    instance.

    E.g for choice type "Foo", generates:
        bool Foo::Populate(const base::Value& value, Foo& out)
    """
    classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))
    c = Code()
    (c.Append('// static') \
      .Append('bool %(namespace)s::Populate(') \
      .Sblock('    %s) {' % self._GenerateParams(
          ('const base::Value& value', '%(name)s& out'))))

    if type_.property_type is PropertyType.CHOICES:
      for choice in type_.choices:
        (c.Sblock('if (%s) {' % self._GenerateValueIsTypeExpression('value',
                                                                    choice)) \
            .Concat(self._GeneratePopulateVariableFromValue(
                choice,
                'value',
                'out.as_%s' % choice.unix_name,
                'false',
                is_ptr=True)) \
            .Append('return true;') \
          .Eblock('}')
        )
      (c.Concat(self._AppendError16(
          'u"expected %s, got " + %s' %
              (" or ".join(choice.name for choice in type_.choices),
              self._util_cc_helper.GetValueTypeString('value')))) \
        .Append('return false;'))
    elif type_.property_type == PropertyType.OBJECT:
      (c.Sblock('if (!value.is_dict()) {') \
        .Concat(self._AppendError16(
          'u"expected dictionary, got " + ' +
          self._util_cc_helper.GetValueTypeString('value'))) \
        .Append('return false;') \
        .Eblock('}'))
      (c.Append('return Populate(%s);' % self._GenerateArgs(
          ('value.GetDict()', 'out'))))

    (c.Eblock('}') \
      .Substitute({'namespace': cpp_namespace, 'name': classname}))
    return c

  def _GenerateValueIsTypeExpression(self, var, type_):
    real_type = self._type_helper.FollowRef(type_)
    if real_type.property_type is PropertyType.CHOICES:
      return '(%s)' % ' || '.join(
          self._GenerateValueIsTypeExpression(var, choice)
          for choice in real_type.choices)
    return '%s.type() == %s' % (var, cpp_util.GetValueType(real_type))

  def _GenerateTypePopulateProperty(self, prop, src, dst):
    """Generate the code to populate a single property in a type.

    src: base::Value::Dict*
    dst: Type*
    """
    c = Code()
    value_var = prop.unix_name + '_value'
    c.Append('const base::Value* %(value_var)s = %(src)s.Find("%(key)s");')
    if prop.optional:
      (c.Sblock(
          'if (%(value_var)s) {') \
        .Concat(self._GeneratePopulatePropertyFromValue(
            prop, '(*%s)' % value_var, dst, 'false')))
      underlying_type = self._type_helper.FollowRef(prop.type_)
      if underlying_type.property_type == PropertyType.ENUM:
        (c.Append('} else {') \
          .Append('%%(dst)s.%%(name)s = %s;' %
            self._type_helper.GetEnumDefaultValue(underlying_type,
                                                  self._namespace)))
      c.Eblock('}')
    else:
      (c.Sblock(
          'if (!%(value_var)s) {') \
        .Concat(self._AppendError16('u"\'%%(key)s\' is required"')) \
        .Append('return false;') \
        .Eblock('}') \
        .Concat(self._GeneratePopulatePropertyFromValue(
            prop, '(*%s)' % value_var, dst, 'false'))
      )
    c.Append()
    c.Substitute({
        'value_var': value_var,
        'key': prop.name,
        'src': src,
        'dst': dst,
        'name': prop.unix_name
    })
    return c

  def _GenerateTypeFromValue(self, cpp_namespace, type_, is_dict):
    classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))

    return_type = self._type_helper.GetOptionalReturnType(
        cpp_namespace, support_errors=self._generate_error_messages)

    param_type = ('base::Value::Dict' if is_dict else 'base::Value')

    c = Code()
    (c.Append(f'// static') \
      .Append('{return_type} '
              '{classname}::FromValue(const {param_type}& value) {{'.format(
                return_type=return_type,
                classname=cpp_namespace,
                param_type=param_type))
    )
    c.Sblock()
    # TODO(crbug.com/40235429): Once the deprecated version of this method is
    # removed, we should consider making Populate return an optional, rather
    # than using an out param.
    if self._generate_error_messages:
      c.Append('std::u16string error;')

    c.Append(f'{classname} out;')
    c.Append('bool result = Populate(%s);' % self._GenerateArgs(
        ('value', 'out')))

    c.Sblock('if (!result) {')
    if self._generate_error_messages:
      c.Append('DCHECK(!error.empty());')
      c.Append('return base::unexpected(std::move(error));')
    else:
      c.Append('return std::nullopt;')
    c.Eblock('}')

    c.Append('return out;')
    c.Eblock('}')
    return c

  def _GenerateTypeToValue(self, cpp_namespace, type_):
    """Generates a function that serializes the type into a base::Value.
    E.g. for type "Foo" generates Foo::ToValue()
    """
    if type_.property_type == PropertyType.OBJECT:
      return self._GenerateObjectTypeToValue(cpp_namespace, type_)
    elif type_.property_type == PropertyType.CHOICES:
      return self._GenerateChoiceTypeToValue(cpp_namespace, type_)
    else:
      raise ValueError("Unsupported property type %s" % type_.type_)

  def _GenerateManifestKeysIncludes(self):
    # type: () -> (Code)
    """Returns the includes needed for manifest key parsing.
    """
    c = Code()
    if not self._namespace.manifest_keys:
      return c

    c.Append('#include "tools/json_schema_compiler/manifest_parse_util.h"')
    return c

  def _GenerateManifestKeyConstants(self, classname_in_namespace, properties):
    # type: (str, List[Property]) -> Code
    """ Generates the definition for manifest key constants declared in the
    header.
    """
    c = Code()
    for prop in properties:
      c.Comment('static')
      c.Append('constexpr char %s::%s[];' %
               (classname_in_namespace,
                cpp_util.UnixNameToConstantName(prop.unix_name)))

    return c

  def _GenerateManifestKeys(self):
    # type: () -> Code
    """Generates the types and parsing code for manifest keys.
    """
    assert self._namespace.manifest_keys
    assert self._namespace.manifest_keys.property_type == PropertyType.OBJECT
    return self._GenerateType(None, self._namespace.manifest_keys)

  def _GenerateParseFromDictionary(self, classname, classname_in_namespace,
                                   type_):
    # type: (str, str, Type) -> Code
    """Generates a function that deserializes the type from the passed
    dictionary. E.g. for type "Foo", generates Foo::ParseFromDictionary().
    """
    if type_.IsRootManifestKeyType():
      # Root manifest types must always be objects.
      assert type_.property_type == PropertyType.OBJECT, \
        ('Manifest type %s must be an object, but it is: %s' %
        (type_.name, type_.property_type))
      return self._GenerateParseFromDictionaryForRootManifestType(
          classname, classname_in_namespace, type_.properties.values())

    return self._GenerateParseFromDictionaryForChildManifestType(
        type_, classname, classname_in_namespace, type_.properties.values())

  def _GenerateParseFromDictionaryForRootManifestType(self, classname,
                                                      classname_in_namespace,
                                                      properties):
    # type: (str, str, List[Property]) -> Code
    """Generates definition for ManifestKeys::ParseFromDictionary.
    """
    params = [
        'const base::Value::Dict& root_dict',
        '%(classname)s& out',
    ]

    c = Code()
    c.Append('//static')
    c.Append('bool %(classname_in_namespace)s::ParseFromDictionary(')

    # Make |generate_error_messages| True since we always generate error
    # messages for manifest parsing.
    c.Sblock('%s) {' %
             self._GenerateParams(params, generate_error_messages=True))

    c.Append()

    c.Append('std::vector<std::string_view> error_path_reversed;')
    c.Append('const base::Value::Dict& dict = root_dict;')

    for prop in properties:
      c.Concat(self._InitializePropertyToDefault(prop, 'out'))

    for prop in properties:
      c.Cblock(
          self._ParsePropertyFromDictionary(prop, is_root_manifest_type=True))

    c.Append('return true;')
    c.Eblock('}')
    c.Substitute({
        'classname_in_namespace': classname_in_namespace,
        'classname': classname
    })
    return c

  def _GenerateParseFromDictionaryForChildManifestType(self, type_, classname,
                                                       classname_in_namespace,
                                                       properties):
    # type: (str, str, List[Property]) -> Code
    """Generates T::ParseFromDictionary for a child manifest type.
    """
    params = [
        'const base::Value::Dict& root_dict', 'std::string_view key',
        '%(classname)s& out', 'std::u16string& error',
        'std::vector<std::string_view>& error_path_reversed'
    ]

    c = Code()
    c.Append('//static')
    c.Append('bool %(classname_in_namespace)s::ParseFromDictionary(')

    # Make |generate_error_messages| False since |error| is already included
    # within |params|.
    c.Sblock('%s) {' %
             self._GenerateParams(params, generate_error_messages=False))

    c.Append()

    # For CHOICES, we leverage the specialized helper in manifest_parse_util.
    if type_.property_type is PropertyType.CHOICES:
      c.Append('return ::json_schema_compiler::manifest_parse_util::\n'
               '    ParseChoicesFromDictionary(root_dict, key, out, error,\n'
               '                               error_path_reversed);')
      c.Eblock('}')
      return c.Substitute({
          'classname_in_namespace': classname_in_namespace,
          'classname': classname
      })

    # Otherwise, this must be an object, and we parse each property
    # individually.
    assert type_.property_type == PropertyType.OBJECT, \
      ('Manifest type %s must be an object, but it is: %s' %
      (type_.name, type_.property_type))

    c.Append('const base::Value* value = '
             '::json_schema_compiler::manifest_parse_util::FindKeyOfType('
             'root_dict, key, base::Value::Type::DICT, error, '
             'error_path_reversed);')
    c.Sblock('if (!value)')
    c.Append('return false;')
    if len(properties) > 0:
      c.Eblock('const base::Value::Dict& dict = value->GetDict();')
    else:
      c.Eblock('')

    for prop in properties:
      c.Concat(self._InitializePropertyToDefault(prop, 'out'))

    for prop in properties:
      c.Cblock(
          self._ParsePropertyFromDictionary(prop, is_root_manifest_type=False))

    c.Append('return true;')
    c.Eblock('}')
    c.Substitute({
        'classname_in_namespace': classname_in_namespace,
        'classname': classname
    })
    return c

  def _ParsePropertyFromDictionary(self, property, is_root_manifest_type):
    # type: (Property, bool) -> Code
    """Generates the code to parse a single property from a dictionary.
    """
    supported_property_types = {
        PropertyType.ARRAY,
        PropertyType.BOOLEAN,
        PropertyType.DOUBLE,
        PropertyType.INT64,
        PropertyType.INTEGER,
        PropertyType.CHOICES,
        PropertyType.OBJECT,
        PropertyType.STRING,
        PropertyType.ENUM,
    }

    c = Code()
    underlying_type = self._type_helper.FollowRef(property.type_)
    underlying_property_type = underlying_type.property_type
    underlying_item_type = (self._type_helper.FollowRef(
        underlying_type.item_type) if underlying_property_type
                            is PropertyType.ARRAY else None)

    assert (underlying_property_type in supported_property_types), (
        'Property type not implemented for %s, type: %s, namespace: %s' %
        (underlying_property_type, underlying_type.name,
         underlying_type.namespace.name))

    property_constant = cpp_util.UnixNameToConstantName(property.unix_name)
    out_expression = 'out.%s' % property.unix_name

    def get_enum_params(enum_type, include_optional_param):
      # type: (Type, bool) -> List[str]
      enum_name = cpp_util.Classname(schema_util.StripNamespace(enum_type.name))
      cpp_type_namespace = ('' if enum_type.namespace == self._namespace else
                            '%s::' % enum_type.namespace.unix_name)

      params = [
          'dict',
          '%s' % property_constant,
          '&%sParse%s' % (cpp_type_namespace, enum_name)
      ]
      if include_optional_param:
        params.append('true' if property.optional else 'false')
      params += [
          '%s' %
          self._type_helper.GetEnumDefaultValue(enum_type, self._namespace),
          '%s' % out_expression, 'error', 'error_path_reversed'
      ]
      return params

    if underlying_property_type == PropertyType.ENUM:
      params = get_enum_params(underlying_type, include_optional_param=True)
      func_name = 'ParseEnumFromDictionary'
    elif underlying_item_type and \
      underlying_item_type.property_type == PropertyType.ENUM:
      # Array of enums.
      params = get_enum_params(underlying_item_type,
                               include_optional_param=False)
      func_name = 'ParseEnumArrayFromDictionary'
    else:
      params = [
          'dict',
          '%s' % property_constant,
          '%s' % out_expression, 'error', 'error_path_reversed'
      ]
      func_name = 'ParseFromDictionary'

    c.Sblock('if (!::json_schema_compiler::manifest_parse_util::%s(%s)) {' %
             (func_name,
              self._GenerateParams(params, generate_error_messages=False)))
    if is_root_manifest_type:
      c.Append('::json_schema_compiler::manifest_parse_util::'
               'PopulateFinalError(error, error_path_reversed);')
    else:
      c.Append('error_path_reversed.push_back(key);')
    c.Append('return false;')
    c.Eblock('}')

    return c

  def _GenerateObjectTypeToValue(self, cpp_namespace, type_):
    """Generates a function that serializes an object-representing type
    into a base::Value::Dict.
    """
    c = Code()
    (c.Sblock('base::Value::Dict %s::ToValue() const {' % cpp_namespace) \
        .Append('base::Value::Dict to_value_result;') \
        .Append()
    )

    for prop in type_.properties.values():
      prop_var = 'this->%s' % prop.unix_name
      if prop.optional:
        underlying_type = self._type_helper.FollowRef(prop.type_)
        if underlying_type.property_type == PropertyType.ENUM:
          # Optional enum values are generated with default initialisation (e.g.
          # kNone), potentially from another namespace.
          c.Sblock('if (%s != %s) {' % (prop_var,
                                        self._type_helper.GetEnumDefaultValue(
                                            underlying_type, self._namespace)))
        else:
          c.Sblock('if (%s) {' % prop_var)

      c.Cblock(
          self._CreateValueFromType('to_value_result.Set("%s", %%s);' %
                                    prop.name,
                                    prop.name,
                                    prop.type_,
                                    prop_var,
                                    is_ptr=prop.optional))

      if prop.optional:
        c.Eblock('}')

    if type_.additional_properties is not None:
      if type_.additional_properties.property_type == PropertyType.ANY:
        c.Append('to_value_result.Merge(additional_properties.Clone());')
      else:
        (c.Sblock('for (const auto& it : additional_properties) {') \
          .Cblock(self._CreateValueFromType(
              'to_value_result.Set(it.first, %s);',
              type_.additional_properties.name,
              type_.additional_properties,
              'it.second')) \
          .Eblock('}')
        )

    return (c.Append() \
             .Append('return to_value_result;') \
           .Eblock('}'))

  def _GenerateChoiceTypeToValue(self, cpp_namespace, type_):
    """Generates a function that serializes a choice-representing type
    into a base::Value.
    """
    c = Code()
    c.Sblock('base::Value %s::ToValue() const {' % cpp_namespace)
    c.Append('base::Value result;')
    for choice in type_.choices:
      choice_var = 'as_%s' % choice.unix_name

      # Enum class values cannot be checked as a boolean, so they require
      # specific handling when checking if they are engaged, by comparing it
      # against kNone.
      if (self._type_helper.FollowRef(choice).property_type == PropertyType.ENUM
          ):
        comparison_expr = '{enum_var} != {default_value}'.format(
            enum_var=choice_var,
            default_value=self._type_helper.GetEnumDefaultValue(
                choice, self._namespace))
      else:
        comparison_expr = choice_var

      (c.Sblock('if (%s) {' % comparison_expr) \
       .Append('DCHECK(result.is_none()) << "Cannot set multiple choices for '
               '%s";' %
               type_.unix_name).Cblock(self._CreateValueFromType(
                   'result = base::Value(%s);', choice.name, choice, choice_var,
                   True)) \
       .Eblock('}'))
    (c.Append('DCHECK(!result.is_none()) << "Must set at least one choice for '
              '%s";' % type_.unix_name).Append('return result;').Eblock('}'))
    return c

  def _GenerateFunction(self, function):
    """Generates the definitions for function structs.
    """
    c = Code()

    # TODO(kalman): use function.unix_name not Classname.
    function_namespace = cpp_util.Classname(function.name)
    # Windows has a #define for SendMessage, so to avoid any issues, we need
    # to not use the name.
    if function_namespace == 'SendMessage':
      function_namespace = 'PassMessage'
    (c.Append('namespace %s {' % function_namespace) \
      .Append()
    )

    # Params::Populate function
    if function.params:
      c.Concat(self._GeneratePropertyFunctions('Params', function.params))
      (c.Append('Params::Params() = default;') \
        .Append('Params::~Params() = default;') \
        .Append('Params::Params(Params&& rhs) noexcept = default;') \
        .Append('Params& Params::operator=(Params&& rhs) noexcept = default;') \
        .Append() \
        .Cblock(self._GenerateFunctionParamsCreate(function))
      )
      if self._generate_error_messages:
        c.Cblock(self._GenerateFunctionParamsCreateWithExpected(function))

    # Results::Create function
    if function.returns_async:
      c.Concat(
          self._GenerateAsyncResponseArguments('Results',
                                               function.returns_async.params))

    c.Append('}  // namespace %s' % function_namespace)
    return c

  def _GenerateEvent(self, event):
    # TODO(kalman): use event.unix_name not Classname.
    c = Code()
    event_namespace = cpp_util.Classname(event.name)
    (c.Append('namespace %s {' % event_namespace) \
      .Append() \
      .Cblock(self._GenerateEventNameConstant(event)) \
      .Cblock(self._GenerateAsyncResponseArguments(None, event.params)) \
      .Append('}  // namespace %s' % event_namespace)
    )
    return c

  def _CreateValueFromType(self, code, prop_name, type_, var, is_ptr=False):
    """Creates a base::Value given a type.

    var: variable or variable*

    E.g for std::string, generate new base::Value(var)
    """
    c = Code()
    underlying_type = self._type_helper.FollowRef(type_)
    if underlying_type.property_type == PropertyType.ARRAY:
      # Enums are treated specially because C++ templating thinks that they're
      # ints, but really they're strings. So we create a vector of strings and
      # populate it with the names of the enum in the array. The |ToString|
      # function of the enum can be in another namespace when the enum is
      # referenced. Templates can not be used here because C++ templating does
      # not support passing a namespace as an argument.
      item_type = self._type_helper.FollowRef(underlying_type.item_type)
      if item_type.property_type == PropertyType.ENUM:
        varname = ('*' if is_ptr else '') + '(%s)' % var

        maybe_namespace = ''
        if type_.item_type.property_type == PropertyType.REF:
          maybe_namespace = '%s::' % item_type.namespace.unix_name

        enum_list_var = '%s_list' % prop_name
        # Scope the std::vector variable declaration inside braces.
        (c.Sblock('{') \
          .Append('std::vector<std::string> %s;' % enum_list_var) \
          .Sblock('for (const auto& it : %s) {' % varname) \
            .Append('%s.emplace_back(%sToString(it));' % (enum_list_var,
                                                          maybe_namespace)) \
          .Eblock('}'))

        # Because the std::vector above is always created for both required and
        # optional enum arrays, |is_ptr| is set to false and uses the
        # std::vector to create the values.
        (c.Append(code %
            self._GenerateCreateValueFromType(type_, enum_list_var, False)) \
          .Eblock('}'))
        return c

    c.Append(code % self._GenerateCreateValueFromType(type_, var, is_ptr))
    return c

  def _GenerateCreateValueFromType(self, type_, var, is_ptr):
    """Generates the statement to create a base::Value given a type.

    type_:  The type of the values being converted.
    var:    The name of the variable.
    is_ptr: Whether |type_| is optional.
    """
    underlying_type = self._type_helper.FollowRef(type_)
    if (underlying_type.property_type == PropertyType.CHOICES
        or underlying_type.property_type == PropertyType.OBJECT):
      if is_ptr:
        return '(%s)->ToValue()' % var
      else:
        return '(%s).ToValue()' % var
    elif (underlying_type.property_type == PropertyType.ANY
          or (underlying_type.property_type == PropertyType.FUNCTION
              and not underlying_type.is_serializable_function)):
      if is_ptr:
        vardot = '(%s)->' % var
      else:
        vardot = '(%s).' % var
      return '%sClone()' % vardot
    elif underlying_type.property_type == PropertyType.ENUM:
      maybe_namespace = ''
      if type_.property_type == PropertyType.REF:
        maybe_namespace = '%s::' % underlying_type.namespace.unix_name
      return '%sToString(%s)' % (maybe_namespace, var)
    elif underlying_type.property_type == PropertyType.BINARY:
      if is_ptr:
        var = '*%s' % var
      return 'base::Value(%s)' % var
    elif underlying_type.property_type == PropertyType.ARRAY:
      if is_ptr:
        var = '*%s' % var
      underlying_item_cpp_type = (self._type_helper.GetCppType(
          underlying_type.item_type))
      if underlying_item_cpp_type != 'base::Value':
        return '%s' % self._util_cc_helper.CreateValueFromArray(var)
      else:
        return '(%s).Clone()' % var
    elif (underlying_type.property_type.is_fundamental
          or underlying_type.is_serializable_function):
      if is_ptr:
        var = '*%s' % var
      return '%s' % var
    else:
      raise NotImplementedError('Conversion of %s to base::Value not '
                                'implemented' % repr(type_.type_))

  def _GenerateParamsCheck(self, function, var, failure_value):
    """Generates a check for the correct number of arguments when creating
    Params.
    """
    c = Code()
    num_required = 0
    for param in function.params:
      if not param.optional:
        num_required += 1
    if num_required == len(function.params):
      c.Sblock('if (%(var)s.size() != %(total)d) {')
    elif not num_required:
      c.Sblock('if (%(var)s.size() > %(total)d) {')
    else:
      c.Sblock('if (%(var)s.size() < %(required)d'
               ' || %(var)s.size() > %(total)d) {')
    (c.Concat(self._AppendError16(
        'u"expected %%(total)d arguments, got " '
        '+ base::NumberToString16(%%(var)s.size())')) \
      .Append('return %(failure_value)s;') \
      .Eblock('}') \
      .Substitute({
        'var': var,
        'failure_value': failure_value,
        'required': num_required,
        'total': len(function.params),
    }))
    return c

  def _GenerateFunctionParamsCreate(self, function):
    """Generate function to create an instance of Params. The generated
    function takes a const base::Value::List& of arguments.

    E.g for function "Bar", generate Bar::Params::Create()
    """
    c = Code()

    (c.Append('// static') \
      .Sblock('std::optional<Params> Params::Create(%s) {' %
                  self._GenerateParams([
                      'const base::Value::List& args']))
    )

    failure_value = 'std::nullopt'
    (c.Concat(self._GenerateParamsCheck(function, 'args', failure_value)) \
      .Append('Params params;')
    )

    for param in function.params:
      c.Concat(self._InitializePropertyToDefault(param, 'params'))

    for i, param in enumerate(function.params):
      # Any failure will cause this function to return. If any argument is
      # incorrect or missing, those following it are not processed. Note that
      # for optional arguments, we allow missing arguments and proceed because
      # there may be other arguments following it.
      c.Append()
      value_var = param.unix_name + '_value'
      (c.Append('if (%(i)s < args.size() &&') \
        .Sblock('    !args[%(i)s].is_none()) {') \
        .Append('const base::Value& %(value_var)s = args[%(i)s];') \
        .Concat(self._GeneratePopulatePropertyFromValue(
            param, value_var, 'params', failure_value)) \
        .Eblock('}')
      )
      if not param.optional:
        (c.Sblock('else {') \
          .Concat(self._AppendError16('u"\'%%(key)s\' is required"')) \
          .Append('return %s;' % failure_value) \
          .Eblock('}'))
      c.Substitute({'value_var': value_var, 'i': i, 'key': param.name})
    (c.Append() \
      .Append('return params;') \
      .Eblock('}') \
      .Append()
    )

    return c

  def _GenerateFunctionParamsCreateWithExpected(self, function):
    """An overloaded added to `Create()` communinicating errors through
    `base::expected`.
    """
    # TODO(crbug.com/40256450): This function is being temporarily added
    # separately to allow us to migrate the places where error is being passed
    # as an out param. Once that is done, this duplication should be deleted,
    # and everything should be handled by a single Create function.
    c = Code()

    (c.Append('// static') \
      .Sblock('base::expected<Params, std::u16string> '
          'Params::Create(const base::Value::List& args) {')
    )

    (c.Append('std::u16string error;') \
      .Append('auto result = Params::Create(args, error);') \
      .Sblock('if (!result) {') \
        .Append('DCHECK(!error.empty());') \
        .Append('return base::unexpected(std::move(error));') \
      .Eblock('}') \
      .Append('return std::move(result).value();') \
      .Eblock('}') \
      .Append())
    return c

  def _GeneratePopulatePropertyFromValue(self, prop, src_var, dst_class_var,
                                         failure_value):
    """Generates code to populate property |prop| of |dst_class_var| (a
    pointer) from a Value. See |_GeneratePopulateVariableFromValue| for
    semantics.
    """
    return self._GeneratePopulateVariableFromValue(
        prop.type_,
        src_var,
        '%s.%s' % (dst_class_var, prop.unix_name),
        failure_value,
        is_ptr=prop.optional)

  def _GeneratePopulateVariableFromValue(self,
                                         type_,
                                         src_var,
                                         dst_var,
                                         failure_value,
                                         is_ptr=False):
    """Generates code to populate a variable |dst_var| of type |type_| from a
    Value |src_var|. In the generated code, if |dst_var| fails to be populated
    then Populate will return |failure_value|.
    """
    c = Code()

    underlying_type = self._type_helper.FollowRef(type_)

    if (underlying_type.property_type.is_fundamental
        or underlying_type.is_serializable_function):
      is_string_or_function = (
          underlying_type.property_type == PropertyType.STRING
          or (underlying_type.property_type == PropertyType.FUNCTION
              and underlying_type.is_serializable_function))
      c.Append('auto%s temp = %s;' %
               ('*' if is_string_or_function else '',
                cpp_util.GetAsFundamentalValue(underlying_type, src_var)))
      if is_string_or_function:
        (c.Sblock('if (!temp) {') \
          .Concat(self._AppendError16(
            'u"\'%%(key)s\': expected ' + '%s, got " + %s' % (
                type_.name,
                self._util_cc_helper.GetValueTypeString('%%(src_var)s')))))
      else:
        (c.Sblock('if (!temp.has_value()) {') \
          .Concat(self._AppendError16(
            'u"\'%%(key)s\': expected ' + '%s, got " + %s' % (
                type_.name,
                self._util_cc_helper.GetValueTypeString('%%(src_var)s')))))
      if is_ptr:
        if cpp_util.ShouldUseStdOptional(underlying_type):
          c.Append('%(dst_var)s = std::nullopt;')
        else:
          c.Append('%(dst_var)s.reset();')
      c.Append('return %(failure_value)s;')
      (c.Eblock('}'))
      if is_ptr:
        if cpp_util.ShouldUseStdOptional(underlying_type):
          c.Append('%(dst_var)s = *temp;')
        elif is_string_or_function:
          c.Append('%(dst_var)s = std::make_unique<%(cpp_type)s>(*temp);')
        else:
          c.Append('%(dst_var)s = ' +
                   'std::make_unique<%(cpp_type)s>(temp.value());')
      else:
        c.Append('%(dst_var)s = *temp;')
    elif underlying_type.property_type == PropertyType.OBJECT:
      if is_ptr:
        (c.Sblock('if (!%(src_var)s.is_dict()) {') \
          .Concat(self._AppendError16(
            'u"\'%%(key)s\': expected dictionary, got " + ' +
            self._util_cc_helper.GetValueTypeString('%%(src_var)s'))) \
          .Append('return %(failure_value)s;')
        )
        (c.Eblock('}') \
          .Sblock('else {') \
          .Append('%(cpp_type)s temp;') \
          .Append('if (!%%(cpp_type)s::Populate(%s))' % self._GenerateArgs(
              ('%(src_var)s.GetDict()', 'temp'))) \
          .Append('  return %(failure_value)s;') \
          .Append('%(dst_var)s = std::move(temp);') \
          .Eblock('}')
        )
      else:
        (c.Sblock('if (!%(src_var)s.is_dict()) {') \
          .Concat(self._AppendError16(
            'u"\'%%(key)s\': expected dictionary, got " + ' +
            self._util_cc_helper.GetValueTypeString('%%(src_var)s'))) \
          .Append('return %(failure_value)s;') \
          .Eblock('}') \
          .Append('if (!%%(cpp_type)s::Populate(%s)) {' % self._GenerateArgs(
            ('%(src_var)s.GetDict()', '%(dst_var)s'))) \
          .Append('  return %(failure_value)s;') \
          .Append('}')
        )
    elif underlying_type.property_type == PropertyType.FUNCTION:
      assert not underlying_type.is_serializable_function, \
          'Serializable functions should have been handled above.'
      # Non-serializable functions are just represented as empty dicts. If it
      # was optional we call emplace to construct it in-place, otherwise we just
      # check we were passed an empty dict.
      if is_ptr:
        c.Append('%(dst_var)s.emplace();')
      else:
        (c.Sblock('if (!%(src_var)s.is_dict() || ' +
                  '!%(src_var)s.GetDict().empty()) {') \
          .Concat(self._AppendError16(
            'u"\'%%(key)s\': expected dictionary, got " + ' +
            self._util_cc_helper.GetValueTypeString('%%(src_var)s'))) \
          .Append('return %(failure_value)s;') \
          .Eblock('}')
        )
    elif underlying_type.property_type == PropertyType.ANY:
      c.Append('%(dst_var)s = %(src_var)s.Clone();')
    elif underlying_type.property_type == PropertyType.ARRAY:
      # util_cc_helper deals with optional and required arrays
      (c.Sblock('if (!%(src_var)s.is_list()) {') \
        .Concat(self._AppendError16(
          'u"\'%%(key)s\': expected list, got " + ' +
          self._util_cc_helper.GetValueTypeString('%%(src_var)s'))) \
        .Append('return %(failure_value)s;')
      )
      c.Eblock('}')
      c.Sblock('else {')
      item_type = self._type_helper.FollowRef(underlying_type.item_type)
      if item_type.property_type == PropertyType.ENUM:
        c.Concat(
            self._GenerateListValueToEnumArrayConversion(item_type,
                                                         src_var,
                                                         dst_var,
                                                         failure_value,
                                                         is_ptr=is_ptr))
      else:
        args = ['%(src_var)s.GetList()', '%(dst_var)s']
        if self._generate_error_messages:
          c.Append('std::u16string array_parse_error;')
          args.append('array_parse_error')

        item_cpp_type = self._type_helper.GetCppType(item_type)
        if item_cpp_type != 'base::Value':
          c.Append('if (!%s(%s)) {' %
                   (self._util_cc_helper.PopulateArrayFromListFunction(is_ptr),
                    self._GenerateArgs(args, generate_error_messages=False)))
          c.Sblock()
          if self._generate_error_messages:
            c.Append('array_parse_error = u"Error at key \'%(key)s\': " + '
                     'array_parse_error;')
            c.Concat(self._AppendError16('array_parse_error'))
          c.Append('return %(failure_value)s;')
          c.Eblock('}')
        else:
          c.Append('%(dst_var)s = %(src_var)s.GetList().Clone();')
      c.Eblock('}')
    elif underlying_type.property_type == PropertyType.CHOICES:
      if is_ptr:
        (c.Append('%(cpp_type)s temp;') \
          .Append('if (!%%(cpp_type)s::Populate(%s))' % self._GenerateArgs(
              ('%(src_var)s', 'temp'))) \
          .Append('  return %(failure_value)s;') \
          .Append('%(dst_var)s = std::move(temp);')
        )
      else:
        (c.Append('if (!%%(cpp_type)s::Populate(%s))' % self._GenerateArgs(
            ('%(src_var)s', '%(dst_var)s'))) \
          .Append('  return %(failure_value)s;'))
    elif underlying_type.property_type == PropertyType.ENUM:
      c.Concat(
          self._GenerateStringToEnumConversion(underlying_type, src_var,
                                               dst_var, failure_value))
    elif underlying_type.property_type == PropertyType.BINARY:
      (c.Sblock('if (!%(src_var)s.is_blob()) {') \
        .Concat(self._AppendError16(
          'u"\'%%(key)s\': expected binary, got " + ' +
          self._util_cc_helper.GetValueTypeString('%%(src_var)s'))) \
        .Append('return %(failure_value)s;')
      )
      (c.Eblock('}') \
        .Sblock('else {')
      )
      c.Append('%(dst_var)s = %(src_var)s.GetBlob();')
      c.Eblock('}')
    else:
      raise NotImplementedError(type_)
    if c.IsEmpty():
      return c
    return Code().Sblock('{').Concat(
        c.Substitute({
            'cpp_type': self._type_helper.GetCppType(type_),
            'src_var': src_var,
            'dst_var': dst_var,
            'failure_value': failure_value,
            'key': type_.name,
            'parent_key': type_.parent.name,
        })).Eblock('}')

  def _GenerateListValueToEnumArrayConversion(self,
                                              item_type,
                                              src_var,
                                              dst_var,
                                              failure_value,
                                              is_ptr=False):
    """Returns Code that converts a list Value of string constants from
    |src_var| into an array of enums of |type_| in |dst_var|. On failure,
    returns |failure_value|.
    """
    c = Code()
    accessor = '.'
    if is_ptr:
      accessor = '->'
      cpp_type = self._type_helper.GetCppType(item_type)
      c.Append('%s.emplace();' % dst_var)
    (c.Sblock('for (const auto& it : (%s).GetList()) {' % src_var) \
      .Append('%s tmp;' % self._type_helper.GetCppType(item_type)) \
      .Concat(self._GenerateStringToEnumConversion(item_type,
                                                   '(it)',
                                                   'tmp',
                                                   failure_value)) \
      .Append('%s%spush_back(tmp);' % (dst_var, accessor)) \
      .Eblock('}')
    )
    return c

  def _GenerateStringToEnumConversion(self, type_, src_var, dst_var,
                                      failure_value):
    """Returns Code that converts a string type in |src_var| to an enum with
    type |type_| in |dst_var|. In the generated code, if |src_var| is not
    a valid enum name then the function will return |failure_value|.
    """
    if type_.property_type != PropertyType.ENUM:
      raise TypeError(type_)
    c = Code()
    enum_as_string = '%s_as_string' % type_.unix_name
    cpp_type_namespace = ''
    if type_.namespace != self._namespace:
      namespace = cpp_util.GetCppNamespace(
          type_.namespace.environment.namespace_pattern,
          type_.namespace.unix_name)
      cpp_type_namespace = '%s::' % namespace
    (c.Append('const std::string* %s = %s.GetIfString();' % (enum_as_string,
                                                            src_var)) \
      .Sblock('if (!%s) {' % enum_as_string) \
      .Concat(self._AppendError16(
        'u"\'%%(key)s\': expected string, got " + ' +
        self._util_cc_helper.GetValueTypeString('%%(src_var)s'))) \
      .Append('return %s;' % failure_value) \
      .Eblock('}') \
      .Append('%s = %sParse%s(*%s);' % (dst_var,
                                       cpp_type_namespace,
                                       cpp_util.Classname(type_.name),
                                       enum_as_string)) \
      .Sblock('if (%s == %s) {' % (dst_var,
                        self._type_helper.GetEnumDefaultValue(type_,
                          self._namespace))) \
      .Concat(self._AppendError16(
        'u\"\'%%(key)s\': "' + (
            ' + %sGet%sParseError(*%s)' %
            (cpp_type_namespace,
             cpp_util.Classname(type_.name),
             enum_as_string)))) \
      .Append('return %s;' % failure_value) \
      .Eblock('}') \
      .Substitute({'src_var': src_var, 'key': type_.name})
    )
    return c

  def _GeneratePropertyFunctions(self, namespace, params):
    """Generates the member functions for a list of parameters.
    """
    return self._GenerateTypes(namespace, (param.type_ for param in params))

  def _GenerateTypes(self, namespace, types):
    """Generates the member functions for a list of types.
    """
    c = Code()
    for type_ in types:
      c.Cblock(self._GenerateType(namespace, type_))
    return c

  def _GenerateEnumToString(self, cpp_namespace, type_):
    """Generates ToString() which gets the string representation of an enum.
    """
    c = Code()
    classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))

    if cpp_namespace is not None:
      c.Append('// static')
    maybe_namespace = '' if cpp_namespace is None else '%s::' % cpp_namespace

    c.Sblock('const char* %sToString(%s enum_param) {' %
             (maybe_namespace, classname))
    c.Sblock('switch (enum_param) {')
    for enum_value in self._type_helper.FollowRef(type_).enum_values:
      name = enum_value.name
      (c.Append('case %s: ' %
                self._type_helper.GetEnumValue(type_, enum_value)) \
        .Append('  return "%s";' % name))
    (c.Append('case %s:' % self._type_helper.GetEnumNoneValue(type_)) \
      .Append('  return "";') \
      .Eblock('}') \
      .Append('NOTREACHED();') \
      .Eblock('}')
    )
    return c

  def _GenerateEnumFromString(self, cpp_namespace, type_):
    """Generates FromClassNameString() which gets an enum from its string
    representation.
    """
    c = Code()
    classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))

    if cpp_namespace is not None:
      c.Append('// static')
    maybe_namespace = '' if cpp_namespace is None else '%s::' % cpp_namespace

    c.Sblock('%s%s %sParse%s(std::string_view enum_string) {' %
             (maybe_namespace, classname, maybe_namespace, classname))
    for _, enum_value in enumerate(
        self._type_helper.FollowRef(type_).enum_values):
      # This is broken up into all ifs with no else ifs because we get
      # "fatal error C1061: compiler limit : blocks nested too deeply"
      # on Windows.
      name = enum_value.name
      (c.Append('if (enum_string == "%s")' % name) \
        .Append('  return %s;' %
            self._type_helper.GetEnumValue(type_, enum_value)))
    (c.Append('return %s;' % self._type_helper.GetEnumNoneValue(type_)) \
      .Eblock('}')
    )
    return c

  def _GenerateEnumParseErrorMessage(self, cpp_namespace, type_):
    """Generates Get<ClassName>ParseError() which returns a parse error message
    for a given string input.
    """

    c = Code()
    classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))

    if cpp_namespace is not None:
      c.Append('// static')
    maybe_namespace = '' if cpp_namespace is None else '%s::' % cpp_namespace

    c.Sblock(
        'std::u16string %sGet%sParseError(std::string_view enum_string) {' %
        (maybe_namespace, classname))
    error_message = ('u\"expected \\"' + '\\" or \\"'.join(
        enum_value.name
        for enum_value in self._type_helper.FollowRef(type_).enum_values) +
                     '\\", got \\"" + UTF8ToUTF16(enum_string) + u"\\""')
    c.Append('return %s;' % error_message)
    c.Eblock('}')
    return c

  def _GenerateAsyncResponseArguments(self, function_scope, params):
    """Generate the function that creates base::Value parameters to return to a
    callback, promise or pass to an event listener.

    E.g for function "Bar", generate Bar::Results::Create
    E.g for event "Baz", generate Baz::Create

    function_scope: the function scope path, e.g. Foo::Bar for the function
                    Foo::Bar::Baz(). May be None if there is no function scope.
    params: the parameters passed as results or event details.
    """
    c = Code()
    c.Concat(self._GeneratePropertyFunctions(function_scope, params))

    (c.Sblock('base::Value::List %(function_scope)s'
                  'Create(%(declaration_list)s) {') \
      .Append('base::Value::List create_results;') \
      .Append('create_results.reserve(%d);' % len(params) if len(params)
              else '')
    )
    declaration_list = []
    for param in params:
      declaration_list.append(
          cpp_util.GetParameterDeclaration(
              param, self._type_helper.GetCppType(param.type_)))
      c.Cblock(
          self._CreateValueFromType('create_results.Append(%s);', param.name,
                                    param.type_, param.unix_name))
    c.Append('return create_results;')
    c.Eblock('}')
    c.Substitute({
        'function_scope': ('%s::' % function_scope) if function_scope else '',
        'declaration_list':
        ', '.join(declaration_list),
        'param_names':
        ', '.join(param.unix_name for param in params)
    })
    return c

  def _GenerateEventNameConstant(self, event):
    """Generates a constant string array for the event name.
    """
    c = Code()
    c.Append('const char kEventName[] = "%s.%s";' %
             (self._namespace.name, event.name))
    return c

  def _InitializePropertyToDefault(self, prop, dst):
    """Initialize a model.Property to its default value inside an object.

    E.g for optional enum "state", generate dst.state = STATE_NONE;

    dst: Type
    """
    c = Code()
    underlying_type = self._type_helper.FollowRef(prop.type_)
    if (underlying_type.property_type == PropertyType.ENUM and prop.optional):
      c.Append('%s.%s = %s;' % (dst, prop.unix_name,
                                self._type_helper.GetEnumDefaultValue(
                                    underlying_type, self._namespace)))
    return c

  def _AppendError16(self, error16):
    """Appends the given |error16| expression/variable to |error|.
    """
    c = Code()
    if not self._generate_error_messages:
      return c
    c.Append('DCHECK(error.empty());')
    c.Append('error = %s;' % error16)
    return c

  def _GenerateParams(self, params, generate_error_messages=None):
    """Builds the parameter list for a function, given an array of parameters.
    If |generate_error_messages| is specified, it overrides
    |self._generate_error_messages|.
    """
    if generate_error_messages is None:
      generate_error_messages = self._generate_error_messages
    if generate_error_messages:
      params = list(params) + ['std::u16string& error']
    return ', '.join(str(p) for p in params)

  def _GenerateArgs(self, args, generate_error_messages=None):
    """Builds the argument list for a function, given an array of arguments.
    If |generate_error_messages| is specified, it overrides
    |self._generate_error_messages|.
    """
    if generate_error_messages is None:
      generate_error_messages = self._generate_error_messages
    if generate_error_messages:
      args = list(args) + ['error']
    return ', '.join(str(a) for a in args)
