Bug 1161831 - Generate an extra macro to declare a non-virtual variant of an interface. r=billm
authorBobby Holley <bobbyholley@gmail.com>
Fri, 17 Jul 2015 14:22:58 -0700
changeset 254009 f659ec819bf6ecdeb04da10b00f3404ef6768a09
parent 254008 d82fc1a3328be4ade6b23933e26f467f4e37dcda
child 254010 cd49cae74a81362ffca63066f65a6bc345dbd2b3
push id29087
push usercbook@mozilla.com
push dateWed, 22 Jul 2015 12:01:23 +0000
treeherdermozilla-central@e7434cafdf2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1161831
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1161831 - Generate an extra macro to declare a non-virtual variant of an interface. r=billm This allows us to have a shared superclass that implements the guts of a shared superinterface, without having the superclass actually inherit the superinterface (which leads to annoying and unnecessary diamond-inheritance).
xpcom/idl-parser/xpidl/header.py
--- a/xpcom/idl-parser/xpidl/header.py
+++ b/xpcom/idl-parser/xpidl/header.py
@@ -57,20 +57,20 @@ def attributeParamlist(a, getter):
     l = ["%s%s" % (a.realtype.nativeType(getter and 'out' or 'in'),
                    attributeParamName(a))]
     if a.implicit_jscontext:
         l.insert(0, "JSContext* cx")
 
     return ", ".join(l)
 
 
-def attributeAsNative(a, getter):
+def attributeAsNative(a, getter, declType = 'NS_IMETHOD'):
         deprecated = a.deprecated and "NS_DEPRECATED " or ""
         params = {'deprecated': deprecated,
-                  'returntype': attributeReturnType(a, 'NS_IMETHOD'),
+                  'returntype': attributeReturnType(a, declType),
                   'binaryname': attributeNativeName(a, getter),
                   'paramlist': attributeParamlist(a, getter)}
         return "%(deprecated)s%(returntype)s %(binaryname)s(%(paramlist)s)" % params
 
 
 def methodNativeName(m):
     return m.binaryname is not None and m.binaryname or firstCap(m.name)
 
@@ -83,18 +83,18 @@ def methodReturnType(m, macro):
     elif m.nostdcall:
         return "%snsresult" % (macro == "NS_IMETHOD" and "virtual " or "")
     elif m.notxpcom:
         return "%s_(%s)" % (macro, m.realtype.nativeType('in').strip())
     else:
         return macro
 
 
-def methodAsNative(m):
-    return "%s %s(%s)" % (methodReturnType(m, 'NS_IMETHOD'),
+def methodAsNative(m, declType = 'NS_IMETHOD'):
+    return "%s %s(%s)" % (methodReturnType(m, declType),
                           methodNativeName(m),
                           paramlistAsNative(m))
 
 
 def paramlistAsNative(m, empty='void'):
     l = [paramAsNative(p) for p in m.params]
 
     if m.implicit_jscontext:
@@ -250,16 +250,21 @@ iface_prolog = """ {
 
 iface_epilog = """};
 
   NS_DEFINE_STATIC_IID_ACCESSOR(%(name)s, %(defname)s_IID)
 
 /* Use this macro when declaring classes that implement this interface. */
 #define NS_DECL_%(macroname)s """
 
+iface_nonvirtual = """
+
+/* Use this macro when declaring the members of this interface when the
+   class doesn't implement the interface. This is useful for forwarding. */
+#define NS_DECL_NON_VIRTUAL_%(macroname)s """
 
 iface_forward = """
 
 /* Use this macro to declare functions that forward the behavior of this interface to another object. */
 #define NS_FORWARD_%(macroname)s(_to) """
 
 iface_forward_safe = """
 
@@ -415,30 +420,36 @@ def write_interface(iface, fd):
                     write_method_decl(member)
                 elif key == xpidl.CDATA:
                     fd.write(" %s" % member.data)
                 else:
                     raise Exception("Unexpected interface member: %s" % member)
 
     fd.write(iface_epilog % names)
 
-    for member in iface.members:
-        if isinstance(member, xpidl.Attribute):
-            if member.infallible:
-                fd.write("\\\n  using %s::%s; " % (iface.name, attributeNativeName(member, True)))
-            fd.write("\\\n  %s override; " % attributeAsNative(member, True))
-            if not member.readonly:
-                fd.write("\\\n  %s override; " % attributeAsNative(member, False))
-        elif isinstance(member, xpidl.Method):
-            fd.write("\\\n  %s override; " % methodAsNative(member))
-    if len(iface.members) == 0:
-        fd.write('\\\n  /* no methods! */')
-    elif not member.kind in ('attribute', 'method'):
-        fd.write('\\')
+    def writeDeclaration(fd, iface, virtual):
+        declType = "NS_IMETHOD" if virtual else "NS_METHOD"
+        suffix = " override" if virtual else ""
+        for member in iface.members:
+            if isinstance(member, xpidl.Attribute):
+                if member.infallible:
+                    fd.write("\\\n  using %s::%s; " % (iface.name, attributeNativeName(member, True)))
+                fd.write("\\\n  %s%s; " % (attributeAsNative(member, True, declType), suffix))
+                if not member.readonly:
+                    fd.write("\\\n  %s%s; " % (attributeAsNative(member, False, declType), suffix))
+            elif isinstance(member, xpidl.Method):
+                fd.write("\\\n  %s%s; " % (methodAsNative(member, declType), suffix))
+        if len(iface.members) == 0:
+            fd.write('\\\n  /* no methods! */')
+        elif not member.kind in ('attribute', 'method'):
+            fd.write('\\')
 
+    writeDeclaration(fd, iface, True);
+    fd.write(iface_nonvirtual % names)
+    writeDeclaration(fd, iface, False);
     fd.write(iface_forward % names)
 
     def emitTemplate(forward_infallible, tmpl, tmpl_notxpcom=None):
         if tmpl_notxpcom is None:
             tmpl_notxpcom = tmpl
         for member in iface.members:
             if isinstance(member, xpidl.Attribute):
                 if forward_infallible and member.infallible: