mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 09:45:41 +00:00
4d1911e395
Summary:
This patch allows parsing generic types, such as Sequence<T>, in XPIDL. It does
this by introducing a new type, TypeId, which contains both the name string and
an optional list of generic parameters.
Various places which use the xpidl.py library had to be updated to construct one
of these TypeId objects, as TypeId and `str` are not compatible types.
Depends On D2106
Reviewers: mccr8!
Tags: #secure-revision
Bug #: 1474369
Differential Revision: https://phabricator.services.mozilla.com/D2109
252 lines
8.4 KiB
Python
Executable File
252 lines
8.4 KiB
Python
Executable File
#!/usr/bin/env python
|
|
#
|
|
# 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/.
|
|
|
|
import sys
|
|
import os
|
|
|
|
import buildconfig
|
|
import mozpack.path as mozpath
|
|
|
|
# The xpidl parser is not incorporated in the in-tree virtualenv.
|
|
xpidl_dir = mozpath.join(buildconfig.topsrcdir, 'xpcom', 'idl-parser',
|
|
'xpidl')
|
|
xpidl_cachedir = mozpath.join(buildconfig.topobjdir, 'xpcom', 'idl-parser',
|
|
'xpidl')
|
|
sys.path.extend([xpidl_dir, xpidl_cachedir])
|
|
import xpidl
|
|
|
|
# Load the webidl configuration file.
|
|
glbl = {}
|
|
execfile(mozpath.join(buildconfig.topsrcdir,
|
|
'dom', 'bindings', 'Bindings.conf'),
|
|
glbl)
|
|
webidlconfig = glbl['DOMInterfaces']
|
|
|
|
# Instantiate the parser.
|
|
p = xpidl.IDLParser()
|
|
|
|
|
|
def findIDL(includePath, interfaceFileName):
|
|
for d in includePath:
|
|
path = mozpath.join(d, interfaceFileName)
|
|
if os.path.exists(path):
|
|
return path
|
|
raise BaseException("No IDL file found for interface %s "
|
|
"in include path %r"
|
|
% (interfaceFileName, includePath))
|
|
|
|
|
|
def loadEventIDL(parser, includePath, eventname):
|
|
eventidl = ("nsIAccessible%s.idl" % eventname)
|
|
idlFile = findIDL(includePath, eventidl)
|
|
idl = p.parse(open(idlFile).read(), idlFile)
|
|
idl.resolve(includePath, p, webidlconfig)
|
|
return idl, idlFile
|
|
|
|
|
|
class Configuration:
|
|
def __init__(self, filename):
|
|
config = {}
|
|
execfile(filename, config)
|
|
self.simple_events = config.get('simple_events', [])
|
|
|
|
|
|
def firstCap(str):
|
|
return str[0].upper() + str[1:]
|
|
|
|
|
|
def writeAttributeParams(a):
|
|
return ("%s a%s" % (a.realtype.nativeType('in'), firstCap(a.name)))
|
|
|
|
|
|
def print_header_file(fd, conf, incdirs):
|
|
idl_paths = set()
|
|
|
|
fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n")
|
|
fd.write("#ifndef _mozilla_a11y_generated_AccEvents_h_\n"
|
|
"#define _mozilla_a11y_generated_AccEvents_h_\n\n")
|
|
fd.write("#include \"nscore.h\"\n")
|
|
fd.write("#include \"nsCOMPtr.h\"\n")
|
|
fd.write("#include \"nsCycleCollectionParticipant.h\"\n")
|
|
fd.write("#include \"nsString.h\"\n")
|
|
for e in conf.simple_events:
|
|
fd.write("#include \"nsIAccessible%s.h\"\n" % e)
|
|
for e in conf.simple_events:
|
|
idl, idl_path = loadEventIDL(p, incdirs, e)
|
|
idl_paths.add(idl_path)
|
|
for iface in filter(lambda p: p.kind == "interface", idl.productions):
|
|
classname = ("xpcAcc%s" % e)
|
|
baseinterfaces = interfaces(iface)
|
|
|
|
fd.write("\nclass %s final : public %s\n" % (classname, iface.name))
|
|
fd.write("{\n")
|
|
fd.write("public:\n")
|
|
|
|
attributes = allAttributes(iface)
|
|
args = map(writeAttributeParams, attributes)
|
|
fd.write(" %s(%s) :\n" % (classname, ", ".join(args)))
|
|
|
|
initializers = []
|
|
for a in attributes:
|
|
initializers.append("m%s(a%s)" % (firstCap(a.name), firstCap(a.name)))
|
|
fd.write(" %s\n {}\n\n" % ", ".join(initializers))
|
|
fd.write(" NS_DECL_CYCLE_COLLECTING_ISUPPORTS\n")
|
|
fd.write(" NS_DECL_CYCLE_COLLECTION_CLASS(%s)\n" % (classname))
|
|
|
|
for iface in filter(lambda i: i.name != "nsISupports", baseinterfaces):
|
|
fd.write(" NS_DECL_%s\n" % iface.name.upper())
|
|
|
|
fd.write("\nprivate:\n")
|
|
fd.write(" ~%s() {}\n\n" % classname)
|
|
for a in attributes:
|
|
fd.write(" %s\n" % attributeVariableTypeAndName(a))
|
|
fd.write("};\n\n")
|
|
|
|
fd.write("#endif\n")
|
|
|
|
return idl_paths
|
|
|
|
|
|
def interfaceAttributeTypes(idl):
|
|
ifaces = filter(lambda p: p.kind == "interface", idl.productions)
|
|
attributes = []
|
|
for i in ifaces:
|
|
ifaceAttributes = allAttributes(i)
|
|
attributes.extend(ifaceAttributes)
|
|
ifaceAttrs = filter(lambda a: a.realtype.nativeType("in").endswith("*"), attributes)
|
|
return map(lambda a: a.realtype.nativeType("in").strip(" *"), ifaceAttrs)
|
|
|
|
|
|
def print_cpp(idl, fd, conf, eventname):
|
|
for p in idl.productions:
|
|
if p.kind == 'interface':
|
|
write_cpp(eventname, p, fd)
|
|
|
|
|
|
def print_cpp_file(fd, conf, incdirs):
|
|
idl_paths = set()
|
|
fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n")
|
|
fd.write('#include "xpcAccEvents.h"\n')
|
|
|
|
includes = []
|
|
for e in conf.simple_events:
|
|
if e not in includes:
|
|
includes.append(("nsIAccessible%s" % e))
|
|
|
|
types = []
|
|
for e in conf.simple_events:
|
|
idl, idl_path = loadEventIDL(p, incdirs, e)
|
|
idl_paths.add(idl_path)
|
|
types.extend(interfaceAttributeTypes(idl))
|
|
|
|
for c in types:
|
|
fd.write("#include \"%s.h\"\n" % c)
|
|
|
|
fd.write("\n")
|
|
for e in conf.simple_events:
|
|
idl, idl_path = loadEventIDL(p, incdirs, e)
|
|
idl_paths.add(idl_path)
|
|
print_cpp(idl, fd, conf, e)
|
|
|
|
return idl_paths
|
|
|
|
|
|
def attributeVariableTypeAndName(a):
|
|
if a.realtype.nativeType('in').endswith('*'):
|
|
l = ["nsCOMPtr<%s> m%s;" % (a.realtype.nativeType('in').strip('* '),
|
|
firstCap(a.name))]
|
|
elif a.realtype.nativeType('in').count("nsAString"):
|
|
l = ["nsString m%s;" % firstCap(a.name)]
|
|
elif a.realtype.nativeType('in').count("nsACString"):
|
|
l = ["nsCString m%s;" % firstCap(a.name)]
|
|
else:
|
|
l = ["%sm%s;" % (a.realtype.nativeType('in'),
|
|
firstCap(a.name))]
|
|
return ", ".join(l)
|
|
|
|
|
|
def writeAttributeGetter(fd, classname, a):
|
|
fd.write("NS_IMETHODIMP\n")
|
|
fd.write("%s::Get%s(" % (classname, firstCap(a.name)))
|
|
if a.realtype.nativeType('in').endswith('*'):
|
|
fd.write("%s** a%s" % (a.realtype.nativeType('in').strip('* '), firstCap(a.name)))
|
|
elif a.realtype.nativeType('in').count("nsAString"):
|
|
fd.write("nsAString& a%s" % firstCap(a.name))
|
|
elif a.realtype.nativeType('in').count("nsACString"):
|
|
fd.write("nsACString& a%s" % firstCap(a.name))
|
|
else:
|
|
fd.write("%s*a%s" % (a.realtype.nativeType('in'), firstCap(a.name)))
|
|
fd.write(")\n")
|
|
fd.write("{\n")
|
|
if a.realtype.nativeType('in').endswith('*'):
|
|
fd.write(" NS_IF_ADDREF(*a%s = m%s);\n" % (firstCap(a.name), firstCap(a.name)))
|
|
elif a.realtype.nativeType('in').count("nsAString"):
|
|
fd.write(" a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name)))
|
|
elif a.realtype.nativeType('in').count("nsACString"):
|
|
fd.write(" a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name)))
|
|
else:
|
|
fd.write(" *a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name)))
|
|
fd.write(" return NS_OK;\n")
|
|
fd.write("}\n\n")
|
|
|
|
|
|
def interfaces(iface):
|
|
interfaces = []
|
|
while iface.base:
|
|
interfaces.append(iface)
|
|
iface = iface.idl.getName(xpidl.TypeId(iface.base), iface.location)
|
|
interfaces.append(iface)
|
|
interfaces.reverse()
|
|
return interfaces
|
|
|
|
|
|
def allAttributes(iface):
|
|
attributes = []
|
|
for i in interfaces(iface):
|
|
attrs = filter(lambda m: isinstance(m, xpidl.Attribute), i.members)
|
|
attributes.extend(attrs)
|
|
|
|
return attributes
|
|
|
|
|
|
def write_cpp(eventname, iface, fd):
|
|
classname = "xpcAcc%s" % eventname
|
|
attributes = allAttributes(iface)
|
|
ccattributes = filter(lambda m: m.realtype.nativeType('in').endswith('*'), attributes)
|
|
fd.write("NS_IMPL_CYCLE_COLLECTION(%s" % classname)
|
|
for c in ccattributes:
|
|
fd.write(", m%s" % firstCap(c.name))
|
|
fd.write(")\n\n")
|
|
|
|
fd.write("NS_IMPL_CYCLE_COLLECTING_ADDREF(%s)\n" % classname)
|
|
fd.write("NS_IMPL_CYCLE_COLLECTING_RELEASE(%s)\n\n" % classname)
|
|
|
|
fd.write("NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(%s)\n" % classname)
|
|
for baseiface in interfaces(iface):
|
|
fd.write(" NS_INTERFACE_MAP_ENTRY(%s)\n" % baseiface.name)
|
|
fd.write("NS_INTERFACE_MAP_END\n\n")
|
|
|
|
for a in attributes:
|
|
writeAttributeGetter(fd, classname, a)
|
|
|
|
|
|
def get_conf(conf_file):
|
|
conf = Configuration(conf_file)
|
|
inc_dir = [
|
|
mozpath.join(buildconfig.topsrcdir, 'accessible', 'interfaces'),
|
|
mozpath.join(buildconfig.topsrcdir, 'xpcom', 'base'),
|
|
]
|
|
return conf, inc_dir
|
|
|
|
|
|
def gen_files(fd, conf_file, xpidllex, xpidlyacc):
|
|
deps = set()
|
|
conf, inc_dir = get_conf(conf_file)
|
|
deps.update(print_header_file(fd, conf, inc_dir))
|
|
with open(os.path.join(os.path.dirname(fd.name), 'xpcAccEvents.cpp'), 'w') as cpp_fd:
|
|
deps.update(print_cpp_file(cpp_fd, conf, inc_dir))
|
|
return deps
|