Bug 1007878 part 1. Add parsing of MozMap to the WebIDL parser. r=khuey

This commit is contained in:
Boris Zbarsky 2014-05-23 17:32:38 -04:00
Родитель 900ca9c9b2
Коммит 0cca97fdf1
3 изменённых файлов: 150 добавлений и 14 удалений

Просмотреть файл

@ -1200,9 +1200,10 @@ class IDLDictionary(IDLObjectWithScope):
None, if the boolean value in the first element is False. None, if the boolean value in the first element is False.
""" """
if memberType.nullable() or \ if (memberType.nullable() or
memberType.isArray() or \ memberType.isArray() or
memberType.isSequence(): memberType.isSequence() or
memberType.isMozMap()):
return typeContainsDictionary(memberType.inner, dictionary) return typeContainsDictionary(memberType.inner, dictionary)
if memberType.isDictionary(): if memberType.isDictionary():
@ -1320,6 +1321,7 @@ class IDLType(IDLObject):
'callback', 'callback',
'union', 'union',
'sequence', 'sequence',
'mozmap',
'array' 'array'
) )
@ -1367,6 +1369,9 @@ class IDLType(IDLObject):
def isSequence(self): def isSequence(self):
return False return False
def isMozMap(self):
return False
def isArray(self): def isArray(self):
return False return False
@ -1549,6 +1554,9 @@ class IDLNullableType(IDLType):
def isSequence(self): def isSequence(self):
return self.inner.isSequence() return self.inner.isSequence()
def isMozMap(self):
return self.inner.isMozMap()
def isArray(self): def isArray(self):
return self.inner.isArray() return self.inner.isArray()
@ -1701,6 +1709,60 @@ class IDLSequenceType(IDLType):
def _getDependentObjects(self): def _getDependentObjects(self):
return self.inner._getDependentObjects() return self.inner._getDependentObjects()
class IDLMozMapType(IDLType):
# XXXbz This is pretty similar to IDLSequenceType in various ways.
# And maybe to IDLNullableType. Should we have a superclass for
# "type containing this other type"? Bug 1015318.
def __init__(self, location, parameterType):
assert not parameterType.isVoid()
IDLType.__init__(self, location, parameterType.name)
self.inner = parameterType
self.builtin = False
def __eq__(self, other):
return isinstance(other, IDLMozMapType) and self.inner == other.inner
def __str__(self):
return self.inner.__str__() + "MozMap"
def isMozMap(self):
return True
def includesRestrictedFloat(self):
return self.inner.includesRestrictedFloat()
def tag(self):
return IDLType.Tags.mozmap
def resolveType(self, parentScope):
assert isinstance(parentScope, IDLScope)
self.inner.resolveType(parentScope)
def isComplete(self):
return self.inner.isComplete()
def complete(self, scope):
self.inner = self.inner.complete(scope)
self.name = self.inner.name
return self
def unroll(self):
# We do not unroll our inner. Just stop at ourselves. That
# lets us add headers for both ourselves and our inner as
# needed.
return self
def isDistinguishableFrom(self, other):
if other.isUnion():
# Just forward to the union; it'll deal
return other.isDistinguishableFrom(self)
return (other.isPrimitive() or other.isString() or other.isEnum() or
other.isDate() or other.isNonCallbackInterface())
def _getDependentObjects(self):
return self.inner._getDependentObjects()
class IDLUnionType(IDLType): class IDLUnionType(IDLType):
def __init__(self, location, memberTypes): def __init__(self, location, memberTypes):
IDLType.__init__(self, location, "") IDLType.__init__(self, location, "")
@ -1744,7 +1806,8 @@ class IDLUnionType(IDLType):
return typeName(type._identifier.object()) return typeName(type._identifier.object())
if isinstance(type, IDLObjectWithIdentifier): if isinstance(type, IDLObjectWithIdentifier):
return typeName(type.identifier) return typeName(type.identifier)
if isinstance(type, IDLType) and (type.isArray() or type.isSequence()): if (isinstance(type, IDLType) and
(type.isArray() or type.isSequence() or type.isMozMap)):
return str(type) return str(type)
return type.name return type.name
@ -1816,6 +1879,9 @@ class IDLArrayType(IDLType):
if parameterType.isSequence(): if parameterType.isSequence():
raise WebIDLError("Array type cannot parameterize over a sequence type", raise WebIDLError("Array type cannot parameterize over a sequence type",
[location]) [location])
if parameterType.isMozMap():
raise WebIDLError("Array type cannot parameterize over a MozMap type",
[location])
if parameterType.isDictionary(): if parameterType.isDictionary():
raise WebIDLError("Array type cannot parameterize over a dictionary type", raise WebIDLError("Array type cannot parameterize over a dictionary type",
[location]) [location])
@ -1946,6 +2012,9 @@ class IDLTypedefType(IDLType, IDLObjectWithIdentifier):
def isSequence(self): def isSequence(self):
return self.inner.isSequence() return self.inner.isSequence()
def isMozMap(self):
return self.inner.isMozMap()
def isArray(self): def isArray(self):
return self.inner.isArray() return self.inner.isArray()
@ -2100,7 +2169,7 @@ class IDLWrapperType(IDLType):
if self.isEnum(): if self.isEnum():
return (other.isPrimitive() or other.isInterface() or other.isObject() or return (other.isPrimitive() or other.isInterface() or other.isObject() or
other.isCallback() or other.isDictionary() or other.isCallback() or other.isDictionary() or
other.isSequence() or other.isArray() or other.isSequence() or other.isMozMap() or other.isArray() or
other.isDate()) other.isDate())
if self.isDictionary() and other.nullable(): if self.isDictionary() and other.nullable():
return False return False
@ -2122,7 +2191,7 @@ class IDLWrapperType(IDLType):
(self.isNonCallbackInterface() or (self.isNonCallbackInterface() or
other.isNonCallbackInterface())) other.isNonCallbackInterface()))
if (other.isDictionary() or other.isCallback() or if (other.isDictionary() or other.isCallback() or
other.isSequence() or other.isArray()): other.isSequence() or other.isMozMap() or other.isArray()):
return self.isNonCallbackInterface() return self.isNonCallbackInterface()
# Not much else |other| can be # Not much else |other| can be
@ -2296,19 +2365,19 @@ class IDLBuiltinType(IDLType):
return (other.isNumeric() or other.isString() or other.isEnum() or return (other.isNumeric() or other.isString() or other.isEnum() or
other.isInterface() or other.isObject() or other.isInterface() or other.isObject() or
other.isCallback() or other.isDictionary() or other.isCallback() or other.isDictionary() or
other.isSequence() or other.isArray() or other.isSequence() or other.isMozMap() or other.isArray() or
other.isDate()) other.isDate())
if self.isNumeric(): if self.isNumeric():
return (other.isBoolean() or other.isString() or other.isEnum() or return (other.isBoolean() or other.isString() or other.isEnum() or
other.isInterface() or other.isObject() or other.isInterface() or other.isObject() or
other.isCallback() or other.isDictionary() or other.isCallback() or other.isDictionary() or
other.isSequence() or other.isArray() or other.isSequence() or other.isMozMap() or other.isArray() or
other.isDate()) other.isDate())
if self.isString(): if self.isString():
return (other.isPrimitive() or other.isInterface() or return (other.isPrimitive() or other.isInterface() or
other.isObject() or other.isObject() or
other.isCallback() or other.isDictionary() or other.isCallback() or other.isDictionary() or
other.isSequence() or other.isArray() or other.isSequence() or other.isMozMap() or other.isArray() or
other.isDate()) other.isDate())
if self.isAny(): if self.isAny():
# Can't tell "any" apart from anything # Can't tell "any" apart from anything
@ -2319,7 +2388,7 @@ class IDLBuiltinType(IDLType):
return (other.isPrimitive() or other.isString() or other.isEnum() or return (other.isPrimitive() or other.isString() or other.isEnum() or
other.isInterface() or other.isCallback() or other.isInterface() or other.isCallback() or
other.isDictionary() or other.isSequence() or other.isDictionary() or other.isSequence() or
other.isArray()) other.isMozMap() or other.isArray())
if self.isVoid(): if self.isVoid():
return not other.isVoid() return not other.isVoid()
# Not much else we could be! # Not much else we could be!
@ -2327,7 +2396,8 @@ class IDLBuiltinType(IDLType):
# Like interfaces, but we know we're not a callback # Like interfaces, but we know we're not a callback
return (other.isPrimitive() or other.isString() or other.isEnum() or return (other.isPrimitive() or other.isString() or other.isEnum() or
other.isCallback() or other.isDictionary() or other.isCallback() or other.isDictionary() or
other.isSequence() or other.isArray() or other.isDate() or other.isSequence() or other.isMozMap() or other.isArray() or
other.isDate() or
(other.isInterface() and ( (other.isInterface() and (
# ArrayBuffer is distinguishable from everything # ArrayBuffer is distinguishable from everything
# that's not an ArrayBuffer or a callback interface # that's not an ArrayBuffer or a callback interface
@ -2710,6 +2780,9 @@ class IDLAttribute(IDLInterfaceMember):
if self.type.isSequence() and not self.getExtendedAttribute("Cached"): if self.type.isSequence() and not self.getExtendedAttribute("Cached"):
raise WebIDLError("A non-cached attribute cannot be of a sequence " raise WebIDLError("A non-cached attribute cannot be of a sequence "
"type", [self.location]) "type", [self.location])
if self.type.isMozMap() and not self.getExtendedAttribute("Cached"):
raise WebIDLError("A non-cached attribute cannot be of a MozMap "
"type", [self.location])
if self.type.isUnion(): if self.type.isUnion():
for f in self.type.unroll().flatMemberTypes: for f in self.type.unroll().flatMemberTypes:
if f.isDictionary(): if f.isDictionary():
@ -2724,6 +2797,12 @@ class IDLAttribute(IDLInterfaceMember):
"one of its member types's member " "one of its member types's member "
"types, and so on) is a sequence " "types, and so on) is a sequence "
"type", [self.location, f.location]) "type", [self.location, f.location])
if f.isMozMap():
raise WebIDLError("An attribute cannot be of a union "
"type if one of its member types (or "
"one of its member types's member "
"types, and so on) is a MozMap "
"type", [self.location, f.location])
if not self.type.isInterface() and self.getExtendedAttribute("PutForwards"): if not self.type.isInterface() and self.getExtendedAttribute("PutForwards"):
raise WebIDLError("An attribute with [PutForwards] must have an " raise WebIDLError("An attribute with [PutForwards] must have an "
"interface type as its type", [self.location]) "interface type as its type", [self.location])
@ -2742,9 +2821,11 @@ class IDLAttribute(IDLInterfaceMember):
"getter won't always be called.", "getter won't always be called.",
[self.location]) [self.location])
if self.getExtendedAttribute("Frozen"): if self.getExtendedAttribute("Frozen"):
if not self.type.isSequence() and not self.type.isDictionary(): if (not self.type.isSequence() and not self.type.isDictionary() and
raise WebIDLError("[Frozen] is only allowed on sequence-valued " not self.type.isMozMap()):
"and dictionary-valued attributes", raise WebIDLError("[Frozen] is only allowed on "
"sequence-valued, dictionary-valued, and "
"MozMap-valued attributes",
[self.location]) [self.location])
def handleExtendedAttribute(self, attr): def handleExtendedAttribute(self, attr):
@ -3627,6 +3708,7 @@ class Tokenizer(object):
"octet": "OCTET", "octet": "OCTET",
"optional": "OPTIONAL", "optional": "OPTIONAL",
"sequence": "SEQUENCE", "sequence": "SEQUENCE",
"MozMap": "MOZMAP",
"short": "SHORT", "short": "SHORT",
"unsigned": "UNSIGNED", "unsigned": "UNSIGNED",
"void": "VOID", "void": "VOID",
@ -4523,6 +4605,7 @@ class Parser(Tokenizer):
| OCTET | OCTET
| OPTIONAL | OPTIONAL
| SEQUENCE | SEQUENCE
| MOZMAP
| SETTER | SETTER
| SHORT | SHORT
| STATIC | STATIC
@ -4632,6 +4715,16 @@ class Parser(Tokenizer):
type = IDLNullableType(self.getLocation(p, 5), type) type = IDLNullableType(self.getLocation(p, 5), type)
p[0] = type p[0] = type
def p_NonAnyTypeMozMapType(self, p):
"""
NonAnyType : MOZMAP LT Type GT Null
"""
innerType = p[3]
type = IDLMozMapType(self.getLocation(p, 1), innerType)
if p[5]:
type = IDLNullableType(self.getLocation(p, 5), type)
p[0] = type
def p_NonAnyTypeScopedName(self, p): def p_NonAnyTypeScopedName(self, p):
""" """
NonAnyType : ScopedName TypeSuffix NonAnyType : ScopedName TypeSuffix

Просмотреть файл

@ -158,6 +158,7 @@ def WebIDLTest(parser, harness):
"CallbackInterface?", "CallbackInterface2", "CallbackInterface?", "CallbackInterface2",
"object", "Callback", "Callback2", "optional Dict", "object", "Callback", "Callback2", "optional Dict",
"optional Dict2", "sequence<long>", "sequence<short>", "optional Dict2", "sequence<long>", "sequence<short>",
"MozMap<object>", "MozMap<Dict>", "MozMap<long>",
"long[]", "short[]", "Date", "Date?", "any" ] "long[]", "short[]", "Date", "Date?", "any" ]
# When we can parse Date and RegExp, we need to add them here. # When we can parse Date and RegExp, we need to add them here.
@ -219,6 +220,9 @@ def WebIDLTest(parser, harness):
setDistinguishable("optional Dict2", allBut(nonUserObjects, nullables)) setDistinguishable("optional Dict2", allBut(nonUserObjects, nullables))
setDistinguishable("sequence<long>", nonUserObjects) setDistinguishable("sequence<long>", nonUserObjects)
setDistinguishable("sequence<short>", nonUserObjects) setDistinguishable("sequence<short>", nonUserObjects)
setDistinguishable("MozMap<object>", nonUserObjects)
setDistinguishable("MozMap<Dict>", nonUserObjects)
setDistinguishable("MozMap<long>", nonUserObjects)
setDistinguishable("long[]", nonUserObjects) setDistinguishable("long[]", nonUserObjects)
setDistinguishable("short[]", nonUserObjects) setDistinguishable("short[]", nonUserObjects)
setDistinguishable("Date", allBut(argTypes, dates + ["object"])) setDistinguishable("Date", allBut(argTypes, dates + ["object"]))

Просмотреть файл

@ -0,0 +1,39 @@
import WebIDL
def WebIDLTest(parser, harness):
parser.parse("""
dictionary Dict {};
interface MozMapArg {
void foo(MozMap<Dict> arg);
};
""")
results = parser.finish()
harness.check(len(results), 2, "Should know about two things");
harness.ok(isinstance(results[1], WebIDL.IDLInterface),
"Should have an interface here");
members = results[1].members
harness.check(len(members), 1, "Should have one member")
harness.ok(members[0].isMethod(), "Should have method")
signature = members[0].signatures()[0]
args = signature[1]
harness.check(len(args), 1, "Should have one arg")
harness.ok(args[0].type.isMozMap(), "Should have a MozMap type here")
harness.ok(args[0].type.inner.isDictionary(),
"Should have a dictionary inner type")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface MozMapVoidArg {
void foo(MozMap<void> arg);
};
""")
results = parser.finish()
except Exception,x:
threw = True
harness.ok(threw, "Should have thrown.")