// get a name that is safe to use from ObjC code void GetSignatures(string objName, string monoName, MemberInfo info, ParameterInfo [] parameters, bool useTypeNames, bool isExtension, out string objcSignature, out string monoSignature) { var method = (info as MethodBase); // else it's a PropertyInfo // special case for setter-only - the underscore looks ugly if ((method != null) && method.IsSpecialName) { objName = objName.Replace("_", String.Empty); } var objc = new StringBuilder(objName); var mono = new StringBuilder(monoName); mono.Append('('); for (int n = 0; n < parameters.Length; ++n) { ParameterInfo p = parameters [n]; if (objc.Length > objName.Length) { objc.Append(' '); mono.Append(','); } string paramName = useTypeNames ? p.ParameterType.Name : p.Name; if ((method != null) && (n > 0 || !isExtension)) { if (n == 0) { bool mutatePropertyOrOperatorMethod = useTypeNames && (method.IsPropertyMethod() || method.IsOperatorMethod()); if (method.IsConstructor || mutatePropertyOrOperatorMethod || !method.IsSpecialName) { objc.Append(paramName.PascalCase()); } } else { objc.Append(paramName.ToLowerInvariant()); } } if (n > 0 || !isExtension) { string ptname = NameGenerator.GetObjCParamTypeName(p, types); objc.Append(":(").Append(ptname).Append(")").Append(NameGenerator.GetExtendedParameterName(p, parameters)); } mono.Append(NameGenerator.GetMonoName(p.ParameterType)); } mono.Append(')'); objcSignature = objc.ToString(); monoSignature = mono.ToString(); }
public EquatableHelper(ProcessedMethod method, SourceWriter headers, SourceWriter implementation) : base(method, headers, implementation) { ReturnType = "bool"; var pt = method.Method.GetParameters() [0].ParameterType; var objc = NameGenerator.GetTypeName(pt); var nullable = !pt.IsPrimitive ? " * _Nullable" : ""; ParameterType = pt; ObjCSignature = $"isEqualTo{objc.PascalCase ()}:({objc}{nullable})other"; MonoSignature = $"Equals({NameGenerator.GetMonoName (pt)})"; }
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(); }