diff --git a/src/bgen/Caches/NamespaceCache.cs b/src/bgen/Caches/NamespaceCache.cs index 90463540d343..9ce97d9dc208 100644 --- a/src/bgen/Caches/NamespaceCache.cs +++ b/src/bgen/Caches/NamespaceCache.cs @@ -17,6 +17,7 @@ public class NamespaceCache { public ICollection UINamespaces { get; private set; } public ICollection ImplicitNamespaces { get; private set; } public ICollection NamespacesThatConflictWithTypes { get; private set; } + public ICollection TypesInMultipleNamespaces { get; private set; } public NamespaceCache (PlatformName currentPlatform, string customObjCRuntimeNS, bool skipSystemDrawing) { @@ -154,6 +155,10 @@ public NamespaceCache (PlatformName currentPlatform, string customObjCRuntimeNS, "AudioUnit", }; + TypesInMultipleNamespaces = new HashSet { + "NWEndpoint", // Both in Network and NetworkExtension + }; + if (!skipSystemDrawing) ImplicitNamespaces.Add ("System.Drawing"); } diff --git a/src/bgen/Generator.cs b/src/bgen/Generator.cs index 8c97f6c1fcf5..05ce9781c4f0 100644 --- a/src/bgen/Generator.cs +++ b/src/bgen/Generator.cs @@ -894,6 +894,9 @@ public string MarshalParameter (MethodInfo mi, ParameterInfo pi, bool null_allow return safe_name + ".Handle"; } + if (TypeCache.INativeObject.IsAssignableFrom (pi.ParameterType)) + return $"{safe_name}.GetHandle ()"; + // This means you need to add a new MarshalType in the method "Go" throw new BindingException (1002, true, pi.ParameterType.FullName, mi.DeclaringType.FullName, mi.Name.GetSafeParamName ()); } diff --git a/src/bgen/TypeManager.cs b/src/bgen/TypeManager.cs index 2cdc7a1238d7..a608bf75348d 100644 --- a/src/bgen/TypeManager.cs +++ b/src/bgen/TypeManager.cs @@ -300,12 +300,17 @@ public string FormatTypeUsedIn (string? usedInNamespace, Type? type) if (t.Namespace is not null) { string ns = t.Namespace; - if (NamespaceCache.ImplicitNamespaces.Contains (ns) || t.IsGenericType) { + var isImplicitNamespace = NamespaceCache.ImplicitNamespaces.Contains (ns); + var isInMultipleNamespaces = IsInMultipleNamespaces (t); + var nonGlobalCandidate = isImplicitNamespace && !isInMultipleNamespaces; + if (nonGlobalCandidate || t.IsGenericType) { var targs = t.GetGenericArguments (); if (targs.Length == 0) return t.Name + nullable; return $"global::{t.Namespace}." + t.Name.RemoveArity () + "<" + string.Join (", ", targs.Select (l => FormatTypeUsedIn (null, l)).ToArray ()) + ">" + nullable; } + if (isInMultipleNamespaces) + return "global::" + t.FullName + nullable; if (NamespaceCache.NamespacesThatConflictWithTypes.Contains (ns)) return "global::" + t.FullName + nullable; if (t.Name == t.Namespace) @@ -317,6 +322,17 @@ public string FormatTypeUsedIn (string? usedInNamespace, Type? type) return t.FullName + nullable; } + bool IsInMultipleNamespaces (Type? type) + { + if (type is null) + return false; + + if (NamespaceCache.TypesInMultipleNamespaces.Contains (type.Name)) + return true; + + return IsInMultipleNamespaces (type.GetElementType ()); + } + // TODO: If we ever have an API with nested properties of the same name more than // 2 deep, we'll need to have this return a list of PropertyInfo and comb through them all. public PropertyInfo? GetParentTypeWithSameNamedProperty (BaseTypeAttribute bta, string propertyName) diff --git a/tests/generator/BGenTests.cs b/tests/generator/BGenTests.cs index 629381f707fb..3295ffd1e6e2 100644 --- a/tests/generator/BGenTests.cs +++ b/tests/generator/BGenTests.cs @@ -526,6 +526,13 @@ public void StackOverflow20696157 () BuildFile (Profile.iOS, "sof20696157.cs"); } + [Test] + [TestCase (Profile.iOS)] + public void TypesInMultipleNamespaces (Profile profile) + { + BuildFile (profile, "tests/types-in-multiple-namespaces.cs"); + } + [Test] public void HyphenInName () { diff --git a/tests/generator/tests/types-in-multiple-namespaces.cs b/tests/generator/tests/types-in-multiple-namespaces.cs new file mode 100644 index 000000000000..37fae9e134f7 --- /dev/null +++ b/tests/generator/tests/types-in-multiple-namespaces.cs @@ -0,0 +1,15 @@ +using System; + +using CoreFoundation; +using Foundation; +using ObjCRuntime; + +namespace NS { + delegate void D1 ([NullAllowed] Network.NWEndpoint remoteEndpoints); + + [BaseType (typeof (NSObject))] + interface TypesInMultipleNamespaces { + [Export ("someProperty")] + D1 SomeProperty { get; set; } + } +}