summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py')
-rwxr-xr-xSource/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py270
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.