public AutoIndentStringBuilder WriteLine(AutoIndentStringBuilder isb) { return AppendLine (isb); }
public string Generate() { using (var sb = new AutoIndentStringBuilder ()) { using (var hdr = new AutoIndentStringBuilder ()) { using (var decls = new AutoIndentStringBuilder ()) { using (var mthds = new AutoIndentStringBuilder ()) { hdr.WriteLine ("#pragma clang diagnostic ignored \"-Wdeprecated-declarations\""); hdr.WriteLine ("#pragma clang diagnostic ignored \"-Wtypedef-redefinition\""); // temporary hack until we can stop including glib.h hdr.WriteLine ("#pragma clang diagnostic ignored \"-Wobjc-designated-initializers\""); if (Driver.EnableDebug) hdr.WriteLine ("#define DEBUG 1"); hdr.WriteLine ("#include <stdarg.h>"); hdr.WriteLine ("#include <xamarin/xamarin.h>"); hdr.WriteLine ("#include <objc/objc.h>"); hdr.WriteLine ("#include <objc/runtime.h>"); header = hdr; declarations = decls; methods = mthds; Specialize (sb); header = null; declarations = null; methods = null; FlushTrace (); return hdr.ToString () + "\n" + decls.ToString () + "\n" + mthds.ToString () + "\n" + sb.ToString (); } } } } }
void Specialize(AutoIndentStringBuilder sb, ObjCMethod method, List<Exception> exceptions) { var isGeneric = method.DeclaringType.IsGeneric; switch (method.CurrentTrampoline) { case Trampoline.Retain: sb.WriteLine ("-(id) retain"); sb.WriteLine ("{"); sb.WriteLine ("return xamarin_retain_trampoline (self, _cmd);"); sb.WriteLine ("}"); sb.WriteLine (); return; case Trampoline.Release: sb.WriteLine ("-(void) release"); sb.WriteLine ("{"); sb.WriteLine ("xamarin_release_trampoline (self, _cmd);"); sb.WriteLine ("}"); sb.WriteLine (); return; case Trampoline.GetGCHandle: sb.WriteLine ("-(int) xamarinGetGCHandle"); sb.WriteLine ("{"); sb.WriteLine ("return __monoObjectGCHandle.gc_handle;"); sb.WriteLine ("}"); sb.WriteLine (); return; case Trampoline.SetGCHandle: sb.WriteLine ("-(void) xamarinSetGCHandle: (int) gc_handle"); sb.WriteLine ("{"); sb.WriteLine ("__monoObjectGCHandle.gc_handle = gc_handle;"); sb.WriteLine ("__monoObjectGCHandle.native_object = self;"); sb.WriteLine ("}"); sb.WriteLine (); return; case Trampoline.Constructor: if (isGeneric) { sb.WriteLine (GetObjCSignature (method, exceptions)); sb.WriteLine ("{"); sb.WriteLine ("xamarin_throw_product_exception (4126, \"Cannot construct an instance of the type '{0}' from Objective-C because the type is generic.\");\n", method.DeclaringType.Type.FullName.Replace ("/", "+")); sb.WriteLine ("return self;"); sb.WriteLine ("}"); return; } break; #if MONOMAC case Trampoline.CopyWithZone1: sb.AppendLine ("-(id) copyWithZone: (NSZone *) zone"); sb.AppendLine ("{"); sb.AppendLine ("id rv;"); sb.AppendLine ("int gchandle;"); sb.AppendLine (); sb.AppendLine ("gchandle = xamarin_get_gchandle_with_flags (self);"); sb.AppendLine ("if (gchandle != 0)"); sb.Indent ().AppendLine ("xamarin_set_gchandle (self, 0);").Unindent (); // Call the base class implementation sb.AppendLine ("rv = [super copyWithZone: zone];"); sb.AppendLine (); sb.AppendLine ("if (gchandle != 0)"); sb.Indent ().AppendLine ("xamarin_set_gchandle (self, gchandle);").Unindent (); sb.AppendLine (); sb.AppendLine ("return rv;"); sb.AppendLine ("}"); return; case Trampoline.CopyWithZone2: sb.AppendLine ("-(id) copyWithZone: (NSZone *) zone"); sb.AppendLine ("{"); sb.AppendLine ("return xamarin_copyWithZone_trampoline2 (self, _cmd, zone);"); sb.AppendLine ("}"); return; #endif } var rettype = string.Empty; var returntype = method.Method.ReturnType; var isStatic = method.IsStatic; var isInstanceCategory = method.IsCategoryInstance; var isCtor = false; var num_arg = method.Method.Parameters.Count; var descriptiveMethodName = method.DescriptiveMethodName; var name = GetUniqueTrampolineName ("native_to_managed_trampoline_" + descriptiveMethodName); var isVoid = returntype.FullName == "System.Void"; var arguments = new List<string> (); var merge_bodies = true; switch (method.CurrentTrampoline) { case Trampoline.None: case Trampoline.Normal: case Trampoline.Static: case Trampoline.Single: case Trampoline.Double: case Trampoline.Long: case Trampoline.StaticLong: case Trampoline.StaticDouble: case Trampoline.StaticSingle: case Trampoline.X86_DoubleABI_StaticStretTrampoline: case Trampoline.X86_DoubleABI_StretTrampoline: case Trampoline.StaticStret: case Trampoline.Stret: switch (returntype.FullName) { case "System.Int64": rettype = "long long"; break; case "System.UInt64": rettype = "unsigned long long"; break; case "System.Single": rettype = "float"; break; case "System.Double": rettype = "double"; break; default: rettype = ToObjCParameterType (returntype, descriptiveMethodName, exceptions, method.Method); break; } break; case Trampoline.Constructor: rettype = "id"; isCtor = true; break; default: return; } comment.Clear (); nslog_start.Clear (); nslog_end.Clear (); copyback.Clear (); invoke.Clear (); setup_call_stack.Clear (); body.Clear (); setup_return.Clear (); counter++; body.WriteLine ("{"); var indent = merge_bodies ? sb.Indentation : sb.Indentation + 1; body.Indentation = indent; copyback.Indentation = indent; invoke.Indentation = indent; setup_call_stack.Indentation = indent; setup_return.Indentation = indent; // A comment describing the managed signature if (trace) { nslog_start.Indentation = sb.Indentation; comment.Indentation = sb.Indentation; nslog_end.Indentation = sb.Indentation; comment.AppendFormat ("// {2} {0}.{1} (", method.Method.DeclaringType.FullName, method.Method.Name, method.Method.ReturnType.FullName); for (int i = 0; i < num_arg; i++) { var param = method.Method.Parameters [i]; if (i > 0) comment.Append (", "); comment.AppendFormat ("{0} {1}", param.ParameterType.FullName, param.Name); } comment.AppendLine (")"); comment.AppendLine ("// ArgumentSemantic: {0} IsStatic: {1} Selector: '{2}' Signature: '{3}'", method.ArgumentSemantic, method.IsStatic, method.Selector, method.Signature); } // a couple of debug printfs if (trace) { StringBuilder args = new StringBuilder (); nslog_start.AppendFormat ("NSLog (@\"{0} (this: %@, sel: %@", name); for (int i = 0; i < num_arg; i++) { var type = method.Method.Parameters [i].ParameterType; bool isRef = type.IsByReference; if (isRef) type = type.GetElementType (); var td = type.Resolve (); nslog_start.AppendFormat (", {0}: ", method.Method.Parameters [i].Name); args.Append (", "); switch (type.FullName) { case "System.Drawing.RectangleF": if (isRef) { nslog_start.Append ("%p : %@"); #if MMP args.AppendFormat ("p{0}, p{0} ? NSStringFromRect (*p{0}) : @\"NULL\"", i); #else args.AppendFormat ("p{0}, p{0} ? NSStringFromCGRect (*p{0}) : @\"NULL\"", i); #endif } else { nslog_start.Append ("%@"); #if MMP args.AppendFormat ("NSStringFromRect (p{0})", i); #else args.AppendFormat ("NSStringFromCGRect (p{0})", i); #endif } break; case "System.Drawing.PointF": if (isRef) { nslog_start.Append ("%p: %@"); #if MMP args.AppendFormat ("p{0}, p{0} ? NSStringFromPoint (*p{0}) : @\"NULL\"", i); #else args.AppendFormat ("p{0}, p{0} ? NSStringFromCGPoint (*p{0}) : @\"NULL\"", i); #endif } else { nslog_start.Append ("%@"); #if MMP args.AppendFormat ("NSStringFromPoint (p{0})", i); #else args.AppendFormat ("NSStringFromCGPoint (p{0})", i); #endif } break; default: bool unknown; var spec = GetPrintfFormatSpecifier (td, out unknown); if (unknown) { nslog_start.AppendFormat ("%{0}", spec); args.AppendFormat ("&p{0}", i); } else if (isRef) { nslog_start.AppendFormat ("%p *= %{0}", spec); args.AppendFormat ("p{0}, *p{0}", i); } else { nslog_start.AppendFormat ("%{0}", spec); args.AppendFormat ("p{0}", i); } break; } } string ret_arg = string.Empty; nslog_end.Append (nslog_start.ToString ()); if (!isVoid) { bool unknown; var spec = GetPrintfFormatSpecifier (method.Method.ReturnType.Resolve (), out unknown); if (!unknown) { nslog_end.Append (" ret: %"); nslog_end.Append (spec); ret_arg = ", res"; } } nslog_end.Append (") END\", self, NSStringFromSelector (_cmd)"); nslog_end.Append (args.ToString ()); nslog_end.Append (ret_arg); nslog_end.AppendLine (");"); nslog_start.Append (") START\", self, NSStringFromSelector (_cmd)"); nslog_start.Append (args.ToString ()); nslog_start.AppendLine (");"); } // prepare the parameters var baseMethod = GetBaseMethodInTypeHierarchy (method.Method); for (int i = 0; i < num_arg; i++) { var param = method.Method.Parameters [i]; var paramBase = baseMethod.Parameters [i]; var type = method.Parameters [i]; var objctype = ToObjCParameterType (type, descriptiveMethodName, exceptions, method.Method); var original_objctype = objctype; var isRef = type.IsByReference; var isOut = param.IsOut || paramBase.IsOut; var isArray = type is ArrayType; var isNativeEnum = false; var td = type.Resolve (); var isVariadic = i + 1 == num_arg && method.IsVariadic; if (isRef) { type = type.GetElementType (); td = type.Resolve (); original_objctype = ToObjCParameterType (type, descriptiveMethodName, exceptions, method.Method); objctype = ToObjCParameterType (type, descriptiveMethodName, exceptions, method.Method) + "*"; } else if (td.IsEnum) { type = SharedStatic.GetEnumUnderlyingType (td); isNativeEnum = IsDualBuild && SharedStatic.HasAttribute (td, ObjCRuntime, StringConstants.NativeAttribute); td = type.Resolve (); } switch (type.FullName) { case "System.Int64": case "System.UInt64": // We already show MT4145 if the underlying enum type isn't a long or ulong if (isNativeEnum) { string tp; string ntp; if (type.FullName == "System.UInt64") { tp = "unsigned long long"; ntp = "NSUInteger"; } else { tp = "long long"; ntp = "NSInteger"; } if (isRef || isOut) { setup_call_stack.AppendLine ("{1} nativeEnum{0} = 0;", i, tp); setup_call_stack.AppendLine ("arg_ptrs [{0}] = &nativeEnum{0};", i); copyback.AppendLine ("*p{0} = ({1}) nativeEnum{0};", ntp); } else { setup_call_stack.AppendLine ("{1} nativeEnum{0} = p{0};", i, tp); setup_call_stack.AppendLine ("arg_ptrs [{0}] = &nativeEnum{0};", i); } break; } goto case "System.SByte"; case "System.SByte": case "System.Byte": case "System.Char": case "System.Int16": case "System.UInt16": case "System.Int32": case "System.UInt32": case "System.Single": case "System.Double": case "System.Boolean": if (isRef || isOut) { // The isOut semantics isn't quite correct here: we pass the actual input value to managed code. // In theory we should create a temp location and then use a writeback when done instead. // This should be safe though, since managed code (at least C#) can't actually observe the value. setup_call_stack.AppendLine ("arg_ptrs [{0}] = p{0};", i); } else { setup_call_stack.AppendLine ("arg_ptrs [{0}] = &p{0};", i); } break; case "System.IntPtr": if (isVariadic) { setup_call_stack.AppendLine ("va_list a{0};", i); setup_call_stack.AppendLine ("va_start (a{0}, p{1});", i, i - 1); setup_call_stack.AppendLine ("arg_ptrs [{0}] = &a{0};", i); copyback.AppendLine ("va_end (a{0});", i); } else if (isOut) { setup_call_stack.AppendLine ("{1} a{0} = 0;", i, objctype); setup_call_stack.AppendLine ("arg_ptrs [{0}] = &a{0};", i); copyback.AppendLine ("*p{0} = a{0};", i); } else if (isRef) { setup_call_stack.AppendLine ("arg_ptrs [{0}] = p{0};", i); } else { setup_call_stack.AppendLine ("{1} a{0} = p{0};", i, original_objctype); setup_call_stack.AppendLine ("arg_ptrs [{0}] = &a{0};", i); } break; case "ObjCRuntime.Selector": case CompatNamespace + ".ObjCRuntime.Selector": if (isRef) { if (isOut) { setup_call_stack.AppendLine ("void *a{0} = NULL;", i); } else { setup_call_stack.AppendLine ("void *a{0} = *p{0} ? xamarin_get_selector (*p{0}) : NULL;", i); } setup_call_stack.AppendLine ("arg_ptrs [{0}] = &a{0};", i); copyback.AppendLine ("*p{0} = a{0};", i); } else { setup_call_stack.AppendLine ("arg_ptrs [{0}] = p{0} ? xamarin_get_selector (p{0}) : NULL;", i); } break; case "ObjCRuntime.Class": case CompatNamespace + ".ObjCRuntime.Class": if (isRef) { if (isOut) { setup_call_stack.AppendLine ("void *a{0} = NULL;", i); } else { setup_call_stack.AppendLine ("void *a{0} = *p{0} ? xamarin_get_class (*p{0}) : NULL;", i); } setup_call_stack.AppendLine ("arg_ptrs [{0}] = &a{0};", i); copyback.AppendLine ("*p{0} = a{0};", i); } else { setup_call_stack.AppendLine ("arg_ptrs [{0}] = p{0} ? xamarin_get_class (p{0}) : NULL;", i); } break; case "System.String": // This should always be an NSString and never char* if (isRef) { if (isOut) { setup_call_stack.AppendLine ("MonoString *a{0} = NULL;", i); } else { setup_call_stack.AppendLine ("MonoString *a{0} = *p{0} ? mono_string_new (mono_domain_get (), [(*p{0}) UTF8String]) : NULL;", i); } setup_call_stack.AppendLine ("arg_ptrs [{0}] = &a{0};", i); copyback.AppendLine ("char *str{0} = mono_string_to_utf8 (a{0});", i); copyback.AppendLine ("*p{0} = [[NSString alloc] initWithUTF8String:str{0}];", i); copyback.AppendLine ("[*p{0} autorelease];", i); copyback.AppendLine ("mono_free (str{0});", i); } else { setup_call_stack.AppendLine ("arg_ptrs [{0}] = p{0} ? mono_string_new (mono_domain_get (), [p{0} UTF8String]) : NULL;", i); } break; default: if (isArray) { var elementType = ((ArrayType)type).ElementType; var isNativeObject = false; setup_call_stack.AppendLine ("if (p{0}) {{", i); setup_call_stack.AppendLine ("NSArray *arr = (NSArray *) p{0};", i); if (Driver.EnableDebug) setup_call_stack.AppendLine ("xamarin_check_objc_type (p{0}, [NSArray class], _cmd, self, {0}, managed_method);", i); setup_call_stack.AppendLine ("MonoClass *e_class;"); setup_call_stack.AppendLine ("MonoArray *marr;"); setup_call_stack.AppendLine ("MonoType *p;"); setup_call_stack.AppendLine ("int j;", i); setup_call_stack.AppendLine ("p = xamarin_get_parameter_type (managed_method, {0});", i); setup_call_stack.AppendLine ("e_class = mono_class_get_element_class (mono_class_from_mono_type (p));"); setup_call_stack.AppendLine ("marr = mono_array_new (mono_domain_get (), e_class, [arr count]);", i); setup_call_stack.AppendLine ("for (j = 0; j < [arr count]; j++) {{", i); if (elementType.FullName == "System.String") { setup_call_stack.AppendLine ("NSString *sv = (NSString *) [arr objectAtIndex: j];", i); setup_call_stack.AppendLine ("mono_array_set (marr, MonoString *, j, mono_string_new (mono_domain_get (), [sv UTF8String]));", i); } else if (IsNSObject (elementType) || (elementType.Namespace == "System" && elementType.Name == "Object") || (isNativeObject = SharedStatic.IsNativeObject (elementType))) { setup_call_stack.AppendLine ("NSObject *nobj = [arr objectAtIndex: j];"); setup_call_stack.AppendLine ("MonoObject *mobj{0} = NULL;", i); setup_call_stack.AppendLine ("if (nobj) {"); if (isNativeObject) { TypeDefinition nativeObjType = elementType.Resolve (); if (nativeObjType.IsInterface) { var wrapper_type = GetProtocolAttributeWrapperType (nativeObjType); if (wrapper_type == null) throw ErrorHelper.CreateError (4125, "The registrar found an invalid type '{0}' in signature for method '{1}': " + "The interface must have a Protocol attribute specifying its wrapper type.", td.FullName, descriptiveMethodName); nativeObjType = wrapper_type.Resolve (); } // verify that the type has a ctor with two parameters if (!HasIntPtrBoolCtor (nativeObjType)) throw ErrorHelper.CreateError (4103, "The registrar found an invalid type `{0}` in signature for method `{1}`: " + "The type implements INativeObject, but does not have a constructor that takes " + "two (IntPtr, bool) arguments.", nativeObjType.FullName, descriptiveMethodName); if (nativeObjType.IsInterface) { setup_call_stack.AppendLine ("mobj{0} = xamarin_get_inative_object_static (nobj, false, \"{1}\", \"{2}\");", i, GetAssemblyQualifiedName (nativeObjType), GetAssemblyQualifiedName (elementType)); } else { // find the MonoClass for this parameter setup_call_stack.AppendLine ("MonoType *type{0};", i); setup_call_stack.AppendLine ("type{0} = xamarin_get_parameter_type (managed_method, {0});", i); setup_call_stack.AppendLine ("mobj{0} = xamarin_get_inative_object_dynamic (nobj, false, mono_type_get_object (mono_domain_get (), mono_class_get_type (e_class)));", i); } } else { setup_call_stack.AppendLine ("mobj{0} = xamarin_get_managed_object_for_ptr_fast (nobj);", i); } if (Driver.EnableDebug) { setup_call_stack.AppendLine ("xamarin_verify_parameter (mobj{0}, _cmd, self, nobj, {0}, e_class, managed_method);", i); } setup_call_stack.AppendLine ("}"); setup_call_stack.AppendLine ("mono_array_set (marr, MonoObject *, j, mobj{0});", i); } else { throw ErrorHelper.CreateError (4111, method.Method, "The registrar cannot build a signature for type `{0}' in method `{1}`.", type.FullName, descriptiveMethodName); } setup_call_stack.AppendLine ("}"); setup_call_stack.AppendLine ("arg_ptrs [{0}] = marr;", i); setup_call_stack.AppendLine ("} else {"); setup_call_stack.AppendLine ("arg_ptrs [{0}] = NULL;", i); setup_call_stack.AppendLine ("}"); } else if (IsNSObject (type)) { if (isRef) { setup_call_stack.AppendLine ("MonoObject *mobj{0} = NULL;", i); if (!isOut) { setup_call_stack.AppendLine ("NSObject *nsobj{0} = *(NSObject **) p{0};", i); setup_call_stack.AppendLine ("if (nsobj{0}) {{", i); setup_call_stack.AppendLine ("MonoType *paramtype{0} = xamarin_get_parameter_type (managed_method, {0});", i); setup_call_stack.AppendLine ("mobj{0} = xamarin_get_nsobject_with_type_for_ptr (nsobj{0}, false, paramtype{0});", i); if (Driver.EnableDebug) { setup_call_stack.AppendLine ("xamarin_verify_parameter (mobj{0}, _cmd, self, nsobj{0}, {0}, mono_class_from_mono_type (paramtype{0}), managed_method);", i); } setup_call_stack.AppendLine ("}"); } // argument semantics? setup_call_stack.AppendLine ("arg_ptrs [{0}] = (int *) &mobj{0};", i); copyback.AppendLine ("void * handle{0} = NULL;", i); copyback.AppendLine ("if (mobj{0} != NULL)", i); copyback.AppendLine ("handle{0} = xamarin_get_nsobject_handle (mobj{0});", i); copyback.AppendLine ("*p{0} = (id) handle{0};", i); } else { setup_call_stack.AppendLine ("NSObject *nsobj{0} = (NSObject *) p{0};", i); if (method.ArgumentSemantic == ArgumentSemantic.Copy) { setup_call_stack.AppendLine ("nsobj{0} = [nsobj{0} copy];", i); setup_call_stack.AppendLine ("[nsobj{0} autorelease];", i); } setup_call_stack.AppendLine ("MonoObject *mobj{0} = NULL;", i); setup_call_stack.AppendLine ("int32_t created{0} = false;", i); setup_call_stack.AppendLine ("if (nsobj{0}) {{", i); setup_call_stack.AppendLine ("MonoType *paramtype{0} = xamarin_get_parameter_type (managed_method, {0});", i); setup_call_stack.AppendLine ("mobj{0} = xamarin_get_nsobject_with_type_for_ptr_created (nsobj{0}, false, paramtype{0}, &created{0});", i); if (Driver.EnableDebug) { setup_call_stack.AppendLine ("xamarin_verify_parameter (mobj{0}, _cmd, self, nsobj{0}, {0}, mono_class_from_mono_type (paramtype{0}), managed_method);", i); } setup_call_stack.AppendLine ("}"); setup_call_stack.AppendLine ("arg_ptrs [{0}] = mobj{0};", i); if (SharedStatic.HasAttribute (paramBase, ObjCRuntime, StringConstants.TransientAttribute)) { copyback.AppendLine ("if (created{0})", i); copyback.Indentation++; copyback.AppendLine ("xamarin_dispose (mobj{0});", i); copyback.Indentation--; } } } else if (SharedStatic.IsNativeObject (td)) { TypeDefinition nativeObjType = td; if (td.IsInterface) { var wrapper_type = GetProtocolAttributeWrapperType (td); if (wrapper_type == null) throw ErrorHelper.CreateError (4125, "The registrar found an invalid type '{0}' in signature for method '{1}': " + "The interface must have a Protocol attribute specifying its wrapper type.", td.FullName, descriptiveMethodName); nativeObjType = wrapper_type.Resolve (); } // verify that the type has a ctor with two parameters if (!HasIntPtrBoolCtor (nativeObjType)) throw ErrorHelper.CreateError (4103, "The registrar found an invalid type `{0}` in signature for method `{1}`: " + "The type implements INativeObject, but does not have a constructor that takes " + "two (IntPtr, bool) arguments.", nativeObjType.FullName, descriptiveMethodName); if (!td.IsInterface) { // find the MonoClass for this parameter setup_call_stack.AppendLine ("MonoType *type{0};", i); setup_call_stack.AppendLine ("type{0} = xamarin_get_parameter_type (managed_method, {0});", i); } if (isRef) { setup_call_stack.AppendLine ("MonoObject *inobj{0};", i); if (isOut) { setup_call_stack.AppendLine ("inobj{0} = NULL;", i); } else if (td.IsInterface) { setup_call_stack.AppendLine ("inobj{0} = xamarin_get_inative_object_static (*p{0}, false, \"{1}\", \"{2}\");", i, GetAssemblyQualifiedName (nativeObjType), GetAssemblyQualifiedName (td)); } else { setup_call_stack.AppendLine ("inobj{0} = xamarin_get_inative_object_dynamic (*p{0}, false, mono_type_get_object (mono_domain_get (), type{0}));", i); } setup_call_stack.AppendLine ("arg_ptrs [{0}] = &inobj{0};", i); copyback.AppendLine ("id handle{0} = nil;", i); copyback.AppendLine ("if (inobj{0} != NULL)", i); copyback.AppendLine ("handle{0} = xamarin_get_handle_for_inativeobject (inobj{0});", i); copyback.AppendLine ("*p{0} = (id) handle{0};", i); } else { if (td.IsInterface) { setup_call_stack.AppendLine ("arg_ptrs [{0}] = xamarin_get_inative_object_static (p{0}, false, \"{1}\", \"{2}\");", i, GetAssemblyQualifiedName (nativeObjType), GetAssemblyQualifiedName (td)); } else { setup_call_stack.AppendLine ("arg_ptrs [{0}] = xamarin_get_inative_object_dynamic (p{0}, false, mono_type_get_object (mono_domain_get (), type{0}));", i); } } } else if (type.IsValueType) { if (isRef || isOut) { // The isOut semantics isn't quite correct here: we pass the actual input value to managed code. // In theory we should create a temp location and then use a writeback when done instead. // This should be safe though, since managed code (at least C#) can't actually observe the value. setup_call_stack.AppendLine ("arg_ptrs [{0}] = p{0};", i); } else { setup_call_stack.AppendLine ("arg_ptrs [{0}] = &p{0};", i); } } else if (td.BaseType.FullName == "System.MulticastDelegate") { if (isRef) { throw ErrorHelper.CreateError (4110, "The registrar cannot marshal the out parameter of type `{0}` in signature for method `{1}`.", type.FullName, descriptiveMethodName); } else { // Bug #4858 (also related: #4718) setup_call_stack.AppendLine ("if (p{0}) {{", i); setup_call_stack.AppendLine ("arg_ptrs [{0}] = (void *) xamarin_get_delegate_for_block_parameter (managed_method, {0}, p{0});", i); setup_call_stack.AppendLine ("} else {"); setup_call_stack.AppendLine ("arg_ptrs [{0}] = NULL;", i); setup_call_stack.AppendLine ("}"); } } else { throw ErrorHelper.CreateError (4105, "The registrar cannot marshal the parameter of type `{0}` in signature for method `{1}`.", type.FullName, descriptiveMethodName); } break; } } // the actual invoke if (isCtor) { invoke.AppendLine ("mthis = mono_object_new (mono_domain_get (), mono_method_get_class (managed_method));", counter); invoke.AppendLine ("uint8_t flags = NSObjectFlagsNativeRef;"); invoke.AppendLine ("xamarin_set_nsobject_handle (mthis, self);"); invoke.AppendLine ("xamarin_set_nsobject_flags (mthis, flags);"); } if (!isVoid) invoke.AppendFormat ("{0} retval = ", "MonoObject *"); invoke.AppendLine ("mono_runtime_invoke (managed_method, {0}, arg_ptrs, NULL);", isStatic ? "NULL" : "mthis"); if (isCtor) invoke.AppendLine ("xamarin_create_managed_ref (self, mthis, true);"); // prepare the return value if (!isVoid) { setup_return.AppendLine ("{0} res;", rettype); var isArray = returntype is ArrayType; var type = returntype.Resolve () ?? returntype; var retain = method.RetainReturnValue; if (returntype.IsValueType) { setup_return.AppendLine ("res = *({0} *) mono_object_unbox ((MonoObject *) retval);", rettype); } else if (isArray) { var elementType = ((ArrayType) returntype).ElementType; setup_return.AppendLine ("if (retval) {"); setup_return.AppendLine ("int length = mono_array_length ((MonoArray *) retval);"); setup_return.AppendLine ("int i;"); setup_return.AppendLine ("id *buf = (id *) malloc (sizeof (void *) * length);"); setup_return.AppendLine ("for (i = 0; i < length; i++) {"); setup_return.AppendLine ("MonoObject *value = mono_array_get ((MonoArray *) retval, MonoObject *, i);"); if (elementType.FullName == "System.String") { setup_return.AppendLine ("char *str = mono_string_to_utf8 ((MonoString *) value);"); setup_return.AppendLine ("NSString *sv = [[NSString alloc] initWithUTF8String:str];"); setup_return.AppendLine ("[sv autorelease];"); setup_return.AppendLine ("mono_free (str);"); setup_return.AppendLine ("buf [i] = sv;"); } else if (IsNSObject (elementType)) { setup_return.AppendLine ("buf [i] = xamarin_get_nsobject_handle ((MonoObject *) value);"); } else if (IsINativeObject (elementType)) { setup_return.AppendLine ("buf [i] = xamarin_get_handle_for_inativeobject ((MonoObject *) value);"); } else { throw ErrorHelper.CreateError (4111, method.Method, "The registrar cannot build a signature for type `{0}' in method `{1}`.", returntype.FullName, descriptiveMethodName); } setup_return.AppendLine ("}"); setup_return.AppendLine ("NSArray *arr = [[NSArray alloc] initWithObjects: buf count: length];"); setup_return.AppendLine ("free (buf);"); if (!retain) setup_return.AppendLine ("[arr autorelease];"); setup_return.AppendLine ("res = arr;"); setup_return.AppendLine ("} else {"); setup_return.AppendLine ("res = NULL;"); setup_return.AppendLine ("}"); setup_return.AppendLine ("xamarin_framework_peer_lock ();"); setup_return.AppendLine ("mt_dummy_use (retval);"); setup_return.AppendLine ("xamarin_framework_peer_unlock ();"); } else { setup_return.AppendLine ("if (!retval) {"); setup_return.AppendLine ("res = NULL;"); setup_return.AppendLine ("} else {"); if (IsNSObject (type)) { setup_return.AppendLine ("id retobj;"); setup_return.AppendLine ("retobj = xamarin_get_nsobject_handle (retval);"); setup_return.AppendLine ("xamarin_framework_peer_lock ();"); setup_return.AppendLine ("[retobj retain];"); setup_return.AppendLine ("xamarin_framework_peer_unlock ();"); if (!retain) setup_return.AppendLine ("[retobj autorelease];"); setup_return.AppendLine ("mt_dummy_use (retval);"); setup_return.AppendLine ("res = retobj;"); } else if (type.IsPlatformType ("ObjCRuntime", "Selector")) { setup_return.AppendLine ("res = xamarin_get_selector_handle (retval);"); } else if (type.IsPlatformType ("ObjCRuntime", "Class")) { setup_return.AppendLine ("res = xamarin_get_class_handle (retval);"); } else if (SharedStatic.IsNativeObject (type)) { setup_return.AppendLine ("{0} retobj;", rettype); setup_return.AppendLine ("retobj = xamarin_get_handle_for_inativeobject ((MonoObject *) retval);"); setup_return.AppendLine ("xamarin_framework_peer_lock ();"); setup_return.AppendLine ("[retobj retain];"); setup_return.AppendLine ("xamarin_framework_peer_unlock ();"); if (!retain) setup_return.AppendLine ("[retobj autorelease];"); setup_return.AppendLine ("mt_dummy_use (retval);"); setup_return.AppendLine ("res = retobj;"); } else if (type.FullName == "System.String") { // This should always be an NSString and never char* setup_return.AppendLine ("char *str = mono_string_to_utf8 ((MonoString *) retval);"); setup_return.AppendLine ("NSString *nsstr = [[NSString alloc] initWithUTF8String:str];"); if (!retain) setup_return.AppendLine ("[nsstr autorelease];"); setup_return.AppendLine ("mono_free (str);"); setup_return.AppendLine ("res = nsstr;"); } else if (SharedStatic.IsDelegate (type.Resolve ())) { setup_return.AppendLine ("res = xamarin_get_block_for_delegate (managed_method, retval);"); } else { throw ErrorHelper.CreateError (4104, "The registrar cannot marshal the return value for type `{0}` in signature for method `{1}`.", returntype.FullName, descriptiveMethodName); } setup_return.AppendLine ("}"); } } // Write out everything if (merge_bodies) { body.WriteLine ("MonoMethod *managed_method = *managed_method_ptr;"); } else { if (!isGeneric) body.Write ("static "); body.WriteLine ("MonoMethod *managed_method = NULL;"); } if (comment.Length > 0) body.WriteLine (comment.ToString ()); if (isInstanceCategory) body.WriteLine ("id p0 = self;"); body.WriteLine ("void *arg_ptrs [{0}];", num_arg); if (!isStatic || isInstanceCategory) body.WriteLine ("MonoObject *mthis;"); body.WriteLine ("if (mono_domain_get () == NULL)"); body.Indent (); body.WriteLine ("mono_jit_thread_attach (NULL);"); body.Unindent (); if (isCtor) { body.WriteLine ("if (xamarin_try_get_nsobject (self)) {"); body.WriteLine ("*call_super = true;"); body.WriteLine ("return self;"); body.WriteLine ("}"); } if ((!isStatic || isInstanceCategory) && !isCtor) { body.WriteLine ("mthis = NULL;"); body.WriteLine ("if (self) {"); body.WriteLine ("mthis = xamarin_get_managed_object_for_ptr_fast (self);"); body.WriteLine ("}"); } // no locking should be required here, it doesn't matter if we overwrite the field (it'll be the same value). body.WriteLine ("if (!managed_method) {"); if (num_arg > 0) { body.Write ("const char *paramptr[{0}] = {{ ", num_arg); for (int i = 0; i < num_arg; i++) { string paramtype; if (isGeneric) { paramtype = GetAssemblyQualifiedName (method.Method.Parameters [i].ParameterType); } else { paramtype = GetAssemblyQualifiedName (method.Parameters [i]); } if (merge_bodies) { body.Write ("r{0}", arguments.Count); arguments.Add (paramtype); } else { body.Write ("\"{0}\"", paramtype); } if (i < num_arg - 1) body.Write (", "); } body.WriteLine (" };"); } body.Write ("managed_method = "); if (isGeneric) body.Write ("xamarin_get_reflection_method_method (xamarin_get_generic_method_direct (mthis, "); else body.Write ("xamarin_get_reflection_method_method (xamarin_get_method_direct("); if (merge_bodies) { body.WriteLine ("r{2}, r{3}, {0}, {1}));", num_arg, num_arg > 0 ? "paramptr" : "NULL", arguments.Count, arguments.Count + 1); arguments.Add (GetAssemblyQualifiedName (method.Method.DeclaringType)); arguments.Add (method.Method.Name); } else { body.WriteLine ("\"{0}\", \"{1}\", {2}, {3}));", GetAssemblyQualifiedName (method.Method.DeclaringType), method.Method.Name, num_arg, num_arg > 0 ? "paramptr" : "NULL"); } if (merge_bodies) body.WriteLine ("*managed_method_ptr = managed_method;"); body.WriteLine ("}"); if (!isStatic && !isInstanceCategory && !isCtor) body.WriteLine ("xamarin_check_for_gced_object (mthis, _cmd, self, managed_method);"); if (trace) body.AppendLine (nslog_start); body.AppendLine (setup_call_stack); body.AppendLine (invoke); body.AppendLine (copyback); body.AppendLine (setup_return); if (trace ) body.AppendLine (nslog_end); if (isCtor) { body.WriteLine ("return self;"); } else if (isVoid) { body.WriteLine ("return;"); } else { body.WriteLine ("return res;"); } body.WriteLine ("}"); /* We merge duplicated bodies (based on the signature of the method and the entire body) */ var objc_signature = new StringBuilder ().Append (rettype).Append (":"); for (int i = 0; i < method.Method.Parameters.Count; i++) objc_signature.Append (ToObjCParameterType (method.Method.Parameters [i].ParameterType, descriptiveMethodName, exceptions, method.Method)).Append (":"); Body existing; Body b = new Body () { Code = body.ToString (), Signature = objc_signature.ToString (), }; if (merge_bodies && bodies.TryGetValue (b, out existing)) { /* We already have an identical trampoline, use it instead */ b = existing; } else { /* Need to create a new trampoline */ if (merge_bodies) bodies [b] = b; b.Name = "native_to_managed_trampoline_" + bodies.Count.ToString (); if (merge_bodies) { methods.Append ("static "); methods.Append (rettype).Append (" ").Append (b.Name).Append (" (id self, SEL _cmd, MonoMethod **managed_method_ptr"); for (int i = (isInstanceCategory ? 1 : 0); i < method.Method.Parameters.Count; i++) { methods.Append (", ").Append (ToObjCParameterType (method.Method.Parameters [i].ParameterType, descriptiveMethodName, exceptions, method.Method)); methods.Append (" ").Append ("p").Append (i.ToString ()); } for (int i = 0; i < arguments.Count; i++) methods.Append (", const char *").Append ("r").Append (i.ToString ()); if (isCtor) methods.Append (", bool* call_super"); methods.AppendLine (")"); methods.AppendLine (body); methods.AppendLine (); } } b.Count++; sb.WriteLine (); sb.WriteLine (GetObjCSignature (method, exceptions)); if (merge_bodies) { sb.WriteLine ("{"); if (!isGeneric) sb.Write ("static "); sb.WriteLine ("MonoMethod *managed_method = NULL;"); if (isCtor) { sb.WriteLine ("bool call_super = false;"); sb.Write ("id rv = "); } else if (!isVoid) { sb.Write ("return "); } sb.Write (b.Name); sb.Write (" (self, _cmd, &managed_method"); var paramCount = method.Method.Parameters.Count; if (isInstanceCategory) paramCount--; for (int i = 0; i < paramCount; i++) sb.Write (", p{0}", i); for (int i = 0; i < arguments.Count; i++) sb.Write (", \"").Write (arguments [i]).Write ("\""); if (isCtor) sb.Write (", &call_super"); sb.WriteLine (");"); if (isCtor) { sb.WriteLine ("if (call_super)"); sb.Indent (); sb.Write ("rv = [super"); var split = method.Selector.Split (':'); if (split.Length == 1) { sb.Append (" "); sb.Append (split [0]); } else { for (int i = 0; i < split.Length - 1; i++) { sb.Append (" "); sb.Append (split [i]); sb.Append (":"); sb.AppendFormat ("p{0}", i); } } sb.WriteLine ("];"); sb.Unindent (); sb.WriteLine ("return rv;"); } sb.WriteLine ("}"); } else { sb.WriteLine (body); } }
void Specialize(AutoIndentStringBuilder sb) { List<Exception> exceptions = new List<Exception> (); List<ObjCMember> skip = new List<ObjCMember> (); var map = new AutoIndentStringBuilder (1); var map_init = new AutoIndentStringBuilder (); var i = 0; map.AppendLine ("static MTClassMap __xamarin_class_map [] = {"); if (string.IsNullOrEmpty (single_assembly)) { map_init.AppendLine ("void xamarin_create_classes () {"); } else { map_init.AppendLine ("void xamarin_create_classes_{0} () {{", single_assembly.Replace ('.', '_').Replace ('-', '_')); } // Select the types that needs to be registered. var allTypes = new List<ObjCType> (); foreach (var @class in Types.Values) { if (!string.IsNullOrEmpty (single_assembly) && single_assembly != @class.Type.Module.Assembly.Name.Name) continue; #if !MONOMAC var isPlatformType = IsPlatformType (@class.Type); if (isPlatformType && IsSimulatorOrDesktop && IsMetalType (@class)) continue; // Metal isn't supported in the simulator. #endif if (@class.IsFakeProtocol) continue; allTypes.Add (@class); } // Move all the custom types to the end of the list, respecting // existing order (so that a derived type always comes after // its base type; the Types.Values has that property, and we // need to keep it that way). var mappedEnd = allTypes.Count; var counter = 0; while (counter < mappedEnd) { if (!IsPlatformType (allTypes [counter].Type)) { var t = allTypes [counter]; allTypes.RemoveAt (counter); allTypes.Add (t); mappedEnd--; } else { counter++; } } var customTypeCount = 0; foreach (var @class in allTypes) { var isPlatformType = IsPlatformType (@class.Type); skip.Clear (); if ([email protected] && [email protected] && [email protected]) { if (!isPlatformType) customTypeCount++; CheckNamespace (@class, exceptions); map.AppendLine ("{{\"{0}\", \"{1}\", NULL }},", @class.ExportedName, GetAssemblyQualifiedName (@class.Type)); bool use_dynamic; if (@class.Type.Resolve ().Module.Assembly.Name.Name == PlatformAssembly) { // we don't need to use the static ref to prevent the linker from removing (otherwise unreferenced) code for monotouch.dll types. use_dynamic = true; // be smarter: we don't need to use dynamic refs for types available in the lowest version (target deployment) we building for. // We do need to use dynamic class lookup when the following conditions are all true: // * The class is not available in the target deployment version. // * The class is not in a weakly linked framework (for instance if an existing framework introduces a new class, we don't // weakly link the framework because it already exists in the target deployment version - but since the class doesn't, we // must use dynamic class lookup to determine if it's available or not. } else { use_dynamic = false; } switch (@class.ExportedName) { case "EKObject": // EKObject's class is a private symbol, so we can't link with it... use_dynamic = true; break; } string get_class; if (use_dynamic) { get_class = string.Format ("objc_getClass (\"{0}\")", @class.ExportedName); } else { get_class = string.Format ("[{0} class]", EncodeNonAsciiCharacters (@class.ExportedName)); } map_init.AppendLine ("__xamarin_class_map [{1}].handle = {0};", get_class, i++); } if (@class.IsWrapper && isPlatformType) continue; if (@class.Methods == null && isPlatformType && [email protected] && [email protected]) continue; if (@class.IsModel) continue; CheckNamespace (@class, exceptions); if (@class.BaseType != null) CheckNamespace (@class.BaseType, exceptions); var class_name = EncodeNonAsciiCharacters (@class.ExportedName); var is_protocol = @class.IsProtocol; if (@class.IsCategory) { sb.Write ("@interface {0} ({1})", EncodeNonAsciiCharacters (@class.BaseType.ExportedName), @class.CategoryName); } else if (is_protocol) { sb.Write ("@protocol ").Write (EncodeNonAsciiCharacters (@class.ProtocolName)); } else { sb.Write ("@interface {0} : {1}", class_name, EncodeNonAsciiCharacters (@class.SuperType.ExportedName)); } bool any_protocols = false; ObjCType tp = @class; while (tp != null && tp != tp.BaseType) { if (tp.IsWrapper) break; // no need to declare protocols for wrapper types, they do it already in their headers. if (tp.Protocols != null) { for (int p = 0; p < tp.Protocols.Length; p++) { if (tp.Protocols [p].ProtocolName == "UIAppearance") continue; sb.Append (any_protocols ? ", " : "<"); any_protocols = true; sb.Append (tp.Protocols [p].ProtocolName); CheckNamespace (tp.Protocols [p], exceptions); } } tp = tp.BaseType; } if (any_protocols) sb.Append (">"); if (is_protocol) { sb.WriteLine (); } else { sb.WriteLine (" {"); if (@class.Fields != null) { foreach (var field in @class.Fields.Values) { try { switch (field.FieldType) { case "@": sb.Write ("id "); break; case "^v": sb.Write ("void *"); break; case "XamarinObject": sb.Write ("XamarinObject "); break; default: throw ErrorHelper.CreateError (4120, "The registrar found an unknown field type '{0}' in field '{1}.{2}'. Please file a bug report at http://bugzilla.xamarin.com", field.FieldType, field.DeclaringType.Type.FullName, field.Name); } sb.Write (field.Name); sb.WriteLine (";"); } catch (Exception ex) { exceptions.Add (ex); } } } sb.WriteLine ("}"); } sb.Indent (); if (@class.Properties != null) { foreach (var property in @class.Properties) { try { if (is_protocol) sb.Write (property.IsOptional ? "@optional " : "@required "); sb.Write ("@property (nonatomic"); switch (property.ArgumentSemantic) { case ArgumentSemantic.Copy: sb.Write (", copy"); break; case ArgumentSemantic.Retain: sb.Write (", retain"); break; case ArgumentSemantic.Assign: case ArgumentSemantic.None: default: sb.Write (", assign"); break; } if (property.IsReadOnly) sb.Write (", readonly"); if (property.Selector != null) { if (property.GetterSelector != null && property.Selector != property.GetterSelector) sb.Write (", getter = ").Write (property.GetterSelector); if (property.SetterSelector != null) { var setterSel = string.Format ("set{0}{1}:", char.ToUpperInvariant (property.Selector [0]), property.Selector.Substring (1)); if (setterSel != property.SetterSelector) sb.Write (", setter = ").Write (property.SetterSelector); } } sb.Write (") "); try { sb.Write (ToObjCParameterType (property.PropertyType, property.DeclaringType.Type.FullName, exceptions, property.Property)); } catch (ProductException mte) { exceptions.Add (CreateException (4138, mte, property.Property, "The registrar cannot marshal the property type '{0}' of the property '{1}.{2}'.", GetTypeFullName (property.PropertyType), property.DeclaringType.Type.FullName, property.Name)); } sb.Write (" ").Write (property.Selector); sb.WriteLine (";"); } catch (Exception ex) { exceptions.Add (ex); } } } if (@class.Methods != null) { foreach (var method in @class.Methods) { try { if (is_protocol) sb.Write (method.IsOptional ? "@optional " : "@required "); sb.WriteLine ("{0};", GetObjCSignature (method, exceptions)); } catch (ProductException ex) { skip.Add (method); exceptions.Add (ex); } catch (Exception ex) { skip.Add (method); exceptions.Add (ErrorHelper.CreateError (4114, ex, "Unexpected error in the registrar for the method '{0}.{1}' - Please file a bug report at http://bugzilla.xamarin.com", method.DeclaringType.Type.FullName, method.Method.Name)); } } } sb.Unindent (); sb.WriteLine ("@end"); if (!is_protocol && [email protected]) { if (@class.IsCategory) { sb.WriteLine ("@implementation {0} ({1})", EncodeNonAsciiCharacters (@class.BaseType.ExportedName), @class.CategoryName); } else { sb.WriteLine ("@implementation {0} {{ }} ", class_name); } sb.Indent (); if (@class.Methods != null) { foreach (var method in @class.Methods) { if (skip.Contains (method)) continue; try { Specialize (sb, method, exceptions); } catch (Exception ex) { exceptions.Add (ex); } } } sb.Unindent (); sb.WriteLine ("@end"); } sb.WriteLine (); } map.AppendLine ("{ NULL, NULL, NULL },"); map.AppendLine ("};"); map.AppendLine (); map.AppendLine ("static const char *__xamarin_registration_assemblies []= {"); int count = 0; var registered_assemblies = new List<string> (); if (string.IsNullOrEmpty (single_assembly)) { foreach (var assembly in GetAssemblies ()) registered_assemblies.Add (GetAssemblyName (assembly)); } else { registered_assemblies.Add (single_assembly); } foreach (var assembly in registered_assemblies) { count++; if (count > 1) map.AppendLine (", "); map.Append ("\""); map.Append (assembly); map.Append ("\""); } map.AppendLine (); map.AppendLine ("};"); map.AppendLine (); map.AppendLine ("static struct MTRegistrationMap __xamarin_registration_map = {"); map.AppendLine ("NULL,"); map.AppendLine ("__xamarin_registration_assemblies,"); map.AppendLine ("__xamarin_class_map,"); map.AppendLine ("{0},", count); map.AppendLine ("{0},", i); map.AppendLine ("{0}", customTypeCount); map.AppendLine ("};"); map_init.AppendLine ("xamarin_add_registration_map (&__xamarin_registration_map);"); map_init.AppendLine ("}"); sb.WriteLine (map.ToString ()); sb.WriteLine (map_init.ToString ()); if (exceptions.Count > 0) throw new AggregateException (exceptions); }
string CheckStructure(TypeDefinition structure, string descriptiveMethodName, MemberReference inMember) { string n; StringBuilder name = new StringBuilder (); var body = new AutoIndentStringBuilder (1); int size = 0; ProcessStructure (name, body, structure, ref size, descriptiveMethodName, structure, inMember); n = "struct trampoline_struct_" + name.ToString (); if (!structures.Contains (n)) { structures.Add (n); declarations.WriteLine ("{0} {{\n{1}}};", n, body.ToString ()); } return n; }
public AutoIndentStringBuilder AppendLine(AutoIndentStringBuilder isb) { if (isb.Length > 0) { sb.Append (isb.ToString ()); AppendLine (); } return this; }
static void ProcessStructure(StringBuilder name, AutoIndentStringBuilder body, TypeDefinition structure, ref int size, string descriptiveMethodName, TypeDefinition root_structure, MemberReference inMember) { switch (structure.FullName) { case "System.Char": name.Append ('c'); body.AppendLine ("char v{0};", size); size += 1; break; case "System.Boolean": // map managed 'bool' to ObjC BOOL name.Append ('B'); body.AppendLine ("BOOL v{0};", size); size += 1; break; case "System.Byte": case "System.SByte": name.Append ('b'); body.AppendLine ("char v{0};", size); size += 1; break; case "System.UInt16": case "System.Int16": name.Append ('s'); body.AppendLine ("short v{0};", size); size += 2; break; case "System.UInt32": case "System.Int32": name.Append ('i'); body.AppendLine ("int v{0};", size); size += 4; break; case "System.Int64": case "System.UInt64": name.Append ('l'); body.AppendLine ("long long v{0};", size); size += 8; break; case "System.Single": name.Append ('f'); body.AppendLine ("float v{0};", size); size += 4; break; case "System.Double": name.Append ('d'); body.AppendLine ("double v{0};", size); size += 8; break; case "System.IntPtr": name.Append ('p'); body.AppendLine ("void *v{0};", size); size += 4; // for now at least... break; default: bool found = false; foreach (FieldDefinition field in structure.Fields) { if (field.IsStatic) continue; var fieldType = field.FieldType.Resolve (); if (fieldType == null) throw ErrorHelper.CreateError (4111, inMember, "The registrar cannot build a signature for type `{0}' in method `{1}`.", structure.FullName, descriptiveMethodName); if (!fieldType.IsValueType) throw ErrorHelper.CreateError (4161, inMember, "The registrar found an unsupported structure '{0}': All fields in a structure must also be structures (field '{1}' with type '{2}' is not a structure).", root_structure.FullName, field.Name, fieldType.FullName); found = true; ProcessStructure (name, body, fieldType, ref size, descriptiveMethodName, root_structure, inMember); } if (!found) throw ErrorHelper.CreateError (4111, inMember, "The registrar cannot build a signature for type `{0}' in method `{1}`.", structure.FullName, descriptiveMethodName); break; } }