Ejemplo n.º 1
0
        // 生成定参部分 type 列表 (首参前也会补",")
        public string GetFixedMatchTypes(T method)
        {
            var snippet     = "";
            var parameters  = method.GetParameters();
            var isExtension = BindingManager.IsExtensionMethod(method);
            var i           = isExtension ? 1 : 0;
            var length      = parameters.Length;

            for (; i < length; i++)
            {
                var parameter = parameters[i];
                if (parameter.IsDefined(typeof(ParamArrayAttribute), false))
                {
                    break;
                }
                snippet += ", ";
                if (parameter.ParameterType.IsByRef)
                {
                    //TODO: 检查 ref/out 参数有效性 (null undefined 或者 符合 Ref/Out 约定)
                    snippet += "null";
                }
                else
                {
                    var typename = this.cg.bindingManager.GetCSTypeFullName(parameter.ParameterType);
                    snippet += $"typeof({typename})";
                }
            }
            return(snippet);
        }
Ejemplo n.º 2
0
        private void CollectMethods(IEnumerable <MethodInfo> methods)
        {
            foreach (var method in methods)
            {
                if (BindingManager.IsGenericMethod(method))
                {
                    bindingManager.Info("skip generic method: {0}", method);
                    continue;
                }

                if (BindingManager.ContainsPointer(method))
                {
                    bindingManager.Info("skip unsafe (pointer) method: {0}", method);
                    continue;
                }

                if (method.IsSpecialName)
                {
                    if (!IsSupportedOperators(method))
                    {
                        bindingManager.Info("skip special method: {0}", method);
                        continue;
                    }
                }

                if (method.IsDefined(typeof(JSOmitAttribute), false))
                {
                    bindingManager.Info("skip omitted method: {0}", method);
                    continue;
                }

                if (method.IsDefined(typeof(ObsoleteAttribute), false))
                {
                    bindingManager.Info("skip obsolete method: {0}", method);
                    continue;
                }

                if (transform != null && transform.IsMemberBlocked(method.Name))
                {
                    bindingManager.Info("skip blocked method: {0}", method.Name);
                    continue;
                }

                if (BindingManager.IsExtensionMethod(method))
                {
                    var targetType = method.GetParameters()[0].ParameterType;
                    var targetInfo = bindingManager.GetExportedType(targetType);
                    if (targetInfo != null)
                    {
                        targetInfo.AddMethod(method);
                        continue;
                    }
                }

                AddMethod(method);
            }
        }
Ejemplo n.º 3
0
 public string AppendGetThisCS(MethodBase method)
 {
     if (method.IsConstructor)
     {
         return(null);
     }
     if (BindingManager.IsExtensionMethod(method))
     {
         var parameters = method.GetParameters();
         return(AppendGetThisCS(false, parameters[0].ParameterType));
     }
     return(AppendGetThisCS(method.IsStatic, method.DeclaringType));
 }
Ejemplo n.º 4
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);
            }
        }
Ejemplo n.º 5
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);
        }
Ejemplo n.º 6
0
        public void AddMethod(MethodInfo methodInfo, bool isIndexer, string renameRegName)
        {
            if (this.transform != null)
            {
                if (this.transform.IsBlocked(methodInfo))
                {
                    bindingManager.Info("skip blocked method: {0}", methodInfo.Name);
                    return;
                }
            }

            var isExtension = BindingManager.IsExtensionMethod(methodInfo);
            var isStatic    = methodInfo.IsStatic && !isExtension;

            if (IsSupportedOperators(methodInfo))
            {
                var methodName    = TypeBindingInfo.GetNamingAttribute(methodInfo);
                var parameters    = methodInfo.GetParameters();
                var declaringType = methodInfo.DeclaringType;
                switch (methodName)
                {
                case "op_Addition":
                    if (parameters.Length == 2)
                    {
                        if (parameters[0].ParameterType == declaringType && parameters[1].ParameterType == declaringType)
                        {
                            var bindingInfo = new OperatorBindingInfo(methodInfo, isExtension, isStatic, methodName, "+", "+", 2);
                            operators.Add(bindingInfo);
                        }
                    }
                    break;

                case "op_Subtraction":
                    if (parameters.Length == 2)
                    {
                        if (parameters[0].ParameterType == declaringType && parameters[1].ParameterType == declaringType)
                        {
                            var bindingInfo = new OperatorBindingInfo(methodInfo, isExtension, isStatic, methodName, "-", "-", 2);
                            operators.Add(bindingInfo);
                        }
                    }
                    break;

                case "op_Equality":
                    if (parameters.Length == 2)
                    {
                        if (parameters[0].ParameterType == declaringType && parameters[1].ParameterType == declaringType)
                        {
                            var bindingInfo = new OperatorBindingInfo(methodInfo, isExtension, isStatic, methodName, "==", "==", 2);
                            operators.Add(bindingInfo);
                        }
                    }
                    break;

                case "op_Multiply":
                    if (parameters.Length == 2)
                    {
                        var op0 = bindingManager.GetExportedType(parameters[0].ParameterType);
                        var op1 = bindingManager.GetExportedType(parameters[1].ParameterType);
                        if (op0 == null || op1 == null)
                        {
                            return;
                        }
                        var bindingName = methodName + "_" + op0.name + "_" + op1.name;
                        var bindingInfo = new OperatorBindingInfo(methodInfo, isExtension, isStatic, bindingName, "*", "*", 2);
                        operators.Add(bindingInfo);
                    }
                    break;

                case "op_Division":
                    if (parameters.Length == 2)
                    {
                        var op0 = bindingManager.GetExportedType(parameters[0].ParameterType);
                        var op1 = bindingManager.GetExportedType(parameters[1].ParameterType);
                        if (op0 == null || op1 == null)
                        {
                            return;
                        }
                        var bindingName = methodName + "_" + op0.name + "_" + op1.name;
                        var bindingInfo = new OperatorBindingInfo(methodInfo, isExtension, isStatic, bindingName, "/", "/", 2);
                        operators.Add(bindingInfo);
                    }
                    break;

                case "op_UnaryNegation":
                {
                    var bindingInfo = new OperatorBindingInfo(methodInfo, isExtension, isStatic, methodName, "neg", "-", 1);
                    operators.Add(bindingInfo);
                }
                break;

                default:
                    bindingManager.Info("skip unsupported operator method: {0}", methodInfo.Name);
                    return;
                }
            }
            else
            {
                var group = isStatic ? staticMethods : methods;
                MethodBindingInfo methodBindingInfo;
                var methodName = TypeBindingInfo.GetNamingAttribute(methodInfo);
                if (!group.TryGetValue(methodName, out methodBindingInfo))
                {
                    methodBindingInfo = new MethodBindingInfo(isIndexer, isStatic, methodName, renameRegName ?? methodName);
                    group.Add(methodName, methodBindingInfo);
                }
                if (!methodBindingInfo.Add(methodInfo, isExtension))
                {
                    bindingManager.Info("fail to add method: {0}", methodInfo.Name);
                    return;
                }
            }

            CollectDelegate(methodInfo);
            bindingManager.Info("[AddMethod] {0}.{1}", type, methodInfo);
        }