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); }
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;"); }
// 回填 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); }
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 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(); } } }
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("}"); }