swift
6cbbb7cb - [Async Refactoring] Split ambiguous (error + success) completion handler calls into success and error case

Commit
3 years ago
[Async Refactoring] Split ambiguous (error + success) completion handler calls into success and error case Previously, when a completion handler call had arguments for both the success and error parameters, we were always interpreting it as an error call. In case the error argument was an `Optional`, this could cause us to generate code that didn't compile, because we `throw`ed the `Error?` or passed it to `continuation.resume(throwing)`, both of which didn't work. We now generate an `if let` statement that checks if the error is `nil`. If it is, the error is thrown. Otherwise, we interpret the call as a success call and return the result. - Example 1 (convert to continuation) -- Base Code ```swift func test(completionHandler: (Int?, Error?) -> Void) { withoutAsyncAlternativeThrowing { (theValue, theError) in completionHandler(theValue, theError) } } ``` -- Old Refactoring Result ```swift func test() async throws -> Int { return try await withCheckedThrowingContinuation { continuation in withoutAsyncAlternativeThrowing { (theValue, theError) in continuation.resume(throwing: theError) // error: Argument type 'Error?' does not conform to expected type 'Error' } } } -- New Refactoring Result ```swift func testThrowingContinuationRelayingErrorAndResult() async throws -> Int { return try await withCheckedThrowingContinuation { continuation in withoutAsyncAlternativeThrowing { (theValue, theError) in if let error = theError { continuation.resume(throwing: error) } else { guard let theValue = theValue else { fatalError("Expected non-nil success argument 'theValue' for nil error") } continuation.resume(returning: theValue) } } } } ``` - Example 2 (convert to async/await) -- Base Code ```swift func test(completion: (String?, Error?) -> Void) { simpleErr() { (res, err) in completion(res, err) } } ``` -- Old Refactoring Result ```swift func test() async throws -> String { let res = try await simpleErr() throw <#err#> } ``` -- New Refactoring Result ```swift func test() async throws -> String { let res = try await simpleErr() return res } ```
Author
Committer
Parents
  • lib/IDE
    • File
      Refactoring.cpp
  • test/refactoring/ConvertAsync
    • File
      convert_function.swift
    • File
      convert_invalid.swift
    • File
      convert_to_continuation.swift