public EventProxyCodeGen(CodeGenerator cg, EventBindingInfo eventBindingInfo)
        {
            this.cg = cg;
            this.eventBindingInfo = eventBindingInfo;

            var eventInfo     = this.eventBindingInfo.eventInfo;
            var declaringType = eventInfo.DeclaringType;
            var tsFieldVar    = BindingManager.GetTSVariable(eventBindingInfo.regName);
            var caller        = this.cg.AppendGetThisCS(eventBindingInfo);

            this.cg.cs.AppendLine("return js_new_event(ctx, {0}, {1}, {2});", caller, this.eventBindingInfo.adderName, this.eventBindingInfo.removerName);
        }
Esempio n. 2
0
        public EventProxyCodeGen(CodeGenerator cg, EventBindingInfo eventBindingInfo)
        {
            this.cg = cg;
            this.eventBindingInfo = eventBindingInfo;

            var eventInfo     = this.eventBindingInfo.eventInfo;
            var declaringType = eventInfo.DeclaringType;
            var tsFieldVar    = BindingManager.GetTSVariable(eventBindingInfo.regName);

            // this.cg.cs.AppendLine("DuktapeDLL.duk_push_this(ctx);");
            this.cg.cs.AppendLine($"duk_add_event_instanced(ctx, \"{tsFieldVar}\", {this.eventBindingInfo.adderName}, {this.eventBindingInfo.removerName}, -1);");
            this.cg.cs.AppendLine("DuktapeDLL.duk_remove(ctx, -2);");
            this.cg.cs.AppendLine("return 1;");
        }
Esempio n. 3
0
        // 回填 ref/out 参数
        // 扩展方法参数索引需要偏移
        protected string _WriteBackParametersByRef(bool isExtension, List <ParameterInfo> parametersByRef, string retJsVar)
        {
            var retVar = "mult_ret";

            cg.cs.AppendLine("var context = ScriptEngine.GetContext(ctx);");
            cg.cs.AppendLine("var {0} = JSApi.JS_NewObject(ctx);", retVar);

            if (!string.IsNullOrEmpty(retJsVar))
            {
                var retJsVarName = BindingManager.GetTSVariable("return");
                cg.cs.AppendLine("JSApi.JS_SetProperty(ctx, {0}, context.GetAtom(\"{1}\"), {2});", retVar, retJsVarName, retJsVar);
            }

            for (var i = 0; i < parametersByRef.Count; i++)
            {
                var parameter = parametersByRef[i];
                var pname     = BindingManager.GetTSVariable(parameter);
                var position  = isExtension ? parameter.Position - 1 : parameter.Position;
                var argname   = $"arg{position}";
                var pusher    = cg.AppendValuePusher(parameter.ParameterType, argname);

                cg.cs.AppendLine("var out{0} = {1};", i, pusher);
                cg.cs.AppendLine("if (JSApi.JS_IsException(out{0}))", i);
                using (cg.cs.Block())
                {
                    for (var j = 0; j < i; j++)
                    {
                        cg.cs.AppendLine("JSApi.JS_FreeValue(ctx, out{0});", j);
                    }
                    cg.cs.AppendLine("JSApi.JS_FreeValue(ctx, {0});", retVar);
                    cg.cs.AppendLine("return out{0};", i);
                }
                cg.cs.AppendLine("JSApi.JS_SetProperty(ctx, {0}, context.GetAtom(\"{1}\"), out{2});", retVar, pname, i);
            }
            return(retVar);
        }
Esempio n. 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);
        }
Esempio n. 5
0
        // 写入返回类型声明
        protected virtual void WriteTSReturn(T method, List <ParameterInfo> returnParameters)
        {
            var returnType = GetReturnType(method);
            var count      = returnParameters.Count;

            if (returnType != null && returnType != typeof(void))
            {
                if (count != 0)
                {
                    this.cg.tsDeclare.AppendL(": { ");

                    var returnTypeTS  = this.cg.bindingManager.GetTSReturnTypeFullName(returnType);
                    var returnVarName = BindingManager.GetTSVariable("return");
                    this.cg.tsDeclare.AppendL($"\"{returnVarName}\": {returnTypeTS}");

                    for (var i = 0; i < count; i++)
                    {
                        var rp   = returnParameters[i];
                        var name = BindingManager.GetTSVariable(rp.Name);
                        var ts   = this.cg.bindingManager.GetTSTypeFullName(rp.ParameterType);
                        if (i != count - 1)
                        {
                            this.cg.tsDeclare.AppendL($", \"{name}\": {ts}");
                        }
                        else
                        {
                            this.cg.tsDeclare.AppendL($", \"{name}\": {ts}");
                        }
                    }
                    this.cg.tsDeclare.AppendL(" }");
                    this.cg.tsDeclare.AppendLine();
                }
                else
                {
                    var returnTypeTS = this.cg.bindingManager.GetTSReturnTypeFullName(returnType);
                    this.cg.tsDeclare.AppendL($": {returnTypeTS}");
                    this.cg.tsDeclare.AppendLine();
                }
            }
            else
            {
                if (count != 0)
                {
                    this.cg.tsDeclare.AppendL(": { ");
                    for (var i = 0; i < count; i++)
                    {
                        var rp   = returnParameters[i];
                        var name = rp.Name;
                        var ts   = this.cg.bindingManager.GetTSTypeFullName(rp.ParameterType);
                        if (i != count - 1)
                        {
                            this.cg.tsDeclare.AppendL($"\"{name}\": {ts}, ");
                        }
                        else
                        {
                            this.cg.tsDeclare.AppendL($"\"{name}\": {ts}");
                        }
                    }
                    this.cg.tsDeclare.AppendL(" }");
                    this.cg.tsDeclare.AppendLine();
                }
                else
                {
                    this.cg.tsDeclare.AppendLine();
                }
            }
        }
Esempio n. 6
0
        public override void Dispose()
        {
            using (new RegFuncCodeGen(cg))
            {
                using (new RegFuncNamespaceCodeGen(cg, typeBindingInfo))
                {
                    var constructor = typeBindingInfo.constructors.available ? typeBindingInfo.constructors.name : "JSApi.class_private_ctor";
                    if (!typeBindingInfo.constructors.available && !typeBindingInfo.type.IsAbstract)
                    {
                        if (typeBindingInfo.type.IsSubclassOf(typeof(Component)))
                        {
                            // 因为 ts 泛型约束需要 new() 形式, 所以在定义中产生一个 public 定义
                            // 例如: GetComponent<T extends Component>(type: { new(): T }): T
                            cg.tsDeclare.AppendLine("/*protected*/ constructor()");
                        }
                        else
                        {
                            cg.tsDeclare.AppendLine("protected constructor()");
                        }
                    }
                    cg.cs.AppendLine("var cls = ns.CreateClass(\"{0}\", typeof({1}), {2});",
                                     typeBindingInfo.jsName,
                                     this.cg.bindingManager.GetCSTypeFullName(typeBindingInfo.type),
                                     constructor);

                    // 运算符
                    foreach (var operatorBindingInfo in typeBindingInfo.operators)
                    {
                        var    regName       = operatorBindingInfo.regName;
                        var    funcName      = operatorBindingInfo.name;
                        var    parameters    = operatorBindingInfo.methodInfo.GetParameters();
                        var    declaringType = operatorBindingInfo.methodInfo.DeclaringType;
                        string redirect;
                        if (this.typeBindingInfo.transform != null && this.typeBindingInfo.transform.TryRedirectMethod(regName, out redirect))
                        {
                            funcName = redirect;
                        }

                        do
                        {
                            if (parameters.Length == 2)
                            {
                                if (parameters[0].ParameterType != declaringType)
                                {
                                    var leftType = typeBindingInfo.bindingManager.GetCSTypeFullName(parameters[0].ParameterType);
                                    cg.cs.AppendLine("cls.AddLeftOperator(\"{0}\", {1}, {2}, typeof({3}));", regName, funcName, operatorBindingInfo.length, leftType);
                                    break;
                                }
                                else if (parameters[1].ParameterType != declaringType)
                                {
                                    var rightType = typeBindingInfo.bindingManager.GetCSTypeFullName(parameters[1].ParameterType);
                                    cg.cs.AppendLine("cls.AddRightOperator(\"{0}\", {1}, {2}, typeof({3}));", regName, funcName, operatorBindingInfo.length, rightType);
                                    break;
                                }
                            }

                            cg.cs.AppendLine("cls.AddSelfOperator(\"{0}\", {1}, {2});", regName, funcName, operatorBindingInfo.length);
                        } while (false);
                    }

                    // 非静态方法
                    foreach (var kv in typeBindingInfo.methods)
                    {
                        var    regName  = kv.Value.regName;
                        var    funcName = kv.Value.name;
                        string redirect;
                        if (this.typeBindingInfo.transform != null && this.typeBindingInfo.transform.TryRedirectMethod(regName, out redirect))
                        {
                            funcName = redirect;
                        }

                        if (typeBindingInfo.bindingManager.prefs.optToString && regName == "ToString")
                        {
                            cg.cs.AppendLine("cls.AddMethod(false, \"{0}\", {1});", "toString", funcName);
                        }
                        else
                        {
                            cg.cs.AppendLine("cls.AddMethod(false, \"{0}\", {1});", regName, funcName);
                        }
                    }

                    // 静态方法
                    foreach (var kv in typeBindingInfo.staticMethods)
                    {
                        var methodBindingInfo = kv.Value;
                        var regName           = methodBindingInfo.regName;
                        if (methodBindingInfo._cfunc != null)
                        {
                            var attr           = (JSCFunctionAttribute)methodBindingInfo._cfunc.GetCustomAttribute(typeof(JSCFunctionAttribute));
                            var methodDeclType = this.cg.bindingManager.GetCSTypeFullName(methodBindingInfo._cfunc.DeclaringType);
                            var isStatic       = attr.isStatic ? "true" : "false";
                            cg.cs.AppendLine("cls.AddRawMethod({0}, \"{1}\", {2}.{3});", isStatic, regName, methodDeclType, methodBindingInfo._cfunc.Name);
                            foreach (var defEntry in attr.difinitions)
                            {
                                string tsMethodRename;
                                var    prefix = attr.isStatic ? "static" : "";
                                if (defEntry.StartsWith("("))
                                {
                                    if (this.cg.bindingManager.GetTSMethodRename(methodBindingInfo._cfunc, out tsMethodRename))
                                    {
                                        this.cg.tsDeclare.AppendLine($"{prefix}{tsMethodRename}{defEntry}");
                                    }
                                    else
                                    {
                                        this.cg.tsDeclare.AppendLine($"{prefix}{regName}{defEntry}");
                                    }
                                }
                                else
                                {
                                    this.cg.tsDeclare.AppendLine($"{prefix}{defEntry}");
                                }
                            }
                        }
                        else
                        {
                            var    funcName = methodBindingInfo.name;
                            string redirect;
                            if (this.typeBindingInfo.transform != null && this.typeBindingInfo.transform.TryRedirectMethod(regName, out redirect))
                            {
                                funcName = redirect;
                            }
                            cg.cs.AppendLine("cls.AddMethod(true, \"{0}\", {1});", regName, funcName);
                        }
                    }

                    // 属性
                    foreach (var kv in typeBindingInfo.properties)
                    {
                        var bindingInfo = kv.Value;
                        if (bindingInfo.staticPair.IsValid())
                        {
                            var tsPropertyVar = BindingManager.GetTSVariable(bindingInfo.regName);
                            cg.cs.AppendLine("cls.AddProperty(true, \"{0}\", {1}, {2});",
                                             tsPropertyVar,
                                             bindingInfo.staticPair.getterName != null ? bindingInfo.staticPair.getterName : "null",
                                             bindingInfo.staticPair.setterName != null ? bindingInfo.staticPair.setterName : "null");

                            var tsPropertyPrefix = "static ";
                            if (bindingInfo.staticPair.setterName == null)
                            {
                                tsPropertyPrefix += "readonly ";
                            }
                            var tsPropertyType = this.cg.bindingManager.GetTSTypeFullName(bindingInfo.propertyInfo.PropertyType);
                            cg.AppendJSDoc(bindingInfo.propertyInfo);
                            cg.tsDeclare.AppendLine($"{tsPropertyPrefix}{tsPropertyVar}: {tsPropertyType}");
                        }

                        if (bindingInfo.instancePair.IsValid())
                        {
                            var tsPropertyVar = BindingManager.GetTSVariable(bindingInfo.regName);
                            cg.cs.AppendLine("cls.AddProperty(false, \"{0}\", {1}, {2});",
                                             tsPropertyVar,
                                             bindingInfo.instancePair.getterName != null ? bindingInfo.instancePair.getterName : "null",
                                             bindingInfo.instancePair.setterName != null ? bindingInfo.instancePair.setterName : "null");

                            var tsPropertyPrefix = "";
                            if (bindingInfo.instancePair.setterName == null)
                            {
                                tsPropertyPrefix += "readonly ";
                            }
                            var tsPropertyType = this.cg.bindingManager.GetTSTypeFullName(bindingInfo.propertyInfo.PropertyType);
                            cg.AppendJSDoc(bindingInfo.propertyInfo);
                            cg.tsDeclare.AppendLine($"{tsPropertyPrefix}{tsPropertyVar}: {tsPropertyType}");
                        }
                    }
                    foreach (var kv in typeBindingInfo.fields)
                    {
                        var bindingInfo = kv.Value;
                        var bStatic     = bindingInfo.isStatic;
                        var tsFieldVar  = BindingManager.GetTSVariable(bindingInfo.regName);
                        if (bindingInfo.constantValue != null)
                        {
                            var cv = bindingInfo.constantValue;
                            cg.cs.AppendLine($"cls.AddConstValue(\"{tsFieldVar}\", {cv});");
                        }
                        else
                        {
                            cg.cs.AppendLine("cls.AddField({0}, \"{1}\", {2}, {3});",
                                             bStatic ? "true" : "false",
                                             tsFieldVar,
                                             bindingInfo.getterName != null ? bindingInfo.getterName : "null",
                                             bindingInfo.setterName != null ? bindingInfo.setterName : "null");
                        }
                        var tsFieldPrefix = bStatic ? "static " : "";
                        if (bindingInfo.setterName == null)
                        {
                            tsFieldPrefix += "readonly ";
                        }
                        var tsFieldType = this.cg.bindingManager.GetTSTypeFullName(bindingInfo.fieldInfo.FieldType);
                        cg.AppendJSDoc(bindingInfo.fieldInfo);
                        cg.tsDeclare.AppendLine($"{tsFieldPrefix}{tsFieldVar}: {tsFieldType}");
                    }
                    foreach (var kv in typeBindingInfo.events)
                    {
                        var eventBindingInfo = kv.Value;
                        var bStatic          = eventBindingInfo.isStatic;
                        //NOTE: 静态事件在绑定过程直接定义, 非静态事件推迟到构造时直接赋值创建
                        var tsFieldVar    = BindingManager.GetTSVariable(eventBindingInfo.regName);
                        var tsFieldType   = this.cg.bindingManager.GetTSTypeFullName(eventBindingInfo.eventInfo.EventHandlerType);
                        var tsFieldPrefix = "";
                        if (bStatic)
                        {
                            tsFieldPrefix += "static ";
                            cg.cs.AppendLine($"cls.AddStaticEvent(\"{tsFieldVar}\", {eventBindingInfo.adderName}, {eventBindingInfo.removerName});");
                        }
                        else
                        {
                            cg.cs.AppendLine($"cls.AddProperty(false, \"{tsFieldVar}\", {eventBindingInfo.proxyName}, null);");
                        }
                        tsFieldPrefix += "readonly ";
                        cg.tsDeclare.AppendLine($"{tsFieldPrefix}{tsFieldVar}: jsb.event<{tsFieldType}>");
                    }
                    cg.cs.AppendLine("cls.Close();");
                }
            }
            base.Dispose();

            this.cg.tsDeclare.DecTabLevel();
            this.cg.tsDeclare.AppendLine("}");
        }