Beispiel #1
0
        // 输出所有变体绑定
        // hasOverrides: 是否需要处理重载
        protected void WriteCSAllVariants(MethodBaseBindingInfo <T> methodBindingInfo) // SortedDictionary<int, MethodBaseVariant<T>> variants)
        {
            var variants = methodBindingInfo.variants;
            var prefs    = cg.bindingManager.prefs;

            if (prefs.alwaysCheckArgc || /*hasOverrides*/ methodBindingInfo.count > 1)
            {
                // 需要处理重载
                GenMethodVariants(methodBindingInfo, 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];
                        WriteCSMethodBinding(methodBindingInfo, method.method, argc, true, method.isExtension);
                    }
                    else
                    {
                        var method = variant.plainMethods[0];
                        WriteCSMethodBinding(methodBindingInfo, method.method, argc, false, method.isExtension);
                    }
                }
            }
        }
Beispiel #2
0
        protected void WriteTSAllVariants(TypeBindingInfo typeBindingInfo, 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(typeBindingInfo, method.method, bindingInfo, method.isExtension);
                }
                foreach (var method in variantKV.Value.varargMethods)
                {
                    WriteTSDeclaration(typeBindingInfo, method.method, bindingInfo, method.isExtension);
                }
            }
        }
        // 写入绑定代码
        protected void WriteCSMethodBinding(MethodBaseBindingInfo <T> bindingInfo, T method, string argc, bool isVararg, bool isExtension)
        {
            if (this.cg.bindingManager.prefs.verboseLog)
            {
                cg.bindingManager.Info($"WriteCSMethodBinding: {method.Name} {isExtension}");
            }

            // 是否接管 cs 绑定代码生成
            var transform = cg.bindingManager.GetTypeTransform(method.DeclaringType);

            if (transform != null && transform.OnBinding(BindingPoints.METHOD_BINDING_FULL, method, cg))
            {
                return;
            }

            // var isRaw = method.IsDefined(typeof(JSCFunctionAttribute));
            var parameters = method.GetParameters();
            var caller     = this.cg.AppendGetThisCS(method, isExtension);
            var returnType = GetReturnType(method);

            if (returnType == null || returnType == typeof(void))
            {
                // 方法本身没有返回值
                this.BeginInvokeBinding();
                cg.cs.AppendLine($"{this.GetInvokeBinding(caller, method, isVararg, isExtension, argc, parameters)};");
                this.EndInvokeBinding();

                _WriteBackParameters(isExtension, parameters);
                WriteRebindThis(method, caller);
                InvokeVoidReturn();
            }
            else
            {
                var retVar = "ret"; // cs return value var name
                this.BeginInvokeBinding();
                cg.cs.AppendLine($"var {retVar} = {this.GetInvokeBinding(caller, method, isVararg, isExtension, argc, parameters)};");
                this.EndInvokeBinding();

                var retPusher = cg.AppendMethodReturnValuePusher(method, returnType, retVar);

                _WriteBackParameters(isExtension, parameters);
                cg.cs.AppendLine("return {0};", retPusher);
            }
        }
Beispiel #4
0
        protected List <ParameterInfo> WriteTSDeclaration(TypeBindingInfo typeBindingInfo, T method, MethodBaseBindingInfo <T> bindingInfo, bool isExtension)
        {
            var    refParameters = new List <ParameterInfo>();
            string tsMethodDeclaration;

            this.cg.AppendJSDoc(method);

            if (typeBindingInfo.transform.GetTSMethodDeclaration(method, out tsMethodDeclaration) ||
                this.cg.bindingManager.GetTSMethodDeclaration(method, out tsMethodDeclaration))
            {
                this.cg.tsDeclare.AppendLine(tsMethodDeclaration);
                return(refParameters);
            }

            string tsMethodRename;

            if (!this.cg.bindingManager.GetTSMethodRename(method, out tsMethodRename))
            {
                tsMethodRename = bindingInfo.jsName;
            }

            var isRaw = method.IsDefined(typeof(JSCFunctionAttribute));
            //TODO: 需要处理参数类型归并问题, 因为如果类型没有导入 ts 中, 可能会在声明中出现相同参数列表的定义
            //      在 MethodVariant 中创建每个方法对应的TS类型名参数列表, 完全相同的不再输出
            var prefix = "";

            // if (method.Name.StartsWith("op_"))
            if (bindingInfo is OperatorBindingInfo)
            {
                prefix += "// js_op_overloading: ";
            }
            else
            {
                // var baseType = typeBindingInfo.type.BaseType;
                // if (baseType != null)
                // {
                //     //TODO: 需要检查 TypeBindingInfo 对此的命名修改
                //     if (baseType.GetMethods().Where(baseMethodInfo => baseMethodInfo.Name == tsMethodRename).Count() != 0)
                //     {
                //         prefix += "// @ts-ignore" + this.cg.tsDeclare.newline + this.cg.tsDeclare.tabString;
                //     }
                // }
            }

            if (method.IsStatic && !isExtension)
            {
                prefix += "static ";
            }

            this.cg.tsDeclare.Append($"{prefix}{tsMethodRename}(");

            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);
                }

                for (int i = 0, len = parameters.Length; i < len;)
                {
                    var parameter     = parameters[i];
                    var parameterType = parameter.ParameterType;
                    if (parameterType == typeof(Native.JSContext) || parameterType == typeof(Native.JSRuntime))
                    {
                        // 剔除 JSContext, JSRuntime
                        ArrayUtility.RemoveAt(ref parameters, i);
                        len--;
                    }
                    else if (parameterType == typeof(ScriptContext) || parameterType == typeof(ScriptRuntime))
                    {
                        // 剔除 ScriptContext, ScriptRuntime
                        ArrayUtility.RemoveAt(ref parameters, i);
                        len--;
                    }
                    // else if (parameter.IsOut)
                    // {
                    //     ArrayUtility.RemoveAt(ref parameters, i);
                    //     len--;
                    //     refParameters.Add(parameter);
                    // }
                    else
                    {
                        // if (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> methodBindingInfo, SortedDictionary <int, MethodBaseVariant <T> > variants)
        {
            var argc = cg.AppendGetArgCount(true);

            using (cg.cs.DoWhileBlockScope(methodBindingInfo.count > 1))
            {
                foreach (var variantKV in variants)
                {
                    var expectedArgCount = variantKV.Key;
                    var variant          = variantKV.Value;
                    var gecheck          = expectedArgCount > 0 && variant.isVararg; // 最后一组分支且存在变参时才需要判断 >=

                    if (gecheck)
                    {
                        cg.cs.AppendLine("if (argc >= {0})", expectedArgCount);
                        cg.cs.AppendLine("{");
                        cg.cs.AddTabLevel();
                    }

                    // 处理定参
                    if (variant.plainMethods.Count > 0)
                    {
                        cg.cs.AppendLine("if (argc == {0})", expectedArgCount);
                        using (cg.cs.CodeBlockScope())
                        {
                            var prefs = cg.bindingManager.prefs;
                            if (prefs.alwaysCheckArgType || variant.plainMethods.Count > 1)
                            {
                                foreach (var method in variant.plainMethods)
                                {
                                    var fixedMatchers = GetFixedMatchTypes(method.method, false, method.isExtension);
                                    if (fixedMatchers.Length != 0)
                                    {
                                        cg.cs.AppendLine($"if ({fixedMatchers})");
                                        using (cg.cs.CodeBlockScope())
                                        {
                                            this.WriteCSMethodBinding(methodBindingInfo, method.method, argc, false, method.isExtension);
                                        }
                                    }
                                    else
                                    {
                                        this.WriteCSMethodBinding(methodBindingInfo, method.method, argc, false, method.isExtension);
                                    }
                                }

                                if (methodBindingInfo.count > 1 && expectedArgCount != 0)
                                {
                                    cg.cs.AppendLine("break;");
                                }
                            }
                            else
                            {
                                // 只有一个定参方法时, 不再判定类型匹配
                                var method = variant.plainMethods[0];
                                this.WriteCSMethodBinding(methodBindingInfo, method.method, argc, false, method.isExtension);
                            }
                        }
                    }

                    // 处理变参
                    if (variant.varargMethods.Count > 0)
                    {
                        foreach (var method in variant.varargMethods)
                        {
                            var fixedMatchers   = GetFixedMatchTypes(method.method, true, method.isExtension);
                            var variantMatchers = GetParamArrayMatchType(method.method);

                            if (fixedMatchers.Length > 0)
                            {
                                cg.cs.AppendLine($"if ({fixedMatchers} && js_match_param_types(ctx, {expectedArgCount}, argv, {variantMatchers}))");
                            }
                            else
                            {
                                cg.cs.AppendLine($"if (js_match_param_types(ctx, {expectedArgCount}, argv, {variantMatchers}))");
                            }

                            using (cg.cs.CodeBlockScope())
                            {
                                this.WriteCSMethodBinding(methodBindingInfo, method.method, argc, true, method.isExtension);
                            }
                        }
                    }

                    if (gecheck)
                    {
                        cg.cs.DecTabLevel();
                        cg.cs.AppendLine("}");
                    }
                }
            }
            var error = this.cg.bindingManager.GetThrowError("no matched method variant");

            cg.cs.AppendLine($"return {error};");
        }
 public TSMethodCodeGen(CodeGenerator cg, TypeBindingInfo typeBindingInfo, MethodBaseBindingInfo <T> bindingInfo)
     : base(cg)
 {
     this.bindingInfo = bindingInfo;
     WriteTSAllVariants(typeBindingInfo, this.bindingInfo);
 }