| Index: client/dom/scripts/dartgenerator.py
|
| diff --git a/client/dom/scripts/dartgenerator.py b/client/dom/scripts/dartgenerator.py
|
| index c155fce3c600a10a676a71dc9bda08e584b34817..2b1b62c3738fef5212a367f7767ea34245e724ad 100755
|
| --- a/client/dom/scripts/dartgenerator.py
|
| +++ b/client/dom/scripts/dartgenerator.py
|
| @@ -426,7 +426,7 @@ class DartGenerator(object):
|
|
|
| self._ComputeInheritanceClosure()
|
|
|
| - interface_system = WrappingInterfacesSystem(
|
| + interface_system = InterfacesSystem(
|
| TemplateLoader(self._template_dir, ['dom/interface', 'dom', '']),
|
| self._database, self._emitters, self._output_dir)
|
|
|
| @@ -436,12 +436,15 @@ class DartGenerator(object):
|
|
|
| # Makes interface files available for listing in the library for the
|
| # wrapping implementation.
|
| +
|
| wrapping_system._interface_system = interface_system
|
|
|
| frog_system = FrogSystem(
|
| TemplateLoader(self._template_dir, ['dom/frog', 'dom', '']),
|
| self._database, self._emitters, self._output_dir)
|
|
|
| + frog_system._interface_system = interface_system
|
| +
|
| self._systems = [interface_system,
|
| wrapping_system,
|
| frog_system]
|
| @@ -472,7 +475,7 @@ class DartGenerator(object):
|
| continue
|
|
|
|
|
| - info = self._RecognizeCallback(interface)
|
| + info = _RecognizeCallback(interface)
|
| if info:
|
| for system in self._systems:
|
| system.ProcessCallback(interface, info)
|
| @@ -491,17 +494,6 @@ class DartGenerator(object):
|
| system.Finish()
|
|
|
|
|
| - def _RecognizeCallback(self, interface):
|
| - """Returns the info for the callback method if the interface smells like a
|
| - callback.
|
| - """
|
| - if 'Callback' not in interface.ext_attrs: return None
|
| - handlers = [op for op in interface.operations if op.id == 'handleEvent']
|
| - if not handlers: return None
|
| - if not (handlers == interface.operations): return None
|
| - return self._AnalyzeOperation(interface, handlers)
|
| -
|
| -
|
| def _ProcessInterface(self, interface, super_interface_name,
|
| source_filter,
|
| common_prefix):
|
| @@ -523,7 +515,8 @@ class DartGenerator(object):
|
|
|
| for attr in sorted(interface.attributes, AttributeOutputOrder):
|
| if attr.type.id == 'EventListener':
|
| - # Remove EventListener attributes when addEventListener is available.
|
| + # Remove EventListener attributes like 'onclick' when addEventListener
|
| + # is available.
|
| if 'EventTarget' in self._AllImplementedInterfaces(interface):
|
| continue
|
| if attr.is_fc_getter:
|
| @@ -550,7 +543,7 @@ class DartGenerator(object):
|
| # Generate operations
|
| for id in sorted(operationsById.keys()):
|
| operations = operationsById[id]
|
| - info = self._AnalyzeOperation(interface, operations)
|
| + info = _AnalyzeOperation(interface, operations)
|
| for generator in generators:
|
| generator.AddOperation(info)
|
|
|
| @@ -584,7 +577,7 @@ class DartGenerator(object):
|
| for id in sorted(operationsById.keys()):
|
| if not any(op.id == id for op in interface.operations):
|
| operations = operationsById[id]
|
| - info = self._AnalyzeOperation(interface, operations)
|
| + info = _AnalyzeOperation(interface, operations)
|
| for generator in generators:
|
| generator.AddSecondaryOperation(parent_interface, info)
|
|
|
| @@ -618,79 +611,6 @@ class DartGenerator(object):
|
| walk(interface.parents[1:])
|
| return result;
|
|
|
| - def _AnalyzeOperation(self, interface, operations):
|
| - """Makes operation calling convention decision for a set of overloads.
|
| -
|
| - Returns: An OperationInfo object.
|
| - """
|
| -
|
| - # Zip together arguments from each overload by position, then convert
|
| - # to a dart argument.
|
| -
|
| - # Given a list of overloaded arguments, choose a suitable name.
|
| - def OverloadedName(args):
|
| - return '_OR_'.join(sorted(set(arg.id for arg in args)))
|
| -
|
| - # Given a list of overloaded arguments, choose a suitable type.
|
| - def OverloadedType(args):
|
| - typeIds = sorted(set(arg.type.id for arg in args))
|
| - if len(typeIds) == 1:
|
| - return typeIds[0]
|
| - else:
|
| - return TypeName(typeIds, interface)
|
| -
|
| - # Given a list of overloaded arguments, render a dart argument.
|
| - def DartArg(args):
|
| - filtered = filter(None, args)
|
| - optional = any(not arg or arg.is_optional for arg in args)
|
| - type = OverloadedType(filtered)
|
| - name = OverloadedName(filtered)
|
| - if optional:
|
| - return (name, type, 'null')
|
| - else:
|
| - return (name, type, None)
|
| -
|
| - def FormatArg(arg_info):
|
| - """Returns an argument declaration fragment for an argument info tuple."""
|
| - (name, type, default) = arg_info
|
| - if default:
|
| - return '%s %s = %s' % (type, name, default)
|
| - else:
|
| - return '%s %s' % (type, name)
|
| -
|
| - def FormatArgs(args, is_interface):
|
| - required = []
|
| - optional = []
|
| - for (name, type, default) in args:
|
| - if default:
|
| - if is_interface:
|
| - optional.append((name, type, None))
|
| - else:
|
| - optional.append((name, type, default))
|
| - else:
|
| - if optional:
|
| - raise Exception('Optional arguments cannot precede required ones: '
|
| - + str(args))
|
| - required.append((name, type, None))
|
| - argtexts = map(FormatArg, required)
|
| - if optional:
|
| - argtexts.append('[' + ', '.join(map(FormatArg, optional)) + ']')
|
| - return ', '.join(argtexts)
|
| -
|
| - args = map(lambda *args: DartArg(args),
|
| - *(op.arguments for op in operations))
|
| -
|
| - info = OperationInfo()
|
| - info.overloads = operations
|
| - info.declared_name = operations[0].id
|
| - info.name = operations[0].ext_attrs.get('DartName', info.declared_name)
|
| - info.js_name = info.declared_name
|
| - info.type_name = operations[0].type.id # TODO: widen.
|
| - info.arg_interface_declaration = FormatArgs(args, True)
|
| - info.arg_implementation_declaration = FormatArgs(args, False)
|
| - info.arg_infos = args
|
| - return info
|
| -
|
|
|
| def Flush(self):
|
| """Write out all pending files."""
|
| @@ -728,6 +648,62 @@ class DartGenerator(object):
|
| return self._inheritance_closure[interface.id]
|
|
|
|
|
| +def _RecognizeCallback(interface):
|
| + """Returns the info for the callback method if the interface smells like a
|
| + callback.
|
| + """
|
| + if 'Callback' not in interface.ext_attrs: return None
|
| + handlers = [op for op in interface.operations if op.id == 'handleEvent']
|
| + if not handlers: return None
|
| + if not (handlers == interface.operations): return None
|
| + return _AnalyzeOperation(interface, handlers)
|
| +
|
| +
|
| +def _AnalyzeOperation(interface, operations):
|
| + """Makes operation calling convention decision for a set of overloads.
|
| +
|
| + Returns: An OperationInfo object.
|
| + """
|
| +
|
| + # Zip together arguments from each overload by position, then convert
|
| + # to a dart argument.
|
| +
|
| + # Given a list of overloaded arguments, choose a suitable name.
|
| + def OverloadedName(args):
|
| + return '_OR_'.join(sorted(set(arg.id for arg in args)))
|
| +
|
| + # Given a list of overloaded arguments, choose a suitable type.
|
| + def OverloadedType(args):
|
| + typeIds = sorted(set(arg.type.id for arg in args))
|
| + if len(typeIds) == 1:
|
| + return typeIds[0]
|
| + else:
|
| + return TypeName(typeIds, interface)
|
| +
|
| + # Given a list of overloaded arguments, render a dart argument.
|
| + def DartArg(args):
|
| + filtered = filter(None, args)
|
| + optional = any(not arg or arg.is_optional for arg in args)
|
| + type = OverloadedType(filtered)
|
| + name = OverloadedName(filtered)
|
| + if optional:
|
| + return (name, type, 'null')
|
| + else:
|
| + return (name, type, None)
|
| +
|
| + args = map(lambda *args: DartArg(args),
|
| + *(op.arguments for op in operations))
|
| +
|
| + info = OperationInfo()
|
| + info.overloads = operations
|
| + info.declared_name = operations[0].id
|
| + info.name = operations[0].ext_attrs.get('DartName', info.declared_name)
|
| + info.js_name = info.declared_name
|
| + info.type_name = operations[0].type.id # TODO: widen.
|
| + info.arg_infos = args
|
| + return info
|
| +
|
| +
|
| class OperationInfo(object):
|
| """Holder for various derived information from a set of overloaded operations.
|
|
|
| @@ -735,13 +711,54 @@ class OperationInfo(object):
|
| overloads: A list of IDL operation overloads with the same name.
|
| name: A string, the simple name of the operation.
|
| type_name: A string, the name of the return type of the operation.
|
| - arg_declarations: A list of strings, Dart argument declarations for the
|
| - member that implements the set of overloads. Each string is of the form
|
| - "T arg" or "T arg = null".
|
| arg_infos: A list of (name, type, default_value) tuples.
|
| default_value is None for mandatory arguments.
|
| """
|
| - pass
|
| +
|
| + def ParametersInterfaceDeclaration(self):
|
| + """Returns a formatted string declaring the parameters for the interface."""
|
| + return self._FormatArgs(self.arg_infos, True)
|
| +
|
| + def ParametersImplementationDeclaration(self, rename_type=None):
|
| + """Returns a formatted string declaring the parameters for the
|
| + implementation.
|
| +
|
| + Args:
|
| + rename_type: A function that allows the types to be renamed.
|
| + """
|
| + args = self.arg_infos
|
| + if rename_type:
|
| + args = [(name, rename_type(type), default)
|
| + for (name, type, default) in args]
|
| + return self._FormatArgs(args, False)
|
| +
|
| +
|
| + def _FormatArgs(self, args, is_interface):
|
| + def FormatArg(arg_info):
|
| + """Returns an argument declaration fragment for an argument info tuple."""
|
| + (name, type, default) = arg_info
|
| + if default:
|
| + return '%s %s = %s' % (type, name, default)
|
| + else:
|
| + return '%s %s' % (type, name)
|
| +
|
| + required = []
|
| + optional = []
|
| + for (name, type, default) in args:
|
| + if default:
|
| + if is_interface:
|
| + optional.append((name, type, None)) # Default values illegal.
|
| + else:
|
| + optional.append((name, type, default))
|
| + else:
|
| + if optional:
|
| + raise Exception('Optional arguments cannot precede required ones: '
|
| + + str(args))
|
| + required.append((name, type, None))
|
| + argtexts = map(FormatArg, required)
|
| + if optional:
|
| + argtexts.append('[' + ', '.join(map(FormatArg, optional)) + ']')
|
| + return ', '.join(argtexts)
|
|
|
|
|
| def MaybeListElementType(interface):
|
| @@ -876,10 +893,10 @@ class System(object):
|
| code = self._emitters.FileEmitter(file_path)
|
|
|
| code.Emit(self._templates.Load('callback.darttemplate'))
|
| - code.Emit('typedef $TYPE $NAME($ARGS);\n',
|
| + code.Emit('typedef $TYPE $NAME($PARAMS);\n',
|
| NAME=interface.id,
|
| TYPE=info.type_name,
|
| - ARGS=info.arg_implementation_declaration)
|
| + PARAMS=info.ParametersImplementationDeclaration())
|
|
|
| def _GenerateLibFile(self, lib_template, lib_file_path, file_paths):
|
| """Generates a lib file from a template and a list of files."""
|
| @@ -921,10 +938,10 @@ class System(object):
|
|
|
| # ------------------------------------------------------------------------------
|
|
|
| -class WrappingInterfacesSystem(System):
|
| +class InterfacesSystem(System):
|
|
|
| def __init__(self, templates, database, emitters, output_dir):
|
| - super(WrappingInterfacesSystem, self).__init__(
|
| + super(InterfacesSystem, self).__init__(
|
| templates, database, emitters, output_dir)
|
| self._dart_interface_file_paths = []
|
|
|
| @@ -1099,20 +1116,21 @@ class FrogSystem(System):
|
|
|
| dart_code = self._emitters.FileEmitter(dart_frog_file_path)
|
| dart_code.Emit(self._templates.Load('frog_impl.darttemplate'))
|
| - return FrogInterfaceGenerator(interface, super_interface_name,
|
| + return FrogInterfaceGenerator(self, interface, super_interface_name,
|
| dart_code)
|
|
|
| - def ProcessCallback(self, interface, info):
|
| - """Generates a typedef for the callback interface."""
|
| - file_path = self._FilePathForFrogImpl(interface.id)
|
| - self._ProcessCallback(interface, info, file_path)
|
| + #def ProcessCallback(self, interface, info):
|
| + # """Generates a typedef for the callback interface."""
|
| + # file_path = self._FilePathForFrogImpl(interface.id)
|
| + # self._ProcessCallback(interface, info, file_path)
|
|
|
| def GenerateLibraries(self, lib_dir):
|
| self._GenerateLibFile(
|
| 'frog_dom.darttemplate',
|
| os.path.join(lib_dir, 'dom_frog.dart'),
|
| - self._dart_frog_file_paths +
|
| - self._dart_callback_file_paths)
|
| + (self._interface_system._dart_interface_file_paths +
|
| + self._interface_system._dart_callback_file_paths +
|
| + self._dart_frog_file_paths))
|
|
|
| def Finish(self):
|
| pass
|
| @@ -1122,7 +1140,6 @@ class FrogSystem(System):
|
| return os.path.join(self._output_dir, 'src', 'frog',
|
| '%s.dart' % interface_name)
|
|
|
| -
|
| # ------------------------------------------------------------------------------
|
|
|
| class DartInterfaceGenerator(object):
|
| @@ -1249,10 +1266,10 @@ class DartInterfaceGenerator(object):
|
| name.
|
| """
|
| self._members_emitter.Emit('\n'
|
| - ' $TYPE $NAME($ARGS);\n',
|
| + ' $TYPE $NAME($PARAMS);\n',
|
| TYPE=info.type_name,
|
| NAME=info.name,
|
| - ARGS=info.arg_interface_declaration)
|
| + PARAMS=info.ParametersInterfaceDeclaration())
|
|
|
| # Interfaces get secondary members directly via the superinterfaces.
|
| def AddSecondaryGetter(self, interface, attr):
|
| @@ -1599,12 +1616,12 @@ class WrappingInterfaceGenerator(object):
|
| """
|
| body = self._members_emitter.Emit(
|
| '\n'
|
| - ' $TYPE $NAME($ARGS) {\n'
|
| + ' $TYPE $NAME($PARAMS) {\n'
|
| '$!BODY'
|
| ' }\n',
|
| TYPE=info.type_name,
|
| NAME=info.name,
|
| - ARGS=info.arg_implementation_declaration)
|
| + PARAMS=info.ParametersImplementationDeclaration())
|
|
|
| # Process in order of ascending number of arguments to ensure missing
|
| # optional arguments are processed early.
|
| @@ -1809,7 +1826,7 @@ class WrappingInterfaceGenerator(object):
|
| class FrogInterfaceGenerator(object):
|
| """Generates a Frog class for a DOM IDL interface."""
|
|
|
| - def __init__(self, interface, super_interface, dart_code):
|
| + def __init__(self, system, interface, super_interface, dart_code):
|
| """Generates Dart code for the given interface.
|
|
|
| Args:
|
| @@ -1822,6 +1839,7 @@ class FrogInterfaceGenerator(object):
|
| dart_code: an Emitter for the file containing the Dart implementation
|
| class.
|
| """
|
| + self._system = system
|
| self._interface = interface
|
| self._super_interface = super_interface
|
| self._dart_code = dart_code
|
| @@ -1872,20 +1890,21 @@ class FrogInterfaceGenerator(object):
|
| native_spec = '*' + interface_name
|
|
|
| # TODO: Include all implemented interfaces, including other Lists.
|
| - implements = ''
|
| + implements = [interface_name]
|
| element_type = MaybeTypedArrayElementType(self._interface)
|
| if element_type:
|
| - implements = ' implements List<' + element_type + '>'
|
| + implements.append('List<' + element_type + '>')
|
|
|
| (self._members_emitter, self._base_emitter) = self._dart_code.Emit(
|
| '\n'
|
| - 'class $CLASS$BASE$IMPLEMENTS native "$NATIVE" {\n'
|
| + 'class $CLASS$BASE implements $IMPLEMENTS native "$NATIVE" {\n'
|
| '$!MEMBERS'
|
| '$!ADDITIONS'
|
| '}\n',
|
| - CLASS=self._class_name, BASE=extends,
|
| + CLASS=self._class_name,
|
| + BASE=extends,
|
| INTERFACE=interface_name,
|
| - IMPLEMENTS=implements,
|
| + IMPLEMENTS=', '.join(implements),
|
| NATIVE=native_spec)
|
|
|
| if interface_name in _constructable_types:
|
| @@ -1913,8 +1932,28 @@ class FrogInterfaceGenerator(object):
|
| ' String get typeName() native;\n')
|
|
|
| def _ImplClassName(self, type_name):
|
| + return type_name + 'JS'
|
| +
|
| + def _NarrowToImplementationType(self, type_name):
|
| + # TODO(sra): Move into the 'system' and cache the result.
|
| + if type_name == 'EventListener':
|
| + # Callbacks are typedef functions so don't have a class.
|
| + return type_name
|
| + if self._system._database.HasInterface(type_name):
|
| + interface = self._system._database.GetInterface(type_name)
|
| + if _RecognizeCallback(interface):
|
| + # Callbacks are typedef functions so don't have a class.
|
| + return type_name
|
| + else:
|
| + return self._ImplClassName(type_name)
|
| return type_name
|
|
|
| + def _NarrowInputType(self, type_name):
|
| + return self._NarrowToImplementationType(type_name)
|
| +
|
| + def _NarrowOutputType(self, type_name):
|
| + return self._NarrowToImplementationType(type_name)
|
| +
|
| def FinishInterface(self):
|
| """."""
|
| pass
|
| @@ -1934,13 +1973,13 @@ class FrogInterfaceGenerator(object):
|
| # TODO(sra): Remove native body when Issue 829 fixed.
|
| self._members_emitter.Emit(
|
| '\n $TYPE get $NAME() native "return this.$NAME;";\n',
|
| - NAME=attr.id, TYPE=attr.type.id)
|
| + NAME=attr.id, TYPE=self._NarrowOutputType(attr.type.id))
|
|
|
| def AddSetter(self, attr):
|
| # TODO(sra): Remove native body when Issue 829 fixed.
|
| self._members_emitter.Emit(
|
| '\n void set $NAME($TYPE value) native "this.$NAME = value;";\n',
|
| - NAME=attr.id, TYPE=attr.type.id)
|
| + NAME=attr.id, TYPE=self._NarrowInputType(attr.type.id))
|
|
|
| def AddSecondaryGetter(self, interface, attr):
|
| self._SecondaryContext(interface)
|
| @@ -1981,20 +2020,20 @@ class FrogInterfaceGenerator(object):
|
| self._members_emitter.Emit(
|
| '\n'
|
| ' $TYPE operator[](int index) native;\n',
|
| - TYPE=element_type)
|
| + TYPE=self._NarrowOutputType(element_type))
|
|
|
| if 'HasCustomIndexSetter' in self._interface.ext_attrs:
|
| self._members_emitter.Emit(
|
| '\n'
|
| ' void operator[]=(int index, $TYPE value) native;\n',
|
| - TYPE=element_type)
|
| + TYPE=self._NarrowInputType(element_type))
|
| else:
|
| self._members_emitter.Emit(
|
| '\n'
|
| ' void operator[]=(int index, $TYPE value) {\n'
|
| ' throw new UnsupportedOperationException("Cannot assign element of immutable List.");\n'
|
| ' }\n',
|
| - TYPE=element_type)
|
| + TYPE=self._NarrowInputType(element_type))
|
|
|
|
|
| def AddTypedArrayConstructors(self, element_type):
|
| @@ -2019,7 +2058,8 @@ class FrogInterfaceGenerator(object):
|
| # TODO(vsm): Handle overloads.
|
| self._members_emitter.Emit(
|
| '\n'
|
| - ' $TYPE $NAME($ARGS) native;\n',
|
| - TYPE=info.type_name,
|
| + ' $TYPE $NAME($PARAMS) native;\n',
|
| + TYPE=self._NarrowOutputType(info.type_name),
|
| NAME=info.name,
|
| - ARGS=info.arg_implementation_declaration)
|
| + PARAMS=info.ParametersImplementationDeclaration(
|
| + lambda type_name: self._NarrowInputType(type_name)))
|
|
|