Do all of the codegen with CGThings.
authorBobby Holley <bobbyholley@gmail.com>
Tue, 31 Jan 2012 18:58:23 +0100
changeset 85188 988157b08a4bb2ed92a78624aa15f8a344c845c8
parent 85187 688faf7ebf54fcf7434b1946d973687e2d71c44c
child 85189 394b1f82d6d3f6a88f5b57d3dc1360a5658c43c3
push id82
push userbobbyholley@gmail.com
push dateTue, 31 Jan 2012 18:00:24 +0000
milestone12.0a1
Do all of the codegen with CGThings.
dom/bindings/BindingGen.py
dom/bindings/Codegen.py
--- a/dom/bindings/BindingGen.py
+++ b/dom/bindings/BindingGen.py
@@ -12,79 +12,31 @@ def generate_binding_header(config, outp
     """
     |config| Is the configuration object.
     |outputprefix| is a prefix to use for the header guards and filename.
     """
 
     filename = outputprefix + ".h"
     print "Generating binding header: %s" % (filename)
     f = open(filename, 'w')
-
-    prologue = autogenerated_comment + """
-#ifndef mozilla_dom_bindings_%s_h__
-#define mozilla_dom_bindings_%s_h__
-
-#include "mozilla/dom/bindings/DOMJSClass.h"
-#include "mozilla/dom/bindings/Utils.h"
-
-""" % (outputprefix, outputprefix)
-
-    epilogue = """
-
-#endif // mozilla_dom_bindings_%s_h__
-""" % (outputprefix)
-
-    # Generate the tree.
-    root = CGRoot(config)
-
-    # Write recursively.
-    f.write(prologue)
+    root = CGRoot(config, outputprefix)
     f.write(root.declare())
-    f.write(epilogue)
     f.close()
 
 def generate_binding_cpp(config, outputprefix):
     """
     |config| Is the configuration object.
     |outputprefix| is a prefix to use for the header guards and filename.
     """
 
     filename = outputprefix + ".cpp"
     print "Generating binding implementation: %s" % (filename)
     f = open(filename, 'w')
-
-    parentIncludeTemplate = """#include "%sBinding.h"
-"""
-
-    implIncludeTemplate = """#include "%s"
-"""
-
-    includes = ""
-    for descriptor in config.getConcreteDescriptors():
-        parentInterface = descriptor.interface.parent
-        if parentInterface:
-            parentFileName = os.path.split(parentInterface.filename())[1].replace(".webidl", "");
-            includes += parentIncludeTemplate % parentFileName
-        includes += implIncludeTemplate % descriptor.headerFile
-
-    prologue = autogenerated_comment + """
-%s
-#include "%s.h"
-
-""" % (includes, outputprefix)
-
-    epilogue = """"""
-
-    # Generate the tree.
-    root = CGRoot(config)
-
-    # Write recursively.
-    f.write(prologue)
+    root = CGRoot(config, outputprefix)
     f.write(root.define())
-    f.write(epilogue)
     f.close()
 
 def main():
 
     # Parse arguments.
     from optparse import OptionParser
     usagestring = "usage: %prog [header|cpp] configFile outputPrefix webIDLFile"
     o = OptionParser(usage=usagestring)
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1,15 +1,16 @@
 # 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/.
 
 # Common codegen classes.
 
 import re
+import os
 
 class CGThing():
     """
     Abstract base case for things that spit out code.
     """
     def __init__(self):
         pass # Nothing for now
     def declare(self):
@@ -80,16 +81,55 @@ class CGNamespace(CGWrapper):
     def build(namespaces, child):
         """
         Static helper method to build multiple wrapped namespaces.
         """
         if not namespaces:
             return child
         return CGNamespace(namespaces[0], CGNamespace.build(namespaces[1:], child))
 
+class CGIncludeGuard(CGWrapper):
+    """
+    Generates include guards for a header.
+    """
+    def __init__(self, prefix, child):
+        """|prefix| is the filename without the extension."""
+        define = 'mozilla_dom_bindings_%s_h__' % prefix
+        CGWrapper.__init__(self, child,
+                           declarePre='#ifndef %s\n#define %s\n\n' % (define, define),
+                           declarePost='\n#endif // %s\n' % define)
+
+class CGHeaders(CGWrapper):
+    """
+    Generates the appropriate include statements.
+    """
+    def __init__(self, descriptors, declareIncludes, child):
+        """
+        Builds a set of include to cover |descriptors|.
+
+        Also includes the files in |declareIncludes| in the header file.
+        """
+        # Determine the filenames for which we need headers.
+        interfaceDeps = [d.interface for d in descriptors]
+        interfaceDeps.extend([d.parent for d in interfaceDeps if d.parent])
+        filenames = set([os.path.basename(d.filename()) for d in interfaceDeps])
+        bindingIncludes = ['mozilla/dom/bindings/' + f.replace('.webidl', 'Binding.h')
+                           for f in filenames]
+
+        # Grab all the implementation declaration files we need.
+        implementationIncludes = [f for f in set([d.headerFile for d in descriptors])]
+
+        # Let the machinery do its thing.
+        def _includeString(includes):
+            return ''.join(['#include "%s"\n' % i for i in includes]) + '\n'
+        CGWrapper.__init__(self, child,
+                           declarePre=_includeString(declareIncludes),
+                           definePre=_includeString(implementationIncludes)
+                                     + _includeString(bindingIncludes))
+
 class Argument():
     def __init__(self, argType, name):
         self.argType = argType
         self.name = name
     def __str__(self):
         return self.argType + ' ' + self.name
 
 class CGAbstractMethod(CGThing):
@@ -342,16 +382,33 @@ class CGDescriptor(CGThing):
         allCGThings = CGWrapper(allCGThings, post="\n")
         self.cgRoot = CGWrapper(CGNamespace(descriptor.name, allCGThings), post="\n")
     def declare(self):
         return self.cgRoot.declare()
     def define(self):
         return self.cgRoot.define()
 
 class CGRoot(CGThing):
-    def __init__(self, config):
-        descriptors = CGList([CGDescriptor(x) for x in config.getConcreteDescriptors()])
-        self.root = CGNamespace.build(['mozilla', 'dom', 'bindings', 'prototypes'],
-                                      CGWrapper(descriptors, pre="\n"))
+    def __init__(self, config, prefix):
+
+        # Do codegen for all the descriptors.
+        curr = CGList([CGDescriptor(x) for x in config.getConcreteDescriptors()])
+
+        # Wrap all of that in our namespaces.
+        curr = CGNamespace.build(['mozilla', 'dom', 'bindings', 'prototypes'],
+                                 CGWrapper(curr, pre="\n"))
+
+        # Add header includes.
+        curr = CGHeaders(config.getConcreteDescriptors(), ['DOMJSClass.h', 'Utils.h'], curr)
+
+        # Add include guards.
+        curr = CGIncludeGuard(prefix, curr)
+
+        # Add the auto-generated comment.
+        curr = CGWrapper(curr, pre="/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n")
+
+        # Store the final result.
+        self.root = curr
+
     def declare(self):
         return self.root.declare()
     def define(self):
         return self.root.define()