| 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 STRING_INCLUDE_PATH = 'wtf/text/WTFString.h' |
| 32 WEB_MODULE_IDL_ATTRIBUTE = 'WebModuleAPI' | 33 WEB_MODULE_IDL_ATTRIBUTE = 'WebModuleAPI' |
| 33 STRING_INCLUDE_PATH = 'wtf/text/WTFString.h' | |
| 34 | 34 |
| 35 def interface_context(idl_interface): | 35 |
| 36 builder = InterfaceContextBuilder(MODULE_PYNAME, TypeResolver()) | 36 def interface_context(idl_interface, type_resolver): |
| 37 builder = InterfaceContextBuilder(MODULE_PYNAME, type_resolver) |
| 37 builder.set_class_name(idl_interface.name) | 38 builder.set_class_name(idl_interface.name) |
| 38 builder.set_inheritance(idl_interface.parent) | 39 builder.set_inheritance(idl_interface.parent) |
| 39 | 40 |
| 40 for idl_attribute in idl_interface.attributes: | 41 for idl_attribute in idl_interface.attributes: |
| 41 builder.add_attribute(idl_attribute) | 42 builder.add_attribute(idl_attribute) |
| 42 | 43 |
| 43 for idl_operation in idl_interface.operations: | 44 for idl_operation in idl_interface.operations: |
| 44 builder.add_operation(idl_operation) | 45 builder.add_operation(idl_operation) |
| 45 | 46 |
| 46 return builder.build() | 47 return builder.build() |
| 47 | 48 |
| 48 | 49 |
| 49 class TypeResolver(object): | 50 class TypeResolver(object): |
| 50 """Resolves Web IDL types into corresponding C++ types and include paths | 51 """Resolves Web IDL types into corresponding C++ types and include paths |
| 51 to the generated and existing files.""" | 52 to the generated and existing files.""" |
| 52 | 53 |
| 53 def includes_from_interface(self, base_type): | 54 def __init__(self, interfaces_info): |
| 54 # TODO(dglazkov): Are there any exceptional conditions here? | 55 self.interfaces_info = interfaces_info |
| 55 return set([base_type]) | 56 |
| 57 def includes_from_interface(self, interface_name): |
| 58 interface_info = self.interfaces_info.get(interface_name) |
| 59 if interface_info is None: |
| 60 raise KeyError('Unknown interface "%s".' % interface_name) |
| 61 return set([interface_info['include_path']]) |
| 56 | 62 |
| 57 def _includes_from_type(self, idl_type): | 63 def _includes_from_type(self, idl_type): |
| 58 if idl_type.is_void: | 64 if idl_type.is_void: |
| 59 return set() | 65 return set() |
| 60 if idl_type.is_primitive_type: | 66 if idl_type.is_primitive_type: |
| 61 return set() | 67 return set() |
| 62 if idl_type.is_string_type: | 68 if idl_type.is_string_type: |
| 63 return set([STRING_INCLUDE_PATH]) | 69 return set([STRING_INCLUDE_PATH]) |
| 64 | 70 |
| 65 # TODO(dglazkov): Handle complex/weird types. | 71 # TODO(dglazkov): Handle complex/weird types. |
| 66 # TODO(dglazkov): Make these proper paths to generated and non-generated | 72 return self.includes_from_interface(idl_type.base_type) |
| 67 # files. | |
| 68 return set([idl_type.base_type]) | |
| 69 | 73 |
| 70 def includes_from_definition(self, idl_definition): | 74 def includes_from_definition(self, idl_definition): |
| 71 return self._includes_from_type(idl_definition.idl_type) | 75 return self._includes_from_type(idl_definition.idl_type) |
| 72 | 76 |
| 73 def type_from_definition(self, idl_definition): | 77 def type_from_definition(self, idl_definition): |
| 74 # TODO(dglazkov): The output of this method must be a reasonable C++ | 78 # TODO(dglazkov): The output of this method must be a reasonable C++ |
| 75 # type that can be used directly in the jinja2 template. | 79 # type that can be used directly in the jinja2 template. |
| 76 return idl_definition.idl_type.base_type | 80 return idl_definition.idl_type.base_type |
| 77 | 81 |
| 82 def base_class_includes(self): |
| 83 return set(['platform/heap/Handle.h']) |
| 84 |
| 78 | 85 |
| 79 class InterfaceContextBuilder(object): | 86 class InterfaceContextBuilder(object): |
| 80 def __init__(self, code_generator, type_resolver): | 87 def __init__(self, code_generator, type_resolver): |
| 81 self.result = {'code_generator': code_generator} | 88 self.result = {'code_generator': code_generator} |
| 82 self.type_resolver = type_resolver | 89 self.type_resolver = type_resolver |
| 83 | 90 |
| 84 def set_class_name(self, class_name): | 91 def set_class_name(self, class_name): |
| 85 converter = NameStyleConverter(class_name) | 92 converter = NameStyleConverter(class_name) |
| 86 self.result['class_name'] = converter.to_all_cases() | 93 self.result['class_name'] = converter.to_all_cases() |
| 94 self._ensure_set('cpp_includes').update( |
| 95 self.type_resolver.includes_from_interface(class_name)) |
| 87 | 96 |
| 88 def set_inheritance(self, base_interface): | 97 def set_inheritance(self, base_interface): |
| 89 if base_interface is None: | 98 if base_interface is None: |
| 99 self._ensure_set('header_includes').update( |
| 100 self.type_resolver.base_class_includes()) |
| 90 return | 101 return |
| 91 self.result['inherits_expression'] = ' : public %s' % base_interface | 102 self.result['base_class'] = base_interface |
| 92 self._ensure_set('cpp_includes').update( | 103 self._ensure_set('header_includes').update( |
| 93 self.type_resolver.includes_from_interface(base_interface)) | 104 self.type_resolver.includes_from_interface(base_interface)) |
| 94 | 105 |
| 95 def _ensure_set(self, name): | 106 def _ensure_set(self, name): |
| 96 return self.result.setdefault(name, set()) | 107 return self.result.setdefault(name, set()) |
| 97 | 108 |
| 98 def _ensure_list(self, name): | 109 def _ensure_list(self, name): |
| 99 return self.result.setdefault(name, []) | 110 return self.result.setdefault(name, []) |
| 100 | 111 |
| 101 def add_attribute(self, idl_attribute): | 112 def add_attribute(self, idl_attribute): |
| 102 self._ensure_list('attributes').append( | 113 self._ensure_list('attributes').append( |
| (...skipping 26 matching lines...) Expand all Loading... |
| 129 } | 140 } |
| 130 | 141 |
| 131 def build(self): | 142 def build(self): |
| 132 return self.result | 143 return self.result |
| 133 | 144 |
| 134 | 145 |
| 135 class CodeGeneratorWebModule(CodeGeneratorBase): | 146 class CodeGeneratorWebModule(CodeGeneratorBase): |
| 136 def __init__(self, info_provider, cache_dir, output_dir): | 147 def __init__(self, info_provider, cache_dir, output_dir): |
| 137 CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider, | 148 CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider, |
| 138 cache_dir, output_dir) | 149 cache_dir, output_dir) |
| 150 self.type_resolver = TypeResolver(info_provider.interfaces_info) |
| 139 self.typedef_resolver = TypedefResolver(info_provider) | 151 self.typedef_resolver = TypedefResolver(info_provider) |
| 140 | 152 |
| 141 def get_template(self, file_extension): | 153 def get_template(self, file_extension): |
| 142 template_filename = 'web_module_interface.%s.tmpl' % file_extension | 154 template_filename = 'web_module_interface.%s.tmpl' % file_extension |
| 143 return self.jinja_env.get_template(template_filename) | 155 return self.jinja_env.get_template(template_filename) |
| 144 | 156 |
| 145 def generate_file(self, template_context, file_extension): | 157 def generate_file(self, template_context, file_extension): |
| 146 template = self.get_template(file_extension) | 158 template = self.get_template(file_extension) |
| 147 path = posixpath.join( | 159 path = posixpath.join( |
| 148 self.output_dir, | 160 self.output_dir, |
| 149 '%s.%s' % (template_context['class_name']['snake_case'], | 161 '%s.%s' % (template_context['class_name']['snake_case'], |
| 150 file_extension)) | 162 file_extension)) |
| 151 text = render_template(template, template_context) | 163 text = render_template(template, template_context) |
| 152 return (path, text) | 164 return (path, text) |
| 153 | 165 |
| 154 def generate_interface_code(self, interface): | 166 def generate_interface_code(self, interface): |
| 155 # TODO(dglazkov): Implement callback interfaces. | 167 # TODO(dglazkov): Implement callback interfaces. |
| 156 # TODO(dglazkov): Make sure partial interfaces are handled. | 168 # TODO(dglazkov): Make sure partial interfaces are handled. |
| 157 if interface.is_callback or interface.is_partial: | 169 if interface.is_callback or interface.is_partial: |
| 158 raise ValueError('Partial or callback interfaces are not supported') | 170 raise ValueError('Partial or callback interfaces are not supported') |
| 159 | 171 |
| 160 template_context = interface_context(interface) | 172 template_context = interface_context(interface, self.type_resolver) |
| 161 | 173 |
| 162 return ( | 174 return ( |
| 163 self.generate_file(template_context, 'h'), | 175 self.generate_file(template_context, 'h'), |
| 164 self.generate_file(template_context, 'cc') | 176 self.generate_file(template_context, 'cc') |
| 165 ) | 177 ) |
| 166 | 178 |
| 167 def generate_code(self, definitions, definition_name): | 179 def generate_code(self, definitions, definition_name): |
| 168 self.typedef_resolver.resolve(definitions, definition_name) | 180 self.typedef_resolver.resolve(definitions, definition_name) |
| 169 | 181 |
| 170 # TODO(dglazkov): Implement dictionaries | 182 # TODO(dglazkov): Implement dictionaries |
| 171 if definition_name not in definitions.interfaces: | 183 if definition_name not in definitions.interfaces: |
| 172 return None | 184 return None |
| 173 | 185 |
| 174 interface = definitions.interfaces[definition_name] | 186 interface = definitions.interfaces[definition_name] |
| 175 if WEB_MODULE_IDL_ATTRIBUTE not in interface.extended_attributes: | 187 if WEB_MODULE_IDL_ATTRIBUTE not in interface.extended_attributes: |
| 176 return None | 188 return None |
| 177 | 189 |
| 178 return self.generate_interface_code(interface) | 190 return self.generate_interface_code(interface) |
| OLD | NEW |