Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(105)

Unified Diff: third_party/WebKit/Source/bindings/scripts/code_generator_v8.py

Issue 2345083004: Split Jinja-related CodeGeneratorV8 guts into a separate class. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/bindings/scripts/code_generator_v8.py
diff --git a/third_party/WebKit/Source/bindings/scripts/code_generator_v8.py b/third_party/WebKit/Source/bindings/scripts/code_generator_v8.py
index 9038af8e2179c5cf1e125460bb332b3f4e6cc878..a31ae8b73917cd2043423e6ce8e872a4e1a60531 100644
--- a/third_party/WebKit/Source/bindings/scripts/code_generator_v8.py
+++ b/third_party/WebKit/Source/bindings/scripts/code_generator_v8.py
@@ -47,93 +47,21 @@ Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
import os
import posixpath
-import re
-import sys
-
-# Path handling for libraries and templates
-# Paths have to be normalized because Jinja uses the exact template path to
-# determine the hash used in the cache filename, and we need a pre-caching step
-# to be concurrency-safe. Use absolute path because __file__ is absolute if
-# module is imported, and relative if executed directly.
-# If paths differ between pre-caching and individual file compilation, the cache
-# is regenerated, which causes a race condition and breaks concurrent build,
-# since some compile processes will try to read the partially written cache.
-module_path, module_filename = os.path.split(os.path.realpath(__file__))
-third_party_dir = os.path.normpath(os.path.join(
- module_path, os.pardir, os.pardir, os.pardir, os.pardir))
-templates_dir = os.path.normpath(os.path.join(
- module_path, os.pardir, 'templates'))
-# Make sure extension is .py, not .pyc or .pyo, so doesn't depend on caching
-module_pyname = os.path.splitext(module_filename)[0] + '.py'
-
-# jinja2 is in chromium's third_party directory.
-# Insert at 1 so at front to override system libraries, and
-# after path[0] == invoking script dir
-sys.path.insert(1, third_party_dir)
-import jinja2
+from code_generator import CodeGeneratorBase, normalize_and_sort_includes
from idl_definitions import Visitor
-import idl_types
from idl_types import IdlType
-from v8_attributes import attribute_filters
import v8_callback_interface
import v8_dictionary
from v8_globals import includes, interfaces
import v8_interface
-from v8_methods import method_filters
import v8_types
import v8_union
-from v8_utilities import capitalize, cpp_name, for_origin_trial_feature, unique_by
-from utilities import (
- idl_filename_to_component, is_valid_component_dependency, is_testing_target,
- shorten_union_name, format_remove_duplicates, format_blink_cpp_source_code)
-
-
-def normalize_and_sort_includes(include_paths):
- normalized_include_paths = []
- for include_path in include_paths:
- match = re.search(r'/gen/blink/(.*)$', posixpath.abspath(include_path))
- if match:
- include_path = match.group(1)
- normalized_include_paths.append(include_path)
- return sorted(normalized_include_paths)
-
-
-def render_template(include_paths, header_template, cpp_template,
- template_context, component=None):
- template_context['code_generator'] = module_pyname
-
- # Add includes for any dependencies
- template_context['header_includes'] = normalize_and_sort_includes(
- template_context['header_includes'])
-
- for include_path in include_paths:
- if component:
- dependency = idl_filename_to_component(include_path)
- assert is_valid_component_dependency(component, dependency)
- includes.add(include_path)
-
- template_context['cpp_includes'] = normalize_and_sort_includes(includes)
-
- header_text = header_template.render(template_context)
- cpp_text = cpp_template.render(template_context)
- return header_text, cpp_text
-
-
-def set_global_type_info(info_provider):
- interfaces_info = info_provider.interfaces_info
- idl_types.set_ancestors(interfaces_info['ancestors'])
- IdlType.set_callback_interfaces(interfaces_info['callback_interfaces'])
- IdlType.set_dictionaries(interfaces_info['dictionaries'])
- IdlType.set_enums(info_provider.enumerations)
- IdlType.set_implemented_as_interfaces(interfaces_info['implemented_as_interfaces'])
- IdlType.set_garbage_collected_types(interfaces_info['garbage_collected_interfaces'])
- v8_types.set_component_dirs(interfaces_info['component_dirs'])
-
-
-def should_generate_code(definitions):
- return definitions.interfaces or definitions.dictionaries
+from v8_utilities import cpp_name
+from utilities import idl_filename_to_component, is_testing_target, shorten_union_name
+# Make sure extension is .py, not .pyc or .pyo, so doesn't depend on caching
+MODULE_PYNAME = os.path.splitext(os.path.basename(__file__))[0] + '.py'
def depending_union_type(idl_type):
"""Returns the union type name if the given idl_type depends on a
@@ -195,20 +123,17 @@ class TypedefResolver(Visitor):
self._resolve_typedefs(typed_object)
-class CodeGeneratorBase(object):
+class CodeGeneratorV8Base(CodeGeneratorBase):
"""Base class for v8 bindings generator and IDL dictionary impl generator"""
def __init__(self, info_provider, cache_dir, output_dir):
- self.info_provider = info_provider
- self.jinja_env = initialize_jinja_env(cache_dir)
- self.output_dir = output_dir
+ CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider, cache_dir, output_dir)
self.typedef_resolver = TypedefResolver(info_provider)
- set_global_type_info(info_provider)
def generate_code(self, definitions, definition_name):
"""Returns .h/.cpp code as ((path, content)...)."""
# Set local type info
- if not should_generate_code(definitions):
+ if not self.should_generate_code(definitions):
return set()
IdlType.set_callback_functions(definitions.callback_functions.keys())
@@ -221,9 +146,9 @@ class CodeGeneratorBase(object):
raise NotImplementedError()
-class CodeGeneratorV8(CodeGeneratorBase):
+class CodeGeneratorV8(CodeGeneratorV8Base):
def __init__(self, info_provider, cache_dir, output_dir):
- CodeGeneratorBase.__init__(self, info_provider, cache_dir, output_dir)
+ CodeGeneratorV8Base.__init__(self, info_provider, cache_dir, output_dir)
def output_paths(self, definition_name):
header_path = posixpath.join(self.output_dir,
@@ -283,7 +208,7 @@ class CodeGeneratorV8(CodeGeneratorBase):
interface_info.get('additional_header_includes', []))
header_template = self.jinja_env.get_template(header_template_filename)
cpp_template = self.jinja_env.get_template(cpp_template_filename)
- header_text, cpp_text = render_template(
+ header_text, cpp_text = self.render_template(
include_paths, header_template, cpp_template, template_context,
component)
header_path, cpp_path = self.output_paths(interface_name)
@@ -308,7 +233,7 @@ class CodeGeneratorV8(CodeGeneratorBase):
if not is_testing_target(interface_info.get('full_path')):
template_context['header_includes'].add(self.info_provider.include_path_for_export)
template_context['exported'] = self.info_provider.specifier_for_export
- header_text, cpp_text = render_template(
+ header_text, cpp_text = self.render_template(
include_paths, header_template, cpp_template, template_context)
header_path, cpp_path = self.output_paths(dictionary_name)
return (
@@ -317,9 +242,9 @@ class CodeGeneratorV8(CodeGeneratorBase):
)
-class CodeGeneratorDictionaryImpl(CodeGeneratorBase):
+class CodeGeneratorDictionaryImpl(CodeGeneratorV8Base):
def __init__(self, info_provider, cache_dir, output_dir):
- CodeGeneratorBase.__init__(self, info_provider, cache_dir, output_dir)
+ CodeGeneratorV8Base.__init__(self, info_provider, cache_dir, output_dir)
def output_paths(self, definition_name, interface_info):
output_dir = posixpath.join(self.output_dir,
@@ -344,7 +269,7 @@ class CodeGeneratorDictionaryImpl(CodeGeneratorBase):
template_context['header_includes'].add(self.info_provider.include_path_for_export)
template_context['header_includes'].update(
interface_info.get('additional_header_includes', []))
- header_text, cpp_text = render_template(
+ header_text, cpp_text = self.render_template(
include_paths, header_template, cpp_template, template_context)
header_path, cpp_path = self.output_paths(
cpp_name(dictionary), interface_info)
@@ -354,18 +279,15 @@ class CodeGeneratorDictionaryImpl(CodeGeneratorBase):
)
-class CodeGeneratorUnionType(object):
+class CodeGeneratorUnionType(CodeGeneratorBase):
"""Generates union type container classes.
This generator is different from CodeGeneratorV8 and
CodeGeneratorDictionaryImpl. It assumes that all union types are already
collected. It doesn't process idl files directly.
"""
def __init__(self, info_provider, cache_dir, output_dir, target_component):
- self.info_provider = info_provider
- self.jinja_env = initialize_jinja_env(cache_dir)
- self.output_dir = output_dir
+ CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider, cache_dir, output_dir)
self.target_component = target_component
- set_global_type_info(info_provider)
def _generate_container_code(self, union_type):
header_template = self.jinja_env.get_template('union_container.h')
@@ -376,7 +298,7 @@ class CodeGeneratorUnionType(object):
self.info_provider.include_path_for_export)
template_context['header_includes'] = normalize_and_sort_includes(
template_context['header_includes'])
- template_context['code_generator'] = module_pyname
+ template_context['code_generator'] = self.generator_name
template_context['exported'] = self.info_provider.specifier_for_export
name = shorten_union_name(union_type)
template_context['this_include_header_name'] = name
@@ -414,87 +336,3 @@ class CodeGeneratorUnionType(object):
for union_type in union_types:
outputs.update(self._generate_container_code(union_type))
return outputs
-
-
-def initialize_jinja_env(cache_dir):
- jinja_env = jinja2.Environment(
- loader=jinja2.FileSystemLoader(templates_dir),
- # Bytecode cache is not concurrency-safe unless pre-cached:
- # if pre-cached this is read-only, but writing creates a race condition.
- bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir),
- keep_trailing_newline=True, # newline-terminate generated files
- lstrip_blocks=True, # so can indent control flow tags
- trim_blocks=True)
- jinja_env.filters.update({
- 'blink_capitalize': capitalize,
- 'exposed': exposed_if,
- 'for_origin_trial_feature': for_origin_trial_feature,
- 'format_blink_cpp_source_code': format_blink_cpp_source_code,
- 'format_remove_duplicates': format_remove_duplicates,
- 'runtime_enabled': runtime_enabled_if,
- 'secure_context': secure_context_if,
- 'unique_by': unique_by,
- })
- jinja_env.filters.update(attribute_filters())
- jinja_env.filters.update(v8_interface.constant_filters())
- jinja_env.filters.update(method_filters())
- return jinja_env
-
-
-def generate_indented_conditional(code, conditional):
- # Indent if statement to level of original code
- indent = re.match(' *', code).group(0)
- return ('%sif (%s) {\n' % (indent, conditional) +
- ' %s\n' % '\n '.join(code.splitlines()) +
- '%s}\n' % indent)
-
-
-# [Exposed]
-def exposed_if(code, exposed_test):
- if not exposed_test:
- return code
- return generate_indented_conditional(code, 'executionContext && (%s)' % exposed_test)
-
-
-# [SecureContext]
-def secure_context_if(code, secure_context_test):
- if not secure_context_test:
- return code
- return generate_indented_conditional(code, 'executionContext && (%s)' % secure_context_test)
-
-
-# [RuntimeEnabled]
-def runtime_enabled_if(code, runtime_enabled_function_name):
- if not runtime_enabled_function_name:
- return code
- return generate_indented_conditional(code, '%s()' % runtime_enabled_function_name)
-
-
-################################################################################
-
-def main(argv):
- # If file itself executed, cache templates
- try:
- cache_dir = argv[1]
- dummy_filename = argv[2]
- except IndexError:
- print 'Usage: %s CACHE_DIR DUMMY_FILENAME' % argv[0]
- return 1
-
- # Cache templates
- jinja_env = initialize_jinja_env(cache_dir)
- template_filenames = [filename for filename in os.listdir(templates_dir)
- # Skip .svn, directories, etc.
- if filename.endswith(('.cpp', '.h'))]
- for template_filename in template_filenames:
- jinja_env.get_template(template_filename)
-
- # Create a dummy file as output for the build system,
- # since filenames of individual cache files are unpredictable and opaque
- # (they are hashes of the template path, which varies based on environment)
- with open(dummy_filename, 'w') as dummy_file:
- pass # |open| creates or touches the file
-
-
-if __name__ == '__main__':
- sys.exit(main(sys.argv))
« no previous file with comments | « third_party/WebKit/Source/bindings/scripts/code_generator.py ('k') | third_party/WebKit/Source/bindings/scripts/scripts.gni » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698