def Generate(self, _):  # namespace not relevant, this is a bundle
        c = code.Code()
        c.Append(cpp_util.CHROMIUM_LICENSE)
        c.Append()
        c.Append('#include "%s"' % (cpp_util.ToPosixPath(
            os.path.join(self._bundle._impl_dir,
                         'generated_api_registration.h'))))
        c.Append()
        c.Append('#include "build/build_config.h"')
        c.Append('#include "build/chromeos_buildflags.h"')
        c.Append()
        for namespace in self._bundle._model.namespaces.values():
            namespace_name = namespace.unix_name.replace("experimental_", "")
            implementation_header = namespace.compiler_options.get(
                "implemented_in", "%s/%s/%s_api.h" %
                (self._bundle._impl_dir, namespace_name, namespace_name))
            if not os.path.exists(
                    os.path.join(self._bundle._root,
                                 os.path.normpath(implementation_header))):
                if "implemented_in" in namespace.compiler_options:
                    raise ValueError(
                        'Header file for namespace "%s" specified in '
                        'compiler_options not found: %s' %
                        (namespace.unix_name, implementation_header))
                continue
            ifdefs = self._bundle._GetPlatformIfdefs(namespace)
            if ifdefs is not None:
                c.Append("#if %s" % ifdefs, indent_level=0)

            c.Append('#include "%s"' %
                     cpp_util.ToPosixPath(implementation_header))

            if ifdefs is not None:
                c.Append("#endif  // %s" % ifdefs, indent_level=0)
        c.Append()
        c.Append('#include '
                 '"extensions/browser/extension_function_registry.h"')
        c.Append()
        c.Concat(cpp_util.OpenNamespace(self._bundle._cpp_namespace))
        c.Append()
        c.Concat(self._bundle._GenerateFunctionRegistryRegisterAll())
        c.Append()
        c.Concat(cpp_util.CloseNamespace(self._bundle._cpp_namespace))
        c.Append()
        return c
    def _GenerateHeader(self, file_base, body_code):
        """Generates a code.Code object for a header file

    Parameters:
    - |file_base| - the base of the filename, e.g. 'foo' (for 'foo.h')
    - |body_code| - the code to put in between the multiple inclusion guards"""
        c = code.Code()
        c.Append(cpp_util.CHROMIUM_LICENSE)
        c.Append()
        c.Append(cpp_util.GENERATED_BUNDLE_FILE_MESSAGE %
                 cpp_util.ToPosixPath(self._source_file_dir))
        ifndef_name = cpp_util.GenerateIfndefName(
            '%s/%s.h' %
            (cpp_util.ToPosixPath(self._source_file_dir), file_base))
        c.Append()
        c.Append('#ifndef %s' % ifndef_name)
        c.Append('#define %s' % ifndef_name)
        c.Append()
        c.Concat(body_code)
        c.Append()
        c.Append('#endif  // %s' % ifndef_name)
        c.Append()
        return c
    def GenerateIncludes(self, include_soft=False):
        """Returns the #include lines for self._default_namespace.
    """
        c = Code()
        if self._default_namespace.manifest_keys:
            c.Append('#include "base/strings/string_piece.h"')

        # Note: It's possible that there are multiple dependencies from the same
        # API. Make sure to only include them once.
        added_paths = set()
        for namespace, dependencies in self._NamespaceTypeDependencies().items(
        ):
            for dependency in dependencies:
                if dependency.hard or include_soft:
                    path = '%s/%s.h' % (namespace.source_file_dir,
                                        namespace.unix_name)
                    if path not in added_paths:
                        added_paths.add(path)
                        c.Append('#include "%s"' % cpp_util.ToPosixPath(path))
        return c
    def Generate(self, _):  # namespace not relevant, this is a bundle
        c = code.Code()
        c.Append(cpp_util.CHROMIUM_LICENSE)
        c.Append()
        c.Append('#include "%s"' % (cpp_util.ToPosixPath(
            os.path.join(self._bundle._source_file_dir,
                         'generated_schemas.h'))))
        c.Append()
        c.Append('#include <algorithm>')
        c.Append('#include <iterator>')
        c.Append()
        c.Append('#include "base/containers/fixed_flat_map.h"')
        c.Append('#include "base/strings/string_piece.h"')
        c.Append()
        c.Append('namespace {')
        for api in self._bundle._api_defs:
            namespace = self._bundle._model.namespaces[api.get('namespace')]
            json_content = json.dumps(_PrefixSchemaWithNamespace(
                _RemoveUnneededFields(api)),
                                      separators=(',', ':'))
            # This will output a valid JSON C string. Note that some schemas are
            # too large to compile on windows. Split the JSON up into several
            # strings, since apparently that helps.
            max_length = 8192
            segments = [
                json_content[i:i + max_length]
                for i in range(0, len(json_content), max_length)
            ]
            c.Append('constexpr char %s[] = R"R(%s)R";' %
                     (_FormatNameAsConstant(
                         namespace.name), ')R" R"R('.join(segments)))
        c.Append('}  // namespace')
        c.Append()
        c.Concat(cpp_util.OpenNamespace(self._bundle._cpp_namespace))
        c.Append()
        c.Append('// static')
        c.Sblock('bool %s::IsGenerated(base::StringPiece name) {' %
                 self._bundle._GenerateBundleClass('GeneratedSchemas'))
        c.Append('return !Get(name).empty();')
        c.Eblock('}')
        c.Append()
        c.Append('// static')
        c.Sblock('base::StringPiece %s::Get(base::StringPiece name) {' %
                 self._bundle._GenerateBundleClass('GeneratedSchemas'))

        c.Append(
            'static constexpr auto kSchemas = '
            'base::MakeFixedFlatMap<base::StringPiece, base::StringPiece>({')
        c.Sblock()
        namespaces = [
            self._bundle._model.namespaces[api.get('namespace')].name
            for api in self._bundle._api_defs
        ]
        for namespace in sorted(namespaces):
            schema_constant_name = _FormatNameAsConstant(namespace)
            c.Append('{"%s", %s},' % (namespace, schema_constant_name))
        c.Eblock('});')
        c.Append('auto it = kSchemas.find(name);')
        c.Append(
            'return it != kSchemas.end() ? it->second : base::StringPiece();')
        c.Eblock('}')
        c.Append()
        c.Concat(cpp_util.CloseNamespace(self._bundle._cpp_namespace))
        c.Append()
        return c
Beispiel #5
0
  def Generate(self):
    """Generates a Code object for features.
    """
    c = Code()
    (c.Append(cpp_util.CHROMIUM_LICENSE)
      .Append()
      .Append(cpp_util.GENERATED_FEATURE_MESSAGE %
              cpp_util.ToPosixPath(self._source_file))
      .Append()
      .Append('#include <string>')
      .Append()
      .Append('#include "%s.h"' %
              cpp_util.ToPosixPath(self._source_file_filename))
      .Append()
      .Append('#include "base/notreached.h"')
      .Append()
      .Concat(cpp_util.OpenNamespace(self._namespace))
      .Append()
    )

    # Generate the constructor.
    (c.Append('%s::%s() {' % (self._class_name, self._class_name))
      .Sblock()
    )
    for feature in self._feature_defs:
      c.Append('features_["%s"] = %s;'
                       % (feature.name,
                          cpp_util.FeatureNameToConstantName(feature.name)))
    (c.Eblock()
      .Append('}')
      .Append()
    )

    # Generate the ToString function.
    (c.Append('const char* %s::ToString('
                  '%s::ID id) const {' % (self._class_name, self._class_name))
      .Sblock()
      .Append('switch (id) {')
      .Sblock()
    )
    for feature in self._feature_defs:
      c.Append('case %s: return "%s";' %
          (cpp_util.FeatureNameToConstantName(feature.name), feature.name))
    (c.Append('case kUnknown: break;')
      .Append('case kEnumBoundary: break;')
      .Eblock()
      .Append('}')
      .Append('NOTREACHED();')
      .Append('return "";')
    )
    (c.Eblock()
      .Append('}')
      .Append()
    )

    # Generate the FromString function.

    (c.Append('%s::ID %s::FromString('
                  'const std::string& id) const {'
                  % (self._class_name, self._class_name))
      .Sblock()
      .Append('const auto& it = features_.find(id);' % self._class_name)
      .Append('return (it == features_.end()) ? kUnknown : it->second;')
      .Eblock()
      .Append('}')
      .Append()
      .Cblock(cpp_util.CloseNamespace(self._namespace))
    )

    return c
Beispiel #6
0
    def Generate(self):
        """Generates a Code object with the .h for a single namespace.
    """
        c = Code()
        (c.Append(cpp_util.CHROMIUM_LICENSE).Append().Append(
            cpp_util.GENERATED_FILE_MESSAGE %
            cpp_util.ToPosixPath(self._namespace.source_file)).Append())

        # Hack: for the purpose of gyp the header file will always be the source
        # file with its file extension replaced by '.h'. Assume so.
        output_file = os.path.splitext(self._namespace.source_file)[0] + '.h'
        ifndef_name = cpp_util.GenerateIfndefName(output_file)

        # Hack: tabs and windows have circular references, so only generate hard
        # references for them (i.e. anything that can't be forward declared). In
        # other cases, generate soft dependencies so that they can include
        # non-optional types from other namespaces.
        include_soft = self._namespace.name not in ('tabs', 'windows')

        (c.Append('#ifndef %s' % ifndef_name).Append(
            '#define %s' % ifndef_name).Append().Append('#include <stdint.h>').
         Append().Append('#include <map>').Append('#include <memory>').Append(
             '#include <string>').Append('#include <vector>').Append().Append(
                 '#include "base/values.h"').Cblock(
                     self._type_helper.GenerateIncludes(
                         include_soft=include_soft)).Append())

        # Hack: we're not generating soft includes for tabs and windows, so we need
        # to generate forward declarations for them.
        if not include_soft:
            c.Cblock(self._type_helper.GenerateForwardDeclarations())

        cpp_namespace = cpp_util.GetCppNamespace(
            self._namespace.environment.namespace_pattern,
            self._namespace.unix_name)
        c.Concat(cpp_util.OpenNamespace(cpp_namespace))
        c.Append()
        if self._namespace.properties:
            (c.Append('//').Append('// Properties').Append('//').Append())
            for prop in self._namespace.properties.values():
                property_code = self._type_helper.GeneratePropertyValues(
                    prop, 'extern const %(type)s %(name)s;')
                if property_code:
                    c.Cblock(property_code)
        if self._namespace.types:
            (c.Append('//').Append('// Types').Append('//').Append().Cblock(
                self._GenerateTypes(self._FieldDependencyOrder(),
                                    is_toplevel=True,
                                    generate_typedefs=True)))
        if self._namespace.manifest_keys:
            c.Append('//')
            c.Append('// Manifest Keys')
            c.Append('//')
            c.Append()
            c.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.Concat(cpp_util.CloseNamespace(cpp_namespace)).Append().Append(
            '#endif  // %s' % ifndef_name).Append())
        return c