Generate the TypeId enums in codegen

This commit is contained in:
Anthony Ramine 2015-09-27 13:37:57 +02:00
parent 55769b2fbf
commit aab2c40389
107 changed files with 678 additions and 774 deletions

View file

@ -4,6 +4,8 @@
# Common codegen classes.
from collections import defaultdict
import operator
import re
import string
@ -1722,23 +1724,20 @@ class CGNamespace(CGWrapper):
return CGNamespace(namespaces[0], inner, public=public)
def EventTargetEnum(desc):
def DOMClassTypeId(desc):
protochain = desc.prototypeChain
if protochain[0] != "EventTarget" or desc.interface.getExtendedAttribute("Abstract"):
return "None"
inner = ""
name = desc.interface.identifier.name
if desc.interface.getUserData("hasConcreteDescendant", False):
inner = "(::dom::%s::%sTypeId::%s)" % (name.lower(), name, name)
prev_proto = ""
for proto in reversed(protochain):
if prev_proto != "":
inner = "(::dom::%s::%sTypeId::%s%s)" % (proto.lower(), proto, prev_proto, inner)
prev_proto = proto
if inner == "":
return "None"
return "Some%s" % inner
if desc.hasDescendants():
if desc.interface.getExtendedAttribute("Abstract"):
return "::dom::bindings::codegen::InheritTypes::TopTypeId::Abstract"
name = desc.interface.identifier.name
inner = "(::dom::bindings::codegen::InheritTypes::%sTypeId::%s)" % (name, name)
elif len(protochain) == 1:
return "::dom::bindings::codegen::InheritTypes::TopTypeId::Alone"
reversed_protochain = list(reversed(protochain))
for (child, parent) in zip(reversed_protochain, reversed_protochain[1:]):
inner = "(::dom::bindings::codegen::InheritTypes::%sTypeId::%s%s)" % (parent, child, inner)
return "::dom::bindings::codegen::InheritTypes::TopTypeId::%s%s" % (protochain[0], inner)
def DOMClass(descriptor):
@ -1754,7 +1753,7 @@ DOMClass {
interface_chain: [ %s ],
native_hooks: &sNativePropertyHooks,
type_id: %s,
}""" % (prototypeChainString, EventTargetEnum(descriptor))
}""" % (prototypeChainString, DOMClassTypeId(descriptor))
class CGDOMJSClass(CGThing):
@ -5815,23 +5814,29 @@ class GlobalGenRoots():
def InheritTypes(config):
descriptors = config.getDescriptors(register=True, isCallback=False)
allprotos = [CGGeneric("use dom::types::*;\n"),
CGGeneric("use dom::bindings::js::{JS, LayoutJS, Root};\n"),
CGGeneric("use dom::bindings::trace::JSTraceable;\n"),
CGGeneric("use dom::bindings::utils::Reflectable;\n"),
CGGeneric("use js::jsapi::JSTracer;\n\n"),
CGGeneric("use std::mem;\n\n")]
imports = [CGGeneric("use dom::types::*;\n"),
CGGeneric("use dom::bindings::conversions::get_dom_class;\n"),
CGGeneric("use dom::bindings::js::{JS, LayoutJS, Root};\n"),
CGGeneric("use dom::bindings::trace::JSTraceable;\n"),
CGGeneric("use dom::bindings::utils::Reflectable;\n"),
CGGeneric("use js::jsapi::JSTracer;\n\n"),
CGGeneric("use std::mem;\n\n")]
allprotos = []
topTypes = []
hierarchy = defaultdict(list)
for descriptor in descriptors:
name = descriptor.name
chain = descriptor.prototypeChain
upcast = (descriptor.interface.getUserData("hasConcreteDescendant", False) or
descriptor.interface.getUserData("hasProxyDescendant", False))
upcast = descriptor.hasDescendants()
downcast = len(chain) != 1
if upcast or downcast:
# Define a dummy structure to hold the cast functions.
allprotos.append(CGGeneric("pub struct %sCast;\n\n" % name))
if upcast and not downcast:
topTypes.append(name)
if upcast:
# Define a `FooBase` trait for subclasses to implement, as well as the
# `FooCast::from_*` methods that use it.
@ -5872,6 +5877,7 @@ impl %(name)sCast {
allprotos.append(CGGeneric("\n"))
if downcast:
hierarchy[descriptor.getParentName()].append(name)
# Define a `FooDerived` trait for superclasses to implement,
# as well as the `FooCast::to_*` methods that use it.
allprotos.append(CGGeneric("""\
@ -5922,7 +5928,7 @@ impl %(name)sCast {
'baseName': baseName,
'derivedTrait': name + 'Derived',
'methodName': 'is_' + name.lower(),
'parentName': config.getDescriptor(baseName).prototypeChain[-2],
'parentName': config.getDescriptor(baseName).getParentName(),
}
allprotos.append(CGGeneric("""\
impl %(derivedTrait)s for %(baseName)s {
@ -5934,7 +5940,54 @@ impl %(derivedTrait)s for %(baseName)s {
""" % args))
curr = CGList(allprotos)
typeIdCode = []
topTypeVariants = [
("ID used by abstract interfaces.", "Abstract"),
("ID used by interfaces that are not castable.", "Alone"),
]
topTypeVariants += [
("ID used by interfaces that derive from %s." % name, "%s(%sTypeId)" % (name, name))
for name in topTypes
]
topTypeVariantsAsStrings = [CGGeneric("/// %s\n%s," % variant) for variant in topTypeVariants]
typeIdCode.append(CGWrapper(CGIndenter(CGList(topTypeVariantsAsStrings, "\n"), 4),
pre="#[derive(Clone, Copy, Debug)]\npub enum TopTypeId {\n",
post="\n}\n\n"))
def type_id_variant(name):
# If `name` is present in the hierarchy keys', that means some other interfaces
# derive from it and this enum variant should have an argument with its own
# TypeId enum.
return "%s(%sTypeId)" % (name, name) if name in hierarchy else name
for base, derived in hierarchy.iteritems():
variants = []
if not config.getInterface(base).getExtendedAttribute("Abstract"):
variants.append(CGGeneric(base))
variants += [CGGeneric(type_id_variant(name)) for name in derived]
derives = "Clone, Copy, Debug"
if base != 'EventTarget' and base != 'HTMLElement':
derives += ", PartialEq"
typeIdCode.append(CGWrapper(CGIndenter(CGList(variants, ",\n"), 4),
pre="#[derive(%s)]\npub enum %sTypeId {\n" % (derives, base),
post="\n}\n\n"))
if base in topTypes:
typeIdCode.append(CGGeneric("""\
impl %(base)s {
pub fn type_id(&self) -> &'static %(base)sTypeId {
let domclass = unsafe {
get_dom_class(self.reflector().get_jsobject().get()).unwrap()
};
match domclass.type_id {
TopTypeId::%(base)s(ref type_id) => type_id,
_ => unreachable!(),
}
}
}
""" % {'base': base}))
curr = CGList(imports + typeIdCode + allprotos)
curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
return curr