mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[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
}
```
This commit is contained in:
@@ -10,6 +10,9 @@ func simpleErr(arg: String, _ completion: (String?, Error?) -> Void) { }
|
||||
func simpleRes(arg: String, _ completion: (Result<String, Error>) -> Void) { }
|
||||
func run(block: () -> Bool) -> Bool { return false }
|
||||
|
||||
func makeOptionalError() -> Error? { return nil }
|
||||
func makeOptionalString() -> String? { return nil }
|
||||
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NESTED %s
|
||||
func nested() {
|
||||
simple {
|
||||
@@ -295,6 +298,27 @@ func testReturnHandling3(_ completion: (String?, Error?) -> Void) {
|
||||
// RETURN-HANDLING3-NEXT: {{^}} return ""{{$}}
|
||||
// RETURN-HANDLING3-NEXT: }
|
||||
|
||||
// RUN: %refactor -add-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=RETURN-HANDLING4 %s
|
||||
func testReturnHandling4(_ completion: (String?, Error?) -> Void) {
|
||||
simpleErr(arg: "xxx") { str, err in
|
||||
if str != nil {
|
||||
completion(str, err)
|
||||
return
|
||||
}
|
||||
print("some error stuff")
|
||||
completion(str, err)
|
||||
}
|
||||
}
|
||||
// RETURN-HANDLING4: func testReturnHandling4() async throws -> String {
|
||||
// RETURN-HANDLING4-NEXT: do {
|
||||
// RETURN-HANDLING4-NEXT: let str = try await simpleErr(arg: "xxx")
|
||||
// RETURN-HANDLING4-NEXT: return str
|
||||
// RETURN-HANDLING4-NEXT: } catch let err {
|
||||
// RETURN-HANDLING4-NEXT: print("some error stuff")
|
||||
// RETURN-HANDLING4-NEXT: throw err
|
||||
// RETURN-HANDLING4-NEXT: }
|
||||
// RETURN-HANDLING4-NEXT: }
|
||||
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=RDAR78693050 %s
|
||||
func rdar78693050(_ completion: () -> Void) {
|
||||
simple { str in
|
||||
@@ -342,4 +366,234 @@ func withImplicitReturn(completionHandler: (String) -> Void) {
|
||||
// IMPLICIT-RETURN: func withImplicitReturn() async -> String {
|
||||
// IMPLICIT-RETURN-NEXT: let val0 = await simple()
|
||||
// IMPLICIT-RETURN-NEXT: return val0
|
||||
// IMPLICIT-RETURN-NEXT: }
|
||||
// IMPLICIT-RETURN-NEXT: }
|
||||
|
||||
// This code doesn't compile after refactoring because we can't return `nil` from the async function.
|
||||
// But there's not much else we can do here.
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NIL-RESULT-AND-NIL-ERROR %s
|
||||
func nilResultAndNilError(completion: (String?, Error?) -> Void) {
|
||||
completion(nil, nil)
|
||||
}
|
||||
// NIL-RESULT-AND-NIL-ERROR: func nilResultAndNilError() async throws -> String {
|
||||
// NIL-RESULT-AND-NIL-ERROR-NEXT: return nil
|
||||
// NIL-RESULT-AND-NIL-ERROR-NEXT: }
|
||||
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NIL-RESULT-AND-OPTIONAL-RELAYED-ERROR %s
|
||||
func nilResultAndOptionalRelayedError(completion: (String?, Error?) -> Void) {
|
||||
simpleErr(arg: "test") { (res, err) in
|
||||
completion(nil, err)
|
||||
}
|
||||
}
|
||||
// NIL-RESULT-AND-OPTIONAL-RELAYED-ERROR: func nilResultAndOptionalRelayedError() async throws -> String {
|
||||
// NIL-RESULT-AND-OPTIONAL-RELAYED-ERROR-NEXT: let res = try await simpleErr(arg: "test")
|
||||
// NIL-RESULT-AND-OPTIONAL-RELAYED-ERROR-EMPTY:
|
||||
// NIL-RESULT-AND-OPTIONAL-RELAYED-ERROR-NEXT: }
|
||||
|
||||
// This code doesn't compile after refactoring because we can't throw an optional error returned from makeOptionalError().
|
||||
// But it's not clear what the intended result should be either.
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NIL-RESULT-AND-OPTIONAL-COMPLEX-ERROR %s
|
||||
func nilResultAndOptionalComplexError(completion: (String?, Error?) -> Void) {
|
||||
completion(nil, makeOptionalError())
|
||||
}
|
||||
// NIL-RESULT-AND-OPTIONAL-COMPLEX-ERROR: func nilResultAndOptionalComplexError() async throws -> String {
|
||||
// NIL-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: throw makeOptionalError()
|
||||
// NIL-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: }
|
||||
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NIL-RESULT-AND-NON-OPTIONAL-ERROR %s
|
||||
func nilResultAndNonOptionalError(completion: (String?, Error?) -> Void) {
|
||||
completion(nil, CustomError.Bad)
|
||||
}
|
||||
// NIL-RESULT-AND-NON-OPTIONAL-ERROR: func nilResultAndNonOptionalError() async throws -> String {
|
||||
// NIL-RESULT-AND-NON-OPTIONAL-ERROR-NEXT: throw CustomError.Bad
|
||||
// NIL-RESULT-AND-NON-OPTIONAL-ERROR-NEXT: }
|
||||
|
||||
// In this case, we are previously ignoring the error returned from simpleErr but are rethrowing it in the refactored case.
|
||||
// That's probably fine although it changes semantics.
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=OPTIONAL-RELAYED-RESULT-AND-NIL-ERROR %s
|
||||
func optionalRelayedResultAndNilError(completion: (String?, Error?) -> Void) {
|
||||
simpleErr(arg: "test") { (res, err) in
|
||||
completion(res, nil)
|
||||
}
|
||||
}
|
||||
// OPTIONAL-RELAYED-RESULT-AND-NIL-ERROR: func optionalRelayedResultAndNilError() async throws -> String {
|
||||
// OPTIONAL-RELAYED-RESULT-AND-NIL-ERROR-NEXT: let res = try await simpleErr(arg: "test")
|
||||
// OPTIONAL-RELAYED-RESULT-AND-NIL-ERROR-NEXT: return res
|
||||
// OPTIONAL-RELAYED-RESULT-AND-NIL-ERROR-NEXT: }
|
||||
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-RELAYED-ERROR %s
|
||||
func optionalRelayedResultAndOptionalRelayedError(completion: (String?, Error?) -> Void) {
|
||||
simpleErr(arg: "test") { (res, err) in
|
||||
completion(res, err)
|
||||
}
|
||||
}
|
||||
// OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-RELAYED-ERROR: func optionalRelayedResultAndOptionalRelayedError() async throws -> String {
|
||||
// OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-RELAYED-ERROR-NEXT: let res = try await simpleErr(arg: "test")
|
||||
// OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-RELAYED-ERROR-NEXT: return res
|
||||
// OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-RELAYED-ERROR-NEXT: }
|
||||
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-COMPLEX-ERROR %s
|
||||
func optionalRelayedResultAndOptionalComplexError(completion: (String?, Error?) -> Void) {
|
||||
simpleErr(arg: "test") { (res, err) in
|
||||
completion(res, makeOptionalError())
|
||||
}
|
||||
}
|
||||
// OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-COMPLEX-ERROR: func optionalRelayedResultAndOptionalComplexError() async throws -> String {
|
||||
// OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: let res = try await simpleErr(arg: "test")
|
||||
// OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: if let error = makeOptionalError() {
|
||||
// OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: throw error
|
||||
// OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: } else {
|
||||
// OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: return res
|
||||
// OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: }
|
||||
// OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: }
|
||||
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=OPTIONAL-RELAYED-RESULT-AND-NON-OPTIONAL-ERROR %s
|
||||
func optionalRelayedResultAndNonOptionalError(completion: (String?, Error?) -> Void) {
|
||||
simpleErr(arg: "test") { (res, err) in
|
||||
completion(res, CustomError.Bad)
|
||||
}
|
||||
}
|
||||
// OPTIONAL-RELAYED-RESULT-AND-NON-OPTIONAL-ERROR: func optionalRelayedResultAndNonOptionalError() async throws -> String {
|
||||
// OPTIONAL-RELAYED-RESULT-AND-NON-OPTIONAL-ERROR-NEXT: let res = try await simpleErr(arg: "test")
|
||||
// OPTIONAL-RELAYED-RESULT-AND-NON-OPTIONAL-ERROR-NEXT: throw CustomError.Bad
|
||||
// OPTIONAL-RELAYED-RESULT-AND-NON-OPTIONAL-ERROR-NEXT: }
|
||||
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NON-OPTIONAL-RELAYED-RESULT-AND-NIL-ERROR %s
|
||||
func nonOptionalRelayedResultAndNilError(completion: (String?, Error?) -> Void) {
|
||||
simple { res in
|
||||
completion(res, nil)
|
||||
}
|
||||
}
|
||||
// NON-OPTIONAL-RELAYED-RESULT-AND-NIL-ERROR: func nonOptionalRelayedResultAndNilError() async throws -> String {
|
||||
// NON-OPTIONAL-RELAYED-RESULT-AND-NIL-ERROR-NEXT: let res = await simple()
|
||||
// NON-OPTIONAL-RELAYED-RESULT-AND-NIL-ERROR-NEXT: return res
|
||||
// NON-OPTIONAL-RELAYED-RESULT-AND-NIL-ERROR-NEXT: }
|
||||
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NON-OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-COMPLEX-ERROR %s
|
||||
func nonOptionalRelayedResultAndOptionalComplexError(completion: (String?, Error?) -> Void) {
|
||||
simple { res in
|
||||
completion(res, makeOptionalError())
|
||||
}
|
||||
}
|
||||
// NON-OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-COMPLEX-ERROR: func nonOptionalRelayedResultAndOptionalComplexError() async throws -> String {
|
||||
// NON-OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: let res = await simple()
|
||||
// NON-OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: if let error = makeOptionalError() {
|
||||
// NON-OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: throw error
|
||||
// NON-OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: } else {
|
||||
// NON-OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: return res
|
||||
// NON-OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: }
|
||||
// NON-OPTIONAL-RELAYED-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: }
|
||||
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NON-OPTIONAL-RELAYED-RESULT-AND-NON-OPTIONAL-ERROR %s
|
||||
func nonOptionalRelayedResultAndNonOptionalError(completion: (String?, Error?) -> Void) {
|
||||
simple { res in
|
||||
completion(res, CustomError.Bad)
|
||||
}
|
||||
}
|
||||
// NON-OPTIONAL-RELAYED-RESULT-AND-NON-OPTIONAL-ERROR: func nonOptionalRelayedResultAndNonOptionalError() async throws -> String {
|
||||
// NON-OPTIONAL-RELAYED-RESULT-AND-NON-OPTIONAL-ERROR-NEXT: let res = await simple()
|
||||
// NON-OPTIONAL-RELAYED-RESULT-AND-NON-OPTIONAL-ERROR-NEXT: throw CustomError.Bad
|
||||
// NON-OPTIONAL-RELAYED-RESULT-AND-NON-OPTIONAL-ERROR-NEXT: }
|
||||
|
||||
// The refactored code doesn't compile because we can't return an optional String from the async function.
|
||||
// But it's not clear what the intended result should be either, because `error` is always `nil`.
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=OPTIONAL-COMPLEX-RESULT-AND-NIL-ERROR %s
|
||||
func optionalComplexResultAndNilError(completion: (String?, Error?) -> Void) {
|
||||
completion(makeOptionalString(), nil)
|
||||
}
|
||||
// OPTIONAL-COMPLEX-RESULT-AND-NIL-ERROR: func optionalComplexResultAndNilError() async throws -> String {
|
||||
// OPTIONAL-COMPLEX-RESULT-AND-NIL-ERROR-NEXT: return makeOptionalString()
|
||||
// OPTIONAL-COMPLEX-RESULT-AND-NIL-ERROR-NEXT: }
|
||||
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=OPTIONAL-COMPLEX-RESULT-AND-OPTIONAL-RELAYED-ERROR %s
|
||||
func optionalComplexResultAndOptionalRelayedError(completion: (String?, Error?) -> Void) {
|
||||
simpleErr(arg: "test") { (res, err) in
|
||||
completion(makeOptionalString(), err)
|
||||
}
|
||||
}
|
||||
// OPTIONAL-COMPLEX-RESULT-AND-OPTIONAL-RELAYED-ERROR: func optionalComplexResultAndOptionalRelayedError() async throws -> String {
|
||||
// OPTIONAL-COMPLEX-RESULT-AND-OPTIONAL-RELAYED-ERROR-NEXT: let res = try await simpleErr(arg: "test")
|
||||
// OPTIONAL-COMPLEX-RESULT-AND-OPTIONAL-RELAYED-ERROR-NEXT: return makeOptionalString()
|
||||
// OPTIONAL-COMPLEX-RESULT-AND-OPTIONAL-RELAYED-ERROR-NEXT: }
|
||||
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=OPTIONAL-COMPLEX-RESULT-AND-OPTIONAL-COMPLEX-ERROR %s
|
||||
func optionalComplexResultAndOptionalComplexError(completion: (String?, Error?) -> Void) {
|
||||
completion(makeOptionalString(), makeOptionalError())
|
||||
}
|
||||
// OPTIONAL-COMPLEX-RESULT-AND-OPTIONAL-COMPLEX-ERROR: func optionalComplexResultAndOptionalComplexError() async throws -> String {
|
||||
// OPTIONAL-COMPLEX-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: if let error = makeOptionalError() {
|
||||
// OPTIONAL-COMPLEX-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: throw error
|
||||
// OPTIONAL-COMPLEX-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: } else {
|
||||
// OPTIONAL-COMPLEX-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: return makeOptionalString()
|
||||
// OPTIONAL-COMPLEX-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: }
|
||||
// OPTIONAL-COMPLEX-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: }
|
||||
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=OPTIONAL-COMPLEX-RESULT-AND-NON-OPTIONAL-ERROR %s
|
||||
func optionalComplexResultAndNonOptionalError(completion: (String?, Error?) -> Void) {
|
||||
completion(makeOptionalString(), CustomError.Bad)
|
||||
}
|
||||
// OPTIONAL-COMPLEX-RESULT-AND-NON-OPTIONAL-ERROR: func optionalComplexResultAndNonOptionalError() async throws -> String {
|
||||
// OPTIONAL-COMPLEX-RESULT-AND-NON-OPTIONAL-ERROR-NEXT: throw CustomError.Bad
|
||||
// OPTIONAL-COMPLEX-RESULT-AND-NON-OPTIONAL-ERROR-NEXT: }
|
||||
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NON-OPTIONAL-RESULT-AND-NIL-ERROR %s
|
||||
func nonOptionalResultAndNilError(completion: (String?, Error?) -> Void) {
|
||||
completion("abc", nil)
|
||||
}
|
||||
// NON-OPTIONAL-RESULT-AND-NIL-ERROR: func nonOptionalResultAndNilError() async throws -> String {
|
||||
// NON-OPTIONAL-RESULT-AND-NIL-ERROR-NEXT: return "abc"
|
||||
// NON-OPTIONAL-RESULT-AND-NIL-ERROR-NEXT: }
|
||||
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NON-OPTIONAL-RESULT-AND-OPTIONAL-RELAYED-ERROR %s
|
||||
func nonOptionalResultAndOptionalRelayedError(completion: (String?, Error?) -> Void) {
|
||||
simpleErr(arg: "test") { (res, err) in
|
||||
completion("abc", err)
|
||||
}
|
||||
}
|
||||
// NON-OPTIONAL-RESULT-AND-OPTIONAL-RELAYED-ERROR: func nonOptionalResultAndOptionalRelayedError() async throws -> String {
|
||||
// NON-OPTIONAL-RESULT-AND-OPTIONAL-RELAYED-ERROR-NEXT: let res = try await simpleErr(arg: "test")
|
||||
// NON-OPTIONAL-RESULT-AND-OPTIONAL-RELAYED-ERROR-NEXT: return "abc"
|
||||
// NON-OPTIONAL-RESULT-AND-OPTIONAL-RELAYED-ERROR-NEXT: }
|
||||
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NON-OPTIONAL-RESULT-AND-OPTIONAL-COMPLEX-ERROR %s
|
||||
func nonOptionalResultAndOptionalComplexError(completion: (String?, Error?) -> Void) {
|
||||
completion("abc", makeOptionalError())
|
||||
}
|
||||
// NON-OPTIONAL-RESULT-AND-OPTIONAL-COMPLEX-ERROR: func nonOptionalResultAndOptionalComplexError() async throws -> String {
|
||||
// NON-OPTIONAL-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: if let error = makeOptionalError() {
|
||||
// NON-OPTIONAL-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: throw error
|
||||
// NON-OPTIONAL-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: } else {
|
||||
// NON-OPTIONAL-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: return "abc"
|
||||
// NON-OPTIONAL-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: }
|
||||
// NON-OPTIONAL-RESULT-AND-OPTIONAL-COMPLEX-ERROR-NEXT: }
|
||||
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NON-OPTIONAL-RESULT-AND-NON-OPTIONAL-ERROR %s
|
||||
func nonOptionalResultAndNonOptionalError(completion: (String?, Error?) -> Void) {
|
||||
completion("abc", CustomError.Bad)
|
||||
}
|
||||
// NON-OPTIONAL-RESULT-AND-NON-OPTIONAL-ERROR: func nonOptionalResultAndNonOptionalError() async throws -> String {
|
||||
// NON-OPTIONAL-RESULT-AND-NON-OPTIONAL-ERROR-NEXT: throw CustomError.Bad
|
||||
// NON-OPTIONAL-RESULT-AND-NON-OPTIONAL-ERROR-NEXT: }
|
||||
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=WRAP-COMPLETION-CALL-IN-PARENS %s
|
||||
func wrapCompletionCallInParenthesis(completion: (String?, Error?) -> Void) {
|
||||
simpleErr(arg: "test") { (res, err) in
|
||||
(completion(res, err))
|
||||
}
|
||||
}
|
||||
// WRAP-COMPLETION-CALL-IN-PARENS: func wrapCompletionCallInParenthesis() async throws -> String {
|
||||
// WRAP-COMPLETION-CALL-IN-PARENS-NEXT: let res = try await simpleErr(arg: "test")
|
||||
// WRAP-COMPLETION-CALL-IN-PARENS-NEXT: return res
|
||||
// WRAP-COMPLETION-CALL-IN-PARENS-NEXT: }
|
||||
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=TWO-COMPLETION-HANDLER-CALLS %s
|
||||
func twoCompletionHandlerCalls(completion: (String?, Error?) -> Void) {
|
||||
simpleErr(arg: "test") { (res, err) in
|
||||
completion(res, err)
|
||||
completion(res, err)
|
||||
}
|
||||
}
|
||||
// TWO-COMPLETION-HANDLER-CALLS: func twoCompletionHandlerCalls() async throws -> String {
|
||||
// TWO-COMPLETION-HANDLER-CALLS-NEXT: let res = try await simpleErr(arg: "test")
|
||||
// TWO-COMPLETION-HANDLER-CALLS-NEXT: return res
|
||||
// TWO-COMPLETION-HANDLER-CALLS-NEXT: return res
|
||||
// TWO-COMPLETION-HANDLER-CALLS-NEXT: }
|
||||
|
||||
Reference in New Issue
Block a user