From 00cfda5bcb36205c6f62cc7ee67fc2964c5205b3 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Wed, 28 Jan 2026 17:55:17 +0100 Subject: [PATCH 1/6] [mtouch/dotnet-linker] Enable nullability for the static registrar. --- src/ObjCRuntime/Registrar.cs | 2 + tools/common/Application.cs | 6 +- tools/common/DerivedLinkContext.cs | 7 +- tools/common/StaticRegistrar.cs | 540 ++++++++++-------- tools/common/Target.cs | 9 +- tools/dotnet-linker/Compat.cs | 7 +- tools/dotnet-linker/LinkerConfiguration.cs | 3 +- .../Steps/ManagedRegistrarStep.cs | 16 +- tools/linker/MobileExtensions.cs | 6 +- tools/mtouch/LinkerConfiguration.cs | 4 + tools/mtouch/mtouch.cs | 4 +- tools/mtouch/mtouch.csproj | 1 + 12 files changed, 337 insertions(+), 268 deletions(-) create mode 100644 tools/mtouch/LinkerConfiguration.cs diff --git a/src/ObjCRuntime/Registrar.cs b/src/ObjCRuntime/Registrar.cs index 6aa9743f3a67..197167c6e806 100644 --- a/src/ObjCRuntime/Registrar.cs +++ b/src/ObjCRuntime/Registrar.cs @@ -90,7 +90,9 @@ public static List GetMT4127 (TMethod impl, List ifac abstract partial class Registrar { #if LEGACY_TOOLS || BUNDLER +#nullable enable public Application App { get; protected set; } +#nullable disable #endif const string NFloatTypeName = "System.Runtime.InteropServices.NFloat"; diff --git a/tools/common/Application.cs b/tools/common/Application.cs index bc0f3895d4f3..290c124138ea 100644 --- a/tools/common/Application.cs +++ b/tools/common/Application.cs @@ -261,8 +261,12 @@ public Version GetMacCatalystiOSVersion (Version macOSVersion) return value; } - public Application () + public Application (LinkerConfiguration configuration) { +#if !LEGACY_TOOLS + this.configuration = configuration; + this.LinkContext = new Tuner.DerivedLinkContext (configuration, this); +#endif this.StaticRegistrar = new StaticRegistrar (this); } diff --git a/tools/common/DerivedLinkContext.cs b/tools/common/DerivedLinkContext.cs index 5f297047acfd..35a39f09f125 100644 --- a/tools/common/DerivedLinkContext.cs +++ b/tools/common/DerivedLinkContext.cs @@ -8,6 +8,7 @@ using Registrar; using Mono.Tuner; using Xamarin.Bundler; +using Xamarin.Linker; #if !LEGACY_TOOLS using LinkContext = Xamarin.Bundler.DotNetLinkContext; @@ -19,8 +20,8 @@ namespace Xamarin.Tuner { public class DerivedLinkContext : LinkContext { #if !LEGACY_TOOLS internal StaticRegistrar StaticRegistrar => App.StaticRegistrar; - internal Application App; #endif + internal Application App; Symbols? required_symbols; // Any errors or warnings during the link process that won't prevent linking from continuing can be stored here. @@ -47,13 +48,13 @@ public class DerivedLinkContext : LinkContext { // so we need a second dictionary Dictionary LinkedAwayTypeMap = new Dictionary (); + public DerivedLinkContext (LinkerConfiguration configuration, Application app) #if !LEGACY_TOOLS - public DerivedLinkContext (Xamarin.Linker.LinkerConfiguration configuration, Application app) : base (configuration) +#endif { this.App = app; } -#endif AssemblyDefinition? corlib; public AssemblyDefinition Corlib { diff --git a/tools/common/StaticRegistrar.cs b/tools/common/StaticRegistrar.cs index 4119d28cd7cf..aa1c152f96ab 100644 --- a/tools/common/StaticRegistrar.cs +++ b/tools/common/StaticRegistrar.cs @@ -33,12 +33,7 @@ using Mono.Tuner; using ClassRedirector; -// Disable warnings about nullability attributes in code until we've reviewed this file for nullability (and enabled it). -// This way we can add nullability attributes to new code in this file without getting warnings about these attributes. -#pragma warning disable 8632 // warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. - -// Disable until we get around to enable + fix any issues. -#nullable disable +#nullable enable namespace Registrar { /* @@ -221,7 +216,7 @@ class StaticRegistrar : Registrar { const string NFloatTypeName = "System.Runtime.InteropServices.NFloat"; const uint INVALID_TOKEN_REF = 0xFFFFFFFF; - Dictionary protocol_member_method_map; + Dictionary? protocol_member_method_map; public Dictionary ProtocolMemberMethodMap { get { @@ -236,11 +231,11 @@ public static bool IsPlatformType (TypeReference type, string @namespace, string return type.Is (@namespace, name); } - public static bool ParametersMatch (IList a, TypeReference [] b) + public static bool ParametersMatch (IList? a, TypeReference []? b) { if (a is null && b is null) return true; - if (a is null ^ b is null) + if (a is null || b is null) return false; if (a.Count != b.Length) @@ -290,8 +285,14 @@ public static bool TypeMatch (GenericInstanceType a, GenericInstanceType b) return true; } - public static bool TypeMatch (TypeReference a, TypeReference b) + public static bool TypeMatch (TypeReference? a, TypeReference? b) { + if (a is null && b is null) + return true; + + if (a is null || b is null) + return false; + if (a is GenericParameter) return true; @@ -335,7 +336,7 @@ public static bool MethodMatch (MethodDefinition candidate, MethodDefinition met return true; } - void CollectInterfaces (ref List ifaces, TypeDefinition type) + void CollectInterfaces ([NotNullIfNotNull (nameof (ifaces))] ref List? ifaces, TypeDefinition? type) { if (type is null) return; @@ -363,12 +364,12 @@ void CollectInterfaces (ref List ifaces, TypeDefinition type) } } - public Dictionary> PrepareInterfaceMethodMapping (TypeReference type) + public Dictionary>? PrepareInterfaceMethodMapping (TypeReference type) { TypeDefinition td = type.Resolve (); - List ifaces = null; + List? ifaces = null; List iface_methods; - Dictionary> rv = null; + Dictionary>? rv = null; CollectInterfaces (ref ifaces, td); @@ -406,7 +407,7 @@ public Dictionary> PrepareInterfaceMeth } else { iface_methods.Remove (ifaceMethodDef); - List list; + List? list; if (rv is null) { rv = new Dictionary> (); rv [impl] = list = new List (); @@ -427,7 +428,7 @@ public Dictionary> PrepareInterfaceMeth if (!MethodMatch (impl, ifaceMethod)) continue; - List list; + List? list; if (rv is null) { rv = new Dictionary> (); rv [impl] = list = new List (); @@ -447,11 +448,14 @@ public static TypeReference GetEnumUnderlyingType (TypeDefinition type) if (field.IsSpecialName && field.Name == "value__") return field.FieldType; - return null; + throw new InvalidOperationException ($"The type {type.FullName} is not an enum."); } - public string ToObjCType (TypeReference type) + public string ToObjCType (TypeReference? type) { + if (type is null) + throw ErrorHelper.CreateError (99, Errors.MX0099, "ToObjCType called with null value."); + var definition = type as TypeDefinition; if (definition is not null) return ToObjCType (definition); @@ -495,7 +499,7 @@ public string ToObjCType (TypeDefinition type, bool delegateToBlockType = false, if (!delegateToBlockType) return "id"; - MethodDefinition invokeMethod = type.Methods.SingleOrDefault (method => method.Name == "Invoke"); + var invokeMethod = type.Methods.SingleOrDefault (method => method.Name == "Invoke"); if (invokeMethod is null) return "id"; @@ -523,24 +527,24 @@ public string ToObjCType (TypeDefinition type, bool delegateToBlockType = false, throw ErrorHelper.CreateError (4108, Errors.MT4108, type.FullName); } - public static bool IsDelegate (TypeDefinition type) + public static bool IsDelegate (TypeDefinition? type) { while (type is not null) { if (type.FullName == "System.Delegate") return true; - type = type.BaseType is not null ? type.BaseType.Resolve () : null; + type = type.BaseType?.Resolve (); } return false; } - TypeDefinition ResolveType (TypeReference tr) + TypeDefinition? ResolveType (TypeReference tr) { return ResolveType (LinkContext, tr); } - public static TypeDefinition ResolveType (Xamarin.Tuner.DerivedLinkContext context, TypeReference tr) + public static TypeDefinition? ResolveType (Xamarin.Tuner.DerivedLinkContext? context, TypeReference tr) { // The static registrar might sometimes deal with types that have been linked away // It's not always possible to call .Resolve () on types that have been linked away, @@ -560,13 +564,16 @@ public static TypeDefinition ResolveType (Xamarin.Tuner.DerivedLinkContext conte } } - public bool IsNativeObject (TypeReference tr) + public bool IsNativeObject ([NotNullWhen (true)] TypeReference? tr) { return IsNativeObject (LinkContext, tr); } - public static bool IsNativeObject (Xamarin.Tuner.DerivedLinkContext context, TypeReference tr) + public static bool IsNativeObject (Xamarin.Tuner.DerivedLinkContext? context, TypeReference? tr) { + if (tr is null) + return false; + var gp = tr as GenericParameter; if (gp is not null) { if (gp.HasConstraints) { @@ -595,22 +602,28 @@ public static bool IsNativeObject (Xamarin.Tuner.DerivedLinkContext context, Typ public bool IsSingleAssembly { get { return !string.IsNullOrEmpty (single_assembly); } } - string single_assembly; + string? single_assembly; IEnumerable input_assemblies; - Dictionary availability_annotations; + Dictionary? availability_annotations; - PlatformResolver resolver; + PlatformResolver? resolver; PlatformResolver Resolver { get { return resolver ?? App.Resolver; } } - readonly Version MacOSTenTwelveVersion = new Version (10, 12); - +#if LEGACY_TOOLS + public Xamarin.Tuner.DerivedLinkContext? LinkContext { +#else public Xamarin.Tuner.DerivedLinkContext LinkContext { +#endif get { +#if LEGACY_TOOLS return App?.GetLinkContext (); +#else + return App.LinkContext; +#endif } } - Dictionary AvailabilityAnnotations { + Dictionary? AvailabilityAnnotations { get { if (availability_annotations is null) availability_annotations = LinkContext?.GetAllCustomAttributes ("Availability"); @@ -623,9 +636,7 @@ IEnumerable GetCustomAttributes (ICustomAttributeProvider prov { #if !LEGACY_TOOLS var dict = LinkContext?.Annotations?.GetCustomAnnotations (name); - object annotations = null; - - if (dict?.TryGetValue (provider, out annotations) == true) { + if (dict?.TryGetValue (provider, out var annotations) == true) { var attributes = (IEnumerable) annotations; foreach (var attrib in attributes) { if (IsAttributeMatch (attrib, @namespace, name, inherits)) @@ -642,7 +653,7 @@ IEnumerable GetCustomAttributes (ICustomAttributeProvider prov } } - public bool TryGetAttribute (ICustomAttributeProvider provider, string @namespace, string attributeName, out ICustomAttribute attribute) + public bool TryGetAttribute (ICustomAttributeProvider provider, string @namespace, string attributeName, [NotNullWhen (true)] out ICustomAttribute? attribute) { attribute = null; @@ -666,18 +677,14 @@ bool IsAttributeMatch (ICustomAttribute attribute, string @namespace, string nam return attribute.AttributeType.Is (@namespace, name); } - void Init (Application app) + public StaticRegistrar (Application app) { this.App = app; + this.input_assemblies = []; trace = !LaxMode && (app.RegistrarOptions & RegistrarOptions.Trace) == RegistrarOptions.Trace; } - public StaticRegistrar (Application app) - { - Init (app); - } - - protected override PropertyDefinition FindProperty (TypeReference type, string name) + protected override PropertyDefinition? FindProperty (TypeReference type, string name) { var td = type.Resolve (); if (td?.HasProperties != true) @@ -691,13 +698,13 @@ protected override PropertyDefinition FindProperty (TypeReference type, string n return null; } - protected override IEnumerable FindMethods (TypeReference type, string name) + protected override IEnumerable? FindMethods (TypeReference type, string name) { var td = type.Resolve (); if (td?.HasMethods != true) return null; - List list = null; + List? list = null; foreach (var method in td.Methods) { if (method.Name != name) continue; @@ -985,7 +992,7 @@ protected override TypeReference GetReturnType (MethodDefinition method) return method.ReturnType; } - TypeReference system_void; + TypeReference? system_void; protected override TypeReference GetSystemVoidType () { if (system_void is not null) @@ -993,7 +1000,7 @@ protected override TypeReference GetSystemVoidType () // find corlib var corlib_name = Driver.CorlibName; - AssemblyDefinition corlib = null; + AssemblyDefinition? corlib = null; var candidates = new List (); foreach (var assembly in input_assemblies) { @@ -1118,7 +1125,7 @@ protected override bool IsPointer (TypeReference type) return type is PointerType; } - protected override TypeReference [] GetInterfaces (TypeReference type) + protected override TypeReference []? GetInterfaces (TypeReference type) { var td = type.Resolve (); if (!td.HasInterfaces || td.Interfaces.Count == 0) @@ -1129,7 +1136,7 @@ protected override TypeReference [] GetInterfaces (TypeReference type) return rv; } - protected override TypeReference [] GetLinkedAwayInterfaces (TypeReference type) + protected override TypeReference []? GetLinkedAwayInterfaces (TypeReference type) { if (LinkContext is null) return null; @@ -1151,7 +1158,7 @@ protected override TypeReference GetGenericTypeDefinition (TypeReference type) return type; } - protected override bool AreEqual (TypeReference a, TypeReference b) + protected override bool AreEqual (TypeReference? a, TypeReference? b) { if (a == b) return true; @@ -1162,7 +1169,7 @@ protected override bool AreEqual (TypeReference a, TypeReference b) return TypeMatch (a, b); } - public override bool VerifyIsConstrainedToNSObject (TypeReference type, out TypeReference constrained_type) + public override bool VerifyIsConstrainedToNSObject (TypeReference type, out TypeReference? constrained_type) { constrained_type = null; @@ -1185,8 +1192,7 @@ public override bool VerifyIsConstrainedToNSObject (TypeReference type, out Type if (git.HasGenericArguments) { var newGit = new GenericInstanceType (git.ElementType); for (int i = 0; i < git.GenericArguments.Count; i++) { - TypeReference constr; - rv &= VerifyIsConstrainedToNSObject (git.GenericArguments [i], out constr); + rv &= VerifyIsConstrainedToNSObject (git.GenericArguments [i], out var constr); newGit.GenericArguments.Add (constr ?? git.GenericArguments [i]); } constrained_type = newGit; @@ -1229,7 +1235,7 @@ protected override bool IsINativeObject (TypeReference tr) return IsNativeObject (tr); } - protected override TypeReference GetBaseType (TypeReference tr) + protected override TypeReference? GetBaseType (TypeReference tr) { var gp = tr as GenericParameter; if (gp is not null) { @@ -1241,10 +1247,7 @@ protected override TypeReference GetBaseType (TypeReference tr) return null; } var type = ResolveType (tr); - if (type.BaseType is null) - return null; - - return type.BaseType.Resolve (); + return type?.BaseType?.Resolve (); } protected override MethodDefinition GetBaseMethod (MethodDefinition method) @@ -1252,13 +1255,27 @@ protected override MethodDefinition GetBaseMethod (MethodDefinition method) return GetBaseMethodInTypeHierarchy (method); } - protected override TypeReference GetEnumUnderlyingType (TypeReference tr) + protected override TypeReference? GetEnumUnderlyingType (TypeReference tr) { var type = tr.Resolve (); return GetEnumUnderlyingType (type); } - protected override TypeReference [] GetParameters (MethodDefinition method) + bool TryGetEnumUnderlyingType ([NotNullWhen (true)] TypeReference? tr, [NotNullWhen (true)] out TypeReference? underlyingType) + { + underlyingType = null; + + if (tr is null) + return false; + + if (!IsEnum (tr)) + return false; + + underlyingType = GetEnumUnderlyingType (tr); + return underlyingType is not null; + } + + protected override TypeReference []? GetParameters (MethodDefinition method) { if (!method.HasParameters || method.Parameters.Count == 0) return null; @@ -1292,16 +1309,16 @@ protected override void GetNamespaceAndName (TypeReference type, out string @nam @namespace = type.Namespace; } - protected override bool TryGetAttribute (TypeReference type, string attributeNamespace, string attributeType, out object attribute) + protected override bool TryGetAttribute (TypeReference type, string attributeNamespace, string attributeType, [NotNullWhen (true)] out object? attribute) { bool res = TryGetAttribute (type.Resolve (), attributeNamespace, attributeType, out var attrib); attribute = attrib; return res; } - public override RegisterAttribute GetRegisterAttribute (TypeReference type) + public override RegisterAttribute? GetRegisterAttribute (TypeReference type) { - RegisterAttribute rv = null; + RegisterAttribute? rv = null; if (!TryGetAttribute (type.Resolve (), Foundation, StringConstants.RegisterAttribute, out var attrib)) return null; @@ -1348,9 +1365,9 @@ public override RegisterAttribute GetRegisterAttribute (TypeReference type) return rv; } - public override CategoryAttribute GetCategoryAttribute (TypeReference type) + public override CategoryAttribute? GetCategoryAttribute (TypeReference type) { - string name = null; + string? name = null; if (!TryGetAttribute (type.Resolve (), ObjCRuntime, StringConstants.CategoryAttribute, out var attrib)) return null; @@ -1370,23 +1387,23 @@ public override CategoryAttribute GetCategoryAttribute (TypeReference type) switch (attrib.ConstructorArguments.Count) { case 1: var t1 = (TypeReference) attrib.ConstructorArguments [0].Value; - return new CategoryAttribute (t1 is not null ? t1.Resolve () : null) { Name = name }; + return new CategoryAttribute (t1?.Resolve ()) { Name = name }; default: throw ErrorHelper.CreateError (4124, Errors.MT4124, "CategoryAttribute", type.FullName); } } - public override ExportAttribute GetExportAttribute (MethodDefinition method) + public override ExportAttribute? GetExportAttribute (MethodDefinition method) { return CreateExportAttribute (GetBaseMethodInTypeHierarchy (method) ?? method); } - protected override ExportAttribute GetExportAttribute (PropertyDefinition property) + protected override ExportAttribute? GetExportAttribute (PropertyDefinition property) { return CreateExportAttribute (GetBasePropertyInTypeHierarchy (property) ?? property); } - public override ProtocolAttribute GetProtocolAttribute (TypeReference type) + public override ProtocolAttribute? GetProtocolAttribute (TypeReference type) { if (!TryGetAttribute (type.Resolve (), Foundation, StringConstants.ProtocolAttribute, out var attrib)) return null; @@ -1407,8 +1424,7 @@ public override ProtocolAttribute GetProtocolAttribute (TypeReference type) rv.IsInformal = (bool) prop.Argument.Value; break; case "FormalSince": - Version version; - if (!Version.TryParse ((string) prop.Argument.Value, out version)) + if (!Version.TryParse ((string) prop.Argument.Value, out var version)) throw ErrorHelper.CreateError (4147, Errors.MT4147, "ProtocolAttribute", type.FullName); rv.FormalSinceVersion = version; break; @@ -1425,40 +1441,32 @@ public override ProtocolAttribute GetProtocolAttribute (TypeReference type) return rv; } - public BlockProxyAttribute GetBlockProxyAttribute (ParameterDefinition parameter) + public BlockProxyAttribute? GetBlockProxyAttribute (ParameterDefinition parameter) { if (!TryGetAttribute (parameter, ObjCRuntime, "BlockProxyAttribute", out var attrib)) return null; - var rv = new BlockProxyAttribute (); - switch (attrib.ConstructorArguments.Count) { case 1: - rv.Type = ((TypeReference) attrib.ConstructorArguments [0].Value).Resolve (); - break; + var type = ((TypeReference) attrib.ConstructorArguments [0].Value).Resolve (); + return new BlockProxyAttribute (type); default: throw ErrorHelper.CreateError (4124, Errors.MT4124, "BlockProxyAttribute", ((MethodReference) parameter.Method)?.FullName); } - - return rv; } - public DelegateProxyAttribute GetDelegateProxyAttribute (MethodDefinition method) + public DelegateProxyAttribute? GetDelegateProxyAttribute (MethodDefinition method) { if (!TryGetAttribute (method.MethodReturnType, ObjCRuntime, "DelegateProxyAttribute", out var attrib)) return null; - var rv = new DelegateProxyAttribute (); - switch (attrib.ConstructorArguments.Count) { case 1: - rv.DelegateType = ((TypeReference) attrib.ConstructorArguments [0].Value).Resolve (); - break; + var delegateType = ((TypeReference) attrib.ConstructorArguments [0].Value).Resolve (); + return new DelegateProxyAttribute (delegateType); default: throw ErrorHelper.CreateError (4124, Errors.MT4124, "DelegateProxyAttribute", ((MethodReference) method)?.FullName); } - - return rv; } protected override string PlatformName { @@ -1467,12 +1475,12 @@ protected override string PlatformName { } } - ProtocolMemberAttribute GetProtocolMemberAttribute (TypeReference type, string selector, ObjCMethod obj_method, MethodDefinition method) + ProtocolMemberAttribute? GetProtocolMemberAttribute (TypeReference type, string selector, ObjCMethod obj_method, MethodDefinition method) { return GetProtocolMemberAttribute (type, selector, obj_method.IsPropertyAccessor, method); } - ProtocolMemberAttribute GetProtocolMemberAttribute (TypeReference type, string selector, bool isPropertyAccessor, MethodDefinition method) + ProtocolMemberAttribute? GetProtocolMemberAttribute (TypeReference type, string selector, bool isPropertyAccessor, MethodDefinition method) { var memberAttributes = GetProtocolMemberAttributes (type); foreach (var attrib in memberAttributes) { @@ -1492,8 +1500,8 @@ ProtocolMemberAttribute GetProtocolMemberAttribute (TypeReference type, string s if (!isPropertyAccessor) { var attribParameters = new TypeReference [attrib.ParameterType?.Length ?? 0]; for (var i = 0; i < attribParameters.Length; i++) { - attribParameters [i] = attrib.ParameterType [i]; - if (attrib.ParameterByRef [i]) + attribParameters [i] = attrib.ParameterType! [i]; + if (attrib.ParameterByRef! [i]) attribParameters [i] = new ByReferenceType (attribParameters [i]); } if (!ParametersMatch (method.Parameters, attribParameters)) @@ -1513,32 +1521,31 @@ protected override IEnumerable GetProtocolMemberAttribu foreach (var ca in GetCustomAttributes (td, Foundation, StringConstants.ProtocolMemberAttribute)) { var rv = new ProtocolMemberAttribute (); - MethodDefinition implMethod = null; - if (ProtocolMemberMethodMap.TryGetValue (ca, out implMethod) == true) + if (ProtocolMemberMethodMap.TryGetValue (ca, out var implMethod) == true) rv.Method = implMethod; foreach (var prop in ca.Properties) { switch (prop.Name) { case "IsRequired": - rv.IsRequired = (bool) prop.Argument.Value; + rv.IsRequired = (bool) prop.Argument.Value!; break; case "IsProperty": - rv.IsProperty = (bool) prop.Argument.Value; + rv.IsProperty = (bool) prop.Argument.Value!; break; case "IsStatic": - rv.IsStatic = (bool) prop.Argument.Value; + rv.IsStatic = (bool) prop.Argument.Value!; break; case "Name": - rv.Name = (string) prop.Argument.Value; + rv.Name = (string) prop.Argument.Value!; break; case "Selector": - rv.Selector = (string) prop.Argument.Value; + rv.Selector = (string) prop.Argument.Value!; break; case "ReturnType": - rv.ReturnType = (TypeReference) prop.Argument.Value; + rv.ReturnType = (TypeReference) prop.Argument.Value!; break; case "ReturnTypeDelegateProxy": - rv.ReturnTypeDelegateProxy = (TypeReference) prop.Argument.Value; + rv.ReturnTypeDelegateProxy = (TypeReference) prop.Argument.Value!; break; case "ParameterType": if (prop.Argument.Value is not null) { @@ -1568,19 +1575,19 @@ protected override IEnumerable GetProtocolMemberAttribu } break; case "IsVariadic": - rv.IsVariadic = (bool) prop.Argument.Value; + rv.IsVariadic = (bool) prop.Argument.Value!; break; case "PropertyType": - rv.PropertyType = (TypeReference) prop.Argument.Value; + rv.PropertyType = (TypeReference) prop.Argument.Value!; break; case "GetterSelector": - rv.GetterSelector = (string) prop.Argument.Value; + rv.GetterSelector = (string) prop.Argument.Value!; break; case "SetterSelector": - rv.SetterSelector = (string) prop.Argument.Value; + rv.SetterSelector = (string) prop.Argument.Value!; break; case "ArgumentSemantic": - rv.ArgumentSemantic = (ArgumentSemantic) prop.Argument.Value; + rv.ArgumentSemantic = (ArgumentSemantic) prop.Argument.Value!; break; } } @@ -1589,7 +1596,7 @@ protected override IEnumerable GetProtocolMemberAttribu } #if !LEGACY_TOOLS - bool GetDotNetAvailabilityAttribute (ICustomAttribute ca, ApplePlatform currentPlatform, out Version sdkVersion, out string message) + bool GetDotNetAvailabilityAttribute (ICustomAttribute ca, ApplePlatform currentPlatform, out Version? sdkVersion, out string? message) { var caType = ca.AttributeType; @@ -1615,7 +1622,7 @@ bool GetDotNetAvailabilityAttribute (ICustomAttribute ca, ApplePlatform currentP } #endif // NET - bool CollectAvailabilityAttributes (IEnumerable attributes, out Version sdkVersion, out string message) + bool CollectAvailabilityAttributes (IEnumerable attributes, out Version? sdkVersion, out string? message) { sdkVersion = null; message = null; @@ -1677,7 +1684,7 @@ bool CollectAvailabilityAttributes (IEnumerable attributes, ou return false; } - protected override Version GetSdkIntroducedVersion (TypeReference obj, out string message) + protected override Version? GetSdkIntroducedVersion (TypeReference obj, out string? message) { TypeDefinition td = obj.Resolve (); @@ -1699,22 +1706,22 @@ protected override Version GetSdkIntroducedVersion (TypeReference obj, out strin return null; } - protected override Version GetSDKVersion () + protected override Version? GetSDKVersion () { return App.SdkVersion; } - protected override Dictionary> PrepareMethodMapping (TypeReference type) + protected override Dictionary>? PrepareMethodMapping (TypeReference type) { return PrepareInterfaceMethodMapping (type); } - public TypeReference GetProtocolAttributeWrapperType (TypeDefinition type) + public TypeReference? GetProtocolAttributeWrapperType (TypeDefinition type) { return GetProtocolAttributeWrapperType ((TypeReference) type); } - public static TypeReference GetProtocolAttributeWrapperType (ICustomAttribute attrib) + public static TypeReference? GetProtocolAttributeWrapperType (ICustomAttribute attrib) { if (!attrib.HasProperties) return null; @@ -1727,7 +1734,7 @@ public static TypeReference GetProtocolAttributeWrapperType (ICustomAttribute at return null; } - protected override TypeReference GetProtocolAttributeWrapperType (TypeReference type) + protected override TypeReference? GetProtocolAttributeWrapperType (TypeReference type) { if (!TryGetAttribute (type.Resolve (), Foundation, StringConstants.ProtocolAttribute, out var attrib)) return null; @@ -1735,7 +1742,7 @@ protected override TypeReference GetProtocolAttributeWrapperType (TypeReference return GetProtocolAttributeWrapperType (attrib); } - protected override IList GetAdoptsAttributes (TypeReference type) + protected override IList? GetAdoptsAttributes (TypeReference type) { var attributes = GetCustomAttributes (type.Resolve (), ObjCRuntime, "AdoptsAttribute"); if (attributes is null || !attributes.Any ()) @@ -1743,21 +1750,20 @@ protected override IList GetAdoptsAttributes (TypeReference typ var rv = new List (); foreach (var ca in attributes) { - var attrib = new AdoptsAttribute (); switch (ca.ConstructorArguments.Count) { case 1: - attrib.ProtocolType = (string) ca.ConstructorArguments [0].Value; + var attrib = new AdoptsAttribute ((string) ca.ConstructorArguments [0].Value); + rv.Add (attrib); break; default: throw ErrorHelper.CreateError (4124, Errors.MT4124_B, type.FullName, 1, ca.ConstructorArguments.Count); } - rv.Add (attrib); } return rv; } - NativeNameAttribute GetNativeNameAttribute (TypeReference type) + NativeNameAttribute? GetNativeNameAttribute (TypeReference type) { if (!TryGetAttribute ((ICustomAttributeProvider) type, ObjCRuntime, "NativeNameAttribute", out var attrib)) return null; @@ -1779,7 +1785,7 @@ static NativeNameAttribute CreateNativeNameAttribute (ICustomAttribute attrib, T } } - public override BindAsAttribute GetBindAsAttribute (PropertyDefinition property) + public override BindAsAttribute? GetBindAsAttribute (PropertyDefinition property) { if (property is null) return null; @@ -1792,7 +1798,7 @@ public override BindAsAttribute GetBindAsAttribute (PropertyDefinition property) return CreateBindAsAttribute (attrib, property); } - public override BindAsAttribute GetBindAsAttribute (MethodDefinition method, int parameter_index) + public override BindAsAttribute? GetBindAsAttribute (MethodDefinition method, int parameter_index) { if (method is null) return null; @@ -1807,7 +1813,7 @@ public override BindAsAttribute GetBindAsAttribute (MethodDefinition method, int static BindAsAttribute CreateBindAsAttribute (ICustomAttribute attrib, IMemberDefinition member) { - TypeReference originalType = null; + TypeReference? originalType = null; if (attrib.HasFields) { foreach (var field in attrib.Fields) { switch (field.Name) { @@ -1829,7 +1835,7 @@ static BindAsAttribute CreateBindAsAttribute (ICustomAttribute attrib, IMemberDe } } - public override TypeReference GetNullableType (TypeReference type) + public override TypeReference? GetNullableType (TypeReference type) { var git = type as GenericInstanceType; if (git is null) @@ -1839,11 +1845,9 @@ public override TypeReference GetNullableType (TypeReference type) return git.GenericArguments [0]; } - protected override ConnectAttribute GetConnectAttribute (PropertyDefinition property) + protected override ConnectAttribute? GetConnectAttribute (PropertyDefinition property) { - ICustomAttribute attrib; - - if (!TryGetAttribute (property, Foundation, StringConstants.ConnectAttribute, out attrib)) + if (!TryGetAttribute (property, Foundation, StringConstants.ConnectAttribute, out var attrib)) return null; if (!attrib.HasConstructorArguments) @@ -1857,7 +1861,7 @@ protected override ConnectAttribute GetConnectAttribute (PropertyDefinition prop } } - public static ExportAttribute CreateExportAttribute (IMemberDefinition candidate) + public static ExportAttribute? CreateExportAttribute (IMemberDefinition candidate) { bool is_variadic = false; var attribute = GetExportAttribute (candidate); @@ -1890,7 +1894,7 @@ public static ExportAttribute CreateExportAttribute (IMemberDefinition candidate } // [Export] is not sealed anymore - so we cannot simply compare strings - public static ICustomAttribute GetExportAttribute (ICustomAttributeProvider candidate) + public static ICustomAttribute? GetExportAttribute (ICustomAttributeProvider candidate) { if (!candidate.HasCustomAttributes) return null; @@ -1909,7 +1913,7 @@ PropertyDefinition GetBasePropertyInTypeHierarchy (PropertyDefinition property) var @base = GetBaseType (property.DeclaringType); while (@base is not null) { - PropertyDefinition base_property = TryMatchProperty (@base.Resolve (), property); + var base_property = TryMatchProperty (@base.Resolve (), property); if (base_property is not null) return GetBasePropertyInTypeHierarchy (base_property) ?? base_property; @@ -1919,7 +1923,7 @@ PropertyDefinition GetBasePropertyInTypeHierarchy (PropertyDefinition property) return property; } - static PropertyDefinition TryMatchProperty (TypeDefinition type, PropertyDefinition property) + static PropertyDefinition? TryMatchProperty (TypeDefinition type, PropertyDefinition property) { if (!type.HasProperties) return null; @@ -1964,7 +1968,7 @@ public MethodDefinition GetBaseMethodInTypeHierarchy (MethodDefinition method) var @base = GetBaseType (method.DeclaringType); while (@base is not null) { - MethodDefinition base_method = TryMatchMethod (@base.Resolve (), method); + var base_method = TryMatchMethod (@base.Resolve (), method); if (base_method is not null) return GetBaseMethodInTypeHierarchy (base_method) ?? base_method; @@ -1974,7 +1978,7 @@ public MethodDefinition GetBaseMethodInTypeHierarchy (MethodDefinition method) return method; } - static MethodDefinition TryMatchMethod (TypeDefinition type, MethodDefinition method) + static MethodDefinition? TryMatchMethod (TypeDefinition type, MethodDefinition method) { if (!type.HasMethods) return null; @@ -1989,10 +1993,10 @@ static MethodDefinition TryMatchMethod (TypeDefinition type, MethodDefinition me // here we try to create a specialized trampoline for the specified method. static int counter = 0; static bool trace = false; - AutoIndentStringBuilder header; - AutoIndentStringBuilder declarations; // forward declarations, struct definitions - AutoIndentStringBuilder methods; // c methods that contain the actual implementations - AutoIndentStringBuilder interfaces; // public objective-c @interface declarations + AutoIndentStringBuilder? header; + AutoIndentStringBuilder? declarations; // forward declarations, struct definitions + AutoIndentStringBuilder? methods; // c methods that contain the actual implementations + AutoIndentStringBuilder? interfaces; // public objective-c @interface declarations AutoIndentStringBuilder nslog_start = new AutoIndentStringBuilder (); AutoIndentStringBuilder nslog_end = new AutoIndentStringBuilder (); @@ -2023,8 +2027,8 @@ bool IsPlatformType (TypeReference type) string aname; if (type.Module is null) { // This type was probably linked away - if (LinkContext.GetLinkedAwayType (type, out var module) is not null) { - aname = module.Assembly.Name.Name; + if (LinkContext?.GetLinkedAwayType (type, out var module) is not null) { + aname = module?.Assembly?.Name?.Name ?? ""; } else { aname = string.Empty; } @@ -2048,7 +2052,7 @@ void CheckNamespace (ObjCType objctype, List exceptions) CheckNamespace (objctype.Type, exceptions); } - HashSet reported_frameworks; + HashSet? reported_frameworks; void CheckNamespace (TypeReference type, List exceptions) { if (!IsPlatformType (type)) @@ -2061,8 +2065,7 @@ void CheckNamespace (TypeReference type, List exceptions) if (type.Is ("AVKit", "AVCustomRoutingControllerDelegate")) ns = "AVRouting"; #endif - Framework framework; - if (Driver.GetFrameworks (App).TryGetValue (ns, out framework)) { + if (Driver.GetFrameworks (App).TryGetValue (ns, out var framework)) { if (framework.Version > App.SdkVersion) { if (reported_frameworks is null) reported_frameworks = new HashSet (); @@ -2087,12 +2090,15 @@ void CheckNamespace (string ns, List exceptions) if (namespaces.Contains (ns)) return; + if (header is null) + throw ErrorHelper.CreateError (99, Errors.MX0099, "No header?"); + namespaces.Add (ns); if (App.IsSimulatorBuild && !App.IsFrameworkAvailableInSimulator (ns)) { Driver.Log (5, "Not importing the framework {0} in the generated registrar code because it's not available in the simulator.", ns); return; - } else if (Frameworks.GetFrameworks (App.Platform, false).TryGetValue (ns, out var fw) && fw.Unavailable) { + } else if (Frameworks.GetFrameworks (App.Platform, false)?.TryGetValue (ns, out var fw) == true && fw.Unavailable) { Driver.Log (5, "Not importing the framework {0} in the generated registrar code because it's not available in the current platform.", ns); return; } @@ -2145,13 +2151,6 @@ void CheckNamespace (string ns, List exceptions) return; case "CoreAnimation": header.WriteLine ("#import "); - switch (App.Platform) { - case ApplePlatform.iOS: - case ApplePlatform.TVOS: - if (App.SdkVersion.Major > 7 && App.SdkVersion.Major < 11) - header.WriteLine ("#import "); - break; - } return; case "CoreMidi": h = ""; @@ -2163,10 +2162,8 @@ void CheckNamespace (string ns, List exceptions) header.WriteLine ("#import "); header.WriteLine ("#import "); header.WriteLine ("#import "); - if (App.SdkVersion.Major >= 7) { - header.WriteLine ("#import "); - header.WriteLine ("#import "); - } + header.WriteLine ("#import "); + header.WriteLine ("#import "); return; case "IOSurface": // There is no IOSurface.h h = ""; @@ -2187,6 +2184,9 @@ void CheckNamespace (string ns, List exceptions) string CheckStructure (TypeDefinition structure, string descriptiveMethodName, MemberReference inMember) { + if (declarations is null) + throw ErrorHelper.CreateError (99, Errors.MX0099, "No declarations?"); + string n; var name = new StringBuilder (); var body = new AutoIndentStringBuilder (1); @@ -2326,9 +2326,9 @@ string ToObjCParameterType (TypeReference type, string descriptiveMethodName, Li var reftype = type as ByReferenceType; if (reftype is not null) { - string res = ToObjCParameterType (GetElementType (reftype), descriptiveMethodName, exceptions, inMethod); + var res = ToObjCParameterType (GetElementType (reftype), descriptiveMethodName, exceptions, inMethod); if (res is null) - return null; + return ""; return res + "*"; } @@ -2410,8 +2410,11 @@ string ToObjCParameterType (TypeReference type, string descriptiveMethodName, Li CheckNamespace ("CoreGraphics", exceptions); return "CGFloat"; } - TypeDefinition td = ResolveType (type); - if (IsNSObject (td)) { + var td = ResolveType (type); + if (td is null) { + exceptions.Add (ErrorHelper.CreateError (99, Errors.MX0099, $"Unable to resolve the type {type.FullName} when generating the registrar for the method '{descriptiveMethodName}'.")); + return ""; + } else if (IsNSObject (td)) { if (!IsPlatformType (td)) return "id"; @@ -2585,7 +2588,7 @@ protected override string GetAssemblyQualifiedName (TypeReference type) public static string EncodeNonAsciiCharacters (string value) { - StringBuilder sb = null; + StringBuilder? sb = null; for (int i = 0; i < value.Length; i++) { char c = value [i]; if (c > 127) { @@ -2628,6 +2631,12 @@ bool IsTypeAllowedInSimulator (ObjCType type) class ProtocolInfo { public uint TokenReference; public ObjCType Protocol; + + public ProtocolInfo (uint tokenReference, ObjCType protocol) + { + TokenReference = tokenReference; + Protocol = protocol; + } } public class SkippedType { @@ -2635,19 +2644,26 @@ public class SkippedType { public ObjCType Actual; public uint SkippedTokenReference; public uint ActualTokenReference; + + public SkippedType (TypeReference skipped, ObjCType actual) + { + Skipped = skipped; + Actual = actual; + } } + List skipped_types = new List (); protected override void OnSkipType (TypeReference type, ObjCType registered_type) { base.OnSkipType (type, registered_type); - skipped_types.Add (new SkippedType { Skipped = type, Actual = registered_type }); + skipped_types.Add (new SkippedType (type, registered_type)); } public List SkippedTypes { get => skipped_types; } - public string GetInitializationMethodName (string single_assembly) + public string GetInitializationMethodName (string? single_assembly) { if (!string.IsNullOrEmpty (single_assembly)) { return "xamarin_create_classes_" + single_assembly.Replace ('.', '_').Replace ('-', '_'); @@ -2716,7 +2732,7 @@ List GetAllTypes (List exceptions) return all_types; } - CSToObjCMap type_map_dictionary; + CSToObjCMap? type_map_dictionary; public CSToObjCMap GetTypeMapDictionary (List exceptions) { if (type_map_dictionary is not null) @@ -2755,6 +2771,12 @@ public void Rewrite () void Specialize (AutoIndentStringBuilder sb, out string initialization_method) { + if (interfaces is null) + throw ErrorHelper.CreateError (99, Errors.MX0099, "No interfaces?"); + + if (declarations is null) + throw ErrorHelper.CreateError (99, Errors.MX0099, "No declarations?"); + var exceptions = new List (); var skip = new List (); @@ -2865,7 +2887,7 @@ void Specialize (AutoIndentStringBuilder sb, out string initialization_method) continue; protocol_wrapper_map.Add (token_ref, new Tuple (@class, protocol_wrapper_type_ref)); if (needs_protocol_map || TryGetAttribute (@class.Type, "Foundation", "XpcInterfaceAttribute", out var xpcAttr)) { - protocols.Add (new ProtocolInfo { TokenReference = token_ref, Protocol = @class }); + protocols.Add (new ProtocolInfo (token_ref, @class)); CheckNamespace (@class, exceptions); } } @@ -2892,7 +2914,7 @@ void Specialize (AutoIndentStringBuilder sb, out string initialization_method) } if (@class.IsCategory) { - var exportedName = EncodeNonAsciiCharacters (@class.BaseType.ExportedName); + var exportedName = EncodeNonAsciiCharacters (@class.BaseType!.ExportedName); iface.Write ("@interface {0} ({1})", exportedName, @class.CategoryName); declarations.AppendFormat ("@class {0};\n", exportedName); } else if (is_protocol) { @@ -2907,7 +2929,7 @@ void Specialize (AutoIndentStringBuilder sb, out string initialization_method) declarations.AppendFormat ("@class {0};\n", class_name); } var implementedProtocols = new HashSet (); - ObjCType tp = @class; + ObjCType? tp = @class; while (tp is not null && tp != tp.BaseType) { if (tp.IsWrapper) break; // no need to declare protocols for wrapper types, they do it already in their headers. @@ -2935,7 +2957,7 @@ void Specialize (AutoIndentStringBuilder sb, out string initialization_method) iface.Append (">"); } - AutoIndentStringBuilder implementation_fields = null; + AutoIndentStringBuilder? implementation_fields = null; if (is_protocol) { iface.WriteLine (); } else { @@ -2943,7 +2965,7 @@ void Specialize (AutoIndentStringBuilder sb, out string initialization_method) if (@class.Fields is not null) { foreach (var field in @class.Fields.Values) { - AutoIndentStringBuilder fields = null; + AutoIndentStringBuilder? fields = null; if (field.IsPrivate) { // Private fields go in the @implementation section. if (implementation_fields is null) @@ -3000,14 +3022,12 @@ void Specialize (AutoIndentStringBuilder sb, out string initialization_method) if (property.IsReadOnly) iface.Write (", readonly"); - if (property.Selector is not null) { - if (property.GetterSelector is not null && property.Selector != property.GetterSelector) - iface.Write (", getter = ").Write (property.GetterSelector); - if (property.SetterSelector is not null) { - var setterSel = string.Format ("set{0}{1}:", char.ToUpperInvariant (property.Selector [0]), property.Selector.Substring (1)); - if (setterSel != property.SetterSelector) - iface.Write (", setter = ").Write (property.SetterSelector); - } + if (property.GetterSelector is not null && property.Selector != property.GetterSelector) + iface.Write (", getter = ").Write (property.GetterSelector); + if (property.SetterSelector is not null) { + var setterSel = string.Format ("set{0}{1}:", char.ToUpperInvariant (property.Selector [0]), property.Selector.Substring (1)); + if (setterSel != property.SetterSelector) + iface.Write (", setter = ").Write (property.SetterSelector); } iface.Write (") "); @@ -3054,7 +3074,7 @@ void Specialize (AutoIndentStringBuilder sb, out string initialization_method) sb.WriteLine ("#pragma clang diagnostic ignored \"-Wobjc-property-implementation\""); } if (@class.IsCategory) { - sb.WriteLine ("@implementation {0} ({1})", EncodeNonAsciiCharacters (@class.BaseType.ExportedName), @class.CategoryName); + sb.WriteLine ("@implementation {0} ({1})", EncodeNonAsciiCharacters (@class.BaseType!.ExportedName), @class.CategoryName); } else { sb.WriteLine ("@implementation {0} {{", class_name); if (implementation_fields is not null) { @@ -3217,6 +3237,7 @@ bool TryGetIntPtrBoolCtor (TypeDefinition type, List exceptions, [Not if (method.Parameters [0].ParameterType.Is ("System", "IntPtr")) { // The registrar found a non-optimal type `{0}`: the type does not have a constructor that takes two (ObjCRuntime.NativeHandle, bool) arguments. However, a constructor that takes two (System.IntPtr, bool) arguments was found (and will be used instead). It's highly recommended to change the signature of the (System.IntPtr, bool) constructor to be (ObjCRuntime.NativeHandle, bool). exceptions.Add (ErrorHelper.CreateWarning (App, 4186, method, Errors.MT4186, type.FullName)); + ctor = method; return true; } if (!method.Parameters [0].ParameterType.Is ("ObjCRuntime", "NativeHandle")) @@ -3447,9 +3468,9 @@ void SpecializePrepareParameters (AutoIndentStringBuilder sb, ObjCMethod method, td = type.Resolve (); original_objctype = ToObjCParameterType (type, descriptiveMethodName, exceptions, method.Method); objctype = ToObjCParameterType (type, descriptiveMethodName, exceptions, method.Method) + "*"; - } else if (td.IsEnum) { - type = GetEnumUnderlyingType (td); + } else if (TryGetEnumUnderlyingType (td, out var underlyingEnumType)) { isNativeEnum = HasAttribute (td, ObjCRuntime, StringConstants.NativeAttribute); + type = underlyingEnumType; td = type.Resolve (); } @@ -3619,7 +3640,7 @@ void SpecializePrepareParameters (AutoIndentStringBuilder sb, ObjCMethod method, setup_call_stack.AppendLine ("paramtype{0} = xamarin_get_parameter_type (managed_method, {0});", i); if (isNativeObjectInterface) { var resolvedElementType = ResolveType (elementType); - if (TryCreateTokenReference (resolvedElementType, TokenType.TypeDef, out var iface_token_ref, out _) && TryCreateTokenReference (nativeObjType, TokenType.TypeDef, out var implementation_token_ref, out _)) { + if (resolvedElementType is not null && TryCreateTokenReference (resolvedElementType, TokenType.TypeDef, out var iface_token_ref, out _) && TryCreateTokenReference (nativeObjType, TokenType.TypeDef, out var implementation_token_ref, out _)) { var iface_token_ref_str = $"0x{iface_token_ref:X} /* {resolvedElementType} */ "; var implementation_token_ref_str = $"0x{implementation_token_ref:X} /* {nativeObjType} */ "; setup_call_stack.AppendLine ("marr{0} = xamarin_nsarray_to_managed_inativeobject_array_static (arr{0}, paramtype{0}, NULL, {1}, {2}, &exception_gchandle);", i, iface_token_ref_str, implementation_token_ref_str); @@ -3794,7 +3815,7 @@ void SpecializePrepareParameters (AutoIndentStringBuilder sb, ObjCMethod method, } } else if (type.IsPointer) { setup_call_stack.AppendLine ("arg_ptrs [{0}] = p{0};", i); - } else if (td.BaseType.FullName == "System.MulticastDelegate") { + } else if (td?.BaseType.FullName == "System.MulticastDelegate") { if (isRef) { throw ErrorHelper.CreateError (4110, Errors.MT4110, type.FullName, descriptiveMethodName); } else { @@ -3844,6 +3865,9 @@ void Specialize (AutoIndentStringBuilder sb, ObjCMethod method, List if (!TryGetReturnType (method, descriptiveMethodName, exceptions, out var rettype, out var isCtor)) return; + if (methods is null) + throw ErrorHelper.CreateError (99, Errors.MX0099, "methods collection is null"); + comment.Clear (); nslog_start.Clear (); nslog_end.Clear (); @@ -4124,13 +4148,9 @@ void Specialize (AutoIndentStringBuilder sb, ObjCMethod method, List objc_signature.Append (ToSimpleObjCParameterType (method.NativeParameters [i], descriptiveMethodName, exceptions, method.Method)).Append (":"); } - Body existing; - var b = new Body () { - Code = body.ToString (), - Signature = objc_signature.ToString (), - }; - - if (merge_bodies && bodies.TryGetValue (b, out existing)) { + var b = new Body (body.ToString (), objc_signature.ToString ()); + + if (merge_bodies && bodies.TryGetValue (b, out var existing)) { /* We already have an identical trampoline, use it instead */ b = existing; } else { @@ -4455,7 +4475,7 @@ public TypeDefinition GetInstantiableType (TypeDefinition td, List ex public TypeDefinition GetInstantiableType (TypeDefinition td, List exceptions, string descriptiveMethodName, out MethodDefinition ctor) { - TypeDefinition nativeObjType = td; + var nativeObjType = td; if (td.IsInterface) { var wrapper_type = GetProtocolAttributeWrapperType (td); @@ -4466,14 +4486,16 @@ public TypeDefinition GetInstantiableType (TypeDefinition td, List ex } // verify that the type has a ctor with two parameters - if (!TryGetIntPtrBoolCtor (nativeObjType, exceptions, out ctor)) + if (!TryGetIntPtrBoolCtor (nativeObjType, exceptions, out var ibCtor)) throw ErrorHelper.CreateError (4103, Errors.MT4103, nativeObjType.FullName, descriptiveMethodName); + ctor = ibCtor; + return nativeObjType; } // This method finds the CreateBlock method generated by the generator. - public MethodDefinition GetCreateBlockMethod (TypeDefinition delegateProxyType) + public MethodDefinition? GetCreateBlockMethod (TypeDefinition delegateProxyType) { if (!delegateProxyType.HasMethods) return null; @@ -4496,17 +4518,17 @@ public MethodDefinition GetCreateBlockMethod (TypeDefinition delegateProxyType) return null; } - public TypeDefinition GetDelegateProxyType (ObjCMethod obj_method) + public TypeDefinition? GetDelegateProxyType (ObjCMethod obj_method) { return GetDelegateProxyType (obj_method.Method, obj_method); } - public TypeDefinition GetDelegateProxyType (MethodDefinition method, ObjCMethod? obj_method = null) + public TypeDefinition? GetDelegateProxyType (MethodDefinition method, ObjCMethod? obj_method = null) { // A mirror of this method is also implemented in BlockLiteral:GetDelegateProxyType // If this method is changed, that method will probably have to be updated too (tests!!!) MethodDefinition first = method; - MethodDefinition last = null; + MethodDefinition? last = null; while (method != last) { last = method; var delegateProxyType = GetDelegateProxyAttribute (method); @@ -4531,7 +4553,7 @@ public TypeDefinition GetDelegateProxyType (MethodDefinition method, ObjCMethod? if (obj_method is not null) { var allProtocols = obj_method.DeclaringType.AllProtocolsInHierarchy; if (allProtocols is not null) { - string selector = null; + string? selector = null; foreach (var proto in allProtocols) { // We store the DelegateProxy type in the ProtocolMemberAttribute, so check those. @@ -4547,7 +4569,7 @@ public TypeDefinition GetDelegateProxyType (MethodDefinition method, ObjCMethod? } else { var allProtocols = CollectAllProtocolsInHierarchy (method.DeclaringType); if (allProtocols is not null) { - string selector = null; + string? selector = null; foreach (var proto in allProtocols) { // We store the DelegateProxy type in the ProtocolMemberAttribute, so check those. if (selector is null) @@ -4576,13 +4598,13 @@ List CollectAllProtocolsInHierarchy (TypeDefinition type) // a the block in the given method at the given parameter into a strongly typed // delegate // - public MethodDefinition GetBlockWrapperCreator (ObjCMethod obj_method, int parameter) + public MethodDefinition? GetBlockWrapperCreator (ObjCMethod obj_method, int parameter) { // A mirror of this method is also implemented in Runtime:GetBlockWrapperCreator // If this method is changed, that method will probably have to be updated too (tests!!!) MethodDefinition method = obj_method.Method; MethodDefinition first = method; - MethodDefinition last = null; + MethodDefinition? last = null; while (method != last) { last = method; var createMethod = GetBlockProxyAttributeMethod (method, parameter); @@ -4606,7 +4628,7 @@ public MethodDefinition GetBlockWrapperCreator (ObjCMethod obj_method, int param // Might be an implementation of an optional protocol member. var allProtocols = obj_method.DeclaringType.AllProtocolsInHierarchy; if (allProtocols is not null) { - string selector = null; + string? selector = null; foreach (var proto in allProtocols) { // We store the BlockProxy type in the ProtocolMemberAttribute, so check those. @@ -4631,7 +4653,7 @@ public MethodDefinition GetBlockWrapperCreator (ObjCMethod obj_method, int param if (!ParametersMatch (method.Parameters, pMethod.Parameters)) continue; - MethodDefinition extensionMethod = pMethod.Method; + MethodDefinition? extensionMethod = pMethod.Method; if (extensionMethod is null) { MapProtocolMember (obj_method.Method, out extensionMethod); if (extensionMethod is null) @@ -4671,7 +4693,7 @@ public bool TryFindMethod (MethodDefinition method, [NotNullWhen (true)] out Obj return false; } - MethodDefinition GetBlockProxyAttributeMethod (MethodDefinition method, int parameter) + MethodDefinition? GetBlockProxyAttributeMethod (MethodDefinition method, int parameter) { var param = method.Parameters [parameter]; var attrib = GetBlockProxyAttribute (param); @@ -4690,7 +4712,7 @@ MethodDefinition GetBlockProxyAttributeMethod (MethodDefinition method, int para return createMethod; } - public bool MapProtocolMember (MethodDefinition method, out MethodDefinition extensionMethod) + public bool MapProtocolMember (MethodDefinition method, [NotNullWhen (true)] out MethodDefinition? extensionMethod) { // Given 'method', finds out if it's the implementation of an optional protocol method, // and if so, return the corresponding IProtocol_Extensions method. @@ -4710,7 +4732,7 @@ public bool MapProtocolMember (MethodDefinition method, out MethodDefinition ext return false; } - public bool MapProtocolMember (TypeDefinition t, MethodDefinition method, out MethodDefinition extensionMethod) + public bool MapProtocolMember (TypeDefinition t, MethodDefinition method, [NotNullWhen (true)] out MethodDefinition? extensionMethod) { extensionMethod = null; @@ -4719,7 +4741,7 @@ public bool MapProtocolMember (TypeDefinition t, MethodDefinition method, out Me // special processing to find [BlockProxy] attributes in _Extensions types // ref: https://bugzilla.xamarin.com/show_bug.cgi?id=23540 - string selector = null; + string? selector = null; foreach (var r in t.Interfaces) { var i = r.InterfaceType.Resolve (); if (i is null || !HasAttribute (i, Namespaces.Foundation, "ProtocolAttribute")) @@ -4729,14 +4751,14 @@ public bool MapProtocolMember (TypeDefinition t, MethodDefinition method, out Me var ea = CreateExportAttribute (method); selector = ea?.Selector; } - string name = null; + string? name = null; bool match = false; - ICustomAttribute protocolMemberAttribute = null; + ICustomAttribute? protocolMemberAttribute = null; foreach (var ca in GetCustomAttributes (i, Foundation, StringConstants.ProtocolMemberAttribute)) { foreach (var p in ca.Properties) { switch (p.Name) { case "Selector": - match = (p.Argument.Value as string == selector); + match = p.Argument.Value as string == selector; break; case "Name": name = p.Argument.Value as string; @@ -4748,7 +4770,7 @@ public bool MapProtocolMember (TypeDefinition t, MethodDefinition method, out Me break; } } - if (!match || name is null) + if (!match || name is null || protocolMemberAttribute is null) continue; // _Extensions time... var td = i.Module.GetType (i.Namespace, i.Name.Substring (1) + "_Extensions"); @@ -4800,8 +4822,8 @@ public string GetManagedToNSNumberFunc (TypeReference managedType, TypeReference default: if (typeName == NFloatTypeName) return "xamarin_nfloat_to_nsnumber"; - if (IsEnum (managedType)) - return GetManagedToNSNumberFunc (GetEnumUnderlyingType (managedType), inputType, outputType, descriptiveMethodName); + if (TryGetEnumUnderlyingType (managedType, out var enumUnderlyingType)) + return GetManagedToNSNumberFunc (enumUnderlyingType, inputType, outputType, descriptiveMethodName); throw ErrorHelper.CreateError (99, Errors.MX0099, $"can't convert from '{inputType.FullName}' to '{outputType.FullName}' in {descriptiveMethodName}"); } } @@ -4830,8 +4852,8 @@ public string GetNSNumberToManagedFunc (TypeReference managedType, TypeReference nativeType = "CGFloat"; return "xamarin_nsnumber_to_nfloat"; } - if (IsEnum (managedType)) - return GetNSNumberToManagedFunc (GetEnumUnderlyingType (managedType), inputType, outputType, descriptiveMethodName, out nativeType); + if (TryGetEnumUnderlyingType (managedType, out var enumUnderlyingType)) + return GetNSNumberToManagedFunc (enumUnderlyingType, inputType, outputType, descriptiveMethodName, out nativeType); throw ErrorHelper.CreateError (99, Errors.MX0099, $"can't convert from '{inputType.FullName}' to '{outputType.FullName}' in {descriptiveMethodName}"); } } @@ -4935,6 +4957,8 @@ void GenerateConversionToManaged (TypeReference inputType, TypeReference outputT cleanup.AppendLine ($"xamarin_mono_object_release (&{classVariableName});"); } else if (isManagedNullable) { underlyingManagedType = GetNullableType (managedType); + if (underlyingManagedType is null) + throw ErrorHelper.CreateError (99, Errors.MX0099, $"can't convert from '{inputType.FullName}' to '{outputType.FullName}' in {descriptiveMethodName}: {managedType.FullName} is not a valid nullable type"); sb.AppendLine ($"{classVariableName} = xamarin_get_nullable_type ({managedClassExpression}, &exception_gchandle);"); sb.AppendLine ($"if (exception_gchandle != INVALID_GCHANDLE) goto exception_handling;"); cleanup.AppendLine ($"xamarin_mono_object_release (&{classVariableName});"); @@ -5031,6 +5055,8 @@ void GenerateConversionToNative (TypeReference inputType, TypeReference outputTy cleanup.AppendLine ($"xamarin_mono_object_release (&{classVariableName});"); } else if (isManagedNullable) { underlyingManagedType = GetNullableType (managedType); + if (underlyingManagedType is null) + throw ErrorHelper.CreateError (99, Errors.MX0099, $"can't convert from '{inputType.FullName}' to '{outputType.FullName}' in {descriptiveMethodName}: {managedType.FullName} is not a nullable type"); sb.AppendLine ($"{classVariableName} = xamarin_get_nullable_type ({managedClassExpression}, &exception_gchandle);"); sb.AppendLine ($"if (exception_gchandle != INVALID_GCHANDLE) goto exception_handling;"); cleanup.AppendLine ($"xamarin_mono_object_release (&{classVariableName});"); @@ -5084,11 +5110,19 @@ class Body { public string Name; public int Count; + public Body (string code, string signature) + { + Code = code; + Signature = signature; + Name = ""; + } + public override int GetHashCode () { return Code.GetHashCode () ^ Signature.GetHashCode (); } - public override bool Equals (object obj) + + public override bool Equals (object? obj) { var other = obj as Body; if (other is null) @@ -5097,7 +5131,7 @@ public override bool Equals (object obj) } } - bool TryCreateFullTokenReference (MemberReference member, out uint token_ref, out Exception exception) + bool TryCreateFullTokenReference (MemberReference member, out uint token_ref, out Exception? exception) { switch (member.MetadataToken.TokenType) { case TokenType.TypeDef: @@ -5115,7 +5149,7 @@ bool TryCreateFullTokenReference (MemberReference member, out uint token_ref, ou return WriteFullTokenReference (member.Module.Assembly, moduleToken, moduleName, memberToken, memberName, out token_ref, out exception); } - bool WriteFullTokenReference (AssemblyDefinition assembly, uint moduleToken, string moduleName, uint memberToken, string memberName, out uint token_ref, out Exception exception) + bool WriteFullTokenReference (AssemblyDefinition assembly, uint moduleToken, string moduleName, uint memberToken, string memberName, out uint token_ref, out Exception? exception) { token_ref = (full_token_reference_count++ << 1) + 1; var assemblyIndex = registered_assemblies.FindIndex (v => v.Assembly == assembly); @@ -5132,13 +5166,14 @@ bool WriteFullTokenReference (AssemblyDefinition assembly, uint moduleToken, str Dictionary, uint> token_ref_cache = new Dictionary, uint> (); bool TryCreateTokenReference (MemberReference member, TokenType implied_type, out uint token_ref, List exceptions) { - var rv = TryCreateTokenReference (member, implied_type, out token_ref, out var ex); - if (!rv) - exceptions.Add (ex); - return rv; + if (TryCreateTokenReference (member, implied_type, out token_ref, out var ex)) + return true; + + exceptions.Add (ex); + return false; } - bool TryCreateTokenReference (MemberReference member, TokenType implied_type, out uint token_ref, out Exception exception) + bool TryCreateTokenReference (MemberReference member, TokenType implied_type, out uint token_ref, [NotNullWhen (false)] out Exception? exception) { var key = new Tuple (member, implied_type); exception = null; @@ -5150,7 +5185,7 @@ bool TryCreateTokenReference (MemberReference member, TokenType implied_type, ou return true; } - bool TryCreateTokenReferenceUncached (MemberReference member, TokenType implied_type, out uint token_ref, out Exception exception) + bool TryCreateTokenReferenceUncached (MemberReference member, TokenType implied_type, out uint token_ref, [NotNullWhen (false)] out Exception? exception) { var token = member.MetadataToken; @@ -5257,8 +5292,7 @@ string TryGeneratePInvokeWrapper (PInvokeWrapperGenerator state, MethodDefinitio } signature.Append (")"); - string wrapperName; - if (!signatures.TryGetValue (signature.ToString (), out wrapperName)) { + if (!signatures.TryGetValue (signature.ToString (), out var wrapperName)) { var methodName = method.Name.Replace ('<', '_').Replace ('>', '_').Replace ('|', '_'); var baseName = "xamarin_pinvoke_wrapper_" + methodName; var name = baseName; @@ -5338,7 +5372,7 @@ public void GeneratePInvokeWrapper (PInvokeWrapperGenerator state, MethodDefinit } // find the module reference to __Internal - ModuleReference mr = null; + ModuleReference? mr = null; foreach (var mref in method.Module.ModuleReferences) { if (mref.Name == "__Internal") { mr = mref; @@ -5359,7 +5393,7 @@ public void Register (IEnumerable assemblies) Register (null, assemblies); } - public void Register (PlatformResolver resolver, IEnumerable assemblies) + public void Register (PlatformResolver? resolver, IEnumerable assemblies) { this.resolver = resolver; this.input_assemblies = assemblies; @@ -5472,7 +5506,7 @@ public void Generate (IEnumerable assemblies, string header_ Generate (null, assemblies, header_path, source_path, out initialization_method); } - public void Generate (PlatformResolver resolver, IEnumerable assemblies, string header_path, string source_path, out string initialization_method) + public void Generate (PlatformResolver? resolver, IEnumerable assemblies, string header_path, string source_path, out string initialization_method) { Register (resolver, assemblies); Generate (header_path, source_path, out initialization_method); @@ -5555,19 +5589,19 @@ protected override bool SkipRegisterAssembly (AssemblyDefinition assembly) } // Find the value of the [UserDelegateType] attribute on the specified delegate - public TypeReference GetUserDelegateType (MethodReference invokeMethod) + public TypeReference? GetUserDelegateType (MethodReference invokeMethod) { return GetUserDelegateTypeImpl (invokeMethod.Resolve ()); } // Find the value of the [UserDelegateType] attribute on the specified method - TypeReference GetUserDelegateType (TypeReference delegateType) + TypeReference? GetUserDelegateType (TypeReference delegateType) { return GetUserDelegateTypeImpl (delegateType.Resolve ()); } // Find the value of the [UserDelegateType] attribute on the specified delegate - TypeReference GetUserDelegateTypeImpl (ICustomAttributeProvider provider) + TypeReference? GetUserDelegateTypeImpl (ICustomAttributeProvider provider) { if (provider?.HasCustomAttributes != true) return null; @@ -5581,7 +5615,7 @@ TypeReference GetUserDelegateTypeImpl (ICustomAttributeProvider provider) } #if !LEGACY_TOOLS - public MethodReference GetDelegateInvoke (TypeReference delegateType) + public MethodReference? GetDelegateInvoke (TypeReference delegateType) { var td = delegateType.Resolve (); foreach (var method in td.Methods) { @@ -5608,14 +5642,14 @@ public MethodReference InflateMethod (TypeReference inflatedDeclaringType, Metho return mr; } - public bool TryComputeBlockSignature (ICustomAttributeProvider codeLocation, TypeReference trampolineDelegateType, out Exception exception, out string signature) + public bool TryComputeBlockSignature (ICustomAttributeProvider codeLocation, TypeReference trampolineDelegateType, [NotNullWhen (false)] out Exception? exception, [NotNullWhen (true)] out string? signature) { signature = null; exception = null; try { // Calculate the block signature. var blockSignature = false; - MethodReference userMethod = null; + MethodReference? userMethod = null; // First look for any [UserDelegateType] attributes on the trampoline delegate type. var userDelegateType = GetUserDelegateType (trampolineDelegateType); @@ -5650,10 +5684,10 @@ public bool TryComputeBlockSignature (ICustomAttributeProvider codeLocation, Typ // Replicate a few attribute types here, with TypeDefinition instead of Type class ProtocolAttribute : Attribute { - public TypeDefinition WrapperType { get; set; } - public string Name { get; set; } + public TypeDefinition? WrapperType { get; set; } + public string? Name { get; set; } public bool IsInformal { get; set; } - public Version FormalSinceVersion { get; set; } + public Version? FormalSinceVersion { get; set; } #if !XAMCORE_5_0 public bool BackwardsCompatibleCodeGeneration { get; set; } #endif @@ -5661,10 +5695,20 @@ class ProtocolAttribute : Attribute { class BlockProxyAttribute : Attribute { public TypeDefinition Type { get; set; } + + public BlockProxyAttribute (TypeDefinition type) + { + this.Type = type; + } } class DelegateProxyAttribute : Attribute { public TypeDefinition DelegateType { get; set; } + + public DelegateProxyAttribute (TypeDefinition delegateType) + { + this.DelegateType = delegateType; + } } class BindAsAttribute : Attribute { @@ -5674,7 +5718,7 @@ public BindAsAttribute (TypeReference type) } public TypeReference Type { get; set; } - public TypeReference OriginalType { get; set; } + public TypeReference? OriginalType { get; set; } } public sealed class ProtocolMemberAttribute : Attribute { @@ -5683,31 +5727,31 @@ public ProtocolMemberAttribute () { } public bool IsRequired { get; set; } public bool IsProperty { get; set; } public bool IsStatic { get; set; } - public string Name { get; set; } - public string Selector { get; set; } - public TypeReference ReturnType { get; set; } - public TypeReference ReturnTypeDelegateProxy { get; set; } - public TypeReference [] ParameterType { get; set; } - public bool [] ParameterByRef { get; set; } - public TypeReference [] ParameterBlockProxy { get; set; } + public string? Name { get; set; } + public string? Selector { get; set; } + public TypeReference? ReturnType { get; set; } + public TypeReference? ReturnTypeDelegateProxy { get; set; } + public TypeReference []? ParameterType { get; set; } + public bool []? ParameterByRef { get; set; } + public TypeReference []? ParameterBlockProxy { get; set; } public bool IsVariadic { get; set; } - public TypeReference PropertyType { get; set; } - public string GetterSelector { get; set; } - public string SetterSelector { get; set; } + public TypeReference? PropertyType { get; set; } + public string? GetterSelector { get; set; } + public string? SetterSelector { get; set; } public ArgumentSemantic ArgumentSemantic { get; set; } - public MethodDefinition Method { get; set; } // not in the API, used to find the original method in the static registrar + public MethodDefinition? Method { get; set; } // not in the API, used to find the original method in the static registrar } class CategoryAttribute : Attribute { - public CategoryAttribute (TypeDefinition type) + public CategoryAttribute (TypeDefinition? type) { Type = type; } - public TypeDefinition Type { get; set; } - public string Name { get; set; } + public TypeDefinition? Type { get; set; } + public string? Name { get; set; } } class RegisterAttribute : Attribute { @@ -5723,7 +5767,7 @@ public RegisterAttribute (string name, bool isWrapper) this.IsWrapper = isWrapper; } - public string Name { get; set; } + public string? Name { get; set; } public bool IsWrapper { get; set; } public bool SkipRegistration { get; set; } public bool IsStubClass { get; set; } @@ -5731,6 +5775,10 @@ public RegisterAttribute (string name, bool isWrapper) class AdoptsAttribute : Attribute { public string ProtocolType { get; set; } + public AdoptsAttribute (string protocolType) + { + this.ProtocolType = protocolType; + } } [Flags] diff --git a/tools/common/Target.cs b/tools/common/Target.cs index dd66babe19d3..9c70601442ef 100644 --- a/tools/common/Target.cs +++ b/tools/common/Target.cs @@ -28,7 +28,11 @@ public partial class Application { public Application App => this; public AssemblyCollection Assemblies = new AssemblyCollection (); // The root assembly is not in this list. +#if LEGACY_TOOLS public PlatformLinkContext? LinkContext; +#else + public PlatformLinkContext LinkContext; +#endif public PlatformResolver Resolver = new PlatformResolver (); internal StaticRegistrar StaticRegistrar { get; set; } @@ -40,12 +44,9 @@ public Assembly AddAssembly (AssemblyDefinition assembly) return asm; } - // This will find the link context, possibly looking in container targets. public PlatformLinkContext? GetLinkContext () { - if (LinkContext is not null) - return LinkContext; - return null; + return LinkContext; } public void ExtractNativeLinkInfo (List exceptions) diff --git a/tools/dotnet-linker/Compat.cs b/tools/dotnet-linker/Compat.cs index 5aa803a6530b..bb461f92a79f 100644 --- a/tools/dotnet-linker/Compat.cs +++ b/tools/dotnet-linker/Compat.cs @@ -10,6 +10,7 @@ using Xamarin.Bundler; using Xamarin.Linker; +using Xamarin.Tuner; using Xamarin.Utils; #nullable enable @@ -20,12 +21,6 @@ public partial class Application { public LinkerConfiguration Configuration { get => configuration!; } public string? RuntimeConfigurationFile { get; set; } - public Application (LinkerConfiguration configuration) - : this () - { - this.configuration = configuration; - } - public string ProductName { get { switch (Platform) { diff --git a/tools/dotnet-linker/LinkerConfiguration.cs b/tools/dotnet-linker/LinkerConfiguration.cs index e169119f2c32..1e1ec4c74590 100644 --- a/tools/dotnet-linker/LinkerConfiguration.cs +++ b/tools/dotnet-linker/LinkerConfiguration.cs @@ -50,7 +50,7 @@ public class LinkerConfiguration { LinkContext? context; public LinkContext Context { get => context!; private set { context = value; } } - public DerivedLinkContext DerivedLinkContext { get; private set; } + public DerivedLinkContext DerivedLinkContext { get => Application.LinkContext; } public Profile Profile { get; private set; } // The list of assemblies is populated in CollectAssembliesStep. @@ -103,7 +103,6 @@ public static LinkerConfiguration GetInstance (LinkContext context) Profile = new BaseProfile (this); Application = new Application (this); - DerivedLinkContext = new DerivedLinkContext (this, Application); CompilerFlags = new CompilerFlags (Application); var use_llvm = false; diff --git a/tools/dotnet-linker/Steps/ManagedRegistrarStep.cs b/tools/dotnet-linker/Steps/ManagedRegistrarStep.cs index 0e07b5fb9ec4..2b9e55e9a9dd 100644 --- a/tools/dotnet-linker/Steps/ManagedRegistrarStep.cs +++ b/tools/dotnet-linker/Steps/ManagedRegistrarStep.cs @@ -698,6 +698,10 @@ bool EmitConversion (MethodDefinition method, ILProcessor il, TypeReference type if (!(parameter == -1 && !method.IsStatic && method.DeclaringType == type)) { var bindAsAttribute = GetBindAsAttribute (method, parameter); if (bindAsAttribute is not null) { + if (bindAsAttribute.OriginalType is null) { + AddException (ErrorHelper.CreateError (99, "BindAs attribute without OriginalType. Method: {0}", GetMethodSignatureWithSourceCode (method))); + return false; + } if (toManaged) { GenerateConversionToManaged (method, il, bindAsAttribute.OriginalType, type, "descriptiveMethodName", parameter, out nativeType); return true; @@ -751,12 +755,16 @@ bool EmitConversion (MethodDefinition method, ILProcessor il, TypeReference type if (type is ByReferenceType brt) { if (toManaged) { - var elementType = brt.ElementType; + var elementType = brt.ElementType!; if (elementType is GenericParameter gp) { if (!StaticRegistrar.VerifyIsConstrainedToNSObject (gp, out var constrained)) { AddException (ErrorHelper.CreateError (99, "Incorrectly constrained generic parameter. Method: {0}", GetMethodSignatureWithSourceCode (method))); return false; } + if (constrained is null) { + AddException (ErrorHelper.CreateError (99, "Incorrectly constrained generic parameter (2). Method: {0}", GetMethodSignatureWithSourceCode (method))); + return false; + } elementType = constrained; } @@ -888,7 +896,7 @@ bool EmitConversion (MethodDefinition method, ILProcessor il, TypeReference type return true; } - AddException (ErrorHelper.CreateError (99, "Don't know how (3) to convert array element type {1} for array type {0} between managed and native code. Method: {2}", type.FullName, elementType.FullName, GetMethodSignatureWithSourceCode (method))); + AddException (ErrorHelper.CreateError (99, "Don't know how (3) to convert array element type {1} for array type {0} between managed and native code. Method: {2}", type.FullName, elementType?.FullName, GetMethodSignatureWithSourceCode (method))); return false; } @@ -1162,6 +1170,8 @@ void GenerateConversionToManaged (MethodDefinition method, ILProcessor il, TypeR underlyingManagedType = StaticRegistrar.GetElementType (managedType); } else if (isManagedNullable) { underlyingManagedType = StaticRegistrar.GetNullableType (managedType); + if (underlyingManagedType is null) + throw ErrorHelper.CreateError (99, Errors.MX0099, $"can't convert from '{inputType.FullName}' to '{outputType.FullName}' in {descriptiveMethodName}: {managedType.FullName} is not a nullable type"); } string? func = null; @@ -1259,6 +1269,8 @@ void GenerateConversionToNative (MethodDefinition method, ILProcessor il, TypeRe underlyingManagedType = StaticRegistrar.GetElementType (managedType); } else if (isManagedNullable) { underlyingManagedType = StaticRegistrar.GetNullableType (managedType); + if (underlyingManagedType is null) + throw ErrorHelper.CreateError (99, Errors.MX0099, $"can't convert from '{inputType.FullName}' to '{outputType.FullName}' in {descriptiveMethodName}: {managedType.FullName} is not a nullable type"); } string? func = null; diff --git a/tools/linker/MobileExtensions.cs b/tools/linker/MobileExtensions.cs index 6d7425022db1..cba0f7f9997e 100644 --- a/tools/linker/MobileExtensions.cs +++ b/tools/linker/MobileExtensions.cs @@ -128,7 +128,7 @@ static bool HasGeneratedCodeAttribute (ICustomAttributeProvider? provider, Deriv return null; } - public static bool IsGeneratedCode (this MethodDefinition self, DerivedLinkContext link_context) + public static bool IsGeneratedCode (this MethodDefinition self, DerivedLinkContext? link_context) { // check the property too if (self.IsGetter || self.IsSetter) { @@ -138,7 +138,7 @@ public static bool IsGeneratedCode (this MethodDefinition self, DerivedLinkConte return HasGeneratedCodeAttribute (self, link_context); } - public static bool IsBindingImplOptimizableCode (this MethodDefinition self, DerivedLinkContext link_context) + public static bool IsBindingImplOptimizableCode (this MethodDefinition self, DerivedLinkContext? link_context) { var attrib = GetBindingImplAttribute (self, link_context); if ((attrib & BindingImplOptions.Optimizable) == BindingImplOptions.Optimizable) @@ -154,7 +154,7 @@ public static bool IsBindingImplOptimizableCode (this MethodDefinition self, Der return false; } - public static bool IsOptimizableCode (this MethodDefinition self, DerivedLinkContext link_context) + public static bool IsOptimizableCode (this MethodDefinition self, DerivedLinkContext? link_context) { if (IsBindingImplOptimizableCode (self, link_context)) return true; diff --git a/tools/mtouch/LinkerConfiguration.cs b/tools/mtouch/LinkerConfiguration.cs new file mode 100644 index 000000000000..b18f8f3210f5 --- /dev/null +++ b/tools/mtouch/LinkerConfiguration.cs @@ -0,0 +1,4 @@ +namespace Xamarin.Linker; + +public class LinkerConfiguration { +} diff --git a/tools/mtouch/mtouch.cs b/tools/mtouch/mtouch.cs index f3aa5266d464..21349adc0aaf 100644 --- a/tools/mtouch/mtouch.cs +++ b/tools/mtouch/mtouch.cs @@ -10,13 +10,15 @@ using Mono.Options; +using Xamarin.Linker; + namespace Xamarin.Bundler { public partial class Driver { internal const string NAME = "mtouch"; static int Main2 (string [] args) { - var app = new Application (); + var app = new Application (new LinkerConfiguration ()); var os = new OptionSet (); ParseOptions (app, os, args); diff --git a/tools/mtouch/mtouch.csproj b/tools/mtouch/mtouch.csproj index 4472894e07af..ca0541e4ea60 100644 --- a/tools/mtouch/mtouch.csproj +++ b/tools/mtouch/mtouch.csproj @@ -18,6 +18,7 @@ + external/tools/common/error.cs From ed2c405e8bd0bfd47aa6700863fcfc1eaa4dcd9b Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Wed, 28 Jan 2026 18:40:57 +0100 Subject: [PATCH 2/6] Registrar --- src/ObjCRuntime/Registrar.core.cs | 7 +- src/ObjCRuntime/Registrar.cs | 524 +++++++++++++++--------------- tools/common/ErrorHelper.tools.cs | 40 +-- tools/common/StaticRegistrar.cs | 102 +++--- 4 files changed, 340 insertions(+), 333 deletions(-) diff --git a/src/ObjCRuntime/Registrar.core.cs b/src/ObjCRuntime/Registrar.core.cs index ebed24b57385..6ec72e425e7c 100644 --- a/src/ObjCRuntime/Registrar.core.cs +++ b/src/ObjCRuntime/Registrar.core.cs @@ -4,6 +4,7 @@ namespace Registrar { abstract partial class Registrar { + [return: NotNullIfNotNull (nameof (getterSelector))] internal static string? CreateSetterSelector (string? getterSelector) { if (string.IsNullOrEmpty (getterSelector)) @@ -16,8 +17,12 @@ abstract partial class Registrar { return "set" + ((char) first).ToString () + getterSelector.Substring (1) + ":"; } - public static string SanitizeObjectiveCName (string name) + [return: NotNullIfNotNull (nameof (name))] + public static string? SanitizeObjectiveCName (string? name) { + if (string.IsNullOrEmpty (name)) + return name; + StringBuilder? sb = null; for (int i = 0; i < name.Length; i++) { diff --git a/src/ObjCRuntime/Registrar.cs b/src/ObjCRuntime/Registrar.cs index 197167c6e806..4e9f705ae17b 100644 --- a/src/ObjCRuntime/Registrar.cs +++ b/src/ObjCRuntime/Registrar.cs @@ -43,11 +43,10 @@ [assembly: Preserve (typeof (System.Action))] #endif -// Disable until we get around to enable + fix any issues. -#nullable disable +#nullable enable // -// This file cannot use any cecil code, since it's also compiled into Xamarin.[iOS|Mac].dll +// This file cannot use any cecil code, since it's also compiled into Microsoft.[iOS|macOS|tvOS|MacCatalyst].dll // #if MONOMAC @@ -90,14 +89,12 @@ public static List GetMT4127 (TMethod impl, List ifac abstract partial class Registrar { #if LEGACY_TOOLS || BUNDLER -#nullable enable - public Application App { get; protected set; } -#nullable disable + public Application App { get; private set; } #endif const string NFloatTypeName = "System.Runtime.InteropServices.NFloat"; - Dictionary assemblies = new Dictionary (); // Use Dictionary instead of HashSet to avoid pulling in System.Core.dll. + Dictionary assemblies = new (); // Use Dictionary instead of HashSet to avoid pulling in System.Core.dll. // locking: all accesses must lock 'types'. Dictionary types = new Dictionary (); // this is used to check if multiple types are registered with the same name. @@ -109,8 +106,8 @@ abstract partial class Registrar { // this is used to check if multiple categories are registered with the same name. // locking: all accesses must lock 'categories_map'. Dictionary categories_map = new Dictionary (); - TMethod conforms_to_protocol; - TMethod invoke_conforms_to_protocol; + TMethod? conforms_to_protocol; + TMethod? invoke_conforms_to_protocol; public IEnumerable GetAssemblies () { @@ -119,14 +116,14 @@ public IEnumerable GetAssemblies () internal class ObjCType { - public Registrar Registrar; - public RegisterAttribute RegisterAttribute; - public CategoryAttribute CategoryAttribute; - public TType Type; - public ObjCType BaseType; + public readonly Registrar Registrar; + public RegisterAttribute? RegisterAttribute; + public CategoryAttribute? CategoryAttribute; + public readonly TType Type; + public ObjCType? BaseType; // This only contains the leaf protocols implemented by this type. - public ObjCType [] Protocols; - public string [] AdoptedProtocols; + public ObjCType []? Protocols; + public string []? AdoptedProtocols; public bool IsModel; // if this type represents an ObjC protocol (!= has the protocol attribute, since that can be applied to all kinds of things). public bool IsProtocol; @@ -136,22 +133,28 @@ internal class ObjCType { #if !LEGACY_TOOLS && !BUNDLER public IntPtr Handle; #else - public TType ProtocolWrapperType; + public TType? ProtocolWrapperType; public int ClassMapIndex; #endif - public Dictionary Fields; - public List Methods; - public List Properties; + public Dictionary? Fields; + public List? Methods; + public List? Properties; Dictionary Map = new Dictionary (); - ObjCType superType; + ObjCType? superType; public bool IsCategory { get { return CategoryAttribute is not null; } } + public ObjCType (Registrar registrar, TType type) + { + this.Registrar = registrar; + this.Type = type; + } + #if LEGACY_TOOLS || BUNDLER - HashSet all_protocols; + HashSet? all_protocols; // This contains all protocols in the type hierarchy. // Given a type T that implements a protocol with super protocols: // class T : NSObject, IProtocol2 {} @@ -160,7 +163,7 @@ internal class ObjCType { // [Protocol] // interface IP2 : IP1 {} // This property will contain both IP1 and IP2. The Protocols property only contains IP2. - public IEnumerable AllProtocols { + public IEnumerable? AllProtocols { get { if (Protocols is null || Protocols.Length == 0) return null; @@ -171,7 +174,7 @@ public IEnumerable AllProtocols { while (queue.Count > 0) { var type = queue.Dequeue (); if (rv.Add (type)) { - foreach (var iface in type.Type.Resolve ().Interfaces) { + foreach (var iface in type.Type!.Resolve ().Interfaces) { if (!Registrar.Types.TryGetValue (iface.InterfaceType, out var superIface)) { // This is not an interface that corresponds to a protocol. continue; @@ -187,13 +190,13 @@ public IEnumerable AllProtocols { } } - HashSet all_protocols_in_hierarchy; + HashSet? all_protocols_in_hierarchy; public IEnumerable AllProtocolsInHierarchy { get { if (all_protocols_in_hierarchy is null) { all_protocols_in_hierarchy = new HashSet (); var type = this; - while (type is not null && (object) type != (object) type.BaseType) { + while (type is not null && (object) type != (object?) type.BaseType) { var allProtocols = type.AllProtocols; if (allProtocols is not null) all_protocols_in_hierarchy.UnionWith (allProtocols); @@ -206,7 +209,7 @@ public IEnumerable AllProtocolsInHierarchy { } #endif - public void VerifyRegisterAttribute (ref List exceptions) + public void VerifyRegisterAttribute ([NotNullIfNotNull (nameof (exceptions))] ref List? exceptions) { if (RegisterAttribute is null) return; @@ -241,7 +244,7 @@ public void VerifyRegisterAttribute (ref List exceptions) // This list is duplicated in tests/mtouch/RegistrarTest.cs. // Update that list whenever this list is updated. static readonly char [] invalidSelectorCharacters = { ' ', '\t', '?', '\\', '!', '|', '@', '"', '\'', '%', '&', '/', '(', ')', '=', '^', '[', ']', '{', '}', ',', '.', ';', '-', '\n', '<', '>' }; - void VerifySelector (ObjCMethod method, ref List exceptions) + void VerifySelector (ObjCMethod method, [NotNullIfNotNull (nameof (exceptions))] ref List? exceptions) { if (method.Method is null) return; @@ -283,7 +286,7 @@ void VerifySelector (ObjCMethod method, ref List exceptions) } } - public void VerifyAdoptedProtocolsNames (ref List exceptions) + public void VerifyAdoptedProtocolsNames ([NotNullIfNotNull (nameof (exceptions))] ref List? exceptions) { if (AdoptedProtocols is null) return; @@ -311,7 +314,7 @@ public void VerifyAdoptedProtocolsNames (ref List exceptions) } } - public void Add (ObjCField field, ref List exceptions) + public void Add (ObjCField field, [NotNullIfNotNull (nameof (exceptions))] ref List? exceptions) { // Check if there are any base types with the same property. var base_type = BaseType; @@ -332,7 +335,7 @@ public void Add (ObjCField field, ref List exceptions) Fields.Add (fieldNameInDictionary, field); } - public bool Add (ObjCMethod method, ref List exceptions) + public bool Add (ObjCMethod method, [NotNullIfNotNull (nameof (exceptions))] ref List? exceptions) { bool rv; @@ -352,7 +355,7 @@ public bool Add (ObjCMethod method, ref List exceptions) return rv; } - public void Add (ObjCProperty property, ref List exceptions) + public void Add (ObjCProperty property, [NotNullIfNotNull (nameof (exceptions))] ref List? exceptions) { if (Properties is null) Properties = new List (); @@ -365,7 +368,7 @@ public void Add (ObjCProperty property, ref List exceptions) VerifyIsNotKeyword (ref exceptions, property); } - public static bool IsObjectiveCKeyword (string name) + public static bool IsObjectiveCKeyword (string? name) { switch (name) { case "auto": @@ -413,13 +416,13 @@ public static bool IsObjectiveCKeyword (string name) } } - void VerifyIsNotKeyword (ref List exceptions, ObjCProperty property) + void VerifyIsNotKeyword ([NotNullIfNotNull (nameof (exceptions))] ref List? exceptions, ObjCProperty property) { if (IsObjectiveCKeyword (property.Selector)) AddException (ref exceptions, CreateException (4164, property, Errors.MT4164, property.Name, property.Selector)); } - public bool TryGetMember (string selector, bool is_static, out ObjCMember member) + public bool TryGetMember (string selector, bool is_static, [NotNullWhen (true)] out ObjCMember? member) { if (is_static) selector = "+" + selector; @@ -428,14 +431,13 @@ public bool TryGetMember (string selector, bool is_static, out ObjCMember member return Map.TryGetValue (selector, out member); } - bool AddToMap (ObjCMember member, ref List exceptions, out bool alreadyAdded) + bool AddToMap (ObjCMember member, [NotNullIfNotNull (nameof (exceptions))] ref List? exceptions, out bool alreadyAdded) { - ObjCMember existing; bool rv = true; alreadyAdded = false; - if (TryGetMember (member.Selector, member.IsNativeStatic, out existing)) { + if (TryGetMember (member.Selector, member.IsNativeStatic, out var existing)) { if (existing is ObjCMethod existingMethod && member is ObjCMethod method && object.ReferenceEquals (method.Method, existingMethod.Method)) { // This can happen if we try to register: // * A property declared on a type (we register the getter + setter) @@ -455,7 +457,7 @@ bool AddToMap (ObjCMember member, ref List exceptions, out bool alrea return rv; } - Exception CreateException (int code, ObjCMember member, string message, params object [] args) + Exception CreateException (int code, ObjCMember member, string message, params object? [] args) { var method = member as ObjCMethod; if (method is not null) @@ -466,16 +468,16 @@ Exception CreateException (int code, ObjCMember member, string message, params o return Registrar.CreateException (code, message, args); } - public string Name { + public string? Name { get { return RegisterAttribute is not null && RegisterAttribute.Name is not null ? RegisterAttribute.Name : Registrar.GetTypeFullName (Type); } } - public string CategoryName { + public string? CategoryName { get { if (!IsCategory) throw new InvalidOperationException (); var attrib = CategoryAttribute; - var name = attrib.Name ?? Registrar.GetTypeFullName (Type); + var name = attrib?.Name ?? Registrar.GetTypeFullName (Type); return SanitizeObjectiveCName (name); } } @@ -484,21 +486,21 @@ public string ProtocolName { get { if (!IsProtocol) throw new InvalidOperationException (); - var attrib = Registrar.GetProtocolAttribute (Type); - var name = attrib.Name ?? Registrar.GetTypeFullName (Type); + var attrib = Registrar.GetProtocolAttribute (Type!); + var name = attrib?.Name ?? Registrar.GetTypeFullName (Type!); return SanitizeObjectiveCName (name); } } public string ExportedName { get { - return Registrar.GetExportedTypeName (Type, RegisterAttribute); + return Registrar.GetExportedTypeName (Type!, RegisterAttribute); } } public bool IsFakeProtocol { get { - if (RegisterAttribute is null || IsProtocol || IsModel) + if (RegisterAttribute is null || IsProtocol || IsModel || Type is null) return false; return Registrar.HasProtocolAttribute (Type); @@ -508,7 +510,7 @@ public bool IsFakeProtocol { /// /// This is the first parent type which is not a model. /// - public ObjCType SuperType { + public ObjCType? SuperType { get { if (superType is not null) return superType; @@ -523,15 +525,15 @@ public ObjCType SuperType { } abstract internal class ObjCMember { - public Registrar Registrar; - public ObjCType DeclaringType; - public string Name; - public ObjCType CategoryType; + public readonly Registrar Registrar; + public readonly ObjCType DeclaringType; + public string? Name; + public ObjCType? CategoryType; public ArgumentSemantic ArgumentSemantic = ArgumentSemantic.None; public bool IsVariadic; public bool IsOptional; - public bool SetExportAttribute (ExportAttribute ea, ref List exceptions) + public bool SetExportAttribute (ExportAttribute ea, [NotNullIfNotNull (nameof (exceptions))] ref List? exceptions) { if (string.IsNullOrEmpty (ea.Selector)) { AddException (ref exceptions, Registrar.CreateException (4135, this, Errors.MT4135, FullName)); @@ -543,9 +545,10 @@ public bool SetExportAttribute (ExportAttribute ea, ref List exceptio return true; } - public ObjCMember () - { - } + // public ObjCMember (Registrar registrar) + // { + // Registrar = registrar; + // } public ObjCMember (Registrar registrar, ObjCType declaringType) { @@ -553,9 +556,9 @@ public ObjCMember (Registrar registrar, ObjCType declaringType) DeclaringType = declaringType; } - string selector; + string? selector; public string Selector { - get { return selector; } + get { return selector!; } set { if (string.IsNullOrEmpty (value)) throw Registrar.CreateException (4135, this, Errors.MT4135, FullName); @@ -574,17 +577,17 @@ protected string ToSignature (TType type, ref bool success) } internal class ObjCMethod : ObjCMember { - public readonly TMethod Method; - string signature; + public readonly TMethod? Method; + string? signature; Trampoline trampoline; bool? is_static; bool? is_ctor; - TType [] parameters; - TType [] native_parameters; - TType return_type; - TType native_return_type; + TType []? parameters; + TType []? native_parameters; + TType? return_type; + TType? native_return_type; - public ObjCMethod (Registrar registrar, ObjCType declaringType, TMethod method) + public ObjCMethod (Registrar registrar, ObjCType declaringType, TMethod? method) : base (registrar, declaringType) { Method = method; @@ -592,7 +595,7 @@ public ObjCMethod (Registrar registrar, ObjCType declaringType, TMethod method) public string MethodName { get { - return Name ?? Registrar.GetMethodName (Method); + return Name ?? Registrar.GetMethodName (Method!); } } @@ -620,7 +623,7 @@ public override bool IsImplicit { public bool IsConstructor { get { if (!is_ctor.HasValue) - is_ctor = Registrar.IsConstructor (Method); + is_ctor = Registrar.IsConstructor (Method!); return is_ctor.Value; } set { @@ -687,10 +690,10 @@ public bool HasParameters { } } - public TType [] Parameters { + public TType []? Parameters { get { if (parameters is null) - parameters = Registrar.GetParameters (Method); + parameters = Registrar.GetParameters (Method!); return parameters; } set { @@ -699,12 +702,12 @@ public TType [] Parameters { } } - public TType [] NativeParameters { + public TType []? NativeParameters { get { if (native_parameters is null && Parameters is not null) { // Put the parameters in a temporary variable, and only store them in the instance field once done, // so that if an exception occurs, the same exception will be raised the next time too. - var native_parameters = new TType [parameters.Length]; + var native_parameters = new TType [parameters!.Length]; for (int i = 0; i < parameters.Length; i++) { var originalType = Registrar.GetBindAsAttribute (this, i)?.OriginalType; if (originalType is not null) { @@ -724,13 +727,11 @@ public TType [] NativeParameters { bool IsValidToManagedTypeConversion (TType inputType, TType outputType) { var nullableType = Registrar.GetNullableType (outputType); - var isNullable = nullableType is not null; - var arrayRank = 0; - var isArray = Registrar.IsArray (outputType, out arrayRank); + var isArray = Registrar.IsArray (outputType, out var arrayRank); TType underlyingOutputType = outputType; TType underlyingInputType = inputType; - if (isNullable) { + if (nullableType is not null) { underlyingOutputType = nullableType; } else if (isArray) { if (arrayRank != 1) @@ -797,21 +798,16 @@ bool IsValidToManagedTypeConversion (TType inputType, TType outputType) } } - bool IsValidToNativeTypeConversion (TType inputType, TType outputType) - { - return IsValidToManagedTypeConversion (inputType: outputType, outputType: inputType); - } - public bool HasReturnType { get { return return_type is not null; } } - public TType ReturnType { + public TType? ReturnType { get { if (return_type is null) - return_type = Registrar.GetReturnType (Method); + return_type = Registrar.GetReturnType (Method!); return return_type; } set { @@ -823,16 +819,16 @@ public TType ReturnType { public TType NativeReturnType { get { if (native_return_type is null) { - if (Registrar.Is (ReturnType, "System", "Void")) { - native_return_type = ReturnType; + if (Registrar.Is (ReturnType!, "System", "Void")) { + native_return_type = ReturnType!; } else { var originalType = Registrar.GetBindAsAttribute (this, -1)?.OriginalType; if (originalType is not null) { - if (!IsValidToManagedTypeConversion (originalType, ReturnType)) + if (!IsValidToManagedTypeConversion (originalType, ReturnType!)) throw Registrar.CreateException (4170, Method, Errors.MT4170, Registrar.GetTypeFullName (ReturnType), originalType.FullName, DescriptiveMethodName); native_return_type = originalType; } else { - native_return_type = ReturnType; + native_return_type = ReturnType!; } } } @@ -842,7 +838,7 @@ public TType NativeReturnType { // If the managed method is static. public bool IsStatic { - get { return is_static.HasValue ? is_static.Value : Registrar.IsStatic (Method); } + get { return is_static.HasValue ? is_static.Value : Registrar.IsStatic (Method!); } set { is_static = value; } } @@ -854,7 +850,7 @@ public override bool IsNativeStatic { public bool IsCategoryInstance { get { - return IsCategory && Registrar.HasThisAttribute (Method); + return IsCategory && Registrar.HasThisAttribute (Method!); } } @@ -864,7 +860,7 @@ public bool IsCategory { public bool RetainReturnValue { get { - return Registrar.HasReleaseAttribute (Method); + return Registrar.HasReleaseAttribute (Method!); } } @@ -946,7 +942,7 @@ public string Signature { } } - public bool ValidateSignature (ref List exceptions) + public bool ValidateSignature ([NotNullWhen (false)] [NotNullIfNotNull (nameof (exceptions))] ref List? exceptions) { if (Registrar.LaxMode) return true; @@ -987,20 +983,20 @@ public override string FullName { public bool IsPropertyAccessor { get { - return Registrar.IsPropertyAccessor (Method); + return Registrar.IsPropertyAccessor (Method!); } } } internal class ObjCProperty : ObjCMember { bool? is_static; - public TProperty Property; - TType property_type; + public TProperty? Property; + TType? property_type; public TType PropertyType { get { if (property_type is null) - property_type = Property.PropertyType; - return property_type; + property_type = Property?.PropertyType; + return property_type!; } set { property_type = value; @@ -1008,13 +1004,13 @@ public TType PropertyType { } bool? is_read_only; - public string GetterSelector; - public string SetterSelector; + public string? GetterSelector; + public string? SetterSelector; public bool IsReadOnly { get { if (!is_read_only.HasValue) - is_read_only = Registrar.GetSetMethod (Property) is null; + is_read_only = Registrar.GetSetMethod (Property!) is null; return is_read_only.Value; } set { @@ -1023,7 +1019,7 @@ public bool IsReadOnly { } public bool IsStatic { - get { return is_static.HasValue ? is_static.Value : Registrar.IsStatic (Property); } + get { return is_static.HasValue ? is_static.Value : Registrar.IsStatic (Property!); } set { is_static = value; } } @@ -1031,7 +1027,7 @@ public override bool IsNativeStatic { get { return IsStatic; } } - public ObjCProperty () : base () + public ObjCProperty (Registrar registrar, ObjCType declaringType) : base (registrar, declaringType) { } @@ -1048,12 +1044,17 @@ internal class ObjCField : ObjCMember { public byte Alignment; #else public bool IsPrivate; - public TProperty Property; + public TProperty? Property; #endif public string FieldType; public bool IsProperty; bool is_static; + public ObjCField (Registrar registrar, ObjCType declaringType, string fieldType) : base (registrar, declaringType) + { + FieldType = fieldType; + } + public override string FullName { get { return Registrar.GetTypeFullName (DeclaringType.Type) + "." + Name; @@ -1074,7 +1075,7 @@ protected virtual void OnRegisterType (ObjCType type) { } protected virtual void OnSkipType (TType type, ObjCType registered_type) { } protected virtual void OnReloadType (ObjCType type) { } protected virtual void OnRegisterProtocol (ObjCType type) { } - protected virtual void OnRegisterCategory (ObjCType type, ref List exceptions) { } + protected virtual void OnRegisterCategory (ObjCType type, [NotNullIfNotNull (nameof (exceptions))] ref List? exceptions) { } protected virtual bool SkipRegisterAssembly (TAssembly assembly) { return false; } @@ -1084,12 +1085,12 @@ protected virtual void OnRegisterCategory (ObjCType type, ref List ex protected abstract IEnumerable CollectConstructors (TType type); // Must return all instance ctors. May return static ctors too (they're automatically filtered out). protected abstract bool ContainsPlatformReference (TAssembly assembly); // returns true if the assembly is monotouch.dll too. - protected abstract TType GetBaseType (TType type); // for generic parameters it returns the first specific class constraint. - protected abstract TType [] GetInterfaces (TType type); // may return interfaces from base classes as well. May return null if no interfaces found. - protected virtual TType [] GetLinkedAwayInterfaces (TType type) { return null; } // may NOT return interfaces from base classes as well. May return null if no interfaces found. + protected abstract TType? GetBaseType (TType? type); // for generic parameters it returns the first specific class constraint. + protected abstract TType []? GetInterfaces (TType type); // may return interfaces from base classes as well. May return null if no interfaces found. + protected virtual TType []? GetLinkedAwayInterfaces (TType type) { return null; } // may NOT return interfaces from base classes as well. May return null if no interfaces found. protected abstract TMethod GetBaseMethod (TMethod method); - protected abstract TType [] GetParameters (TMethod method); - protected abstract string GetParameterName (TMethod method, int parameter_index); + protected abstract TType []? GetParameters (TMethod method); + protected abstract string GetParameterName (TMethod? method, int parameter_index); protected abstract TMethod GetGetMethod (TProperty property); protected abstract TMethod GetSetMethod (TProperty property); protected abstract TType GetSystemVoidType (); @@ -1104,22 +1105,22 @@ protected virtual void OnRegisterCategory (ObjCType type, ref List ex public abstract TType GetElementType (TType type); protected abstract TType GetReturnType (TMethod method); protected abstract void GetNamespaceAndName (TType type, out string @namespace, out string name); - protected abstract bool TryGetAttribute (TType type, string attributeNamespace, string attributeType, out object attribute); - protected abstract ExportAttribute GetExportAttribute (TProperty property); // Return null if no attribute is found. Must check the base property (i.e. if property is overriding a property in a base class, must check the overridden property for the attribute). - public abstract ExportAttribute GetExportAttribute (TMethod method); // Return null if no attribute is found. Must check the base method (i.e. if method is overriding a method in a base class, must check the overridden method for the attribute). - protected abstract Dictionary> PrepareMethodMapping (TType type); - public abstract RegisterAttribute GetRegisterAttribute (TType type); // Return null if no attribute is found. Do not consider base types. - public abstract CategoryAttribute GetCategoryAttribute (TType type); // Return null if no attribute is found. Do not consider base types. - protected abstract ConnectAttribute GetConnectAttribute (TProperty property); // Return null if no attribute is found. Do not consider inherited properties. - public abstract ProtocolAttribute GetProtocolAttribute (TType type); // Return null if no attribute is found. Do not consider base types. + protected abstract bool TryGetAttribute (TType type, string attributeNamespace, string attributeType, [NotNullWhen (true)] out object? attribute); + protected abstract ExportAttribute? GetExportAttribute (TProperty property); // Return null if no attribute is found. Must check the base property (i.e. if property is overriding a property in a base class, must check the overridden property for the attribute). + public abstract ExportAttribute? GetExportAttribute (TMethod method); // Return null if no attribute is found. Must check the base method (i.e. if method is overriding a method in a base class, must check the overridden method for the attribute). + protected abstract Dictionary>? PrepareMethodMapping (TType type); + public abstract RegisterAttribute? GetRegisterAttribute (TType type); // Return null if no attribute is found. Do not consider base types. + public abstract CategoryAttribute? GetCategoryAttribute (TType type); // Return null if no attribute is found. Do not consider base types. + protected abstract ConnectAttribute? GetConnectAttribute (TProperty property); // Return null if no attribute is found. Do not consider inherited properties. + public abstract ProtocolAttribute? GetProtocolAttribute (TType type); // Return null if no attribute is found. Do not consider base types. protected abstract IEnumerable GetProtocolMemberAttributes (TType type); // Return null if no attributes found. Do not consider base types. - protected virtual Version GetSdkIntroducedVersion (TType obj, out string message) { message = null; return null; } // returns the sdk version when the type was introduced for the current platform (null if all supported versions) + protected virtual Version? GetSdkIntroducedVersion (TType obj, out string? message) { message = null; return null; } // returns the sdk version when the type was introduced for the current platform (null if all supported versions) protected abstract Version GetSDKVersion (); - protected abstract TType GetProtocolAttributeWrapperType (TType type); // Return null if no attribute is found. Do not consider base types. - public abstract BindAsAttribute GetBindAsAttribute (TMethod method, int parameter_index); // If parameter_index = -1 then get the attribute for the return type. Return null if no attribute is found. Must consider base method. - public abstract BindAsAttribute GetBindAsAttribute (TProperty property); - protected abstract IList GetAdoptsAttributes (TType type); - public abstract TType GetNullableType (TType type); // For T? returns T. For T returns null. + protected abstract TType? GetProtocolAttributeWrapperType (TType type); // Return null if no attribute is found. Do not consider base types. + public abstract BindAsAttribute? GetBindAsAttribute (TMethod method, int parameter_index); // If parameter_index = -1 then get the attribute for the return type. Return null if no attribute is found. Must consider base method. + public abstract BindAsAttribute? GetBindAsAttribute (TProperty? property); + protected abstract IList? GetAdoptsAttributes (TType type); + public abstract TType? GetNullableType (TType type); // For T? returns T. For T returns null. public abstract bool HasReleaseAttribute (TMethod method); // Returns true of the method's return type/value has a [Release] attribute. protected abstract bool IsINativeObject (TType type); protected abstract bool IsValueType (TType type); @@ -1133,22 +1134,24 @@ protected virtual void OnRegisterCategory (ObjCType type, ref List ex protected abstract bool IsAbstract (TType type); protected abstract bool IsPointer (TType type); protected abstract TType GetGenericTypeDefinition (TType type); - public abstract bool VerifyIsConstrainedToNSObject (TType type, out TType constrained_type); - protected abstract TType GetEnumUnderlyingType (TType type); + public abstract bool VerifyIsConstrainedToNSObject (TType type, out TType? constrained_type); + protected abstract TType? GetEnumUnderlyingType (TType type); + protected abstract bool TryGetEnumUnderlyingType ([NotNullWhen (true)] TType? tr, [NotNullWhen (true)] out TType? underlyingType); protected abstract IEnumerable GetFields (TType type); // Must return all instance fields. May return static fields (they are filtered out automatically). protected abstract TType GetFieldType (TField field); protected abstract int GetValueTypeSize (TType type); protected abstract bool IsSimulatorOrDesktop { get; } protected abstract bool IsARM64 { get; } - protected abstract Exception CreateExceptionImpl (int code, bool error, Exception innerException, TMethod method, string message, params object [] args); - protected abstract Exception CreateExceptionImpl (int code, bool error, Exception innerException, TType type, string message, params object [] args); + protected abstract Exception CreateExceptionImpl (int code, bool error, Exception? innerException, TMethod? method, string message, params object? [] args); + protected abstract Exception CreateExceptionImpl (int code, bool error, Exception? innerException, TType? type, string message, params object? [] args); protected abstract string PlatformName { get; } public abstract TType FindType (TType relative, string @namespace, string name); - protected abstract IEnumerable FindMethods (TType type, string name); // will return null if nothing was found - protected abstract TProperty FindProperty (TType type, string name); // will return null if nothing was found + protected abstract IEnumerable? FindMethods (TType type, string name); // will return null if nothing was found + protected abstract TProperty? FindProperty (TType type, string name); // will return null if nothing was found protected abstract string GetAssemblyName (TAssembly assembly); - protected abstract string GetTypeFullName (TType type); + [return: NotNullIfNotNull (nameof (type))] + protected abstract string? GetTypeFullName (TType? type); protected abstract string GetAssemblyQualifiedName (TType type); protected abstract string GetTypeName (TType type); protected abstract string GetPropertyName (TProperty property); @@ -1160,9 +1163,16 @@ protected virtual void OnRegisterCategory (ObjCType type, ref List ex // used for Xamarin.iOS.dll. protected virtual bool LaxMode { get { return false; } } +#if LEGACY_TOOLS || BUNDLER + public Registrar (Application app) + { + App = app; + } +#else public Registrar () { } +#endif public static bool IsPropertyAccessor (TMethod method) { @@ -1179,7 +1189,7 @@ public static bool IsPropertyAccessor (TMethod method) return true; } - public bool IsPropertyAccessor (TMethod method, out TProperty property) + public bool IsPropertyAccessor (TMethod method, [NotNullWhen (true)] out TProperty? property) { property = null; @@ -1202,17 +1212,18 @@ protected bool IsEnum (TType type) return IsEnum (type, out dummy); } - public BindAsAttribute GetBindAsAttribute (ObjCMethod method, int parameter_index) + public BindAsAttribute? GetBindAsAttribute (ObjCMethod method, int parameter_index) { - var attrib = GetBindAsAttribute (method.Method, parameter_index); + var mthd = method.Method!; + var attrib = GetBindAsAttribute (mthd, parameter_index); if (attrib is not null) { - var type = parameter_index == -1 ? GetReturnType (method.Method) : GetParameters (method.Method) [parameter_index]; + var type = parameter_index == -1 ? GetReturnType (mthd) : GetParameters (mthd)! [parameter_index]; if (parameter_index == -1) { - var returnType = GetReturnType (method.Method); + var returnType = GetReturnType (mthd); if (!AreEqual (returnType, attrib.Type)) throw CreateException (4171, method.Method, Errors.MT4171, method.DescriptiveMethodName, GetTypeFullName (attrib.Type), GetTypeFullName (returnType)); } else { - var parameterType = GetParameters (method.Method) [parameter_index]; + var parameterType = GetParameters (mthd)! [parameter_index]; if (IsByRef (parameterType)) parameterType = GetElementType (parameterType); if (!AreEqual (parameterType, attrib.Type)) @@ -1227,7 +1238,7 @@ public BindAsAttribute GetBindAsAttribute (ObjCMethod method, int parameter_inde var property = FindProperty (method.DeclaringType.Type, method.MethodName.Substring (4)); attrib = GetBindAsAttribute (property); - if (attrib is not null) { + if (attrib is not null && property is not null) { var propertyType = GetPropertyType (property); if (!AreEqual (propertyType, attrib.Type)) throw CreateException (4171, property, Errors.MT4171_B, GetTypeFullName (method.DeclaringType.Type), GetPropertyName (property), GetTypeFullName (attrib.Type), GetTypeFullName (propertyType)); @@ -1237,11 +1248,10 @@ public BindAsAttribute GetBindAsAttribute (ObjCMethod method, int parameter_inde bool IsSmartEnum (TType type) { - TMethod getConstant, getValue; - return IsSmartEnum (type, out getConstant, out getValue); + return IsSmartEnum (type, out var _, out var _); } - public bool IsSmartEnum (TType type, out TMethod getConstantMethod, out TMethod getValueMethod) + public bool IsSmartEnum (TType type, [NotNullWhen (true)] out TMethod? getConstantMethod, [NotNullWhen (true)] out TMethod? getValueMethod) { getConstantMethod = null; getValueMethod = null; @@ -1254,6 +1264,8 @@ public bool IsSmartEnum (TType type, out TMethod getConstantMethod, out TMethod return false; var getConstantMethods = FindMethods (extension, "GetConstant"); + if (getConstantMethods is null) + return false; foreach (var m in getConstantMethods) { if (!Is (GetReturnType (m), Foundation, "NSString")) continue; @@ -1269,6 +1281,8 @@ public bool IsSmartEnum (TType type, out TMethod getConstantMethod, out TMethod return false; var getValueMethods = FindMethods (extension, "GetValue"); + if (getValueMethods is null) + return false; foreach (var m in getValueMethods) { if (!AreEqual (GetReturnType (m), type)) continue; @@ -1296,8 +1310,8 @@ protected string GetMemberName (ObjCMember member) } var property = member as ObjCProperty; if (property is not null) - return GetPropertyName (property.Property); - return ((ObjCField) member).Name; + return GetPropertyName (property.Property!); + return ((ObjCField) member).Name!; } internal static string Foundation { @@ -1381,67 +1395,67 @@ public Dictionary Types { } #endif - protected Exception CreateException (int code, string message, params object [] args) + protected Exception CreateException (int code, string message, params object? [] args) { return CreateExceptionImpl (code, true, message, args); } - protected Exception CreateException (int code, TMethod method, string message, params object [] args) + protected Exception CreateException (int code, TMethod? method, string message, params object? [] args) { return CreateExceptionImpl (code, true, method, message, args); } - protected Exception CreateException (int code, TProperty property, string message, params object [] args) + protected Exception CreateException (int code, TProperty? property, string message, params object? [] args) { return CreateExceptionImpl (code, true, property, message, args); } - protected Exception CreateException (int code, TType type, string message, params object [] args) + protected Exception CreateException (int code, TType? type, string message, params object? [] args) { return CreateExceptionImpl (code, true, type, message, args); } - protected Exception CreateException (int code, Exception innerException, TProperty property, string message, params object [] args) + protected Exception CreateException (int code, Exception? innerException, TProperty? property, string message, params object? [] args) { return CreateExceptionImpl (code, true, innerException, property, message, args); } - Exception CreateExceptionImpl (int code, bool error, string message, params object [] args) + Exception CreateExceptionImpl (int code, bool error, string message, params object? [] args) { - return CreateExceptionImpl (code, error, (TMethod) null, message, args); + return CreateExceptionImpl (code, error, (TMethod?) null, message, args); } - Exception CreateExceptionImpl (int code, bool error, TMethod method, string message, params object [] args) + Exception CreateExceptionImpl (int code, bool error, TMethod? method, string message, params object? [] args) { return CreateExceptionImpl (code, error, null, method, message, args); } - Exception CreateExceptionImpl (int code, bool error, TProperty property, string message, params object [] args) + Exception CreateExceptionImpl (int code, bool error, TProperty? property, string message, params object? [] args) { return CreateExceptionImpl (code, error, null, property, message, args); } - Exception CreateExceptionImpl (int code, bool error, TType type, string message, params object [] args) + Exception CreateExceptionImpl (int code, bool error, TType? type, string message, params object? [] args) { return CreateExceptionImpl (code, error, null, type, message, args); } - Exception CreateExceptionImpl (int code, bool error, Exception innerException, TProperty property, string message, params object [] args) + Exception CreateExceptionImpl (int code, bool error, Exception? innerException, TProperty? property, string message, params object? [] args) { if (property is null) - return CreateExceptionImpl (code, error, innerException, (TMethod) null, message, args); + return CreateExceptionImpl (code, error, innerException, (TMethod?) null, message, args); var getter = GetGetMethod (property); if (getter is not null) return CreateExceptionImpl (code, error, innerException, getter, message, args); return CreateExceptionImpl (code, error, innerException, GetSetMethod (property), message, args); } - Exception CreateException (int code, ObjCMember member, string message, params object [] args) + Exception CreateException (int code, ObjCMember? member, string message, params object? [] args) { return CreateExceptionImpl (code, true, member, message, args); } - Exception CreateExceptionImpl (int code, bool error, ObjCMember member, string message, params object [] args) + Exception CreateExceptionImpl (int code, bool error, ObjCMember? member, string message, params object? [] args) { var method = member as ObjCMethod; if (method is not null) @@ -1452,12 +1466,12 @@ Exception CreateExceptionImpl (int code, bool error, ObjCMember member, string m return CreateExceptionImpl (code, error, message, args); } - Exception CreateWarning (int code, ObjCMember member, string message, params object [] args) + Exception CreateWarning (int code, ObjCMember? member, string message, params object? [] args) { return CreateExceptionImpl (code, false, member, message, args); } - protected string GetDescriptiveMethodName (TMethod method) + protected string GetDescriptiveMethodName (TMethod? method) { if (method is null) return string.Empty; @@ -1478,7 +1492,7 @@ protected string GetDescriptiveMethodName (TMethod method) return sb.ToString (); } - string GetDescriptiveMethodName (TType type, TMethod method) + string GetDescriptiveMethodName (TType type, TMethod? method) { return GetTypeFullName (type) + "." + GetDescriptiveMethodName (method); } @@ -1517,23 +1531,21 @@ protected bool Is (TType type, string @namespace, string name) // do not check base types. protected virtual bool HasModelAttribute (TType type) { - object dummy; - return TryGetAttribute (type, Foundation, StringConstants.ModelAttribute, out dummy); + return TryGetAttribute (type, Foundation, StringConstants.ModelAttribute, out var _); } // overridable so that descendant classes can provide a faster implementation // do not check base types. public virtual bool HasProtocolAttribute (TType type) { - object dummy; - return TryGetAttribute (type, Foundation, StringConstants.ProtocolAttribute, out dummy); + return TryGetAttribute (type, Foundation, StringConstants.ProtocolAttribute, out var _); } // This method is thread-safe (locks 'types'). - public ObjCType RegisterType (TType type) + public ObjCType? RegisterType (TType type) { - ObjCType rv; - List exceptions = null; + ObjCType? rv; + List? exceptions = null; lock (types) { if (types.TryGetValue (type, out rv)) @@ -1549,13 +1561,13 @@ public ObjCType RegisterType (TType type) } // This method is thread-safe (locks 'types'). - public ObjCType RegisterType (TType type, ref List exceptions) + public ObjCType? RegisterType (TType type, [NotNullIfNotNull (nameof (exceptions))] ref List? exceptions) { lock (types) return RegisterTypeUnsafe (type, ref exceptions); } - bool VerifyNonGenericMethod (ref List exceptions, TType declaringType, TMethod method) + bool VerifyNonGenericMethod ([NotNullIfNotNull (nameof (exceptions))] ref List? exceptions, TType declaringType, TMethod method) { if (!IsGenericMethod (method)) return true; @@ -1565,23 +1577,23 @@ bool VerifyNonGenericMethod (ref List exceptions, TType declaringType return false; } - void VerifyInSdk (ref List exceptions, ObjCMethod method) + void VerifyInSdk ([NotNullIfNotNull (nameof (exceptions))] ref List? exceptions, ObjCMethod method) { if (method.HasReturnType || (method.Method is not null && !method.IsConstructor && method.NativeReturnType is not null)) VerifyTypeInSDK (ref exceptions, method.NativeReturnType, returnTypeOf: method); if (method.HasParameters || (method.Method is not null && method.Parameters is not null)) { - foreach (var p in method.Parameters) + foreach (var p in method.Parameters!) VerifyTypeInSDK (ref exceptions, p, parameterIn: method); } } - void VerifyInSdk (ref List exceptions, ObjCProperty property) + void VerifyInSdk ([NotNullIfNotNull (nameof (exceptions))] ref List? exceptions, ObjCProperty property) { VerifyTypeInSDK (ref exceptions, property.PropertyType, propertyTypeOf: property); } - void VerifyTypeInSDK (ref List exceptions, TType type, ObjCMethod parameterIn = null, ObjCMethod returnTypeOf = null, ObjCProperty propertyTypeOf = null, TType baseTypeOf = null) + void VerifyTypeInSDK ([NotNullIfNotNull (nameof (exceptions))] ref List? exceptions, TType type, ObjCMethod? parameterIn = null, ObjCMethod? returnTypeOf = null, ObjCProperty? propertyTypeOf = null, TType? baseTypeOf = null) { var sdkVersion = GetSdkIntroducedVersion (type, out var message); if (sdkVersion is null) @@ -1633,14 +1645,14 @@ void VerifyTypeInSDK (ref List exceptions, TType type, ObjCMethod par AddException (ref exceptions, ex); } - protected static void AddException (ref List exceptions, Exception mex) + protected static void AddException ([NotNull] ref List? exceptions, Exception mex) { if (exceptions is null) exceptions = new List (); exceptions.Add (mex); } - bool IsSubClassOf (TType type, string @namespace, string name) + bool IsSubClassOf (TType? type, string @namespace, string name) { while ((type = GetBaseType (type)) is not null) { string ns, n; @@ -1652,11 +1664,9 @@ bool IsSubClassOf (TType type, string @namespace, string name) return false; } - bool VerifyIsConstrainedToNSObject (ref List exceptions, TType type, ObjCMethod method) + bool VerifyIsConstrainedToNSObject ([NotNullIfNotNull (nameof (exceptions))] ref List? exceptions, TType type, ObjCMethod method) { - TType constrained_type = null; - - if (!VerifyIsConstrainedToNSObject (method.ReturnType, out constrained_type)) { + if (!VerifyIsConstrainedToNSObject (method.ReturnType!, out var constrained_type)) { AddException (ref exceptions, CreateException (4129, method.Method, Errors.MT4129, GetTypeFullName (method.ReturnType), GetDescriptiveMethodName (type, method.Method))); return false; } @@ -1667,7 +1677,7 @@ bool VerifyIsConstrainedToNSObject (ref List exceptions, TType type, if (pars is null) return true; - List types = null; + List? types = null; for (int i = 0; i < pars.Length; i++) { var p = pars [i]; if (!VerifyIsConstrainedToNSObject (p, out constrained_type)) { @@ -1698,7 +1708,7 @@ bool VerifyIsConstrainedToNSObject (ref List exceptions, TType type, // If the list contains {A,B}, this function will // null out the B entry to {A,null}, since A already // implements B. - void FlattenInterfaces (TType [] ifaces) + void FlattenInterfaces (TType? [] ifaces) { if (ifaces.Length == 1) return; @@ -1723,7 +1733,7 @@ void FlattenInterfaces (TType [] ifaces) } } - TType [] GetInterfacesImpl (ObjCType objcType) + TType? []? GetInterfacesImpl (ObjCType objcType) { // Both the dynamic and static registrars (i.e both Cecil and SRE) // return interfaces from all base classes as well. @@ -1759,17 +1769,18 @@ TType [] GetInterfacesImpl (ObjCType objcType) return allI; } - ObjCType [] GetProtocols (ObjCType type, ref List exceptions) + ObjCType []? GetProtocols (ObjCType type, [NotNullIfNotNull (nameof (exceptions))] ref List? exceptions) { var interfaces = GetInterfacesImpl (type); - List protocolList = null; + List? protocolList = null; if (interfaces?.Length > 0) { - var ifaceList = new List (interfaces); + var ifaceList = new List (interfaces); protocolList = new List (interfaces.Length); for (int i = 0; i < ifaceList.Count; i++) { - if (ifaceList [i] is null) + var iface = ifaceList [i]; + if (iface is null) continue; - var baseP = RegisterTypeUnsafe (ifaceList [i], ref exceptions); + var baseP = RegisterTypeUnsafe (iface, ref exceptions); if (baseP is not null) { if (baseP.IsInformalProtocol) { var ifaces = GetInterfacesImpl (baseP); @@ -1814,9 +1825,7 @@ ObjCType [] GetProtocols (ObjCType type, ref List exceptions) // but we still need to return information about it. // So create an ObjCType with just the required information, // and add that to what we return. - var objcType = new ObjCType () { - Registrar = this, - Type = iface, + var objcType = new ObjCType (this, iface) { IsProtocol = true, }; #if LEGACY_TOOLS || BUNDLER @@ -1832,7 +1841,7 @@ ObjCType [] GetProtocols (ObjCType type, ref List exceptions) return protocolList.ToArray (); } - string [] GetAdoptedProtocols (ObjCType type) + string []? GetAdoptedProtocols (ObjCType type) { var attribs = GetAdoptsAttributes (type.Type); if (attribs is null || attribs.Count == 0) @@ -1843,7 +1852,7 @@ string [] GetAdoptedProtocols (ObjCType type) return rv; } - ObjCType RegisterCategory (TType type, CategoryAttribute attrib, ref List exceptions) + ObjCType? RegisterCategory (TType type, CategoryAttribute attrib, [NotNullIfNotNull (nameof (exceptions))] ref List? exceptions) { if (IsINativeObject (type)) { AddException (ref exceptions, ErrorHelper.CreateError (4152, Errors.MT4152, GetTypeFullName (type))); @@ -1866,21 +1875,19 @@ ObjCType RegisterCategory (TType type, CategoryAttribute attrib, ref List exceptions) + ObjCType? RegisterTypeUnsafe (TType type, [NotNullIfNotNull (nameof (exceptions))] ref List? exceptions) { - ObjCType objcType; bool isGenericType = false; bool isProtocol = false; bool isInformalProtocol = false; @@ -1956,7 +1962,7 @@ ObjCType RegisterTypeUnsafe (TType type, ref List exceptions) isGenericType = true; } - if (types.TryGetValue (type, out objcType)) { + if (types.TryGetValue (type, out var objcType)) { OnReloadType (objcType); return objcType; } @@ -1974,12 +1980,12 @@ ObjCType RegisterTypeUnsafe (TType type, ref List exceptions) return null; if (isGenericType) { - exceptions.Add (ErrorHelper.CreateError (4148, Errors.MT4148, GetTypeFullName (type))); + AddException (ref exceptions, ErrorHelper.CreateError (4148, Errors.MT4148, GetTypeFullName (type))); return null; } // This is a protocol - var pAttr = GetProtocolAttribute (type); + var pAttr = GetProtocolAttribute (type)!; isInformalProtocol = pAttr.IsInformal; isProtocol = true; @@ -1991,7 +1997,7 @@ ObjCType RegisterTypeUnsafe (TType type, ref List exceptions) // make sure the base type is already registered var baseType = GetBaseType (type); - ObjCType baseObjCType = null; + ObjCType? baseObjCType = null; if (baseType is not null) { Trace ("Registering base type {0} of {1}", GetTypeName (baseType), GetTypeName (type)); baseObjCType = RegisterTypeUnsafe (baseType, ref exceptions); @@ -1999,14 +2005,13 @@ ObjCType RegisterTypeUnsafe (TType type, ref List exceptions) var register_attribute = GetRegisterAttribute (type); if (register_attribute is not null && register_attribute.SkipRegistration) { - OnSkipType (type, baseObjCType); + if (baseObjCType is not null) + OnSkipType (type, baseObjCType); return baseObjCType; } - objcType = new ObjCType () { - Registrar = this, + objcType = new ObjCType (this, type) { RegisterAttribute = GetRegisterAttribute (type), - Type = type, IsModel = HasModelAttribute (type), IsProtocol = isProtocol, IsInformalProtocol = isInformalProtocol, @@ -2032,11 +2037,13 @@ ObjCType RegisterTypeUnsafe (TType type, ref List exceptions) if (objcType.Protocols is not null) { foreach (var p in objcType.Protocols) { Trace ("Registering implemented protocol {0} of {1}", p is null ? "null" : p.ProtocolName, GetTypeName (type)); + if (p is null) + continue; OnRegisterProtocol (p); } } - TType previous_type; + TType? previous_type; if (objcType.IsProtocol) { lock (protocol_map) { if (protocol_map.TryGetValue (objcType.ExportedName, out previous_type)) @@ -2061,7 +2068,7 @@ ObjCType RegisterTypeUnsafe (TType type, ref List exceptions) bool is_first_nonWrapper = false; var methods = new List (CollectMethods (type)); if (!isProtocol) { - is_first_nonWrapper = !(objcType.IsWrapper || objcType.IsModel) && (objcType.BaseType.IsWrapper || objcType.BaseType.IsModel); + 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) { @@ -2144,9 +2151,7 @@ ObjCType RegisterTypeUnsafe (TType type, ref List exceptions) // Special fields if (is_first_nonWrapper) { // static registrar - objcType.Add (new ObjCField () { - DeclaringType = objcType, - FieldType = "XamarinObject",// "^v", // void* + objcType.Add (new ObjCField (this, objcType, "XamarinObject") { Name = "__monoObjectGCHandle", IsPrivate = true, IsStatic = false, @@ -2166,7 +2171,7 @@ ObjCType RegisterTypeUnsafe (TType type, ref List exceptions) // 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, + Selector = attrib.GetterSelector!, Parameters = new TType [] { }, ReturnType = attrib.PropertyType, IsStatic = attrib.IsStatic, @@ -2180,7 +2185,7 @@ ObjCType RegisterTypeUnsafe (TType type, ref List exceptions) var objcSetter = new ObjCMethod (this, objcType, null) { Name = attrib.Name, Selector = attrib.SetterSelector, - Parameters = new TType [] { attrib.PropertyType }, + Parameters = new TType [] { attrib.PropertyType! }, ReturnType = GetSystemVoidType (), IsStatic = attrib.IsStatic, IsOptional = !attrib.IsRequired, @@ -2189,30 +2194,28 @@ ObjCType RegisterTypeUnsafe (TType type, ref List exceptions) objcType.Add (objcSetter, ref exceptions); } } else { - var objcProperty = new ObjCProperty () { - Registrar = this, - DeclaringType = objcType, + var objcProperty = new ObjCProperty (this, objcType) { Property = null, Name = attrib.Name, - Selector = attrib.Selector, + 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, + PropertyType = attrib.PropertyType!, }; objcType.Add (objcProperty, ref exceptions); } } else { - TMethod method = null; + TMethod? method = null; #if LEGACY_TOOLS || BUNDLER method = attrib.Method; #endif var objcMethod = new ObjCMethod (this, objcType, method) { Name = attrib.Name, - Selector = attrib.Selector, + Selector = attrib.Selector!, ArgumentSemantic = attrib.ArgumentSemantic, IsVariadic = attrib.IsVariadic, ReturnType = attrib.ReturnType ?? GetSystemVoidType (), @@ -2224,7 +2227,7 @@ ObjCType RegisterTypeUnsafe (TType type, ref List exceptions) if (attrib.ParameterType is not null) { var parameters = new TType [attrib.ParameterType.Length]; for (int i = 0; i < parameters.Length; i++) { - if (attrib.ParameterByRef [i]) { + if (attrib.ParameterByRef! [i]) { parameters [i] = MakeByRef (attrib.ParameterType [i]); } else { parameters [i] = attrib.ParameterType [i]; @@ -2253,14 +2256,12 @@ ObjCType RegisterTypeUnsafe (TType type, ref List exceptions) continue; } - objcType.Add (new ObjCField () { - DeclaringType = objcType, + objcType.Add (new ObjCField (this, objcType, "@") { Name = ca.Name ?? GetPropertyName (property), #if !LEGACY_TOOLS && !BUNDLER Size = 8, Alignment = (byte) 3, #endif - FieldType = "@", IsProperty = true, IsStatic = IsStatic (property), #if LEGACY_TOOLS || BUNDLER @@ -2286,7 +2287,7 @@ ObjCType RegisterTypeUnsafe (TType type, ref List exceptions) continue; } - TType property_type = null; + TType? property_type = null; if (isGenericType && !VerifyIsConstrainedToNSObject (GetPropertyType (property), out property_type)) { AddException (ref exceptions, CreateException (4132, property, Errors.MT4132, GetTypeFullName (GetPropertyType (property)), GetTypeFullName (type), GetPropertyName (property))); continue; @@ -2296,9 +2297,7 @@ ObjCType RegisterTypeUnsafe (TType type, ref List exceptions) Trace (" [PROPERTY] {0} => {1}", property, ea.Selector); - var objcProperty = new ObjCProperty () { - Registrar = this, - DeclaringType = objcType, + var objcProperty = new ObjCProperty (this, objcType) { Property = property, Name = property.Name, Selector = ea.Selector ?? GetPropertyName (property), @@ -2316,9 +2315,9 @@ ObjCType RegisterTypeUnsafe (TType type, ref List exceptions) ReturnType = property_type, }; - List excs = null; + List? excs = null; if (!method.ValidateSignature (ref excs)) { - exceptions.Add (CreateException (4138, excs [0], property, Errors.MT4138, + AddException (ref exceptions, CreateException (4138, excs [0], property, Errors.MT4138, GetTypeFullName (property.PropertyType), property.DeclaringType.FullName, property.Name)); continue; } @@ -2326,7 +2325,7 @@ ObjCType RegisterTypeUnsafe (TType type, ref List exceptions) if (!objcType.Add (method, ref exceptions)) continue; - Trace (" [GET] {0}", objcType.Methods [objcType.Methods.Count - 1].Name); + Trace (" [GET] {0}", objcType.Methods? [objcType.Methods.Count - 1]?.Name); } if (setter is not null && VerifyNonGenericMethod (ref exceptions, type, setter)) { @@ -2338,9 +2337,9 @@ ObjCType RegisterTypeUnsafe (TType type, ref List exceptions) Parameters = new TType [] { property_type }, }; - List excs = null; + List? excs = null; if (!method.ValidateSignature (ref excs)) { - exceptions.Add (CreateException (4138, excs [0], property, Errors.MT4138, + AddException (ref exceptions, CreateException (4138, excs [0], property, Errors.MT4138, GetTypeFullName (property.PropertyType), property.DeclaringType.FullName, property.Name)); continue; } @@ -2348,7 +2347,7 @@ ObjCType RegisterTypeUnsafe (TType type, ref List exceptions) if (!objcType.Add (method, ref exceptions)) continue; - Trace (" [SET] {0}", objcType.Methods [objcType.Methods.Count - 1].Name); + Trace (" [SET] {0}", objcType.Methods? [objcType.Methods.Count - 1]?.Name); } objcType.Add (objcProperty, ref exceptions); @@ -2357,7 +2356,7 @@ ObjCType RegisterTypeUnsafe (TType type, ref List 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 || BUNDLER - ObjCMethod custom_copy_with_zone = null; + ObjCMethod? custom_copy_with_zone = null; var isNSCellSubclass = false; #if BUNDLER var isMac = App.Platform == ApplePlatform.MacOSX; @@ -2367,7 +2366,7 @@ ObjCType RegisterTypeUnsafe (TType type, ref List exceptions) if (isMac) isNSCellSubclass = IsSubClassOf (type, AppKit, "NSCell"); #endif - Dictionary> method_map = null; + Dictionary>? method_map = null; if (!isProtocol) method_map = PrepareMethodMapping (type); @@ -2379,8 +2378,7 @@ ObjCType RegisterTypeUnsafe (TType type, ref List exceptions) var ea = GetExportAttribute (method); if (ea is null) { - List impls; - if (method_map is not null && method_map.TryGetValue (method, out impls)) { + if (method_map is not null && method_map.TryGetValue (method, out var impls)) { if (impls.Count != 1) { foreach (var err in Shared.GetMT4127 (method, impls)) AddException (ref exceptions, err); @@ -2551,32 +2549,35 @@ public void RegisterAssembly (TAssembly assembly) } } - public string ComputeSignature (TType DeclaringType, TMethod Method, ObjCMember member = null, bool isCategoryInstance = false, bool isBlockSignature = false) + public string ComputeSignature (TType? DeclaringType, TMethod? Method, ObjCMember? member = null, bool isCategoryInstance = false, bool isBlockSignature = false) { bool is_ctor; var method = member as ObjCMethod; - TType return_type = null; + TType? return_type = null; if (Method is not null) { is_ctor = IsConstructor (Method); + if (!is_ctor) + return_type = GetReturnType (Method); + } else if (method is null) { + throw ErrorHelper.CreateError (99, Errors.MX0099, "ComputeSignature requires either a Method or an ObjCMethod."); } else { is_ctor = method.IsConstructor; + if (!is_ctor) + return_type = method.NativeReturnType; } - if (!is_ctor) - return_type = Method is not null ? GetReturnType (Method) : method.NativeReturnType; - - TType [] parameters; + TType []? parameters; if (Method is not null) { parameters = GetParameters (Method); } else { - parameters = method.NativeParameters; + parameters = method!.NativeParameters; } return ComputeSignature (DeclaringType, is_ctor, return_type, parameters, Method, member, isCategoryInstance, isBlockSignature); } - public string ComputeSignature (TType declaring_type, bool is_ctor, TType return_type, TType [] parameters, TMethod mi = null, ObjCMember member = null, bool isCategoryInstance = false, bool isBlockSignature = false) + public string ComputeSignature (TType? declaring_type, bool is_ctor, TType? return_type, TType []? parameters, TMethod? mi = null, ObjCMember? member = null, bool isCategoryInstance = false, bool isBlockSignature = false) { var success = true; var signature = new StringBuilder (); @@ -2586,7 +2587,7 @@ public string ComputeSignature (TType declaring_type, bool is_ctor, TType return if (is_ctor) { signature.Append ('@'); } else { - signature.Append (ToSignature (return_type, member, ref success)); + signature.Append (ToSignature (return_type!, member, ref success)); if (!success) throw CreateException (4104, mi, Errors.MT4104_A, GetTypeFullName (return_type), GetTypeFullName (declaring_type), GetDescriptiveMethodName (mi)); } @@ -2602,7 +2603,7 @@ public string ComputeSignature (TType declaring_type, bool is_ctor, TType return signature.Append ("^"); var elementType = GetElementType (type); if (IsNullable (elementType)) { - signature.Append (ToSignature (GetNullableType (elementType), member, ref success)); + signature.Append (ToSignature (GetNullableType (elementType)!, member, ref success)); } else { signature.Append (ToSignature (elementType, member, ref success)); } @@ -2614,7 +2615,7 @@ public string ComputeSignature (TType declaring_type, bool is_ctor, TType return // The input 'parameters' might be closed generic types, and thus might not correspond exactly with the source code. // By fetching the parameters from the method again, we attempt to report the parameter type as close as possible // to the source code. - parameters = GetParameters (mi); + parameters = GetParameters (mi)!; } throw CreateException (4136, mi, Errors.MT4136, GetTypeFullName (parameters [i]), GetParameterName (mi, i), GetTypeFullName (declaring_type), GetDescriptiveMethodName (mi)); @@ -2638,12 +2639,12 @@ protected string ToSignature (TType type, ObjCMember member, bool forProperty = throw ErrorHelper.CreateError (4101, Errors.MT4101, GetTypeFullName (type)); } - public string GetExportedTypeName (TType type, RegisterAttribute register_attribute) + public string GetExportedTypeName (TType type, RegisterAttribute? register_attribute) { - string name = null; + string? name = null; if (register_attribute is not null) { if (register_attribute.SkipRegistration) - return GetExportedTypeName (GetBaseType (type)); + return GetExportedTypeName (GetBaseType (type)!); name = register_attribute.Name; } if (name is null) @@ -2679,10 +2680,9 @@ string GetBoolEncoding () #endif } - protected string ToSignature (TType type, ObjCMember member, ref bool success, bool forProperty = false) + // 'member' is only used for diagnostic purposes. + protected string ToSignature (TType type, ObjCMember? member, ref bool success, bool forProperty = false) { - bool isNativeEnum; - var typeFullName = GetTypeFullName (type); switch (typeFullName) { @@ -2708,7 +2708,7 @@ protected string ToSignature (TType type, ObjCMember member, ref bool success, b case "System.nuint": return "Q"; case "System.DateTime": - throw CreateException (4102, member, Errors.MT4102, "System.DateTime", "Foundation.NSDate", member.FullName); + throw CreateException (4102, member, Errors.MT4102, "System.DateTime", "Foundation.NSDate", member?.FullName); } if (typeFullName == NFloatTypeName) @@ -2722,7 +2722,7 @@ protected string ToSignature (TType type, ObjCMember member, ref bool success, b if (IsINativeObject (type)) { if (!IsGenericType (type) && !IsInterface (type) && !IsNSObject (type) && IsAbstract (type)) - ErrorHelper.Show (CreateWarning (4179, member, Errors.MT4179, type.FullName, member.FullName)); + ErrorHelper.Show (CreateWarning (4179, member, Errors.MT4179, type.FullName, member?.FullName)); if (IsNSObject (type) && forProperty) { return "@\"" + GetExportedTypeName (type) + "\""; } else { @@ -2733,9 +2733,8 @@ protected string ToSignature (TType type, ObjCMember member, ref bool success, b if (IsDelegate (type)) return "^v"; - if (IsEnum (type, out isNativeEnum)) { - return ToSignature (GetEnumUnderlyingType (type), member, ref success); - } + if (TryGetEnumUnderlyingType (type, out var underlyingType)) + return ToSignature (underlyingType, member, ref success); if (IsValueType (type)) return ValueTypeSignature (type, member, ref success); @@ -2758,7 +2757,8 @@ string ValueTypeSignature (TType type, ObjCMember member) return ValueTypeSignature (type, member, ref success); } - string ValueTypeSignature (TType type, ObjCMember member, ref bool success) + // 'member' is only used for diagnostic purposes. + string ValueTypeSignature (TType type, ObjCMember? member, ref bool success) { var signature = new StringBuilder (); signature.Append ("{"); @@ -2809,7 +2809,7 @@ protected virtual void ReportWarning (int code, string message, params object [] R.NSLog (ErrorHelper.CreateWarning (code, message, args).ToString ()); } - static StringBuilder trace; + static StringBuilder? trace; [Conditional ("VERBOSE_REGISTRAR")] public static void FlushTrace () @@ -2825,7 +2825,7 @@ public static void FlushTrace () } [Conditional ("VERBOSE_REGISTRAR")] - public static void Trace (string msg, params object [] args) + public static void Trace (string msg, params object? [] args) { if (trace is null) trace = new StringBuilder (); diff --git a/tools/common/ErrorHelper.tools.cs b/tools/common/ErrorHelper.tools.cs index 9f3f5e464ba2..cbfef0ddb7d0 100644 --- a/tools/common/ErrorHelper.tools.cs +++ b/tools/common/ErrorHelper.tools.cs @@ -118,87 +118,87 @@ public static void SetLocation (Application app, ProductException ex, MethodDefi ex.LineNumber = seq.StartLine; } - public static ProductException CreateError (Application app, int code, MemberReference member, string message, params object [] args) + public static ProductException CreateError (Application app, int code, MemberReference? member, string message, params object? [] args) { return Create (app, code, true, null, member, null, message, args); } - public static ProductException CreateError (Application app, int code, MethodDefinition location, string message, params object [] args) + public static ProductException CreateError (Application app, int code, MethodDefinition? location, string message, params object? [] args) { return Create (app, code, true, null, location, null, message, args); } - public static ProductException CreateError (Application app, int code, MethodDefinition location, Instruction instruction, string message, params object [] args) + public static ProductException CreateError (Application app, int code, MethodDefinition? location, Instruction? instruction, string message, params object? [] args) { return Create (app, code, true, null, location, instruction, message, args); } - public static ProductException CreateError (Application app, int code, ICustomAttributeProvider provider, string message, params object [] args) + public static ProductException CreateError (Application app, int code, ICustomAttributeProvider? provider, string message, params object? [] args) { return Create (app, code, true, null, provider, null, message, args); } - public static ProductException CreateError (Application app, int code, Exception innerException, MethodDefinition location, string message, params object [] args) + public static ProductException CreateError (Application app, int code, Exception? innerException, MethodDefinition? location, string message, params object? [] args) { return Create (app, code, true, innerException, location, message, args); } - public static ProductException CreateError (Application app, int code, Exception innerException, TypeReference location, string message, params object [] args) + public static ProductException CreateError (Application app, int code, Exception? innerException, TypeReference? location, string message, params object? [] args) { return Create (app, code, true, innerException, location, message, args); } - public static ProductException CreateError (Application app, int code, Exception innerException, ICustomAttributeProvider provider, string message, params object [] args) + public static ProductException CreateError (Application app, int code, Exception? innerException, ICustomAttributeProvider? provider, string message, params object? [] args) { return Create (app, code, true, innerException, provider, message, args); } - public static ProductException CreateWarning (Application app, int code, MemberReference member, string message, params object [] args) + public static ProductException CreateWarning (Application app, int code, MemberReference? member, string message, params object? [] args) { return Create (app, code, false, null, member, null, message, args); } - public static ProductException CreateWarning (Application app, int code, MemberReference member, Instruction? instruction, string message, params object [] args) + public static ProductException CreateWarning (Application app, int code, MemberReference? member, Instruction? instruction, string message, params object? [] args) { return Create (app, code, false, null, member, instruction, message, args); } - public static ProductException CreateWarning (Application app, int code, MethodDefinition location, string message, params object [] args) + public static ProductException CreateWarning (Application app, int code, MethodDefinition? location, string message, params object? [] args) { return Create (app, code, false, null, location, message, args); } - public static ProductException CreateWarning (Application app, int code, ICustomAttributeProvider provider, string message, params object [] args) + public static ProductException CreateWarning (Application app, int code, ICustomAttributeProvider? provider, string message, params object? [] args) { return Create (app, code, false, null, provider, message, args); } - public static ProductException CreateWarning (Application app, int code, Exception innerException, MethodDefinition location, string message, params object [] args) + public static ProductException CreateWarning (Application app, int code, Exception? innerException, MethodDefinition? location, string message, params object? [] args) { return Create (app, code, false, innerException, location, message, args); } - public static ProductException CreateWarning (Application app, int code, Exception innerException, MethodDefinition location, Instruction instruction, string message, params object [] args) + public static ProductException CreateWarning (Application app, int code, Exception? innerException, MethodDefinition? location, Instruction? instruction, string message, params object? [] args) { return Create (app, code, false, innerException, location, instruction, message, args); } - public static ProductException CreateWarning (Application app, int code, Exception innerException, TypeReference location, string message, params object [] args) + public static ProductException CreateWarning (Application app, int code, Exception? innerException, TypeReference? location, string message, params object? [] args) { return Create (app, code, false, innerException, location, message, args); } - public static ProductException CreateWarning (Application app, int code, Exception innerException, ICustomAttributeProvider provider, string message, params object [] args) + public static ProductException CreateWarning (Application app, int code, Exception? innerException, ICustomAttributeProvider? provider, string message, params object? [] args) { return Create (app, code, false, innerException, provider, message, args); } - public static ProductException Create (Application app, int code, bool error, Exception? innerException, ICustomAttributeProvider provider, string message, params object [] args) + public static ProductException Create (Application app, int code, bool error, Exception? innerException, ICustomAttributeProvider? provider, string message, params object? [] args) { return Create (app, code, error, innerException, provider, null, message, args); } - public static ProductException Create (Application app, int code, bool error, Exception? innerException, ICustomAttributeProvider provider, Instruction? instruction, string message, params object [] args) + public static ProductException Create (Application app, int code, bool error, Exception? innerException, ICustomAttributeProvider? provider, Instruction? instruction, string message, params object? [] args) { if (provider is MemberReference member) { if (instruction is not null) @@ -212,7 +212,7 @@ public static ProductException Create (Application app, int code, bool error, Ex return new ProductException (code, error, innerException, message, args); } - public static ProductException Create (Application app, int code, bool error, Exception? innerException, MemberReference member, Instruction? instruction, string message, params object [] args) + public static ProductException Create (Application app, int code, bool error, Exception? innerException, MemberReference? member, Instruction? instruction, string message, params object? [] args) { var method = member as MethodReference; if (method is null) { @@ -226,7 +226,7 @@ public static ProductException Create (Application app, int code, bool error, Ex return Create (app, code, error, innerException, method is null ? null : method.Resolve (), instruction, message, args); } - public static ProductException Create (Application app, int code, bool error, Exception? innerException, MethodDefinition? location, Instruction? instruction, string message, params object [] args) + public static ProductException Create (Application app, int code, bool error, Exception? innerException, MethodDefinition? location, Instruction? instruction, string message, params object? [] args) { var e = new ProductException (code, error, innerException, message, args); if (location is not null) @@ -234,7 +234,7 @@ public static ProductException Create (Application app, int code, bool error, Ex return e; } - public static ProductException Create (Application app, int code, bool error, Exception? innerException, TypeReference? location, string message, params object [] args) + public static ProductException Create (Application app, int code, bool error, Exception? innerException, TypeReference? location, string message, params object? [] args) { var e = new ProductException (code, error, innerException, message, args); if (location is not null) { diff --git a/tools/common/StaticRegistrar.cs b/tools/common/StaticRegistrar.cs index aa1c152f96ab..d3b8dd234c6b 100644 --- a/tools/common/StaticRegistrar.cs +++ b/tools/common/StaticRegistrar.cs @@ -533,7 +533,7 @@ public static bool IsDelegate (TypeDefinition? type) if (type.FullName == "System.Delegate") return true; - type = type.BaseType?.Resolve (); + type = type?.BaseType?.Resolve (); } return false; @@ -678,8 +678,8 @@ bool IsAttributeMatch (ICustomAttribute attribute, string @namespace, string nam } public StaticRegistrar (Application app) + : base (app) { - this.App = app; this.input_assemblies = []; trace = !LaxMode && (app.RegistrarOptions & RegistrarOptions.Trace) == RegistrarOptions.Trace; } @@ -804,12 +804,12 @@ protected override bool IsARM64 { } } - protected override Exception CreateExceptionImpl (int code, bool error, Exception innerException, MethodDefinition method, string message, params object [] args) + protected override Exception CreateExceptionImpl (int code, bool error, Exception? innerException, MethodDefinition? method, string message, params object? [] args) { return ErrorHelper.Create (App, code, error, innerException, method, message, args); } - protected override Exception CreateExceptionImpl (int code, bool error, Exception innerException, TypeReference type, string message, params object [] args) + protected override Exception CreateExceptionImpl (int code, bool error, Exception? innerException, TypeReference? type, string message, params object? [] args) { return ErrorHelper.Create (App, code, error, innerException, type, message, args); } @@ -898,9 +898,9 @@ protected override string GetAssemblyName (AssemblyDefinition assembly) return assembly.Name.Name; } - protected override string GetTypeFullName (TypeReference type) + protected override string? GetTypeFullName (TypeReference? type) { - return type.FullName; + return type?.FullName; } protected override string GetMethodName (MethodDefinition method) @@ -1235,8 +1235,11 @@ protected override bool IsINativeObject (TypeReference tr) return IsNativeObject (tr); } - protected override TypeReference? GetBaseType (TypeReference tr) + protected override TypeReference? GetBaseType (TypeReference? tr) { + if (tr is null) + return null; + var gp = tr as GenericParameter; if (gp is not null) { foreach (var constr in gp.Constraints) { @@ -1261,7 +1264,7 @@ protected override MethodDefinition GetBaseMethod (MethodDefinition method) return GetEnumUnderlyingType (type); } - bool TryGetEnumUnderlyingType ([NotNullWhen (true)] TypeReference? tr, [NotNullWhen (true)] out TypeReference? underlyingType) + protected override bool TryGetEnumUnderlyingType ([NotNullWhen (true)] TypeReference? tr, [NotNullWhen (true)] out TypeReference? underlyingType) { underlyingType = null; @@ -1286,7 +1289,7 @@ bool TryGetEnumUnderlyingType ([NotNullWhen (true)] TypeReference? tr, [NotNullW return types; } - protected override string GetParameterName (MethodDefinition method, int parameter_index) + protected override string GetParameterName (MethodDefinition? method, int parameter_index) { if (method is null) return "?"; @@ -1706,9 +1709,9 @@ bool CollectAvailabilityAttributes (IEnumerable attributes, ou return null; } - protected override Version? GetSDKVersion () + protected override Version GetSDKVersion () { - return App.SdkVersion; + return App.SdkVersion!; } protected override Dictionary>? PrepareMethodMapping (TypeReference type) @@ -1785,7 +1788,7 @@ static NativeNameAttribute CreateNativeNameAttribute (ICustomAttribute attrib, T } } - public override BindAsAttribute? GetBindAsAttribute (PropertyDefinition property) + public override BindAsAttribute? GetBindAsAttribute (PropertyDefinition? property) { if (property is null) return null; @@ -2182,7 +2185,7 @@ void CheckNamespace (string ns, List exceptions) header.WriteLine ("#import {0}", h); } - string CheckStructure (TypeDefinition structure, string descriptiveMethodName, MemberReference inMember) + string CheckStructure (TypeDefinition structure, string descriptiveMethodName, MemberReference? inMember) { if (declarations is null) throw ErrorHelper.CreateError (99, Errors.MX0099, "No declarations?"); @@ -2204,7 +2207,7 @@ string CheckStructure (TypeDefinition structure, string descriptiveMethodName, M return n; } - void ProcessStructure (StringBuilder name, AutoIndentStringBuilder body, TypeDefinition structure, ref int size, string descriptiveMethodName, TypeDefinition root_structure, MemberReference inMember) + void ProcessStructure (StringBuilder name, AutoIndentStringBuilder body, TypeDefinition structure, ref int size, string descriptiveMethodName, TypeDefinition root_structure, MemberReference? inMember) { switch (structure.FullName) { case "System.Char": @@ -2308,7 +2311,7 @@ string GetUniqueTrampolineName (string suggestion) // Some declarations can be generalized to NSObject for its subclasses // (and System.String too as we convert it into an NSString) // since the generated code, except the function signature, is identical anyway - string ToSimpleObjCParameterType (TypeReference type, string descriptiveMethodName, List exceptions, MemberReference inMethod) + string ToSimpleObjCParameterType (TypeReference type, string descriptiveMethodName, List exceptions, MemberReference? inMethod) { var byref = type.IsByReference; var t = byref ? type.GetElementType () : type; @@ -2318,7 +2321,7 @@ string ToSimpleObjCParameterType (TypeReference type, string descriptiveMethodNa return ToObjCParameterType (type, descriptiveMethodName, exceptions, inMethod); } - string ToObjCParameterType (TypeReference type, string descriptiveMethodName, List exceptions, MemberReference inMethod, bool delegateToBlockType = false, bool cSyntaxForBlocks = false) + string ToObjCParameterType (TypeReference type, string descriptiveMethodName, List exceptions, MemberReference? inMethod, bool delegateToBlockType = false, bool cSyntaxForBlocks = false) { var gp = type as GenericParameter; if (gp is not null) @@ -2532,7 +2535,7 @@ string GetObjCSignature (ObjCMethod method, List exceptions) sb.Append (split [i]); sb.Append (':'); sb.Append ('('); - sb.Append (ToObjCParameterType (method.NativeParameters [i + indexOffset], method.DescriptiveMethodName, exceptions, method.Method, delegateToBlockType: true)); + sb.Append (ToObjCParameterType (method.NativeParameters! [i + indexOffset], method.DescriptiveMethodName, exceptions, method.Method, delegateToBlockType: true)); sb.Append (')'); sb.AppendFormat ("p{0}", i); } @@ -2915,7 +2918,7 @@ void Specialize (AutoIndentStringBuilder sb, out string initialization_method) if (@class.IsCategory) { var exportedName = EncodeNonAsciiCharacters (@class.BaseType!.ExportedName); - iface.Write ("@interface {0} ({1})", exportedName, @class.CategoryName); + iface.Write ("@interface {0} ({1})", exportedName, @class.CategoryName!); declarations.AppendFormat ("@class {0};\n", exportedName); } else if (is_protocol) { var exportedName = EncodeNonAsciiCharacters (@class.ProtocolName); @@ -2925,7 +2928,7 @@ void Specialize (AutoIndentStringBuilder sb, out string initialization_method) var is_stub_class = @class.RegisterAttribute?.IsStubClass; if (is_stub_class == true) iface.WriteLine ("__attribute__((objc_class_stub)) __attribute__((objc_subclassing_restricted))"); - iface.Write ("@interface {0} : {1}", class_name, EncodeNonAsciiCharacters (@class.SuperType.ExportedName)); + iface.Write ("@interface {0} : {1}", class_name, EncodeNonAsciiCharacters (@class.SuperType!.ExportedName)); declarations.AppendFormat ("@class {0};\n", class_name); } var implementedProtocols = new HashSet (); @@ -2989,7 +2992,7 @@ void Specialize (AutoIndentStringBuilder sb, out string initialization_method) default: throw ErrorHelper.CreateError (4120, Errors.MT4120, field.FieldType, field.DeclaringType.Type.FullName, field.Name); } - fields.Write (field.Name); + fields.Write (field.Name!); fields.WriteLine (";"); } catch (Exception ex) { exceptions.Add (ex); @@ -3056,7 +3059,7 @@ void Specialize (AutoIndentStringBuilder sb, out string initialization_method) exceptions.Add (ex); } catch (Exception ex) { skip.Add (method); - exceptions.Add (ErrorHelper.CreateError (4114, ex, Errors.MT4114, method.DeclaringType.Type.FullName, method.Method.Name)); + exceptions.Add (ErrorHelper.CreateError (4114, ex, Errors.MT4114, method.DeclaringType.Type.FullName, method.Method?.Name)); } } } @@ -3074,7 +3077,7 @@ void Specialize (AutoIndentStringBuilder sb, out string initialization_method) sb.WriteLine ("#pragma clang diagnostic ignored \"-Wobjc-property-implementation\""); } if (@class.IsCategory) { - sb.WriteLine ("@implementation {0} ({1})", EncodeNonAsciiCharacters (@class.BaseType!.ExportedName), @class.CategoryName); + sb.WriteLine ("@implementation {0} ({1})", EncodeNonAsciiCharacters (@class.BaseType!.ExportedName), @class.CategoryName!); } else { sb.WriteLine ("@implementation {0} {{", class_name); if (implementation_fields is not null) { @@ -3155,7 +3158,7 @@ void Specialize (AutoIndentStringBuilder sb, out string initialization_method) var ordered = protocol_wrapper_map.OrderBy ((v) => v.Key); map.AppendLine ("static const MTProtocolWrapperMap __xamarin_protocol_wrapper_map [] = {"); foreach (var p in ordered) { - map.AppendLine ("{{ 0x{0:X} /* {1} */, 0x{2:X} /* {3} */ }},", p.Key, p.Value.Item1.Name, p.Value.Item2, p.Value.Item1.ProtocolWrapperType.Name); + map.AppendLine ("{{ 0x{0:X} /* {1} */, 0x{2:X} /* {3} */ }},", p.Key, p.Value.Item1.Name!, p.Value.Item2, p.Value.Item1.ProtocolWrapperType!.Name); } map.AppendLine ("};"); map.AppendLine (); @@ -3361,9 +3364,9 @@ bool SpecializeTrampoline (AutoIndentStringBuilder sb, ObjCMethod method, List exceptions) { // prepare the parameters - var baseMethod = GetBaseMethodInTypeHierarchy (method.Method); + var mthd = method.Method!; + var baseMethod = GetBaseMethodInTypeHierarchy (mthd); for (int i = 0; i < num_arg; i++) { - var param = method.Method.Parameters [i]; + var param = mthd.Parameters [i]; var paramBase = baseMethod.Parameters [i]; - var type = method.Parameters [i]; - var nativetype = method.NativeParameters [i]; - var objctype = ToObjCParameterType (nativetype, descriptiveMethodName, exceptions, method.Method); + var type = method.Parameters! [i]; + var nativetype = method.NativeParameters! [i]; + var objctype = ToObjCParameterType (nativetype, descriptiveMethodName, exceptions, mthd); var original_objctype = objctype; var isRef = type.IsByReference; var isOut = param.IsOut || paramBase.IsOut; @@ -3856,10 +3860,10 @@ void Specialize (AutoIndentStringBuilder sb, ObjCMethod method, List var returntype = method.ReturnType; var isStatic = method.IsStatic; var isInstanceCategory = method.IsCategoryInstance; - var num_arg = method.Method.HasParameters ? method.Method.Parameters.Count : 0; + var num_arg = method.Method!.HasParameters ? method.Method.Parameters.Count : 0; var descriptiveMethodName = method.DescriptiveMethodName; var name = GetUniqueTrampolineName ("native_to_managed_trampoline_" + descriptiveMethodName); - var isVoid = returntype.FullName == "System.Void"; + var isVoid = returntype?.FullName == "System.Void"; var merge_bodies = true; if (!TryGetReturnType (method, descriptiveMethodName, exceptions, out var rettype, out var isCtor)) @@ -4144,7 +4148,7 @@ void Specialize (AutoIndentStringBuilder sb, ObjCMethod method, List var objc_signature = new StringBuilder ().Append (rettype).Append (":"); if (method.Method.HasParameters) { - for (int i = 0; i < method.NativeParameters.Length; i++) + for (int i = 0; i < method.NativeParameters!.Length; i++) objc_signature.Append (ToSimpleObjCParameterType (method.NativeParameters [i], descriptiveMethodName, exceptions, method.Method)).Append (":"); } @@ -4162,9 +4166,9 @@ void Specialize (AutoIndentStringBuilder sb, ObjCMethod method, List if (merge_bodies) { methods.Append ("static "); methods.Append (rettype).Append (" ").Append (b.Name).Append (" (id self, SEL _cmd, MonoMethod **managed_method_ptr"); - var pcount = method.Method.HasParameters ? method.NativeParameters.Length : 0; + var pcount = method.Method.HasParameters ? method.NativeParameters!.Length : 0; for (int i = (isInstanceCategory ? 1 : 0); i < pcount; i++) { - methods.Append (", ").Append (ToSimpleObjCParameterType (method.NativeParameters [i], descriptiveMethodName, exceptions, method.Method)); + methods.Append (", ").Append (ToSimpleObjCParameterType (method.NativeParameters! [i], descriptiveMethodName, exceptions, method.Method)); methods.Append (" ").Append ("p").Append (i.ToString ()); } if (isCtor) @@ -4223,7 +4227,7 @@ void GenerateCallToUnmanagedCallersOnlyMethod (AutoIndentStringBuilder sb, ObjCM // method (we store the result in a static variable, so that we only do this once // per method, the first time it's called). var staticCall = App.IsAOTCompiled (method.DeclaringType.Type.Module.Assembly.Name.Name); - if (!App.Configuration.AssemblyTrampolineInfos.TryFindInfo (method.Method, out var pinvokeMethodInfo)) { + if (!App.Configuration.AssemblyTrampolineInfos.TryFindInfo (method.Method!, out var pinvokeMethodInfo)) { exceptions.Add (ErrorHelper.CreateError (99, "Could not find the managed callback for {0}", descriptiveMethodName)); return; } @@ -4257,7 +4261,7 @@ void GenerateCallToUnmanagedCallersOnlyMethod (AutoIndentStringBuilder sb, ObjCM var indexOffset = method.IsCategoryInstance ? 1 : 0; for (var i = indexOffset; i < num_arg; i++) { sb.Append (", "); - var parameterType = ToObjCParameterType (method.NativeParameters [i], method.DescriptiveMethodName, exceptions, method.Method, delegateToBlockType: true, cSyntaxForBlocks: true); + var parameterType = ToObjCParameterType (method.NativeParameters! [i], method.DescriptiveMethodName, exceptions, method.Method, delegateToBlockType: true, cSyntaxForBlocks: true); var containsBlock = parameterType.Contains ("%PARAMETERNAME%"); parameterType = parameterType.Replace ("%PARAMETERNAME%", $"p{i - indexOffset}"); sb.Append (parameterType); @@ -4291,7 +4295,7 @@ void GenerateCallToUnmanagedCallersOnlyMethod (AutoIndentStringBuilder sb, ObjCM if (!staticCall) { sb.WriteLine ($"static {ucoEntryPoint}_function {ucoEntryPoint};"); - sb.WriteLine ($"xamarin_registrar_dlsym ((void **) &{ucoEntryPoint}, \"{method.Method.Module.Assembly.Name.Name}\", \"{ucoEntryPoint}\", {pinvokeMethodInfo.Id});"); + sb.WriteLine ($"xamarin_registrar_dlsym ((void **) &{ucoEntryPoint}, \"{method.Method!.Module.Assembly.Name.Name}\", \"{ucoEntryPoint}\", {pinvokeMethodInfo.Id});"); } if (hasReturnType) sb.Write ("rv = "); @@ -4326,7 +4330,7 @@ void GenerateCallToUnmanagedCallersOnlyMethod (AutoIndentStringBuilder sb, ObjCM void SpecializePrepareReturnValue (AutoIndentStringBuilder sb, ObjCMethod method, string descriptiveMethodName, string rettype, List exceptions) { var returntype = method.ReturnType; - var isVoid = returntype.FullName == "System.Void"; + var isVoid = returntype!.FullName == "System.Void"; if (isVoid) return; @@ -4446,7 +4450,7 @@ void SpecializePrepareReturnValue (AutoIndentStringBuilder sb, ObjCMethod method void GenerateCallToSuperForConstructor (AutoIndentStringBuilder sb, ObjCMethod method, List exceptions) { sb.WriteLine ("if (call_super && rv) {"); - sb.Write ("struct objc_super super = { rv, [").Write (method.DeclaringType.SuperType.ExportedName).WriteLine (" class] };"); + sb.Write ("struct objc_super super = { rv, [").Write (method.DeclaringType.SuperType!.ExportedName).WriteLine (" class] };"); sb.Write ("rv = ((id (*)(objc_super*, SEL"); if (method.Parameters is not null) { @@ -4520,7 +4524,7 @@ public TypeDefinition GetInstantiableType (TypeDefinition td, List ex public TypeDefinition? GetDelegateProxyType (ObjCMethod obj_method) { - return GetDelegateProxyType (obj_method.Method, obj_method); + return GetDelegateProxyType (obj_method.Method!, obj_method); } public TypeDefinition? GetDelegateProxyType (MethodDefinition method, ObjCMethod? obj_method = null) @@ -4602,7 +4606,7 @@ List CollectAllProtocolsInHierarchy (TypeDefinition type) { // A mirror of this method is also implemented in Runtime:GetBlockWrapperCreator // If this method is changed, that method will probably have to be updated too (tests!!!) - MethodDefinition method = obj_method.Method; + MethodDefinition method = obj_method.Method!; MethodDefinition first = method; MethodDefinition? last = null; while (method != last) { @@ -4655,7 +4659,7 @@ List CollectAllProtocolsInHierarchy (TypeDefinition type) MethodDefinition? extensionMethod = pMethod.Method; if (extensionMethod is null) { - MapProtocolMember (obj_method.Method, out extensionMethod); + MapProtocolMember (obj_method.Method!, out extensionMethod); if (extensionMethod is null) return null; } @@ -4682,7 +4686,7 @@ public bool TryFindMethod (MethodDefinition method, [NotNullWhen (true)] out Obj if (TryFindType (method.DeclaringType, out var type)) { if (type.Methods is not null) { foreach (var m in type.Methods) { - if ((object) m.Method == (object) method) { + if ((object?) m.Method == (object) method) { objcMethod = m; return true; } @@ -4981,8 +4985,7 @@ void GenerateConversionToManaged (TypeReference inputType, TypeReference outputT func = GetNSValueToManagedFunc (underlyingManagedType, inputType, outputType, descriptiveMethodName, out nativeTypeName); } else if (underlyingNativeType.Is (Foundation, "NSString")) { func = GetNSStringToSmartEnumFunc (underlyingManagedType, inputType, outputType, descriptiveMethodName, managedClassExpression, out nativeTypeName); - MethodDefinition getConstantMethod, getValueMethod; - if (!IsSmartEnum (underlyingManagedType, out getConstantMethod, out getValueMethod)) { + if (!IsSmartEnum (underlyingManagedType, out var _, out var getValueMethod)) { // method linked away!? this should already be verified ErrorHelper.Show (ErrorHelper.CreateWarning (99, Errors.MX0099, $"the smart enum {underlyingManagedType.FullName} doesn't seem to be a smart enum after all")); token = "INVALID_TOKEN_REF"; @@ -5078,8 +5081,7 @@ void GenerateConversionToNative (TypeReference inputType, TypeReference outputTy func = GetManagedToNSValueFunc (underlyingManagedType, inputType, outputType, descriptiveMethodName); } else if (underlyingNativeType.Is (Foundation, "NSString")) { func = GetSmartEnumToNSStringFunc (underlyingManagedType, inputType, outputType, descriptiveMethodName, classVariableName); - MethodDefinition getConstantMethod, getValueMethod; - if (!IsSmartEnum (underlyingManagedType, out getConstantMethod, out getValueMethod)) { + if (!IsSmartEnum (underlyingManagedType, out var getConstantMethod, out var _)) { // method linked away!? this should already be verified ErrorHelper.Show (ErrorHelper.CreateWarning (99, Errors.MX0099, $"the smart enum {underlyingManagedType.FullName} doesn't seem to be a smart enum after all")); token = "INVALID_TOKEN_REF"; @@ -5405,7 +5407,7 @@ public void Register (PlatformResolver? resolver, IEnumerable Date: Wed, 28 Jan 2026 20:02:33 +0100 Subject: [PATCH 3/6] wip dynamic registrar --- src/ObjCRuntime/DynamicRegistrar.cs | 156 +++++++++++++++------------- src/ObjCRuntime/Registrar.core.cs | 1 + src/ObjCRuntime/Registrar.cs | 21 ++-- 3 files changed, 98 insertions(+), 80 deletions(-) diff --git a/src/ObjCRuntime/DynamicRegistrar.cs b/src/ObjCRuntime/DynamicRegistrar.cs index 27023ae45e5c..fe11e7a9e41c 100644 --- a/src/ObjCRuntime/DynamicRegistrar.cs +++ b/src/ObjCRuntime/DynamicRegistrar.cs @@ -18,8 +18,7 @@ using Xamarin.Bundler; -// Disable until we get around to enable + fix any issues. -#nullable disable +#nullable enable namespace Registrar { // Somewhere to put shared code between the old and the new dynamic registrars. @@ -33,13 +32,13 @@ static class SharedDynamic { // IL2062: Value passed to parameter 'interfaceType' of method 'System.Type.GetInterfaceMap(Type)' can not be statically determined and may not meet 'DynamicallyAccessedMembersAttribute' requirements. [UnconditionalSuppressMessage ("", "IL2062", Justification = "The APIs this method tries to access are marked by other means, so this is linker-safe.")] [BindingImpl (BindingImplOptions.Optimizable)] - public static Dictionary> PrepareInterfaceMethodMapping (Type type) + public static Dictionary>? PrepareInterfaceMethodMapping (Type type) { // Note that the code in this method shouldn't be called when using any static registrar, so throw an exception in that case. if (!Runtime.DynamicRegistrationSupported) throw ErrorHelper.CreateError (8026, "The 'DynamicRegistrar' class is not supported when the dynamic registrar has been linked away."); - Dictionary> rv = null; + Dictionary>? rv = null; var ifaces = type.FindInterfaces ((v, o) => { var attribs = v.GetCustomAttributes (typeof (ProtocolAttribute), true); return attribs is not null && attribs.Length > 0; @@ -54,7 +53,7 @@ public static Dictionary> PrepareInterfaceMethodMap if (SharedDynamic.GetOneAttribute (ifaceMethod) is null) continue; - List list; + List? list; if (rv is null) { rv = new Dictionary> (); rv [impl] = list = new List (); @@ -68,7 +67,7 @@ public static Dictionary> PrepareInterfaceMethodMap return rv; } - public static T GetOneAttribute (ICustomAttributeProvider provider) where T : Attribute + public static T? GetOneAttribute (ICustomAttributeProvider provider) where T : Attribute { var attribs = provider.GetCustomAttributes (typeof (T), false); if (attribs.Length == 0) @@ -88,21 +87,21 @@ public static T GetOneAttribute (ICustomAttributeProvider provider) where T : class DynamicRegistrar : Registrar { Dictionary type_map; - Dictionary registered_assemblies; // Use Dictionary instead of HashSet to avoid pulling in System.Core.dll. + Dictionary? registered_assemblies; // Use Dictionary instead of HashSet to avoid pulling in System.Core.dll. // custom_type_map can be accessed from multiple threads, and at the // same time mutated by the registrar, so any accesses needs to be locked // so that it's not queried and mutated at the same time from multiple threads. // Note that the registrar is already making sure it's not _mutated_ from // multiple threads at the same time. - Dictionary custom_type_map; // Use Dictionary instead of HashSet to avoid pulling in System.Core.dll. + Dictionary custom_type_map; // Use Dictionary instead of HashSet to avoid pulling in System.Core.dll. protected object lock_obj = new object (); public DynamicRegistrar () { type_map = new Dictionary (Runtime.IntPtrEqualityComparer); - custom_type_map = new Dictionary (Runtime.TypeEqualityComparer); + custom_type_map = new Dictionary (Runtime.TypeEqualityComparer); } protected override bool SkipRegisterAssembly (Assembly assembly) @@ -113,7 +112,7 @@ protected override bool SkipRegisterAssembly (Assembly assembly) public void SetAssemblyRegistered (string assembly) { if (registered_assemblies is null) - registered_assemblies = new Dictionary (); + registered_assemblies = new Dictionary (); registered_assemblies.Add (assembly, null); } @@ -171,14 +170,14 @@ public void RegisterMethod (Type type, MethodInfo minfo, ExportAttribute ea) throw new ArgumentException (string.Format ("Cannot register methods on '{0}'; it does not inherit from NSObject.", type.FullName)); if (!minfo.IsStatic && type != minfo.DeclaringType) - throw new ArgumentException (string.Format ("Cannot register the instance method '{0}' on the type '{1}'. The type to connect to ('{2}') must match the method's type ('{1}').", minfo.Name, type.FullName, minfo.DeclaringType.FullName)); + throw new ArgumentException (string.Format ("Cannot register the instance method '{0}' on the type '{1}'. The type to connect to ('{2}') must match the method's type ('{1}').", minfo.Name, type.FullName, minfo.DeclaringType?.FullName)); - List exceptions = null; + List? exceptions = null; var objcType = RegisterType (type, ref exceptions); - var method = new ObjCMethod (this, objcType, minfo); + var method = new ObjCMethod (this, objcType!, minfo); if (method.SetExportAttribute (ea, ref exceptions)) { if (exceptions is null) { - objcType.Add (method, ref exceptions); + objcType!.Add (method, ref exceptions); if (exceptions is null) RegisterMethod (method); } @@ -211,7 +210,7 @@ protected override IEnumerable FindMethods (Type type, string name) // IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicProperties', 'DynamicallyAccessedMemberTypes.NonPublicProperties' in call to 'System.Type.GetProperty(String, BindingFlags)'. The parameter 'type' of method 'Registrar.DynamicRegistrar.FindProperty(Type, String)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [UnconditionalSuppressMessage ("", "IL2070", Justification = "The APIs this method tries to access are marked by other means, so this is linker-safe.")] [BindingImpl (BindingImplOptions.Optimizable)] - protected override PropertyInfo FindProperty (Type type, string name) + protected override PropertyInfo? FindProperty (Type type, string name) { // Note that the code in this method shouldn't be called when using any static registrar, so throw an exception in that case. if (!Runtime.DynamicRegistrationSupported) @@ -225,7 +224,7 @@ protected override PropertyInfo FindProperty (Type type, string name) // IL2026: Using member 'System.Reflection.Assembly.GetTypes()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Types might be removed. [UnconditionalSuppressMessage ("", "IL2026", Justification = "The APIs this method tries to access are marked by other means, so this is linker-safe.")] [BindingImpl (BindingImplOptions.Optimizable)] - public override Type FindType (Type relative, string @namespace, string name) + public override Type? FindType (Type relative, string @namespace, string name) { // Note that the code in this method shouldn't be called when using any static registrar, so throw an exception in that case. if (!Runtime.DynamicRegistrationSupported) @@ -300,12 +299,12 @@ protected override IEnumerable CollectTypes (Assembly assembly) return assembly.GetTypes (); } - public override BindAsAttribute GetBindAsAttribute (PropertyInfo property) + public override BindAsAttribute? GetBindAsAttribute (PropertyInfo? property) { return property?.GetCustomAttribute (false); } - public override BindAsAttribute GetBindAsAttribute (MethodBase method, int parameter_index) + public override BindAsAttribute? GetBindAsAttribute (MethodBase method, int parameter_index) { ICustomAttributeProvider provider; @@ -325,14 +324,14 @@ public override BindAsAttribute GetBindAsAttribute (MethodBase method, int param if (parameter_index == -1) { throw ErrorHelper.CreateError (99, $"Internal error: can't get the BindAs attribute for the return value of a constructor ({GetDescriptiveMethodName (method)}). Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new)."); } else { - provider = cinfo.GetParameters () [parameter_index]; + provider = cinfo?.GetParameters ()! [parameter_index]!; } } return SharedDynamic.GetOneAttribute (provider); } - public override Type GetNullableType (Type type) + public override Type? GetNullableType (Type type) { if (!type.IsGenericType) return null; @@ -341,40 +340,40 @@ public override Type GetNullableType (Type type) return type.GetGenericArguments () [0]; } - protected override ConnectAttribute GetConnectAttribute (PropertyInfo property) + protected override ConnectAttribute? GetConnectAttribute (PropertyInfo property) { return SharedDynamic.GetOneAttribute (property); } - public override ExportAttribute GetExportAttribute (MethodBase method) + public override ExportAttribute? GetExportAttribute (MethodBase method) { - MethodInfo minfo = method as MethodInfo; + var minfo = method as MethodInfo; if (minfo is not null) return SharedDynamic.GetOneAttribute (minfo.GetBaseDefinition ()); - ConstructorInfo cinfo = method as ConstructorInfo; + var cinfo = method as ConstructorInfo; if (cinfo is not null) return SharedDynamic.GetOneAttribute (cinfo); return null; } - protected override Dictionary> PrepareMethodMapping (Type type) + protected override Dictionary>? PrepareMethodMapping (Type type) { return SharedDynamic.PrepareInterfaceMethodMapping (type); } - protected override ExportAttribute GetExportAttribute (PropertyInfo property) + protected override ExportAttribute? GetExportAttribute (PropertyInfo property) { return SharedDynamic.GetOneAttribute (GetBasePropertyInTypeHierarchy (property) ?? property); } - public override RegisterAttribute GetRegisterAttribute (Type type) + public override RegisterAttribute? GetRegisterAttribute (Type type) { return SharedDynamic.GetOneAttribute (type); } - public override ProtocolAttribute GetProtocolAttribute (Type type) + public override ProtocolAttribute? GetProtocolAttribute (Type type) { return SharedDynamic.GetOneAttribute (type); } @@ -422,15 +421,15 @@ protected override Type MakeByRef (Type type) return type.MakeByRefType (); } - public override CategoryAttribute GetCategoryAttribute (Type type) + public override CategoryAttribute? GetCategoryAttribute (Type type) { return SharedDynamic.GetOneAttribute (type); } - protected override Type GetProtocolAttributeWrapperType (Type type) + protected override Type? GetProtocolAttributeWrapperType (Type type) { var attr = SharedDynamic.GetOneAttribute (type); - return attr is null ? null : attr.WrapperType; + return attr?.WrapperType; } protected override IList GetAdoptsAttributes (Type type) @@ -440,12 +439,12 @@ protected override IList GetAdoptsAttributes (Type type) protected override string GetAssemblyName (Assembly assembly) { - return assembly.GetName ().Name; + return assembly.GetName ().Name!; } - protected override Type GetBaseType (Type type) + protected override Type? GetBaseType (Type? type) { - return type.BaseType; + return type?.BaseType; } protected override MethodBase GetBaseMethod (MethodBase method) @@ -453,7 +452,7 @@ protected override MethodBase GetBaseMethod (MethodBase method) return ((MethodInfo) method).GetBaseDefinition (); } - public override Type GetElementType (Type type) + public override Type? GetElementType (Type type) { return type.GetElementType (); } @@ -463,6 +462,17 @@ protected override Type GetEnumUnderlyingType (Type type) return Enum.GetUnderlyingType (type); } + protected override bool TryGetEnumUnderlyingType ([NotNullWhen (true)] Type? tr, [NotNullWhen (true)] out Type? underlyingType) + { + underlyingType = null; + + if (tr?.IsEnum != true) + return false; + + underlyingType = Enum.GetUnderlyingType (tr); + return true; + } + protected override string GetFieldName (FieldInfo field) { return field.Name; @@ -488,12 +498,12 @@ protected override Type GetFieldType (FieldInfo field) return field.FieldType; } - protected override MethodBase GetGetMethod (PropertyInfo property) + protected override MethodBase? GetGetMethod (PropertyInfo property) { return property.GetGetMethod (true); } - protected override MethodBase GetSetMethod (PropertyInfo property) + protected override MethodBase? GetSetMethod (PropertyInfo property) { return property.GetSetMethod (true); } @@ -503,7 +513,7 @@ protected override string GetMethodName (MethodBase method) return method.Name; } - protected override void GetNamespaceAndName (Type type, out string @namespace, out string name) + protected override void GetNamespaceAndName (Type type, out string? @namespace, out string name) { @namespace = type.Namespace; name = type.Name; @@ -520,9 +530,11 @@ protected override Type [] GetParameters (MethodBase method) return types; } - protected override string GetParameterName (MethodBase method, int parameter_index) + protected override string GetParameterName (MethodBase? method, int parameter_index) { - return method.GetParameters () [parameter_index].Name; + if (method is null) + return ""; + return method.GetParameters () [parameter_index].Name!; } protected override string GetPropertyName (PropertyInfo property) @@ -544,9 +556,9 @@ protected override Type GetReturnType (MethodBase method) throw ErrorHelper.CreateError (0, "Cannot get the return type of a {0}", method.GetType ().Name); } - protected override string GetTypeFullName (Type type) + protected override string? GetTypeFullName (Type? type) { - return type.FullName; + return type?.FullName; } // Note that the code in this method shouldn't be called when using any static registrar, so throw an exception in that case. @@ -554,7 +566,7 @@ protected override string GetTypeFullName (Type type) // IL2055: Call to 'System.Type.MakeGenericType(Type[])' can not be statically analyzed. It's not possible to guarantee the availability of requirements of the generic type. [UnconditionalSuppressMessage ("", "IL2055", Justification = "The APIs this method tries to access are marked by other means, so this is linker-safe.")] [BindingImpl (BindingImplOptions.Optimizable)] - public override bool VerifyIsConstrainedToNSObject (Type type, out Type constrained_type) + public override bool VerifyIsConstrainedToNSObject (Type type, out Type? constrained_type) { // Note that the code in this method shouldn't be called when using any static registrar, so throw an exception in that case. if (!Runtime.DynamicRegistrationSupported) @@ -587,9 +599,8 @@ public override bool VerifyIsConstrainedToNSObject (Type type, out Type constrai var args = type.GetGenericArguments (); var constrs = new Type [args.Length]; for (int i = 0; i < args.Length; i++) { - Type constr; - rv &= VerifyIsConstrainedToNSObject (args [i], out constr); - constrs [i] = constr; + rv &= VerifyIsConstrainedToNSObject (args [i], out var constr); + constrs [i] = constr!; } constrained_type = type.MakeGenericType (constrs); return rv; @@ -598,7 +609,7 @@ public override bool VerifyIsConstrainedToNSObject (Type type, out Type constrai return true; } - protected override Exception CreateExceptionImpl (int code, bool error, Exception innerException, MethodBase method, string message, params object [] args) + protected override Exception CreateExceptionImpl (int code, bool error, Exception? innerException, MethodBase? method, string message, params object? [] args) { // There doesn't seem to be a way to find the source code location // for the method using System.Reflection. @@ -607,7 +618,7 @@ protected override Exception CreateExceptionImpl (int code, bool error, Exceptio return ErrorHelper.CreateWarning (code, innerException, message, args); } - protected override Exception CreateExceptionImpl (int code, bool error, Exception innerException, Type type, string message, params object [] args) + protected override Exception CreateExceptionImpl (int code, bool error, Exception? innerException, Type? type, string message, params object? [] args) { // There doesn't seem to be a way to find the source code location // for the method using System.Reflection. @@ -618,7 +629,7 @@ protected override Exception CreateExceptionImpl (int code, bool error, Exceptio protected override string GetAssemblyQualifiedName (Type type) { - return type.AssemblyQualifiedName; + return type.AssemblyQualifiedName!; } public override bool HasReleaseAttribute (MethodBase method) @@ -631,7 +642,7 @@ public override bool HasReleaseAttribute (MethodBase method) // IL2025: Attribute 'System.Runtime.CompilerServices.ExtensionAttribute' is being referenced in code but the trimmer was instructed to remove all instances of this attribute. If the attribute instances are necessary make sure to either remove the trimmer attribute XML portion which removes the attribute instances, or override the removal by using the trimmer XML descriptor to keep the attribute type (which in turn keeps all of its instances). [UnconditionalSuppressMessage ("", "IL2045", Justification = "The Extension attribute is manually preserved.")] - public static bool HasThisAttributeImpl (MethodBase method) + public static bool HasThisAttributeImpl (MethodBase? method) { var mi = method as MethodInfo; if (mi is null) @@ -774,7 +785,7 @@ protected override Type [] GetInterfaces (Type type) return type.GetInterfaces (); } - protected override bool TryGetAttribute (Type type, string attributeNamespace, string attributeType, out object attribute) + protected override bool TryGetAttribute (Type type, string attributeNamespace, string attributeType, [NotNullWhen (true)] out object? attribute) { var attribs = type.GetCustomAttributes (false); @@ -862,9 +873,9 @@ protected override void OnRegisterProtocol (ObjCType type) Protocol.protocol_addProperty (protocol, property.Selector, props, count, !property.IsOptional, !property.IsStatic); // The properties need to be added as methods as well. var propertyType = ToSignature (property.PropertyType, property, false); - Protocol.protocol_addMethodDescription (protocol, Selector.GetHandle (property.GetterSelector), propertyType + "@:", !property.IsOptional, !property.IsStatic); + Protocol.protocol_addMethodDescription (protocol, Selector.GetHandle (property.GetterSelector!), propertyType + "@:", !property.IsOptional, !property.IsStatic); if (!property.IsReadOnly) - Protocol.protocol_addMethodDescription (protocol, Selector.GetHandle (property.SetterSelector), "v@:" + propertyType, !property.IsOptional, !property.IsStatic); + Protocol.protocol_addMethodDescription (protocol, Selector.GetHandle (property.SetterSelector!), "v@:" + propertyType, !property.IsOptional, !property.IsStatic); } } @@ -880,7 +891,7 @@ protected override void OnRegisterProtocol (ObjCType type) Trace (" [DYNAMIC PROTOCOL] Registered the protocol {0} for {1}", type.ProtocolName, type.Type.FullName); } - protected override void OnRegisterCategory (ObjCType type, ref List exceptions) + protected override void OnRegisterCategory (ObjCType type, [NotNullIfNotNull (nameof (exceptions))] ref List? exceptions) { if (type.Methods is not null) { foreach (var method in type.Methods) { @@ -928,7 +939,7 @@ protected override void OnRegisterType (ObjCType type) if (type.IsFakeProtocol) return; - var super = type.SuperType; + var super = type.SuperType!; type.Handle = Class.objc_allocateClassPair (super.Handle, type.ExportedName, IntPtr.Zero); @@ -942,7 +953,7 @@ protected override void OnRegisterType (ObjCType type) if (type.Fields is not null) { foreach (var field in type.Fields.Values) - Class.class_addIvar (type.Handle, field.Name, new IntPtr (field.Size), field.Alignment, field.FieldType); + Class.class_addIvar (type.Handle, field.Name!, new IntPtr (field.Size), field.Alignment, field.FieldType); } if (type.Methods is not null) { @@ -980,9 +991,9 @@ public void GetMethodDescriptionAndObject (Type type, IntPtr selector, bool is_s mthis = IntPtr.Zero; } else { try { - var nsobj = Runtime.GetNSObject (obj, Runtime.MissingCtorResolution.ThrowConstructor1NotFound, true); + var nsobj = Runtime.GetNSObject (obj, Runtime.MissingCtorResolution.ThrowConstructor1NotFound, true)!; mthis = Runtime.AllocGCHandle (nsobj); - if (res.Method.ContainsGenericParameters) { + if (res.Method!.ContainsGenericParameters) { res.WriteUnmanagedDescription (desc, Runtime.FindClosedMethod (nsobj.GetType (), res.Method)); return; } @@ -1013,10 +1024,10 @@ ObjCMethod GetMethodNoThrow (Type original_type, Type type, string selector, boo if (objcType is null) throw ErrorHelper.CreateError (4142, "Failed to register the type '{0}'", type.FullName); - ObjCMember member = null; + ObjCMember? member = null; if (type.BaseType != typeof (object) && !objcType.TryGetMember (selector, is_static, out member)) - return GetMethodNoThrow (original_type, type.BaseType, selector, is_static); + return GetMethodNoThrow (original_type, type.BaseType!, selector, is_static); var method = member as ObjCMethod; @@ -1026,9 +1037,8 @@ ObjCMethod GetMethodNoThrow (Type original_type, Type type, string selector, boo return method; } - public Type Lookup (IntPtr @class, bool throw_on_error) + public Type? Lookup (IntPtr @class, bool throw_on_error) { - ObjCType type; IntPtr original_class = @class; bool lockTaken = false; @@ -1036,7 +1046,7 @@ public Type Lookup (IntPtr @class, bool throw_on_error) LockRegistrar (ref lockTaken); do { - if (type_map.TryGetValue (@class, out type)) + if (type_map.TryGetValue (@class, out var type)) return type.Type; bool is_custom_type; @@ -1143,9 +1153,9 @@ bool RegisterMethod (ObjCMethod method) static MethodInfo GetPropertyMethod (PropertyInfo property) { if (property.CanRead) - return property.GetGetMethod (true); + return property.GetGetMethod (true)!; - return property.GetSetMethod (true); + return property.GetSetMethod (true)!; } static bool IsStaticProperty (PropertyInfo property) @@ -1158,12 +1168,12 @@ static bool IsVirtualProperty (PropertyInfo property) return GetPropertyMethod (property).IsVirtual; } - static PropertyInfo GetBasePropertyInTypeHierarchy (PropertyInfo property) + static PropertyInfo? GetBasePropertyInTypeHierarchy (PropertyInfo property) { if (IsStaticProperty (property) || !IsVirtualProperty (property)) return property; - var @base = property.DeclaringType.BaseType; + var @base = property.DeclaringType?.BaseType; while (@base is not null) { var base_property = TryMatchProperty (@base, property); if (base_property is not null) @@ -1180,7 +1190,7 @@ static PropertyInfo GetBasePropertyInTypeHierarchy (PropertyInfo property) // IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicProperties', 'DynamicallyAccessedMemberTypes.NonPublicProperties' in call to 'System.Type.GetProperties(BindingFlags)'. The parameter 'type' of method 'Registrar.DynamicRegistrar.TryMatchProperty(Type, PropertyInfo)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [UnconditionalSuppressMessage ("", "IL2070", Justification = "The APIs this method tries to access are marked by other means, so this is linker-safe.")] [BindingImpl (BindingImplOptions.Optimizable)] - static PropertyInfo TryMatchProperty (Type type, PropertyInfo property) + static PropertyInfo? TryMatchProperty (Type type, PropertyInfo property) { // Note that the code in this method shouldn't be called when using any static registrar, so throw an exception in that case. if (!Runtime.DynamicRegistrationSupported) @@ -1219,8 +1229,14 @@ static bool PropertyMatch (PropertyInfo candidate, PropertyInfo property) return true; } - static bool MethodMatch (MethodInfo candidate, MethodInfo method) + static bool MethodMatch (MethodInfo? candidate, MethodInfo? method) { + if (candidate is null && method is null) + return true; + + if (candidate is null || method is null) + return false; + if (!candidate.IsVirtual) return false; @@ -1249,7 +1265,7 @@ static bool TypeMatch (Type a, Type b) public IntPtr Register (Type type) { - List exceptions = null; + List? exceptions = null; var objctype = RegisterType (type, ref exceptions); if (exceptions is not null && exceptions.Count > 0) throw new AggregateException (exceptions); diff --git a/src/ObjCRuntime/Registrar.core.cs b/src/ObjCRuntime/Registrar.core.cs index 6ec72e425e7c..958a17174874 100644 --- a/src/ObjCRuntime/Registrar.core.cs +++ b/src/ObjCRuntime/Registrar.core.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using System.Text; #nullable enable diff --git a/src/ObjCRuntime/Registrar.cs b/src/ObjCRuntime/Registrar.cs index 4e9f705ae17b..a78794753e90 100644 --- a/src/ObjCRuntime/Registrar.cs +++ b/src/ObjCRuntime/Registrar.cs @@ -11,6 +11,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Text; @@ -78,10 +79,10 @@ static class Shared { public static List GetMT4127 (TMethod impl, List ifaceMethods) { var exceptions = new List (); - exceptions.Add (ErrorHelper.CreateError (4127, Errors.MT4127, impl.DeclaringType.FullName, impl.Name)); + exceptions.Add (ErrorHelper.CreateError (4127, Errors.MT4127, impl.DeclaringType?.FullName, impl.Name)); for (int i = 0; i < ifaceMethods.Count; i++) { var ifaceM = ifaceMethods [i]; - exceptions.Add (ErrorHelper.CreateError (4137, Errors.MT4137, impl.DeclaringType.FullName, impl.Name, ifaceM.DeclaringType.FullName, ifaceM.Name)); + exceptions.Add (ErrorHelper.CreateError (4137, Errors.MT4137, impl.DeclaringType?.FullName, impl.Name, ifaceM.DeclaringType?.FullName, ifaceM.Name)); } return exceptions; } @@ -265,10 +266,10 @@ void VerifySelector (ObjCMethod method, [NotNullIfNotNull (nameof (exceptions))] if (method.IsVariadic) { ex = Registrar.CreateException (4140, method, Errors.MT4140, - method.Method.DeclaringType.FullName, method.MethodName, nativeParamCount, paramCount, method.Selector); + method.Method.DeclaringType?.FullName, method.MethodName, nativeParamCount, paramCount, method.Selector); } else { ex = Registrar.CreateException (4117, method, Errors.MT4117, - method.Method.DeclaringType.FullName, method.MethodName, nativeParamCount, paramCount, method.Selector); + method.Method.DeclaringType?.FullName, method.MethodName, nativeParamCount, paramCount, method.Selector); } Registrar.AddException (ref exceptions, ex); @@ -648,7 +649,7 @@ internal bool IsInstanceCategory { internal void WriteUnmanagedDescription (IntPtr desc) { - WriteUnmanagedDescription (desc, (System.Reflection.MethodBase) (object) Method); + WriteUnmanagedDescription (desc, (System.Reflection.MethodBase) (object) Method!); } internal void WriteUnmanagedDescription (IntPtr desc, System.Reflection.MethodBase method_base) @@ -1091,8 +1092,8 @@ protected virtual void OnRegisterCategory (ObjCType type, [NotNullIfNotNull (nam protected abstract TMethod GetBaseMethod (TMethod method); protected abstract TType []? GetParameters (TMethod method); protected abstract string GetParameterName (TMethod? method, int parameter_index); - protected abstract TMethod GetGetMethod (TProperty property); - protected abstract TMethod GetSetMethod (TProperty property); + protected abstract TMethod? GetGetMethod (TProperty property); + protected abstract TMethod? GetSetMethod (TProperty property); protected abstract TType GetSystemVoidType (); protected abstract bool IsVirtual (TMethod method); protected abstract bool IsByRef (TType type); @@ -1102,9 +1103,9 @@ protected virtual void OnRegisterCategory (ObjCType type, [NotNullIfNotNull (nam protected abstract TType MakeByRef (TType type); public abstract bool HasThisAttribute (TMethod method); protected abstract bool IsConstructor (TMethod method); - public abstract TType GetElementType (TType type); + public abstract TType? GetElementType (TType type); protected abstract TType GetReturnType (TMethod method); - protected abstract void GetNamespaceAndName (TType type, out string @namespace, out string name); + protected abstract void GetNamespaceAndName (TType type, out string? @namespace, out string name); protected abstract bool TryGetAttribute (TType type, string attributeNamespace, string attributeType, [NotNullWhen (true)] out object? attribute); protected abstract ExportAttribute? GetExportAttribute (TProperty property); // Return null if no attribute is found. Must check the base property (i.e. if property is overriding a property in a base class, must check the overridden property for the attribute). public abstract ExportAttribute? GetExportAttribute (TMethod method); // Return null if no attribute is found. Must check the base method (i.e. if method is overriding a method in a base class, must check the overridden method for the attribute). @@ -1145,7 +1146,7 @@ protected virtual void OnRegisterCategory (ObjCType type, [NotNullIfNotNull (nam protected abstract Exception CreateExceptionImpl (int code, bool error, Exception? innerException, TMethod? method, string message, params object? [] args); protected abstract Exception CreateExceptionImpl (int code, bool error, Exception? innerException, TType? type, string message, params object? [] args); protected abstract string PlatformName { get; } - public abstract TType FindType (TType relative, string @namespace, string name); + public abstract TType? FindType (TType relative, string @namespace, string name); protected abstract IEnumerable? FindMethods (TType type, string name); // will return null if nothing was found protected abstract TProperty? FindProperty (TType type, string name); // will return null if nothing was found From 59c01d257345dda4bdc0b940f2025a12565dc7fe Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 30 Jan 2026 00:01:27 +0100 Subject: [PATCH 4/6] wip --- src/ObjCRuntime/Class.cs | 2 +- src/ObjCRuntime/DynamicRegistrar.cs | 2 +- src/ObjCRuntime/Registrar.cs | 47 +++++++++++++---------------- tools/common/StaticRegistrar.cs | 2 +- 4 files changed, 24 insertions(+), 29 deletions(-) diff --git a/src/ObjCRuntime/Class.cs b/src/ObjCRuntime/Class.cs index 36c69c87e1a8..2feeb62469fe 100644 --- a/src/ObjCRuntime/Class.cs +++ b/src/ObjCRuntime/Class.cs @@ -74,7 +74,7 @@ internal unsafe static void Initialize (Runtime.InitializationOptions* options) for (int i = 0; i < map->assembly_count; i++) { var assembly = map->assemblies [i]; - Runtime.Registrar.SetAssemblyRegistered (Marshal.PtrToStringAuto (assembly.name)); + Runtime.Registrar.SetAssemblyRegistered (Marshal.PtrToStringAuto (assembly.name)!); } } diff --git a/src/ObjCRuntime/DynamicRegistrar.cs b/src/ObjCRuntime/DynamicRegistrar.cs index fe11e7a9e41c..789e0b328ac3 100644 --- a/src/ObjCRuntime/DynamicRegistrar.cs +++ b/src/ObjCRuntime/DynamicRegistrar.cs @@ -224,7 +224,7 @@ protected override IEnumerable FindMethods (Type type, string name) // IL2026: Using member 'System.Reflection.Assembly.GetTypes()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Types might be removed. [UnconditionalSuppressMessage ("", "IL2026", Justification = "The APIs this method tries to access are marked by other means, so this is linker-safe.")] [BindingImpl (BindingImplOptions.Optimizable)] - public override Type? FindType (Type relative, string @namespace, string name) + public override Type? FindType (Type relative, string? @namespace, string name) { // Note that the code in this method shouldn't be called when using any static registrar, so throw an exception in that case. if (!Runtime.DynamicRegistrationSupported) diff --git a/src/ObjCRuntime/Registrar.cs b/src/ObjCRuntime/Registrar.cs index a78794753e90..865c22adf1c0 100644 --- a/src/ObjCRuntime/Registrar.cs +++ b/src/ObjCRuntime/Registrar.cs @@ -68,7 +68,7 @@ public class AssemblyRegistrationEventArgs : EventArgs { /// To be added. /// To be added. /// To be added. - public System.Reflection.AssemblyName AssemblyName { get; internal set; } + public System.Reflection.AssemblyName? AssemblyName { get; internal set; } } } #endif @@ -669,16 +669,16 @@ internal void WriteUnmanagedDescription (IntPtr desc, System.Reflection.MethodBa semantic |= (ArgumentSemantic) (InstanceCategoryFlag); var bindas_count = Marshal.ReadInt32 (desc + IntPtr.Size + 4); - if (bindas_count < 1 + Parameters.Length) - throw ErrorHelper.CreateError (8018, $"Internal consistency error: BindAs array is not big enough (expected at least {1 + parameters.Length} elements, got {bindas_count} elements) for {method_base.DeclaringType.FullName + "." + method_base.Name}. Please file a bug report at https://github.com/dotnet/macios/issues/new."); + if (bindas_count < 1 + Parameters!.Length) + throw ErrorHelper.CreateError (8018, $"Internal consistency error: BindAs array is not big enough (expected at least {1 + parameters!.Length} elements, got {bindas_count} elements) for {method_base.DeclaringType?.FullName + "." + method_base.Name}. Please file a bug report at https://github.com/dotnet/macios/issues/new."); Marshal.WriteIntPtr (desc, Runtime.AllocGCHandle (method_base)); Marshal.WriteInt32 (desc + IntPtr.Size, (int) semantic); if (!IsConstructor && ReturnType != NativeReturnType) Marshal.WriteIntPtr (desc + IntPtr.Size + 8, Runtime.AllocGCHandle (NativeReturnType)); - for (int i = 0; i < NativeParameters.Length; i++) { - if (parameters [i] == native_parameters [i]) + for (int i = 0; i < NativeParameters!.Length; i++) { + if (parameters! [i] == native_parameters! [i]) continue; Marshal.WriteIntPtr (desc + IntPtr.Size + 8 + IntPtr.Size * (i + 1), Runtime.AllocGCHandle (native_parameters [i])); } @@ -739,8 +739,8 @@ bool IsValidToManagedTypeConversion (TType inputType, TType outputType) return false; if (!Registrar.IsArray (inputType)) return false; - underlyingOutputType = Registrar.GetElementType (outputType); - underlyingInputType = Registrar.GetElementType (inputType); + underlyingOutputType = Registrar.GetElementType (outputType)!; + underlyingInputType = Registrar.GetElementType (inputType)!; } var outputTypeName = Registrar.GetTypeFullName (underlyingOutputType); @@ -879,7 +879,7 @@ public Trampoline Trampoline { #if LEGACY_TOOLS || BUNDLER throw ErrorHelper.CreateError (8018, Errors.MT8018); #else - var mi = (System.Reflection.MethodInfo) Method; + var mi = (System.Reflection.MethodInfo?) Method; bool is_stret; #if MONOMAC || __MACCATALYST__ if (Runtime.IsARM64CallingConvention) { @@ -1146,7 +1146,7 @@ protected virtual void OnRegisterCategory (ObjCType type, [NotNullIfNotNull (nam protected abstract Exception CreateExceptionImpl (int code, bool error, Exception? innerException, TMethod? method, string message, params object? [] args); protected abstract Exception CreateExceptionImpl (int code, bool error, Exception? innerException, TType? type, string message, params object? [] args); protected abstract string PlatformName { get; } - public abstract TType? FindType (TType relative, string @namespace, string name); + public abstract TType? FindType (TType relative, string? @namespace, string name); protected abstract IEnumerable? FindMethods (TType type, string name); // will return null if nothing was found protected abstract TProperty? FindProperty (TType type, string name); // will return null if nothing was found @@ -1197,7 +1197,7 @@ public bool IsPropertyAccessor (TMethod method, [NotNullWhen (true)] out TProper if (!IsPropertyAccessor (method)) return false; - property = FindProperty (method.DeclaringType, method.Name.Substring (4)); + property = FindProperty (method.DeclaringType!, method.Name.Substring (4)); return property is not null; } @@ -1501,10 +1501,7 @@ string GetDescriptiveMethodName (TType type, TMethod? method) // overridable so that descendant classes can provide faster implementations protected virtual bool IsNSObject (TType type) { - string @namespace; - string name; - - GetNamespaceAndName (type, out @namespace, out name); + GetNamespaceAndName (type, out var @namespace, out var name); if (@namespace == Foundation && name == "NSObject") return true; @@ -1516,15 +1513,14 @@ protected virtual bool IsNSObject (TType type) return false; } - protected virtual bool AreEqual (TType a, TType b) + protected virtual bool AreEqual (TType? a, TType? b) { return a == b; } protected bool Is (TType type, string @namespace, string name) { - string ns, n; - GetNamespaceAndName (type, out ns, out n); + GetNamespaceAndName (type, out var ns, out var n); return ns == @namespace && n == name; } @@ -1656,8 +1652,7 @@ protected static void AddException ([NotNull] ref List? exceptions, E bool IsSubClassOf (TType? type, string @namespace, string name) { while ((type = GetBaseType (type)) is not null) { - string ns, n; - GetNamespaceAndName (type, out ns, out n); + GetNamespaceAndName (type, out var ns, out var n); if (ns == @namespace && n == name) return true; } @@ -2306,8 +2301,8 @@ void FlattenInterfaces (TType? [] ifaces) PropertyType = property_type, }; - TMethod getter = GetGetMethod (property); - TMethod setter = GetSetMethod (property); + TMethod? getter = GetGetMethod (property); + TMethod? setter = GetSetMethod (property); if (getter is not null && VerifyNonGenericMethod (ref exceptions, type, getter)) { var method = new ObjCMethod (this, objcType, getter) { @@ -2319,7 +2314,7 @@ void FlattenInterfaces (TType? [] ifaces) List? excs = null; if (!method.ValidateSignature (ref excs)) { AddException (ref exceptions, CreateException (4138, excs [0], property, Errors.MT4138, - GetTypeFullName (property.PropertyType), property.DeclaringType.FullName, property.Name)); + GetTypeFullName (property.PropertyType), property.DeclaringType?.FullName, property.Name)); continue; } @@ -2341,7 +2336,7 @@ void FlattenInterfaces (TType? [] ifaces) List? excs = null; if (!method.ValidateSignature (ref excs)) { AddException (ref exceptions, CreateException (4138, excs [0], property, Errors.MT4138, - GetTypeFullName (property.PropertyType), property.DeclaringType.FullName, property.Name)); + GetTypeFullName (property.PropertyType), property.DeclaringType?.FullName, property.Name)); continue; } @@ -2602,7 +2597,7 @@ public string ComputeSignature (TType? declaring_type, bool is_ctor, TType? retu var type = parameters [i]; if (IsByRef (type)) { signature.Append ("^"); - var elementType = GetElementType (type); + var elementType = GetElementType (type)!; if (IsNullable (elementType)) { signature.Append (ToSignature (GetNullableType (elementType)!, member, ref success)); } else { @@ -2741,12 +2736,12 @@ protected string ToSignature (TType type, ObjCMember? member, ref bool success, return ValueTypeSignature (type, member, ref success); if (IsArray (type)) { - ToSignature (GetElementType (type), member, ref success); // this validates that the element type is a type we support. + ToSignature (GetElementType (type)!, member, ref success); // this validates that the element type is a type we support. return "@"; // But we don't care about the actual type, we'll just return '@'. We only support NSArrays of the element type, so '@' is always right. } if (IsPointer (type)) - return "^" + ToSignature (GetElementType (type), member, ref success); + return "^" + ToSignature (GetElementType (type)!, member, ref success); success = false; return string.Empty; diff --git a/tools/common/StaticRegistrar.cs b/tools/common/StaticRegistrar.cs index d3b8dd234c6b..91231b57e768 100644 --- a/tools/common/StaticRegistrar.cs +++ b/tools/common/StaticRegistrar.cs @@ -717,7 +717,7 @@ public StaticRegistrar (Application app) return list; } - public override TypeReference FindType (TypeReference relative, string @namespace, string name) + public override TypeReference FindType (TypeReference relative, string? @namespace, string name) { return relative.Resolve ().Module.GetType (@namespace, name); } From 9444e73f3a335a61a99f04f7e8cea74bbbf1974e Mon Sep 17 00:00:00 2001 From: GitHub Actions Autoformatter Date: Fri, 30 Jan 2026 11:37:59 +0000 Subject: [PATCH 5/6] Auto-format source code --- src/ObjCRuntime/DynamicRegistrar.cs | 2 +- src/ObjCRuntime/Registrar.cs | 6 +++--- tools/common/StaticRegistrar.cs | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ObjCRuntime/DynamicRegistrar.cs b/src/ObjCRuntime/DynamicRegistrar.cs index 789e0b328ac3..93dc571ced6b 100644 --- a/src/ObjCRuntime/DynamicRegistrar.cs +++ b/src/ObjCRuntime/DynamicRegistrar.cs @@ -468,7 +468,7 @@ protected override bool TryGetEnumUnderlyingType ([NotNullWhen (true)] Type? tr, if (tr?.IsEnum != true) return false; - + underlyingType = Enum.GetUnderlyingType (tr); return true; } diff --git a/src/ObjCRuntime/Registrar.cs b/src/ObjCRuntime/Registrar.cs index 865c22adf1c0..740ea4335044 100644 --- a/src/ObjCRuntime/Registrar.cs +++ b/src/ObjCRuntime/Registrar.cs @@ -96,7 +96,7 @@ abstract partial class Registrar { const string NFloatTypeName = "System.Runtime.InteropServices.NFloat"; Dictionary assemblies = new (); // Use Dictionary instead of HashSet to avoid pulling in System.Core.dll. - // locking: all accesses must lock 'types'. + // locking: all accesses must lock 'types'. Dictionary types = new Dictionary (); // this is used to check if multiple types are registered with the same name. // locking: all accesses must lock 'type_map'. @@ -943,7 +943,7 @@ public string Signature { } } - public bool ValidateSignature ([NotNullWhen (false)] [NotNullIfNotNull (nameof (exceptions))] ref List? exceptions) + public bool ValidateSignature ([NotNullWhen (false)][NotNullIfNotNull (nameof (exceptions))] ref List? exceptions) { if (Registrar.LaxMode) return true; @@ -2730,7 +2730,7 @@ protected string ToSignature (TType type, ObjCMember? member, ref bool success, return "^v"; if (TryGetEnumUnderlyingType (type, out var underlyingType)) - return ToSignature (underlyingType, member, ref success); + return ToSignature (underlyingType, member, ref success); if (IsValueType (type)) return ValueTypeSignature (type, member, ref success); diff --git a/tools/common/StaticRegistrar.cs b/tools/common/StaticRegistrar.cs index 91231b57e768..74b6c5640a26 100644 --- a/tools/common/StaticRegistrar.cs +++ b/tools/common/StaticRegistrar.cs @@ -1273,7 +1273,7 @@ protected override bool TryGetEnumUnderlyingType ([NotNullWhen (true)] TypeRefer if (!IsEnum (tr)) return false; - + underlyingType = GetEnumUnderlyingType (tr); return underlyingType is not null; } @@ -2417,7 +2417,7 @@ string ToObjCParameterType (TypeReference type, string descriptiveMethodName, Li if (td is null) { exceptions.Add (ErrorHelper.CreateError (99, Errors.MX0099, $"Unable to resolve the type {type.FullName} when generating the registrar for the method '{descriptiveMethodName}'.")); return ""; - } else if (IsNSObject (td)) { + } else if (IsNSObject (td)) { if (!IsPlatformType (td)) return "id"; @@ -2647,7 +2647,7 @@ public class SkippedType { public ObjCType Actual; public uint SkippedTokenReference; public uint ActualTokenReference; - + public SkippedType (TypeReference skipped, ObjCType actual) { Skipped = skipped; @@ -4153,7 +4153,7 @@ void Specialize (AutoIndentStringBuilder sb, ObjCMethod method, List } var b = new Body (body.ToString (), objc_signature.ToString ()); - + if (merge_bodies && bodies.TryGetValue (b, out var existing)) { /* We already have an identical trampoline, use it instead */ b = existing; @@ -4962,7 +4962,7 @@ void GenerateConversionToManaged (TypeReference inputType, TypeReference outputT } else if (isManagedNullable) { underlyingManagedType = GetNullableType (managedType); if (underlyingManagedType is null) - throw ErrorHelper.CreateError (99, Errors.MX0099, $"can't convert from '{inputType.FullName}' to '{outputType.FullName}' in {descriptiveMethodName}: {managedType.FullName} is not a valid nullable type"); + throw ErrorHelper.CreateError (99, Errors.MX0099, $"can't convert from '{inputType.FullName}' to '{outputType.FullName}' in {descriptiveMethodName}: {managedType.FullName} is not a valid nullable type"); sb.AppendLine ($"{classVariableName} = xamarin_get_nullable_type ({managedClassExpression}, &exception_gchandle);"); sb.AppendLine ($"if (exception_gchandle != INVALID_GCHANDLE) goto exception_handling;"); cleanup.AppendLine ($"xamarin_mono_object_release (&{classVariableName});"); From 18c16b0794963c7fe70b381bf01ffdcc18b4b226 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Sat, 31 Jan 2026 00:34:36 +0100 Subject: [PATCH 6/6] testsupdate --- .../expected/iOS-MonoVM-interpreter-preservedapis.txt | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/dotnet/UnitTests/expected/iOS-MonoVM-interpreter-preservedapis.txt b/tests/dotnet/UnitTests/expected/iOS-MonoVM-interpreter-preservedapis.txt index 7e67679fb9e1..41dc16024580 100644 --- a/tests/dotnet/UnitTests/expected/iOS-MonoVM-interpreter-preservedapis.txt +++ b/tests/dotnet/UnitTests/expected/iOS-MonoVM-interpreter-preservedapis.txt @@ -863,7 +863,6 @@ Microsoft.iOS.dll:Registrar.DynamicRegistrar.GetBindAsAttribute(System.Reflectio Microsoft.iOS.dll:Registrar.DynamicRegistrar.GetCategoryAttribute(System.Type) Microsoft.iOS.dll:Registrar.DynamicRegistrar.GetConnectAttribute(System.Reflection.PropertyInfo) Microsoft.iOS.dll:Registrar.DynamicRegistrar.GetElementType(System.Type) -Microsoft.iOS.dll:Registrar.DynamicRegistrar.GetEnumUnderlyingType(System.Type) Microsoft.iOS.dll:Registrar.DynamicRegistrar.GetExportAttribute(System.Reflection.MethodBase) Microsoft.iOS.dll:Registrar.DynamicRegistrar.GetExportAttribute(System.Reflection.PropertyInfo) Microsoft.iOS.dll:Registrar.DynamicRegistrar.GetFields(System.Type) @@ -932,6 +931,7 @@ Microsoft.iOS.dll:Registrar.DynamicRegistrar.ReportError(System.Int32, System.St Microsoft.iOS.dll:Registrar.DynamicRegistrar.SetAssemblyRegistered(System.String) Microsoft.iOS.dll:Registrar.DynamicRegistrar.SkipRegisterAssembly(System.Reflection.Assembly) Microsoft.iOS.dll:Registrar.DynamicRegistrar.TryGetAttribute(System.Type, System.String, System.String, out System.Object&) +Microsoft.iOS.dll:Registrar.DynamicRegistrar.TryGetEnumUnderlyingType(System.Type, out System.Type&) Microsoft.iOS.dll:Registrar.DynamicRegistrar.TryMatchProperty(System.Type, System.Reflection.PropertyInfo) Microsoft.iOS.dll:Registrar.DynamicRegistrar.TypeMatch(System.Type, System.Type) Microsoft.iOS.dll:Registrar.DynamicRegistrar.VerifyIsConstrainedToNSObject(System.Type, out System.Type&) @@ -990,7 +990,6 @@ Microsoft.iOS.dll:Registrar.Registrar.GetConnectAttribute(System.Reflection.Prop Microsoft.iOS.dll:Registrar.Registrar.GetDescriptiveMethodName(System.Reflection.MethodBase) Microsoft.iOS.dll:Registrar.Registrar.GetDescriptiveMethodName(System.Type, System.Reflection.MethodBase) Microsoft.iOS.dll:Registrar.Registrar.GetElementType(System.Type) -Microsoft.iOS.dll:Registrar.Registrar.GetEnumUnderlyingType(System.Type) Microsoft.iOS.dll:Registrar.Registrar.GetExportAttribute(System.Reflection.MethodBase) Microsoft.iOS.dll:Registrar.Registrar.GetExportAttribute(System.Reflection.PropertyInfo) Microsoft.iOS.dll:Registrar.Registrar.GetExportedTypeName(System.Type, Foundation.RegisterAttribute) @@ -1069,6 +1068,7 @@ Microsoft.iOS.dll:Registrar.Registrar.SkipRegisterAssembly(System.Reflection.Ass Microsoft.iOS.dll:Registrar.Registrar.ToSignature(System.Type, Registrar.Registrar/ObjCMember, System.Boolean) Microsoft.iOS.dll:Registrar.Registrar.ToSignature(System.Type, Registrar.Registrar/ObjCMember, System.Boolean&, System.Boolean) Microsoft.iOS.dll:Registrar.Registrar.TryGetAttribute(System.Type, System.String, System.String, out System.Object&) +Microsoft.iOS.dll:Registrar.Registrar.TryGetEnumUnderlyingType(System.Type, out System.Type&) Microsoft.iOS.dll:Registrar.Registrar.UnlockRegistrar() Microsoft.iOS.dll:Registrar.Registrar.ValueTypeSignature(System.Type, Registrar.Registrar/ObjCMember, System.Boolean&) Microsoft.iOS.dll:Registrar.Registrar.VerifyInSdk(System.Collections.Generic.List`1&, Registrar.Registrar/ObjCMethod) @@ -1078,13 +1078,12 @@ Microsoft.iOS.dll:Registrar.Registrar.VerifyIsConstrainedToNSObject(System.Type, Microsoft.iOS.dll:Registrar.Registrar.VerifyNonGenericMethod(System.Collections.Generic.List`1&, System.Type, System.Reflection.MethodBase) Microsoft.iOS.dll:Registrar.Registrar.VerifyTypeInSDK(System.Collections.Generic.List`1&, System.Type, Registrar.Registrar/ObjCMethod, Registrar.Registrar/ObjCMethod, Registrar.Registrar/ObjCProperty, System.Type) Microsoft.iOS.dll:Registrar.Registrar/ObjCField -Microsoft.iOS.dll:Registrar.Registrar/ObjCField..ctor() +Microsoft.iOS.dll:Registrar.Registrar/ObjCField..ctor(Registrar.Registrar, Registrar.Registrar/ObjCType, System.String) Microsoft.iOS.dll:Registrar.Registrar/ObjCField.get_FullName() Microsoft.iOS.dll:Registrar.Registrar/ObjCField.get_IsNativeStatic() Microsoft.iOS.dll:Registrar.Registrar/ObjCField.get_IsStatic() Microsoft.iOS.dll:Registrar.Registrar/ObjCField.set_IsStatic(System.Boolean) Microsoft.iOS.dll:Registrar.Registrar/ObjCMember -Microsoft.iOS.dll:Registrar.Registrar/ObjCMember..ctor() Microsoft.iOS.dll:Registrar.Registrar/ObjCMember..ctor(Registrar.Registrar, Registrar.Registrar/ObjCType) Microsoft.iOS.dll:Registrar.Registrar/ObjCMember.get_FullName() Microsoft.iOS.dll:Registrar.Registrar/ObjCMember.get_IsImplicit() @@ -1126,7 +1125,7 @@ Microsoft.iOS.dll:Registrar.Registrar/ObjCMethod.ValidateSignature(System.Collec Microsoft.iOS.dll:Registrar.Registrar/ObjCMethod.WriteUnmanagedDescription(System.IntPtr, System.Reflection.MethodBase) Microsoft.iOS.dll:Registrar.Registrar/ObjCMethod.WriteUnmanagedDescription(System.IntPtr) Microsoft.iOS.dll:Registrar.Registrar/ObjCProperty -Microsoft.iOS.dll:Registrar.Registrar/ObjCProperty..ctor() +Microsoft.iOS.dll:Registrar.Registrar/ObjCProperty..ctor(Registrar.Registrar, Registrar.Registrar/ObjCType) Microsoft.iOS.dll:Registrar.Registrar/ObjCProperty.get_FullName() Microsoft.iOS.dll:Registrar.Registrar/ObjCProperty.get_IsNativeStatic() Microsoft.iOS.dll:Registrar.Registrar/ObjCProperty.get_IsReadOnly() @@ -1142,7 +1141,7 @@ Microsoft.iOS.dll:Registrar.Registrar/ObjCType Registrar.Registrar/ObjCType::Bas Microsoft.iOS.dll:Registrar.Registrar/ObjCType Registrar.Registrar/ObjCType::superType Microsoft.iOS.dll:Registrar.Registrar/ObjCType Registrar.Registrar/ObjCType::SuperType() Microsoft.iOS.dll:Registrar.Registrar/ObjCType..cctor() -Microsoft.iOS.dll:Registrar.Registrar/ObjCType..ctor() +Microsoft.iOS.dll:Registrar.Registrar/ObjCType..ctor(Registrar.Registrar, System.Type) Microsoft.iOS.dll:Registrar.Registrar/ObjCType.Add(Registrar.Registrar/ObjCField, System.Collections.Generic.List`1&) Microsoft.iOS.dll:Registrar.Registrar/ObjCType.Add(Registrar.Registrar/ObjCMethod, System.Collections.Generic.List`1&) Microsoft.iOS.dll:Registrar.Registrar/ObjCType.Add(Registrar.Registrar/ObjCProperty, System.Collections.Generic.List`1&)