зеркало из https://github.com/mozilla/gecko-dev.git
Bug 742144. Implement support for typedefs in WebIDL. r=khuey
This commit is contained in:
Родитель
cbc670ae41
Коммит
57c2a362b2
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче