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); }
public static string GetMethodArg_DelegateFuncionName(Type classType, string methodName, int methodTag, int argIndex) { // append Method Index if still conflicts StringBuilder sb = new StringBuilder(); sb.AppendFormat("{0}_{1}_GetDelegate_member{2}_arg{3}", classType.Name, methodName, methodTag, argIndex); return(JSNameMgr.HandleFunctionName(sb.ToString())); }
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 string typefn(Type tType, string eraseNs, CsNameOption opt = CsNameOption.Compilable) { string fn = JSNameMgr.CsFullName(tType, opt); if (eraseNs == "no-namespace") { int dot = fn.LastIndexOf('.'); if (dot >= 0) { fn = fn.Substring(dot + 1); } } else if (!string.IsNullOrEmpty(eraseNs) && fn.StartsWith(eraseNs + ".")) { fn = fn.Substring(eraseNs.Length + 1); } return(fn); }
public TextFile Get_GetParam(Type t) { elementType = t.GetElementType(); if (elementType.IsArray) { //...error } bool needCast; string getVal = JSDataExchangeMgr.GetMetatypeKeyword(elementType, out needCast); var arrayFullName = string.Empty; var elementFullName = string.Empty; if (elementType.IsGenericParameter) { arrayFullName = "object[]"; elementFullName = "object"; } else { arrayFullName = JSNameMgr.CsFullName(t); elementFullName = JSNameMgr.CsFullName(elementType); } TextFile tf = new TextFile(); tf.AddMultiline(@"JSDataExchangeMgr.GetJSArg<{0}>(() => {{ int jsObjID = JSApi.getObject((int)JSApi.GetType.Arg); int length = jsObjID == 0 ? 0 : JSApi.getArrayLength(jsObjID); var ret = new {1}[length]; for (var i = 0; i < length; i++) {{ JSApi.getElement(jsObjID, i); ret[i] = ({1}){2}((int)JSApi.GetType.SaveAndRemove); }} return ret; }})", arrayFullName, elementFullName, getVal); return(tf); }
public string Get_Return(string expVar) { if (elementType == null) { Debug.LogError("JSDataExchange_Arr elementType == null !!"); return(""); } StringBuilder sb = new StringBuilder(); bool needCast; string getValMethod = JSDataExchangeMgr.GetMetatypeKeyword(elementType, out needCast).Replace("get", "set"); // 2015.Sep.2 // +判断arrRet为null的情况 if (elementType.ContainsGenericParameters) { sb.AppendFormat(" var arrRet = (Array){0};\n", expVar) .AppendFormat(" for (int i = 0; arrRet != null && i < arrRet.Length; i++)\n") .Append(" [[\n") .AppendFormat(" {0}((int)JSApi.SetType.SaveAndTempTrace, arrRet.GetValue(i));\n", getValMethod) .AppendFormat(" JSApi.moveSaveID2Arr(i);\n") .AppendFormat(" ]]\n") .AppendFormat(" JSApi.setArrayS((int)JSApi.SetType.Rval, (arrRet != null ? arrRet.Length : 0), true);"); } else { sb.AppendFormat(" var arrRet = ({0}[]){1};\n", JSNameMgr.CsFullName(elementType), expVar) .AppendFormat(" for (int i = 0; arrRet != null && i < arrRet.Length; i++)\n") .Append(" [[\n") .AppendFormat(" {0}((int)JSApi.SetType.SaveAndTempTrace, {1}arrRet[i]);\n", getValMethod, elementType.IsEnum ? "(int)" : "") .AppendFormat(" JSApi.moveSaveID2Arr(i);\n") .AppendFormat(" ]]\n") .AppendFormat(" JSApi.setArrayS((int)JSApi.SetType.Rval, (arrRet != null ? arrRet.Length : 0), true);"); } sb.Replace("[[", "{"); sb.Replace("]]", "}"); return(sb.ToString()); }
public static bool CheckClasses(out Type[] arrEnums, out Type[] arrClasses, out HashSet <string> bridgeTypes) { arrEnums = null; arrClasses = null; var sb = new StringBuilder(); bool ok = true; bridgeTypes = LoadBridgeDefinedTypes(); foreach (var e in enums) { if (bridgeTypes.Contains(e.FullName)) { sb.AppendFormat("Bridge已包含\"{0}\",无需导出", e.FullName); ok = false; continue; } } if (ok) { arrEnums = enums; } HashSet <Type> wanted = new HashSet <Type>(); foreach (var type in classes) { if (typeof(System.Delegate).IsAssignableFrom(type)) { sb.AppendFormat("Delegate \"{0}\" 不能导出\n", JSNameMgr.CsFullName(type)); ok = false; continue; } if (type.IsGenericType && !type.IsGenericTypeDefinition) { sb.AppendFormat("\"{0}\" 不能导出,换成 \"{1}\"\n", JSNameMgr.CsFullName(type), JSNameMgr.CsFullName(type.GetGenericTypeDefinition())); ok = false; continue; } if (type.IsInterface) { sb.AppendFormat("接口 \"{0}\" 不需要配置。如果有配置继承这个接口的类,则这个接口会自动添加\n", JSNameMgr.CsFullName(type)); ok = false; continue; } if (wanted.Contains(type)) { sb.AppendFormat("\"{0}\" 配了多个.\n", JSNameMgr.CsFullName(type)); ok = false; continue; } if (bridgeTypes.Contains(type.FullName)) { sb.AppendFormat("Bridge已包含\"{0}\",无需导出", type.FullName); ok = false; continue; } wanted.Add(type); } // 自动添加基类 foreach (var typeb in wanted.ToArray()) { Type type = typeb; Type vBaseType = type.ValidBaseType(); while (vBaseType != null) { if (!bridgeTypes.Contains(vBaseType.FullName) && !wanted.Contains(vBaseType) && !(vBaseType.IsGenericType && !vBaseType.IsGenericTypeDefinition) //&& //!IsDiscardType(baseType) ) { wanted.Add(vBaseType); } vBaseType = vBaseType.ValidBaseType(); } } // 自动添加接口 foreach (var typeb in wanted.ToArray()) { Type type = typeb; Type[] interfaces = type.GetInterfaces(); for (int i = 0; i < interfaces.Length; i++) { Type ti = interfaces[i]; string tiFullName = JSNameMgr.CsFullName(ti); if (tiFullName.Contains("<") || tiFullName.Contains(">")) { continue; } if (!bridgeTypes.Contains(interfaces[i].FullName) && !wanted.Contains(ti) //&& //!IsDiscardType(ti) ) { wanted.Add(ti); } } } if (!ok) { Debug.LogError(sb); return(false); } List <Type> lst = wanted.ToList(); // 对 lst 进行排序 // Bridge.js 假设基类在前(接口也算) // var baseType = extend[j], // baseI = (baseType.$interfaces || []).concat(baseType.$baseInterfaces || []); { Dictionary <Type, int> dict = new Dictionary <Type, int>(); foreach (var type in wanted) { dict.Add(type, 0); } while (true) { bool bC = false; foreach (Type type in dict.Keys.ToArray()) { int v = dict[type]; if (v != 0) { continue; } bool allParentResolved = true; int maxParentValue = 0; Type[] interfaces = type.GetInterfaces(); foreach (var interf in interfaces) { if (dict.ContainsKey(interf)) { if (dict[interf] == 0) { allParentResolved = false; break; } else { maxParentValue = Math.Max(maxParentValue, dict[interf]); } } } Type baseType = type.ValidBaseType(); if (allParentResolved) { if (baseType != null && dict.ContainsKey(baseType)) { if (dict[baseType] == 0) { allParentResolved = false; } else { maxParentValue = Math.Max(maxParentValue, dict[baseType]); } } } if (allParentResolved) { dict[type] = maxParentValue + 1; } else { bC = true; } } if (!bC) { break; } } lst.Sort((t1, t2) => (dict[t1] < dict[t2] ? -1 : (dict[t1] > dict[t2] ? 1 : 0))); } // 打印最终要导出的类型 sb.Remove(0, sb.Length); sb.AppendLine("最终要导出的类型:"); foreach (var t in lst) { sb.AppendLine(JSNameMgr.CsFullName(t)); } Debug.Log(sb.ToString()); arrClasses = lst.ToArray(); return(true); }
public static TextFile GenerateClass() { GeneratorHelp.ATypeInfo ti; int slot = GeneratorHelp.AddTypeInfo(type, out ti); TextFile tfDef = new TextFile(); TextFile tfClass = null; bool gtd = type.IsGenericTypeDefinition; if (!gtd) { tfClass = tfDef.Add("Bridge.define(\"{0}\", {{", JSNameMgr.JsFullName(type)) .In(); tfDef.Add("});"); } else { args TNames = new args(); foreach (var T in type.GetGenericArguments()) { TNames.Add(T.Name); } tfClass = tfDef.Add("Bridge.define(\"{0}\", function ({1}) {{ return {{", JSNameMgr.JsFullName(type), TNames.Format(args.ArgsFormat.OnlyList)) .In(); tfDef.Add("}});"); } // base type, interfaces { Type vBaseType = type.ValidBaseType(); Type[] interfaces = type.GetInterfaces(); if (vBaseType != null || interfaces.Length > 0) { args a = new args(); // 这里baseType要在前面 // Bridge.js: // var noBase = extend ? extend[0].$kind === "interface" : true; // // 可以忽略object基类 // Bridge.js: // if (!extend) { // extend = [Object].concat(interfaces); // } if (vBaseType != null) { a.Add(JSNameMgr.JsFullName(vBaseType)); } foreach (var i in interfaces) { a.Add(JSNameMgr.JsFullName(i)); } tfClass.Add("inherits: [{0}],", a.ToString()); } } if (type.IsInterface) { tfClass.Add("$kind: \"interface\","); } else if (type.IsValueType) { tfClass.Add("$kind: \"struct\","); } TextFile tfStatic = tfClass.Add("statics: {").In(); tfStatic.Out().Add("},"); TextFile tfInst = tfClass.Add(""); if (type.IsValueType) { tfStatic.Add("getDefaultValue: function () {{ return new {0}(); }},", JSNameMgr.JsFullName(type)); tfInst.Add("equals: function (o) {") .In() .Add("if (!Bridge.is(o, {0})) {{", JSNameMgr.JsFullName(type)) .In() .Add("return false;") .BraceOut() .Add(() => { StringBuilder sb = new StringBuilder(); if (ti.Fields.Count == 0) { sb.Append("return true;"); } else { for (int f = 0; f < ti.Fields.Count; f++) { if (ti.Fields[f].Ignored) { continue; } sb.AppendFormat("Bridge.equals(this.{0}, o.{0})", ti.Fields[f].member.Name); if (f < ti.Fields.Count - 1) { sb.AppendFormat(" && "); } else { sb.Append(";"); } } } return(new TextFile().Add(sb.ToString()).Ch); }) .BraceOutComma(); tfInst.Add("$clone: function (to) {") .In() .Add("return this; // don't clone").AddLine() .Add("var s = to || new {0}();", JSNameMgr.JsFullName(type)) .Add(() => { TextFile tf = new TextFile(); for (int f = 0; f < ti.Fields.Count; f++) { if (ti.Fields[f].Ignored) { continue; } tf.Add("s.{0} = this.{0};", ti.Fields[f].member.Name); } return(tf.Ch); }) .Add("return s;") .BraceOutComma(); } BuildConstructors(tfInst, type, ti.Cons, slot); BuildFields(tfStatic, tfInst, type, ti.Fields, slot); BuildProperties(tfStatic, tfInst, type, ti.Pros, slot); BuildMethods(tfStatic, tfInst, type, ti.Methods, slot); return(tfDef); }
public static string SharpKitClassName(Type type) { return(JSNameMgr.JsFullName(type)); }
// // arg: a,b,c // public static TextFile BuildCallString(Type classType, MemberInfo memberInfo, string argList, MemberFeature features, object newValue = null /* string 或 TextFile */) { bool bGenericT = classType.IsGenericTypeDefinition; string memberName = memberInfo.Name; bool bIndexer = ((features & MemberFeature.Indexer) > 0); bool bStatic = ((features & MemberFeature.Static) > 0); bool bStruct = classType.IsValueType; string typeFullName = JSNameMgr.CsFullName(classType); bool bField = (memberInfo is FieldInfo); bool bProperty = (memberInfo is PropertyInfo); bool bGet = ((features & MemberFeature.Get) > 0); bool bSet = ((features & MemberFeature.Set) > 0); if ((bGet && bSet) || (!bGet && !bSet)) { return(null); } TextFile tf = new TextFile(); if (bField || bProperty) { if (!bGenericT) { var strThis = typeFullName; if (!bStatic) { strThis = "_this"; tf.Add("{0} _this = ({0})vc.csObj;", typeFullName); } string access = bIndexer ? string.Format("{0}[{1}]", strThis, argList) : string.Format("{0}.{1}", strThis, memberName); if (bGet) { tf.Add("var result = {0};", access); } else { if (newValue is string) { tf.Add("{0} = {1};", access, newValue); } else { tf.Add("{0} = ", access).In().Add((newValue as TextFile).Ch).Out().Add(";"); } if (!bStatic && bStruct) { tf.Add("JSMgr.changeJSObj(vc.jsObjID, _this);"); } } } else { // convention: name 'member' if (bIndexer || !bIndexer) // both indexer and not indexer enters { string objs = (bStatic ? "null" : "vc.csObj"); if (bProperty) { if (bGet) { tf.Add("var result = member.GetValue({0}, new object[]{{{1}}});", objs, argList); } else { if (newValue is string) { tf.Add("member.SetValue({0}, {1}, new object[]{{{2}}});", objs, newValue, argList); } else { tf.Add("member.SetValue({0}, ", objs) .In() .Add((newValue as TextFile).Ch) .Out() .Add(", new object[]{{{0}}});", argList); } } //tf.Add("{4}member.{0}({1}, {2}new object[]{{{3}}});", // bGet ? "GetValue" : "SetValue", // bStatic ? "null" : "vc.csObj", // bSet ? newValue + ", " : "", // argList, // bGet ? "var result = " : ""); } else { if (bGet) { tf.Add("var result = member.GetValue({0});", objs); } else { if (newValue is string) { tf.Add("member.SetValue({0}, {1});", objs, newValue); } else { tf.Add("member.SetValue({0}, ", objs).In().Add((newValue as TextFile).Ch).Out().Add(");"); } } //tf.Add("{3}member.{0}({1}{2});", // bGet ? "GetValue" : "SetValue", // bStatic ? "null" : "vc.csObj", // bSet ? ", " + newValue : "", // bGet ? "var result = " : ""); } } } } return(tf); }
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); }
public static string Get_Return(Type type, string expVar) { if (type == typeof(void)) { return(expVar + ";"); } if (type.IsArray) { arrayExchange.elementType = type.GetElementType(); if (arrayExchange.elementType.IsArray) { Debug.LogError("Return [][] not supported"); return(string.Empty); } // else if (arrayExchange.elementType.ContainsGenericParameters) // { // Debug.LogError(" Return T[] not supported"); // return "/* Return T[] is not supported */"; // } return(arrayExchange.Get_Return(expVar)); } else { var sb = new StringBuilder(); bool needCast; var keyword = GetMetatypeKeyword(type, out needCast).Replace("get", "set"); if (type.IsPrimitive) { sb.AppendFormat("{0}((int)JSApi.SetType.Rval, ({1})({2}));", keyword, JSNameMgr.CsFullName(type), expVar); } else if (type.IsEnum) { sb.AppendFormat("{0}((int)JSApi.SetType.Rval, (int){1});", keyword, expVar); } else { sb.AppendFormat("{0}((int)JSApi.SetType.Rval, {1});", keyword, expVar); } return(sb.ToString()); } }
// Editor only public static ParamHandler Get_ParamHandler(Type type, int paramIndex, bool isRef, bool isOut) { ParamHandler ph = new ParamHandler(); ph.argName = "arg" + paramIndex.ToString(); if (IsDelegateDerived(type)) { Debug.LogError("Delegate derived class should not get here"); return(ph); } bool bTOrContainsT = (type.IsGenericParameter || type.ContainsGenericParameters); string typeFullName; if (bTOrContainsT) { typeFullName = "object"; } else { typeFullName = JSNameMgr.CsFullName(type); } if (isRef || isOut) { type = type.GetElementType(); } if (type.IsArray) { ph.getter = new TextFile() .Add("{0} {1} = ", typeFullName, ph.argName) .In() .Add(arrayExchange.Get_GetParam(type).Ch) .Out() .Add(";"); } else { bool needCast; string keyword = GetMetatypeKeyword(type, out needCast); if (keyword == string.Empty) { Debug.LogError("keyword is empty: " + type.Name); return(ph); } if (isOut) { ph.getter = new TextFile() .Add("int r_arg{0} = JSApi.incArgIndex();", paramIndex) .Add("{0} {1}{2};", typeFullName, ph.argName, bTOrContainsT ? " = null" : ""); } else if (isRef) { ph.getter = new TextFile() .Add("int r_arg{0} = JSApi.getArgIndex();", paramIndex) .Add("{0} {1} = ({0}){2}((int)JSApi.GetType.ArgRef);", typeFullName, ph.argName, keyword); } else { if (needCast) { ph.getter = new TextFile() .Add("{0} {1} = ({0}){2}((int)JSApi.GetType.Arg);", typeFullName, ph.argName, keyword); } else { ph.getter = new TextFile() .Add("{0} {1} = {2}((int)JSApi.GetType.Arg);", typeFullName, ph.argName, keyword); } } if (isOut || isRef) { TextFile tf = new TextFile(); if (bTOrContainsT) { // TODO // sorry, 'arr_t' is written in CSGenerator2.cs tf.Add("{0} = arr_t[{1}];", ph.argName, paramIndex); } tf.Add("JSApi.setArgIndex(r_arg{0});", paramIndex) .Add("{0}((int)JSApi.SetType.ArgRef, {1});", keyword.Replace("get", "set"), ph.argName); ph.updater = tf; } } return(ph); }