Skip to content

[swift2objc] Support throws annotation #1766

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 1, 2024
Merged

[swift2objc] Support throws annotation #1766

merged 2 commits into from
Dec 1, 2024

Conversation

liamappelbe
Copy link
Contributor

@liamappelbe liamappelbe commented Nov 29, 2024

Methods and functions in Swift that can throw an exception must be annotated with throws. When you call one of these functions, you have to either handle the exception, or forward it by prefixing the call with try (in which case your function must also be marked throws).

So when we're wrapping one of these methods we need to add try and throws keywords, like this:

@objc public class MyClassWrapper: NSObject {
  var wrappedInstance: MyClass

  @objc public func voidMethod() throws {
    return try wrappedInstance.voidMethod()
  }
}

throws shows up in the declarationFragments of the function, after the ) but before the ->. Getters can also throw, but supporting them is a little more complicated.

Details

  • I didn't realize about the issues with throwing getters until I'd already implemented their AST and parsing changes. So I'm leaving those changes in and just logging an error if we hit that case. It makes the error a bit nicer for users anyway.
  • In the AST, added a CanThrow interface. Added this to all functions, methods, initializers, properties, and variables.
  • Code-gen is trivial. Just add throws to the method signature, and try when invoking the wrapped method.
  • Parsing is more complicated
    • The old way I was doing token splitting was getting a bit combinatorial, so I changed it to just split text tokens whenever it finds a splittable string. To avoid writing a full tokenizer, it gives up as soon as it finds an unknown prefix, but I've never seen this in real symbolgraphs.
    • I'm also trimming all the whitespace from these tokens now.
    • Now that () is split into ( and ), in parse_type.dart I had to change the _emptyTupleParselet to be a _tupleParselet, though we haven't added support for tuples yet.
    • Changed parseFunctionParams to parseFunctionInfo, which now also checks for annotations. Essentially it just reads all the keywords after the ). Had to refactor a bit to handle all the new token splitting.
    • Cleaned up parse_variable_declaration.dart, using matchFragment.

@coveralls
Copy link

coveralls commented Nov 29, 2024

Coverage Status

coverage: 88.855% (+0.005%) from 88.85%
when pulling 27032c9 on throwsanno
into e69c74d on main.

@liamappelbe liamappelbe marked this pull request as ready for review November 29, 2024 01:06
@liamappelbe liamappelbe merged commit d79f68c into main Dec 1, 2024
6 checks passed
@liamappelbe liamappelbe deleted the throwsanno branch December 1, 2024 22:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants