Skip to content

Commit

Permalink
[bgen] Fix using types that are in multiple namespaces. (#21182)
Browse files Browse the repository at this point in the history
There's both a Network.NWEndpoint and a NetworkExtension.NWEndpoint, and the
generator generates ambiguous code in certain cases.

Fix the generator to use the full type reference for such types.
  • Loading branch information
rolfbjarne authored Sep 9, 2024
1 parent 7325ce8 commit 941ead0
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/bgen/Caches/NamespaceCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class NamespaceCache {
public ICollection<string> UINamespaces { get; private set; }
public ICollection<string> ImplicitNamespaces { get; private set; }
public ICollection<string> NamespacesThatConflictWithTypes { get; private set; }
public ICollection<string> TypesInMultipleNamespaces { get; private set; }

public NamespaceCache (PlatformName currentPlatform, string customObjCRuntimeNS, bool skipSystemDrawing)
{
Expand Down Expand Up @@ -154,6 +155,10 @@ public NamespaceCache (PlatformName currentPlatform, string customObjCRuntimeNS,
"AudioUnit",
};

TypesInMultipleNamespaces = new HashSet<string> {
"NWEndpoint", // Both in Network and NetworkExtension
};

if (!skipSystemDrawing)
ImplicitNamespaces.Add ("System.Drawing");
}
Expand Down
3 changes: 3 additions & 0 deletions src/bgen/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 ());
}
Expand Down
18 changes: 17 additions & 1 deletion src/bgen/TypeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down
7 changes: 7 additions & 0 deletions tests/generator/BGenTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 ()
{
Expand Down
15 changes: 15 additions & 0 deletions tests/generator/tests/types-in-multiple-namespaces.cs
Original file line number Diff line number Diff line change
@@ -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; }
}
}

13 comments on commit 941ead0

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

Please sign in to comment.