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 Web Agent API bindings. | 7 """Generates Web Agent API bindings. |
8 | 8 |
9 The Web Agent API bindings provide a stable, IDL-generated interface for the | 9 The Web Agent API bindings provide a stable, IDL-generated interface for the |
10 Web Agents. | 10 Web Agents. |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
76 | 76 |
77 def type_from_definition(self, idl_definition): | 77 def type_from_definition(self, idl_definition): |
78 # 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++ |
79 # type that can be used directly in the jinja2 template. | 79 # type that can be used directly in the jinja2 template. |
80 return idl_definition.idl_type.base_type | 80 return idl_definition.idl_type.base_type |
81 | 81 |
82 def base_class_includes(self): | 82 def base_class_includes(self): |
83 return set(['platform/heap/Handle.h']) | 83 return set(['platform/heap/Handle.h']) |
84 | 84 |
85 | 85 |
86 class MethodOverloadSplitter(object): | |
87 """Because of union and optional types being used as arguments, some | |
88 operations may result in more than one generated method. This class | |
89 contains the logic for spliting an operation into multiple C++ overloads. | |
90 """ | |
91 | |
92 def __init__(self, idl_operation): | |
93 self.idl_operation = idl_operation | |
94 | |
95 def _update_argument_lists(self, argument_lists, idl_types): | |
96 """Given a list of IdlTypes and an existing list of argument lists (yes, | |
97 this is a list of lists), produces a next generation of the list of | |
98 lists. This is the where the actual splitting into overloads happens. | |
haraken
2017/03/18 16:30:17
the place where
dglazkov
2017/03/20 03:25:33
Fixed. Thanks! :)
| |
99 """ | |
100 result = [] | |
101 for argument_list in argument_lists: | |
102 for idl_type in idl_types: | |
103 new_argument_list = list(argument_list) | |
104 if idl_type is not None: | |
105 new_argument_list.append(idl_type) | |
106 result.append(new_argument_list) | |
107 return result | |
108 | |
109 def _enumerate_argument_types(self, idl_argument): | |
110 """Given an IdlArgument, returns a list of types that are included | |
111 in this argument. If optional, the list will include a 'None'.""" | |
112 argument_type = idl_argument.idl_type | |
113 # TODO(dglazkov): What should we do with primitive nullable args? | |
114 if (argument_type.is_nullable and | |
115 argument_type.inner_type.is_primitive_type): | |
116 raise ValueError('Primitive nullable types are not supported.') | |
117 | |
118 idl_types = [] | |
119 if idl_argument.is_optional: | |
120 idl_types.append(None) # None is used to convey optionality. | |
121 if argument_type.is_union_type: | |
122 idl_types = idl_types + argument_type.member_types | |
123 else: | |
124 idl_types.append(argument_type) | |
125 return idl_types | |
126 | |
127 def split_into_overloads(self): | |
haraken
2017/03/18 16:30:17
It would be helpful to describe a concrete example
dglazkov
2017/03/20 03:25:33
Sure thing! I added an explanation with an example
| |
128 argument_lists = [[]] | |
129 for idl_argument in self.idl_operation.arguments: | |
130 idl_types = self._enumerate_argument_types(idl_argument) | |
131 argument_lists = self._update_argument_lists(argument_lists, | |
132 idl_types) | |
133 return argument_lists | |
134 | |
135 | |
86 class InterfaceContextBuilder(object): | 136 class InterfaceContextBuilder(object): |
87 def __init__(self, code_generator, type_resolver): | 137 def __init__(self, code_generator, type_resolver): |
88 self.result = {'code_generator': code_generator} | 138 self.result = {'code_generator': code_generator} |
89 self.type_resolver = type_resolver | 139 self.type_resolver = type_resolver |
90 | 140 |
91 def set_class_name(self, class_name): | 141 def set_class_name(self, class_name): |
92 converter = NameStyleConverter(class_name) | 142 converter = NameStyleConverter(class_name) |
93 self.result['class_name'] = converter.to_all_cases() | 143 self.result['class_name'] = converter.to_all_cases() |
94 self._ensure_set('cpp_includes').update( | 144 self._ensure_set('cpp_includes').update( |
95 self.type_resolver.includes_from_interface(class_name)) | 145 self.type_resolver.includes_from_interface(class_name)) |
(...skipping 15 matching lines...) Expand all Loading... | |
111 | 161 |
112 def add_attribute(self, idl_attribute): | 162 def add_attribute(self, idl_attribute): |
113 self._ensure_list('attributes').append( | 163 self._ensure_list('attributes').append( |
114 self.create_attribute(idl_attribute)) | 164 self.create_attribute(idl_attribute)) |
115 self._ensure_set('cpp_includes').update( | 165 self._ensure_set('cpp_includes').update( |
116 self.type_resolver.includes_from_definition(idl_attribute)) | 166 self.type_resolver.includes_from_definition(idl_attribute)) |
117 | 167 |
118 def add_operation(self, idl_operation): | 168 def add_operation(self, idl_operation): |
119 if not idl_operation.name: | 169 if not idl_operation.name: |
120 return | 170 return |
121 self._ensure_list('methods').append( | 171 overload_splitter = MethodOverloadSplitter(idl_operation) |
122 self.create_method(idl_operation)) | 172 overloads = overload_splitter.split_into_overloads() |
123 self._ensure_set('cpp_includes').update( | 173 argument_names = [argument.name for argument |
124 self.type_resolver.includes_from_definition(idl_operation)) | 174 in idl_operation.arguments] |
175 for argument_types in overloads: | |
176 arguments = [] | |
177 for position, argument_type in enumerate(argument_types): | |
178 arguments.append( | |
179 self.create_argument(argument_names[position], | |
180 argument_type)) | |
181 self._ensure_list('methods').append( | |
182 self.create_method(idl_operation, arguments)) | |
183 self._ensure_set('cpp_includes').update( | |
184 self.type_resolver.includes_from_definition(idl_operation)) | |
125 | 185 |
126 def create_method(self, idl_operation): | 186 def create_argument(self, argument_name, argument_type): |
127 name = idl_operation.name | 187 name_converter = NameStyleConverter(argument_name) |
188 return { | |
189 'name': name_converter.to_snake_case(), | |
190 'type': argument_type.base_type, | |
191 } | |
192 | |
193 def create_method(self, idl_operation, arguments): | |
194 name_converter = NameStyleConverter(idl_operation.name) | |
128 return_type = self.type_resolver.type_from_definition(idl_operation) | 195 return_type = self.type_resolver.type_from_definition(idl_operation) |
129 return { | 196 return { |
130 'name': name, | 197 'name': name_converter.to_upper_camel_case(), |
131 'return_type': return_type | 198 'type': return_type, |
199 'arguments': arguments | |
132 } | 200 } |
133 | 201 |
134 def create_attribute(self, idl_attribute): | 202 def create_attribute(self, idl_attribute): |
135 name = idl_attribute.name | 203 name = idl_attribute.name |
136 return_type = self.type_resolver.type_from_definition(idl_attribute) | 204 return_type = self.type_resolver.type_from_definition(idl_attribute) |
137 return { | 205 return { |
138 'name': name, | 206 'name': name, |
139 'return_type': return_type | 207 'type': return_type |
140 } | 208 } |
141 | 209 |
142 def build(self): | 210 def build(self): |
143 return self.result | 211 return self.result |
144 | 212 |
145 | 213 |
146 class CodeGeneratorWebAgentAPI(CodeGeneratorBase): | 214 class CodeGeneratorWebAgentAPI(CodeGeneratorBase): |
147 def __init__(self, info_provider, cache_dir, output_dir): | 215 def __init__(self, info_provider, cache_dir, output_dir): |
148 CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider, | 216 CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider, |
149 cache_dir, output_dir) | 217 cache_dir, output_dir) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
181 | 249 |
182 # TODO(dglazkov): Implement dictionaries | 250 # TODO(dglazkov): Implement dictionaries |
183 if definition_name not in definitions.interfaces: | 251 if definition_name not in definitions.interfaces: |
184 return None | 252 return None |
185 | 253 |
186 interface = definitions.interfaces[definition_name] | 254 interface = definitions.interfaces[definition_name] |
187 if WEB_AGENT_API_IDL_ATTRIBUTE not in interface.extended_attributes: | 255 if WEB_AGENT_API_IDL_ATTRIBUTE not in interface.extended_attributes: |
188 return None | 256 return None |
189 | 257 |
190 return self.generate_interface_code(interface) | 258 return self.generate_interface_code(interface) |
OLD | NEW |