diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py')
-rwxr-xr-x | Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py b/Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py new file mode 100755 index 000000000..e39a604fc --- /dev/null +++ b/Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py @@ -0,0 +1,270 @@ +#!/usr/bin/env python +# +# Copyright (c) 2014, 2016 Apple Inc. All rights reserved. +# Copyright (c) 2014 University of Washington. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. + +# This script generates JS, Objective C, and C++ bindings for the inspector protocol. +# Generators for individual files are located in the codegen/ directory. + +import os.path +import re +import sys +import string +from string import Template +import optparse +import logging + +try: + import json +except ImportError: + import simplejson as json + +logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.ERROR) +log = logging.getLogger('global') + +try: + from codegen import * + +# When copying generator files to JavaScriptCore's private headers on Mac, +# the codegen/ module directory is flattened. So, import directly. +except ImportError, e: + # log.error(e) # Uncomment this to debug early import errors. + import models + from models import * + from generator import * + from cpp_generator import * + from objc_generator import * + + from generate_cpp_alternate_backend_dispatcher_header import * + from generate_cpp_backend_dispatcher_header import * + from generate_cpp_backend_dispatcher_implementation import * + from generate_cpp_frontend_dispatcher_header import * + from generate_cpp_frontend_dispatcher_implementation import * + from generate_cpp_protocol_types_header import * + from generate_cpp_protocol_types_implementation import * + from generate_js_backend_commands import * + from generate_objc_backend_dispatcher_header import * + from generate_objc_backend_dispatcher_implementation import * + from generate_objc_configuration_header import * + from generate_objc_configuration_implementation import * + from generate_objc_frontend_dispatcher_implementation import * + from generate_objc_header import * + from generate_objc_internal_header import * + from generate_objc_protocol_type_conversions_header import * + from generate_objc_protocol_type_conversions_implementation import * + from generate_objc_protocol_types_implementation import * + + +# A writer that only updates file if it actually changed. +class IncrementalFileWriter: + def __init__(self, filepath, force_output): + self._filepath = filepath + self._output = "" + self.force_output = force_output + + def write(self, text): + self._output += text + + def close(self): + text_changed = True + self._output = self._output.rstrip() + "\n" + + try: + if self.force_output: + raise + + read_file = open(self._filepath, "r") + old_text = read_file.read() + read_file.close() + text_changed = old_text != self._output + except: + # Ignore, just overwrite by default + pass + + if text_changed or self.force_output: + out_file = open(self._filepath, "w") + out_file.write(self._output) + out_file.close() + + +def generate_from_specification(primary_specification_filepath=None, + supplemental_specification_filepaths=[], + concatenate_output=False, + output_dirpath=None, + force_output=False, + framework_name="", + platform_name="", + generate_frontend=True, + generate_backend=True): + + def load_specification(protocol, filepath, isSupplemental=False): + try: + with open(filepath, "r") as input_file: + parsed_json = json.load(input_file) + protocol.parse_specification(parsed_json, isSupplemental) + except ValueError as e: + raise Exception("Error parsing valid JSON in file: " + filepath + "\nParse error: " + str(e)) + + platform = Platform.fromString(platform_name) + protocol = models.Protocol(framework_name) + for specification in supplemental_specification_filepaths: + load_specification(protocol, specification, isSupplemental=True) + load_specification(protocol, primary_specification_filepath, isSupplemental=False) + + protocol.resolve_types() + + generator_arguments = [protocol, platform, primary_specification_filepath] + generators = [] + + if protocol.framework is Frameworks.Test: + generators.append(JSBackendCommandsGenerator(*generator_arguments)) + generators.append(CppAlternateBackendDispatcherHeaderGenerator(*generator_arguments)) + generators.append(CppBackendDispatcherHeaderGenerator(*generator_arguments)) + generators.append(CppBackendDispatcherImplementationGenerator(*generator_arguments)) + generators.append(CppFrontendDispatcherHeaderGenerator(*generator_arguments)) + generators.append(CppFrontendDispatcherImplementationGenerator(*generator_arguments)) + generators.append(CppProtocolTypesHeaderGenerator(*generator_arguments)) + generators.append(CppProtocolTypesImplementationGenerator(*generator_arguments)) + generators.append(ObjCBackendDispatcherHeaderGenerator(*generator_arguments)) + generators.append(ObjCBackendDispatcherImplementationGenerator(*generator_arguments)) + generators.append(ObjCConfigurationHeaderGenerator(*generator_arguments)) + generators.append(ObjCConfigurationImplementationGenerator(*generator_arguments)) + generators.append(ObjCFrontendDispatcherImplementationGenerator(*generator_arguments)) + generators.append(ObjCHeaderGenerator(*generator_arguments)) + generators.append(ObjCInternalHeaderGenerator(*generator_arguments)) + generators.append(ObjCProtocolTypeConversionsHeaderGenerator(*generator_arguments)) + generators.append(ObjCProtocolTypeConversionsImplementationGenerator(*generator_arguments)) + generators.append(ObjCProtocolTypesImplementationGenerator(*generator_arguments)) + + elif protocol.framework is Frameworks.JavaScriptCore: + generators.append(JSBackendCommandsGenerator(*generator_arguments)) + generators.append(CppAlternateBackendDispatcherHeaderGenerator(*generator_arguments)) + generators.append(CppBackendDispatcherHeaderGenerator(*generator_arguments)) + generators.append(CppBackendDispatcherImplementationGenerator(*generator_arguments)) + generators.append(CppFrontendDispatcherHeaderGenerator(*generator_arguments)) + generators.append(CppFrontendDispatcherImplementationGenerator(*generator_arguments)) + generators.append(CppProtocolTypesHeaderGenerator(*generator_arguments)) + generators.append(CppProtocolTypesImplementationGenerator(*generator_arguments)) + + elif protocol.framework is Frameworks.WebKit and generate_backend: + generators.append(CppBackendDispatcherHeaderGenerator(*generator_arguments)) + generators.append(CppBackendDispatcherImplementationGenerator(*generator_arguments)) + generators.append(CppProtocolTypesHeaderGenerator(*generator_arguments)) + generators.append(CppProtocolTypesImplementationGenerator(*generator_arguments)) + + elif protocol.framework is Frameworks.WebKit and generate_frontend: + generators.append(ObjCHeaderGenerator(*generator_arguments)) + generators.append(ObjCProtocolTypeConversionsHeaderGenerator(*generator_arguments)) + generators.append(ObjCProtocolTypeConversionsImplementationGenerator(*generator_arguments)) + generators.append(ObjCProtocolTypesImplementationGenerator(*generator_arguments)) + + elif protocol.framework is Frameworks.WebInspector: + generators.append(ObjCBackendDispatcherHeaderGenerator(*generator_arguments)) + generators.append(ObjCBackendDispatcherImplementationGenerator(*generator_arguments)) + generators.append(ObjCConfigurationHeaderGenerator(*generator_arguments)) + generators.append(ObjCConfigurationImplementationGenerator(*generator_arguments)) + generators.append(ObjCFrontendDispatcherImplementationGenerator(*generator_arguments)) + generators.append(ObjCHeaderGenerator(*generator_arguments)) + generators.append(ObjCInternalHeaderGenerator(*generator_arguments)) + generators.append(ObjCProtocolTypeConversionsHeaderGenerator(*generator_arguments)) + generators.append(ObjCProtocolTypesImplementationGenerator(*generator_arguments)) + + single_output_file_contents = [] + + for generator in generators: + # Only some generators care whether frontend or backend was specified, but it is + # set on all of them to avoid adding more constructor arguments or thinking too hard. + if generate_backend: + generator.set_generator_setting('generate_backend', True) + if generate_frontend: + generator.set_generator_setting('generate_frontend', True) + + output = generator.generate_output() + if concatenate_output: + single_output_file_contents.append('### Begin File: %s' % generator.output_filename()) + single_output_file_contents.append(output) + single_output_file_contents.append('### End File: %s' % generator.output_filename()) + single_output_file_contents.append('') + else: + output_file = IncrementalFileWriter(os.path.join(output_dirpath, generator.output_filename()), force_output) + output_file.write(output) + output_file.close() + + if concatenate_output: + filename = os.path.join(os.path.basename(primary_specification_filepath) + '-result') + output_file = IncrementalFileWriter(os.path.join(output_dirpath, filename), force_output) + output_file.write('\n'.join(single_output_file_contents)) + output_file.close() + + +if __name__ == '__main__': + allowed_framework_names = ['JavaScriptCore', 'WebInspector', 'WebKit', 'Test'] + allowed_platform_names = ['iOS', 'macOS', 'all', 'generic'] + cli_parser = optparse.OptionParser(usage="usage: %prog [options] PrimaryProtocol.json [SupplementalProtocol.json ...]") + cli_parser.add_option("-o", "--outputDir", help="Directory where generated files should be written.") + cli_parser.add_option("--framework", type="choice", choices=allowed_framework_names, help="The framework that the primary specification belongs to.") + cli_parser.add_option("--force", action="store_true", help="Force output of generated scripts, even if nothing changed.") + cli_parser.add_option("-v", "--debug", action="store_true", help="Log extra output for debugging the generator itself.") + cli_parser.add_option("-t", "--test", action="store_true", help="Enable test mode. Use unique output filenames created by prepending the input filename.") + cli_parser.add_option("--frontend", action="store_true", help="Generate code for the frontend-side of the protocol only.") + cli_parser.add_option("--backend", action="store_true", help="Generate code for the backend-side of the protocol only.") + cli_parser.add_option("--platform", default="generic", help="The platform of the backend being generated. For example, we compile WebKit2 for either macOS or iOS. This value is case-insensitive. Allowed values: %s" % ", ".join(allowed_platform_names)) + options = None + + arg_options, arg_values = cli_parser.parse_args() + if (len(arg_values) < 1): + raise ParseException("At least one plain argument expected") + + if not arg_options.outputDir: + raise ParseException("Missing output directory") + + if arg_options.debug: + log.setLevel(logging.DEBUG) + + generate_backend = arg_options.backend; + generate_frontend = arg_options.frontend; + # Default to generating both the frontend and backend if neither is specified. + if not generate_backend and not generate_frontend: + generate_backend = True + generate_frontend = True + + options = { + 'primary_specification_filepath': arg_values[0], + 'supplemental_specification_filepaths': arg_values[1:], + 'output_dirpath': arg_options.outputDir, + 'concatenate_output': arg_options.test, + 'framework_name': arg_options.framework, + 'platform_name': arg_options.platform, + 'force_output': arg_options.force, + 'generate_backend': generate_backend, + 'generate_frontend': generate_frontend, + } + + try: + generate_from_specification(**options) + except (ParseException, TypecheckException) as e: + if arg_options.test: + log.error(e.message) + else: + raise # Force the build to fail. |