/// <summary> /// Returns parameters and return type remapped according to a constructed type. /// </summary> public ParameterInfo[]/*!*/ MakeConstructed(ConstructedType constructedType, out Type/*!*/ returnType) { MethodInfo method_info = method as MethodInfo; returnType = (method_info != null ? method_info.ReturnType : Types.Void); if (constructedType != null) { returnType = constructedType.MapRealType(returnType); ParameterInfo[] new_params = new ParameterInfo[parameters.Length]; for (int i = 0; i < new_params.Length; i++) { ParameterInfo param_info = parameters[i]; new_params[i] = new StubParameterInfo( param_info.Position, constructedType.MapRealType(param_info.ParameterType), param_info.Attributes, param_info.Name); } return new_params; } else { return parameters; } }
/// <summary> /// Enumerates all export overloads for the given target PHP method. /// </summary> public static IEnumerable<StubInfo> DefineMethodExportStubs( PhpRoutine/*!*/ target, PhpType/*!*/ declaringType, MethodAttributes attributes, bool defineConstructors, StubSignatureFilter/*!*/ signatureFilter) { Debug.Assert(target.Builder != null); Type return_type = Types.Object[0]; PhpRoutineSignature signature = target.Signature; AST.FormalParam[] formal_params = target.Builder.Signature.FormalParams; AST.FormalTypeParam[] formal_type_params = target.Builder.TypeSignature.TypeParams; int gen_sig_count = signature.GenericParamCount - signature.MandatoryGenericParamCount + 1; int arg_sig_count = signature.ParamCount - signature.MandatoryParamCount + 1; // TODO: return type hints // HACK: change return type to void for methods that are apparently event handlers if (signature.GenericParamCount == 0 && arg_sig_count == 1 && signature.ParamCount == 2 && (signature.TypeHints[0] == null || signature.TypeHints[0].RealType == Types.Object[0]) && (signature.TypeHints[1] != null && typeof(EventArgs).IsAssignableFrom(signature.TypeHints[1].RealType))) { return_type = Types.Void; } for (int gen_sig = 0; gen_sig < gen_sig_count; gen_sig++) { for (int arg_sig = 0; arg_sig < arg_sig_count; arg_sig++) { // determine parameter types (except for method mandatory generic parameters) object[] parameter_types = GetStubParameterTypes( arg_sig + signature.MandatoryParamCount, gen_sig + signature.MandatoryGenericParamCount, signature, formal_type_params); // determine generic parameter names string[] generic_param_names = new string[target.Signature.MandatoryGenericParamCount + gen_sig]; for (int i = 0; i < generic_param_names.Length; i++) { generic_param_names[i] = formal_type_params[i].Name.ToString(); } // are we allowed to generate this signature? if (!signatureFilter(generic_param_names, parameter_types, return_type)) continue; GenericTypeParameterBuilder[] generic_params = StubInfo.EmptyGenericParameters; MethodBase method_base = null; MethodBuilder method = null; if (!defineConstructors) { method = declaringType.RealTypeBuilder.DefineMethod(target.FullName, attributes); // determine generic parameters if (generic_param_names.Length > 0) generic_params = method.DefineGenericParameters(generic_param_names); method_base = method; } ParameterInfo[] parameters = new ParameterInfo[parameter_types.Length]; // fill in parameter infos Type[] real_parameter_types = new Type[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { Type type = parameter_types[i] as Type; // generic method parameter fixup if (type == null) { int index = (int)parameter_types[i]; if (index < 0) type = generic_params[-(index + 1)].MakeByRefType(); else type = generic_params[index]; } string param_name; ParameterAttributes param_attrs; if (i < formal_params.Length) { param_name = formal_params[i].Name.ToString(); param_attrs = (formal_params[i].IsOut ? ParameterAttributes.Out : ParameterAttributes.None); } else { param_name = "args" + (i + 1); param_attrs = ParameterAttributes.None; } parameters[i] = new StubParameterInfo(i, type, param_attrs, param_name); real_parameter_types[i] = type; } if (method != null) { method.SetParameters(real_parameter_types); method.SetReturnType(return_type); method.SetCustomAttribute(AttributeBuilders.DebuggerHidden); } else { // constructor is never a generic method attributes |= MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; attributes &= ~MethodAttributes.Virtual; ConstructorBuilder constructor = declaringType.RealTypeBuilder.DefineConstructor( attributes, CallingConventions.Standard, real_parameter_types); constructor.SetCustomAttribute(AttributeBuilders.DebuggerHidden); method_base = constructor; } yield return new StubInfo(method_base, parameters, generic_params, return_type); } } }
/// <summary> /// Enumerates all export overloads for the given target PHP method. /// </summary> public static IEnumerable <StubInfo> DefineMethodExportStubs( PhpRoutine /*!*/ target, MethodAttributes attributes, bool defineConstructors, StubSignatureFilter /*!*/ signatureFilter) { Debug.Assert(target.Builder != null); Type return_type = Types.Object[0]; PhpRoutineSignature signature = target.Signature; List <AST.FormalParam> formal_params = target.Builder.Signature.FormalParams; List <AST.FormalTypeParam> formal_type_params = target.Builder.TypeSignature.TypeParams; int gen_sig_count = signature.GenericParamCount - signature.MandatoryGenericParamCount + 1; int arg_sig_count = signature.ParamCount - signature.MandatoryParamCount + 1; // TODO: return type hints // HACK: change return type to void for methods that are apparently event handlers if (signature.GenericParamCount == 0 && arg_sig_count == 1 && signature.ParamCount == 2 && (signature.TypeHints[0] == null || signature.TypeHints[0].RealType == Types.Object[0]) && (signature.TypeHints[1] != null && typeof(EventArgs).IsAssignableFrom(signature.TypeHints[1].RealType))) { return_type = Types.Void; } for (int gen_sig = 0; gen_sig < gen_sig_count; gen_sig++) { for (int arg_sig = 0; arg_sig < arg_sig_count; arg_sig++) { // determine parameter types (except for method mandatory generic parameters) object[] parameter_types = GetStubParameterTypes( arg_sig + signature.MandatoryParamCount, gen_sig + signature.MandatoryGenericParamCount, signature, formal_type_params); // determine generic parameter names string[] generic_param_names = new string[target.Signature.MandatoryGenericParamCount + gen_sig]; for (int i = 0; i < generic_param_names.Length; i++) { generic_param_names[i] = formal_type_params[i].Name.ToString(); } // are we allowed to generate this signature? if (!signatureFilter(generic_param_names, parameter_types, return_type)) { continue; } GenericTypeParameterBuilder[] generic_params = StubInfo.EmptyGenericParameters; MethodBase method_base = null; MethodBuilder method = null; if (!defineConstructors) { method = target.DeclaringType.RealTypeBuilder.DefineMethod(target.FullName, attributes); // determine generic parameters if (generic_param_names.Length > 0) { generic_params = method.DefineGenericParameters(generic_param_names); } method_base = method; } ParameterInfo[] parameters = new ParameterInfo[parameter_types.Length]; // fill in parameter infos Type[] real_parameter_types = new Type[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { Type type = parameter_types[i] as Type; // generic method parameter fixup if (type == null) { int index = (int)parameter_types[i]; if (index < 0) { type = generic_params[-(index + 1)].MakeByRefType(); } else { type = generic_params[index]; } } string param_name; ParameterAttributes param_attrs; if (i < formal_params.Count) { param_name = formal_params[i].Name.ToString(); param_attrs = (formal_params[i].IsOut ? ParameterAttributes.Out : ParameterAttributes.None); } else { param_name = "args" + (i + 1); param_attrs = ParameterAttributes.None; } parameters[i] = new StubParameterInfo(i, type, param_attrs, param_name); real_parameter_types[i] = type; } if (method != null) { method.SetParameters(real_parameter_types); method.SetReturnType(return_type); method.SetCustomAttribute(AttributeBuilders.DebuggerHidden); } else { // constructor is never a generic method attributes |= MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; attributes &= ~MethodAttributes.Virtual; ConstructorBuilder constructor = target.DeclaringType.RealTypeBuilder.DefineConstructor( attributes, CallingConventions.Standard, real_parameter_types); constructor.SetCustomAttribute(AttributeBuilders.DebuggerHidden); method_base = constructor; } yield return(new StubInfo(method_base, parameters, generic_params, return_type)); } } }