blob: c243a8cbb97a96d8ad5a612787049d5da4dce184 [file] [log] [blame]
# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import web_idl
from . import name_style
from .clang_format import clang_format
from .code_node import CodeNode
from .code_node import EmptyNode
from .code_node import LiteralNode
from .code_node import SequenceNode
from .code_node import render_code_node
from .codegen_accumulator import CodeGenAccumulator
from .path_manager import PathManager
def make_copyright_header():
return LiteralNode("""\
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.\
""")
def make_forward_declarations(accumulator):
assert isinstance(accumulator, CodeGenAccumulator)
class ForwardDeclarations(object):
def __init__(self, accumulator):
self._accumulator = accumulator
def __str__(self):
return "\n".join([
"class {};".format(class_name)
for class_name in sorted(self._accumulator.class_decls)
] + [
"struct {};".format(struct_name)
for struct_name in sorted(self._accumulator.struct_decls)
])
return LiteralNode(ForwardDeclarations(accumulator))
def make_header_include_directives(accumulator):
assert isinstance(accumulator, CodeGenAccumulator)
class HeaderIncludeDirectives(object):
def __init__(self, accumulator):
self._accumulator = accumulator
def __str__(self):
return "\n".join([
"#include \"{}\"".format(header)
for header in sorted(self._accumulator.include_headers)
])
return LiteralNode(HeaderIncludeDirectives(accumulator))
def component_export(component):
assert isinstance(component, web_idl.Component)
return name_style.macro(component, "EXPORT")
def component_export_header(component):
assert isinstance(component, web_idl.Component)
if component == "core":
return "third_party/blink/renderer/core/core_export.h"
elif component == "modules":
return "third_party/blink/renderer/modules/modules_export.h"
else:
assert False
def enclose_with_header_guard(code_node, header_guard):
assert isinstance(code_node, CodeNode)
assert isinstance(header_guard, str)
return SequenceNode([
LiteralNode("#ifndef {}".format(header_guard)),
LiteralNode("#define {}".format(header_guard)),
EmptyNode(),
code_node,
EmptyNode(),
LiteralNode("#endif // {}".format(header_guard)),
])
def enclose_with_namespace(code_node, namespace):
assert isinstance(code_node, CodeNode)
assert isinstance(namespace, str)
return SequenceNode([
LiteralNode("namespace {} {{".format(namespace)),
EmptyNode(),
code_node,
EmptyNode(),
LiteralNode("}} // namespace {}".format(namespace)),
])
def traverse_idl_types(idl_definition, callback):
"""
Traverses in the given |idl_definition| to find all the web_idl.IdlType used
in the IDL definition. Invokes |callback| with each web_idl.IdlType.
"""
assert callable(callback)
def get(obj, attr):
try:
return getattr(obj, attr)
except:
return ()
xs = (get(idl_definition, "attributes") + get(idl_definition, "constants")
+ get(idl_definition, "own_members") + (idl_definition, ))
for x in xs:
idl_type = get(x, "idl_type")
if idl_type:
callback(idl_type)
xs = (get(idl_definition, "constructors") + get(idl_definition,
"operations"))
for x in xs:
for argument in x.arguments:
callback(argument.idl_type)
if x.return_type is not None:
callback(x.return_type)
xs = get(idl_definition, "flattened_member_types")
for x in xs:
callback(x)
def collect_include_headers(idl_definition):
"""
Returns a list of include headers that are required by generated bindings of
|idl_definition|.
"""
type_def_objs = set()
def collect_type_def_obj(idl_type):
type_def_obj = idl_type.unwrap().type_definition_object
if type_def_obj is not None:
type_def_objs.add(type_def_obj)
traverse_idl_types(idl_definition, collect_type_def_obj)
header_paths = set(idl_definition.code_generator_info.blink_headers or [])
for type_def_obj in type_def_objs:
if isinstance(type_def_obj, web_idl.Enumeration):
continue
if isinstance(type_def_obj, web_idl.Dictionary):
header_paths.add(PathManager(type_def_obj).dict_path(ext="h"))
continue
header_paths.add(PathManager(type_def_obj).api_path(ext="h"))
return header_paths
def write_code_node_to_file(code_node, filepath):
"""Renders |code_node| and then write the result to |filepath|."""
assert isinstance(code_node, CodeNode)
assert isinstance(filepath, str)
rendered_text = render_code_node(code_node)
format_result = clang_format(rendered_text, filename=filepath)
web_idl.file_io.write_to_file_if_changed(filepath, format_result.contents)