// 生成定参部分 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); }
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); } }
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)); }
// 写入绑定代码 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); } }
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); }
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); }