public static TextFile Build_GetDelegate(string getDelegateFunctionName, Type delType) { TextFile tf = new TextFile(); TextFile tfFun = tf.Add("JSDataExchangeMgr.GetJSArg<{0}>(() => ", JSNameMgr.CsFullName(delType)).BraceIn(); { TextFile tfIf = tfFun.Add("if (JSApi.isFunctionS((int)JSApi.GetType.Arg))").BraceIn(); { tfIf.Add("return {0}(JSApi.getFunctionS((int)JSApi.GetType.Arg));", getDelegateFunctionName); tfIf.BraceOut(); } TextFile tfElse = tfFun.Add("else").BraceIn(); { tfElse.Add("return ({0})JSMgr.datax.getObject((int)JSApi.GetType.Arg);", JSNameMgr.CsFullName(delType)); tfElse.BraceOut(); } tfFun.BraceOut().Add(");"); } return(tf); }
static TextFile GenEnum() { TextFile tf = new TextFile(); string typeName = type.ToString(); // tf.AddLine().Add("// {0}", typeName); // remove name space int lastDot = typeName.LastIndexOf('.'); if (lastDot >= 0) { typeName = typeName.Substring(lastDot + 1); } if (typeName.IndexOf('+') >= 0) { return(null); } TextFile tfDef = tf.Add("Bridge.define(\"{0}\", {{", JSNameMgr.JsFullName(type)).In(); tfDef.Add("$kind: \"enum\","); TextFile tfSta = tfDef.Add("statics: {").In(); Type uType = Enum.GetUnderlyingType(type); FieldInfo[] fields = type.GetFields(BindingFlags.GetField | BindingFlags.Public | BindingFlags.Static); for (int i = 0; i < fields.Length; i++) { string v = ""; if (uType == typeof(ulong)) { v = System.Convert.ToUInt64(fields[i].GetValue(null)).ToString(); } else { v = System.Convert.ToInt64(fields[i].GetValue(null)).ToString(); } tfSta.Add("{0}: {1}{2}", fields[i].Name, v, i == fields.Length - 1 ? "" : ","); } tfSta.BraceOut(); //tfDef.BraceOutSC(); tfDef.Out().Add("});"); return(tf); }
static void GenAMessage(Info info) { TextFile tf = new TextFile(null, "// auto gen"); tf.Add("using UnityEngine;"); tf.Add("using UnityEngine.UI;"); tf.AddLine(); TextFile tfNs = tf.Add("namespace jsb").BraceIn(); { TextFile tfC = tfNs.Add("public class {0} : MonoBehaviour", info.className).BraceIn(); { TextFile tfM = tfC.Add("public void {0}", info.signature).BraceIn(); { tfM.Add("JSComponent[] coms = GetComponents<JSComponent>();") .Add("if (coms == null || coms.Length == 0)") .BraceIn() .Add("Destroy(this);") .Add("return;") .BraceOut() .AddLine() .Add("foreach (var com in coms)"); TextFile tfF = tfM.BraceIn(); { tfF.Add("com.RecvMsg({0});", info.argList); } tfF.BraceOut(); } tfM.BraceOut(); } tfC.BraceOut(); } tfNs.BraceOut(); string s = tf.Format(-1); File.WriteAllText(CsDir + "/" + info.className + ".cs", s); }
static void GenMMgr(string className) { TextFile tf = new TextFile(null, "// auto gen"); tf.Add("using UnityEngine;"); tf.Add("using UnityEngine.UI;"); tf.Add("using System;"); tf.Add("using System.Collections;"); tf.Add("using System.Collections.Generic;"); tf.Add("using jsb;"); tf.AddLine(); TextFile tfNs = tf.Add("namespace jsb").BraceIn(); { TextFile tfC = tfNs.Add("public class {0}", className).BraceIn(); { tfC.Add("static Dictionary<string, int[]> jID = new Dictionary<string, int[]>();"); { tfC.AddMultiline(@" static int[] GetJsClassMessages(string jsFullName) { if (jID.ContainsKey(jsFullName)) return jID[jsFullName]; if (!JSMgr.vCall.CallJSFunctionName(JSCache.GetBridgeJsID(), ""getLMsgs"", jsFullName)) throw new Exception(""call Bridge.getLMsgs failed!""); string str = JSApi.getStringS((int)JSApi.GetType.JSFunRet); if (string.IsNullOrEmpty(str)) { jID[jsFullName] = null; return null; } string[] arr = str.Split(','); int[] r = new int[arr.Length]; for (int i = 0; i < arr.Length; i++) r[i] = int.Parse(arr[i]); jID[jsFullName] = r; return r; }"); } tfC.AddLine(); { tfC.AddMultiline(@" public static void CreateMessages(string jsFullName, GameObject go) { int[] ids = GetJsClassMessages(jsFullName); if (ids == null) return; // ID号 JS和CS保持一致才不会错 for (int i = 0; i < ids.Length; i++) { Type type = MessageTypes[ids[i]]; if (go.GetComponent(type) == null) go.AddComponent(type); } }"); } tfC.AddLine(); { TextFile tfM = tfC.Add("static Type[] MessageTypes = new Type[]").BraceIn(); { for (int i = 0; i < infos.Length; i++) { Info info = infos[i]; tfM.Add("typeof(jsb.{0}),", info.className); } } tfM.BraceOutSC(); } } tfC.BraceOut(); } tfNs.BraceOut(); string s = tf.Format(-1); File.WriteAllText(CsDir + "/" + className + ".cs", s); }
static void GenEnum(Type type, TypeStatus ts, Func <Type, TypeStatus> getParent, Action <Type> onNewType) { TextFile tfFile = null; if (type.DeclaringType != null) { onNewType(type.DeclaringType); ts.IsInnerType = true; TypeStatus tsParent = getParent(type.DeclaringType); if (tsParent == null || tsParent.status == TypeStatus.Status.Wait) { return; } if (tsParent.status == TypeStatus.Status.Ignored) { ts.status = TypeStatus.Status.Ignored; return; } tfFile = tsParent.tf.FindByTag("epos"); } if (tfFile == null) { tfFile = new TextFile(); } ts.tf = tfFile; ts.status = TypeStatus.Status.Exported; //GeneratorHelp.ATypeInfo ti = GeneratorHelp.CreateTypeInfo(type); StringBuilder sb = new StringBuilder(); TextFile tfNs = tfFile; if (type.DeclaringType == null && !string.IsNullOrEmpty(type.Namespace)) { tfNs = tfFile.Add("namespace {0}", type.Namespace).BraceIn(); tfNs.BraceOut(); } tfNs.Add("[Bridge.FileName(\"csw\")]"); Type uType = Enum.GetUnderlyingType(type); TextFile tfClass = null; sb.Remove(0, sb.Length); { if (type.IsPublic || type.IsNestedPublic) { sb.Append("public "); } sb.Append("enum "); sb.Append(type.Name); if (uType != typeof(int)) { sb.AppendFormat(" : {0}", uType.CsFullName()); } tfClass = tfNs.Add(sb.ToString()).BraceIn(); tfClass.BraceOut(); } FieldInfo[] fields = type.GetFields(BindingFlags.GetField | BindingFlags.Public | BindingFlags.Static); for (int i = 0; i < fields.Length; i++) { FieldInfo field = fields[i]; string v = ""; if (uType == typeof(ulong)) { v = System.Convert.ToUInt64(field.GetValue(null)).ToString(); } else { v = System.Convert.ToInt64(field.GetValue(null)).ToString(); } tfClass.Add("{0} = {1},", field.Name, v); } }
static void GenInterfaceOrStructOrClass(Type type, TypeStatus ts, Func <Type, TypeStatus> getParent, Action <Type> onNewType) { TextFile tfFile = null; if (type.DeclaringType != null) { ts.IsInnerType = true; TypeStatus tsParent = getParent(type.DeclaringType); if (tsParent == null || tsParent.status == TypeStatus.Status.Wait) { return; } if (tsParent.status == TypeStatus.Status.Ignored) { ts.status = TypeStatus.Status.Ignored; return; } tfFile = tsParent.tf.FindByTag("epos"); } if (tfFile == null) { tfFile = new TextFile(); } ts.tf = tfFile; ts.status = TypeStatus.Status.Exported; GeneratorHelp.ATypeInfo ti = GeneratorHelp.CreateTypeInfo(type); StringBuilder sb = new StringBuilder(); TextFile tfNs = tfFile; //string dir = Dir; if (type.DeclaringType == null && !string.IsNullOrEmpty(type.Namespace)) { tfNs = tfFile.Add("namespace {0}", type.Namespace).BraceIn(); tfNs.BraceOut(); } tfNs.Add("[Bridge.FileName(\"csw\")]"); TextFile tfClass = null; sb.Remove(0, sb.Length); { if (type.IsPublic || type.IsNestedPublic) { sb.Append("public "); } if (type.IsClass) { if (type.IsAbstract && type.IsSealed) { sb.Append("static "); } //else if (type.IsAbstract) // sb.Append("abstract "); //else if (type.IsSealed) // sb.Append("sealed "); //if (type.is) } if (type.IsInterface) { sb.Append("interface "); } else if (type.IsValueType) { sb.Append("struct "); } else { sb.Append("class "); } string className = type.CsFullName(CsNameOption.CompilableWithT); int dot = className.LastIndexOf("."); if (dot >= 0) { className = className.Substring(dot + 1); } sb.Append(className); Type vBaseType = type.ValidBaseType(); Type[] interfaces = type.GetDeclaringInterfaces(); if (vBaseType != null || interfaces.Length > 0) { sb.Append(" : "); args a = new args(); if (vBaseType != null) { a.Add(typefn(vBaseType, type.Namespace)); onNewType(vBaseType); } foreach (var i in interfaces) { a.Add(typefn(i, type.Namespace)); onNewType(i); } sb.Append(a.ToString()); } tfClass = tfNs.Add(sb.ToString()).BraceIn(); tfClass.BraceOut(); } tfClass.AddTag("epos"); for (int i = 0; i < ti.Fields.Count; i++) { MemberInfoEx infoEx = ti.Fields[i]; FieldInfo field = infoEx.member as FieldInfo; tfClass.Add("public {0}{1} {2};", (field.IsStatic ? "static " : ""), typefn(field.FieldType, type.Namespace), field.Name); onNewType(field.FieldType); } if (ti.Fields.Count > 0) { tfClass.AddLine(); } for (int i = 0; i < ti.Cons.Count; i++) { MemberInfoEx infoEx = ti.Cons[i]; ConstructorInfo con = infoEx.member as ConstructorInfo; if (type.IsValueType) { // 结构体不需要无参数构造函数 if (con == null || con.GetParameters().Length == 0) { continue; } } string ctorName = type.Name; if (type.IsGenericTypeDefinition) { int flag = ctorName.LastIndexOf('`'); if (flag >= 0) { ctorName = ctorName.Substring(0, flag); } } tfClass.Add("public extern {0}({1});", ctorName, con == null ? "" : Ps2String(type, con.GetParameters())); if (con != null) { foreach (var p in con.GetParameters()) { onNewType(p.ParameterType); } } } if (ti.Cons.Count > 0) { tfClass.AddLine(); } handlePros(tfClass, type, ti, onNewType); if (ti.Pros.Count > 0) { tfClass.AddLine(); } handleMethods(tfClass, type, ti, onNewType); if (!type.IsInterface) { handleInterfaceProblems(tfClass, type, onNewType); } }
static void GenDelegate(Type type, TypeStatus ts, Func <Type, TypeStatus> getParent, Action <Type> onNewType) { TextFile tfFile = null; if (type.DeclaringType != null) { ts.IsInnerType = true; TypeStatus tsParent = getParent(type.DeclaringType); if (tsParent == null || tsParent.status == TypeStatus.Status.Wait) { return; } if (tsParent.status == TypeStatus.Status.Ignored) { ts.status = TypeStatus.Status.Ignored; return; } tfFile = tsParent.tf.FindByTag("epos"); } if (tfFile == null) { tfFile = new TextFile(); } ts.tf = tfFile; ts.status = TypeStatus.Status.Exported; StringBuilder sb = new StringBuilder(); TextFile tfNs = tfFile; if (type.DeclaringType == null && !string.IsNullOrEmpty(type.Namespace)) { tfNs = tfFile.Add("namespace {0}", type.Namespace).BraceIn(); tfNs.BraceOut(); } if (type.IsPublic || type.IsNestedPublic) { sb.Append("public "); } sb.Append("delegate "); MethodInfo method = type.GetMethod("Invoke"); sb.Append(typefn(method.ReturnType, type.Namespace)); sb.Append(" "); onNewType(method.ReturnType); ParameterInfo[] ps = method.GetParameters(); { sb.AppendFormat("{0}({1});", // type.Name, typefn(type, "no-namespace", CsNameOption.CompilableWithT), Ps2String(type, ps)); foreach (var p in ps) { onNewType(p.ParameterType); } } tfNs.Add(sb.ToString()); }
public static TextFile Build_DelegateFunction(Type classType, MemberInfo memberInfo, Type delType, int methodTag, int argIndex) { // building a closure // a function having a up-value: jsFunction string getDelFunctionName = GetMethodArg_DelegateFuncionName(classType, memberInfo.Name, methodTag, argIndex); TextFile tf = new TextFile(); MethodInfo delInvoke = delType.GetMethod("Invoke"); ParameterInfo[] ps = delInvoke.GetParameters(); Type returnType = delType.GetMethod("Invoke").ReturnType; var argsParam = new args(); for (int i = 0; i < ps.Length; i++) { argsParam.Add(ps[i].Name); } // format as <t,u,v> string stringTOfMethod = string.Empty; if (delType.ContainsGenericParameters) { var arg = new args(); foreach (var t in delType.GetGenericArguments()) { arg.Add(t.Name); } stringTOfMethod = arg.Format(args.ArgsFormat.GenericT); } // this function name is used in BuildFields, don't change TextFile tfFun = tf.Add("public static {0} {1}{2}(CSRepresentedObject objFunction)", JSNameMgr.CsFullName(delType, CsNameOption.CompilableWithT), // [0] getDelFunctionName, // [2] stringTOfMethod // [1] ) .BraceIn(); { tfFun.Add("if (objFunction == null || objFunction.jsObjID == 0)") .In() .Add("return null;") .Out() .AddLine(); tfFun.Add("{0} action = JSMgr.getJSFunCSDelegateRel<{0}>(objFunction.jsObjID);", JSNameMgr.CsFullName(delType, CsNameOption.CompilableWithT)); tfFun.Add("if (action != null)") .In() .Add("return action;") .Out() .AddLine(); TextFile tfAction = tfFun.Add("action = ({0}) => ", argsParam.Format(args.ArgsFormat.OnlyList)) .BraceIn(); { tfAction.Add("JSMgr.vCall.CallJSFunctionValue(0, objFunction.jsObjID{0}{1});", (argsParam.Count > 0) ? ", " : "", argsParam); if (returnType != typeof(void)) { tfAction.Add("return (" + JSNameMgr.CsFullName(returnType) + ")" + JSDataExchangeEditor.Get_GetJSReturn(returnType) + ";"); } tfAction.BraceOutSC(); } tfFun.Add("JSMgr.addJSFunCSDelegateRel(objFunction.jsObjID, action);") .Add("return action;\n"); tfFun.BraceOut(); } return(tf); }
static void GenInterfaceOrStructOrClass(Type type, TypeStatus ts, Func <Type, TypeStatus> getParent, Action <Type> onNewType) { TextFile tfFile = null; if (type.DeclaringType != null) { ts.IsInnerType = true; TypeStatus tsParent = getParent(type.DeclaringType); if (tsParent == null || tsParent.status == TypeStatus.Status.Wait) { if (tsParent == null) { onNewType(type.DeclaringType); } return; } if (tsParent.status == TypeStatus.Status.Ignored) { ts.status = TypeStatus.Status.Ignored; return; } tfFile = tsParent.tf.FindByTag("epos"); } if (tfFile == null) { tfFile = new TextFile(); } ts.tf = tfFile; ts.status = TypeStatus.Status.Exported; GeneratorHelp.ATypeInfo ti = GeneratorHelp.CreateTypeInfo(type); StringBuilder sb = new StringBuilder(); TextFile tfNs = tfFile; //string dir = Dir; // // ignore Experimental @eugenejiang // if (type.Namespace != null && type.Namespace.IndexOf("UnityEngine.Experimental.") >= 0) { // return; // } if (type.DeclaringType == null && !string.IsNullOrEmpty(type.Namespace)) { tfNs = tfFile.Add("namespace {0}", type.Namespace).BraceIn(); tfNs.BraceOut(); } GenAttributeForClassIfNeeded(type, tfNs); // multiple attributes // tfNs.Add("[Bridge.External]"); TextFile tfClass = null; sb.Remove(0, sb.Length); { // force public if (type.IsPublic || type.IsNestedPublic || type.IsNested || type.IsNestedFamily) { sb.Append("public "); } // if (type.IsNestedFamily) { // sb.Append("protected "); // } // if (type.FullName.IndexOf("DropdownItem") >= 0) { // Debug.Assert(false); // } if (type.IsClass) { if (type.IsAbstract && type.IsSealed) { sb.Append("static "); } //else if (type.IsAbstract) // sb.Append("abstract "); //else if (type.IsSealed) // sb.Append("sealed "); //if (type.is) } if (type.IsInterface) { sb.Append("interface "); } else if (type.IsValueType) { sb.Append("struct "); } else { sb.Append("class "); } string className = type.CsFullName(CsNameOption.CompilableWithT); int dot = className.LastIndexOf("."); if (dot >= 0) { className = className.Substring(dot + 1); } sb.Append(className); Type vBaseType = type.ValidBaseType(); Type[] interfaces = type.GetDeclaringInterfaces(); if (vBaseType != null || interfaces.Length > 0) { sb.Append(" : "); args a = new args(); if (vBaseType != null) { a.Add(typefn(vBaseType, type.Namespace, CsNameOption.CompilableWithT)); onNewType(vBaseType); } foreach (var i in interfaces) { a.Add(typefn(i, type.Namespace, CsNameOption.CompilableWithT)); onNewType(i); } sb.Append(a.ToString()); } tfClass = tfNs.Add(sb.ToString()).BraceIn(); tfClass.BraceOut(); } tfClass.AddTag("epos"); if (handleEvents(tfClass, type, onNewType)) { tfClass.AddLine(); } for (int i = 0; i < ti.Fields.Count; i++) { MemberInfoEx infoEx = ti.Fields[i]; FieldInfo field = infoEx.member as FieldInfo; var publicOrProtected = "public"; if (field.IsFamily) { // publicOrProtected = "protected"; } if (field.IsLiteral && !field.IsInitOnly) { { var attributes = field.GetCustomAttributes(); foreach (var attr in attributes) { tfClass.Add("[{0}]", attr.GetType().Name); onNewType(attr.GetType()); } } if ("string" == typefn(field.FieldType, type.Namespace)) { tfClass.Add(publicOrProtected + " const {0} {1} = \"{2}\";", typefn(field.FieldType, type.Namespace), field.Name, field.GetValue(null)); } else if ("float" == typefn(field.FieldType, type.Namespace)) { var fv = (float)field.GetValue(null); string defaultvalue; if (float.IsNaN(fv)) { defaultvalue = "float.NaN"; } else if (float.IsPositiveInfinity(fv)) { defaultvalue = "float.PositiveInfinity"; } else if (float.IsNegativeInfinity(fv)) { defaultvalue = "float.NegativeInfinity"; } else { defaultvalue = fv + "f"; } tfClass.Add(publicOrProtected + " const {0} {1} = {2};", typefn(field.FieldType, type.Namespace), field.Name, defaultvalue); } else { tfClass.Add(publicOrProtected + " const {0} {1} = {2};", typefn(field.FieldType, type.Namespace), field.Name, field.GetValue(null)); } } else { tfClass.Add(publicOrProtected + " {0}{1} {2};", (field.IsStatic ? "static " : ""), typefn(field.FieldType, type.Namespace), field.Name); } onNewType(field.FieldType); } if (ti.Fields.Count > 0) { tfClass.AddLine(); } // Constructors for (int i = 0; i < ti.Cons.Count; i++) { MemberInfoEx infoEx = ti.Cons[i]; ConstructorInfo con = infoEx.member as ConstructorInfo; if (type.IsValueType) { // 结构体不需要无参数构造函数 if (con == null || con.GetParameters().Length == 0) { continue; } } string ctorName = type.Name; if (type.IsGenericTypeDefinition) { int flag = ctorName.LastIndexOf('`'); if (flag >= 0) { ctorName = ctorName.Substring(0, flag); } } var constructorBuilder = new StringBuilder(); var paras = con == null ? "" : Ps2String(type, con.GetParameters()); constructorBuilder.Append($"public {ctorName}({paras})"); var baseType = type.ValidBaseType(); if (baseType != null && !HasDefaultConstructor(baseType)) { constructorBuilder.Append($" : base({BaseConstructorParameters(baseType)})"); } constructorBuilder.Append(" { throw new Exception(\"not impl\"); }"); tfClass.Add(constructorBuilder.ToString()); if (con != null) { foreach (var p in con.GetParameters()) { onNewType(p.ParameterType); } } } if (ti.Cons.Count > 0) { tfClass.AddLine(); } handlePros(tfClass, type, ti, onNewType); if (ti.Pros.Count > 0) { tfClass.AddLine(); } handleMethods(tfClass, type, ti, onNewType); if (!type.IsInterface) { handleInterfaceProblems(tfClass, type, onNewType); } }