[xtro] Report extra/unknown managed selectors with no native declaration. Fixes #26053.#26135
[xtro] Report extra/unknown managed selectors with no native declaration. Fixes #26053.#26135rolfbjarne wants to merge 2 commits into
Conversation
…ion. xtro only validated selectors native -> managed (!missing-selector!). It never flagged the reverse: a managed [Export] selector with no matching native declaration in the current SDK headers. When Apple removes or privatizes a selector, the managed binding becomes stale but xtro stayed silent, and introspection can't detect a privatized-but-still-implemented selector (a respondsToSelector: call still returns true). Add a reverse check to SelectorCheck that reports '!unknown-selector!' for a managed 'Type::selector' when 'selector' is not part of the effective set of selectors for the native class 'Type', which is: * the selectors declared directly on the class (and its categories); * plus the selectors declared on every base class (and their categories); * plus the selectors of every adopted protocol, transitively through protocol inheritance. The set of adopted protocols is taken from both the headers and the managed binding: Apple frequently implements a protocol (e.g. NSCoding, NSCopying) without declaring the conformance on the class, and the managed binding is the authority on which protocols a class inlines - crediting them avoids a large number of false positives. Additional false-positive guards: * Only publicly visible managed types are checked (internal dispatcher/proxy helper types use fabricated selectors), mirroring the '!unknown-type!' check. * Managed types whose native name has no declaration in the headers are skipped (that's the '!unknown-type!' case). * Frameworks not parsed natively (e.g. excluded from the sharpie run) are skipped. The pre-existing bindings surfaced by the new check (private/SPI selectors, protocol/category members Apple inlines without declaring the conformance on the class, managed callback infrastructure, and API Apple dropped) are added to the per-platform .ignore files as the reviewed baseline; any new occurrence will now fail the build - the deterministic signal requested in the issue. Fixes #26053 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: ffddc3c0-7309-450c-a89e-3898e80a0647
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Pull request overview
Adds a reverse selector validation to xtro (managed → native) so bindings with managed [Export] selectors that are no longer declared in the current SDK headers are reported as !unknown-selector! (fixing the gap described in #26053). This provides a deterministic signal to remove/adjust stale bindings when Apple removes or privatizes API.
Changes:
- Extend
SelectorCheckto compute an “effective selector set” per native class (including base classes, categories, and adopted protocols) and report managed selectors not present in that set as!unknown-selector!. - Add baseline
!unknown-selector!entries to per-platformapi-annotations-dotnet/*.ignorefiles so existing known deltas don’t fail the build, while new ones will. - Add per-file explanatory headers for the new baseline ignore sections.
Reviewed changes
Copilot reviewed 51 out of 51 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/xtro-sharpie/xtro-sharpie/SelectorCheck.cs | Implements managed→native selector validation and emits !unknown-selector! for stale managed exports |
| tests/xtro-sharpie/api-annotations-dotnet/tvOS-VideoSubscriberAccount.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/tvOS-UIKit.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/tvOS-ModelIO.ignore | New ignore file baselining !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/tvOS-MetalPerformanceShaders.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/tvOS-Metal.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/tvOS-GLKit.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/tvOS-Foundation.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/tvOS-CloudKit.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/macOS-WebKit.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/macOS-VideoToolbox.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/macOS-VideoSubscriberAccount.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/macOS-ModelIO.ignore | New ignore file baselining !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/macOS-MetalPerformanceShaders.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/macOS-Metal.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/macOS-ImageCaptureCore.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/macOS-FSKit.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/macOS-Foundation.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/macOS-FileProvider.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/macOS-CoreSpotlight.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/macOS-CloudKit.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/macOS-AuthenticationServices.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/macOS-AppKit.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/MacCatalyst-WebKit.ignore | New ignore file baselining !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/MacCatalyst-UIKit.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/MacCatalyst-StoreKit.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/MacCatalyst-SensorKit.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/MacCatalyst-PencilKit.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/MacCatalyst-ModelIO.ignore | New ignore file baselining !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/MacCatalyst-MetalPerformanceShaders.ignore | New ignore file baselining !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/MacCatalyst-Metal.ignore | New ignore file baselining !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/MacCatalyst-Messages.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/MacCatalyst-Foundation.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/MacCatalyst-CoreSpotlight.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/MacCatalyst-CloudKit.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/iOS-WebKit.ignore | New ignore file baselining !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/iOS-VideoSubscriberAccount.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/iOS-UIKit.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/iOS-PencilKit.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/iOS-ModelIO.ignore | New ignore file baselining !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/iOS-MetalPerformanceShaders.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/iOS-Metal.ignore | New ignore file baselining !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/iOS-Messages.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/iOS-GLKit.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/iOS-Foundation.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/iOS-DeviceDiscoveryUI.ignore | New ignore file baselining !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/iOS-CoreSpotlight.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/iOS-CloudKit.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/iOS-CarPlay.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/iOS-AVFoundation.ignore | Baseline ignores for newly-reported !unknown-selector! findings |
| tests/xtro-sharpie/api-annotations-dotnet/iOS-AccessorySetupKit.ignore | New ignore file baselining !unknown-selector! findings |
This comment has been minimized.
This comment has been minimized.
* Guard against a null result from `TypeReference.Resolve ()` before calling `GetProtocolName`, which dereferences its argument (would throw if a referenced interface type can't be resolved, e.g. a missing assembly). * Use `GetSelector ()` instead of `.Name` when collecting native property accessor selectors, for consistency with the method-declaration path (which uses `GetSelector ()`, preferring `Selector.ToString ()`). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: ffddc3c0-7309-450c-a89e-3898e80a0647
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
✅ API diff for current PR / commitNET (empty diffs)✅ API diff vs stableNET (empty diffs)ℹ️ Generator diffGenerator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes) Pipeline on Agent |
🚀 [CI Build #905187f] Test results 🚀Test results✅ All tests passed on VSTS: test results. 🎉 All 203 tests passed 🎉 Tests counts✅ assembly-processing: All 1 tests passed. Html Report (VSDrops) Download macOS tests✅ Tests on macOS Monterey (12): All 5 tests passed. Html Report (VSDrops) Download Linux Build VerificationPipeline on Agent |
xtro only validated selectors native → managed (
!missing-selector!). It never flagged the reverse: a managed[Export]selector with no matching native declaration in the current SDK headers. When Apple removes or privatizes a selector, the managed binding becomes stale but xtro stayed silent, and introspection can't detect a privatized-but-still-implemented selector (arespondsToSelector:call still returns true).This adds a reverse check to
SelectorCheckthat reports!unknown-selector!for a managedType::selectorwhenselectoris not part of the effective set of selectors for the native classType, which is:The set of adopted protocols is taken from both the headers and the managed binding: Apple frequently implements a protocol (e.g.
NSCoding,NSCopying) without declaring the conformance on the class, and the managed binding is the authority on which protocols a class inlines — crediting them avoids a large number of false positives (this alone reduced the reported entries from ~450 to 144).Additional false-positive guards:
!unknown-type!check.!unknown-type!case).The pre-existing bindings surfaced by the new check (private/SPI selectors, protocol/category members Apple inlines without declaring the conformance on the class, managed callback infrastructure, and API Apple dropped) are added to the per-platform
.ignorefiles as the reviewed baseline; any new occurrence will now fail the build — the deterministic signal requested in the issue.Fixes #26053.
🤖 Pull request created by Copilot