Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 # pylint: disable=import-error,print-statement,relative-import | 5 # pylint: disable=import-error,print-statement,relative-import |
| 6 | 6 |
| 7 """Generates Blink Web Module bindings. | 7 """Generates Blink Web Module bindings. |
| 8 | 8 |
| 9 The Blink Web Module bindings provide a stable, IDL-generated interface for the | 9 The Blink Web Module bindings provide a stable, IDL-generated interface for the |
| 10 Web Modules. | 10 Web Modules. |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 22 import os | 22 import os |
| 23 import posixpath | 23 import posixpath |
| 24 | 24 |
| 25 from code_generator import CodeGeneratorBase, render_template | 25 from code_generator import CodeGeneratorBase, render_template |
| 26 # TODO(dglazkov): Move TypedefResolver to code_generator.py | 26 # TODO(dglazkov): Move TypedefResolver to code_generator.py |
| 27 from code_generator_v8 import TypedefResolver | 27 from code_generator_v8 import TypedefResolver |
| 28 from name_style_converter import NameStyleConverter | 28 from name_style_converter import NameStyleConverter |
| 29 | 29 |
| 30 MODULE_PYNAME = os.path.splitext(os.path.basename(__file__))[0] + '.py' | 30 MODULE_PYNAME = os.path.splitext(os.path.basename(__file__))[0] + '.py' |
| 31 | 31 |
| 32 OILPAN_INCLUDE_PATH = 'platform/heap/Handle.h' | |
|
haraken
2017/02/11 09:56:46
BLINK_GC_INCLUDE_PATH
Oilpan is a project name an
dglazkov
2017/02/11 21:56:20
Good point. Incorporated inline.
| |
| 33 STRING_INCLUDE_PATH = 'wtf/text/WTFString.h' | |
| 32 WEB_MODULE_IDL_ATTRIBUTE = 'WebModuleAPI' | 34 WEB_MODULE_IDL_ATTRIBUTE = 'WebModuleAPI' |
| 33 STRING_INCLUDE_PATH = 'wtf/text/WTFString.h' | |
| 34 | 35 |
| 35 def interface_context(idl_interface): | 36 |
| 36 builder = InterfaceContextBuilder(MODULE_PYNAME, TypeResolver()) | 37 def interface_context(idl_interface, type_resolver): |
| 38 builder = InterfaceContextBuilder(MODULE_PYNAME, type_resolver) | |
| 37 builder.set_class_name(idl_interface.name) | 39 builder.set_class_name(idl_interface.name) |
| 38 builder.set_inheritance(idl_interface.parent) | 40 builder.set_inheritance(idl_interface.parent) |
| 39 | 41 |
| 40 for idl_attribute in idl_interface.attributes: | 42 for idl_attribute in idl_interface.attributes: |
| 41 builder.add_attribute(idl_attribute) | 43 builder.add_attribute(idl_attribute) |
| 42 | 44 |
| 43 for idl_operation in idl_interface.operations: | 45 for idl_operation in idl_interface.operations: |
| 44 builder.add_operation(idl_operation) | 46 builder.add_operation(idl_operation) |
| 45 | 47 |
| 46 return builder.build() | 48 return builder.build() |
| 47 | 49 |
| 48 | 50 |
| 49 class TypeResolver(object): | 51 class TypeResolver(object): |
| 50 """Resolves Web IDL types into corresponding C++ types and include paths | 52 """Resolves Web IDL types into corresponding C++ types and include paths |
| 51 to the generated and existing files.""" | 53 to the generated and existing files.""" |
| 52 | 54 |
| 53 def includes_from_interface(self, base_type): | 55 def __init__(self, interfaces_info): |
| 54 # TODO(dglazkov): Are there any exceptional conditions here? | 56 self.interfaces_info = interfaces_info |
| 55 return set([base_type]) | 57 |
| 58 def includes_from_interface(self, interface_name): | |
| 59 interface_info = self.interfaces_info.get(interface_name) | |
| 60 if interface_info is None: | |
| 61 raise KeyError('Unkown interface "%s".' % interface_name) | |
| 62 return set([interface_info['include_path']]) | |
| 56 | 63 |
| 57 def _includes_from_type(self, idl_type): | 64 def _includes_from_type(self, idl_type): |
| 58 if idl_type.is_void: | 65 if idl_type.is_void: |
| 59 return set() | 66 return set() |
| 60 if idl_type.is_primitive_type: | 67 if idl_type.is_primitive_type: |
| 61 return set() | 68 return set() |
| 62 if idl_type.is_string_type: | 69 if idl_type.is_string_type: |
| 63 return set([STRING_INCLUDE_PATH]) | 70 return set([STRING_INCLUDE_PATH]) |
| 64 | 71 |
| 65 # TODO(dglazkov): Handle complex/weird types. | 72 # TODO(dglazkov): Handle complex/weird types. |
| 66 # TODO(dglazkov): Make these proper paths to generated and non-generated | 73 return self.includes_from_interface(idl_type.base_type) |
| 67 # files. | |
| 68 return set([idl_type.base_type]) | |
| 69 | 74 |
| 70 def includes_from_definition(self, idl_definition): | 75 def includes_from_definition(self, idl_definition): |
| 71 return self._includes_from_type(idl_definition.idl_type) | 76 return self._includes_from_type(idl_definition.idl_type) |
| 72 | 77 |
| 73 def type_from_definition(self, idl_definition): | 78 def type_from_definition(self, idl_definition): |
| 74 # TODO(dglazkov): The output of this method must be a reasonable C++ | 79 # TODO(dglazkov): The output of this method must be a reasonable C++ |
| 75 # type that can be used directly in the jinja2 template. | 80 # type that can be used directly in the jinja2 template. |
| 76 return idl_definition.idl_type.base_type | 81 return idl_definition.idl_type.base_type |
| 77 | 82 |
| 83 def base_class_includes(self): | |
| 84 return set([OILPAN_INCLUDE_PATH]) | |
| 85 | |
| 78 | 86 |
| 79 class InterfaceContextBuilder(object): | 87 class InterfaceContextBuilder(object): |
| 80 def __init__(self, code_generator, type_resolver): | 88 def __init__(self, code_generator, type_resolver): |
| 81 self.result = {'code_generator': code_generator} | 89 self.result = {'code_generator': code_generator} |
| 82 self.type_resolver = type_resolver | 90 self.type_resolver = type_resolver |
| 83 | 91 |
| 84 def set_class_name(self, class_name): | 92 def set_class_name(self, class_name): |
| 85 converter = NameStyleConverter(class_name) | 93 converter = NameStyleConverter(class_name) |
| 86 self.result['class_name'] = converter.to_all_cases() | 94 self.result['class_name'] = converter.to_all_cases() |
| 95 self._ensure_set('cpp_includes').update( | |
| 96 self.type_resolver.includes_from_interface(class_name)) | |
| 87 | 97 |
| 88 def set_inheritance(self, base_interface): | 98 def set_inheritance(self, base_interface): |
| 89 if base_interface is None: | 99 if base_interface is None: |
| 100 self._ensure_set('header_includes').update( | |
| 101 self.type_resolver.base_class_includes()) | |
| 90 return | 102 return |
| 91 self.result['inherits_expression'] = ' : public %s' % base_interface | 103 self.result['base_class'] = base_interface |
| 92 self._ensure_set('cpp_includes').update( | 104 self._ensure_set('header_includes').update( |
| 93 self.type_resolver.includes_from_interface(base_interface)) | 105 self.type_resolver.includes_from_interface(base_interface)) |
| 94 | 106 |
| 95 def _ensure_set(self, name): | 107 def _ensure_set(self, name): |
| 96 return self.result.setdefault(name, set()) | 108 return self.result.setdefault(name, set()) |
| 97 | 109 |
| 98 def _ensure_list(self, name): | 110 def _ensure_list(self, name): |
| 99 return self.result.setdefault(name, []) | 111 return self.result.setdefault(name, []) |
| 100 | 112 |
| 101 def add_attribute(self, idl_attribute): | 113 def add_attribute(self, idl_attribute): |
| 102 self._ensure_list('attributes').append( | 114 self._ensure_list('attributes').append( |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 129 } | 141 } |
| 130 | 142 |
| 131 def build(self): | 143 def build(self): |
| 132 return self.result | 144 return self.result |
| 133 | 145 |
| 134 | 146 |
| 135 class CodeGeneratorWebModule(CodeGeneratorBase): | 147 class CodeGeneratorWebModule(CodeGeneratorBase): |
| 136 def __init__(self, info_provider, cache_dir, output_dir): | 148 def __init__(self, info_provider, cache_dir, output_dir): |
| 137 CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider, | 149 CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider, |
| 138 cache_dir, output_dir) | 150 cache_dir, output_dir) |
| 151 self.type_resolver = TypeResolver(info_provider.interfaces_info) | |
| 139 self.typedef_resolver = TypedefResolver(info_provider) | 152 self.typedef_resolver = TypedefResolver(info_provider) |
| 140 | 153 |
| 141 def get_template(self, file_extension): | 154 def get_template(self, file_extension): |
| 142 template_filename = 'web_module_interface.%s.tmpl' % file_extension | 155 template_filename = 'web_module_interface.%s.tmpl' % file_extension |
| 143 return self.jinja_env.get_template(template_filename) | 156 return self.jinja_env.get_template(template_filename) |
| 144 | 157 |
| 145 def generate_file(self, template_context, file_extension): | 158 def generate_file(self, template_context, file_extension): |
| 146 template = self.get_template(file_extension) | 159 template = self.get_template(file_extension) |
| 147 path = posixpath.join( | 160 path = posixpath.join( |
| 148 self.output_dir, | 161 self.output_dir, |
| 149 '%s.%s' % (template_context['class_name']['snake_case'], | 162 '%s.%s' % (template_context['class_name']['snake_case'], |
| 150 file_extension)) | 163 file_extension)) |
| 151 text = render_template(template, template_context) | 164 text = render_template(template, template_context) |
| 152 return (path, text) | 165 return (path, text) |
| 153 | 166 |
| 154 def generate_interface_code(self, interface): | 167 def generate_interface_code(self, interface): |
| 155 # TODO(dglazkov): Implement callback interfaces. | 168 # TODO(dglazkov): Implement callback interfaces. |
| 156 # TODO(dglazkov): Make sure partial interfaces are handled. | 169 # TODO(dglazkov): Make sure partial interfaces are handled. |
| 157 if interface.is_callback or interface.is_partial: | 170 if interface.is_callback or interface.is_partial: |
| 158 raise ValueError('Partial or callback interfaces are not supported') | 171 raise ValueError('Partial or callback interfaces are not supported') |
| 159 | 172 |
| 160 template_context = interface_context(interface) | 173 template_context = interface_context(interface, self.type_resolver) |
| 161 | 174 |
| 162 return ( | 175 return ( |
| 163 self.generate_file(template_context, 'h'), | 176 self.generate_file(template_context, 'h'), |
| 164 self.generate_file(template_context, 'cc') | 177 self.generate_file(template_context, 'cc') |
| 165 ) | 178 ) |
| 166 | 179 |
| 167 def generate_code(self, definitions, definition_name): | 180 def generate_code(self, definitions, definition_name): |
| 168 self.typedef_resolver.resolve(definitions, definition_name) | 181 self.typedef_resolver.resolve(definitions, definition_name) |
| 169 | 182 |
| 170 # TODO(dglazkov): Implement dictionaries | 183 # TODO(dglazkov): Implement dictionaries |
| 171 if definition_name not in definitions.interfaces: | 184 if definition_name not in definitions.interfaces: |
| 172 return None | 185 return None |
| 173 | 186 |
| 174 interface = definitions.interfaces[definition_name] | 187 interface = definitions.interfaces[definition_name] |
| 175 if WEB_MODULE_IDL_ATTRIBUTE not in interface.extended_attributes: | 188 if WEB_MODULE_IDL_ATTRIBUTE not in interface.extended_attributes: |
| 176 return None | 189 return None |
| 177 | 190 |
| 178 return self.generate_interface_code(interface) | 191 return self.generate_interface_code(interface) |
| OLD | NEW |