tingraldi / SwiftScripting

Utilities and samples to aid in using Swift with the Scripting Bridge. If you want to automate tasks on your Mac, but don't like AppleScript, this is for you.
285 stars 29 forks source link

Bug: Functions lack return values on Mojave / Xcode 10 #18

Open bdkjones opened 6 years ago

bdkjones commented 6 years ago

Here is part of Finder.h generated in Objective-C, following Apple's usual instructions:

screen shot 2018-10-03 at 16 41 25

And here is what gets generated for the Swift API:

screen shot 2018-10-03 at 16 47 41

The Issue

Notice that in the ObjC version, -items returns an SBElementArray of FinderItem objects. In the Swift version, items() returns void. This is not correct and completely breaks the API.

Manually changing the Swift file to:

@objc optional func items() -> SBElementArray

Causes items() to return the expected value, which can then be used. I do not see how a void return can be appropriate here and believe this is a bug with the scripts translating the sdef into Swift.

tingraldi commented 6 years ago

Hello, and thank you for checking out SwiftScripting.

The Xcode command line tools need to be installed for the sbhc.py script to work properly.

You can issue the command xcode-select --install in a Terminal window to initiate installation of the command line tools.

bdkjones commented 6 years ago

Thanks for the quick reply! I have installed the command line tools, but that makes no difference. I've spent some time diving into the issue by adding some logging to sbhc.py and here's what I'm seeing:

screen shot 2018-10-03 at 19 18 09

emit_fuction walks the children property of the cursor we pass in, and then looks for one that does not have the "parameter" type. I log all the children and you can see that items has none. The only children that appear are parameters. So it would seem that return_type will never be anything but nil.

Attempting to log the kind property of result_type shows everything to have an INVALID return type.

Question:

Have you tested the script using Xcode 10 and Mojave? That's what I'm running on. I have not tried Xcode 9 and High Sierra.

orchetect commented 6 years ago

I'm also curious about anyone's experience with Xcode 10 & Mojave. I have an app using Scripting Bridge that worked fine on High Sierra but on Mojave the Scripting Bridge code compiles but doesn't do anything. I think it has something to do with the new security restrictions in 10.14. Haven't tackled fixing it yet but anyone else run into this and find a solution?

I've run through all the obvious stuff like adding the app to the various categories in the Security pane of System Preferences, etc. Strangely, the OS is not popping up the permission request dialog like most other apps will when they try to script another app.

bdkjones commented 6 years ago

@orchetect That's a different issue. Have you enabled the new Hardened Runtime for your app and granted the AppleEvents entitlement? You'll also need to add some specific keys to your info.plist file or the app will crash the first time you ask for permission to send an AppleEvent. (See the WWDC session video about it.)

orchetect commented 6 years ago

@bdkjones Thanks for the tip. I did watch some of the new Apple videos on this topic but that wasn't mentioned.

bdkjones commented 6 years ago

@orchetect They spent a good while on it in the session about modern security and securing your app.

orchetect commented 6 years ago

@bdkjones Bingo. Works now after adding entitlements and plist entries.

Re: your original post - that's a good idea. I haven't tested the script on Mojave yet but I remember even on Sierra I ran into problems that required a fair amount of hand-editing of the resulting output. And if I recall the script wasn't even working (some or all of the time). But I figured out what needed to go where.

bdkjones commented 6 years ago

Well, I'm making progress. I went back to High Sierra and Xcode 9.4.1. When I ran pip install clang I got version 6.0.0. This threw an error about a missing symbol. So, I ran pip install clang==3.5 and then ran it again. This is the output:

screen shot 2018-10-03 at 8 35 06 pm

Notice that the return values ARE now listed as children of each cursor. I'm going to try Mojave with Clang 3.5 and see if I can get the same result.

bdkjones commented 6 years ago

Back on Mojave, with Xcode 10 and clang 3.5, I get this output:

screen shot 2018-10-03 at 20 42 12

It would appear that something has changed in Clang?

bdkjones commented 6 years ago

This is the extent of my abilities in Python, so I'm unable to take this farther. I can simply confirm that Xcode 10 on Mojave breaks the script, even when using the older clang python bindings. I'd love to see a fix!

bdkjones commented 6 years ago

I'm motivated to fix the issue, but without a deep understanding of Clang's inner workings, I've had to enlist help. Hopefully somebody can figure out what's changed:

https://stackoverflow.com/questions/52640399/libclang-python-binding-get-objc-method-return-value

bdkjones commented 6 years ago

@tingraldi any ideas of what I should try? Happy to play around some more.

tingraldi commented 6 years ago

@bdkjones I haven't yet made the leap to Mojave. I don't have any tips off the top of my head to get past this issue. I hope to get on Mojave before too long. If the Scripting Bridge is still viable there, we should be able to move forward.

bdkjones commented 6 years ago

@tingraldi Ha! Has it ever really been viable? Tolerable, maybe. Infuriating, definitely.

I sent an email to the Clang mailing list asking for their help. One guy who worked on the Python bindings replied and said he might take a look. I'm thinking something either (A) changed or (B) broke in Clang 10.0.0.0, which is the version shipped with Xcode 10. I've gone all the way up to the translation unit and logged every single cursor and every property/child I can get for each one: nothing turns up an ObjC return type.

I'm giving it some time to see what the mailing list comes up with, but all I can think to do is ask the cursor for its location in the source file and then go manually pull any alphanumeric characters that appear in a - ( ) wrapper, up to the first NON-alphanumeric character, which eliminates the * and things like NSArray<NSString *> * etc.

adam-rocska commented 3 years ago

@bdkjones @tingraldi @orchetect

This should be solved by now either "with time" either with this PR

I wasn't able to reproduce the issue.

bdkjones commented 3 years ago

Excellent! Once @tingraldi merges that PR I’ll give it a shot and report back.