Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bgen] Fix using types that are in multiple namespaces. #21182

Merged
merged 3 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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; }
}
}