Ejemplo n.º 1
0
			void VerifySelector (ObjCMethod method, ref List<Exception> exceptions)
			{
				if (method.Method == null)
					return;

				var split = method.Selector.Split (':');
				var nativeParamCount = split.Length - 1;

				if (method.IsVariadic)
					nativeParamCount++;

				var pars = method.Parameters;
				var paramCount = pars == null ? 0 : pars.Length;
				if (method.IsCategoryInstance)
					paramCount--;
				
				if (nativeParamCount != paramCount) {
					Exception ex;

					if (method.IsVariadic) {
						ex = Registrar.CreateException (4140, method, "The registrar found a signature mismatch in the method '{0}.{1}' - the selector '{4}' indicates the variadic method takes {2} parameters, while the managed method has {3} parameters.",
							method.Method.DeclaringType.FullName, method.MethodName, nativeParamCount, paramCount, method.Selector);
					} else {
						ex = Registrar.CreateException (4117, method, "The registrar found a signature mismatch in the method '{0}.{1}' - the selector '{4}' indicates the method takes {2} parameters, while the managed method has {3} parameters.",
							method.Method.DeclaringType.FullName, method.MethodName, nativeParamCount, paramCount, method.Selector);
					}

					Registrar.AddException (ref exceptions, ex);
				}

				if (method.IsVariadic && pars != null && Registrar.GetTypeFullName (pars [paramCount - 1]) != "System.IntPtr")
					Registrar.AddException (ref exceptions, Registrar.CreateException (4123, method, "The type of the variadic parameter in the variadic function '{0}' must be System.IntPtr.", Registrar.GetDescriptiveMethodName (method.Method)));
				
				char ch;
				var idx = method.Selector.IndexOfAny (invalidSelectorCharacters);
				if (idx != -1) {
					ch = method.Selector [idx];
					Registrar.AddException (ref exceptions, Registrar.CreateException (4160, method, "Invalid character '{0}' (0x{1}) found in selector '{2}' for '{3}.{4}'",
						ch, ((int) ch).ToString ("x"), method.Selector, Registrar.GetTypeFullName (Type), Registrar.GetDescriptiveMethodName (method.Method)));
				}
			}
Ejemplo n.º 2
0
			public bool Add (ObjCMethod method, ref List<Exception> exceptions)
			{
				bool rv;

				if (Methods == null)
					Methods = new List<ObjCMethod> ();

				VerifySelector (method, ref exceptions);
				method.ValidateSignature (ref exceptions);
				if (!method.IsPropertyAccessor)
					Registrar.VerifyInSdk (ref exceptions, method);

				rv = AddToMap (method, ref exceptions);
				Methods.Add (method);
				return rv;
			}
Ejemplo n.º 3
0
		// This method is not thread-safe wrt 'types', and must be called with
		// a lock held on 'types'.
		ObjCType RegisterTypeUnsafe (TType type, ref List<Exception> exceptions)
		{
			ObjCType objcType;
			bool isGenericType = false;
			bool isProtocol = false;
			bool isInformalProtocol = false;

			if (IsGenericType (type)) {
				type = GetGenericTypeDefinition (type);
				isGenericType = true;
			}

			if (types.TryGetValue (type, out objcType)) {
				OnReloadType (objcType);
				return objcType;
			}

			var categoryAttribute = GetCategoryAttribute (type);
			if (categoryAttribute != null)
				return RegisterCategory (type, categoryAttribute, ref exceptions);

			if (!IsNSObject (type)) {
				//Trace ("{0} is not derived from NSObject", GetTypeFullName (type));
				if (!IsInterface (type))
					return null;

				if (!HasProtocolAttribute (type))
					return null;

				if (isGenericType) {
					exceptions.Add (ErrorHelper.CreateError (4148, "The registrar found a generic protocol: '{0}'. Exporting generic protocols is not supported.", GetTypeFullName (type)));
					return null;
				}

				// This is a protocol
				var pAttr = GetProtocolAttribute (type);
				isInformalProtocol = pAttr.IsInformal;
				isProtocol = true;
			}

			// make sure the base type is already registered
			var baseType = GetBaseType (type);
			ObjCType baseObjCType = null;
			if (baseType != null) {
				Trace ("Registering base type {0} of {1}", GetTypeName (baseType), GetTypeName (type));
				baseObjCType = RegisterTypeUnsafe (baseType, ref exceptions);
			}

			var register_attribute = GetRegisterAttribute (type);
			if (register_attribute != null && register_attribute.SkipRegistration)
				return baseObjCType;

			objcType = new ObjCType () {
				Registrar = this,
				RegisterAttribute = GetRegisterAttribute (type),
				Type = type,
				IsModel = HasModelAttribute (type),
				IsProtocol = isProtocol,
				IsGeneric = isGenericType,
			};
			objcType.VerifyRegisterAttribute ();
			objcType.Protocols = GetProtocols (objcType, ref exceptions);
			objcType.BaseType = isProtocol ? null : (baseObjCType ?? objcType);
			objcType.IsWrapper = (isProtocol && !isInformalProtocol) ? (GetProtocolAttributeWrapperType (objcType.Type) != null) : (objcType.RegisterAttribute != null && objcType.RegisterAttribute.IsWrapper);

			if (!objcType.IsWrapper && objcType.BaseType != null)
				VerifyTypeInSDK (ref exceptions, objcType.BaseType.Type, baseTypeOf: objcType.Type);

			// make sure all the protocols this type implements are registered
			if (objcType.Protocols != null) {
				foreach (var p in objcType.Protocols) {
					Trace ("Registering implemented protocol {0} of {1}", p == null ? "null" : p.ProtocolName, GetTypeName (type));
					OnRegisterProtocol (p);
				}
			}

			TType previous_type;
			if (objcType.IsProtocol) {
				lock (protocol_map) {
					if (protocol_map.TryGetValue (objcType.ExportedName, out previous_type))
						throw ErrorHelper.CreateError (4126, "Cannot register two managed protocols ('{0}' and '{1}') with the same native name ('{2}').",
							GetAssemblyQualifiedName (type), GetAssemblyQualifiedName (previous_type), objcType.ExportedName);
					protocol_map.Add (objcType.ExportedName, type);
				}
			} else {
				lock (type_map) {
					if (type_map.TryGetValue (objcType.ExportedName, out previous_type))
						throw ErrorHelper.CreateError (4118, "Cannot register two managed types ('{0}' and '{1}') with the same native name ('{2}').",
							GetAssemblyQualifiedName (type), GetAssemblyQualifiedName (previous_type), objcType.ExportedName);
					type_map.Add (objcType.ExportedName, type);
				}
			}
		
			types.Add (type, objcType);
			
			Trace ("    [TYPE] Registering {0} => {1} IsWrapper: {2} BaseType: {3} IsModel: {4} IsProtocol: {5}", type.ToString ().Replace ('+', '/'), objcType.ExportedName, objcType.IsWrapper, objcType.BaseType == null ? "null" : objcType.BaseType.Name, objcType.IsModel, objcType.IsProtocol);

			// Special methods
			bool is_first_nonWrapper = false;
			var methods = new List<TMethod> (CollectMethods (type));
			if (!isProtocol) {
				is_first_nonWrapper = !(objcType.IsWrapper || objcType.IsModel) && (objcType.BaseType.IsWrapper || objcType.BaseType.IsModel);
				if (is_first_nonWrapper) {
					bool isCalayerSubclass = IsSubClassOf (objcType.Type, CoreAnimation, "CALayer");
					if (!isCalayerSubclass) {
						objcType.Add (new ObjCMethod (this, objcType, null) {
							Selector = "release",
							Trampoline = Trampoline.Release,
							Signature = "v@:",
							IsStatic = false,
						}, ref exceptions);

						objcType.Add (new ObjCMethod (this, objcType, null) {
							Selector = "retain",
							Trampoline = Trampoline.Retain,
							Signature = "@@:",
							IsStatic = false,
						}, ref exceptions);
					}

					objcType.Add (new ObjCMethod (this, objcType, null) {
						Selector = "xamarinGetGCHandle",
						Trampoline = Trampoline.GetGCHandle,
						Signature = "i@:",
						IsStatic = false,
					}, ref exceptions);

					objcType.Add (new ObjCMethod (this, objcType, null) {
						Selector = "xamarinSetGCHandle:",
						Trampoline = Trampoline.SetGCHandle,
						Signature = "v@:i",
						IsStatic = false,
					}, ref exceptions);
				}

				// Find conform_to_protocol
				if (conforms_to_protocol == null && Is (type, Foundation, "NSObject")) {
					foreach (var method in methods) {
						switch (GetMethodName (method)) {
						case "InvokeConformsToProtocol":
							invoke_conforms_to_protocol = method;
							break;
						case "ConformsToProtocol":
							conforms_to_protocol = method;
							break;
						}

						if (invoke_conforms_to_protocol != null && conforms_to_protocol != null)
							break;
					}
				}

#if MMP || MTOUCH
				// Special fields
				if (is_first_nonWrapper) {
					// static registrar
						objcType.Add (new ObjCField () {
							DeclaringType = objcType,
							FieldType = "XamarinObject",// "^v", // void*
							Name = "__monoObjectGCHandle",
						}, ref exceptions);
					}
#endif
			}

			var properties = new List<TProperty> (CollectProperties (type));
			var hasProtocolMemberAttributes = false;
			if (isProtocol && !isInformalProtocol) {
				var attribs = GetProtocolMemberAttributes (type);
				foreach (var attrib in attribs) {
					hasProtocolMemberAttributes = true;
					if (attrib.IsProperty) {
						if (attrib.IsStatic) {
							// There is no such things as a static property in ObjC, so export this as just the getter[+setter].
							var objcGetter = new ObjCMethod (this, objcType, null) {
								Name = attrib.Name,
								Selector = attrib.GetterSelector,
								Parameters = new TType[] { },
								ReturnType = attrib.PropertyType,
								IsStatic = attrib.IsStatic,
								IsOptional = !attrib.IsRequired,
								IsConstructor = false,
							};

							objcType.Add (objcGetter, ref exceptions);

							if (!string.IsNullOrEmpty (attrib.SetterSelector)) {
								var objcSetter = new ObjCMethod (this, objcType, null) {
									Name = attrib.Name,
									Selector = attrib.SetterSelector,
									Parameters = new TType[] { attrib.PropertyType },
									ReturnType = GetSystemVoidType (),
									IsStatic = attrib.IsStatic,
									IsOptional = !attrib.IsRequired,
									IsConstructor = false,
								};
								objcType.Add (objcSetter, ref exceptions);
							}
						} else {
							var objcProperty = new ObjCProperty () {
								Registrar = this,
								DeclaringType = objcType,
								Property = null,
								Name = attrib.Name,
								Selector = attrib.Selector,
								ArgumentSemantic = attrib.ArgumentSemantic,
								IsReadOnly = string.IsNullOrEmpty (attrib.SetterSelector),
								IsStatic = attrib.IsStatic,
								IsOptional = !attrib.IsRequired,
								GetterSelector = attrib.GetterSelector,
								SetterSelector = attrib.SetterSelector,
								PropertyType = attrib.PropertyType,
							};
							objcType.Add (objcProperty, ref exceptions);
						}
					} else {
						var objcMethod = new ObjCMethod (this, objcType, null) {
							Name = attrib.Name,
							Selector = attrib.Selector,
							ArgumentSemantic = attrib.ArgumentSemantic,
							IsVariadic = attrib.IsVariadic,
							ReturnType = attrib.ReturnType ?? GetSystemVoidType (),
							IsStatic = attrib.IsStatic,
							IsOptional = !attrib.IsRequired,
							IsConstructor = false,
						};

						if (attrib.ParameterType != null) {
							var parameters = new TType [attrib.ParameterType.Length];
							for (int i = 0; i < parameters.Length; i++) {
								if (attrib.ParameterByRef [i]) {
									parameters [i] = MakeByRef (attrib.ParameterType [i]);
								} else {
									parameters [i] = attrib.ParameterType [i];
								}
							}
							objcMethod.Parameters = parameters;
						} else {
							objcMethod.Parameters = new TType[] { };
						}

						objcType.Add (objcMethod, ref exceptions);
					}
				}
			}

			foreach (TProperty property in properties) {
				if (hasProtocolMemberAttributes)
					continue;
				
				if (!isProtocol) {
					var ca = GetConnectAttribute (property);
					if (ca != null) {
						if (!IsINativeObject (GetPropertyType (property))) {
							AddException (ref exceptions, CreateException (4139, property,
								"The registrar cannot marshal the property type '{0}' of the property '{1}.{2}'. Properties with the [Connect] attribute must have a property type of NSObject (or a subclass of NSObject).",
								GetTypeFullName (GetPropertyType (property)), GetTypeFullName (type), GetPropertyName (property)));
							continue;
						}

						objcType.Add (new ObjCField () {
							DeclaringType = objcType,
							Name = ca.Name ?? GetPropertyName (property),
#if !MTOUCH && !MMP
							Size = Is64Bits ? 8 : 4,
							Alignment = (byte) (Is64Bits ? 3 : 2),
#endif
							FieldType = "@",
							IsProperty = true,
						}, ref exceptions);
					}
				}

				var ea = GetExportAttribute (property);

				if (ea == null)
					continue;

				if (IsStatic (property) && (objcType.IsWrapper || objcType.IsModel)) {
					// This is useless to export, since the user can't actually do anything with it,
					// it'll just call back into the base implementation.
					continue;
				}

				if (IsStatic (property) && isGenericType) {
					AddException (ref exceptions, CreateException (4131, property, "The registrar cannot export static properties in generic classes ('{0}.{1}').", GetTypeFullName (type), GetPropertyName (property)));
					continue;
				}

				TType property_type = null;
				if (isGenericType && !VerifyIsConstrainedToNSObject (GetPropertyType (property), out property_type)) {
					AddException (ref exceptions, CreateException (4132, property, "The registrar found an invalid generic return type '{0}' in the property '{1}.{2}'. The return type must have an 'NSObject' constraint.", GetTypeFullName (GetPropertyType (property)), GetTypeFullName (type), GetPropertyName (property)));
					continue;
				}
				if (property_type == null)
					property_type = GetPropertyType (property);

				Trace ("        [PROPERTY] {0} => {1}", property, ea.Selector);

				var objcProperty = new ObjCProperty ()
				{
					Registrar = this,
					DeclaringType = objcType,
					Property = property,
					Name = property.Name,
					Selector = ea.Selector ?? GetPropertyName (property),
					ArgumentSemantic = ea.ArgumentSemantic,
					PropertyType = property_type,
				};

				TMethod getter = GetGetMethod (property);
				TMethod setter = GetSetMethod (property);

				if (getter != null && VerifyNonGenericMethod (ref exceptions, type, getter)) {
					var method = new ObjCMethod (this, objcType, getter) {
						Selector = ea.Selector ?? GetPropertyName (property),
						ArgumentSemantic = ea.ArgumentSemantic,
						ReturnType = property_type,
					};

					List<Exception> excs = null;
					if (!method.ValidateSignature (ref excs)) {
						exceptions.Add (CreateException (4138, excs [0], property, "The registrar cannot marshal the property type '{0}' of the property '{1}.{2}'.",
							GetTypeFullName (property.PropertyType), property.DeclaringType.FullName, property.Name));
						continue;
					}

					if (!objcType.Add (method, ref exceptions))
						continue;

					Trace ("            [GET] {0}", objcType.Methods [objcType.Methods.Count - 1].Name);
				}

				if (setter != null && VerifyNonGenericMethod (ref exceptions, type, setter)) {
					string setterName = ea.Selector ?? GetPropertyName (property);

					var method = new ObjCMethod (this, objcType, setter) {
						Selector = CreateSetterSelector (setterName),
						ArgumentSemantic = ea.ArgumentSemantic,
						Parameters = new TType[] { property_type },
					};

					List<Exception> excs = null;
					if (!method.ValidateSignature (ref excs)) {
						exceptions.Add (CreateException (4138, excs [0], property, "The registrar cannot marshal the property type '{0}' of the property '{1}.{2}'.",
							GetTypeFullName (property.PropertyType), property.DeclaringType.FullName, property.Name));
						continue;
					}

					if (!objcType.Add (method, ref exceptions))
						continue;

					Trace ("            [SET] {0}", objcType.Methods [objcType.Methods.Count - 1].Name);
				}

				objcType.Add (objcProperty, ref exceptions);
			}

			var custom_conforms_to_protocol = !is_first_nonWrapper; // we only have to generate the conformsToProtocol method for the first non-wrapper type.

#if MONOMAC
			ObjCMethod custom_copy_with_zone = null;
			var isNSCellSubclass = IsSubClassOf (type, AppKit, "NSCell");
#endif
			Dictionary<TMethod, List<TMethod>> method_map = null;

			if (!isProtocol)
				method_map = PrepareMethodMapping (type);

			foreach (TMethod method in methods) {
				if (hasProtocolMemberAttributes)
					continue;
				
				var ea = GetExportAttribute (method);

				if (ea == null) {
					List<TMethod> impls;
					if (method_map != null && method_map.TryGetValue (method, out impls)) {
						if (impls.Count != 1) {
							AddException (ref exceptions, Shared.GetMT4127 (method, impls));
							continue;
						}

						ea = GetExportAttribute (impls [0]);
					}
				}

				if (ea == null)
					continue;

				if (IsStatic (method) && (objcType.IsWrapper || objcType.IsModel) && !(objcType.IsProtocol && !objcType.IsFakeProtocol)) {
					// This is useless to export, since the user can't actually do anything with it,
					// it'll just call back into the base implementation.
					continue;
				}

				if (objcType.IsModel && IsVirtual (method))
					continue;

				Trace ("        [METHOD] {0} => {1}", method, ea.Selector);

				if (!custom_conforms_to_protocol && method.DeclaringType == type && GetBaseMethod (method) == conforms_to_protocol)
					custom_conforms_to_protocol = true;

				if (!VerifyNonGenericMethod (ref exceptions, type, method))
					continue;

				var objcMethod = new ObjCMethod (this, objcType, method);
				if (!objcMethod.SetExportAttribute (ea, ref exceptions))
					continue;

#if MONOMAC
				if (objcMethod.Selector == "copyWithZone:")
					custom_copy_with_zone = objcMethod;
#endif

				if (IsStatic (method) && isGenericType) {
					AddException (ref exceptions, CreateException (4130, method, "The registrar cannot export static methods in generic classes ('{0}').", GetDescriptiveMethodName (type, method)));
					continue;
				} else if (isGenericType && !VerifyIsConstrainedToNSObject (ref exceptions, type, objcMethod)) {
					continue;
				}

				try {
					objcType.Add (objcMethod, ref exceptions);
				} catch (Exception ex) {
					AddException (ref exceptions, ex);
				}
			}

			if (!isProtocol && !custom_conforms_to_protocol) {
				objcType.Add (new ObjCMethod (this, objcType, invoke_conforms_to_protocol) {
					Selector = "conformsToProtocol:",
					Trampoline = Trampoline.Normal,
					Signature = "B@:^v",
					IsStatic = false,
				}, ref exceptions);
			}

#if MONOMAC
			if (isNSCellSubclass) {
				if (custom_copy_with_zone != null) {
					custom_copy_with_zone.Trampoline = Trampoline.CopyWithZone2;
				} else {
					objcType.Add (new ObjCMethod (this, objcType, null) {
						Selector = "copyWithZone:",
						Trampoline = Trampoline.CopyWithZone1,
						Signature = "@@:^v",
						IsStatic = false,
					}, ref exceptions);
				}
			}
#endif

			foreach (TMethod ctor in CollectConstructors (type)) {
				if (IsStatic (ctor))
					continue;

				var parameters = GetParameters (ctor);
				if (parameters == null || parameters.Length == 0) {
					Trace ("        [CTOR] {0} default => init", GetTypeName (type));

					objcType.Add (new ObjCMethod (this, objcType, ctor)
					{
						Selector = "init",
						Trampoline = Trampoline.Constructor,
					}, ref exceptions);
					continue;
				}

				var ea = GetExportAttribute (ctor);

				if (ea == null)
					continue;

				Trace ("        [CTOR] {2} {0} => {1}", GetMethodName (ctor), ea.Selector, GetTypeName (type));
				
				if (!VerifyNonGenericMethod (ref exceptions, type, ctor))
					continue;

				var method = new ObjCMethod (this, objcType, ctor) {
					Trampoline = Trampoline.Constructor,
				};
				if (method.SetExportAttribute (ea, ref exceptions))
					objcType.Add (method, ref exceptions);
			}

			if (objcType.IsProtocol) {
				OnRegisterProtocol (objcType);
			} else {
				OnRegisterType (objcType);
			}

			return objcType;
		}
Ejemplo n.º 4
0
		ObjCType RegisterCategory (TType type, CategoryAttribute attrib, ref List<Exception> exceptions)
		{
			if (IsINativeObject (type)) {
				AddException (ref exceptions, ErrorHelper.CreateError (4152, "Cannot register the type '{0}' as a category because it implements INativeObject or subclasses NSObject.", GetTypeFullName (type)));
				return null;
			}

			if (IsGenericType (type)) {
				AddException (ref exceptions, ErrorHelper.CreateError (4153, "Cannot register the type '{0}' as a category because it's generic.", GetTypeFullName (type)));
				return null;
			}

			if (attrib.Type == null) {
				AddException (ref exceptions, ErrorHelper.CreateError (4151, "Cannot register the type '{0}' because the Type property in its Category attribute isn't set.", GetTypeFullName (type)));
				return null;
			}

			var declaringType = RegisterType (attrib.Type, ref exceptions);
			if (declaringType == null) {
				AddException (ref exceptions, ErrorHelper.CreateError (4150, "Cannot register the type '{0}' because the category type '{1}' in its Category attribute does not inherit from NSObject.", GetTypeFullName (type), GetTypeFullName (attrib.Type)));
				return null;
			}

			var objcType = new ObjCType () {
				Registrar = this,
				Type = type,
				BaseType = declaringType,
				CategoryAttribute = attrib,
			};

			lock (categories_map) {
				TType previous_type;
				if (categories_map.TryGetValue (objcType.CategoryName, out previous_type)) {
					AddException (ref exceptions, ErrorHelper.CreateError (4156, "Cannot register two categories ('{0}' and '{1}') with the same native name ('{2}')",
						GetAssemblyQualifiedName (type), GetAssemblyQualifiedName (previous_type), objcType.CategoryName));
					return null;
				}
				categories_map.Add (objcType.CategoryName, type);
			}

			types.Add (type, objcType);

			Trace ("    [CATEGORY] Registering {0} on {1}", type.ToString ().Replace ('+', '/'), attrib.Type.FullName);

			foreach (var ctor in CollectConstructors (type)) {
				var ea = GetExportAttribute (ctor);
				if (ea == null)
					continue;

				AddException (ref exceptions, CreateException (4158, ctor, "Cannot register the constructor {0}.{1} in the category {0} because constructors in categories are not supported.", GetTypeFullName (type), GetDescriptiveMethodName (ctor)));
			}

			foreach (var method in CollectMethods (type)) {
				var ea = GetExportAttribute (method);

				if (ea == null)
					continue;
					
				if (!IsStatic (method)) {
					AddException (ref exceptions, CreateException (4159, method, "Cannot register the method '{0}.{1}' as a category method because category methods must be static.", GetTypeFullName (type), GetMethodName (method)));
					return null;
				}

				if (HasThisAttribute (method)) {
					var parameters = GetParameters (method);
					if (parameters == null || parameters.Length == 0) {
						AddException (ref exceptions, CreateException (4157, method, "Cannot register the category method '{0}.{1}' because at least one parameter is required for extension methods (and its type must match the category type '{2}').",
							GetTypeFullName (type), GetMethodName (method), GetTypeFullName (declaringType.Type)));
						continue;
					} else if (GetTypeFullName (parameters [0]) != GetTypeFullName (declaringType.Type)) {
						AddException (ref exceptions, CreateException (4149, method, "Cannot register the extension method '{0}.{1}' because the type of the first parameter ('{2}') does not match the category type ('{3}').",
							GetTypeFullName (type), GetMethodName (method), GetTypeFullName (parameters [0]), GetTypeFullName (declaringType.Type)));
						continue;
					}
				}

				if (IsGenericMethod (method)) {
					AddException (ref exceptions, CreateException (4154, method, "Cannot register the method '{0}.{1}' as a category method because it's generic.", GetTypeFullName (type), GetMethodName (method)));
					continue;
				}

				Trace ("        [METHOD] {0} => {1}", method, ea.Selector);

				var category_method = new ObjCMethod (this, declaringType, method)
				{
					CategoryType = objcType,
				};
				if (category_method.SetExportAttribute (ea, ref exceptions)) {
					objcType.Add (category_method, ref exceptions);
					declaringType.Add (category_method, ref exceptions);
				}
			}

			// TODO: properties

			OnRegisterCategory (objcType, ref exceptions);

			return objcType;
		}
Ejemplo n.º 5
0
		bool VerifyIsConstrainedToNSObject (ref List<Exception> exceptions, TType type, ObjCMethod method)
		{
			TType constrained_type = null;

			if (!VerifyIsConstrainedToNSObject (method.ReturnType, out constrained_type)) {
				AddException (ref exceptions, CreateException (4129, method.Method, "The registrar found an invalid generic return type '{0}' in the method '{1}'. The generic return type must have an 'NSObject' constraint.", GetTypeFullName (method.ReturnType), GetDescriptiveMethodName (type, method.Method)));
				return false;
			}
			if (constrained_type != null)
				method.ReturnType = constrained_type;

			var pars = method.Parameters;
			if (pars == null)
				return true;

			List<TType> types = null;
			for (int i = 0; i < pars.Length; i++) {
				var p = pars [i];
				if (!VerifyIsConstrainedToNSObject (p, out constrained_type)) {
					AddException (ref exceptions, CreateException (4128, method.Method, "The registrar found an invalid generic parameter type '{0}' in the parameter {2} of the method '{1}'. The generic parameter must have an 'NSObject' constraint.", GetTypeFullName (p), GetDescriptiveMethodName (type, method.Method), GetParameterName (method.Method, i)));
					return false;
				}
				if (constrained_type != null) {
					if (types == null) {
						types = new List<TType> ();
						for (int j = 0; j < i; j++)
							types.Add (pars [j]);
					}
					types.Add (constrained_type);
				} else if (types != null) {
					types.Add (p);
				}
			}
			if (types != null)
				method.Parameters = types.ToArray ();

			return true;
		}
Ejemplo n.º 6
0
		void VerifyTypeInSDK (ref List<Exception> exceptions, TType type, ObjCMethod parameterIn = null, ObjCMethod returnTypeOf = null, ObjCProperty propertyTypeOf = null, TType baseTypeOf = null)
		{
			var attribs = GetAvailabilityAttributes (type);
			if (attribs == null || attribs.Count == 0)
				return;

			Version sdk = GetSDKVersion ();
			foreach (var attrib in attribs) {
				// The attributes are already filtered to the current platform.
				switch (attrib.AvailabilityKind) {
				case AvailabilityKind.Introduced:
					if (attrib.Version <= sdk)
						break;

					string msg = "The type '{0}' (used as {1} {2}) is not available in {3} {4} (it was introduced in {3} {5}){6} Please build with a newer {3} SDK (usually done by using the most recent version of Xcode).";
					string zero = GetTypeFullName (type);
					string one = string.Empty;
					string two = string.Empty;
					string three = PlatformName;
					string four = sdk.ToString ();
					string five = attrib.Version.ToString ();
					string six = string.IsNullOrEmpty (attrib.Message) ? "." : ": '" + attrib.Message + "'.";
					if (baseTypeOf != null) {
						one = "a base type of";
						two = GetTypeFullName (baseTypeOf);
					} else if (parameterIn != null) {
						one = "a parameter in";
						two = parameterIn.DescriptiveMethodName;
					} else if (returnTypeOf != null) {
						one = "a return type in";
						two = returnTypeOf.DescriptiveMethodName;
					} else if (propertyTypeOf != null) {
						one = "the property type of";
						two = propertyTypeOf.FullName;
					} else {
						msg = "The type '{0}' is not available in {3} {4} (it was introduced in {3} {5}){6} Please build with a newer {3} SDK (usually done by using the most recent version of Xcode).";
					}

					msg = string.Format (msg, zero, one, two, three, four, five, six);

					Exception ex;

					if (baseTypeOf != null) {
						ex = CreateException (4162, baseTypeOf, msg);
					} else if (parameterIn != null) {
						ex = CreateException (4162, parameterIn, msg);
					} else if (returnTypeOf != null) {
						ex = CreateException (4162, returnTypeOf, msg);
					} else if (propertyTypeOf != null) {
						ex = CreateException (4162, propertyTypeOf, msg);
					} else {
						ex = CreateException (4162, msg);
					}

					AddException (ref exceptions, ex);

					break;
				}
			}
		}
Ejemplo n.º 7
0
		void VerifyInSdk (ref List<Exception> exceptions, ObjCMethod method)
		{
			if (method.HasReturnType || (method.Method != null && !method.IsConstructor && method.ReturnType != null))
				VerifyTypeInSDK (ref exceptions, method.ReturnType, returnTypeOf: method);

			if (method.HasParameters || (method.Method != null && method.Parameters != null)) {
				foreach (var p in method.Parameters)
					VerifyTypeInSDK (ref exceptions, p, parameterIn: method);
			}
		}