Conversation
|
Hi @liamappelbe, Following your suggestion, I added print statements to dump the full platform availability information for every method. This revealed that After correctly filtering I initially tried guarding against this in the visitor, but due to the execution order the guard triggered too early. The final fix stores the unavailable selectors in Thanks! |
9295ec2 to
34c1e3e
Compare
34c1e3e to
51f7a4d
Compare
PR HealthBreaking changes ✔️
This check can be disabled by tagging the PR with API leaks ✔️The following packages contain symbols visible in the public API, but not exported by the library. Export these symbols or remove them from your publicly visible API.
This check can be disabled by tagging the PR with |
liamappelbe
left a comment
There was a problem hiding this comment.
Good job getting it working despite those issues. I wonder if there's a better approach to the filtering issues though.
Your current approach, where these methods aren't filtered until codegen, has a minor issue where they'll still participate in the logic to pull in transitive deps. This could result in unnecessary bindings being generated. So you'd have to also update the other visitors to check if the method is swiftUnavailable.
A better approach would be to remove ApiAvailability.swiftUnavailable, and set ApiAvailability.alwaysUnavailable instead. You'll run into the same bug as before, where filtering removes the method only for copying from supertypes to add it back in.
But I think this is actually an existing bug you've discovered, which also applies to any other method with an availability annotation. We filter out methods (and other APIs) based on their availability annotation during parsing, which is a bit of a hack. If this results in a method being filtered, there's nothing stopping a supertype from re-adding that method later.
So I think it would be better to fix that bug for all cases, rather than special casing swiftUnavailable to work around it. Rather than deleting filtered methods, we should keep them around so that the copy supertype methods visitor can avoid overwriting the unavailable method.
- Remove
ApiAvailability.swiftUnavailableand setApiAvailability.alwaysUnavailableinstead when you see that swift availability annotation. - Remove this hacky filter. And this one too.
- Add an
unavailableutil method toObjCMethodthat checks the availability annotation, same as the one onObjCInterface. - Update
ObjCMethods._shouldReplaceMethodto return false if eitheroldMethod.unavailableornewMethod.unavailable. This fixes the copy supertype methods bug. - Update
ApplyConfigFiltersVisitation, adding a check form.unavailableto all 3node.filterMethodsmethods.
pkgs/ffigen/lib/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart
Outdated
Show resolved
Hide resolved
|
@liamappelbe Thanks for the detailed feedback, I think i am lucky at discovering bugs through issues i try to resolve :) I tried implementing your suggested approach but hit a conflict in Step 1. Setting Since the two annotations come from different sources in the AST |
…methods in ApplyConfigFiltersVisitation
That's bizarre. Sounds like the test is incorrect. But it was passing, so I guess that's also a bug? Can you investigate that and figure out why they're not being omitted? Check if those method's availability data is being correctly parsed here. Were there any other issues with the approach I suggested, or was it just that failing test? |
@liamappelbe You were right the deprecated_test expectations were incorrect. and all tests pass now based on the approach you suggested, i will push the changes now |
|
@liamappelbe I think this failure due to that our solution can't distinguish between developer explicitly marking init as SWIFT_UNAVAILABLE and Swift compiler auto-generating? |
|
No, these failures just mean that you need to regenerate those bindings. |
@liamappelbe Oh ok, can you please do it as I do not have a mac and test using GitHub actions? Or let me first try using AI to compare between expected and actual and update them. |
|
Done |
|
That's weird. Why did the signature of |
|
I get the same diff at HEAD, so this isn't a bug in your PR. I'll investigate and push a fix asap (probably tomorrow). |
Ok, Let me know if there's anything I can help with. |
|
Figured it out. #3135 made it so that FFIgen respects which version of xcode you have selected, and on my machine I have a few versions of xcode. The version I had selected was a really old version that apparently declares these APIs differently in the headers. That's concerning, but I can easily work around it by selecting a different xcode version. |
FFIgen dealing with many layers,So i think it's more complex, unlike swift2objc, which has to go in one direction, which encourages me to put more effort into it the next days |
liamappelbe
left a comment
There was a problem hiding this comment.
Looks pretty good. Needs a changelog entry though, in ffigen and objective_c.
The objective_c changelog should say: "Removed NSOrderedCollectionChange.init(). This is not a breaking change because this method never would have worked, as it doesn't exist in Objective-C.
| macos = platformAvailability..name = 'macOS'; | ||
| break; | ||
| case 'swift': | ||
| if (platformAvailability.unavailable && |
There was a problem hiding this comment.
Is this still necessary? I thought your fixes to the deprecated test meant you didn't need this extra treatSwiftUnavailableAsUnavailable logic anymore?
Fixes: #2665
ffigen was generating a no arg constructor, for Swift classes that explicitly mark
init/newasSWIFT_UNAVAILABLE,causing runtime crashes. Fixed by detecting the annotation via Clang's platform availability AST and blocking the inherited
newfrom being copied onto the interface during code generation.