Bug 742144. Implement support for typedefs in WebIDL. r=khuey

This commit is contained in:
Boris Zbarsky 2012-09-06 10:23:51 -04:00
Родитель cbc670ae41
Коммит 57c2a362b2
7 изменённых файлов: 159 добавлений и 12 удалений

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

@ -999,6 +999,10 @@ class IDLUnresolvedType(IDLType):
assert obj
if obj.isType():
# obj itself might not be complete; deal with that.
assert obj != self
if not obj.isComplete():
obj = obj.complete(scope)
return obj
name = self.name.resolve(scope, None)
@ -1011,7 +1015,6 @@ class IDLUnresolvedType(IDLType):
class IDLNullableType(IDLType):
def __init__(self, location, innerType):
assert not innerType.isVoid()
assert not innerType.nullable()
assert not innerType == BuiltinTypes[IDLBuiltinType.Types.any]
IDLType.__init__(self, location, innerType.name)
@ -1090,6 +1093,10 @@ class IDLNullableType(IDLType):
def complete(self, scope):
self.inner = self.inner.complete(scope)
if self.inner.nullable():
raise WebIDLError("The inner type of a nullable type must not be "
"a nullable type",
[self.location, self.inner.location])
if self.inner.isUnion():
if self.inner.hasNullableType:
raise WebIDLError("The inner type of a nullable type must not "
@ -1407,9 +1414,24 @@ class IDLTypedefType(IDLType, IDLObjectWithIdentifier):
def isNonCallbackInterface(self):
return self.inner.isNonCallbackInterface()
def resolve(self, parentScope):
assert isinstance(parentScope, IDLScope)
IDLObjectWithIdentifier.resolve(self, parentScope)
def isComplete(self):
return False
def complete(self, parentScope):
if not self.inner.isComplete():
self.inner = self.inner.complete(parentScope)
assert self.inner.isComplete()
return self.inner
def finish(self, parentScope):
# Maybe the IDLObjectWithIdentifier for the typedef should be
# a separate thing from the type?
self.complete(parentScope)
def validate(self):
pass
# Do we need a resolveType impl? I don't think it's particularly useful....
def tag(self):
return self.inner.tag()
@ -1883,18 +1905,28 @@ class IDLConst(IDLInterfaceMember):
raise WebIDLError("A constant cannot be of a dictionary type",
[self.location])
self.type = type
# The value might not match the type
coercedValue = value.coerceToType(self.type, location)
assert coercedValue
self.value = coercedValue
self.value = value
def __str__(self):
return "'%s' const '%s'" % (self.type, self.identifier)
def finish(self, scope):
assert self.type.isComplete()
if not self.type.isComplete():
type = self.type.complete(scope)
if not type.isPrimitive() and not type.isString():
locations = [self.type.location, type.location]
try:
locations.append(type.inner.location)
except:
pass
raise WebIDLError("Incorrect type for constant", locations)
self.type = type
# The value might not match the type
coercedValue = self.value.coerceToType(self.type, self.location)
assert coercedValue
self.value = coercedValue
def validate(self):
pass
@ -1921,6 +1953,7 @@ class IDLAttribute(IDLInterfaceMember):
t = self.type.complete(scope)
assert not isinstance(t, IDLUnresolvedType)
assert not isinstance(t, IDLTypedefType)
assert not isinstance(t.name, IDLUnresolvedIdentifier)
self.type = t
@ -2016,6 +2049,7 @@ class IDLArgument(IDLObjectWithIdentifier):
if not self.type.isComplete():
type = self.type.complete(scope)
assert not isinstance(type, IDLUnresolvedType)
assert not isinstance(type, IDLTypedefType)
assert not isinstance(type.name, IDLUnresolvedIdentifier)
self.type = type
@ -2061,6 +2095,7 @@ class IDLCallbackType(IDLType, IDLObjectWithScope):
type = returnType.complete(scope)
assert not isinstance(type, IDLUnresolvedType)
assert not isinstance(type, IDLTypedefType)
assert not isinstance(type.name, IDLUnresolvedIdentifier)
self._returnType = type
@ -2071,6 +2106,7 @@ class IDLCallbackType(IDLType, IDLObjectWithScope):
type = argument.type.complete(scope)
assert not isinstance(type, IDLUnresolvedType)
assert not isinstance(type, IDLTypedefType)
assert not isinstance(type.name, IDLUnresolvedIdentifier)
argument.type = type
@ -2322,6 +2358,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
type = returnType.complete(scope)
assert not isinstance(type, IDLUnresolvedType)
assert not isinstance(type, IDLTypedefType)
assert not isinstance(type.name, IDLUnresolvedIdentifier)
overload.returnType = type
@ -3448,6 +3485,17 @@ class Parser(Tokenizer):
type = IDLNullableType(self.getLocation(p, 1), type)
p[0] = type
def p_ConstTypeIdentifier(self, p):
"""
ConstType : IDENTIFIER Null
"""
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1])
type = IDLUnresolvedType(self.getLocation(p, 1), identifier)
if p[2]:
type = IDLNullableType(self.getLocation(p, 1), type)
p[0] = type
def p_PrimitiveOrStringTypeUint(self, p):
"""
PrimitiveOrStringType : UnsignedIntegerType

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

@ -31,7 +31,7 @@ def WebIDLTest(parser, harness):
harness.check(len(members), 10, "Should be one production")
names = ["b", "s8", "u8", "s16", "u16", "s32", "u32", "s64", "u64", "ts"]
types = ["Boolean", "Byte", "Octet", "Short", "UnsignedShort", "Long", "UnsignedLong", "LongLong", "UnsignedLongLong", "DOMTimeStamp"]
types = ["Boolean", "Byte", "Octet", "Short", "UnsignedShort", "Long", "UnsignedLong", "LongLong", "UnsignedLongLong", "UnsignedLongLong"]
for i in range(10):
attr = members[i]
harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute")

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

@ -0,0 +1,76 @@
def WebIDLTest(parser, harness):
parser.parse("""
typedef long mylong;
typedef long? mynullablelong;
interface Foo {
const mylong X = 5;
const mynullablelong Y = 7;
const mynullablelong Z = null;
void foo(mylong arg);
};
""")
results = parser.finish()
harness.check(results[2].members[1].type.name, "Long",
"Should expand typedefs")
parser = parser.reset()
threw = False
try:
parser.parse("""
typedef long? mynullablelong;
interface Foo {
void foo(mynullablelong? Y);
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should have thrown on nullable inside nullable arg.")
parser = parser.reset()
threw = False
try:
parser.parse("""
typedef long? mynullablelong;
interface Foo {
const mynullablelong? X = 5;
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should have thrown on nullable inside nullable const.")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface Foo {
const mynullablelong? X = 5;
};
typedef long? mynullablelong;
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should have thrown on nullable inside nullable const typedef "
"after interface.")
parser = parser.reset()
parser.parse("""
interface Foo {
const mylong X = 5;
};
typedef long mylong;
""")
results = parser.finish()
harness.check(results[0].members[0].type.name, "Long",
"Should expand typedefs that come before interface")

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

@ -396,6 +396,11 @@ public:
void PassDictionaryOrLong(int32_t);
void PassDictContainingDict(const DictContainingDict&);
// Typedefs
void ExerciseTypedefInterfaces1(TestInterface&);
already_AddRefed<TestInterface> ExerciseTypedefInterfaces2(TestInterface*);
void ExerciseTypedefInterfaces3(TestInterface&);
// Methods and properties imported via "implements"
bool GetImplementedProperty();
void SetImplementedProperty(bool);

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

@ -4,6 +4,10 @@
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
typedef long myLong;
typedef TestInterface AnotherNameForTestInterface;
typedef TestInterface? NullableTestInterface;
interface TestExternalInterface;
interface TestNonCastableInterface {
@ -309,6 +313,12 @@ interface TestInterface {
void dontEnforceRangeOrClamp(byte arg);
void doEnforceRange([EnforceRange] byte arg);
void doClamp([Clamp] byte arg);
// Typedefs
const myLong myLongConstant = 5;
void exerciseTypedefInterfaces1(AnotherNameForTestInterface arg);
AnotherNameForTestInterface exerciseTypedefInterfaces2(NullableTestInterface arg);
void exerciseTypedefInterfaces3(YetAnotherNameForTestInterface arg);
};
interface TestNonWrapperCacheInterface {

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

@ -0,0 +1,7 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
typedef TestInterface YetAnotherNameForTestInterface;

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

@ -33,6 +33,7 @@ ifdef ENABLE_TESTS
test_webidl_files := \
TestCodeGen.webidl \
TestDictionary.webidl \
TestTypedef.webidl \
$(NULL)
else
test_webidl_files := $(NULL)