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