Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (C) 2013 Google Inc. All rights reserved. | 1 # Copyright (C) 2013 Google Inc. All rights reserved. |
| 2 # | 2 # |
| 3 # Redistribution and use in source and binary forms, with or without | 3 # Redistribution and use in source and binary forms, with or without |
| 4 # modification, are permitted provided that the following conditions are | 4 # modification, are permitted provided that the following conditions are |
| 5 # met: | 5 # met: |
| 6 # | 6 # |
| 7 # * Redistributions of source code must retain the above copyright | 7 # * Redistributions of source code must retain the above copyright |
| 8 # notice, this list of conditions and the following disclaimer. | 8 # notice, this list of conditions and the following disclaimer. |
| 9 # * Redistributions in binary form must reproduce the above | 9 # * Redistributions in binary form must reproduce the above |
| 10 # copyright notice, this list of conditions and the following disclaimer | 10 # copyright notice, this list of conditions and the following disclaimer |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 28 | 28 |
| 29 """Generate Blink V8 bindings (.h and .cpp files). | 29 """Generate Blink V8 bindings (.h and .cpp files). |
| 30 | 30 |
| 31 Input: An object of class IdlDefinitions, containing an IDL interface X | 31 Input: An object of class IdlDefinitions, containing an IDL interface X |
| 32 Output: V8X.h and V8X.cpp | 32 Output: V8X.h and V8X.cpp |
| 33 | |
| 34 FIXME: Currently a stub, as part of landing the parser and code generator | |
| 35 incrementally. Only implements generation of dummy .cpp and .h files. | |
| 36 """ | 33 """ |
| 37 | 34 |
| 38 import os.path | 35 import os |
| 36 import posixpath | |
| 37 import re | |
| 38 import sys | |
| 39 | |
| 40 import idl_definitions | |
| 41 | |
| 42 # jinja2 is in chromium's third_party directory. | |
| 43 module_path, module_name = os.path.split(__file__) | |
| 44 third_party = os.path.join(module_path, os.pardir, os.pardir, os.pardir, os.pard ir) | |
| 45 sys.path.append(third_party) | |
| 46 import jinja2 | |
| 47 | |
| 48 | |
| 49 def apply_template(path_to_template, contents): | |
| 50 dirname, basename = os.path.split(path_to_template) | |
| 51 jinja_env = jinja2.Environment(trim_blocks=True, loader=jinja2.FileSystemLoa der([dirname])) | |
| 52 template = jinja_env.get_template(basename) | |
| 53 return template.render(contents) | |
| 54 | |
| 55 | |
| 56 def v8_class_name(interface): | |
| 57 return 'V8' + interface.name | |
| 58 | |
| 59 | |
| 60 def cpp_type(data_type): | |
| 61 """Returns the cpp type corresponding to the IDL type.""" | |
| 62 if data_type == 'boolean': | |
| 63 return 'bool' | |
| 64 raise Exception('Not supported') | |
| 65 | |
| 66 | |
| 67 def callback_argument_declaration(operation): | |
| 68 arguments = ['%s %s' % (cpp_type(argument.data_type), argument.name) for arg ument in operation.arguments] | |
| 69 return ', '.join(arguments) | |
| 70 | |
| 71 | |
| 72 class CodeGeneratorV8: | |
| 73 def __init__(self, definitions, interface_name, output_directory, idl_direct ories, verbose=False): | |
| 74 if interface_name not in definitions.interfaces: | |
| 75 raise Exception('%s not in IDL definitions' % interface_name) | |
| 76 self.idl_definitions = definitions | |
| 77 self.interface_name = interface_name | |
| 78 self.idl_directories = idl_directories | |
| 79 self.output_directory = output_directory | |
| 80 self.verbose = verbose | |
| 81 self.interface = self.idl_definitions.interfaces[self.interface_name] | |
| 82 | |
| 83 def cpp_class_header_filename(self): | |
| 84 """Returns relative path from bindings/ of webcore header of the interfa ce""" | |
| 85 # FIXME: parser will prepare posix form relative path from Source/bindin gs in IdlInterface.file_name | |
| 86 idl_filename = self.idl_definitions.file_name | |
| 87 idl_rel_path_local = os.path.relpath(idl_filename) | |
| 88 idl_rel_path_posix = idl_rel_path_local.replace(os.path.sep, posixpath.s ep) | |
| 89 | |
| 90 idl_dir_posix = posixpath.join('bindings', posixpath.dirname(idl_rel_pat h_posix)) | |
| 91 return posixpath.join(idl_dir_posix, self.interface.name + '.h') | |
| 92 | |
| 93 def generate_header_and_cpp(self): | |
| 94 if self.interface.is_callback: | |
| 95 template_contents = {} | |
| 96 template_contents.update(self.generate_callback_interface()) | |
| 97 header_file_text = apply_template('templates/callback.h', template_c ontents) | |
| 98 cpp_file_text = apply_template('templates/callback.cpp', template_co ntents) | |
| 99 else: | |
| 100 # FIXME: Implement. | |
| 101 header_file_text = "" | |
| 102 cpp_file_text = "" | |
| 103 self.write_generated_code(header_file_text, cpp_file_text) | |
| 104 | |
| 105 def write_generated_code(self, header_file_text, cpp_file_text): | |
| 106 header_filename = os.path.join(self.output_directory, v8_class_name(self .interface) + '.h') | |
| 107 with open(header_filename, 'w') as header_file: | |
| 108 header_file.write(header_file_text) | |
| 109 cpp_filename = os.path.join(self.output_directory, v8_class_name(self.in terface) + '.cpp') | |
| 110 with open(cpp_filename, 'w') as cpp_file: | |
| 111 cpp_file.write(cpp_file_text) | |
| 112 | |
| 113 def generate_callback_interface(self): | |
| 114 methods = [] | |
| 115 cpp_includes = set([ | |
| 116 'core/dom/ScriptExecutionContext.h', | |
| 117 'bindings/v8/V8Binding.h', | |
| 118 'bindings/v8/V8Callback.h', | |
| 119 'wtf/Assertions.h', | |
| 120 ]) | |
| 121 header_includes = set([ | |
| 122 'bindings/v8/ActiveDOMCallback.h', | |
| 123 'bindings/v8/DOMWrapperWorld.h', | |
| 124 'bindings/v8/ScopedPersistent.h', | |
| 125 ]) | |
| 126 header_includes.add(self.cpp_class_header_filename()) | |
| 127 for operation in self.interface.operations: | |
| 128 method = {} | |
| 129 if 'Custom' not in operation.extended_attributes: | |
| 130 if operation.data_type != 'boolean': | |
| 131 raise Exception("We don't yet support callbacks that return non-boolean values.") | |
| 132 if len(operation.arguments): | |
| 133 raise Exception('Not supported') | |
| 134 method = { | |
|
haraken
2013/07/26 10:15:48
You might want to set 'method.arguments': []
| |
| 135 'return_type': cpp_type(operation.data_type), | |
| 136 'name': operation.name, | |
| 137 'parameter_declaration': callback_argument_declaration(opera tion), | |
|
haraken
2013/07/26 10:15:48
parameter_declaration => argument_declaration
| |
| 138 'custom': None, | |
| 139 } | |
| 140 methods.append(method) | |
| 141 template_contents = { | |
| 142 'cpp_class_name': self.interface.name, | |
| 143 'v8_class_name': v8_class_name(self.interface), | |
| 144 'cpp_includes': sorted(list(cpp_includes)), | |
| 145 'header_includes': sorted(list(header_includes)), | |
| 146 'methods': methods, | |
| 147 } | |
| 148 return template_contents | |
| 39 | 149 |
| 40 | 150 |
| 41 def generate_dummy_header_and_cpp(target_interface_name, output_directory): | 151 def generate_dummy_header_and_cpp(target_interface_name, output_directory): |
|
haraken
2013/07/26 10:15:48
You can put this method inside the CodeGeneratorV8
| |
| 42 header_basename = 'V8%s.h' % target_interface_name | 152 header_basename = 'V8%s.h' % target_interface_name |
| 43 cpp_basename = 'V8%s.cpp' % target_interface_name | 153 cpp_basename = 'V8%s.cpp' % target_interface_name |
| 44 header_fullname = os.path.join(output_directory, header_basename) | 154 header_fullname = os.path.join(output_directory, header_basename) |
| 45 cpp_fullname = os.path.join(output_directory, cpp_basename) | 155 cpp_fullname = os.path.join(output_directory, cpp_basename) |
| 46 contents = """/* | 156 contents = """/* |
| 47 This file is generated just to tell build scripts that {header_basename} and | 157 This file is generated just to tell build scripts that {header_basename} and |
| 48 {cpp_basename} are created for {target_interface_name}.idl, and thus | 158 {cpp_basename} are created for {target_interface_name}.idl, and thus |
| 49 prevent the build scripts from trying to generate {header_basename} and | 159 prevent the build scripts from trying to generate {header_basename} and |
| 50 {cpp_basename} at every build. This file must not be tried to compile. | 160 {cpp_basename} at every build. This file must not be tried to compile. |
| 51 */ | 161 */ |
| 52 """.format(**locals()) | 162 """.format(**locals()) |
| 53 with open(header_fullname, 'w') as header_file: | 163 with open(header_fullname, 'w') as header_file: |
| 54 header_file.write(contents) | 164 header_file.write(contents) |
| 55 with open(cpp_fullname, 'w') as cpp_file: | 165 with open(cpp_fullname, 'w') as cpp_file: |
| 56 cpp_file.write(contents) | 166 cpp_file.write(contents) |
| OLD | NEW |