Home | History | Annotate | Download | only in scripts
      1 #!/usr/bin/env python
      2 # Copyright (C) 2013 Google Inc. All rights reserved.
      3 #
      4 # Redistribution and use in source and binary forms, with or without
      5 # modification, are permitted provided that the following conditions are
      6 # met:
      7 #
      8 #     * Redistributions of source code must retain the above copyright
      9 # notice, this list of conditions and the following disclaimer.
     10 #     * Redistributions in binary form must reproduce the above
     11 # copyright notice, this list of conditions and the following disclaimer
     12 # in the documentation and/or other materials provided with the
     13 # distribution.
     14 #     * Neither the name of Google Inc. nor the names of its
     15 # contributors may be used to endorse or promote products derived from
     16 # this software without specific prior written permission.
     17 #
     18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 
     30 import os.path
     31 import sys
     32 
     33 import in_generator
     34 import license
     35 import name_utilities
     36 import template_expander
     37 
     38 
     39 HEADER_TEMPLATE = """%(license)s
     40 
     41 #ifndef %(namespace)s%(suffix)sHeaders_h
     42 #define %(namespace)s%(suffix)sHeaders_h
     43 %(base_header_for_suffix)s
     44 %(includes)s
     45 
     46 #endif // %(namespace)s%(suffix)sHeaders_h
     47 """
     48 
     49 
     50 def case_insensitive_matching(name):
     51     return (name == ('HTMLEvents')
     52             or name == 'Event'
     53             or name == 'Events'
     54             or name.startswith('UIEvent')
     55             or name.startswith('CustomEvent')
     56             or name.startswith('MouseEvent'))
     57 
     58 
     59 class EventFactoryWriter(in_generator.Writer):
     60     defaults = {
     61         'ImplementedAs': None,
     62         'Conditional': None,
     63         'RuntimeEnabled': None,
     64     }
     65     default_parameters = {
     66         'namespace': '',
     67         'suffix': '',
     68     }
     69     filters = {
     70         'cpp_name': name_utilities.cpp_name,
     71         'enable_conditional': name_utilities.enable_conditional_if_endif,
     72         'lower_first': name_utilities.lower_first,
     73         'case_insensitive_matching': case_insensitive_matching,
     74         'script_name': name_utilities.script_name,
     75     }
     76 
     77     def __init__(self, in_file_path):
     78         super(EventFactoryWriter, self).__init__(in_file_path)
     79         self.namespace = self.in_file.parameters['namespace'].strip('"')
     80         self.suffix = self.in_file.parameters['suffix'].strip('"')
     81         self._validate_entries()
     82         self._outputs = {(self.namespace + self.suffix + "Headers.h"): self.generate_headers_header,
     83                          (self.namespace + self.suffix + ".cpp"): self.generate_implementation,
     84                         }
     85 
     86     def _validate_entries(self):
     87         # If there is more than one entry with the same script name, only the first one will ever
     88         # be hit in practice, and so we'll silently ignore any properties requested for the second
     89         # (like RuntimeEnabled - see crbug.com/332588).
     90         entries_by_script_name = dict()
     91         for entry in self.in_file.name_dictionaries:
     92             script_name = name_utilities.script_name(entry)
     93             if script_name in entries_by_script_name:
     94                 self._fatal('Multiple entries with script_name=%(script_name)s: %(name1)s %(name2)s' % {
     95                     'script_name': script_name,
     96                     'name1': entry['name'],
     97                     'name2': entries_by_script_name[script_name]['name']})
     98             entries_by_script_name[script_name] = entry
     99 
    100     def _fatal(self, message):
    101         print 'FATAL ERROR: ' + message
    102         exit(1)
    103 
    104     def _headers_header_include_path(self, entry):
    105         if entry['ImplementedAs']:
    106             path = os.path.dirname(entry['name'])
    107             if len(path):
    108                 path += '/'
    109             path += entry['ImplementedAs']
    110         else:
    111             path = entry['name']
    112         return path + '.h'
    113 
    114     def _headers_header_includes(self, entries):
    115         includes = dict()
    116         for entry in entries:
    117             cpp_name = name_utilities.cpp_name(entry)
    118             # Avoid duplicate includes.
    119             if cpp_name in includes:
    120                 continue
    121             if self.suffix == 'Modules':
    122                 subdir_name = 'modules'
    123             else:
    124                 subdir_name = 'core'
    125             include = '#include "%(path)s"\n#include "bindings/%(subdir_name)s/v8/V8%(script_name)s.h"' % {
    126                 'path': self._headers_header_include_path(entry),
    127                 'script_name': name_utilities.script_name(entry),
    128                 'subdir_name': subdir_name,
    129             }
    130             includes[cpp_name] = self.wrap_with_condition(include, entry['Conditional'])
    131         return includes.values()
    132 
    133     def generate_headers_header(self):
    134         base_header_for_suffix = ''
    135         if self.suffix:
    136             base_header_for_suffix = '\n#include "core/%(namespace)sHeaders.h"\n' % {'namespace': self.namespace}
    137         return HEADER_TEMPLATE % {
    138             'license': license.license_for_generated_cpp(),
    139             'namespace': self.namespace,
    140             'suffix': self.suffix,
    141             'base_header_for_suffix': base_header_for_suffix,
    142             'includes': '\n'.join(self._headers_header_includes(self.in_file.name_dictionaries)),
    143         }
    144 
    145     @template_expander.use_jinja('EventFactory.cpp.tmpl', filters=filters)
    146     def generate_implementation(self):
    147         return {
    148             'namespace': self.namespace,
    149             'suffix': self.suffix,
    150             'events': self.in_file.name_dictionaries,
    151         }
    152 
    153 
    154 if __name__ == "__main__":
    155     in_generator.Maker(EventFactoryWriter).main(sys.argv)
    156