Skip to content

[sharpie] Fix platform type mapping for types inside generic type arguments. Fixes #24892.#24911

Merged
rolfbjarne merged 2 commits intomainfrom
dev/rolf/issue-24892-sharpie-casing
Mar 17, 2026
Merged

[sharpie] Fix platform type mapping for types inside generic type arguments. Fixes #24892.#24911
rolfbjarne merged 2 commits intomainfrom
dev/rolf/issue-24892-sharpie-casing

Conversation

@rolfbjarne
Copy link
Copy Markdown
Member

The PlatformTypeMappingMassager did not recurse into child nodes (such as type
arguments inside Action<> or Func<>) because the VisitMemberType and
VisitSimpleType overrides did not call their base implementations. This meant
that types like NSURLResponse inside Action<NSData, NSURLResponse> were never
mapped to their .NET equivalents (NSUrlResponse).

Fix by calling base.VisitMemberType/VisitSimpleType before processing the type
itself, so children (type arguments) are mapped first.

Added a test case with a block parameter containing mapped types.

Fixes #24892.

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

rolfbjarne and others added 2 commits March 16, 2026 21:01
…uments

The PlatformTypeMappingMassager did not recurse into child nodes
(such as type arguments inside Action<> or Func<>) because the
VisitMemberType and VisitSimpleType overrides did not call their
base implementations. This meant that types like NSURLResponse
inside Action<NSData, NSURLResponse> were never mapped to their
.NET equivalents (NSUrlResponse).

Fix by calling base.VisitMemberType/VisitSimpleType before processing
the type itself, so children (type arguments) are mapped first.

Added a test case with a block parameter containing mapped types.

Fixes #24892

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ping

The PlatformTypeMappingMassager now correctly recurses into generic
type arguments, which means protocol names like NSSecureCoding inside
generic constraints (e.g. NSObject<NSCopying, NSSecureCoding>) are
now properly mapped to their .NET equivalents (INSSecureCoding).

Update the expected test output to match.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes Sharpie’s PlatformTypeMappingMassager so that platform type mapping is applied recursively inside generic type arguments (for example within Action<>/Func<> block signatures), ensuring native types like NSURLResponse get correctly mapped to their .NET equivalents (e.g. NSUrlResponse). This addresses the generation issue reported in #24892.

Changes:

  • Update PlatformTypeMappingMassager to call base.VisitMemberType / base.VisitSimpleType so child nodes (type arguments) are visited and mapped.
  • Extend the PlatformTypeMapping test header and expected outputs with a block parameter that includes a mapped type inside an Action<>.
  • Update ObjC generics expected outputs to reflect the now-recursive type mapping behavior in generic arguments.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
tools/sharpie/Sharpie.Bind/Massagers/PlatformTypeMappingMassager.cs Ensures AST traversal recurses into generic arguments so nested types are mapped.
tests/sharpie/Tests/Massagers/PlatformTypeMapping.h Adds an Objective-C method with a block parameter containing NSURLResponse to exercise nested mapping.
tests/sharpie/Tests/Massagers/PlatformTypeMapping.macosx.cs Updates expected output to include Action<..., NSUrlResponse> and adds using System;.
tests/sharpie/Tests/Massagers/PlatformTypeMapping.iphoneos.cs Updates expected output to include Action<..., NSUrlResponse> and adds using System;.
tests/sharpie/Tests/ObjCGenerics.macosx.cs Updates expected output for generic type arguments affected by recursive mapping.
tests/sharpie/Tests/ObjCGenerics.iphoneos.cs Updates expected output for generic type arguments affected by recursive mapping.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines -9 to 19
NSObject<NSCopying, NSSecureCoding> ValueTypeProperty { get; }
NSObject<NSCopying, INSSecureCoding> ValueTypeProperty { get; }

// -(ValueType _Nullable)getValueTypeMethod;
[NullAllowed, Export ("getValueTypeMethod")]
[Verify (MethodToProperty)]
NSObject<NSCopying, NSSecureCoding> ValueTypeMethod { get; }
NSObject<NSCopying, INSSecureCoding> ValueTypeMethod { get; }

// -(void)setValueTypeMethod:(ValueType _Nullable)obj;
[Export ("setValueTypeMethod:")]
void SetValueTypeMethod ([NullAllowed] NSObject<NSCopying, NSSecureCoding> obj);
void SetValueTypeMethod ([NullAllowed] NSObject<NSCopying, INSSecureCoding> obj);
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rolfbjarne This is interesting, so we have some inconsistencies in protocols?

Image

While INSSecureCoding is correct, why is NSCopying not getting picked to be INSCopying?

@rolfbjarne rolfbjarne enabled auto-merge (squash) March 17, 2026 15:30
@rolfbjarne
Copy link
Copy Markdown
Member Author

@dalexsoto Good catch — this is a pre-existing inconsistency in the collision detection logic in PlatformTypeMappingMassager.Initialize().

NSCopying has both [Model] + [BaseType] and [Protocol] (in src/foundation.cs), which causes the binding generator to emit two types in the platform assembly:

  • NSCopying class (from [Model]) with [Register("NSCopying")]
  • INSCopying interface (from [Protocol]) with [Protocol(Name="NSCopying")]

Both map to the same native name "NSCopying", which triggers the collision detection (lines 76-80) — when a duplicate native name is found, the existing mapping is removed and the new one is not added. So the mapping is dropped entirely.

NSSecureCoding on the other hand only has [Protocol] (no [Model]/[BaseType]), so only one type is generated:

  • INSSecureCoding interface with [Protocol(Name="NSSecureCoding")]

No collision → the mapping "NSSecureCoding""Foundation.INSSecureCoding" is preserved and applied.

The [Model]/[BaseType] on NSCopying is guarded by #if !XAMCORE_5_0, so this inconsistency will resolve itself when XAMCORE_5_0 is enabled.

@rolfbjarne
Copy link
Copy Markdown
Member Author

I'll ask Copilot to fix this too, in a different pull request.

@vs-mobiletools-engineering-service2
Copy link
Copy Markdown
Collaborator

✅ [CI Build #33b540c] Build passed (Build packages) ✅

Pipeline on Agent
Hash: 33b540c8e7e893e71d3fa19614c9652145fa5243 [PR build]

@vs-mobiletools-engineering-service2
Copy link
Copy Markdown
Collaborator

✅ [PR Build #33b540c] Build passed (Detect API changes) ✅

Pipeline on Agent
Hash: 33b540c8e7e893e71d3fa19614c9652145fa5243 [PR build]

@vs-mobiletools-engineering-service2
Copy link
Copy Markdown
Collaborator

✅ [CI Build #33b540c] Build passed (Build macOS tests) ✅

Pipeline on Agent
Hash: 33b540c8e7e893e71d3fa19614c9652145fa5243 [PR build]

@vs-mobiletools-engineering-service2
Copy link
Copy Markdown
Collaborator

✅ API diff for current PR / commit

NET (empty diffs)

✅ API diff vs stable

NET (empty diffs)

ℹ️ Generator diff

Generator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes)

Pipeline on Agent
Hash: 33b540c8e7e893e71d3fa19614c9652145fa5243 [PR build]

@vs-mobiletools-engineering-service2
Copy link
Copy Markdown
Collaborator

🚀 [CI Build #33b540c] Test results 🚀

Test results

✅ All tests passed on VSTS: test results.

🎉 All 156 tests passed 🎉

Tests counts

✅ cecil: All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (iOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (MacCatalyst): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (macOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (Multiple platforms): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (tvOS): All 1 tests passed. Html Report (VSDrops) Download
✅ framework: All 2 tests passed. Html Report (VSDrops) Download
✅ fsharp: All 4 tests passed. Html Report (VSDrops) Download
✅ generator: All 5 tests passed. Html Report (VSDrops) Download
✅ interdependent-binding-projects: All 4 tests passed. Html Report (VSDrops) Download
✅ introspection: All 6 tests passed. Html Report (VSDrops) Download
✅ linker: All 44 tests passed. Html Report (VSDrops) Download
✅ monotouch (iOS): All 11 tests passed. Html Report (VSDrops) Download
✅ monotouch (MacCatalyst): All 15 tests passed. Html Report (VSDrops) Download
✅ monotouch (macOS): All 12 tests passed. Html Report (VSDrops) Download
✅ monotouch (tvOS): All 11 tests passed. Html Report (VSDrops) Download
✅ msbuild: All 2 tests passed. Html Report (VSDrops) Download
✅ sharpie: All 1 tests passed. Html Report (VSDrops) Download
✅ windows: All 3 tests passed. Html Report (VSDrops) Download
✅ xcframework: All 4 tests passed. Html Report (VSDrops) Download
✅ xtro: All 1 tests passed. Html Report (VSDrops) Download

macOS tests

✅ Tests on macOS Monterey (12): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Ventura (13): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Sonoma (14): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Sequoia (15): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Tahoe (26): All 5 tests passed. Html Report (VSDrops) Download

Pipeline on Agent
Hash: 33b540c8e7e893e71d3fa19614c9652145fa5243 [PR build]

@rolfbjarne rolfbjarne merged commit 03b4918 into main Mar 17, 2026
52 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sharpie generates some classes with wrong casing

4 participants