// 输出所有变体绑定 // hasOverrides: 是否需要处理重载 protected void WriteAllVariants(MethodBaseBindingInfo <T> bindingInfo) // SortedDictionary<int, MethodBaseVariant<T>> variants) { var variants = bindingInfo.variants; var hasOverrides = bindingInfo.count > 1; if (hasOverrides) { // 需要处理重载 GenMethodVariants(bindingInfo, variants); } else { // 没有重载的情况 (variants.Count == 1) foreach (var variantKV in variants) { var args = variantKV.Key; var variant = variantKV.Value; var argc = cg.AppendGetArgCount(variant.isVararg); if (variant.isVararg) { var method = variant.varargMethods[0]; // Debug.Log($"varargMethods {method}"); WriteCSMethodBinding(bindingInfo, method, argc, true); } else { var method = variant.plainMethods[0]; // Debug.Log($"plainMethods {method}"); WriteCSMethodBinding(bindingInfo, method, argc, false); } } } }
protected void WriteTSAllVariants(MethodBaseBindingInfo <T> bindingInfo) { var variants = bindingInfo.variants; //NOTE: 如果产生了无法在 typescript 中声明的方法, 则作标记, 并输出一条万能声明 // [key: string]: any foreach (var variantKV in variants) { foreach (var method in variantKV.Value.plainMethods) { WriteTSDeclaration(method, bindingInfo); } foreach (var method in variantKV.Value.varargMethods) { WriteTSDeclaration(method, bindingInfo); } } }
// 写入绑定代码 protected void WriteCSMethodBinding(MethodBaseBindingInfo <T> bindingInfo, T method, string argc, bool isVararg) { // 是否接管 cs 绑定代码生成 var transform = cg.bindingManager.GetTypeTransform(method.DeclaringType); if (transform != null && transform.OnBinding(BindingPoints.METHOD_BINDING_FULL, method, cg)) { return; } var isExtension = BindingManager.IsExtensionMethod(method); // var isRaw = method.IsDefined(typeof(JSCFunctionAttribute)); var parameters = method.GetParameters(); var in_params = new List <ParameterInfo>(); var out_params = new List <ParameterInfo>(); SplitParamters(parameters, isExtension ? 1 : 0, in_params, out_params); var caller = this.cg.AppendGetThisCS(method); var returnType = GetReturnType(method); // if (isRaw) // { // do // { // if (!isExtension) // { // if (returnType == typeof(int) && in_params.Count == 1) // { // var p = in_params[0]; // if (p.ParameterType == typeof(IntPtr) && !p.IsOut) // { // cg.cs.AppendLine($"return {caller}.{method.Name}(ctx);"); // return; // } // } // cg.bindingManager.Error($"invalid JSCFunction definition: {method}"); // break; // } // cg.bindingManager.Error($"Extension as JSCFunction is not supported: {method}"); // } while (false); // } if (returnType == null || returnType == typeof(void)) { // 方法本身没有返回值 this.BeginInvokeBinding(); cg.cs.AppendLine($"{this.GetInvokeBinding(caller, method, isVararg, isExtension, argc, parameters)};"); this.EndInvokeBinding(); var backVars = out_params.Count > 0 ? _WriteBackParametersByRef(isExtension, out_params, null) : null; if (!method.IsStatic && method.DeclaringType.IsValueType) // struct 非静态方法 检查 Mutable 属性 { if (!string.IsNullOrEmpty(caller)) { cg.cs.AppendLine($"js_rebind_this(ctx, this_obj, {caller});"); } } if (string.IsNullOrEmpty(backVars)) { this.InvokeVoidReturn(); } else { cg.cs.AppendLine("return {0};", backVars); } } else { var retVar = "ret"; // cs return value var name var retJsVar = "ret_js"; this.BeginInvokeBinding(); cg.cs.AppendLine($"var {retVar} = {this.GetInvokeBinding(caller, method, isVararg, isExtension, argc, parameters)};"); this.EndInvokeBinding(); var retPusher = cg.AppendMethodReturnValuePusher(method, returnType, retVar); cg.cs.AppendLine("var {0} = {1};", retJsVar, retPusher); cg.cs.AppendLine("if (JSApi.JS_IsException({0}))", retJsVar); using (cg.cs.Block()) { cg.cs.AppendLine("return {0};", retJsVar); } var backVars = out_params.Count > 0 ? _WriteBackParametersByRef(isExtension, out_params, retJsVar) : retJsVar; cg.cs.AppendLine("return {0};", backVars); } }
protected List <ParameterInfo> WriteTSDeclaration(T method, MethodBaseBindingInfo <T> bindingInfo) { var isExtension = BindingManager.IsExtensionMethod(method); var refParameters = new List <ParameterInfo>(); string tsMethodDeclaration; this.cg.AppendJSDoc(method); if (this.cg.bindingManager.GetTSMethodDeclaration(method, out tsMethodDeclaration)) { this.cg.tsDeclare.AppendLine(tsMethodDeclaration); return(refParameters); } var isRaw = method.IsDefined(typeof(JSCFunctionAttribute)); //TODO: 需要处理参数类型归并问题, 因为如果类型没有导入 ts 中, 可能会在声明中出现相同参数列表的定义 // 在 MethodVariant 中创建每个方法对应的TS类型名参数列表, 完全相同的不再输出 var prefix = ""; if (method.Name.StartsWith("op_")) { prefix += "//"; } if (method.IsStatic && !isExtension) { prefix += "static "; } string tsMethodRename; if (this.cg.bindingManager.GetTSMethodRename(method, out tsMethodRename)) { this.cg.tsDeclare.Append($"{prefix}{tsMethodRename}("); } else { this.cg.tsDeclare.Append($"{prefix}{bindingInfo.regName}("); } if (isRaw) { this.cg.tsDeclare.AppendL("...uncertain: any[]): any /* uncertain */"); this.cg.tsDeclare.AppendLine(); } else { var parameters = method.GetParameters(); if (isExtension) { ArrayUtility.RemoveAt(ref parameters, 0); } // 剔除 out 参数 for (int i = 0, len = parameters.Length; i < len;) { var parameter = parameters[i]; if (parameter.IsOut) { ArrayUtility.RemoveAt(ref parameters, i); len--; refParameters.Add(parameter); } else { if (parameter.ParameterType.IsByRef) { refParameters.Add(parameter); } i++; } } for (int i = 0, len = parameters.Length; i < len; i++) { var parameter = parameters[i]; var parameter_prefix = ""; var parameterType = parameter.ParameterType; if (parameter.IsDefined(typeof(ParamArrayAttribute), false) && i == parameters.Length - 1) { var elementType = parameterType.GetElementType(); var elementTS = this.cg.bindingManager.GetTSTypeFullName(elementType); var parameterVarName = BindingManager.GetTSVariable(parameter); this.cg.tsDeclare.AppendL($"{parameter_prefix}...{parameterVarName}: {elementTS}[]"); } else { var parameterTS = this.cg.bindingManager.GetTSTypeFullName(parameter); var parameterVarName = BindingManager.GetTSVariable(parameter); this.cg.tsDeclare.AppendL($"{parameter_prefix}{parameterVarName}: {parameterTS}"); } if (i != parameters.Length - 1) { this.cg.tsDeclare.AppendL(", "); } } this.cg.tsDeclare.AppendL($")"); WriteTSReturn(method, refParameters); } return(refParameters); }
protected void GenMethodVariants(MethodBaseBindingInfo <T> bindingInfo, SortedDictionary <int, MethodBaseVariant <T> > variants) { var argc = cg.AppendGetArgCount(true); cg.cs.AppendLine("do"); cg.cs.AppendLine("{"); cg.cs.AddTabLevel(); { foreach (var variantKV in variants) { var args = variantKV.Key; var variant = variantKV.Value; //variant.count > 1 var gecheck = args > 0 && variant.isVararg; // 最后一组分支且存在变参时才需要判断 >= if (gecheck) { cg.cs.AppendLine("if (argc >= {0})", args); cg.cs.AppendLine("{"); cg.cs.AddTabLevel(); } // 处理定参 if (variant.plainMethods.Count > 0) { cg.cs.AppendLine("if (argc == {0})", args); cg.cs.AppendLine("{"); cg.cs.AddTabLevel(); if (variant.plainMethods.Count > 1) { foreach (var method in variant.plainMethods) { cg.cs.AppendLine($"if (js_match_types(ctx, argv{GetFixedMatchTypes(method)}))"); cg.cs.AppendLine("{"); cg.cs.AddTabLevel(); this.WriteCSMethodBinding(bindingInfo, method, argc, false); cg.cs.DecTabLevel(); cg.cs.AppendLine("}"); } cg.cs.AppendLine("break;"); } else { // 只有一个定参方法时, 不再判定类型匹配 var method = variant.plainMethods[0]; this.WriteCSMethodBinding(bindingInfo, method, argc, false); } cg.cs.DecTabLevel(); cg.cs.AppendLine("}"); } // 处理变参 if (variant.varargMethods.Count > 0) { foreach (var method in variant.varargMethods) { cg.cs.AppendLine($"if (js_match_types(ctx, argv{GetFixedMatchTypes(method)})"); cg.cs.AppendLine($" && js_match_param_types(ctx, {args}, argv, {GetParamArrayMatchType(method)}))"); cg.cs.AppendLine("{"); cg.cs.AddTabLevel(); this.WriteCSMethodBinding(bindingInfo, method, argc, true); cg.cs.DecTabLevel(); cg.cs.AppendLine("}"); } } if (gecheck) { cg.cs.DecTabLevel(); cg.cs.AppendLine("}"); } } } cg.cs.DecTabLevel(); cg.cs.AppendLine("} while(false);"); var error = this.cg.bindingManager.GetThrowError("no matched method variant"); cg.cs.AppendLine($"return {error};"); }
// 写入绑定代码 protected void WriteCSMethodBinding(MethodBaseBindingInfo <T> bindingInfo, T method, string argc, bool isVararg) { // 是否接管 cs 绑定代码生成 var transform = cg.bindingManager.GetTypeTransform(method.DeclaringType); if (transform != null && transform.OnBinding(BindingPoints.METHOD_BINDING_FULL, method, cg)) { return; } var parameters = method.GetParameters(); var isExtension = method.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute)); var isRaw = method.IsDefined(typeof(JSCFunctionAttribute)); if (isExtension) { ArrayUtility.RemoveAt(ref parameters, 0); } var parametersByRef = new List <ParameterInfo>(); var caller = this.cg.AppendGetThisCS(method); var returnType = GetReturnType(method); if (isRaw) { do { if (!isExtension) { if (returnType == typeof(int) && parameters.Length == 1) { var p = parameters[0]; if (p.ParameterType == typeof(IntPtr) && !p.IsOut) { cg.cs.AppendLine($"return {caller}.{method.Name}(ctx);"); return; } } cg.bindingManager.Error($"invalid JSCFunction definition: {method}"); break; } cg.bindingManager.Error($"Extension as JSCFunction is not supported: {method}"); } while (false); } if (returnType == null || returnType == typeof(void)) { // 方法本身没有返回值 this.BeginInvokeBinding(); cg.cs.AppendLine($"{this.GetInvokeBinding(caller, method, isVararg, isExtension, argc, parameters, parametersByRef)};"); this.EndInvokeBinding(); if (parametersByRef.Count > 0) { _WriteBackParametersByRef(isExtension, parametersByRef); } if (!method.IsStatic && method.DeclaringType.IsValueType) // struct 非静态方法 检查 Mutable 属性 { if (!string.IsNullOrEmpty(caller)) { cg.cs.AppendLine($"js_rebind_this(ctx, this_obj, {caller});"); } } this.InvokeVoidReturn(); } else { this.BeginInvokeBinding(); cg.cs.AppendLine($"var ret = {this.GetInvokeBinding(caller, method, isVararg, isExtension, argc, parameters, parametersByRef)};"); this.EndInvokeBinding(); if (parametersByRef.Count > 0) { _WriteBackParametersByRef(isExtension, parametersByRef); } var pusher = cg.AppendMethodReturnValuePusher(method, returnType, "ret"); cg.cs.AppendLine("return {0};", pusher); } }