void GenerateDefaultValuesWrapper(string name, MethodBase mb, ParameterInfo[] parameters, int start) { MethodInfo mi = mb as MethodInfo; string objcsig; string monosig; var parametersInfo = parameters; var plist = new List <ParameterInfo> (); StringBuilder arguments = new StringBuilder(); headers.WriteLine("/** This is an helper method that inlines the following default values:"); foreach (var p in parameters) { string pName = NameGenerator.GetExtendedParameterName(p, parameters); if (arguments.Length == 0) { arguments.Append(p.Name.PascalCase()).Append(':'); } else { arguments.Append(' ').Append(p.Name.CamelCase()).Append(':'); } if (p.Position >= start && p.HasDefaultValue) { var raw = FormatRawValue(p.ParameterType, p.RawDefaultValue); headers.WriteLine($" * ({NameGenerator.GetTypeName (p.ParameterType)}) {pName} = {raw};"); arguments.Append(raw); } else { arguments.Append(pName); plist.Add(p); } } headers.WriteLine(" *"); headers.WriteLine($" * @see {name}"); headers.WriteLine(" */"); if (mi == null) { name = start == 0 ? "init" : "initWith"; } else { name = mb.Name.CamelCase(); } GetSignatures(name, mb.Name, mb, plist.ToArray(), false, false, out objcsig, out monosig); var type = mb.DeclaringType; var builder = new MethodHelper(headers, implementation) { IsStatic = mb.IsStatic, ReturnType = mi == null ? "nullable instancetype" : GetReturnType(type, mi.ReturnType), ObjCSignature = objcsig, }; builder.WriteHeaders(); headers.WriteLine(); builder.BeginImplementation(); if (mi == null || !mi.ReturnType.Is("System", "Void")) { implementation.Write("return ["); } if (mb.IsStatic) { implementation.Write(NameGenerator.GetObjCName(mi.DeclaringType)); implementation.Write(' '); } else { implementation.Write("self "); } if (mi == null) { name = "initWith"; } implementation.WriteLine($"{name}{arguments}];"); builder.EndImplementation(); }
protected override void Generate(ProcessedType type) { Type t = type.Type; var aname = t.Assembly.GetName().Name.Sanitize(); var static_type = t.IsSealed && t.IsAbstract; var managed_name = NameGenerator.GetObjCName(t); List <string> conformed_protocols = new List <string> (); foreach (var i in t.GetInterfaces()) { if (protocols.Contains(i)) { conformed_protocols.Add(NameGenerator.GetObjCName(i)); } } var tbuilder = new ClassHelper(headers, implementation) { AssemblyQualifiedName = t.AssemblyQualifiedName, AssemblyName = aname, BaseTypeName = NameGenerator.GetTypeName(t.BaseType), Name = NameGenerator.GetTypeName(t), Namespace = t.Namespace, ManagedName = t.Name, Protocols = conformed_protocols, IsBaseTypeBound = types.Contains(t.BaseType), IsStatic = t.IsSealed && t.IsAbstract, MetadataToken = t.MetadataToken, }; tbuilder.BeginHeaders(); tbuilder.BeginImplementation(); var default_init = false; List <ProcessedConstructor> constructors; if (ctors.TryGetValue(t, out constructors)) { // First get the unavailable init ctor selectors in parent class var unavailableCtors = GetUnavailableParentCtors(t, constructors); if (unavailableCtors.Count() > 0) { // TODO: Print a #pragma mark once we have a well defined header structure http://nshipster.com/pragma/ foreach (var uctor in unavailableCtors) { var ctorparams = uctor.Constructor.GetParameters(); string name = "init"; string signature = ".ctor()"; if (ctorparams.Length > 0) { GetSignatures("initWith", uctor.Constructor.Name, uctor.Constructor, ctorparams, uctor.FallBackToTypeName, false, out name, out signature); } headers.WriteLine("/** This initializer is not available as it was not re-exposed from the base type"); headers.WriteLine(" * For more details consult https://github.com/mono/Embeddinator-4000/blob/master/docs/ObjC.md#constructors-vs-initializers"); headers.WriteLine(" */"); headers.WriteLine($"- (nullable instancetype){name} NS_UNAVAILABLE;"); headers.WriteLine(); } } foreach (var ctor in constructors) { var pcount = ctor.Constructor.ParameterCount; default_init |= pcount == 0; var parameters = ctor.Constructor.GetParameters(); string name = "init"; string signature = ".ctor()"; if (parameters.Length > 0) { GetSignatures("initWith", ctor.Constructor.Name, ctor.Constructor, parameters, ctor.FallBackToTypeName, false, out name, out signature); } var builder = new MethodHelper(headers, implementation) { AssemblySafeName = aname, ReturnType = "nullable instancetype", ManagedTypeName = t.FullName, MetadataToken = ctor.Constructor.MetadataToken, MonoSignature = signature, ObjCSignature = name, ObjCTypeName = managed_name, IsConstructor = true, IsValueType = t.IsValueType, IgnoreException = true, }; builder.WriteHeaders(); builder.BeginImplementation(); builder.WriteMethodLookup(); // TODO: this logic will need to be update for managed NSObject types (e.g. from XI / XM) not to call [super init] implementation.WriteLine("if (!_object) {"); implementation.Indent++; implementation.WriteLine($"MonoObject* __instance = mono_object_new (__mono_context.domain, {managed_name}_class);"); string postInvoke = String.Empty; var args = "nil"; if (pcount > 0) { Generate(parameters, false, out postInvoke); args = "__args"; } builder.WriteInvoke(args); implementation.Write(postInvoke); implementation.WriteLine("_object = mono_embeddinator_create_object (__instance);"); implementation.Indent--; implementation.WriteLine("}"); if (types.Contains(t.BaseType)) { implementation.WriteLine("return self = [super initForSuper];"); } else { implementation.WriteLine("return self = [super init];"); } builder.EndImplementation(); headers.WriteLine(); if (members_with_default_values.Contains(ctor.Constructor)) { default_init |= GenerateDefaultValuesWrappers(name, ctor.Constructor); } } } // generate an `init` for a value type (even if none was defined, the default one is usable) if (!default_init && t.IsValueType) { var builder = new MethodHelper(headers, implementation) { AssemblySafeName = aname, ReturnType = "nullable instancetype", ManagedTypeName = t.FullName, MonoSignature = ".ctor()", ObjCSignature = "init", ObjCTypeName = managed_name, IsConstructor = true, IsValueType = t.IsValueType, IgnoreException = true, }; builder.WriteHeaders(); builder.BeginImplementation(); // no call to `WriteMethodLookup` since there is not such method if we reached this case implementation.WriteLine("if (!_object) {"); implementation.Indent++; implementation.WriteLine($"MonoObject* __instance = mono_object_new (__mono_context.domain, {managed_name}_class);"); // no call to `WriteInvoke` since there is not such method if we reached this case implementation.WriteLine("_object = mono_embeddinator_create_object (__instance);"); implementation.Indent--; implementation.WriteLine("}"); if (types.Contains(t.BaseType)) { implementation.WriteLine("return self = [super initForSuper];"); } else { implementation.WriteLine("return self = [super init];"); } builder.EndImplementation(); headers.WriteLine(); default_init = true; } if (!default_init || static_type) { tbuilder.DefineNoDefaultInit(); } List <ProcessedProperty> props; if (properties.TryGetValue(t, out props)) { headers.WriteLine(); foreach (var pi in props) { Generate(pi); } } List <ProcessedFieldInfo> f; if (fields.TryGetValue(t, out f)) { headers.WriteLine(); foreach (var fi in f) { Generate(fi); } } List <ProcessedProperty> s; if (subscriptProperties.TryGetValue(t, out s)) { headers.WriteLine(); foreach (var si in s) { GenerateSubscript(si); } } List <ProcessedMethod> meths; if (methods.TryGetValue(t, out meths)) { headers.WriteLine(); foreach (var mi in meths) { Generate(mi); } } MethodInfo m; if (icomparable.TryGetValue(t, out m)) { var pt = m.GetParameters() [0].ParameterType; var builder = new ComparableHelper(headers, implementation) { ObjCSignature = $"compare:({managed_name} * _Nullable)other", AssemblySafeName = aname, MetadataToken = m.MetadataToken, ObjCTypeName = managed_name, ManagedTypeName = t.FullName, MonoSignature = $"CompareTo({NameGenerator.GetMonoName (pt)})", }; builder.WriteHeaders(); builder.WriteImplementation(); } if (equals.TryGetValue(t, out m)) { var builder = new EqualsHelper(headers, implementation) { AssemblySafeName = aname, MetadataToken = m.MetadataToken, ObjCTypeName = managed_name, ManagedTypeName = t.FullName, }; builder.WriteHeaders(); builder.WriteImplementation(); } if (hashes.TryGetValue(t, out m)) { var builder = new HashHelper(headers, implementation) { AssemblySafeName = aname, MetadataToken = m.MetadataToken, ObjCTypeName = managed_name, ManagedTypeName = t.FullName, }; builder.WriteHeaders(); builder.WriteImplementation(); } tbuilder.EndHeaders(); tbuilder.EndImplementation(); }