accessible/xpcom/AccEventGen.py
author Masayuki Nakano <masayuki@d-toybox.com>
Mon, 26 Mar 2018 23:56:53 +0900
changeset 463914 222afb91d7d3e0338965dea63536dd28f5348811
parent 368904 1e0adeab3951ace3e93e94f91b475a3352940571
child 467733 40a027a1f2cf5318f96e97cef8a5a7a388cb0a20
permissions -rwxr-xr-x
Bug 1448876 - Get rid of nsIClipboardDragDropHooks and nsIClipboardDragDropHookList interfaces r=bz nsIClipboardDragDropHooks and nsIClipboardDragDropHookList allow XUL apps to customize drag and drop operation and paste operation. However, this feature was used only by ChatZilla and it doesn't work on Gecko anymore. So, we can get rid of them from our tree. MozReview-Commit-ID: Ibs3V1gI8Ry

#!/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

# 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)
    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 not e 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(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