Beispiel #1
0
        // 输出所有变体绑定
        // 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);
                    }
                }
            }
        }
Beispiel #2
0
        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);
                }
            }
        }
Beispiel #3
0
        // 写入绑定代码
        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);
            }
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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);
            }
        }