Back to index

lightning-sunbird  0.9+nobinonly
generate-interfaces.cs
Go to the documentation of this file.
00001 using System;
00002 using Mozilla.XPCOM;
00003 using System.Reflection;
00004 using System.Reflection.Emit;
00005 using System.Collections;
00006 
00007 public class Generate
00008 {
00009     ModuleBuilder mb;
00010     Hashtable ifaceTable = new Hashtable();
00011     bool verbose = false;
00012     PropertyBuilder lastProperty = null;
00013     const PropertyAttributes PROPERTY_ATTRS = PropertyAttributes.None;
00014     const MethodAttributes METHOD_ATTRS = MethodAttributes.Public |
00015             MethodAttributes.Abstract | MethodAttributes.Virtual |
00016             MethodAttributes.NewSlot;
00017 
00018     Type FixupInterfaceType(TypeInfo.ParamDescriptor desc)
00019     {
00020         try {
00021             String ifaceName = desc.GetInterfaceName();
00022             return EmitOneInterface(ifaceName);
00023         } catch (Exception e) {
00024             Console.WriteLine(e);
00025             return typeof(object);
00026         }
00027     }
00028 
00029     void GenerateInterfaceMethod(TypeBuilder tb,
00030                                  TypeInfo.MethodDescriptor desc)
00031     {
00032         if (desc == null || !desc.IsVisible())
00033             return;
00034 
00035         MethodAttributes methodAttrs = METHOD_ATTRS;
00036 
00037         String methodName = desc.name;
00038         if (desc.IsGetter()) {
00039             methodName = "get_" + desc.name;
00040             methodAttrs |= MethodAttributes.SpecialName;
00041         } else if (desc.IsSetter()) {
00042             methodName = "set_" + desc.name;
00043             methodAttrs |= MethodAttributes.SpecialName;
00044         }
00045             
00046         // Fix up interface types in parameters
00047         Type ret = desc.resultType;
00048         if (ret == typeof(object))
00049             ret = FixupInterfaceType(desc.args[desc.args.Length - 1]);
00050         Type[] argTypes = (Type[])desc.argTypes.Clone();
00051         for (int i = 0; i < argTypes.Length; i++) {
00052             if (argTypes[i] == typeof(object))
00053                 argTypes[i] = FixupInterfaceType(desc.args[i]);
00054         }
00055         MethodBuilder meth = tb.DefineMethod(methodName, methodAttrs, ret,
00056                                              argTypes);
00057 
00058         if (desc.IsSetter()) {
00059             if (lastProperty != null && lastProperty.Name == desc.name) {
00060                 lastProperty.SetSetMethod(meth);
00061             } else {
00062                 tb.DefineProperty(desc.name, PROPERTY_ATTRS, ret, new Type[0])
00063                     .SetSetMethod(meth);
00064             }
00065             lastProperty = null;
00066         } else if (desc.IsGetter()) {
00067             lastProperty = tb.DefineProperty(desc.name, PROPERTY_ATTRS, ret,
00068                                              new Type[0]);
00069             lastProperty.SetGetMethod(meth);
00070         } else {
00071             lastProperty = null;
00072         }
00073     }
00074 
00075     Type EmitOneInterface(String name)
00076     {
00077         if (ifaceTable.ContainsKey(name))
00078             return (Type)ifaceTable[name];
00079         Console.WriteLine("Interface: {0}", name);
00080         
00081         ushort inheritedMethodCount;
00082         String parentName = TypeInfo.GetParentInfo(name,
00083                                                    out inheritedMethodCount);
00084         Type parentType;
00085 
00086         if (parentName == null)
00087             parentType = typeof(object);
00088         else
00089             parentType = EmitOneInterface(parentName);
00090 
00091         Console.WriteLine ("Emitting: " + name + " : " + parentType);
00092 
00093         TypeBuilder ifaceTb = mb.DefineType("Mozilla.XPCOM.Interfaces." + name,
00094                                             TypeAttributes.Public | 
00095                                             TypeAttributes.Interface |
00096                                             TypeAttributes.Abstract,
00097                                             parentType);
00098         ifaceTable.Add(name, ifaceTb);
00099 
00100         TypeInfo.MethodDescriptor[] descs;
00101         try {
00102             descs = TypeInfo.GetMethodData(name);
00103         } catch (Exception ex) {
00104             Console.WriteLine("skipping interface {0}: {1}", name,
00105                               ex.Message);
00106             return null;
00107         }
00108 
00109         if (descs == null) {
00110             Console.WriteLine("No descs!");
00111             return null;
00112         }
00113 
00114         if (verbose) {
00115             Console.WriteLine("{0} has {1} methods ({2} inherited from {3})",
00116                               name, descs.Length, inheritedMethodCount,
00117                               parentName);
00118         }
00119         for (int i = inheritedMethodCount; i < descs.Length; i++) {
00120             GenerateInterfaceMethod(ifaceTb, descs[i]);
00121         }
00122 
00123         ifaceTb.CreateType();
00124         return ifaceTb;
00125     }
00126 
00127     void GenerateInterfaceAssembly(string[] args)
00128     {
00129         String dllName = args[0];
00130         String onlyInterface = null;
00131         if (args.Length > 1)
00132             onlyInterface = args[1];
00133         AssemblyName an = new AssemblyName();
00134         an.Version = new Version(1, 0, 0, 0);
00135         an.Name = "Mozilla.XPCOM.Interfaces";
00136         
00137         AssemblyBuilder ab = AppDomain.CurrentDomain.
00138             DefineDynamicAssembly(an, AssemblyBuilderAccess.RunAndSave);
00139         mb = ab.DefineDynamicModule(an.Name, dllName);
00140 
00141         if (onlyInterface != null) {
00142             verbose = true;
00143             EmitOneInterface(onlyInterface);
00144         } else {
00145             IntPtr e = TypeInfo.typeinfo_EnumerateInterfacesStart();
00146             if (e == IntPtr.Zero)
00147                 return;
00148             
00149             while (true) {
00150                 String name = TypeInfo.typeinfo_EnumerateInterfacesNext(e);
00151                 if (name == null)
00152                     break;
00153                 EmitOneInterface(name);
00154             }
00155             
00156             TypeInfo.typeinfo_EnumerateInterfacesStop(e);
00157         }
00158 
00159         ab.Save(dllName);
00160 
00161         Console.WriteLine("Generated metadata for {0} interfaces in {1}",
00162                           ifaceTable.Count, dllName);
00163     }
00164     
00165     public static void Main(String[] args)
00166     {
00167         Components.Init();
00168         
00169         Generate gen = new Generate();
00170         gen.GenerateInterfaceAssembly(args);
00171     }
00172 }