OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # Copyright (c) 2011 Google Inc. All rights reserved. | |
3 # Copyright (c) 2012 Intel Corporation. All rights reserved. | |
4 # | |
5 # Redistribution and use in source and binary forms, with or without | |
6 # modification, are permitted provided that the following conditions are | |
7 # met: | |
8 # | |
9 # * Redistributions of source code must retain the above copyright | |
10 # notice, this list of conditions and the following disclaimer. | |
11 # * Redistributions in binary form must reproduce the above | |
12 # copyright notice, this list of conditions and the following disclaimer | |
13 # in the documentation and/or other materials provided with the | |
14 # distribution. | |
15 # * Neither the name of Google Inc. nor the names of its | |
16 # contributors may be used to endorse or promote products derived from | |
17 # this software without specific prior written permission. | |
18 # | |
19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
30 | |
31 import os.path | |
32 import sys | |
33 import string | |
34 import optparse | |
35 import re | |
36 try: | |
37 import json | |
38 except ImportError: | |
39 import simplejson as json | |
40 | |
41 import CodeGeneratorInspectorStrings | |
42 | |
43 # Manually-filled map of type name replacements. | |
44 TYPE_NAME_FIX_MAP = { | |
45 "RGBA": "Rgba", # RGBA is reported to be conflicting with a define name in
Windows CE. | |
46 "": "Empty", | |
47 } | |
48 | |
49 | |
50 TYPES_WITH_RUNTIME_CAST_SET = frozenset(["Runtime.RemoteObject", "Runtime.Proper
tyDescriptor", "Runtime.InternalPropertyDescriptor", | |
51 "Debugger.FunctionDetails", "Debugger.G
eneratorObjectDetails", "Debugger.CollectionEntry", "Debugger.CallFrame", "Debug
ger.Location"]) | |
52 | |
53 TYPES_WITH_OPEN_FIELD_LIST_SET = frozenset([ | |
54 # InspectorStyleSheet not only creat
es this property but wants to read it and modify it. | |
55 "CSS.CSSProperty", | |
56 # InspectorResourceAgent needs to up
date mime-type. | |
57 "Network.Response"]) | |
58 | |
59 cmdline_parser = optparse.OptionParser() | |
60 cmdline_parser.add_option("--output_dir") | |
61 | |
62 try: | |
63 arg_options, arg_values = cmdline_parser.parse_args() | |
64 if (len(arg_values) != 1): | |
65 raise Exception("Exactly one plain argument expected (found %s)" % len(a
rg_values)) | |
66 input_json_filename = arg_values[0] | |
67 output_dirname = arg_options.output_dir | |
68 if not output_dirname: | |
69 raise Exception("Output directory must be specified") | |
70 except Exception: | |
71 # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html | |
72 exc = sys.exc_info()[1] | |
73 sys.stderr.write("Failed to parse command-line arguments: %s\n\n" % exc) | |
74 sys.stderr.write("Usage: <script> --output_dir <output_dir> protocol.json\n"
) | |
75 exit(1) | |
76 | |
77 | |
78 # FIXME: move this methods under Capitalizer class below and remove duplications
. | |
79 def dash_to_camelcase(word): | |
80 return ''.join(x.capitalize() or '-' for x in word.split('-')) | |
81 | |
82 | |
83 def fix_camel_case(name): | |
84 refined = re.sub(r'-(\w)', lambda pat: pat.group(1).upper(), name) | |
85 refined = to_title_case(refined) | |
86 return re.sub(r'(?i)HTML|XML|WML|API', lambda pat: pat.group(0).upper(), ref
ined) | |
87 | |
88 | |
89 def to_title_case(name): | |
90 return name[:1].upper() + name[1:] | |
91 | |
92 | |
93 class Capitalizer: | |
94 @staticmethod | |
95 def lower_camel_case_to_upper(str): | |
96 if len(str) > 0 and str[0].islower(): | |
97 str = str[0].upper() + str[1:] | |
98 return str | |
99 | |
100 @staticmethod | |
101 def upper_camel_case_to_lower(str): | |
102 pos = 0 | |
103 while pos < len(str) and str[pos].isupper(): | |
104 pos += 1 | |
105 if pos == 0: | |
106 return str | |
107 if pos == 1: | |
108 return str[0].lower() + str[1:] | |
109 if pos < len(str): | |
110 pos -= 1 | |
111 possible_abbreviation = str[0:pos] | |
112 if possible_abbreviation not in Capitalizer.ABBREVIATION: | |
113 raise Exception("Unknown abbreviation %s" % possible_abbreviation) | |
114 str = possible_abbreviation.lower() + str[pos:] | |
115 return str | |
116 | |
117 ABBREVIATION = frozenset(["XHR", "DOM", "CSS"]) | |
118 | |
119 VALIDATOR_IFDEF_NAME = "ENABLE(ASSERT)" | |
120 | |
121 | |
122 class DomainNameFixes: | |
123 @staticmethod | |
124 def get_fixed_data(domain_name): | |
125 return Capitalizer.upper_camel_case_to_lower(domain_name) + "Agent" | |
126 | |
127 class RawTypes(object): | |
128 @staticmethod | |
129 def get(json_type): | |
130 if json_type == "boolean": | |
131 return RawTypes.Bool | |
132 elif json_type == "string": | |
133 return RawTypes.String | |
134 elif json_type == "array": | |
135 return RawTypes.Array | |
136 elif json_type == "object": | |
137 return RawTypes.Object | |
138 elif json_type == "integer": | |
139 return RawTypes.Int | |
140 elif json_type == "number": | |
141 return RawTypes.Number | |
142 elif json_type == "any": | |
143 return RawTypes.Any | |
144 else: | |
145 raise Exception("Unknown type: %s" % json_type) | |
146 | |
147 class BaseType(object): | |
148 @classmethod | |
149 def get_raw_validator_call_text(cls): | |
150 return "RuntimeCastHelper::assertType<JSONValue::Type%s>" % cls.get_
getter_name() | |
151 | |
152 @staticmethod | |
153 def get_getter_name(): | |
154 raise Exception("Unsupported") | |
155 | |
156 class String(BaseType): | |
157 @staticmethod | |
158 def get_getter_name(): | |
159 return "String" | |
160 | |
161 get_setter_name = get_getter_name | |
162 | |
163 @staticmethod | |
164 def get_constructor_pattern(): | |
165 return "InspectorString::create(%s)" | |
166 | |
167 @staticmethod | |
168 def is_heavy_value(): | |
169 return True | |
170 | |
171 @staticmethod | |
172 def get_array_item_raw_c_type_text(): | |
173 return "String" | |
174 | |
175 @staticmethod | |
176 def get_raw_type_model(): | |
177 return TypeModel.String | |
178 | |
179 class Int(BaseType): | |
180 @staticmethod | |
181 def get_getter_name(): | |
182 return "Int" | |
183 | |
184 @staticmethod | |
185 def get_setter_name(): | |
186 return "Number" | |
187 | |
188 @staticmethod | |
189 def get_constructor_pattern(): | |
190 return "InspectorBasicValue::create(%s)" | |
191 | |
192 @classmethod | |
193 def get_raw_validator_call_text(cls): | |
194 return "RuntimeCastHelper::assertInt" | |
195 | |
196 @staticmethod | |
197 def is_heavy_value(): | |
198 return False | |
199 | |
200 @staticmethod | |
201 def get_array_item_raw_c_type_text(): | |
202 return "int" | |
203 | |
204 @staticmethod | |
205 def get_raw_type_model(): | |
206 return TypeModel.Int | |
207 | |
208 class Number(BaseType): | |
209 @staticmethod | |
210 def get_getter_name(): | |
211 return "Double" | |
212 | |
213 @staticmethod | |
214 def get_setter_name(): | |
215 return "Number" | |
216 | |
217 @staticmethod | |
218 def get_constructor_pattern(): | |
219 return "InspectorBasicValue::create(%s)" | |
220 | |
221 @staticmethod | |
222 def get_raw_validator_call_text(): | |
223 return "RuntimeCastHelper::assertType<JSONValue::TypeNumber>" | |
224 | |
225 @staticmethod | |
226 def is_heavy_value(): | |
227 return False | |
228 | |
229 @staticmethod | |
230 def get_array_item_raw_c_type_text(): | |
231 return "double" | |
232 | |
233 @staticmethod | |
234 def get_raw_type_model(): | |
235 return TypeModel.Number | |
236 | |
237 class Bool(BaseType): | |
238 @staticmethod | |
239 def get_getter_name(): | |
240 return "Boolean" | |
241 | |
242 get_setter_name = get_getter_name | |
243 | |
244 @staticmethod | |
245 def get_constructor_pattern(): | |
246 return "InspectorBasicValue::create(%s)" | |
247 | |
248 @staticmethod | |
249 def is_heavy_value(): | |
250 return False | |
251 | |
252 @staticmethod | |
253 def get_array_item_raw_c_type_text(): | |
254 return "bool" | |
255 | |
256 @staticmethod | |
257 def get_raw_type_model(): | |
258 return TypeModel.Bool | |
259 | |
260 class Object(BaseType): | |
261 @staticmethod | |
262 def get_getter_name(): | |
263 return "Object" | |
264 | |
265 @staticmethod | |
266 def get_setter_name(): | |
267 return "Value" | |
268 | |
269 @staticmethod | |
270 def get_constructor_pattern(): | |
271 return "%s" | |
272 | |
273 @staticmethod | |
274 def get_output_argument_prefix(): | |
275 return "" | |
276 | |
277 @staticmethod | |
278 def is_heavy_value(): | |
279 return True | |
280 | |
281 @staticmethod | |
282 def get_array_item_raw_c_type_text(): | |
283 return "JSONObject" | |
284 | |
285 @staticmethod | |
286 def get_raw_type_model(): | |
287 return TypeModel.Object | |
288 | |
289 class Any(BaseType): | |
290 @staticmethod | |
291 def get_getter_name(): | |
292 return "Value" | |
293 | |
294 get_setter_name = get_getter_name | |
295 | |
296 @staticmethod | |
297 def get_constructor_pattern(): | |
298 raise Exception("Unsupported") | |
299 | |
300 @staticmethod | |
301 def get_raw_validator_call_text(): | |
302 return "RuntimeCastHelper::assertAny" | |
303 | |
304 @staticmethod | |
305 def is_heavy_value(): | |
306 return True | |
307 | |
308 @staticmethod | |
309 def get_array_item_raw_c_type_text(): | |
310 return "JSONValue" | |
311 | |
312 @staticmethod | |
313 def get_raw_type_model(): | |
314 return TypeModel.Any | |
315 | |
316 class Array(BaseType): | |
317 @staticmethod | |
318 def get_getter_name(): | |
319 return "Array" | |
320 | |
321 @staticmethod | |
322 def get_setter_name(): | |
323 return "Value" | |
324 | |
325 @staticmethod | |
326 def get_constructor_pattern(): | |
327 return "%s" | |
328 | |
329 @staticmethod | |
330 def get_output_argument_prefix(): | |
331 return "" | |
332 | |
333 @staticmethod | |
334 def is_heavy_value(): | |
335 return True | |
336 | |
337 @staticmethod | |
338 def get_array_item_raw_c_type_text(): | |
339 return "JSONArray" | |
340 | |
341 @staticmethod | |
342 def get_raw_type_model(): | |
343 return TypeModel.Array | |
344 | |
345 | |
346 def replace_right_shift(input_str): | |
347 return input_str.replace(">>", "> >") | |
348 | |
349 | |
350 class CommandReturnPassModel: | |
351 class ByReference: | |
352 def __init__(self, var_type, set_condition): | |
353 self.var_type = var_type | |
354 self.set_condition = set_condition | |
355 | |
356 def get_return_var_type(self): | |
357 return self.var_type | |
358 | |
359 @staticmethod | |
360 def get_output_argument_prefix(): | |
361 return "" | |
362 | |
363 @staticmethod | |
364 def get_output_to_raw_expression(): | |
365 return "%s" | |
366 | |
367 def get_output_parameter_type(self): | |
368 return self.var_type + "&" | |
369 | |
370 def get_set_return_condition(self): | |
371 return self.set_condition | |
372 | |
373 class ByPointer: | |
374 def __init__(self, var_type): | |
375 self.var_type = var_type | |
376 | |
377 def get_return_var_type(self): | |
378 return self.var_type | |
379 | |
380 @staticmethod | |
381 def get_output_argument_prefix(): | |
382 return "&" | |
383 | |
384 @staticmethod | |
385 def get_output_to_raw_expression(): | |
386 return "%s" | |
387 | |
388 def get_output_parameter_type(self): | |
389 return self.var_type + "*" | |
390 | |
391 @staticmethod | |
392 def get_set_return_condition(): | |
393 return None | |
394 | |
395 class OptOutput: | |
396 def __init__(self, var_type): | |
397 self.var_type = var_type | |
398 | |
399 def get_return_var_type(self): | |
400 return "TypeBuilder::OptOutput<%s>" % self.var_type | |
401 | |
402 @staticmethod | |
403 def get_output_argument_prefix(): | |
404 return "&" | |
405 | |
406 @staticmethod | |
407 def get_output_to_raw_expression(): | |
408 return "%s.getValue()" | |
409 | |
410 def get_output_parameter_type(self): | |
411 return "TypeBuilder::OptOutput<%s>*" % self.var_type | |
412 | |
413 @staticmethod | |
414 def get_set_return_condition(): | |
415 return "%s.isAssigned()" | |
416 | |
417 | |
418 class TypeModel: | |
419 class RefPtrBased(object): | |
420 def __init__(self, class_name): | |
421 self.class_name = class_name | |
422 self.optional = False | |
423 | |
424 def get_optional(self): | |
425 result = TypeModel.RefPtrBased(self.class_name) | |
426 result.optional = True | |
427 return result | |
428 | |
429 def get_command_return_pass_model(self): | |
430 if self.optional: | |
431 set_condition = "%s" | |
432 else: | |
433 set_condition = None | |
434 return CommandReturnPassModel.ByReference(replace_right_shift("RefPt
r<%s>" % self.class_name), set_condition) | |
435 | |
436 def get_input_param_type_text(self): | |
437 return replace_right_shift("PassRefPtr<%s>" % self.class_name) | |
438 | |
439 @staticmethod | |
440 def get_event_setter_expression_pattern(): | |
441 return "%s" | |
442 | |
443 class Enum(object): | |
444 def __init__(self, base_type_name): | |
445 self.type_name = base_type_name + "::Enum" | |
446 | |
447 def get_optional(base_self): | |
448 class EnumOptional: | |
449 @classmethod | |
450 def get_optional(cls): | |
451 return cls | |
452 | |
453 @staticmethod | |
454 def get_command_return_pass_model(): | |
455 return CommandReturnPassModel.OptOutput(base_self.type_name) | |
456 | |
457 @staticmethod | |
458 def get_input_param_type_text(): | |
459 return base_self.type_name + "*" | |
460 | |
461 @staticmethod | |
462 def get_event_setter_expression_pattern(): | |
463 raise Exception("TODO") | |
464 return EnumOptional | |
465 | |
466 def get_command_return_pass_model(self): | |
467 return CommandReturnPassModel.ByPointer(self.type_name) | |
468 | |
469 def get_input_param_type_text(self): | |
470 return self.type_name | |
471 | |
472 @staticmethod | |
473 def get_event_setter_expression_pattern(): | |
474 return "%s" | |
475 | |
476 class ValueType(object): | |
477 def __init__(self, type_name, is_heavy): | |
478 self.type_name = type_name | |
479 self.is_heavy = is_heavy | |
480 | |
481 def get_optional(self): | |
482 return self.ValueOptional(self) | |
483 | |
484 def get_command_return_pass_model(self): | |
485 return CommandReturnPassModel.ByPointer(self.type_name) | |
486 | |
487 def get_input_param_type_text(self): | |
488 if self.is_heavy: | |
489 return "const %s&" % self.type_name | |
490 else: | |
491 return self.type_name | |
492 | |
493 def get_opt_output_type_(self): | |
494 return self.type_name | |
495 | |
496 @staticmethod | |
497 def get_event_setter_expression_pattern(): | |
498 return "%s" | |
499 | |
500 class ValueOptional: | |
501 def __init__(self, base): | |
502 self.base = base | |
503 | |
504 def get_optional(self): | |
505 return self | |
506 | |
507 def get_command_return_pass_model(self): | |
508 return CommandReturnPassModel.OptOutput(self.base.get_opt_output
_type_()) | |
509 | |
510 def get_input_param_type_text(self): | |
511 return "const %s* const" % self.base.type_name | |
512 | |
513 @staticmethod | |
514 def get_event_setter_expression_pattern(): | |
515 return "*%s" | |
516 | |
517 @classmethod | |
518 def init_class(cls): | |
519 cls.Bool = cls.ValueType("bool", False) | |
520 cls.Int = cls.ValueType("int", False) | |
521 cls.Number = cls.ValueType("double", False) | |
522 cls.String = cls.ValueType("String", True,) | |
523 cls.Object = cls.RefPtrBased("JSONObject") | |
524 cls.Array = cls.RefPtrBased("JSONArray") | |
525 cls.Any = cls.RefPtrBased("JSONValue") | |
526 | |
527 TypeModel.init_class() | |
528 | |
529 | |
530 # Collection of JSONObject class methods that are likely to be overloaded in gen
erated class. | |
531 # We must explicitly import all overloaded methods or they won't be available to
user. | |
532 INSPECTOR_OBJECT_SETTER_NAMES = frozenset(["setValue", "setBoolean", "setNumber"
, "setString", "setValue", "setObject", "setArray"]) | |
533 | |
534 | |
535 def fix_type_name(json_name): | |
536 if json_name in TYPE_NAME_FIX_MAP: | |
537 fixed = TYPE_NAME_FIX_MAP[json_name] | |
538 | |
539 class Result(object): | |
540 class_name = fixed | |
541 | |
542 @staticmethod | |
543 def output_comment(writer): | |
544 writer.newline("// Type originally was named '%s'.\n" % json_nam
e) | |
545 else: | |
546 | |
547 class Result(object): | |
548 class_name = json_name | |
549 | |
550 @staticmethod | |
551 def output_comment(writer): | |
552 pass | |
553 | |
554 return Result | |
555 | |
556 | |
557 class Writer: | |
558 def __init__(self, output, indent): | |
559 self.output = output | |
560 self.indent = indent | |
561 | |
562 def newline(self, str): | |
563 if (self.indent): | |
564 self.output.append(self.indent) | |
565 self.output.append(str) | |
566 | |
567 def append(self, str): | |
568 self.output.append(str) | |
569 | |
570 def newline_multiline(self, str): | |
571 parts = str.split('\n') | |
572 self.newline(parts[0]) | |
573 for p in parts[1:]: | |
574 self.output.append('\n') | |
575 if p: | |
576 self.newline(p) | |
577 | |
578 def append_multiline(self, str): | |
579 parts = str.split('\n') | |
580 self.append(parts[0]) | |
581 for p in parts[1:]: | |
582 self.output.append('\n') | |
583 if p: | |
584 self.newline(p) | |
585 | |
586 def get_indent(self): | |
587 return self.indent | |
588 | |
589 def insert_writer(self, additional_indent): | |
590 new_output = [] | |
591 self.output.append(new_output) | |
592 return Writer(new_output, self.indent + additional_indent) | |
593 | |
594 | |
595 class EnumConstants: | |
596 map_ = {} | |
597 constants_ = [] | |
598 | |
599 @classmethod | |
600 def add_constant(cls, value): | |
601 if value in cls.map_: | |
602 return cls.map_[value] | |
603 else: | |
604 pos = len(cls.map_) | |
605 cls.map_[value] = pos | |
606 cls.constants_.append(value) | |
607 return pos | |
608 | |
609 @classmethod | |
610 def get_enum_constant_code(cls): | |
611 output = [] | |
612 for item in cls.constants_: | |
613 output.append(" \"" + item + "\"") | |
614 return ",\n".join(output) + "\n" | |
615 | |
616 | |
617 # Typebuilder code is generated in several passes: first typedefs, then other cl
asses. | |
618 # Manual pass management is needed because we cannot have forward declarations f
or typedefs. | |
619 class TypeBuilderPass: | |
620 TYPEDEF = "typedef" | |
621 MAIN = "main" | |
622 | |
623 | |
624 class TypeBindings: | |
625 @staticmethod | |
626 def create_named_type_declaration(json_typable, context_domain_name, type_da
ta): | |
627 json_type = type_data.get_json_type() | |
628 | |
629 class Helper: | |
630 is_ad_hoc = False | |
631 full_name_prefix_for_use = "TypeBuilder::" + context_domain_name + "
::" | |
632 full_name_prefix_for_impl = "TypeBuilder::" + context_domain_name +
"::" | |
633 | |
634 @staticmethod | |
635 def write_doc(writer): | |
636 if "description" in json_type: | |
637 writer.newline("/* ") | |
638 writer.append(json_type["description"]) | |
639 writer.append(" */\n") | |
640 | |
641 @staticmethod | |
642 def add_to_forward_listener(forward_listener): | |
643 forward_listener.add_type_data(type_data) | |
644 | |
645 | |
646 fixed_type_name = fix_type_name(json_type["id"]) | |
647 return TypeBindings.create_type_declaration_(json_typable, context_domai
n_name, fixed_type_name, Helper) | |
648 | |
649 @staticmethod | |
650 def create_ad_hoc_type_declaration(json_typable, context_domain_name, ad_hoc
_type_context): | |
651 class Helper: | |
652 is_ad_hoc = True | |
653 full_name_prefix_for_use = ad_hoc_type_context.container_relative_na
me_prefix | |
654 full_name_prefix_for_impl = ad_hoc_type_context.container_full_name_
prefix | |
655 | |
656 @staticmethod | |
657 def write_doc(writer): | |
658 pass | |
659 | |
660 @staticmethod | |
661 def add_to_forward_listener(forward_listener): | |
662 pass | |
663 fixed_type_name = ad_hoc_type_context.get_type_name_fix() | |
664 return TypeBindings.create_type_declaration_(json_typable, context_domai
n_name, fixed_type_name, Helper) | |
665 | |
666 @staticmethod | |
667 def create_type_declaration_(json_typable, context_domain_name, fixed_type_n
ame, helper): | |
668 if json_typable["type"] == "string": | |
669 if "enum" in json_typable: | |
670 | |
671 class EnumBinding: | |
672 need_user_runtime_cast_ = False | |
673 need_internal_runtime_cast_ = False | |
674 | |
675 @classmethod | |
676 def resolve_inner(cls, resolve_context): | |
677 pass | |
678 | |
679 @classmethod | |
680 def request_user_runtime_cast(cls, request): | |
681 if request: | |
682 cls.need_user_runtime_cast_ = True | |
683 request.acknowledge() | |
684 | |
685 @classmethod | |
686 def request_internal_runtime_cast(cls): | |
687 cls.need_internal_runtime_cast_ = True | |
688 | |
689 @classmethod | |
690 def get_code_generator(enum_binding_cls): | |
691 | |
692 class CodeGenerator: | |
693 @staticmethod | |
694 def generate_type_builder(writer, generate_context): | |
695 enum = json_typable["enum"] | |
696 helper.write_doc(writer) | |
697 enum_name = fixed_type_name.class_name | |
698 fixed_type_name.output_comment(writer) | |
699 writer.newline("struct ") | |
700 writer.append(enum_name) | |
701 writer.append(" {\n") | |
702 writer.newline(" enum Enum {\n") | |
703 for enum_item in enum: | |
704 enum_pos = EnumConstants.add_constant(enum_i
tem) | |
705 | |
706 item_c_name = enum_item.replace('-', '_') | |
707 item_c_name = Capitalizer.lower_camel_case_t
o_upper(item_c_name) | |
708 if item_c_name in TYPE_NAME_FIX_MAP: | |
709 item_c_name = TYPE_NAME_FIX_MAP[item_c_n
ame] | |
710 writer.newline(" ") | |
711 writer.append(item_c_name) | |
712 writer.append(" = ") | |
713 writer.append("%s" % enum_pos) | |
714 writer.append(",\n") | |
715 writer.newline(" };\n") | |
716 if enum_binding_cls.need_user_runtime_cast_: | |
717 raise Exception("Not yet implemented") | |
718 | |
719 if enum_binding_cls.need_internal_runtime_cast_: | |
720 writer.append("#if %s\n" % VALIDATOR_IFDEF_N
AME) | |
721 writer.newline(" static void assertCorrec
tValue(JSONValue* value);\n") | |
722 writer.append("#endif // %s\n" % VALIDATOR_
IFDEF_NAME) | |
723 | |
724 validator_writer = generate_context.validato
r_writer | |
725 | |
726 validator_writer.newline("void %s%s::assertC
orrectValue(JSONValue* value)\n" % (helper.full_name_prefix_for_impl, enum_name)
) | |
727 validator_writer.newline("{\n") | |
728 validator_writer.newline(" WTF::String s;
\n") | |
729 validator_writer.newline(" bool cast_res
= value->asString(&s);\n") | |
730 validator_writer.newline(" ASSERT(cast_re
s);\n") | |
731 if len(enum) > 0: | |
732 condition_list = [] | |
733 for enum_item in enum: | |
734 enum_pos = EnumConstants.add_constan
t(enum_item) | |
735 condition_list.append("s == \"%s\""
% enum_item) | |
736 validator_writer.newline(" ASSERT(%s)
;\n" % " || ".join(condition_list)) | |
737 validator_writer.newline("}\n") | |
738 | |
739 validator_writer.newline("\n\n") | |
740 | |
741 writer.newline("}; // struct ") | |
742 writer.append(enum_name) | |
743 writer.append("\n\n") | |
744 | |
745 @staticmethod | |
746 def register_use(forward_listener): | |
747 pass | |
748 | |
749 @staticmethod | |
750 def get_generate_pass_id(): | |
751 return TypeBuilderPass.MAIN | |
752 | |
753 return CodeGenerator | |
754 | |
755 @classmethod | |
756 def get_validator_call_text(cls): | |
757 return helper.full_name_prefix_for_use + fixed_type_name
.class_name + "::assertCorrectValue" | |
758 | |
759 @classmethod | |
760 def get_array_item_c_type_text(cls): | |
761 return helper.full_name_prefix_for_use + fixed_type_name
.class_name + "::Enum" | |
762 | |
763 @staticmethod | |
764 def get_setter_value_expression_pattern(): | |
765 return "TypeBuilder::getEnumConstantValue(%s)" | |
766 | |
767 @staticmethod | |
768 def reduce_to_raw_type(): | |
769 return RawTypes.String | |
770 | |
771 @staticmethod | |
772 def get_type_model(): | |
773 return TypeModel.Enum(helper.full_name_prefix_for_use +
fixed_type_name.class_name) | |
774 | |
775 return EnumBinding | |
776 else: | |
777 if helper.is_ad_hoc: | |
778 | |
779 class PlainString: | |
780 @classmethod | |
781 def resolve_inner(cls, resolve_context): | |
782 pass | |
783 | |
784 @staticmethod | |
785 def request_user_runtime_cast(request): | |
786 raise Exception("Unsupported") | |
787 | |
788 @staticmethod | |
789 def request_internal_runtime_cast(): | |
790 pass | |
791 | |
792 @staticmethod | |
793 def get_code_generator(): | |
794 return None | |
795 | |
796 @classmethod | |
797 def get_validator_call_text(cls): | |
798 return RawTypes.String.get_raw_validator_call_text() | |
799 | |
800 @staticmethod | |
801 def reduce_to_raw_type(): | |
802 return RawTypes.String | |
803 | |
804 @staticmethod | |
805 def get_type_model(): | |
806 return TypeModel.String | |
807 | |
808 @staticmethod | |
809 def get_setter_value_expression_pattern(): | |
810 return None | |
811 | |
812 @classmethod | |
813 def get_array_item_c_type_text(cls): | |
814 return cls.reduce_to_raw_type().get_array_item_raw_c
_type_text() | |
815 | |
816 return PlainString | |
817 | |
818 else: | |
819 | |
820 class TypedefString: | |
821 @classmethod | |
822 def resolve_inner(cls, resolve_context): | |
823 pass | |
824 | |
825 @staticmethod | |
826 def request_user_runtime_cast(request): | |
827 raise Exception("Unsupported") | |
828 | |
829 @staticmethod | |
830 def request_internal_runtime_cast(): | |
831 pass | |
832 | |
833 @staticmethod | |
834 def get_code_generator(): | |
835 class CodeGenerator: | |
836 @staticmethod | |
837 def generate_type_builder(writer, generate_conte
xt): | |
838 helper.write_doc(writer) | |
839 fixed_type_name.output_comment(writer) | |
840 writer.newline("typedef String ") | |
841 writer.append(fixed_type_name.class_name) | |
842 writer.append(";\n\n") | |
843 | |
844 @staticmethod | |
845 def register_use(forward_listener): | |
846 pass | |
847 | |
848 @staticmethod | |
849 def get_generate_pass_id(): | |
850 return TypeBuilderPass.TYPEDEF | |
851 | |
852 return CodeGenerator | |
853 | |
854 @classmethod | |
855 def get_validator_call_text(cls): | |
856 return RawTypes.String.get_raw_validator_call_text() | |
857 | |
858 @staticmethod | |
859 def reduce_to_raw_type(): | |
860 return RawTypes.String | |
861 | |
862 @staticmethod | |
863 def get_type_model(): | |
864 return TypeModel.ValueType("%s%s" % (helper.full_nam
e_prefix_for_use, fixed_type_name.class_name), True) | |
865 | |
866 @staticmethod | |
867 def get_setter_value_expression_pattern(): | |
868 return None | |
869 | |
870 @classmethod | |
871 def get_array_item_c_type_text(cls): | |
872 return "%s%s" % (helper.full_name_prefix_for_use, fi
xed_type_name.class_name) | |
873 | |
874 return TypedefString | |
875 | |
876 elif json_typable["type"] == "object": | |
877 if "properties" in json_typable: | |
878 | |
879 class ClassBinding: | |
880 resolve_data_ = None | |
881 need_user_runtime_cast_ = False | |
882 need_internal_runtime_cast_ = False | |
883 | |
884 @classmethod | |
885 def resolve_inner(cls, resolve_context): | |
886 if cls.resolve_data_: | |
887 return | |
888 | |
889 properties = json_typable["properties"] | |
890 main = [] | |
891 optional = [] | |
892 | |
893 ad_hoc_type_list = [] | |
894 | |
895 for prop in properties: | |
896 prop_name = prop["name"] | |
897 ad_hoc_type_context = cls.AdHocTypeContextImpl(prop_
name, fixed_type_name.class_name, resolve_context, ad_hoc_type_list, helper.full
_name_prefix_for_impl) | |
898 binding = resolve_param_type(prop, context_domain_na
me, ad_hoc_type_context) | |
899 | |
900 code_generator = binding.get_code_generator() | |
901 if code_generator: | |
902 code_generator.register_use(resolve_context.forw
ard_listener) | |
903 | |
904 class PropertyData: | |
905 param_type_binding = binding | |
906 p = prop | |
907 | |
908 if prop.get("optional"): | |
909 optional.append(PropertyData) | |
910 else: | |
911 main.append(PropertyData) | |
912 | |
913 class ResolveData: | |
914 main_properties = main | |
915 optional_properties = optional | |
916 ad_hoc_types = ad_hoc_type_list | |
917 | |
918 cls.resolve_data_ = ResolveData | |
919 | |
920 for ad_hoc in ad_hoc_type_list: | |
921 ad_hoc.resolve_inner(resolve_context) | |
922 | |
923 @classmethod | |
924 def request_user_runtime_cast(cls, request): | |
925 if not request: | |
926 return | |
927 cls.need_user_runtime_cast_ = True | |
928 request.acknowledge() | |
929 cls.request_internal_runtime_cast() | |
930 | |
931 @classmethod | |
932 def request_internal_runtime_cast(cls): | |
933 if cls.need_internal_runtime_cast_: | |
934 return | |
935 cls.need_internal_runtime_cast_ = True | |
936 for p in cls.resolve_data_.main_properties: | |
937 p.param_type_binding.request_internal_runtime_cast() | |
938 for p in cls.resolve_data_.optional_properties: | |
939 p.param_type_binding.request_internal_runtime_cast() | |
940 | |
941 @classmethod | |
942 def get_code_generator(class_binding_cls): | |
943 class CodeGenerator: | |
944 @classmethod | |
945 def generate_type_builder(cls, writer, generate_cont
ext): | |
946 resolve_data = class_binding_cls.resolve_data_ | |
947 helper.write_doc(writer) | |
948 class_name = fixed_type_name.class_name | |
949 | |
950 is_open_type = (context_domain_name + "." + clas
s_name) in TYPES_WITH_OPEN_FIELD_LIST_SET | |
951 | |
952 fixed_type_name.output_comment(writer) | |
953 writer.newline("class ") | |
954 writer.append(class_name) | |
955 writer.append(" : public ") | |
956 if is_open_type: | |
957 writer.append("JSONObject") | |
958 else: | |
959 writer.append("JSONObjectBase") | |
960 writer.append(" {\n") | |
961 writer.newline("public:\n") | |
962 ad_hoc_type_writer = writer.insert_writer(" "
) | |
963 | |
964 for ad_hoc_type in resolve_data.ad_hoc_types: | |
965 code_generator = ad_hoc_type.get_code_genera
tor() | |
966 if code_generator: | |
967 code_generator.generate_type_builder(ad_
hoc_type_writer, generate_context) | |
968 | |
969 writer.newline_multiline( | |
970 """ enum { | |
971 NoFieldsSet = 0, | |
972 """) | |
973 | |
974 state_enum_items = [] | |
975 if len(resolve_data.main_properties) > 0: | |
976 pos = 0 | |
977 for prop_data in resolve_data.main_propertie
s: | |
978 item_name = Capitalizer.lower_camel_case
_to_upper(prop_data.p["name"]) + "Set" | |
979 state_enum_items.append(item_name) | |
980 writer.newline(" %s = 1 << %s,\n"
% (item_name, pos)) | |
981 pos += 1 | |
982 all_fields_set_value = "(" + (" | ".join(sta
te_enum_items)) + ")" | |
983 else: | |
984 all_fields_set_value = "0" | |
985 | |
986 writer.newline_multiline(CodeGeneratorInspectorS
trings.class_binding_builder_part_1 | |
987 % (all_fields_set_value
, class_name, class_name)) | |
988 | |
989 pos = 0 | |
990 for prop_data in resolve_data.main_properties: | |
991 prop_name = prop_data.p["name"] | |
992 | |
993 param_type_binding = prop_data.param_type_bi
nding | |
994 param_raw_type = param_type_binding.reduce_t
o_raw_type() | |
995 | |
996 writer.newline_multiline(CodeGeneratorInspec
torStrings.class_binding_builder_part_2 | |
997 % (state_enum_items[pos], | |
998 Capitalizer.lower_camel_case_to_upper
(prop_name), | |
999 param_type_binding.get_type_model().g
et_input_param_type_text(), | |
1000 state_enum_items[pos], prop_name, | |
1001 param_raw_type.get_setter_name(), pro
p_name, | |
1002 format_setter_value_expression(param_
type_binding, "value"), | |
1003 state_enum_items[pos])) | |
1004 | |
1005 pos += 1 | |
1006 | |
1007 writer.newline_multiline(CodeGeneratorInspectorS
trings.class_binding_builder_part_3 | |
1008 % (class_name, class_na
me, class_name, class_name, class_name, class_name)) | |
1009 | |
1010 writer.newline(" /*\n") | |
1011 writer.newline(" * Synthetic constructor:\n"
) | |
1012 writer.newline(" * RefPtr<%s> result = %s::c
reate()" % (class_name, class_name)) | |
1013 for prop_data in resolve_data.main_properties: | |
1014 writer.append_multiline("\n * .set%s
(...)" % Capitalizer.lower_camel_case_to_upper(prop_data.p["name"])) | |
1015 writer.append_multiline(";\n */\n") | |
1016 | |
1017 writer.newline_multiline(CodeGeneratorInspectorS
trings.class_binding_builder_part_4) | |
1018 | |
1019 writer.newline(" typedef TypeBuilder::StructI
temTraits ItemTraits;\n") | |
1020 | |
1021 for prop_data in resolve_data.main_properties: | |
1022 prop_name = prop_data.p["name"] | |
1023 param_type_binding = prop_data.param_type_bi
nding | |
1024 if isinstance(param_type_binding.get_type_mo
del(), TypeModel.ValueType): | |
1025 writer.append_multiline("\n void %s"
% prop_name) | |
1026 writer.append("(%s value)\n" % param_typ
e_binding.get_type_model().get_command_return_pass_model().get_output_parameter_
type()) | |
1027 writer.newline(" {\n") | |
1028 writer.newline(" JSONObjectBase::
get%s(\"%s\", value);\n" | |
1029 % (param_type_binding.reduce_to_raw_
type().get_setter_name(), prop_data.p["name"])) | |
1030 writer.newline(" }\n") | |
1031 | |
1032 for prop_data in resolve_data.optional_propertie
s: | |
1033 prop_name = prop_data.p["name"] | |
1034 param_type_binding = prop_data.param_type_bi
nding | |
1035 setter_name = "set%s" % Capitalizer.lower_ca
mel_case_to_upper(prop_name) | |
1036 | |
1037 writer.append_multiline("\n void %s" % se
tter_name) | |
1038 writer.append("(%s value)\n" % param_type_bi
nding.get_type_model().get_input_param_type_text()) | |
1039 writer.newline(" {\n") | |
1040 writer.newline(" this->set%s(\"%s\",
%s);\n" | |
1041 % (param_type_binding.reduce_to_raw_type
().get_setter_name(), prop_data.p["name"], | |
1042 format_setter_value_expression(param_
type_binding, "value"))) | |
1043 writer.newline(" }\n") | |
1044 | |
1045 if setter_name in INSPECTOR_OBJECT_SETTER_NA
MES: | |
1046 writer.newline(" using JSONObjectBase
::%s;\n\n" % setter_name) | |
1047 | |
1048 if class_binding_cls.need_user_runtime_cast_: | |
1049 writer.newline(" static PassRefPtr<%s> ru
ntimeCast(PassRefPtr<JSONValue> value)\n" % class_name) | |
1050 writer.newline(" {\n") | |
1051 writer.newline(" RefPtr<JSONObject> o
bject;\n") | |
1052 writer.newline(" bool castRes = value
->asObject(&object);\n") | |
1053 writer.newline(" ASSERT_UNUSED(castRe
s, castRes);\n") | |
1054 writer.append("#if %s\n" % VALIDATOR_IFDEF_N
AME) | |
1055 writer.newline(" assertCorrectValue(o
bject.get());\n") | |
1056 writer.append("#endif // %s\n" % VALIDATOR_
IFDEF_NAME) | |
1057 writer.newline(" static_assert(sizeof
(%s) == sizeof(JSONObjectBase), \"%s should be the same size as JSONObjectBase\"
);\n" % (class_name, class_name)) | |
1058 writer.newline(" return static_cast<%
s*>(static_cast<JSONObjectBase*>(object.get()));\n" % class_name) | |
1059 writer.newline(" }\n") | |
1060 writer.append("\n") | |
1061 | |
1062 if class_binding_cls.need_internal_runtime_cast_
: | |
1063 writer.append("#if %s\n" % VALIDATOR_IFDEF_N
AME) | |
1064 writer.newline(" static void assertCorrec
tValue(JSONValue* value);\n") | |
1065 writer.append("#endif // %s\n" % VALIDATOR_
IFDEF_NAME) | |
1066 | |
1067 closed_field_set = (context_domain_name + ".
" + class_name) not in TYPES_WITH_OPEN_FIELD_LIST_SET | |
1068 | |
1069 validator_writer = generate_context.validato
r_writer | |
1070 | |
1071 validator_writer.newline("void %s%s::assertC
orrectValue(JSONValue* value)\n" % (helper.full_name_prefix_for_impl, class_name
)) | |
1072 validator_writer.newline("{\n") | |
1073 validator_writer.newline(" RefPtr<JSONObj
ect> object;\n") | |
1074 validator_writer.newline(" bool castRes =
value->asObject(&object);\n") | |
1075 validator_writer.newline(" ASSERT_UNUSED(
castRes, castRes);\n") | |
1076 for prop_data in resolve_data.main_propertie
s: | |
1077 validator_writer.newline(" {\n") | |
1078 it_name = "%sPos" % prop_data.p["name"] | |
1079 validator_writer.newline(" JSONOb
ject::iterator %s;\n" % it_name) | |
1080 validator_writer.newline(" %s = o
bject->find(\"%s\");\n" % (it_name, prop_data.p["name"])) | |
1081 validator_writer.newline(" ASSERT
(%s != object->end());\n" % it_name) | |
1082 validator_writer.newline(" %s(%s-
>value.get());\n" % (prop_data.param_type_binding.get_validator_call_text(), it_
name)) | |
1083 validator_writer.newline(" }\n") | |
1084 | |
1085 if closed_field_set: | |
1086 validator_writer.newline(" int foundP
ropertiesCount = %s;\n" % len(resolve_data.main_properties)) | |
1087 | |
1088 for prop_data in resolve_data.optional_prope
rties: | |
1089 validator_writer.newline(" {\n") | |
1090 it_name = "%sPos" % prop_data.p["name"] | |
1091 validator_writer.newline(" JSONOb
ject::iterator %s;\n" % it_name) | |
1092 validator_writer.newline(" %s = o
bject->find(\"%s\");\n" % (it_name, prop_data.p["name"])) | |
1093 validator_writer.newline(" if (%s
!= object->end()) {\n" % it_name) | |
1094 validator_writer.newline(" %s
(%s->value.get());\n" % (prop_data.param_type_binding.get_validator_call_text(),
it_name)) | |
1095 if closed_field_set: | |
1096 validator_writer.newline("
++foundPropertiesCount;\n") | |
1097 validator_writer.newline(" }\n") | |
1098 validator_writer.newline(" }\n") | |
1099 | |
1100 if closed_field_set: | |
1101 validator_writer.newline(" if (foundP
ropertiesCount != object->size()) {\n") | |
1102 validator_writer.newline(" FATAL(\"
Unexpected properties in object: %s\\n\", object->toJSONString().ascii().data())
;\n") | |
1103 validator_writer.newline(" }\n") | |
1104 validator_writer.newline("}\n") | |
1105 | |
1106 validator_writer.newline("\n\n") | |
1107 | |
1108 if is_open_type: | |
1109 cpp_writer = generate_context.cpp_writer | |
1110 writer.append("\n") | |
1111 writer.newline(" // Property names for ty
pe generated as open.\n") | |
1112 for prop_data in resolve_data.main_propertie
s + resolve_data.optional_properties: | |
1113 prop_name = prop_data.p["name"] | |
1114 prop_field_name = Capitalizer.lower_came
l_case_to_upper(prop_name) | |
1115 writer.newline(" static const char %s
[];\n" % (prop_field_name)) | |
1116 cpp_writer.newline("const char %s%s::%s[
] = \"%s\";\n" % (helper.full_name_prefix_for_impl, class_name, prop_field_name,
prop_name)) | |
1117 | |
1118 | |
1119 writer.newline("};\n\n") | |
1120 | |
1121 @staticmethod | |
1122 def generate_forward_declaration(writer): | |
1123 class_name = fixed_type_name.class_name | |
1124 writer.newline("class ") | |
1125 writer.append(class_name) | |
1126 writer.append(";\n") | |
1127 | |
1128 @staticmethod | |
1129 def register_use(forward_listener): | |
1130 helper.add_to_forward_listener(forward_listener) | |
1131 | |
1132 @staticmethod | |
1133 def get_generate_pass_id(): | |
1134 return TypeBuilderPass.MAIN | |
1135 | |
1136 return CodeGenerator | |
1137 | |
1138 @staticmethod | |
1139 def get_validator_call_text(): | |
1140 return helper.full_name_prefix_for_use + fixed_type_name
.class_name + "::assertCorrectValue" | |
1141 | |
1142 @classmethod | |
1143 def get_array_item_c_type_text(cls): | |
1144 return helper.full_name_prefix_for_use + fixed_type_name
.class_name | |
1145 | |
1146 @staticmethod | |
1147 def get_setter_value_expression_pattern(): | |
1148 return None | |
1149 | |
1150 @staticmethod | |
1151 def reduce_to_raw_type(): | |
1152 return RawTypes.Object | |
1153 | |
1154 @staticmethod | |
1155 def get_type_model(): | |
1156 return TypeModel.RefPtrBased(helper.full_name_prefix_for
_use + fixed_type_name.class_name) | |
1157 | |
1158 class AdHocTypeContextImpl: | |
1159 def __init__(self, property_name, class_name, resolve_co
ntext, ad_hoc_type_list, parent_full_name_prefix): | |
1160 self.property_name = property_name | |
1161 self.class_name = class_name | |
1162 self.resolve_context = resolve_context | |
1163 self.ad_hoc_type_list = ad_hoc_type_list | |
1164 self.container_full_name_prefix = parent_full_name_p
refix + class_name + "::" | |
1165 self.container_relative_name_prefix = "" | |
1166 | |
1167 def get_type_name_fix(self): | |
1168 class NameFix: | |
1169 class_name = Capitalizer.lower_camel_case_to_upp
er(self.property_name) | |
1170 | |
1171 @staticmethod | |
1172 def output_comment(writer): | |
1173 writer.newline("// Named after property name
'%s' while generating %s.\n" % (self.property_name, self.class_name)) | |
1174 | |
1175 return NameFix | |
1176 | |
1177 def add_type(self, binding): | |
1178 self.ad_hoc_type_list.append(binding) | |
1179 | |
1180 return ClassBinding | |
1181 else: | |
1182 | |
1183 class PlainObjectBinding: | |
1184 @classmethod | |
1185 def resolve_inner(cls, resolve_context): | |
1186 pass | |
1187 | |
1188 @staticmethod | |
1189 def request_user_runtime_cast(request): | |
1190 pass | |
1191 | |
1192 @staticmethod | |
1193 def request_internal_runtime_cast(): | |
1194 pass | |
1195 | |
1196 @staticmethod | |
1197 def get_code_generator(): | |
1198 pass | |
1199 | |
1200 @staticmethod | |
1201 def get_validator_call_text(): | |
1202 return "RuntimeCastHelper::assertType<JSONValue::TypeObj
ect>" | |
1203 | |
1204 @classmethod | |
1205 def get_array_item_c_type_text(cls): | |
1206 return cls.reduce_to_raw_type().get_array_item_raw_c_typ
e_text() | |
1207 | |
1208 @staticmethod | |
1209 def get_setter_value_expression_pattern(): | |
1210 return None | |
1211 | |
1212 @staticmethod | |
1213 def reduce_to_raw_type(): | |
1214 return RawTypes.Object | |
1215 | |
1216 @staticmethod | |
1217 def get_type_model(): | |
1218 return TypeModel.Object | |
1219 | |
1220 return PlainObjectBinding | |
1221 elif json_typable["type"] == "array": | |
1222 if "items" in json_typable: | |
1223 | |
1224 ad_hoc_types = [] | |
1225 | |
1226 class AdHocTypeContext: | |
1227 container_full_name_prefix = "<not yet defined>" | |
1228 container_relative_name_prefix = "" | |
1229 | |
1230 @staticmethod | |
1231 def get_type_name_fix(): | |
1232 return fixed_type_name | |
1233 | |
1234 @staticmethod | |
1235 def add_type(binding): | |
1236 ad_hoc_types.append(binding) | |
1237 | |
1238 item_binding = resolve_param_type(json_typable["items"], context
_domain_name, AdHocTypeContext) | |
1239 | |
1240 class ArrayBinding: | |
1241 resolve_data_ = None | |
1242 need_internal_runtime_cast_ = False | |
1243 | |
1244 @classmethod | |
1245 def resolve_inner(cls, resolve_context): | |
1246 if cls.resolve_data_: | |
1247 return | |
1248 | |
1249 class ResolveData: | |
1250 item_type_binding = item_binding | |
1251 ad_hoc_type_list = ad_hoc_types | |
1252 | |
1253 cls.resolve_data_ = ResolveData | |
1254 | |
1255 for t in ad_hoc_types: | |
1256 t.resolve_inner(resolve_context) | |
1257 | |
1258 @classmethod | |
1259 def request_user_runtime_cast(cls, request): | |
1260 raise Exception("Not implemented yet") | |
1261 | |
1262 @classmethod | |
1263 def request_internal_runtime_cast(cls): | |
1264 if cls.need_internal_runtime_cast_: | |
1265 return | |
1266 cls.need_internal_runtime_cast_ = True | |
1267 cls.resolve_data_.item_type_binding.request_internal_run
time_cast() | |
1268 | |
1269 @classmethod | |
1270 def get_code_generator(array_binding_cls): | |
1271 | |
1272 class CodeGenerator: | |
1273 @staticmethod | |
1274 def generate_type_builder(writer, generate_context): | |
1275 ad_hoc_type_writer = writer | |
1276 | |
1277 resolve_data = array_binding_cls.resolve_data_ | |
1278 | |
1279 for ad_hoc_type in resolve_data.ad_hoc_type_list
: | |
1280 code_generator = ad_hoc_type.get_code_genera
tor() | |
1281 if code_generator: | |
1282 code_generator.generate_type_builder(ad_
hoc_type_writer, generate_context) | |
1283 | |
1284 @staticmethod | |
1285 def generate_forward_declaration(writer): | |
1286 pass | |
1287 | |
1288 @staticmethod | |
1289 def register_use(forward_listener): | |
1290 item_code_generator = item_binding.get_code_gene
rator() | |
1291 if item_code_generator: | |
1292 item_code_generator.register_use(forward_lis
tener) | |
1293 | |
1294 @staticmethod | |
1295 def get_generate_pass_id(): | |
1296 return TypeBuilderPass.MAIN | |
1297 | |
1298 return CodeGenerator | |
1299 | |
1300 @classmethod | |
1301 def get_validator_call_text(cls): | |
1302 return cls.get_array_item_c_type_text() + "::assertCorre
ctValue" | |
1303 | |
1304 @classmethod | |
1305 def get_array_item_c_type_text(cls): | |
1306 return replace_right_shift("TypeBuilder::Array<%s>" % cl
s.resolve_data_.item_type_binding.get_array_item_c_type_text()) | |
1307 | |
1308 @staticmethod | |
1309 def get_setter_value_expression_pattern(): | |
1310 return None | |
1311 | |
1312 @staticmethod | |
1313 def reduce_to_raw_type(): | |
1314 return RawTypes.Array | |
1315 | |
1316 @classmethod | |
1317 def get_type_model(cls): | |
1318 return TypeModel.RefPtrBased(cls.get_array_item_c_type_t
ext()) | |
1319 | |
1320 return ArrayBinding | |
1321 else: | |
1322 # Fall-through to raw type. | |
1323 pass | |
1324 | |
1325 raw_type = RawTypes.get(json_typable["type"]) | |
1326 | |
1327 return RawTypeBinding(raw_type) | |
1328 | |
1329 | |
1330 class RawTypeBinding: | |
1331 def __init__(self, raw_type): | |
1332 self.raw_type_ = raw_type | |
1333 | |
1334 def resolve_inner(self, resolve_context): | |
1335 pass | |
1336 | |
1337 def request_user_runtime_cast(self, request): | |
1338 raise Exception("Unsupported") | |
1339 | |
1340 def request_internal_runtime_cast(self): | |
1341 pass | |
1342 | |
1343 def get_code_generator(self): | |
1344 return None | |
1345 | |
1346 def get_validator_call_text(self): | |
1347 return self.raw_type_.get_raw_validator_call_text() | |
1348 | |
1349 def get_array_item_c_type_text(self): | |
1350 return self.raw_type_.get_array_item_raw_c_type_text() | |
1351 | |
1352 def get_setter_value_expression_pattern(self): | |
1353 return None | |
1354 | |
1355 def reduce_to_raw_type(self): | |
1356 return self.raw_type_ | |
1357 | |
1358 def get_type_model(self): | |
1359 return self.raw_type_.get_raw_type_model() | |
1360 | |
1361 | |
1362 class TypeData(object): | |
1363 def __init__(self, json_type, json_domain, domain_data): | |
1364 self.json_type_ = json_type | |
1365 self.json_domain_ = json_domain | |
1366 self.domain_data_ = domain_data | |
1367 | |
1368 if "type" not in json_type: | |
1369 raise Exception("Unknown type") | |
1370 | |
1371 json_type_name = json_type["type"] | |
1372 raw_type = RawTypes.get(json_type_name) | |
1373 self.raw_type_ = raw_type | |
1374 self.binding_being_resolved_ = False | |
1375 self.binding_ = None | |
1376 | |
1377 def get_raw_type(self): | |
1378 return self.raw_type_ | |
1379 | |
1380 def get_binding(self): | |
1381 if not self.binding_: | |
1382 if self.binding_being_resolved_: | |
1383 raise Error("Type %s is already being resolved" % self.json_type
_["type"]) | |
1384 # Resolve only lazily, because resolving one named type may require
resolving some other named type. | |
1385 self.binding_being_resolved_ = True | |
1386 try: | |
1387 self.binding_ = TypeBindings.create_named_type_declaration(self.
json_type_, self.json_domain_["domain"], self) | |
1388 finally: | |
1389 self.binding_being_resolved_ = False | |
1390 | |
1391 return self.binding_ | |
1392 | |
1393 def get_json_type(self): | |
1394 return self.json_type_ | |
1395 | |
1396 def get_name(self): | |
1397 return self.json_type_["id"] | |
1398 | |
1399 def get_domain_name(self): | |
1400 return self.json_domain_["domain"] | |
1401 | |
1402 | |
1403 class DomainData: | |
1404 def __init__(self, json_domain): | |
1405 self.json_domain = json_domain | |
1406 self.types_ = [] | |
1407 | |
1408 def add_type(self, type_data): | |
1409 self.types_.append(type_data) | |
1410 | |
1411 def name(self): | |
1412 return self.json_domain["domain"] | |
1413 | |
1414 def types(self): | |
1415 return self.types_ | |
1416 | |
1417 | |
1418 class TypeMap: | |
1419 def __init__(self, api): | |
1420 self.map_ = {} | |
1421 self.domains_ = [] | |
1422 for json_domain in api["domains"]: | |
1423 domain_name = json_domain["domain"] | |
1424 | |
1425 domain_map = {} | |
1426 self.map_[domain_name] = domain_map | |
1427 | |
1428 domain_data = DomainData(json_domain) | |
1429 self.domains_.append(domain_data) | |
1430 | |
1431 if "types" in json_domain: | |
1432 for json_type in json_domain["types"]: | |
1433 type_name = json_type["id"] | |
1434 type_data = TypeData(json_type, json_domain, domain_data) | |
1435 domain_map[type_name] = type_data | |
1436 domain_data.add_type(type_data) | |
1437 | |
1438 def domains(self): | |
1439 return self.domains_ | |
1440 | |
1441 def get(self, domain_name, type_name): | |
1442 return self.map_[domain_name][type_name] | |
1443 | |
1444 | |
1445 def resolve_param_type(json_parameter, scope_domain_name, ad_hoc_type_context): | |
1446 if "$ref" in json_parameter: | |
1447 json_ref = json_parameter["$ref"] | |
1448 type_data = get_ref_data(json_ref, scope_domain_name) | |
1449 return type_data.get_binding() | |
1450 elif "type" in json_parameter: | |
1451 result = TypeBindings.create_ad_hoc_type_declaration(json_parameter, sco
pe_domain_name, ad_hoc_type_context) | |
1452 ad_hoc_type_context.add_type(result) | |
1453 return result | |
1454 else: | |
1455 raise Exception("Unknown type") | |
1456 | |
1457 def resolve_param_raw_type(json_parameter, scope_domain_name): | |
1458 if "$ref" in json_parameter: | |
1459 json_ref = json_parameter["$ref"] | |
1460 type_data = get_ref_data(json_ref, scope_domain_name) | |
1461 return type_data.get_raw_type() | |
1462 elif "type" in json_parameter: | |
1463 json_type = json_parameter["type"] | |
1464 return RawTypes.get(json_type) | |
1465 else: | |
1466 raise Exception("Unknown type") | |
1467 | |
1468 | |
1469 def get_ref_data(json_ref, scope_domain_name): | |
1470 dot_pos = json_ref.find(".") | |
1471 if dot_pos == -1: | |
1472 domain_name = scope_domain_name | |
1473 type_name = json_ref | |
1474 else: | |
1475 domain_name = json_ref[:dot_pos] | |
1476 type_name = json_ref[dot_pos + 1:] | |
1477 | |
1478 return type_map.get(domain_name, type_name) | |
1479 | |
1480 | |
1481 input_file = open(input_json_filename, "r") | |
1482 json_string = input_file.read() | |
1483 json_api = json.loads(json_string) | |
1484 | |
1485 | |
1486 class Templates: | |
1487 def get_this_script_path_(absolute_path): | |
1488 absolute_path = os.path.abspath(absolute_path) | |
1489 components = [] | |
1490 | |
1491 def fill_recursive(path_part, depth): | |
1492 if depth <= 0 or path_part == '/': | |
1493 return | |
1494 fill_recursive(os.path.dirname(path_part), depth - 1) | |
1495 components.append(os.path.basename(path_part)) | |
1496 | |
1497 # Typical path is /Source/WebCore/inspector/CodeGeneratorInspector.py | |
1498 # Let's take 4 components from the real path then. | |
1499 fill_recursive(absolute_path, 4) | |
1500 | |
1501 return "/".join(components) | |
1502 | |
1503 file_header_ = ("// File is generated by %s\n\n" % get_this_script_path_(sys
.argv[0]) + | |
1504 """// Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
1505 // Use of this source code is governed by a BSD-style license that can be | |
1506 // found in the LICENSE file. | |
1507 """) | |
1508 | |
1509 frontend_domain_class = string.Template(CodeGeneratorInspectorStrings.fronte
nd_domain_class) | |
1510 backend_method = string.Template(CodeGeneratorInspectorStrings.backend_metho
d) | |
1511 frontend_method = string.Template(CodeGeneratorInspectorStrings.frontend_met
hod) | |
1512 callback_main_methods = string.Template(CodeGeneratorInspectorStrings.callba
ck_main_methods) | |
1513 callback_failure_method = string.Template(CodeGeneratorInspectorStrings.call
back_failure_method) | |
1514 frontend_h = string.Template(file_header_ + CodeGeneratorInspectorStrings.fr
ontend_h) | |
1515 backend_h = string.Template(file_header_ + CodeGeneratorInspectorStrings.bac
kend_h) | |
1516 backend_cpp = string.Template(file_header_ + CodeGeneratorInspectorStrings.b
ackend_cpp) | |
1517 frontend_cpp = string.Template(file_header_ + CodeGeneratorInspectorStrings.
frontend_cpp) | |
1518 typebuilder_h = string.Template(file_header_ + CodeGeneratorInspectorStrings
.typebuilder_h) | |
1519 typebuilder_cpp = string.Template(file_header_ + CodeGeneratorInspectorStrin
gs.typebuilder_cpp) | |
1520 param_container_access_code = CodeGeneratorInspectorStrings.param_container_
access_code | |
1521 | |
1522 | |
1523 | |
1524 | |
1525 | |
1526 type_map = TypeMap(json_api) | |
1527 | |
1528 | |
1529 class NeedRuntimeCastRequest: | |
1530 def __init__(self): | |
1531 self.ack_ = None | |
1532 | |
1533 def acknowledge(self): | |
1534 self.ack_ = True | |
1535 | |
1536 def is_acknowledged(self): | |
1537 return self.ack_ | |
1538 | |
1539 | |
1540 def resolve_all_types(): | |
1541 runtime_cast_generate_requests = {} | |
1542 for type_name in TYPES_WITH_RUNTIME_CAST_SET: | |
1543 runtime_cast_generate_requests[type_name] = NeedRuntimeCastRequest() | |
1544 | |
1545 class ForwardListener: | |
1546 type_data_set = set() | |
1547 already_declared_set = set() | |
1548 | |
1549 @classmethod | |
1550 def add_type_data(cls, type_data): | |
1551 if type_data not in cls.already_declared_set: | |
1552 cls.type_data_set.add(type_data) | |
1553 | |
1554 class ResolveContext: | |
1555 forward_listener = ForwardListener | |
1556 | |
1557 for domain_data in type_map.domains(): | |
1558 for type_data in domain_data.types(): | |
1559 # Do not generate forwards for this type any longer. | |
1560 ForwardListener.already_declared_set.add(type_data) | |
1561 | |
1562 binding = type_data.get_binding() | |
1563 binding.resolve_inner(ResolveContext) | |
1564 | |
1565 for domain_data in type_map.domains(): | |
1566 for type_data in domain_data.types(): | |
1567 full_type_name = "%s.%s" % (type_data.get_domain_name(), type_data.g
et_name()) | |
1568 request = runtime_cast_generate_requests.pop(full_type_name, None) | |
1569 binding = type_data.get_binding() | |
1570 if request: | |
1571 binding.request_user_runtime_cast(request) | |
1572 | |
1573 if request and not request.is_acknowledged(): | |
1574 raise Exception("Failed to generate runtimeCast in " + full_type
_name) | |
1575 | |
1576 for full_type_name in runtime_cast_generate_requests: | |
1577 raise Exception("Failed to generate runtimeCast. Type " + full_type_name
+ " not found") | |
1578 | |
1579 return ForwardListener | |
1580 | |
1581 | |
1582 global_forward_listener = resolve_all_types() | |
1583 | |
1584 | |
1585 def get_annotated_type_text(raw_type, annotated_type): | |
1586 if annotated_type != raw_type: | |
1587 return "/*%s*/ %s" % (annotated_type, raw_type) | |
1588 else: | |
1589 return raw_type | |
1590 | |
1591 | |
1592 def format_setter_value_expression(param_type_binding, value_ref): | |
1593 pattern = param_type_binding.get_setter_value_expression_pattern() | |
1594 if pattern: | |
1595 return pattern % value_ref | |
1596 else: | |
1597 return value_ref | |
1598 | |
1599 class Generator: | |
1600 frontend_class_field_lines = [] | |
1601 frontend_domain_class_lines = [] | |
1602 | |
1603 method_name_enum_list = [] | |
1604 backend_method_declaration_list = [] | |
1605 backend_method_implementation_list = [] | |
1606 backend_method_name_declaration_list = [] | |
1607 backend_method_name_declaration_index_list = [] | |
1608 backend_method_name_declaration_current_index = 0 | |
1609 method_handler_list = [] | |
1610 frontend_method_list = [] | |
1611 | |
1612 backend_virtual_setters_list = [] | |
1613 backend_agent_interface_list = [] | |
1614 backend_setters_list = [] | |
1615 backend_constructor_init_list = [] | |
1616 backend_field_list = [] | |
1617 frontend_constructor_init_list = [] | |
1618 type_builder_fragments = [] | |
1619 type_builder_forwards = [] | |
1620 validator_impl_list = [] | |
1621 type_builder_impl_list = [] | |
1622 | |
1623 | |
1624 @staticmethod | |
1625 def go(): | |
1626 Generator.process_types(type_map) | |
1627 | |
1628 for json_domain in json_api["domains"]: | |
1629 domain_name = json_domain["domain"] | |
1630 domain_name_lower = domain_name.lower() | |
1631 | |
1632 agent_field_name = DomainNameFixes.get_fixed_data(domain_name) | |
1633 | |
1634 frontend_method_declaration_lines = [] | |
1635 | |
1636 if "events" in json_domain: | |
1637 for json_event in json_domain["events"]: | |
1638 Generator.process_event(json_event, domain_name, frontend_me
thod_declaration_lines) | |
1639 | |
1640 Generator.frontend_class_field_lines.append(" %s m_%s;\n" % (doma
in_name, domain_name_lower)) | |
1641 if Generator.frontend_constructor_init_list: | |
1642 Generator.frontend_constructor_init_list.append(" , ") | |
1643 Generator.frontend_constructor_init_list.append("m_%s(inspectorFront
endChannel)\n" % domain_name_lower) | |
1644 Generator.frontend_domain_class_lines.append(Templates.frontend_doma
in_class.substitute(None, | |
1645 domainClassName=domain_name, | |
1646 domainFieldName=domain_name_lower, | |
1647 frontendDomainMethodDeclarations="".join(flatten_list(frontend_m
ethod_declaration_lines)))) | |
1648 | |
1649 agent_interface_name = Capitalizer.lower_camel_case_to_upper(domain_
name) + "CommandHandler" | |
1650 Generator.backend_agent_interface_list.append(" class CORE_EXPORT
%s {\n" % agent_interface_name) | |
1651 Generator.backend_agent_interface_list.append(" public:\n") | |
1652 if "commands" in json_domain: | |
1653 for json_command in json_domain["commands"]: | |
1654 Generator.process_command(json_command, domain_name, agent_f
ield_name, agent_interface_name) | |
1655 Generator.backend_agent_interface_list.append("\n protected:\n") | |
1656 Generator.backend_agent_interface_list.append(" virtual ~%s()
{ }\n" % agent_interface_name) | |
1657 Generator.backend_agent_interface_list.append(" };\n\n") | |
1658 | |
1659 Generator.backend_constructor_init_list.append(" , m_%s(0)" %
agent_field_name) | |
1660 Generator.backend_virtual_setters_list.append(" virtual void regi
sterAgent(%s* %s) = 0;" % (agent_interface_name, agent_field_name)) | |
1661 Generator.backend_setters_list.append(" virtual void registerAgen
t(%s* %s) { ASSERT(!m_%s); m_%s = %s; }" % (agent_interface_name, agent_field_na
me, agent_field_name, agent_field_name, agent_field_name)) | |
1662 Generator.backend_field_list.append(" %s* m_%s;" % (agent_interfa
ce_name, agent_field_name)) | |
1663 | |
1664 @staticmethod | |
1665 def process_event(json_event, domain_name, frontend_method_declaration_lines
): | |
1666 if (("handlers" in json_event) and (not ("renderer" in json_event["handl
ers"]))): | |
1667 return | |
1668 | |
1669 event_name = json_event["name"] | |
1670 | |
1671 ad_hoc_type_output = [] | |
1672 frontend_method_declaration_lines.append(ad_hoc_type_output) | |
1673 ad_hoc_type_writer = Writer(ad_hoc_type_output, " ") | |
1674 | |
1675 decl_parameter_list = [] | |
1676 | |
1677 json_parameters = json_event.get("parameters") | |
1678 Generator.generate_send_method(json_parameters, event_name, domain_name,
ad_hoc_type_writer, | |
1679 decl_parameter_list, | |
1680 Generator.EventMethodStructTemplate, | |
1681 Generator.frontend_method_list, Templates
.frontend_method, {"eventName": event_name}) | |
1682 | |
1683 frontend_method_declaration_lines.append( | |
1684 " void %s(%s);\n" % (event_name, ", ".join(decl_parameter_lis
t))) | |
1685 | |
1686 class EventMethodStructTemplate: | |
1687 @staticmethod | |
1688 def append_prolog(line_list): | |
1689 line_list.append(" RefPtr<JSONObject> paramsObject = JSONObject::
create();\n") | |
1690 | |
1691 @staticmethod | |
1692 def append_epilog(line_list): | |
1693 line_list.append(" jsonMessage->setObject(\"params\", paramsObjec
t);\n") | |
1694 | |
1695 container_name = "paramsObject" | |
1696 | |
1697 @staticmethod | |
1698 def process_command(json_command, domain_name, agent_field_name, agent_inter
face_name): | |
1699 if (("handlers" in json_command) and (not ("renderer" in json_command["h
andlers"]))): | |
1700 return | |
1701 | |
1702 json_command_name = json_command["name"] | |
1703 | |
1704 cmd_enum_name = "k%s_%sCmd" % (domain_name, json_command["name"]) | |
1705 | |
1706 Generator.method_name_enum_list.append(" %s," % cmd_enum_name) | |
1707 Generator.method_handler_list.append(" &InspectorBackendDispa
tcherImpl::%s_%s," % (domain_name, json_command_name)) | |
1708 Generator.backend_method_declaration_list.append(" void %s_%s(int cal
lId, JSONObject* requestMessageObject, JSONArray* protocolErrors);" % (domain_na
me, json_command_name)) | |
1709 | |
1710 backend_agent_interface_list = [] if "redirect" in json_command else Gen
erator.backend_agent_interface_list | |
1711 | |
1712 ad_hoc_type_output = [] | |
1713 backend_agent_interface_list.append(ad_hoc_type_output) | |
1714 ad_hoc_type_writer = Writer(ad_hoc_type_output, " ") | |
1715 | |
1716 backend_agent_interface_list.append(" virtual void %s(ErrorString
*" % json_command_name) | |
1717 | |
1718 method_in_code = "" | |
1719 method_out_code = "" | |
1720 agent_call_param_list = ["&error"] | |
1721 agent_call_params_declaration_list = [" ErrorString error;"] | |
1722 send_response_call_params_list = ["error"] | |
1723 request_message_param = "" | |
1724 normal_response_cook_text = "" | |
1725 error_type_binding = None | |
1726 if "error" in json_command: | |
1727 json_error = json_command["error"] | |
1728 error_type_binding = Generator.resolve_type_and_generate_ad_hoc(json
_error, json_command_name + "Error", json_command_name, domain_name, ad_hoc_type
_writer, agent_interface_name + "::") | |
1729 error_type_model = error_type_binding.get_type_model().get_optional(
) | |
1730 error_annotated_type = error_type_model.get_command_return_pass_mode
l().get_output_parameter_type() | |
1731 agent_call_param_list.append("%serrorData" % error_type_model.get_co
mmand_return_pass_model().get_output_argument_prefix()) | |
1732 backend_agent_interface_list.append(", %s errorData" % error_annotat
ed_type) | |
1733 method_in_code += " %s errorData;\n" % error_type_model.get_comma
nd_return_pass_model().get_return_var_type() | |
1734 send_response_call_params_list.append("errorData") | |
1735 | |
1736 if "parameters" in json_command: | |
1737 json_params = json_command["parameters"] | |
1738 request_message_param = " requestMessageObject" | |
1739 | |
1740 if json_params: | |
1741 method_in_code += Templates.param_container_access_code | |
1742 | |
1743 for json_parameter in json_params: | |
1744 json_param_name = json_parameter["name"] | |
1745 param_raw_type = resolve_param_raw_type(json_parameter, domain_n
ame) | |
1746 | |
1747 getter_name = param_raw_type.get_getter_name() | |
1748 | |
1749 optional = json_parameter.get("optional") | |
1750 | |
1751 non_optional_type_model = param_raw_type.get_raw_type_model() | |
1752 | |
1753 if optional: | |
1754 code = (" bool %s_valueFound = false;\n" | |
1755 " %s in_%s = get%s(paramsContainerPtr, \"%s\", &%
s_valueFound, protocolErrors);\n" % | |
1756 (json_param_name, non_optional_type_model.get_command
_return_pass_model().get_return_var_type(), json_param_name, getter_name, json_p
aram_name, json_param_name)) | |
1757 param = "%s_valueFound ? &in_%s : 0" % (json_param_name, jso
n_param_name) | |
1758 # FIXME: pass optional refptr-values as PassRefPtr | |
1759 formal_param_type_pattern = "const %s*" | |
1760 else: | |
1761 code = (" %s in_%s = get%s(paramsContainerPtr, \"%s\", 0,
protocolErrors);\n" % | |
1762 (non_optional_type_model.get_command_return_pass_mod
el().get_return_var_type(), json_param_name, getter_name, json_param_name)) | |
1763 param = "in_%s" % json_param_name | |
1764 # FIXME: pass not-optional refptr-values as NonNullPassRefPt
r | |
1765 if param_raw_type.is_heavy_value(): | |
1766 formal_param_type_pattern = "const %s&" | |
1767 else: | |
1768 formal_param_type_pattern = "%s" | |
1769 | |
1770 method_in_code += code | |
1771 agent_call_param_list.append(param) | |
1772 backend_agent_interface_list.append(", %s in_%s" % (formal_param
_type_pattern % non_optional_type_model.get_command_return_pass_model().get_retu
rn_var_type(), json_param_name)) | |
1773 | |
1774 if json_command.get("async") == True: | |
1775 callback_name = Capitalizer.lower_camel_case_to_upper(json_command_n
ame) + "Callback" | |
1776 | |
1777 callback_output = [] | |
1778 callback_writer = Writer(callback_output, ad_hoc_type_writer.get_ind
ent()) | |
1779 | |
1780 decl_parameter_list = [] | |
1781 Generator.generate_send_method(json_command.get("returns"), json_com
mand_name, domain_name, ad_hoc_type_writer, | |
1782 decl_parameter_list, | |
1783 Generator.CallbackMethodStructTemplat
e, | |
1784 Generator.backend_method_implementati
on_list, Templates.callback_main_methods, | |
1785 {"callbackName": callback_name, "agen
tName": agent_interface_name}) | |
1786 | |
1787 callback_writer.newline("class " + callback_name + " : public Callba
ckBase {\n") | |
1788 callback_writer.newline("public:\n") | |
1789 callback_writer.newline(" " + callback_name + "(PassRefPtrWillBeR
awPtr<InspectorBackendDispatcherImpl>, int id);\n") | |
1790 callback_writer.newline(" CORE_EXPORT void sendSuccess(" + ", ".j
oin(decl_parameter_list) + ");\n") | |
1791 error_part_writer = callback_writer.insert_writer("") | |
1792 callback_writer.newline("};\n") | |
1793 | |
1794 if error_type_binding: | |
1795 annotated_type = error_type_model.get_input_param_type_text() | |
1796 error_part_writer.newline(" void sendFailure(const ErrorStrin
g&, %s);\n" % annotated_type) | |
1797 error_part_writer.newline(" using CallbackBase::sendFailure;\
n") | |
1798 | |
1799 assigment_value = error_type_model.get_event_setter_expression_p
attern() % "errorData" | |
1800 assigment_value = error_type_binding.reduce_to_raw_type().get_co
nstructor_pattern() % assigment_value | |
1801 | |
1802 Generator.backend_method_implementation_list.append(Templates.ca
llback_failure_method.substitute(None, | |
1803 agentName=agent_interface_name, | |
1804 callbackName=callback_name, | |
1805 parameter=annotated_type + " errorData", | |
1806 argument=assigment_value)) | |
1807 | |
1808 ad_hoc_type_output.append(callback_output) | |
1809 | |
1810 method_out_code += " RefPtrWillBeRawPtr<" + agent_interface_name
+ "::" + callback_name + "> callback = adoptRefWillBeNoop(new " + agent_interfac
e_name + "::" + callback_name + "(this, callId));\n" | |
1811 agent_call_param_list.append("callback") | |
1812 normal_response_cook_text += " if (!error.length()) \n" | |
1813 normal_response_cook_text += " return;\n" | |
1814 normal_response_cook_text += " callback->disable();\n" | |
1815 backend_agent_interface_list.append(", PassRefPtrWillBeRawPtr<%s> ca
llback" % callback_name) | |
1816 else: | |
1817 if "returns" in json_command: | |
1818 method_out_code += "\n" | |
1819 agent_call_params_declaration_list.append(" RefPtr<JSONObject
> result = JSONObject::create();") | |
1820 send_response_call_params_list.append("result") | |
1821 response_cook_list = [] | |
1822 for json_return in json_command["returns"]: | |
1823 | |
1824 json_return_name = json_return["name"] | |
1825 | |
1826 optional = bool(json_return.get("optional")) | |
1827 | |
1828 return_type_binding = Generator.resolve_param_type_and_gener
ate_ad_hoc(json_return, json_command_name, domain_name, ad_hoc_type_writer, agen
t_interface_name + "::") | |
1829 | |
1830 raw_type = return_type_binding.reduce_to_raw_type() | |
1831 setter_type = raw_type.get_setter_name() | |
1832 | |
1833 type_model = return_type_binding.get_type_model() | |
1834 if optional: | |
1835 type_model = type_model.get_optional() | |
1836 | |
1837 code = " %s out_%s;\n" % (type_model.get_command_return_p
ass_model().get_return_var_type(), json_return_name) | |
1838 param = "%sout_%s" % (type_model.get_command_return_pass_mod
el().get_output_argument_prefix(), json_return_name) | |
1839 var_name = "out_%s" % json_return_name | |
1840 setter_argument = type_model.get_command_return_pass_model()
.get_output_to_raw_expression() % var_name | |
1841 if return_type_binding.get_setter_value_expression_pattern()
: | |
1842 setter_argument = return_type_binding.get_setter_value_e
xpression_pattern() % setter_argument | |
1843 | |
1844 cook = " result->set%s(\"%s\", %s);\n" % (setter_type
, json_return_name, | |
1845 setter_
argument) | |
1846 | |
1847 set_condition_pattern = type_model.get_command_return_pass_m
odel().get_set_return_condition() | |
1848 if set_condition_pattern: | |
1849 cook = (" if (%s)\n " % (set_condition_pattern
% var_name)) + cook | |
1850 annotated_type = type_model.get_command_return_pass_model().
get_output_parameter_type() | |
1851 | |
1852 param_name = var_name | |
1853 if optional: | |
1854 param_name = "opt_" + param_name | |
1855 | |
1856 backend_agent_interface_list.append(", %s %s" % (annotated_t
ype, param_name)) | |
1857 response_cook_list.append(cook) | |
1858 | |
1859 method_out_code += code | |
1860 agent_call_param_list.append(param) | |
1861 | |
1862 normal_response_cook_text += "".join(response_cook_list) | |
1863 | |
1864 if len(normal_response_cook_text) != 0: | |
1865 normal_response_cook_text = " if (!error.length()) {\n" +
normal_response_cook_text + " }" | |
1866 | |
1867 # Redirect to another agent's implementation. | |
1868 agent_field = "m_" + agent_field_name | |
1869 if "redirect" in json_command: | |
1870 agent_field = "m_" + DomainNameFixes.get_fixed_data(json_command.get
("redirect")) | |
1871 | |
1872 Generator.backend_method_implementation_list.append(Templates.backend_me
thod.substitute(None, | |
1873 domainName=domain_name, methodName=json_command_name, | |
1874 agentField=agent_field, | |
1875 methodCode="".join([method_in_code, method_out_code]), | |
1876 agentCallParamsDeclaration="\n".join(agent_call_params_declaration_l
ist), | |
1877 agentCallParams=", ".join(agent_call_param_list), | |
1878 requestMessageObject=request_message_param, | |
1879 responseCook=normal_response_cook_text, | |
1880 sendResponseCallParams=", ".join(send_response_call_params_list), | |
1881 commandNameIndex=cmd_enum_name)) | |
1882 declaration_command_name = "%s.%s\\0" % (domain_name, json_command_name) | |
1883 Generator.backend_method_name_declaration_list.append(" \"%s\"" % dec
laration_command_name) | |
1884 assert Generator.backend_method_name_declaration_current_index < 2 ** 16
, "Number too large for unsigned short." | |
1885 Generator.backend_method_name_declaration_index_list.append(" %d," %
Generator.backend_method_name_declaration_current_index) | |
1886 Generator.backend_method_name_declaration_current_index += len(declarati
on_command_name) - 1 | |
1887 | |
1888 backend_agent_interface_list.append(") = 0;\n") | |
1889 | |
1890 class CallbackMethodStructTemplate: | |
1891 @staticmethod | |
1892 def append_prolog(line_list): | |
1893 pass | |
1894 | |
1895 @staticmethod | |
1896 def append_epilog(line_list): | |
1897 pass | |
1898 | |
1899 container_name = "jsonMessage" | |
1900 | |
1901 # Generates common code for event sending and callback response data sending
. | |
1902 @staticmethod | |
1903 def generate_send_method(parameters, event_name, domain_name, ad_hoc_type_wr
iter, decl_parameter_list, | |
1904 method_struct_template, | |
1905 generator_method_list, method_template, template_pa
rams): | |
1906 method_line_list = [] | |
1907 if parameters: | |
1908 method_struct_template.append_prolog(method_line_list) | |
1909 for json_parameter in parameters: | |
1910 parameter_name = json_parameter["name"] | |
1911 | |
1912 param_type_binding = Generator.resolve_param_type_and_generate_a
d_hoc(json_parameter, event_name, domain_name, ad_hoc_type_writer, "") | |
1913 | |
1914 raw_type = param_type_binding.reduce_to_raw_type() | |
1915 raw_type_binding = RawTypeBinding(raw_type) | |
1916 | |
1917 optional = bool(json_parameter.get("optional")) | |
1918 | |
1919 setter_type = raw_type.get_setter_name() | |
1920 | |
1921 type_model = param_type_binding.get_type_model() | |
1922 raw_type_model = raw_type_binding.get_type_model() | |
1923 if optional: | |
1924 type_model = type_model.get_optional() | |
1925 raw_type_model = raw_type_model.get_optional() | |
1926 | |
1927 annotated_type = type_model.get_input_param_type_text() | |
1928 mode_type_binding = param_type_binding | |
1929 | |
1930 decl_parameter_list.append("%s %s" % (annotated_type, parameter_
name)) | |
1931 | |
1932 setter_argument = raw_type_model.get_event_setter_expression_pat
tern() % parameter_name | |
1933 if mode_type_binding.get_setter_value_expression_pattern(): | |
1934 setter_argument = mode_type_binding.get_setter_value_express
ion_pattern() % setter_argument | |
1935 | |
1936 setter_code = " %s->set%s(\"%s\", %s);\n" % (method_struct_te
mplate.container_name, setter_type, parameter_name, setter_argument) | |
1937 if optional: | |
1938 setter_code = (" if (%s)\n " % parameter_name) + sette
r_code | |
1939 method_line_list.append(setter_code) | |
1940 | |
1941 method_struct_template.append_epilog(method_line_list) | |
1942 | |
1943 generator_method_list.append(method_template.substitute(None, | |
1944 domainName=domain_name, | |
1945 parameters=", ".join(decl_parameter_list), | |
1946 code="".join(method_line_list), **template_params)) | |
1947 | |
1948 @classmethod | |
1949 def resolve_param_type_and_generate_ad_hoc(cls, json_param, method_name, dom
ain_name, ad_hoc_type_writer, container_relative_name_prefix_param): | |
1950 param_name = json_param["name"] | |
1951 return cls.resolve_type_and_generate_ad_hoc(json_param, param_name, meth
od_name, domain_name, ad_hoc_type_writer, container_relative_name_prefix_param) | |
1952 | |
1953 @staticmethod | |
1954 def resolve_type_and_generate_ad_hoc(typable_element, element_name, method_n
ame, domain_name, ad_hoc_type_writer, container_relative_name_prefix_param): | |
1955 ad_hoc_type_list = [] | |
1956 | |
1957 class AdHocTypeContext: | |
1958 container_full_name_prefix = "<not yet defined>" | |
1959 container_relative_name_prefix = container_relative_name_prefix_para
m | |
1960 | |
1961 @staticmethod | |
1962 def get_type_name_fix(): | |
1963 class NameFix: | |
1964 class_name = Capitalizer.lower_camel_case_to_upper(element_n
ame) | |
1965 | |
1966 @staticmethod | |
1967 def output_comment(writer): | |
1968 writer.newline("// Named after parameter '%s' while gene
rating command/event %s.\n" % (element_name, method_name)) | |
1969 | |
1970 return NameFix | |
1971 | |
1972 @staticmethod | |
1973 def add_type(binding): | |
1974 ad_hoc_type_list.append(binding) | |
1975 | |
1976 type_binding = resolve_param_type(typable_element, domain_name, AdHocTyp
eContext) | |
1977 | |
1978 class InterfaceForwardListener: | |
1979 @staticmethod | |
1980 def add_type_data(type_data): | |
1981 pass | |
1982 | |
1983 class InterfaceResolveContext: | |
1984 forward_listener = InterfaceForwardListener | |
1985 | |
1986 for type in ad_hoc_type_list: | |
1987 type.resolve_inner(InterfaceResolveContext) | |
1988 | |
1989 class InterfaceGenerateContext: | |
1990 validator_writer = "not supported in InterfaceGenerateContext" | |
1991 cpp_writer = validator_writer | |
1992 | |
1993 for type in ad_hoc_type_list: | |
1994 generator = type.get_code_generator() | |
1995 if generator: | |
1996 generator.generate_type_builder(ad_hoc_type_writer, InterfaceGen
erateContext) | |
1997 | |
1998 return type_binding | |
1999 | |
2000 @staticmethod | |
2001 def process_types(type_map): | |
2002 output = Generator.type_builder_fragments | |
2003 | |
2004 class GenerateContext: | |
2005 validator_writer = Writer(Generator.validator_impl_list, "") | |
2006 cpp_writer = Writer(Generator.type_builder_impl_list, "") | |
2007 | |
2008 def generate_all_domains_code(out, type_data_callback): | |
2009 writer = Writer(out, "") | |
2010 for domain_data in type_map.domains(): | |
2011 namespace_declared = [] | |
2012 | |
2013 def namespace_lazy_generator(): | |
2014 if not namespace_declared: | |
2015 writer.newline("namespace ") | |
2016 writer.append(domain_data.name()) | |
2017 writer.append(" {\n") | |
2018 # What is a better way to change value from outer scope? | |
2019 namespace_declared.append(True) | |
2020 return writer | |
2021 | |
2022 for type_data in domain_data.types(): | |
2023 type_data_callback(type_data, namespace_lazy_generator) | |
2024 | |
2025 if namespace_declared: | |
2026 writer.append("} // ") | |
2027 writer.append(domain_data.name()) | |
2028 writer.append("\n\n") | |
2029 | |
2030 def create_type_builder_caller(generate_pass_id): | |
2031 def call_type_builder(type_data, writer_getter): | |
2032 code_generator = type_data.get_binding().get_code_generator() | |
2033 if code_generator and generate_pass_id == code_generator.get_gen
erate_pass_id(): | |
2034 writer = writer_getter() | |
2035 | |
2036 code_generator.generate_type_builder(writer, GenerateContext
) | |
2037 return call_type_builder | |
2038 | |
2039 generate_all_domains_code(output, create_type_builder_caller(TypeBuilder
Pass.MAIN)) | |
2040 | |
2041 Generator.type_builder_forwards.append("// Forward declarations.\n") | |
2042 | |
2043 def generate_forward_callback(type_data, writer_getter): | |
2044 if type_data in global_forward_listener.type_data_set: | |
2045 binding = type_data.get_binding() | |
2046 binding.get_code_generator().generate_forward_declaration(writer
_getter()) | |
2047 generate_all_domains_code(Generator.type_builder_forwards, generate_forw
ard_callback) | |
2048 | |
2049 Generator.type_builder_forwards.append("// End of forward declarations.\
n\n") | |
2050 | |
2051 Generator.type_builder_forwards.append("// Typedefs.\n") | |
2052 | |
2053 generate_all_domains_code(Generator.type_builder_forwards, create_type_b
uilder_caller(TypeBuilderPass.TYPEDEF)) | |
2054 | |
2055 Generator.type_builder_forwards.append("// End of typedefs.\n\n") | |
2056 | |
2057 | |
2058 def flatten_list(input): | |
2059 res = [] | |
2060 | |
2061 def fill_recursive(l): | |
2062 for item in l: | |
2063 if isinstance(item, list): | |
2064 fill_recursive(item) | |
2065 else: | |
2066 res.append(item) | |
2067 fill_recursive(input) | |
2068 return res | |
2069 | |
2070 def output_file(file_name): | |
2071 return open(file_name, "w") | |
2072 | |
2073 | |
2074 Generator.go() | |
2075 | |
2076 backend_h_file = output_file(output_dirname + "/InspectorBackendDispatcher.h") | |
2077 backend_cpp_file = output_file(output_dirname + "/InspectorBackendDispatcher.cpp
") | |
2078 | |
2079 frontend_h_file = output_file(output_dirname + "/InspectorFrontend.h") | |
2080 frontend_cpp_file = output_file(output_dirname + "/InspectorFrontend.cpp") | |
2081 | |
2082 typebuilder_h_file = output_file(output_dirname + "/InspectorTypeBuilder.h") | |
2083 typebuilder_cpp_file = output_file(output_dirname + "/InspectorTypeBuilder.cpp") | |
2084 | |
2085 | |
2086 backend_h_file.write(Templates.backend_h.substitute(None, | |
2087 virtualSetters="\n".join(Generator.backend_virtual_setters_list), | |
2088 agentInterfaces="".join(flatten_list(Generator.backend_agent_interface_list)
), | |
2089 methodNamesEnumContent="\n".join(Generator.method_name_enum_list))) | |
2090 | |
2091 backend_cpp_file.write(Templates.backend_cpp.substitute(None, | |
2092 constructorInit="\n".join(Generator.backend_constructor_init_list), | |
2093 setters="\n".join(Generator.backend_setters_list), | |
2094 fieldDeclarations="\n".join(Generator.backend_field_list), | |
2095 methodNameDeclarations="\n".join(Generator.backend_method_name_declaration_l
ist), | |
2096 methodNameDeclarationsIndex="\n".join(Generator.backend_method_name_declarat
ion_index_list), | |
2097 methods="\n".join(Generator.backend_method_implementation_list), | |
2098 methodDeclarations="\n".join(Generator.backend_method_declaration_list), | |
2099 messageHandlers="\n".join(Generator.method_handler_list))) | |
2100 | |
2101 frontend_h_file.write(Templates.frontend_h.substitute(None, | |
2102 fieldDeclarations="".join(Generator.frontend_class_field_lines), | |
2103 domainClassList="".join(Generator.frontend_domain_class_lines))) | |
2104 | |
2105 frontend_cpp_file.write(Templates.frontend_cpp.substitute(None, | |
2106 constructorInit="".join(Generator.frontend_constructor_init_list), | |
2107 methods="\n".join(Generator.frontend_method_list))) | |
2108 | |
2109 typebuilder_h_file.write(Templates.typebuilder_h.substitute(None, | |
2110 typeBuilders="".join(flatten_list(Generator.type_builder_fragments)), | |
2111 forwards="".join(Generator.type_builder_forwards), | |
2112 validatorIfdefName=VALIDATOR_IFDEF_NAME)) | |
2113 | |
2114 typebuilder_cpp_file.write(Templates.typebuilder_cpp.substitute(None, | |
2115 enumConstantValues=EnumConstants.get_enum_constant_code(), | |
2116 implCode="".join(flatten_list(Generator.type_builder_impl_list)), | |
2117 validatorCode="".join(flatten_list(Generator.validator_impl_list)), | |
2118 validatorIfdefName=VALIDATOR_IFDEF_NAME)) | |
2119 | |
2120 backend_h_file.close() | |
2121 backend_cpp_file.close() | |
2122 | |
2123 frontend_h_file.close() | |
2124 frontend_cpp_file.close() | |
2125 | |
2126 typebuilder_h_file.close() | |
2127 typebuilder_cpp_file.close() | |
OLD | NEW |