diff --git a/tests/sharpie/Tests/ObjCGenerics.iphoneos.cs b/tests/sharpie/Tests/ObjCGenerics.iphoneos.cs index 68ed305d6555..63e042105327 100644 --- a/tests/sharpie/Tests/ObjCGenerics.iphoneos.cs +++ b/tests/sharpie/Tests/ObjCGenerics.iphoneos.cs @@ -6,16 +6,16 @@ interface CNLabeledValue : INSCopying, INSSecureCoding { // @property (readonly, copy, nonatomic) ValueType ValueTypeProperty; [Export ("ValueTypeProperty", ArgumentSemantic.Copy)] - NSObject ValueTypeProperty { get; } + NSObject ValueTypeProperty { get; } // -(ValueType _Nullable)getValueTypeMethod; [NullAllowed, Export ("getValueTypeMethod")] [Verify (MethodToProperty)] - NSObject ValueTypeMethod { get; } + NSObject ValueTypeMethod { get; } // -(void)setValueTypeMethod:(ValueType _Nullable)obj; [Export ("setValueTypeMethod:")] - void SetValueTypeMethod ([NullAllowed] NSObject obj); + void SetValueTypeMethod ([NullAllowed] NSObject obj); } // @protocol A diff --git a/tests/sharpie/Tests/ObjCGenerics.macosx.cs b/tests/sharpie/Tests/ObjCGenerics.macosx.cs index 68ed305d6555..63e042105327 100644 --- a/tests/sharpie/Tests/ObjCGenerics.macosx.cs +++ b/tests/sharpie/Tests/ObjCGenerics.macosx.cs @@ -6,16 +6,16 @@ interface CNLabeledValue : INSCopying, INSSecureCoding { // @property (readonly, copy, nonatomic) ValueType ValueTypeProperty; [Export ("ValueTypeProperty", ArgumentSemantic.Copy)] - NSObject ValueTypeProperty { get; } + NSObject ValueTypeProperty { get; } // -(ValueType _Nullable)getValueTypeMethod; [NullAllowed, Export ("getValueTypeMethod")] [Verify (MethodToProperty)] - NSObject ValueTypeMethod { get; } + NSObject ValueTypeMethod { get; } // -(void)setValueTypeMethod:(ValueType _Nullable)obj; [Export ("setValueTypeMethod:")] - void SetValueTypeMethod ([NullAllowed] NSObject obj); + void SetValueTypeMethod ([NullAllowed] NSObject obj); } // @protocol A diff --git a/tools/sharpie/Sharpie.Bind/Massagers/PlatformTypeMappingMassager.cs b/tools/sharpie/Sharpie.Bind/Massagers/PlatformTypeMappingMassager.cs index 3d36915ccdc2..6137a057916b 100644 --- a/tools/sharpie/Sharpie.Bind/Massagers/PlatformTypeMappingMassager.cs +++ b/tools/sharpie/Sharpie.Bind/Massagers/PlatformTypeMappingMassager.cs @@ -12,7 +12,7 @@ namespace Sharpie.Bind.Massagers; [RegisterBefore (typeof (GenerateUsingStatementsMassager))] public sealed class PlatformTypeMappingMassager : Massager { readonly Dictionary typeMap = new (); - readonly Dictionary protocolMap = new (); + readonly HashSet protocolEntries = new (); readonly Stack ignoreType = new Stack (); public PlatformTypeMappingMassager (ObjectiveCBinder binder) @@ -23,6 +23,7 @@ public PlatformTypeMappingMassager (ObjectiveCBinder binder) public override bool Initialize () { typeMap.Clear (); + protocolEntries.Clear (); var path = base.Binder.PlatformAssembly; var decoder = new TypelessDecoder (); @@ -73,12 +74,30 @@ public override bool Initialize () var etName = mr.GetString (et.Name); nativeName ??= etName; - var map = typeMap; - if (map.Remove (nativeName)) { - // there would be a collision, so skip adding again - continue; + var entry = (etNamespace + "." + etName, etNamespace, etName); + if (typeMap.ContainsKey (nativeName)) { + // When two types map to the same native name, prefer the + // standard protocol interface (named "I" + nativeName, e.g. + // INSCopying for "NSCopying") over a [Model] class or a + // non-standard protocol. If neither or both follow the + // convention, drop both (genuine ambiguity). + bool newIsStandardProtocol = isProtocolAttribute && etName == "I" + nativeName; + bool existingIsStandardProtocol = protocolEntries.Contains (nativeName); + if (newIsStandardProtocol && !existingIsStandardProtocol) { + typeMap [nativeName] = entry; + protocolEntries.Add (nativeName); + } else if (!newIsStandardProtocol && existingIsStandardProtocol) { + // existing is the standard protocol, keep it + } else { + // genuine collision, drop both + typeMap.Remove (nativeName); + protocolEntries.Remove (nativeName); + } + } else { + typeMap.Add (nativeName, entry); + if (isProtocolAttribute && etName == "I" + nativeName) + protocolEntries.Add (nativeName); } - map.Add (nativeName, (etNamespace + "." + etName, etNamespace, etName)); } return typeMap.Count > 0;