public ClassCodeGen(CodeGenerator cg, TypeBindingInfo typeBindingInfo) : base(cg, typeBindingInfo) { this.cg.AppendJSDoc(this.typeBindingInfo.type); var transform = this.typeBindingInfo.transform; var prefix = string.IsNullOrEmpty(this.typeBindingInfo.jsNamespace) ? "declare " : ""; var super = this.cg.bindingManager.GetTSSuperName(this.typeBindingInfo); var interfaces = this.cg.bindingManager.GetTSInterfacesName(this.typeBindingInfo); var extends = string.IsNullOrEmpty(super) ? "" : $" extends {super}"; var implements = string.IsNullOrEmpty(interfaces) ? "" : $" implements {interfaces}"; var regName = this.typeBindingInfo.jsName; if (typeBindingInfo.type.IsAbstract) { prefix += "abstract "; } this.cg.tsDeclare.AppendLine($"{prefix}class {regName}{extends}{implements} {{"); this.cg.tsDeclare.AddTabLevel(); // 生成函数体 // 构造函数 if (this.typeBindingInfo.constructors.available) { using (new PInvokeGuardCodeGen(cg, typeof(Native.JSCFunctionMagic))) { using (new BindingConstructorDeclareCodeGen(cg, this.typeBindingInfo.constructors.name)) { using (new TryCatchGuradCodeGen(cg)) { using (new ConstructorCodeGen(cg, this.typeBindingInfo)) { } } } } } // 非静态成员方法 foreach (var kv in this.typeBindingInfo.methods) { var methodBindingInfo = kv.Value; if (transform == null || !transform.IsRedirectedMethod(methodBindingInfo.regName)) { using (new PInvokeGuardCodeGen(cg)) { using (new BindingFuncDeclareCodeGen(cg, methodBindingInfo.name)) { using (new TryCatchGuradCodeGen(cg)) { using (new MethodCodeGen(cg, methodBindingInfo)) { } } } } } using (new TSMethodCodeGen(cg, methodBindingInfo)) { } } //TODO: C# 抽象类可以不提供方法实现, d.ts 需要补充声明 // if (this.bindingInfo.type.IsAbstract && !this.bindingInfo.type.IsInterface) // { // } // 静态成员方法 foreach (var kv in this.typeBindingInfo.staticMethods) { var methodBindingInfo = kv.Value; if (transform == null || !transform.IsRedirectedMethod(methodBindingInfo.regName)) { using (new PInvokeGuardCodeGen(cg)) { using (new BindingFuncDeclareCodeGen(cg, methodBindingInfo.name)) { using (new TryCatchGuradCodeGen(cg)) { using (new MethodCodeGen(cg, methodBindingInfo)) { } } } } } using (new TSMethodCodeGen(cg, methodBindingInfo)) { } } foreach (var operatorBindingInfo in this.typeBindingInfo.operators) { if (transform == null || !transform.IsRedirectedMethod(operatorBindingInfo.regName)) { using (new PInvokeGuardCodeGen(cg)) { using (new BindingFuncDeclareCodeGen(cg, operatorBindingInfo.name)) { using (new TryCatchGuradCodeGen(cg)) { using (new OperatorCodeGen(cg, operatorBindingInfo)) { } } } } } using (new TSOperatorCodeGen(cg, operatorBindingInfo)) { } } // 所有附加方法 if (transform != null) { transform.ForEachAdditionalTSMethodDeclaration(decl => { this.cg.tsDeclare.AppendLine(decl); }); } // 所有属性 foreach (var kv in this.typeBindingInfo.properties) { var propertyBindingInfo = kv.Value; // 静态 if (propertyBindingInfo.staticPair.IsValid()) { // 可读属性 if (propertyBindingInfo.staticPair.getterName != null) { using (new PInvokeGuardCodeGen(cg, typeof(JSGetterCFunction))) { using (new BindingGetterFuncDeclareCodeGen(cg, propertyBindingInfo.staticPair.getterName)) { using (new TryCatchGuradCodeGen(cg)) { using (new PropertyGetterCodeGen(cg, propertyBindingInfo)) { } } } } } // 可写属性 if (propertyBindingInfo.staticPair.setterName != null) { using (new PInvokeGuardCodeGen(cg, typeof(JSSetterCFunction))) { using (new BindingSetterFuncDeclareCodeGen(cg, propertyBindingInfo.staticPair.setterName)) { using (new TryCatchGuradCodeGen(cg)) { using (new PropertySetterCodeGen(cg, propertyBindingInfo)) { } } } } } } // 非静态 if (propertyBindingInfo.instancePair.IsValid()) { // 可读属性 if (propertyBindingInfo.instancePair.getterName != null) { using (new PInvokeGuardCodeGen(cg, typeof(JSGetterCFunction))) { using (new BindingGetterFuncDeclareCodeGen(cg, propertyBindingInfo.instancePair.getterName)) { using (new TryCatchGuradCodeGen(cg)) { using (new PropertyGetterCodeGen(cg, propertyBindingInfo)) { } } } } } // 可写属性 if (propertyBindingInfo.instancePair.setterName != null) { using (new PInvokeGuardCodeGen(cg, typeof(JSSetterCFunction))) { using (new BindingSetterFuncDeclareCodeGen(cg, propertyBindingInfo.instancePair.setterName)) { using (new TryCatchGuradCodeGen(cg)) { using (new PropertySetterCodeGen(cg, propertyBindingInfo)) { } } } } } } } // 所有字段 foreach (var kv in this.typeBindingInfo.fields) { var fieldBindingInfo = kv.Value; if (fieldBindingInfo.getterName != null) { using (new PInvokeGuardCodeGen(cg, typeof(JSGetterCFunction))) { using (new BindingGetterFuncDeclareCodeGen(cg, fieldBindingInfo.getterName)) { using (new TryCatchGuradCodeGen(cg)) { using (new FieldGetterCodeGen(cg, fieldBindingInfo)) { } } } } } // 可写字段 if (fieldBindingInfo.setterName != null) { using (new PInvokeGuardCodeGen(cg, typeof(JSSetterCFunction))) { using (new BindingSetterFuncDeclareCodeGen(cg, fieldBindingInfo.setterName)) { using (new TryCatchGuradCodeGen(cg)) { using (new FieldSetterCodeGen(cg, fieldBindingInfo)) { } } } } } } // 所有事件 (当做field相似处理) foreach (var kv in this.typeBindingInfo.events) { var eventBindingInfo = kv.Value; using (new PInvokeGuardCodeGen(cg)) { using (new BindingFuncDeclareCodeGen(cg, eventBindingInfo.adderName)) { using (new TryCatchGuradCodeGen(cg)) { using (new EventAdderCodeGen(cg, eventBindingInfo)) { } } } } using (new PInvokeGuardCodeGen(cg)) { using (new BindingFuncDeclareCodeGen(cg, eventBindingInfo.removerName)) { using (new TryCatchGuradCodeGen(cg)) { using (new EventRemoverCodeGen(cg, eventBindingInfo)) { } } } } if (!eventBindingInfo.isStatic) { using (new PInvokeGuardCodeGen(cg)) { using (new BindingFuncDeclareCodeGen(cg, eventBindingInfo.proxyName)) { using (new TryCatchGuradCodeGen(cg)) { using (new EventProxyCodeGen(cg, eventBindingInfo)) { } } } } } } }
public DelegateCodeGen(CodeGenerator cg, DelegateBindingInfo delegateBindingInfo, int index) { this.cg = cg; var nargs = delegateBindingInfo.parameters.Length; var retName = this.cg.bindingManager.GetUniqueName(delegateBindingInfo.parameters, "ret"); var firstArgument = typeof(ScriptDelegate) + " fn"; var returnTypeName = this.cg.bindingManager.GetCSTypeFullName(delegateBindingInfo.returnType); var delegateName = CodeGenerator.NameOfDelegates + index; var arglist = this.cg.bindingManager.GetCSArglistDecl(delegateBindingInfo.parameters); foreach (var target in delegateBindingInfo.types) { this.cg.cs.AppendLine("[{0}(typeof({1}))]", this.cg.bindingManager.GetCSTypeFullName(typeof(JSDelegateAttribute)), this.cg.bindingManager.GetCSTypeFullName(target)); this.cg.bindingManager.log.AppendLine("emitting delegate decl: {0}", target); } if (!string.IsNullOrEmpty(arglist)) { arglist = ", " + arglist; } this.cg.cs.AppendLine($"public static unsafe {returnTypeName} {delegateName}({firstArgument}{arglist}) {{"); this.cg.cs.AddTabLevel(); this.cg.cs.AppendLine("var ctx = fn.ctx;"); if (nargs > 0) { this.cg.cs.AppendLine("var argv = stackalloc JSValue[{0}];", nargs); for (var i = 0; i < nargs; i++) { var parameter = delegateBindingInfo.parameters[i]; var pusher = this.cg.AppendValuePusher(parameter.ParameterType, parameter.Name); this.cg.cs.AppendLine("argv[{0}] = {1};", i, pusher); this.cg.cs.AppendLine("if (argv[{0}].IsException())", i); this.cg.cs.AppendLine("{"); this.cg.cs.AddTabLevel(); for (var j = 0; j < i; j++) { this.cg.cs.AppendLine("JSApi.JS_FreeValue(ctx, argv[{0}]);", j); } this.cg.cs.AppendLine("throw new Exception(ctx.GetExceptionString());"); this.cg.cs.DecTabLevel(); this.cg.cs.AppendLine("}"); } this.cg.cs.AppendLine("var rval = fn.Invoke(ctx, {0}, argv);", nargs); } else { this.cg.cs.AppendLine("var rval = fn.Invoke(ctx);"); } if (delegateBindingInfo.returnType != typeof(void)) { this.cg.cs.AppendLine($"{this.cg.bindingManager.GetCSTypeFullName(delegateBindingInfo.returnType)} {retName};"); var getter = this.cg.bindingManager.GetScriptObjectGetter(delegateBindingInfo.returnType, "ctx", "rval", retName); this.cg.cs.AppendLine("var succ = {0};", getter); FreeArgs(nargs); CheckReturnValue(); this.cg.cs.AppendLine("if (succ)"); this.cg.cs.AppendLine("{"); this.cg.cs.AddTabLevel(); this.cg.cs.AppendLine($"return {retName};"); this.cg.cs.DecTabLevel(); this.cg.cs.AppendLine("}"); this.cg.cs.AppendLine("else"); this.cg.cs.AppendLine("{"); this.cg.cs.AddTabLevel(); this.cg.cs.AppendLine($"throw new Exception(\"js exception caught\");"); this.cg.cs.DecTabLevel(); this.cg.cs.AppendLine("}"); } else { FreeArgs(nargs); CheckReturnValue(); } }