Spaces Data
Minimal test - lines (19041, 19224)
path: .spaces[259].spaces[0].metrics.loc.blank
old: 7.0
new: 8.0
path: .spaces[259].spaces[0].metrics.loc.cloc
old: 24.0
new: 25.0
path: .spaces[259].spaces[0].metrics.loc.sloc
old: 182.0
new: 184.0
path: .spaces[259].spaces[0].metrics.mi.mi_sei
old: 6.686479476299365
new: 6.788387376531922
path: .spaces[259].spaces[0].metrics.mi.mi_visual_studio
old: 21.18250400414427
new: 21.078965441207732
path: .spaces[259].spaces[0].metrics.mi.mi_original
old: 36.22208184708671
new: 36.04503090446522
Code
def __init__(
self,
descriptor,
cgMethod,
cgGetter,
cgSetter,
wantGetParent=True,
wrapMethodName="WrapObject",
skipStaticMethods=False,
):
"""
cgMethod, cgGetter and cgSetter are classes used to codegen methods,
getters and setters.
"""
self.descriptor = descriptor
self._deps = descriptor.interface.getDeps()
iface = descriptor.interface
self.methodDecls = []
def appendMethod(m, isConstructor=False):
sigs = m.signatures()
for s in sigs[:-1]:
# Don't put a blank line after overloads, until we
# get to the last one.
self.methodDecls.append(
cgMethod(descriptor, m, s, isConstructor, breakAfter=False)
)
self.methodDecls.append(cgMethod(descriptor, m, sigs[-1], isConstructor))
if iface.ctor():
appendMethod(iface.ctor(), isConstructor=True)
for n in iface.namedConstructors:
appendMethod(n, isConstructor=True)
for m in iface.members:
if m.isMethod():
if m.isIdentifierLess():
continue
if m.isMaplikeOrSetlikeOrIterableMethod():
# Handled by generated code already
continue
if not m.isStatic() or not skipStaticMethods:
appendMethod(m)
elif m.isAttr():
if m.isMaplikeOrSetlikeAttr():
# Handled by generated code already
continue
self.methodDecls.append(cgGetter(descriptor, m))
if not m.readonly:
self.methodDecls.append(cgSetter(descriptor, m))
# Now do the special operations
def appendSpecialOperation(name, op):
if op is None:
return
assert len(op.signatures()) == 1
returnType, args = op.signatures()[0]
# Make a copy of the args, since we plan to modify them.
args = list(args)
if op.isGetter() or op.isDeleter():
# This is a total hack. The '&' belongs with the
# type, not the name! But it works, and is simpler
# than trying to somehow make this pretty.
args.append(
FakeArgument(
BuiltinTypes[IDLBuiltinType.Types.boolean], op, name="&found"
)
)
if name == "Stringifier":
if op.isIdentifierLess():
# XXXbz I wish we were consistent about our renaming here.
name = "Stringify"
else:
# We already added this method
return
if name == "LegacyCaller":
if op.isIdentifierLess():
# XXXbz I wish we were consistent about our renaming here.
name = "LegacyCall"
else:
# We already added this method
return
self.methodDecls.append(
CGNativeMember(
descriptor,
op,
name,
(returnType, args),
descriptor.getExtendedAttributes(op),
)
)
# Sort things by name so we get stable ordering in the output.
ops = sorted(descriptor.operations.items(), key=lambda x: x[0])
for name, op in ops:
appendSpecialOperation(name, op)
# If we support indexed properties, then we need a Length()
# method so we know which indices are supported.
if descriptor.supportsIndexedProperties():
# But we don't need it if we already have an infallible
# "length" attribute, which we often do.
haveLengthAttr = any(
m
for m in iface.members
if m.isAttr()
and CGSpecializedGetter.makeNativeName(descriptor, m) == "Length"
)
if not haveLengthAttr:
self.methodDecls.append(
CGNativeMember(
descriptor,
FakeMember(),
"Length",
(BuiltinTypes[IDLBuiltinType.Types.unsigned_long], []),
[],
),
)
# And if we support named properties we need to be able to
# enumerate the supported names.
if descriptor.supportsNamedProperties():
self.methodDecls.append(
CGNativeMember(
descriptor,
FakeMember(),
"GetSupportedNames",
(
IDLSequenceType(
None, BuiltinTypes[IDLBuiltinType.Types.domstring]
),
[],
),
[],
)
)
if descriptor.concrete:
wrapArgs = [
Argument("JSContext*", "aCx"),
Argument("JS::Handle", "aGivenProto"),
]
if not descriptor.wrapperCache:
wrapReturnType = "bool"
wrapArgs.append(Argument("JS::MutableHandle", "aReflector"))
else:
wrapReturnType = "JSObject*"
self.methodDecls.insert(
0,
ClassMethod(
wrapMethodName,
wrapReturnType,
wrapArgs,
virtual=descriptor.wrapperCache,
breakAfterReturnDecl=" ",
override=descriptor.wrapperCache,
body=self.getWrapObjectBody(),
),
)
if descriptor.hasCEReactions():
self.methodDecls.insert(
0,
ClassMethod(
"GetDocGroup",
"DocGroup*",
[],
const=True,
breakAfterReturnDecl=" ",
body=self.getGetDocGroupBody(),
),
)
if wantGetParent:
self.methodDecls.insert(
0,
ClassMethod(
"GetParentObject",
self.getGetParentObjectReturnType(),
[],
const=True,
breakAfterReturnDecl=" ",
body=self.getGetParentObjectBody(),
),
)
# Invoke CGClass.__init__ in any subclasses afterwards to do the actual codegen.
Minimal test - lines (17782, 17895)
path: .spaces[252].metrics.loc.cloc
old: 34.0
new: 36.0
path: .spaces[252].metrics.loc.sloc
old: 112.0
new: 114.0
path: .spaces[252].metrics.mi.mi_sei
old: 34.485119863789116
new: 34.624928885269746
path: .spaces[252].metrics.mi.mi_original
old: 48.49194345955861
new: 48.20521031054831
path: .spaces[252].metrics.mi.mi_visual_studio
old: 28.3578616722565
new: 28.190181468156904
Code
class ForwardDeclarationBuilder:
"""
Create a canonical representation of a set of namespaced forward
declarations.
"""
def __init__(self):
"""
The set of declarations is represented as a tree of nested namespaces.
Each tree node has a set of declarations |decls| and a dict |children|.
Each declaration is a pair consisting of the class name and a boolean
that is true iff the class is really a struct. |children| maps the
names of inner namespaces to the declarations in that namespace.
"""
self.decls = set()
self.children = {}
def _ensureNonTemplateType(self, type):
if "<" in type:
# This is a templated type. We don't really know how to
# forward-declare those, and trying to do it naively is not going to
# go well (e.g. we may have :: characters inside the type we're
# templated on!). Just bail out.
raise TypeError(
"Attempt to use ForwardDeclarationBuilder on "
"templated type %s. We don't know how to do that "
"yet." % type
)
def _listAdd(self, namespaces, name, isStruct=False):
"""
Add a forward declaration, where |namespaces| is a list of namespaces.
|name| should not contain any other namespaces.
"""
if namespaces:
child = self.children.setdefault(namespaces[0], ForwardDeclarationBuilder())
child._listAdd(namespaces[1:], name, isStruct)
else:
assert "::" not in name
self.decls.add((name, isStruct))
def addInMozillaDom(self, name, isStruct=False):
"""
Add a forward declaration to the mozilla::dom:: namespace. |name| should not
contain any other namespaces.
"""
self._ensureNonTemplateType(name)
self._listAdd(["mozilla", "dom"], name, isStruct)
def add(self, nativeType, isStruct=False):
"""
Add a forward declaration, where |nativeType| is a string containing
the type and its namespaces, in the usual C++ way.
"""
self._ensureNonTemplateType(nativeType)
components = nativeType.split("::")
self._listAdd(components[:-1], components[-1], isStruct)
def _build(self, atTopLevel):
"""
Return a codegenerator for the forward declarations.
"""
decls = []
if self.decls:
decls.append(
CGList(
[
CGClassForwardDeclare(cname, isStruct)
for cname, isStruct in sorted(self.decls)
]
)
)
for namespace, child in sorted(six.iteritems(self.children)):
decls.append(
CGNamespace(namespace, child._build(atTopLevel=False), declareOnly=True)
)
cg = CGList(decls, "\n")
if not atTopLevel and len(decls) + len(self.decls) > 1:
cg = CGWrapper(cg, pre="\n", post="\n")
return cg
def build(self):
return self._build(atTopLevel=True)
def forwardDeclareForType(self, t, config):
t = t.unroll()
if t.isGeckoInterface():
name = t.inner.identifier.name
try:
desc = config.getDescriptor(name)
self.add(desc.nativeType)
except NoSuchDescriptorError:
pass
# Note: SpiderMonkey interfaces are typedefs, so can't be
# forward-declared
elif t.isPromise():
self.addInMozillaDom("Promise")
elif t.isCallback():
self.addInMozillaDom(t.callback.identifier.name)
elif t.isDictionary():
self.addInMozillaDom(t.inner.identifier.name, isStruct=True)
elif t.isCallbackInterface():
self.addInMozillaDom(t.inner.identifier.name)
elif t.isUnion():
# Forward declare both the owning and non-owning version,
# since we don't know which one we might want
self.addInMozillaDom(CGUnionStruct.unionTypeName(t, False))
self.addInMozillaDom(CGUnionStruct.unionTypeName(t, True))
elif t.isRecord():
self.forwardDeclareForType(t.inner, config)
# Don't need to do anything for void, primitive, string, any or object.
# There may be some other cases we are missing.
Minimal test - lines (17867, 17895)
path: .spaces[252].spaces[7].metrics.loc.sloc
old: 27.0
new: 29.0
path: .spaces[252].spaces[7].metrics.loc.cloc
old: 4.0
new: 6.0
path: .spaces[252].spaces[7].metrics.mi.mi_original
old: 81.68394863186202
new: 80.52631341535127
path: .spaces[252].spaces[7].metrics.mi.mi_sei
old: 71.13916894473269
new: 73.7793443759281
path: .spaces[252].spaces[7].metrics.mi.mi_visual_studio
old: 47.76839101278481
new: 47.09141135400659
Code
def forwardDeclareForType(self, t, config):
t = t.unroll()
if t.isGeckoInterface():
name = t.inner.identifier.name
try:
desc = config.getDescriptor(name)
self.add(desc.nativeType)
except NoSuchDescriptorError:
pass
# Note: SpiderMonkey interfaces are typedefs, so can't be
# forward-declared
elif t.isPromise():
self.addInMozillaDom("Promise")
elif t.isCallback():
self.addInMozillaDom(t.callback.identifier.name)
elif t.isDictionary():
self.addInMozillaDom(t.inner.identifier.name, isStruct=True)
elif t.isCallbackInterface():
self.addInMozillaDom(t.inner.identifier.name)
elif t.isUnion():
# Forward declare both the owning and non-owning version,
# since we don't know which one we might want
self.addInMozillaDom(CGUnionStruct.unionTypeName(t, False))
self.addInMozillaDom(CGUnionStruct.unionTypeName(t, True))
elif t.isRecord():
self.forwardDeclareForType(t.inner, config)
# Don't need to do anything for void, primitive, string, any or object.
# There may be some other cases we are missing.