mirror of
https://github.com/shaka-project/shaka-player.git
synced 2026-06-16 16:16:40 +03:00
fe4f5c6e19
Reverts shaka-project/shaka-player#4163 Closes #4167
138 lines
5.0 KiB
Python
Executable File
138 lines
5.0 KiB
Python
Executable File
#!/usr/bin/env python
|
|
#
|
|
# Copyright 2016 Google LLC
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
"""Generates TypeScript defs from Closure externs.
|
|
|
|
This uses the Clutz tool from https://github.com/angular/clutz and then performs
|
|
additional transformations to make the generated defs independent of Clutz.
|
|
"""
|
|
|
|
import argparse
|
|
import os
|
|
import re
|
|
import sys
|
|
|
|
import shakaBuildHelpers
|
|
|
|
|
|
def GenerateTsDefs(inputs, output):
|
|
"""Generates TypeScript defs from Closure externs.
|
|
|
|
Args:
|
|
inputs: A list of paths to Closure extern files.
|
|
output: A path to a TypeScript def output file.
|
|
"""
|
|
clutz = shakaBuildHelpers.get_node_binary('@teppeis/clutz', 'clutz')
|
|
|
|
command = clutz + [
|
|
'--closure_env', 'BROWSER',
|
|
'--externs',
|
|
] + inputs + [
|
|
'-o', '-',
|
|
]
|
|
|
|
# Get the output of Clutz, then transform it to make it independent of Clutz
|
|
# and usable directly in TypeScript projects.
|
|
contents = shakaBuildHelpers.execute_get_output(command)
|
|
|
|
# Remove the prefix clutz puts on all namespaces.
|
|
contents = contents.replace(b'\xe0\xb2\xa0_\xe0\xb2\xa0.clutz.', b'')
|
|
# Replace "GlobalObject" (from Clutz) with TypeScript-native "object".
|
|
contents = re.sub(br'\bGlobalObject\b', b'object', contents)
|
|
# Remove "Global" from Clutz's Global{Date,Element,Event,EventTarget} and use
|
|
# their original definitions instead.
|
|
contents = re.sub(
|
|
br'\bGlobal(Date|Element|Event|EventTarget)\b', br'\1', contents)
|
|
# Remove "protected", which appears on some fields, and is only supported on
|
|
# methods.
|
|
contents = re.sub(br'^\s*protected ', b'', contents, flags=re.MULTILINE)
|
|
# Clutz really likes EventTargets, so it wants IAdManager to extend it twice.
|
|
contents = contents.replace(
|
|
b'extends EventTarget extends EventTarget',
|
|
b'extends EventTarget')
|
|
# Some types allow you to return a Promise or nothing, but the Clutz output of
|
|
# "Promise | null | undefined" doesn't work in TypeScript. We need to use
|
|
# "Promise | void" instead.
|
|
contents = contents.replace(b'| null | undefined', b'| void')
|
|
# shaka.util.Error extends Error and implements shaka.extern.Error, but this
|
|
# confuses TypeScript when both are called "Error" in context of the namespace
|
|
# declaration for "shaka.util". Therefore we need to declare this
|
|
# "GlobalError" type, which is already referenced by Clutz but never defined.
|
|
global_error_def = b'declare class GlobalError extends Error {}\n\n'
|
|
contents = global_error_def + contents
|
|
# There are some types that implement multiple interfaces, such as IReleasable
|
|
# and Iteratable. Also, there are tools used inside Google that (for some
|
|
# reason) want to convert TS defs _BACK_ into Closure Compiler externs. When
|
|
# that happens, these multiple implementors generate externs with broken
|
|
# @implements annotations. Since this team can't control that process or
|
|
# those tools, we need to adjust our TS defs instead. In these particular
|
|
# cases, thankfully, we can just remove the reference to the IReleasable
|
|
# interface, which is not needed outside the library.
|
|
# TODO: This only covers one very specific pattern, and could be brittle.
|
|
contents = contents.replace(
|
|
b'implements shaka.util.IReleasable , ', b'implements ')
|
|
# Finally, Clutz includes a bunch of basic defs for a browser environment
|
|
# generated from Closure compiler's builtins. Remove these.
|
|
sections = re.split(br'\n(?=// Generated from .*)', contents)
|
|
sections = filter(
|
|
lambda s: not s.startswith(b'// Generated from externs.zip'),
|
|
sections)
|
|
contents = b'\n'.join(sections) + b'\n'
|
|
|
|
license_header_path = os.path.join(
|
|
shakaBuildHelpers.get_source_base(), 'build/license-header')
|
|
|
|
with open(license_header_path, 'rb') as f:
|
|
license_header = f.read()
|
|
|
|
with open(output, 'wb') as f:
|
|
f.write(license_header)
|
|
f.write(b'\n')
|
|
f.write(contents)
|
|
|
|
|
|
def CreateParser():
|
|
"""Create the argument parser for this application."""
|
|
base = shakaBuildHelpers.get_source_base()
|
|
|
|
parser = argparse.ArgumentParser(
|
|
description=__doc__,
|
|
formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
|
|
parser.add_argument(
|
|
'--output',
|
|
type=str,
|
|
help='The file path for TypeScripts defs output')
|
|
|
|
parser.add_argument(
|
|
'input',
|
|
type=str,
|
|
nargs='+',
|
|
help='The Closure extern files to be converted to TypeScript defs')
|
|
|
|
return parser
|
|
|
|
|
|
def main(args):
|
|
parser = CreateParser()
|
|
args = parser.parse_args(args)
|
|
GenerateTsDefs(args.input, args.output)
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main(sys.argv[1:])
|