Changeset 103503 in webkit


Ignore:
Timestamp:
Dec 22, 2011 1:21:56 AM (12 years ago)
Author:
commit-queue@webkit.org
Message:

Web Inspector: CodeGeneratorInspector.py: generate anonymous types.
https://bugs.webkit.org/show_bug.cgi?id=74890

Patch by Peter Rybin <peter.rybin@gmail.com> on 2011-12-22
Reviewed by Yury Semikhatsky.

Anonymous types are generated. Forward declarations are generated.

In general it now generates C++ types for anonymous object types from
JSON. It takes a name from the type declaration site, usually a
parameter name. This all is explained in comments in generated file. Also
all generated types now refer to other generated types in setter
methods -- but this is commented out in generated code for now. All
necessary forward declarations are also added. Anonymous enums are
generated, but they are in comments too, because we didn't have
solution about form the enums should have in C++ API.

Internally:
The change reorganizes type bindings — a polymorphous "code generator"
object is factored out from binding.
A helper class Writer is added to allow generating code with ajustable
indentations and to support insertion points where additional code can
be inserted retroactively.
ForwardListener class is used for preparing necessary forward
declarations.
AdHocTypeContext conception is a speculative abstract class that is
needed wherever anonymous type can emerge.

  • inspector/CodeGeneratorInspector.py:

(fix_type_name.Result.output_comment):
(Writer.init):
(Writer.newline):
(Writer.append):
(Writer.newline_multiline):
(Writer.append_multiline):
(Writer.get_indented):
(Writer):
(Writer.insert_writer):
(TypeBindings.create_named_type_declaration.Helper.write_doc):
(TypeBindings.create_named_type_declaration.Helper):
(TypeBindings.create_named_type_declaration.Helper.add_to_forward_listener):
(TypeBindings.create_named_type_declaration):
(TypeBindings.create_ad_hoc_type_declaration.Helper.write_doc):
(TypeBindings.create_ad_hoc_type_declaration.Helper):
(TypeBindings.create_ad_hoc_type_declaration.Helper.add_to_forward_listener):
(TypeBindings.create_ad_hoc_type_declaration):
(TypeBindings.create_type_declaration_.EnumBinding.get_code_generator.CodeGenerator.generate_type_builder):
(TypeBindings.create_type_declaration_.EnumBinding.get_code_generator.CodeGenerator):
(TypeBindings.create_type_declaration_.EnumBinding.get_code_generator.CodeGenerator.register_use):
(TypeBindings.create_type_declaration_.EnumBinding.get_code_generator):
(TypeBindings.create_type_declaration_.PlainString.get_code_generator.CodeGenerator.generate_type_builder.String):
(TypeBindings.create_type_declaration_.PlainString.get_code_generator.CodeGenerator.generate_type_builder):
(TypeBindings.create_type_declaration_.PlainString.get_code_generator.CodeGenerator):
(TypeBindings.create_type_declaration_.PlainString.get_code_generator.CodeGenerator.register_use):
(TypeBindings.create_type_declaration_.PlainString.get_code_generator):
(TypeBindings.create_type_declaration_.PlainString.get_in_c_type_text.name):
(TypeBindings.create_type_declaration_.PlainString):
(TypeBindings.create_type_declaration_):
(TypeBindings.create_type_declaration_.ClassBinding.get_code_generator):
(TypeBindings.create_type_declaration_.ClassBinding.get_code_generator.CodeGenerator):
(TypeBindings.create_type_declaration_.ClassBinding.get_code_generator.CodeGenerator.generate_type_builder):
(AdHocTypeContextImpl.init):
(AdHocTypeContextImpl.get_type_name_fix.NameFix):
(AdHocTypeContextImpl.get_type_name_fix.NameFix.output_comment):
(AdHocTypeContextImpl.get_type_name_fix):
(AdHocTypeContextImpl):
(AdHocTypeContextImpl.call_generate_type_builder):
(generate_forward_declaration):
(register_use):
(get_in_c_type_text):
(reduce_to_raw_type):
(PlainObjectBinding.get_code_generator):
(CodeGenerator.generate_type_builder.AdHocTypeContext.get_type_name_fix.NameFix):
(CodeGenerator.generate_type_builder.AdHocTypeContext.get_type_name_fix.NameFix.output_comment):
(CodeGenerator.generate_type_builder.AdHocTypeContext.get_type_name_fix):
(CodeGenerator.generate_type_builder.AdHocTypeContext):
(CodeGenerator.generate_type_builder.AdHocTypeContext.call_generate_type_builder):
(CodeGenerator.generate_type_builder):
(CodeGenerator):
(CodeGenerator.register_use):
(RawTypesBinding.get_code_generator):
(RawTypesBinding.get_in_c_type_text):
(RawTypesBinding):
(RawTypesBinding.reduce_to_raw_type):
(TypeData.init):
(TypeData.get_json_type):
(resolve_param_type):
(Generator.go):
(Generator.process_event.NoOpForwardListener):
(Generator.process_event.NoOpForwardListener.add_type_data):
(Generator.process_event.AdHocTypeContext.get_type_name_fix.NameFix):
(Generator.process_event.AdHocTypeContext.get_type_name_fix.NameFix.output_comment):
(Generator.process_event.AdHocTypeContext.get_type_name_fix):
(Generator.process_event.AdHocTypeContext):
(Generator.process_event.AdHocTypeContext.call_generate_type_builder):
(Generator.process_event):
(Generator.process_types.ForwardListener):
(Generator.process_types.ForwardListener.add_type_data):
(Generator.process_types.generate_all_domains_code.namespace_lazy_generator):
(Generator.process_types.generate_all_domains_code):
(Generator.process_types.call_type_builder):
(Generator.process_types.generate_forward_callback):
(Generator):
(Generator.process_types):
(flatten_list.fill_recursive):
(flatten_list):

Location:
trunk/Source/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r103502 r103503  
     12011-12-22  Peter Rybin  <peter.rybin@gmail.com>
     2
     3        Web Inspector: CodeGeneratorInspector.py: generate anonymous types.
     4        https://bugs.webkit.org/show_bug.cgi?id=74890
     5
     6        Reviewed by Yury Semikhatsky.
     7
     8        Anonymous types are generated. Forward declarations are generated.
     9
     10        In general it now generates C++ types for anonymous object types from
     11        JSON. It takes a name from the type declaration site, usually a
     12        parameter name. This all is explained in comments in generated file. Also
     13        all generated types now refer to other generated types in setter
     14        methods -- but this is commented out in generated code for now. All
     15        necessary forward declarations are also added. Anonymous enums are
     16        generated, but they are in comments too, because we didn't have
     17        solution about form the enums should have in C++ API.
     18
     19        Internally:
     20        The change reorganizes type bindings — a polymorphous "code generator"
     21        object is factored out from binding.
     22        A helper class Writer is added to allow generating code with ajustable
     23        indentations and to support insertion points where additional code can
     24        be inserted retroactively.
     25        ForwardListener class is used for preparing necessary forward
     26        declarations.
     27        AdHocTypeContext conception is a speculative abstract class that is
     28        needed wherever anonymous type can emerge.
     29
     30        * inspector/CodeGeneratorInspector.py:
     31        (fix_type_name.Result.output_comment):
     32        (Writer.__init__):
     33        (Writer.newline):
     34        (Writer.append):
     35        (Writer.newline_multiline):
     36        (Writer.append_multiline):
     37        (Writer.get_indented):
     38        (Writer):
     39        (Writer.insert_writer):
     40        (TypeBindings.create_named_type_declaration.Helper.write_doc):
     41        (TypeBindings.create_named_type_declaration.Helper):
     42        (TypeBindings.create_named_type_declaration.Helper.add_to_forward_listener):
     43        (TypeBindings.create_named_type_declaration):
     44        (TypeBindings.create_ad_hoc_type_declaration.Helper.write_doc):
     45        (TypeBindings.create_ad_hoc_type_declaration.Helper):
     46        (TypeBindings.create_ad_hoc_type_declaration.Helper.add_to_forward_listener):
     47        (TypeBindings.create_ad_hoc_type_declaration):
     48        (TypeBindings.create_type_declaration_.EnumBinding.get_code_generator.CodeGenerator.generate_type_builder):
     49        (TypeBindings.create_type_declaration_.EnumBinding.get_code_generator.CodeGenerator):
     50        (TypeBindings.create_type_declaration_.EnumBinding.get_code_generator.CodeGenerator.register_use):
     51        (TypeBindings.create_type_declaration_.EnumBinding.get_code_generator):
     52        (TypeBindings.create_type_declaration_.PlainString.get_code_generator.CodeGenerator.generate_type_builder.String):
     53        (TypeBindings.create_type_declaration_.PlainString.get_code_generator.CodeGenerator.generate_type_builder):
     54        (TypeBindings.create_type_declaration_.PlainString.get_code_generator.CodeGenerator):
     55        (TypeBindings.create_type_declaration_.PlainString.get_code_generator.CodeGenerator.register_use):
     56        (TypeBindings.create_type_declaration_.PlainString.get_code_generator):
     57        (TypeBindings.create_type_declaration_.PlainString.get_in_c_type_text.name):
     58        (TypeBindings.create_type_declaration_.PlainString):
     59        (TypeBindings.create_type_declaration_):
     60        (TypeBindings.create_type_declaration_.ClassBinding.get_code_generator):
     61        (TypeBindings.create_type_declaration_.ClassBinding.get_code_generator.CodeGenerator):
     62        (TypeBindings.create_type_declaration_.ClassBinding.get_code_generator.CodeGenerator.generate_type_builder):
     63        (AdHocTypeContextImpl.__init__):
     64        (AdHocTypeContextImpl.get_type_name_fix.NameFix):
     65        (AdHocTypeContextImpl.get_type_name_fix.NameFix.output_comment):
     66        (AdHocTypeContextImpl.get_type_name_fix):
     67        (AdHocTypeContextImpl):
     68        (AdHocTypeContextImpl.call_generate_type_builder):
     69        (generate_forward_declaration):
     70        (register_use):
     71        (get_in_c_type_text):
     72        (reduce_to_raw_type):
     73        (PlainObjectBinding.get_code_generator):
     74        (CodeGenerator.generate_type_builder.AdHocTypeContext.get_type_name_fix.NameFix):
     75        (CodeGenerator.generate_type_builder.AdHocTypeContext.get_type_name_fix.NameFix.output_comment):
     76        (CodeGenerator.generate_type_builder.AdHocTypeContext.get_type_name_fix):
     77        (CodeGenerator.generate_type_builder.AdHocTypeContext):
     78        (CodeGenerator.generate_type_builder.AdHocTypeContext.call_generate_type_builder):
     79        (CodeGenerator.generate_type_builder):
     80        (CodeGenerator):
     81        (CodeGenerator.register_use):
     82        (RawTypesBinding.get_code_generator):
     83        (RawTypesBinding.get_in_c_type_text):
     84        (RawTypesBinding):
     85        (RawTypesBinding.reduce_to_raw_type):
     86        (TypeData.__init__):
     87        (TypeData.get_json_type):
     88        (resolve_param_type):
     89        (Generator.go):
     90        (Generator.process_event.NoOpForwardListener):
     91        (Generator.process_event.NoOpForwardListener.add_type_data):
     92        (Generator.process_event.AdHocTypeContext.get_type_name_fix.NameFix):
     93        (Generator.process_event.AdHocTypeContext.get_type_name_fix.NameFix.output_comment):
     94        (Generator.process_event.AdHocTypeContext.get_type_name_fix):
     95        (Generator.process_event.AdHocTypeContext):
     96        (Generator.process_event.AdHocTypeContext.call_generate_type_builder):
     97        (Generator.process_event):
     98        (Generator.process_types.ForwardListener):
     99        (Generator.process_types.ForwardListener.add_type_data):
     100        (Generator.process_types.generate_all_domains_code.namespace_lazy_generator):
     101        (Generator.process_types.generate_all_domains_code):
     102        (Generator.process_types.call_type_builder):
     103        (Generator.process_types.generate_forward_callback):
     104        (Generator):
     105        (Generator.process_types):
     106        (flatten_list.fill_recursive):
     107        (flatten_list):
     108
    11092011-12-22  Hans Muller  <hmuller@adobe.com>
    2110
  • trunk/Source/WebCore/inspector/CodeGeneratorInspector.py

    r103389 r103503  
    468468
    469469            @staticmethod
    470             def output_comment(output):
    471                 output.append("// Type originally was named '%s'.\n" % json_name)
     470            def output_comment(writer):
     471                writer.newline("// Type originally was named '%s'.\n" % json_name)
    472472    else:
    473473
     
    476476
    477477            @staticmethod
    478             def output_comment(output):
     478            def output_comment(writer):
    479479                pass
    480480
    481481    return Result
    482482
     483
     484class Writer:
     485    def __init__(self, output, indent):
     486        self.output = output
     487        self.indent = indent
     488
     489    def newline(self, str):
     490        if (self.indent):
     491            self.output.append(self.indent)
     492        self.output.append(str)
     493
     494    def append(self, str):
     495        self.output.append(str)
     496
     497    def newline_multiline(self, str):
     498        parts = str.split('\n')
     499        self.newline(parts[0])
     500        for p in parts[1:]:
     501            self.output.append('\n')
     502            if p:
     503                self.newline(p)
     504
     505    def append_multiline(self, str):
     506        parts = str.split('\n')
     507        self.append(parts[0])
     508        for p in parts[1:]:
     509            self.output.append('\n')
     510            if p:
     511                self.newline(p)
     512
     513    def get_indented(self, additional_indent):
     514        return Writer(self.output, self.indent + additional_indent)
     515
     516    def insert_writer(self, additional_indent):
     517        new_output = []
     518        self.output.append(new_output)
     519        return Writer(new_output, self.indent + additional_indent)
    483520
    484521
    485522class TypeBindings:
    486523    @staticmethod
    487     def create_for_named_type_declaration(json_type, context_domain_name):
     524    def create_named_type_declaration(json_typable, context_domain_name, type_data):
     525        json_type = type_data.get_json_type()
     526
     527        class Helper:
     528            is_ad_hoc = False
     529
     530            @staticmethod
     531            def write_doc(writer):
     532                if "description" in json_type:
     533                    writer.newline("/* ")
     534                    writer.append(json_type["description"])
     535                    writer.append(" */\n")
     536
     537            @staticmethod
     538            def add_to_forward_listener(forward_listener):
     539                forward_listener.add_type_data(type_data)
     540
     541
    488542        fixed_type_name = fix_type_name(json_type["id"])
    489 
    490         def write_doc(output):
    491             if "description" in json_type:
    492                 output.append("/* ")
    493                 output.append(json_type["description"])
    494                 output.append(" */\n")
    495 
    496         if json_type["type"] == "string":
    497             if "enum" in json_type:
     543        return TypeBindings.create_type_declaration_(json_typable, context_domain_name, fixed_type_name, Helper)
     544
     545    @staticmethod
     546    def create_ad_hoc_type_declaration(json_typable, context_domain_name, ad_hoc_type_context):
     547        class Helper:
     548            is_ad_hoc = True
     549
     550            @staticmethod
     551            def write_doc(writer):
     552                pass
     553
     554            @staticmethod
     555            def add_to_forward_listener(forward_listener):
     556                pass
     557        fixed_type_name = ad_hoc_type_context.get_type_name_fix()
     558        return TypeBindings.create_type_declaration_(json_typable, context_domain_name, fixed_type_name, Helper)
     559
     560    @staticmethod
     561    def create_type_declaration_(json_typable, context_domain_name, fixed_type_name, helper):
     562        if json_typable["type"] == "string":
     563            if "enum" in json_typable:
    498564
    499565                class EnumBinding:
    500566                    @staticmethod
    501                     def generate_type_builder(output, forward_listener):
    502                         enum = json_type["enum"]
    503                         write_doc(output)
    504                         enum_name = fixed_type_name.class_name
    505                         fixed_type_name.output_comment(output)
    506                         output.append("namespace ")
    507                         output.append(enum_name)
    508                         output.append(" {\n")
    509                         for enum_item in enum:
    510                             item_c_name = enum_item.replace('-', '_')
    511                             output.append("const char* const ")
    512                             output.append(Capitalizer.upper_camel_case_to_lower(item_c_name))
    513                             output.append(" = \"")
    514                             output.append(enum_item)
    515                             output.append("\";\n")
    516                         output.append("} // namespace ")
    517                         output.append(enum_name)
    518                         output.append("\n\n")
     567                    def get_code_generator():
     568                        #FIXME: generate ad-hoc enums too once we figure out how to better implement them in C++.
     569                        comment_out = helper.is_ad_hoc
     570
     571                        class CodeGenerator:
     572                            @staticmethod
     573                            def generate_type_builder(writer, forward_listener):
     574                                if comment_out:
     575                                    writer = writer.get_indented("// ")
     576                                enum = json_typable["enum"]
     577                                helper.write_doc(writer)
     578                                enum_name = fixed_type_name.class_name
     579                                fixed_type_name.output_comment(writer)
     580                                writer.newline("namespace ")
     581                                writer.append(enum_name)
     582                                writer.append(" {\n")
     583                                for enum_item in enum:
     584                                    item_c_name = enum_item.replace('-', '_')
     585                                    writer.newline("const char* const ")
     586                                    writer.append(Capitalizer.upper_camel_case_to_lower(item_c_name))
     587                                    writer.append(" = \"")
     588                                    writer.append(enum_item)
     589                                    writer.append("\";\n")
     590                                writer.newline("} // namespace ")
     591                                writer.append(enum_name)
     592                                writer.append("\n\n")
     593
     594                            @staticmethod
     595                            def register_use(forward_listener):
     596                                pass
     597
     598                        return CodeGenerator
    519599
    520600                    @classmethod
     
    531611                class PlainString:
    532612                    @staticmethod
    533                     def generate_type_builder(output, forward_listener):
    534                         write_doc(output)
    535                         fixed_type_name.output_comment(output)
    536                         output.append("typedef String ")
    537                         output.append(fixed_type_name.class_name)
    538                         output.append(";\n\n")
     613                    def get_code_generator():
     614                        if helper.is_ad_hoc:
     615                            return
     616
     617                        class CodeGenerator:
     618                            @staticmethod
     619                            def generate_type_builder(writer, forward_listener):
     620                                helper.write_doc(writer)
     621                                fixed_type_name.output_comment(writer)
     622                                writer.newline("typedef String ")
     623                                writer.append(fixed_type_name.class_name)
     624                                writer.append(";\n\n")
     625
     626                            @staticmethod
     627                            def register_use(forward_listener):
     628                                pass
     629
     630                        return CodeGenerator
    539631
    540632                    @staticmethod
     
    544636                    @classmethod
    545637                    def get_in_c_type_text(cls, optional):
     638                        #FIXME: return a typedef name instead.
    546639                        return cls.reduce_to_raw_type().get_c_param_type(ParamType.EVENT, optional).get_text()
    547640
    548641                return PlainString
    549642
    550         elif json_type["type"] == "object":
    551             if "properties" in json_type:
     643        elif json_typable["type"] == "object":
     644            if "properties" in json_typable:
    552645
    553646                class ClassBinding:
    554                     class_name_ = json_type["id"]
    555 
    556647                    @staticmethod
    557                     def generate_type_builder(output, forward_listener):
    558                         write_doc(output)
    559                         class_name = fixed_type_name.class_name
    560                         fixed_type_name.output_comment(output)
    561                         output.append("class ")
    562                         output.append(class_name)
    563                         output.append(" : public InspectorObject {\n")
    564                         output.append("public:\n")
    565 
    566                         properties = json_type["properties"]
    567                         main_properties = []
    568                         optional_properties = []
    569                         for p in properties:
    570                             if "optional" in p and p["optional"]:
    571                                 optional_properties.append(p)
    572                             else:
    573                                 main_properties.append(p)
    574 
    575                         output.append(
     648                    def get_code_generator():
     649                        class CodeGenerator:
     650                            @classmethod
     651                            def generate_type_builder(cls, writer, forward_listener):
     652                                helper.write_doc(writer)
     653                                class_name = fixed_type_name.class_name
     654                                fixed_type_name.output_comment(writer)
     655                                writer.newline("class ")
     656                                writer.append(class_name)
     657                                writer.append(" : public InspectorObject {\n")
     658                                writer.newline("public:\n")
     659                                ad_hoc_type_writer = writer.insert_writer("    ")
     660
     661                                properties = json_typable["properties"]
     662                                main_properties = []
     663                                optional_properties = []
     664                                for p in properties:
     665                                    if "optional" in p and p["optional"]:
     666                                        optional_properties.append(p)
     667                                    else:
     668                                        main_properties.append(p)
     669
     670                                writer.newline_multiline(
    576671"""    enum {
    577672        NO_FIELDS_SET = 0,
    578673""")
    579674
    580                         state_enum_items = []
    581                         if len(main_properties) > 0:
    582                             pos = 0
    583                             for p in main_properties:
    584                                 item_name = Capitalizer.camel_case_to_capitalized_with_underscores(p["name"]) + "_SET"
    585                                 state_enum_items.append(item_name)
    586                                 output.append("        %s = 1 << %s,\n" % (item_name, pos))
    587                                 pos += 1
    588                             all_fields_set_value = "(" + (" | ".join(state_enum_items)) + ")"
    589                         else:
    590                             all_fields_set_value = "0"
    591 
    592                         output.append(
     675                                state_enum_items = []
     676                                if len(main_properties) > 0:
     677                                    pos = 0
     678                                    for p in main_properties:
     679                                        item_name = Capitalizer.camel_case_to_capitalized_with_underscores(p["name"]) + "_SET"
     680                                        state_enum_items.append(item_name)
     681                                        writer.newline("        %s = 1 << %s,\n" % (item_name, pos))
     682                                        pos += 1
     683                                    all_fields_set_value = "(" + (" | ".join(state_enum_items)) + ")"
     684                                else:
     685                                    all_fields_set_value = "0"
     686
     687                                writer.newline_multiline(
    593688"""        ALL_FIELDS_SET = %s
    594689    };
     
    613708""" % (all_fields_set_value, class_name, class_name))
    614709
    615                         pos = 0
    616                         for prop in main_properties:
    617                             prop_name = prop["name"]
    618                             param_raw_type = resolve_param_raw_type(prop, context_domain_name)
    619                             output.append("""
     710                                pos = 0
     711                                for prop in main_properties:
     712                                    prop_name = prop["name"]
     713
     714                                    ad_hoc_type_context = cls.AdHocTypeContextImpl(prop_name, fixed_type_name.class_name, ad_hoc_type_writer, forward_listener)
     715
     716                                    param_type_binding = resolve_param_type(prop, context_domain_name, ad_hoc_type_context)
     717                                    param_raw_type = param_type_binding.reduce_to_raw_type()
     718                                    annotated_type = get_annotated_type_text(param_raw_type.get_c_param_type(ParamType.TYPE_BUILDER_OUTPUT, False).get_text(),
     719                                        param_type_binding.get_in_c_type_text(False))
     720                                    writer.newline_multiline("""
    620721        Builder<STATE | %s>& set%s(%s value)
    621722        {
     
    625726        }
    626727"""
    627                             % (state_enum_items[pos],
    628                                Capitalizer.lower_camel_case_to_upper(prop_name),
    629                                param_raw_type.get_c_param_type(ParamType.TYPE_BUILDER_OUTPUT, False).get_text(),
    630                                state_enum_items[pos], prop_name,
    631                                param_raw_type.get_setter_name(), prop_name, state_enum_items[pos]))
    632 
    633                             pos += 1
    634 
    635                         output.append("""
     728                                    % (state_enum_items[pos],
     729                                       Capitalizer.lower_camel_case_to_upper(prop_name),
     730                                       annotated_type,
     731                                       state_enum_items[pos], prop_name,
     732                                       param_raw_type.get_setter_name(), prop_name, state_enum_items[pos]))
     733
     734                                    pos += 1
     735
     736                                    code_generator = param_type_binding.get_code_generator()
     737                                    if code_generator:
     738                                        code_generator.register_use(forward_listener)
     739
     740                                writer.newline_multiline("""
    636741        operator RefPtr<%s>& ()
    637742        {
     
    647752
    648753"""
    649                         % (class_name, class_name, class_name, class_name))
    650 
    651                         output.append("    /*\n")
    652                         output.append("     * Synthetic constructor:\n")
    653                         output.append("     * RefPtr<%s> result = %s::create()" % (class_name, class_name))
    654                         for prop in main_properties:
    655                             output.append("\n     *     .set%s(...)" % Capitalizer.lower_camel_case_to_upper(prop["name"]))
    656                         output.append(";\n     */\n")
    657 
    658                         output.append(
     754                                % (class_name, class_name, class_name, class_name))
     755
     756                                writer.newline("    /*\n")
     757                                writer.newline("     * Synthetic constructor:\n")
     758                                writer.newline("     * RefPtr<%s> result = %s::create()" % (class_name, class_name))
     759                                for prop in main_properties:
     760                                    writer.append_multiline("\n     *     .set%s(...)" % Capitalizer.lower_camel_case_to_upper(prop["name"]))
     761                                writer.append_multiline(";\n     */\n")
     762
     763                                writer.newline_multiline(
    659764"""    static Builder<NO_FIELDS_SET> create()
    660765    {
     
    663768""" % class_name)
    664769
    665                         for prop in optional_properties:
    666                             param_raw_type = resolve_param_raw_type(prop, context_domain_name)
    667                             setter_name = "set%s" % Capitalizer.lower_camel_case_to_upper(prop["name"])
    668                             output.append("\n    void %s" % setter_name)
    669                             output.append("(%s value)\n" % param_raw_type.get_c_param_type(ParamType.TYPE_BUILDER_OUTPUT, False).get_text())
    670                             output.append("    {\n")
    671                             output.append("        this->set%s(\"%s\", value);\n" % (param_raw_type.get_setter_name(), prop["name"]))
    672                             output.append("    }\n")
    673 
    674                             if setter_name in INSPECTOR_OBJECT_SETTER_NAMES:
    675                                 output.append("    using InspectorObject::%s;\n\n" % setter_name)
    676 
    677                         output.append("};\n\n")
     770                                for prop in optional_properties:
     771                                    prop_name = prop["name"]
     772                                    ad_hoc_type_context = cls.AdHocTypeContextImpl(prop_name, fixed_type_name.class_name, ad_hoc_type_writer, forward_listener)
     773
     774                                    param_type_binding = resolve_param_type(prop, context_domain_name, ad_hoc_type_context)
     775                                    setter_name = "set%s" % Capitalizer.lower_camel_case_to_upper(prop_name)
     776                                    writer.append_multiline("\n    void %s" % setter_name)
     777                                    annotated_type = get_annotated_type_text(param_type_binding.reduce_to_raw_type().get_c_param_type(ParamType.TYPE_BUILDER_OUTPUT, False).get_text(),
     778                                        param_type_binding.get_in_c_type_text(False))
     779                                    writer.append("(%s value)\n" % annotated_type)
     780                                    writer.newline("    {\n")
     781                                    writer.newline("        this->set%s(\"%s\", value);\n" % (param_type_binding.reduce_to_raw_type().get_setter_name(), prop["name"]))
     782                                    writer.newline("    }\n")
     783
     784                                    code_generator = param_type_binding.get_code_generator()
     785                                    if code_generator:
     786                                        code_generator.register_use(forward_listener)
     787
     788                                    if setter_name in INSPECTOR_OBJECT_SETTER_NAMES:
     789                                        writer.newline("    using InspectorObject::%s;\n\n" % setter_name)
     790
     791                                writer.newline("};\n\n")
     792
     793                            class AdHocTypeContextImpl:
     794                                def __init__(self, property_name, class_name, writer, forward_listener):
     795                                    self.property_name = property_name
     796                                    self.class_name = class_name
     797                                    self.writer = writer
     798                                    self.forward_listener = forward_listener
     799
     800                                def get_type_name_fix(self):
     801                                    class NameFix:
     802                                        class_name = Capitalizer.lower_camel_case_to_upper(self.property_name)
     803
     804                                        @staticmethod
     805                                        def output_comment(writer):
     806                                            writer.newline("// Named after property name '%s' while generating %s.\n" % (self.property_name, self.class_name))
     807
     808                                    return NameFix
     809
     810                                def call_generate_type_builder(self, code_generator):
     811                                    code_generator.generate_type_builder(self.writer, self.forward_listener)
     812
     813                            @staticmethod
     814                            def generate_forward_declaration(writer):
     815                                class_name = fixed_type_name.class_name
     816                                writer.newline("class ")
     817                                writer.append(class_name)
     818                                writer.append(";\n")
     819
     820                            @staticmethod
     821                            def register_use(forward_listener):
     822                                helper.add_to_forward_listener(forward_listener)
     823
     824                        return CodeGenerator
    678825
    679826                    @classmethod
    680827                    def get_in_c_type_text(cls, optional):
    681                         return "PassRefPtr<TypeBuilder::" + context_domain_name + "::" + cls.class_name_ + ">"
     828                        return "PassRefPtr<TypeBuilder::" + context_domain_name + "::" + fixed_type_name.class_name + ">"
    682829
    683830                    @staticmethod
     
    685832                        return RawTypes.Object
    686833
    687                         output.append("};\n\n")
    688834                return ClassBinding
    689835            else:
     
    691837                class PlainObjectBinding:
    692838                    @staticmethod
    693                     def generate_type_builder(output, forward_listener):
    694                         # No-op
     839                    def get_code_generator():
    695840                        pass
    696841
     
    704849
    705850                return PlainObjectBinding
     851        elif json_typable["type"] == "array":
     852            if "items" in json_typable:
     853
     854                class CodeGenerator:
     855                    @staticmethod
     856                    def generate_type_builder(writer, forward_listener):
     857
     858                        class AdHocTypeContext:
     859                            @staticmethod
     860                            def get_type_name_fix():
     861                                class NameFix:
     862                                    class_name = fixed_type_name.class_name + "Item"
     863
     864                                    @staticmethod
     865                                    def output_comment(writer):
     866                                        fixed_type_name.output_comment(writer)
     867                                        writer.newline("// Named as an item of array.\n")
     868
     869                                return NameFix
     870
     871                            @staticmethod
     872                            def call_generate_type_builder(code_generator):
     873                                code_generator.generate_type_builder(writer, forward_listener)
     874
     875                        resolve_param_type(json_typable["items"], context_domain_name, AdHocTypeContext)
     876
     877                    @staticmethod
     878                    def register_use(forward_listener):
     879                        pass
     880
     881                default_binding_code_generator = CodeGenerator
     882
    706883        else:
    707             raw_type = RawTypes.get(json_type["type"])
    708 
    709             class RawTypesBinding:
    710                 @staticmethod
    711                 def generate_type_builder(output, forward_listener):
    712                     # No-op
    713                     pass
    714 
    715                 @classmethod
    716                 def get_in_c_type_text(cls, optional):
    717                     return cls.reduce_to_raw_type().get_c_param_type(ParamType.EVENT, optional).get_text()
    718 
    719                 @staticmethod
    720                 def reduce_to_raw_type():
    721                     return raw_type
    722 
    723             return RawTypesBinding
     884            default_binding_code_generator = None
     885
     886        raw_type = RawTypes.get(json_typable["type"])
     887
     888        class RawTypesBinding:
     889            @staticmethod
     890            def get_code_generator():
     891                return default_binding_code_generator
     892
     893            @classmethod
     894            def get_in_c_type_text(cls, optional):
     895                return cls.reduce_to_raw_type().get_c_param_type(ParamType.EVENT, optional).get_text()
     896
     897            @staticmethod
     898            def reduce_to_raw_type():
     899                return raw_type
     900
     901        return RawTypesBinding
    724902
    725903
     
    736914        raw_type = RawTypes.get(json_type_name)
    737915        self.raw_type_ = raw_type
    738         self.binding_ = TypeBindings.create_for_named_type_declaration(json_type, json_domain["domain"])
     916        self.binding_ = TypeBindings.create_named_type_declaration(json_type, json_domain["domain"], self)
    739917
    740918    def get_raw_type(self):
     
    743921    def get_binding(self):
    744922        return self.binding_
     923
     924    def get_json_type(self):
     925        return self.json_type_
    745926
    746927
     
    787968
    788969
    789 def resolve_param_type(json_parameter, scope_domain_name):
     970def resolve_param_type(json_parameter, scope_domain_name, ad_hoc_type_context):
    790971    if "$ref" in json_parameter:
    791972        json_ref = json_parameter["$ref"]
     
    793974        return type_data.get_binding()
    794975    elif "type" in json_parameter:
    795         json_type = json_parameter["type"]
    796         raw_type = RawTypes.get(json_type)
    797 
    798         class RawTypeBinding:
    799             @staticmethod
    800             def reduce_to_raw_type():
    801                 return raw_type
    802 
    803             @staticmethod
    804             def get_in_c_type_text(optional):
    805                 return raw_type.get_c_param_type(ParamType.EVENT, optional).get_text()
    806 
    807         return RawTypeBinding
     976        result = TypeBindings.create_ad_hoc_type_declaration(json_parameter, scope_domain_name, ad_hoc_type_context)
     977        code_generator = result.get_code_generator()
     978        if code_generator:
     979            ad_hoc_type_context.call_generate_type_builder(code_generator)
     980        return result
    808981    else:
    809982        raise Exception("Unknown type")
     
    9261099
    9271100namespace TypeBuilder {
     1101${forwards}
    9281102${typeBuilders}
    9291103} // namespace TypeBuilder
     
    14141588    frontend_constructor_init_list = []
    14151589    type_builder_fragments = []
     1590    type_builder_forwards = []
    14161591
    14171592    @staticmethod
     
    14601635                domainClassName=domain_name,
    14611636                domainFieldName=domain_name_lower,
    1462                 frontendDomainMethodDeclarations=join(frontend_method_declaration_lines, "")))
     1637                frontendDomainMethodDeclarations=join(flatten_list(frontend_method_declaration_lines), "")))
    14631638
    14641639            if "commands" in json_domain:
     
    15051680    @staticmethod
    15061681    def process_event(json_event, domain_name, frontend_method_declaration_lines):
     1682        class NoOpForwardListener:
     1683            @staticmethod
     1684            def add_type_data(type_data):
     1685                pass
     1686
    15071687        event_name = json_event["name"]
    15081688        parameter_list = []
    15091689        method_line_list = []
    15101690        backend_js_event_param_list = []
     1691        ad_hoc_type_output = []
     1692        frontend_method_declaration_lines.append(ad_hoc_type_output)
     1693        ad_hoc_type_writer = Writer(ad_hoc_type_output, "    ")
    15111694        if "parameters" in json_event:
    15121695            method_line_list.append("    RefPtr<InspectorObject> paramsObject = InspectorObject::create();\n")
     
    15251708                optional = optional_mask and json_optional
    15261709
    1527                 param_type_binding = resolve_param_type(json_parameter, domain_name)
     1710                class AdHocTypeContext:
     1711                    @staticmethod
     1712                    def get_type_name_fix():
     1713                        class NameFix:
     1714                            class_name = Capitalizer.lower_camel_case_to_upper(parameter_name)
     1715
     1716                            @staticmethod
     1717                            def output_comment(writer):
     1718                                writer.newline("// Named after parameter name '%s' while generating event %s.\n" % (parameter_name, event_name))
     1719
     1720                        return NameFix
     1721
     1722                    @staticmethod
     1723                    def call_generate_type_builder(code_generator):
     1724                        code_generator.generate_type_builder(ad_hoc_type_writer, NoOpForwardListener)
     1725
     1726                param_type_binding = resolve_param_type(json_parameter, domain_name, AdHocTypeContext)
    15281727
    15291728                annotated_type = get_annotated_type_text(c_type.get_text(), param_type_binding.get_in_c_type_text(json_optional))
     
    16531852
    16541853        class ForwardListener:
    1655             pass
    1656 
    1657         for domain_data in type_map.domains():
    1658 
    1659             domain_fixes = DomainNameFixes.get_fixed_data(domain_data.name())
    1660             domain_guard = domain_fixes.get_guard()
    1661 
    1662             if domain_guard:
    1663                 domain_guard.generate_open(output)
    1664 
    1665             output.append("namespace ")
    1666             output.append(domain_data.name())
    1667             output.append(" {\n")
    1668             for type_data in domain_data.types():
    1669                 type_data.get_binding().generate_type_builder(output, ForwardListener)
    1670 
    1671             output.append("} // ")
    1672             output.append(domain_data.name())
    1673             output.append("\n\n")
    1674 
    1675             if domain_guard:
    1676                 domain_guard.generate_close(output)
     1854            type_data_set = set()
     1855            already_declared_set = set()
     1856
     1857            @classmethod
     1858            def add_type_data(cls, type_data):
     1859                if type_data not in cls.already_declared_set:
     1860                    cls.type_data_set.add(type_data)
     1861
     1862        def generate_all_domains_code(out, type_data_callback):
     1863            writer = Writer(out, "")
     1864            for domain_data in type_map.domains():
     1865                domain_fixes = DomainNameFixes.get_fixed_data(domain_data.name())
     1866                domain_guard = domain_fixes.get_guard()
     1867
     1868                namespace_declared = []
     1869
     1870                def namespace_lazy_generator():
     1871                    if not namespace_declared:
     1872                        if domain_guard:
     1873                            domain_guard.generate_open(out)
     1874                        writer.newline("namespace ")
     1875                        writer.append(domain_data.name())
     1876                        writer.append(" {\n")
     1877                        # What is a better way to change value from outer scope?
     1878                        namespace_declared.append(True)
     1879                    return writer
     1880
     1881                for type_data in domain_data.types():
     1882                    type_data_callback(type_data, namespace_lazy_generator)
     1883
     1884                if namespace_declared:
     1885                    writer.append("} // ")
     1886                    writer.append(domain_data.name())
     1887                    writer.append("\n\n")
     1888
     1889                    if domain_guard:
     1890                        domain_guard.generate_close(out)
     1891
     1892        def call_type_builder(type_data, writer_getter):
     1893            # Do not generate forwards for this type any longer.
     1894            ForwardListener.already_declared_set.add(type_data)
     1895
     1896            code_generator = type_data.get_binding().get_code_generator()
     1897            # Call lazy getter even if we don't generat anything.
     1898            writer = writer_getter()
     1899            if code_generator:
     1900                code_generator.generate_type_builder(writer, ForwardListener)
     1901
     1902        generate_all_domains_code(output, call_type_builder)
     1903
     1904        Generator.type_builder_forwards.append("// Forward declarations.\n")
     1905
     1906        def generate_forward_callback(type_data, writer_getter):
     1907            if type_data in ForwardListener.type_data_set:
     1908                binding = type_data.get_binding()
     1909                binding.get_code_generator().generate_forward_declaration(writer_getter())
     1910        generate_all_domains_code(Generator.type_builder_forwards, generate_forward_callback)
     1911
     1912        Generator.type_builder_forwards.append("// End of forward declarations.\n")
     1913
     1914
     1915def flatten_list(input):
     1916    res = []
     1917
     1918    def fill_recursive(l):
     1919        for item in l:
     1920            if isinstance(item, list):
     1921                fill_recursive(item)
     1922            else:
     1923                res.append(item)
     1924    fill_recursive(input)
     1925    return res
     1926
    16771927
    16781928Generator.go()
     
    16901940         fieldDeclarations=join(Generator.frontend_class_field_lines, ""),
    16911941         domainClassList=join(Generator.frontend_domain_class_lines, ""),
    1692          typeBuilders=join(Generator.type_builder_fragments, "")))
     1942         typeBuilders=join(flatten_list(Generator.type_builder_fragments), ""),
     1943         forwards=join(Generator.type_builder_forwards, "")))
    16931944
    16941945backend_h_file.write(Templates.backend_h.substitute(None,
Note: See TracChangeset for help on using the changeset viewer.