Skip to content

Commit

Permalink
[bgen] Fix detecting NSObject types and generating block code with ty…
Browse files Browse the repository at this point in the history
…pes that aren't NSObjects. (xamarin#21181)
  • Loading branch information
rolfbjarne authored Sep 10, 2024
1 parent ec75380 commit 39459a2
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 2 deletions.
21 changes: 19 additions & 2 deletions src/bgen/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,22 @@ public bool IsNSObject (Type type)
return false;
}

return type.IsInterface;
// If any of the interfaces this type implements is an NSObject,
// then this type is also an NSObject
var ifaces = type.GetInterfaces ();
foreach (var iface in ifaces)
if (IsNSObject (iface))
return true;

if (type.IsInterface) {
var bta = ReflectionExtensions.GetBaseTypeAttribute (type, this);
if (bta?.BaseType is not null)
return IsNSObject (bta.BaseType);

return false;
}

return false;
}

public string PrimitiveType (Type t, bool formatted = false)
Expand Down Expand Up @@ -604,8 +619,10 @@ public TrampolineInfo MakeTrampoline (Type t)
invoke.AppendFormat (" Runtime.GetINativeObject<{1}> ({0}, false)!", safe_name, pi.ParameterType);
} else if (isForced) {
invoke.AppendFormat (" Runtime.GetINativeObject<{1}> ({0}, true, {2})!", safe_name, TypeManager.RenderType (pi.ParameterType), isForcedOwns);
} else {
} else if (IsNSObject (pi.ParameterType)) {
invoke.AppendFormat (" Runtime.GetNSObject<{1}> ({0})!", safe_name, TypeManager.RenderType (pi.ParameterType));
} else {
invoke.AppendFormat (" Runtime.GetINativeObject<{1}> ({0}, false)!", safe_name, TypeManager.RenderType (pi.ParameterType));
}
continue;
}
Expand Down
14 changes: 14 additions & 0 deletions tests/generator/BGenTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,20 @@ public void Bug35176 ()
Assert.AreEqual (expectedAttributes, renderedAttributes, "Introduced attributes");
}

[Test]
[TestCase (Profile.iOS)]
public void INativeObjectsInBlocks (Profile profile)
{
var bgen = new BGenTool ();
bgen.Profile = profile;
bgen.Defines = BGenTool.GetDefaultDefines (bgen.Profile);
bgen.AddTestApiDefinition ("tests/inativeobjects-in-blocks.cs");
bgen.AddExtraSourcesRelativeToGeneratorDirectory ("tests/inativeobjects-in-blocks-sources.cs");
bgen.CreateTemporaryBinding ();
bgen.AssertExecute ("build");
bgen.AssertNoWarnings ();
}

[Test]
public void Bug36457 ()
{
Expand Down
14 changes: 14 additions & 0 deletions tests/generator/BGenTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class BGenTool : Tool {

public List<string> ApiDefinitions = new List<string> ();
public List<string> Sources = new List<string> ();
public List<string> ExtraSources = new List<string> ();
public List<string> References = new List<string> ();
#if NET
public List<string>? CompileCommand = null;
Expand Down Expand Up @@ -71,6 +72,16 @@ public void AddTestApiDefinition (string filename)
ApiDefinitions.Add (Path.Combine (Configuration.SourceRoot, "tests", "generator", filename));
}

public void AddExtraSourcesRelativeToGeneratorDirectory (string pathRelativeToGeneratorDirectory)
{
ExtraSources.Add (GetFullPathRelativeToGeneratorDirectory (pathRelativeToGeneratorDirectory));
}

public string GetFullPathRelativeToGeneratorDirectory (string pathRelativeToGeneratorDirectory)
{
return Path.Combine (Configuration.SourceRoot, "tests", "generator", pathRelativeToGeneratorDirectory);
}

public AssemblyDefinition ApiAssembly {
get {
return LoadAssembly ();
Expand Down Expand Up @@ -169,6 +180,9 @@ string [] BuildArgumentArray ()
foreach (var s in Sources)
sb.Add ($"-s={s}");

foreach (var x in ExtraSources)
sb.Add ($"-x={x}");

if (ReferenceBclByDefault) {
if (tf is null) {
// do nothing
Expand Down
9 changes: 9 additions & 0 deletions tests/generator/tests/inativeobjects-in-blocks-sources.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;

using CoreFoundation;
using Foundation;
using ObjCRuntime;

namespace NS {
public partial class DispatchData2 : NativeObject { }
}
21 changes: 21 additions & 0 deletions tests/generator/tests/inativeobjects-in-blocks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;

using CoreFoundation;
using Foundation;
using ObjCRuntime;

namespace NS {

[Partial]
interface DispatchData2 {
}

delegate void DispatchB (DispatchData2 data);
delegate void DispatchA (DispatchData2 data, [BlockCallback] DispatchB dispatch);

[BaseType (typeof (NSObject))]
interface INativeObjectInBlocks {
[Export ("someProperty")]
DispatchA SomeProperty { get; set; }
}
}

0 comments on commit 39459a2

Please sign in to comment.