Files
sdk/lib/dom/scripts/systembase.py
T
podivilov@google.com 0b807ba37b Move interface members traverse logic to BaseGenerator.
AddMembers(merged_interface) will be used by systemhtml to add
all the members from HTMLElement to Element.

R=antonm@google.com,sra@google.com

Review URL: https://chromiumcodereview.appspot.com//10532027

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8438 260f80e4-7a28-3924-810f-c04153c831b5
2012-06-08 13:47:01 +00:00

217 lines
7.1 KiB
Python

#!/usr/bin/python
# Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
"""This module provides base functionality for systems to generate
Dart APIs from the IDL database."""
import os
from generator import *
def MassagePath(path):
# The most robust way to emit path separators is to use / always.
return path.replace('\\', '/')
class System(object):
"""A System generates all the files for one implementation.
This is a base class for all the specific systems.
The life-cycle of a System is:
- construction (__init__)
- (InterfaceGenerator | ProcessCallback)* # for each IDL interface
- GenerateLibraries
- Finish
"""
def __init__(self, templates, database, emitters, output_dir):
self._templates = templates
self._database = database
self._emitters = emitters
self._output_dir = output_dir
self._dart_callback_file_paths = []
def InterfaceGenerator(self,
interface,
common_prefix,
super_interface_name,
source_filter):
"""Returns an interface generator for |interface|.
Called once for each interface that is not a callback function.
"""
return None
def ProcessCallback(self, interface, info):
"""Processes an interface that is a callback function."""
pass
def GenerateLibraries(self, lib_dir):
pass
def Finish(self):
pass
# Helper methods used by several systems.
def _ProcessCallback(self, interface, info, file_path):
"""Generates a typedef for the callback interface."""
self._dart_callback_file_paths.append(file_path)
code = self._emitters.FileEmitter(file_path)
code.Emit(self._templates.Load('callback.darttemplate'))
code.Emit('typedef $TYPE $NAME($PARAMS);\n',
NAME=interface.id,
TYPE=info.type_name,
PARAMS=info.ParametersImplementationDeclaration())
def _GenerateLibFile(self, lib_template, lib_file_path, file_paths,
**template_args):
"""Generates a lib file from a template and a list of files.
Additional keyword arguments are passed to the template.
Typically called from self.GenerateLibraries.
"""
# Load template.
template = self._templates.Load(lib_template)
# Generate the .lib file.
lib_file_contents = self._emitters.FileEmitter(lib_file_path)
# Emit the list of #source directives.
list_emitter = lib_file_contents.Emit(template, **template_args)
lib_file_dir = os.path.dirname(lib_file_path)
for path in sorted(file_paths):
relpath = os.path.relpath(path, lib_file_dir)
list_emitter.Emit("#source('$PATH');\n", PATH=MassagePath(relpath))
def _BaseDefines(self, interface):
"""Returns a set of names (strings) for members defined in a base class.
"""
def WalkParentChain(interface):
if interface.parents:
# Only consider primary parent, secondary parents are not on the
# implementation class inheritance chain.
parent = interface.parents[0]
if IsDartCollectionType(parent.type.id):
return
if self._database.HasInterface(parent.type.id):
parent_interface = self._database.GetInterface(parent.type.id)
for attr in parent_interface.attributes:
result.add(attr.id)
for op in parent_interface.operations:
result.add(op.id)
WalkParentChain(parent_interface)
result = set()
WalkParentChain(interface)
return result;
class BaseGenerator(object):
def __init__(self, database):
self._database = database
def AddMembers(self, interface):
for const in sorted(interface.constants, ConstantOutputOrder):
self.AddConstant(const)
attributes = [attr for attr in interface.attributes
if attr.type.id != 'EventListener']
for (getter, setter) in _PairUpAttributes(attributes):
self.AddAttribute(getter, setter)
# The implementation should define an indexer if the interface directly
# extends List.
(element_type, requires_indexer) = ListImplementationInfo(
interface, self._database)
if element_type:
if requires_indexer:
self.AddIndexer(element_type)
else:
self.AmendIndexer(element_type)
# Group overloaded operations by id
operationsById = {}
for operation in interface.operations:
if operation.id not in operationsById:
operationsById[operation.id] = []
operationsById[operation.id].append(operation)
# Generate operations
for id in sorted(operationsById.keys()):
operations = operationsById[id]
info = AnalyzeOperation(interface, operations)
if info.IsStatic():
self.AddStaticOperation(info)
else:
self.AddOperation(info)
def AddSecondaryMembers(self, interface, secondary_parents):
# With multiple inheritance, attributes and operations of non-first
# interfaces need to be added. Sometimes the attribute or operation is
# defined in the current interface as well as a parent. In that case we
# avoid making a duplicate definition and pray that the signatures match.
for parent_interface in secondary_parents:
if isinstance(parent_interface, str): # IsDartCollectionType(parent_interface)
continue
attributes = [attr for attr in parent_interface.attributes
if not FindMatchingAttribute(interface, attr)]
for (getter, setter) in _PairUpAttributes(attributes):
self.AddSecondaryAttribute(parent_interface, getter, setter)
# Group overloaded operations by id
operationsById = {}
for operation in parent_interface.operations:
if operation.id not in operationsById:
operationsById[operation.id] = []
operationsById[operation.id].append(operation)
# Generate operations
for id in sorted(operationsById.keys()):
if not any(op.id == id for op in interface.operations):
operations = operationsById[id]
info = AnalyzeOperation(interface, operations)
self.AddSecondaryOperation(parent_interface, info)
def AddConstant(self, constant):
pass
def AddAttribute(self, getter, setter):
pass
def AddIndexer(self, element_type):
pass
def AmendIndexer(self, element_type):
pass
def AddOperation(self, info):
pass
def AddStaticOperation(self, info):
pass
def AddSecondaryAttribute(self, interface, getter, setter):
pass
def AddSecondaryOperation(self, interface, attr):
pass
def _PairUpAttributes(attributes):
"""Returns a list of (getter, setter) pairs sorted by name.
One element of the pair may be None.
"""
names = sorted(set(attr.id for attr in attributes))
getters = {}
setters = {}
for attr in attributes:
if attr.is_fc_getter:
getters[attr.id] = attr
elif attr.is_fc_setter and 'Replaceable' not in attr.ext_attrs:
setters[attr.id] = attr
return [(getters.get(id), setters.get(id)) for id in names]