Files
swift-mirror/test/refactoring/ConvertAsync/convert_to_continuation.swift
Josh Soref bb8674df51 spelling: optional
Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
2022-04-21 15:53:30 -04:00

710 lines
43 KiB
Swift

// RUN: %empty-directory(%t)
func withAsyncAlternative(completionHandler: @escaping (Int) -> Void) {}
func withAsyncAlternative() async -> Int { return 42 }
func withAsyncThrowingAlternative(completionHandler: @escaping (Int?, Error?) -> Void) {}
func withAsyncThrowingAlternative() async throws -> Int { return 42 }
func withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName(closure: @escaping (Int) -> Void) {}
func withoutAsyncAlternativeBecauseOfReturnValue(completionHandler: @escaping (Int) -> Void) -> Bool { return true }
func withoutAsyncAlternativeThrowing(closure: @escaping (Int?, Error?) -> Void) {}
func withoutAsyncAlternativeThrowingWithMultipleResults(closure: @escaping (Int?, String?, Error?) -> Void) {}
func asyncVoidWithoutAlternative(completionHandler2: @escaping () -> Void) {}
func resultWithoutAlternative(completionHandler2: @escaping (Result<Int, Error>) -> Void) {}
func lottaClosures(x: () -> Void, y: () -> Void) -> Int? { nil }
struct MyError: Error {}
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=CREATE-CONTINUATION %s
func testCreateContinuation(completionHandler: @escaping (Int) -> Void) {
withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName {
completionHandler($0)
}
}
// CREATE-CONTINUATION: func testCreateContinuation() async -> Int {
// CREATE-CONTINUATION-NEXT: return await withCheckedContinuation { continuation in
// CREATE-CONTINUATION-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName {
// CREATE-CONTINUATION-NEXT: continuation.resume(returning: $0)
// CREATE-CONTINUATION-NEXT: }
// CREATE-CONTINUATION-NEXT: }
// CREATE-CONTINUATION-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=CREATE-CONTINUATION-HANDLER-CALL-IN-PARENS %s
func testCreateContinuationWithCompletionHandlerCallInParens(completionHandler: @escaping (Int) -> Void) {
withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName {
(completionHandler($0))
}
}
// CREATE-CONTINUATION-HANDLER-CALL-IN-PARENS: func testCreateContinuationWithCompletionHandlerCallInParens() async -> Int {
// CREATE-CONTINUATION-HANDLER-CALL-IN-PARENS-NEXT: return await withCheckedContinuation { continuation in
// CREATE-CONTINUATION-HANDLER-CALL-IN-PARENS-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName {
// CREATE-CONTINUATION-HANDLER-CALL-IN-PARENS-NEXT: continuation.resume(returning: $0)
// CREATE-CONTINUATION-HANDLER-CALL-IN-PARENS-NEXT: }
// CREATE-CONTINUATION-HANDLER-CALL-IN-PARENS-NEXT: }
// CREATE-CONTINUATION-HANDLER-CALL-IN-PARENS-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=CREATE-CONTINUATION-BECAUSE-RETURN-VALUE %s
func testCreateContinuationBecauseOfReturnValue(completionHandler: @escaping (Int) -> Void) {
_ = withoutAsyncAlternativeBecauseOfReturnValue {
completionHandler($0)
}
}
// CREATE-CONTINUATION-BECAUSE-RETURN-VALUE: func testCreateContinuationBecauseOfReturnValue() async -> Int {
// CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-NEXT: return await withCheckedContinuation { continuation in
// CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-NEXT: _ = withoutAsyncAlternativeBecauseOfReturnValue {
// CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-NEXT: continuation.resume(returning: $0)
// CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-NEXT: }
// CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-NEXT: }
// CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-2 %s
func testCreateContinuationBecauseOfReturnValue2(completionHandler: @escaping (Int) -> Void) {
let x = withoutAsyncAlternativeBecauseOfReturnValue {
completionHandler($0)
}
print(x)
}
// CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-2: func testCreateContinuationBecauseOfReturnValue2() async -> Int {
// CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-2-NEXT: return await withCheckedContinuation { continuation in
// CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-2-NEXT: let x = withoutAsyncAlternativeBecauseOfReturnValue {
// CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-2-NEXT: continuation.resume(returning: $0)
// CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-2-NEXT: }
// CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-2-NEXT: print(x)
// CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-2-NEXT: }
// CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-2-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=CONTINUATION-IN-NESTED-EXPRESSION %s
func testCompletionHandlerCallInNestedExpression(completionHandler: @escaping (Int) -> Void) {
print(withoutAsyncAlternativeBecauseOfReturnValue {
completionHandler($0)
})
}
// CONTINUATION-IN-NESTED-EXPRESSION: func testCompletionHandlerCallInNestedExpression() async -> Int {
// CONTINUATION-IN-NESTED-EXPRESSION-NEXT: return await withCheckedContinuation { continuation in
// CONTINUATION-IN-NESTED-EXPRESSION-NEXT: print(withoutAsyncAlternativeBecauseOfReturnValue {
// CONTINUATION-IN-NESTED-EXPRESSION-NEXT: continuation.resume(returning: $0)
// CONTINUATION-IN-NESTED-EXPRESSION-NEXT: })
// CONTINUATION-IN-NESTED-EXPRESSION-NEXT: }
// CONTINUATION-IN-NESTED-EXPRESSION-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=THROWING-CONTINUATION %s
func testThrowingContinuation(completionHandler: @escaping (Int?, Error?) -> Void) {
withoutAsyncAlternativeThrowing { (theValue, theError) in
if let theError = theError {
completionHandler(nil, theError)
} else {
completionHandler(theValue!, nil)
}
}
}
// THROWING-CONTINUATION: func testThrowingContinuation() async throws -> Int {
// THROWING-CONTINUATION-NEXT: return try await withCheckedThrowingContinuation { continuation in
// THROWING-CONTINUATION-NEXT: withoutAsyncAlternativeThrowing { (theValue, theError) in
// THROWING-CONTINUATION-NEXT: if let theError = theError {
// THROWING-CONTINUATION-NEXT: continuation.resume(throwing: theError)
// THROWING-CONTINUATION-NEXT: } else {
// THROWING-CONTINUATION-NEXT: continuation.resume(returning: theValue!)
// THROWING-CONTINUATION-NEXT: }
// THROWING-CONTINUATION-NEXT: }
// THROWING-CONTINUATION-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT %s
func testThrowingContinuationRelayingErrorAndResult(completionHandler: @escaping (Int?, Error?) -> Void) {
withoutAsyncAlternativeThrowing { (theValue, theError) in
completionHandler(theValue, theError)
}
}
// THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT: func testThrowingContinuationRelayingErrorAndResult() async throws -> Int {
// THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: return try await withCheckedThrowingContinuation { continuation in
// THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: withoutAsyncAlternativeThrowing { (theValue, theError) in
// THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: if let error = theError {
// THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: continuation.resume(throwing: error)
// THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: } else {
// THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: guard let theValue1 = theValue else {
// THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: fatalError("Expected non-nil result 'theValue1' in the non-error case")
// THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: }
// THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: continuation.resume(returning: theValue1)
// THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: }
// THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: }
// THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: }
// THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT %s
func testThrowingContinuationRelayingErrorAndComplexResult(completionHandler: @escaping (Int?, Error?) -> Void) {
withoutAsyncAlternativeThrowing { (theValue, theError) in
completionHandler(theValue.map({ $0 + 1 }), theError)
}
}
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT: func testThrowingContinuationRelayingErrorAndComplexResult() async throws -> Int {
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: return try await withCheckedThrowingContinuation { continuation in
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: withoutAsyncAlternativeThrowing { (theValue, theError) in
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: if let error = theError {
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: continuation.resume(throwing: error)
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: } else {
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: guard let result = theValue.map({ $0 + 1 }) else {
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: fatalError("Expected non-nil result in the non-error case")
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: }
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: continuation.resume(returning: result)
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: }
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: }
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: }
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS %s
func testThrowingContinuationRelayingErrorAndTwoComplexResults(completionHandler: @escaping (Int?, Int?, Error?) -> Void) {
withoutAsyncAlternativeThrowing { (theValue, theError) in
completionHandler(theValue.map({ $0 + 1 }), theValue.map({ $0 + 2 }), theError)
}
}
// THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS: func testThrowingContinuationRelayingErrorAndTwoComplexResults() async throws -> (Int, Int) {
// THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: return try await withCheckedThrowingContinuation { continuation in
// THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: withoutAsyncAlternativeThrowing { (theValue, theError) in
// THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: if let error = theError {
// THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: continuation.resume(throwing: error)
// THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: } else {
// THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: guard let result0 = theValue.map({ $0 + 1 }) else {
// THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: fatalError("Expected non-nil result 'result0' in the non-error case")
// THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: }
// THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: guard let result1 = theValue.map({ $0 + 2 }) else {
// THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: fatalError("Expected non-nil result 'result1' in the non-error case")
// THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: }
// THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: continuation.resume(returning: (result0, result1))
// THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: }
// THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: }
// THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: }
// THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE %s
func testThrowingContinuationRelayingErrorAndComplexResultWithTrailingClosure(completionHandler: @escaping (Int?, Error?) -> Void) {
withoutAsyncAlternativeThrowing { (theValue, theError) in
completionHandler(theValue.map { $0 + 1 }, theError)
}
}
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE: func testThrowingContinuationRelayingErrorAndComplexResultWithTrailingClosure() async throws -> Int {
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: return try await withCheckedThrowingContinuation { continuation in
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: withoutAsyncAlternativeThrowing { (theValue, theError) in
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: if let error = theError {
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: continuation.resume(throwing: error)
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: } else {
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: guard let result = (theValue.map { $0 + 1 }) else {
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: fatalError("Expected non-nil result in the non-error case")
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: }
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: continuation.resume(returning: result)
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: }
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: }
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: }
// THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=MULTIPLE-TRAILING-CLOSURES %s
func testThrowingContinuationRelayingErrorAndComplexResultWithMultipleTrailingClosures(completionHandler: @escaping (Int?, Error?) -> Void) {
withoutAsyncAlternativeThrowing { theValue, theError in
completionHandler(lottaClosures {} y: {}, theError)
}
}
// MULTIPLE-TRAILING-CLOSURES: func testThrowingContinuationRelayingErrorAndComplexResultWithMultipleTrailingClosures() async throws -> Int {
// MULTIPLE-TRAILING-CLOSURES-NEXT: return try await withCheckedThrowingContinuation { continuation in
// MULTIPLE-TRAILING-CLOSURES-NEXT: withoutAsyncAlternativeThrowing { theValue, theError in
// MULTIPLE-TRAILING-CLOSURES-NEXT: if let error = theError {
// MULTIPLE-TRAILING-CLOSURES-NEXT: continuation.resume(throwing: error)
// MULTIPLE-TRAILING-CLOSURES-NEXT: } else {
// MULTIPLE-TRAILING-CLOSURES-NEXT: guard let result = (lottaClosures {} y: {}) else {
// MULTIPLE-TRAILING-CLOSURES-NEXT: fatalError("Expected non-nil result in the non-error case")
// MULTIPLE-TRAILING-CLOSURES-NEXT: }
// MULTIPLE-TRAILING-CLOSURES-NEXT: continuation.resume(returning: result)
// MULTIPLE-TRAILING-CLOSURES-NEXT: }
// MULTIPLE-TRAILING-CLOSURES-NEXT: }
// MULTIPLE-TRAILING-CLOSURES-NEXT: }
// MULTIPLE-TRAILING-CLOSURES-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=THROWING-CONTINUATION-ALWAYS-RETURNING-ERROR-AND-RESULT %s
func testAlwaysReturnBothResultAndCompletionHandler(completionHandler: @escaping (Int?, Error?) -> Void) {
withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { theValue in
completionHandler(theValue, MyError())
}
}
// THROWING-CONTINUATION-ALWAYS-RETURNING-ERROR-AND-RESULT: func testAlwaysReturnBothResultAndCompletionHandler() async throws -> Int {
// THROWING-CONTINUATION-ALWAYS-RETURNING-ERROR-AND-RESULT-NEXT: return try await withCheckedThrowingContinuation { continuation in
// THROWING-CONTINUATION-ALWAYS-RETURNING-ERROR-AND-RESULT-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { theValue in
// THROWING-CONTINUATION-ALWAYS-RETURNING-ERROR-AND-RESULT-NEXT: continuation.resume(throwing: MyError())
// THROWING-CONTINUATION-ALWAYS-RETURNING-ERROR-AND-RESULT-NEXT: }
// THROWING-CONTINUATION-ALWAYS-RETURNING-ERROR-AND-RESULT-NEXT: }
// THROWING-CONTINUATION-ALWAYS-RETURNING-ERROR-AND-RESULT-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE %s
func testAmbiguousCallToCompletionHandlerWithAlwaysNilVariable(completionHandler: @escaping (Int?, Error?) -> Void) {
withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { theValue in
let error: Error? = nil
completionHandler(theValue, error)
}
}
// AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE: func testAmbiguousCallToCompletionHandlerWithAlwaysNilVariable() async throws -> Int {
// AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: return try await withCheckedThrowingContinuation { continuation in
// AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { theValue in
// AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: let error: Error? = nil
// AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: if let error = error {
// AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: continuation.resume(throwing: error)
// AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: } else {
// AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: continuation.resume(returning: theValue)
// AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: }
// AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: }
// AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: }
// AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=PREVIOUS-COMPLETION-HANDLER-CALL %s
func testPreviousCompletionHandlerCall(completionHandler: @escaping (Int) -> Void) {
withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName {
print($0)
}
withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName {
completionHandler($0)
}
}
// PREVIOUS-COMPLETION-HANDLER-CALL: func testPreviousCompletionHandlerCall() async -> Int {
// PREVIOUS-COMPLETION-HANDLER-CALL-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName {
// PREVIOUS-COMPLETION-HANDLER-CALL-NEXT: print($0)
// PREVIOUS-COMPLETION-HANDLER-CALL-NEXT: }
// PREVIOUS-COMPLETION-HANDLER-CALL-NEXT: return await withCheckedContinuation { continuation in
// PREVIOUS-COMPLETION-HANDLER-CALL-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName {
// PREVIOUS-COMPLETION-HANDLER-CALL-NEXT: continuation.resume(returning: $0)
// PREVIOUS-COMPLETION-HANDLER-CALL-NEXT: }
// PREVIOUS-COMPLETION-HANDLER-CALL-NEXT: }
// PREVIOUS-COMPLETION-HANDLER-CALL-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=PREVIOUS-ASYNC-CALL %s
func testPreviousAsyncCall(completionHandler: @escaping (Int) -> Void) {
withAsyncAlternative { message in
print(message)
}
withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName {
completionHandler($0)
}
}
// PREVIOUS-ASYNC-CALL: func testPreviousAsyncCall() async -> Int {
// PREVIOUS-ASYNC-CALL-NEXT: let message = await withAsyncAlternative()
// PREVIOUS-ASYNC-CALL-NEXT: print(message)
// PREVIOUS-ASYNC-CALL-NEXT: return await withCheckedContinuation { continuation in
// PREVIOUS-ASYNC-CALL-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName {
// PREVIOUS-ASYNC-CALL-NEXT: continuation.resume(returning: $0)
// PREVIOUS-ASYNC-CALL-NEXT: }
// PREVIOUS-ASYNC-CALL-NEXT: }
// PREVIOUS-ASYNC-CALL-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=IN-IF-ELSE %s
func testInIfElse(completionHandler: @escaping (Int) -> Void) {
if true {
withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName {
completionHandler($0)
}
} else {
withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName {
completionHandler($0)
}
}
}
// IN-IF-ELSE: func testInIfElse() async -> Int {
// IN-IF-ELSE-NEXT: if true {
// IN-IF-ELSE-NEXT: return await withCheckedContinuation { continuation in
// IN-IF-ELSE-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName {
// IN-IF-ELSE-NEXT: continuation.resume(returning: $0)
// IN-IF-ELSE-NEXT: }
// IN-IF-ELSE-NEXT: }
// IN-IF-ELSE-NEXT: } else {
// IN-IF-ELSE-NEXT: return await withCheckedContinuation { continuation in
// IN-IF-ELSE-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName {
// IN-IF-ELSE-NEXT: continuation.resume(returning: $0)
// IN-IF-ELSE-NEXT: }
// IN-IF-ELSE-NEXT: }
// IN-IF-ELSE-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=ASYNC-AFTER-CONTINUATION %s
func testAsyncAfterContinuation(completionHandler: @escaping (Int) -> Void) {
withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName {
completionHandler($0)
}
withAsyncAlternative {
print($0)
}
}
// ASYNC-AFTER-CONTINUATION: func testAsyncAfterContinuation() async -> Int {
// ASYNC-AFTER-CONTINUATION-NEXT: return await withCheckedContinuation { continuation in
// ASYNC-AFTER-CONTINUATION-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName {
// ASYNC-AFTER-CONTINUATION-NEXT: continuation.resume(returning: $0)
// ASYNC-AFTER-CONTINUATION-NEXT: }
// ASYNC-AFTER-CONTINUATION-NEXT: withAsyncAlternative {
// ASYNC-AFTER-CONTINUATION-NEXT: print($0)
// ASYNC-AFTER-CONTINUATION-NEXT: }
// ASYNC-AFTER-CONTINUATION-NEXT: }
// ASYNC-AFTER-CONTINUATION-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=WITHOUT-ASYNC-NESTED-IN-WITHOUT-ASYNC %s
func testWithoutAsyncAlternativeNestedInWithoutAsyncAlternative(completionHandler: @escaping (Int) -> Void) {
withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { firstResult in
withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { secondResult in
completionHandler(firstResult + secondResult)
}
}
}
// WITHOUT-ASYNC-NESTED-IN-WITHOUT-ASYNC: func testWithoutAsyncAlternativeNestedInWithoutAsyncAlternative() async -> Int {
// WITHOUT-ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: return await withCheckedContinuation { continuation in
// WITHOUT-ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { firstResult in
// WITHOUT-ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { secondResult in
// WITHOUT-ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: continuation.resume(returning: firstResult + secondResult)
// WITHOUT-ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: }
// WITHOUT-ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: }
// WITHOUT-ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: }
// WITHOUT-ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=WITHOUT-ASYNC-NESTED-IN-ASYNC %s
func testWithoutAsyncAlternativeNestedInAsyncAlternative(completionHandler: @escaping (Int) -> Void) {
withAsyncAlternative { firstResult in
withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { secondResult in
completionHandler(firstResult + secondResult)
}
}
}
// WITHOUT-ASYNC-NESTED-IN-ASYNC: func testWithoutAsyncAlternativeNestedInAsyncAlternative() async -> Int {
// WITHOUT-ASYNC-NESTED-IN-ASYNC-NEXT: let firstResult = await withAsyncAlternative()
// WITHOUT-ASYNC-NESTED-IN-ASYNC-NEXT: return await withCheckedContinuation { continuation in
// WITHOUT-ASYNC-NESTED-IN-ASYNC-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { secondResult in
// WITHOUT-ASYNC-NESTED-IN-ASYNC-NEXT: continuation.resume(returning: firstResult + secondResult)
// WITHOUT-ASYNC-NESTED-IN-ASYNC-NEXT: }
// WITHOUT-ASYNC-NESTED-IN-ASYNC-NEXT: }
// WITHOUT-ASYNC-NESTED-IN-ASYNC-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=ASYNC-NESTED-IN-WITHOUT-ASYNC %s
func testAsyncAlternativeNestedInWithoutAsyncAlternative(completionHandler: @escaping (Int) -> Void) {
withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { firstResult in
withAsyncAlternative { secondResult in
completionHandler(firstResult + secondResult)
}
}
}
// ASYNC-NESTED-IN-WITHOUT-ASYNC: func testAsyncAlternativeNestedInWithoutAsyncAlternative() async -> Int {
// ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: return await withCheckedContinuation { continuation in
// ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { firstResult in
// ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: withAsyncAlternative { secondResult in
// ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: continuation.resume(returning: firstResult + secondResult)
// ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: }
// ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: }
// ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: }
// ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=SHADOW-CONT-NAME %s
func testShadowContName(completionHandler: @escaping (Int) -> Void) {
withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { continuation in
completionHandler(continuation)
}
}
// SHADOW-CONT-NAME: func testShadowContName() async -> Int {
// SHADOW-CONT-NAME-NEXT: return await withCheckedContinuation { continuation in
// SHADOW-CONT-NAME-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { continuation1 in
// SHADOW-CONT-NAME-NEXT: continuation.resume(returning: continuation1)
// SHADOW-CONT-NAME-NEXT: }
// SHADOW-CONT-NAME-NEXT: }
// SHADOW-CONT-NAME-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=SHADOW-CONT-NAME-2 %s
func testShadowContName2(completionHandler: @escaping (Int) -> Void) {
let continuation = 3
withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { result in
completionHandler(result + continuation)
}
}
// SHADOW-CONT-NAME-2: func testShadowContName2() async -> Int {
// SHADOW-CONT-NAME-2-NEXT: let continuation = 3
// SHADOW-CONT-NAME-2-NEXT: return await withCheckedContinuation { continuation1 in
// SHADOW-CONT-NAME-2-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { result in
// SHADOW-CONT-NAME-2-NEXT: continuation1.resume(returning: result + continuation)
// SHADOW-CONT-NAME-2-NEXT: }
// SHADOW-CONT-NAME-2-NEXT: }
// SHADOW-CONT-NAME-2-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=VOID-RETURN %s
func testVoidReturnValue(completionHandler: @escaping () -> Void) {
asyncVoidWithoutAlternative {
completionHandler()
}
}
// VOID-RETURN: func testVoidReturnValue() async {
// VOID-RETURN-NEXT: return await withCheckedContinuation { continuation in
// VOID-RETURN-NEXT: asyncVoidWithoutAlternative {
// VOID-RETURN-NEXT: continuation.resume(returning: ())
// VOID-RETURN-NEXT: }
// VOID-RETURN-NEXT: }
// VOID-RETURN-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=SIMPLE-RESULT %s
func testSimpleResult(completionHandler: @escaping (Result<Int, Error>) -> Void) {
resultWithoutAlternative { result in
completionHandler(result)
}
}
// SIMPLE-RESULT: func testSimpleResult() async throws -> Int {
// SIMPLE-RESULT-NEXT: return try await withCheckedThrowingContinuation { continuation in
// SIMPLE-RESULT-NEXT: resultWithoutAlternative { result in
// SIMPLE-RESULT-NEXT: continuation.resume(with: result)
// SIMPLE-RESULT-NEXT: }
// SIMPLE-RESULT-NEXT: }
// SIMPLE-RESULT-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=RESULT-FROM-VALUE-AND-ERROR %s
func testResultFromValueAndError(completionHandler: @escaping (Result<Int, Error>) -> Void) {
withoutAsyncAlternativeThrowing { (value, error) in
if let error = error {
completionHandler(.failure(error))
} else {
completionHandler(.success(value!))
}
}
}
// RESULT-FROM-VALUE-AND-ERROR: func testResultFromValueAndError() async throws -> Int {
// RESULT-FROM-VALUE-AND-ERROR-NEXT: return try await withCheckedThrowingContinuation { continuation in
// RESULT-FROM-VALUE-AND-ERROR-NEXT: withoutAsyncAlternativeThrowing { (value, error) in
// RESULT-FROM-VALUE-AND-ERROR-NEXT: if let error = error {
// RESULT-FROM-VALUE-AND-ERROR-NEXT: continuation.resume(with: .failure(error))
// RESULT-FROM-VALUE-AND-ERROR-NEXT: } else {
// RESULT-FROM-VALUE-AND-ERROR-NEXT: continuation.resume(with: .success(value!))
// RESULT-FROM-VALUE-AND-ERROR-NEXT: }
// RESULT-FROM-VALUE-AND-ERROR-NEXT: }
// RESULT-FROM-VALUE-AND-ERROR-NEXT: }
// RESULT-FROM-VALUE-AND-ERROR-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=MULTIPLE-RETURN-VALUES-AND-ERROR %s
func testMultipleReturnValuesAndError(completion: @escaping (Int?, String?, Error?) -> Void) {
withoutAsyncAlternativeThrowingWithMultipleResults { (first, second, error) in
completion(first, second, error)
}
}
// MULTIPLE-RETURN-VALUES-AND-ERROR: func testMultipleReturnValuesAndError() async throws -> (Int, String) {
// MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: return try await withCheckedThrowingContinuation { continuation in
// MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: withoutAsyncAlternativeThrowingWithMultipleResults { (first, second, error) in
// MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: if let error = error {
// MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: continuation.resume(throwing: error)
// MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: } else {
// MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: guard let first1 = first else {
// MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: fatalError("Expected non-nil result 'first1' in the non-error case")
// MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: }
// MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: guard let second1 = second else {
// MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: fatalError("Expected non-nil result 'second1' in the non-error case")
// MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: }
// MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: continuation.resume(returning: (first1, second1))
// MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: }
// MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: }
// MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: }
// MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NON-OPTIONAL-VALUE-FOR-RESULT-AND-ERROR %s
func testReturnNonOptionalValuesForResultAndError(completion: @escaping (Int?, Error?) -> Void) {
withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { result in
completion(1, MyError())
}
}
// NON-OPTIONAL-VALUE-FOR-RESULT-AND-ERROR: func testReturnNonOptionalValuesForResultAndError() async throws -> Int {
// NON-OPTIONAL-VALUE-FOR-RESULT-AND-ERROR-NEXT: return try await withCheckedThrowingContinuation { continuation in
// NON-OPTIONAL-VALUE-FOR-RESULT-AND-ERROR-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { result in
// NON-OPTIONAL-VALUE-FOR-RESULT-AND-ERROR-NEXT: continuation.resume(throwing: MyError())
// NON-OPTIONAL-VALUE-FOR-RESULT-AND-ERROR-NEXT: }
// NON-OPTIONAL-VALUE-FOR-RESULT-AND-ERROR-NEXT: }
// NON-OPTIONAL-VALUE-FOR-RESULT-AND-ERROR-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT %s
func testMixedOptionalAnNonOptionalResults(completion: @escaping (Int?, String?, Error?) -> Void) {
withoutAsyncAlternativeThrowing { (theResult, error) in
completion(theResult, "hi", nil)
}
}
// MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT: func testMixedOptionalAnNonOptionalResults() async throws -> (Int, String) {
// MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT-NEXT: return try await withCheckedThrowingContinuation { continuation in
// MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT-NEXT: withoutAsyncAlternativeThrowing { (theResult, error) in
// MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT-NEXT: guard let theResult1 = theResult else {
// MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT-NEXT: fatalError("Expected non-nil result 'theResult1' in the non-error case")
// MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT-NEXT: }
// MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT-NEXT: continuation.resume(returning: (theResult1, "hi"))
// MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT-NEXT: }
// MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT-NEXT: }
// MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL %s
func testUseOptionalResultValueAfterCompletionHandlerCall(completion: @escaping (Int?, String?, Error?) -> Void) {
withoutAsyncAlternativeThrowing { (theResult, error) in
completion(theResult, "hi", nil)
print(theResult.map { $0 + 1 } as Any)
}
}
// USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL: func testUseOptionalResultValueAfterCompletionHandlerCall() async throws -> (Int, String) {
// USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL-NEXT: return try await withCheckedThrowingContinuation { continuation in
// USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL-NEXT: withoutAsyncAlternativeThrowing { (theResult, error) in
// USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL-NEXT: guard let theResult1 = theResult else {
// USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL-NEXT: fatalError("Expected non-nil result 'theResult1' in the non-error case")
// USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL-NEXT: }
// USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL-NEXT: continuation.resume(returning: (theResult1, "hi"))
// USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL-NEXT: print(theResult.map { $0 + 1 } as Any)
// USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL-NEXT: }
// USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL-NEXT: }
// USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL-NEXT: }
// We shouldn't need to unwrap `theResult` twice here, but the example is silly and I don't care too much.
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=PASS-SAME-RESULT-TWICE %s
func testPassSameResultTwice(completion: @escaping (Int?, Int?, Error?) -> Void) {
withoutAsyncAlternativeThrowing { (theResult, error) in
completion(theResult, theResult, nil)
}
}
// PASS-SAME-RESULT-TWICE: func testPassSameResultTwice() async throws -> (Int, Int) {
// PASS-SAME-RESULT-TWICE-NEXT: return try await withCheckedThrowingContinuation { continuation in
// PASS-SAME-RESULT-TWICE-NEXT: withoutAsyncAlternativeThrowing { (theResult, error) in
// PASS-SAME-RESULT-TWICE-NEXT: guard let theResult1 = theResult else {
// PASS-SAME-RESULT-TWICE-NEXT: fatalError("Expected non-nil result 'theResult1' in the non-error case")
// PASS-SAME-RESULT-TWICE-NEXT: }
// PASS-SAME-RESULT-TWICE-NEXT: guard let theResult2 = theResult else {
// PASS-SAME-RESULT-TWICE-NEXT: fatalError("Expected non-nil result 'theResult2' in the non-error case")
// PASS-SAME-RESULT-TWICE-NEXT: }
// PASS-SAME-RESULT-TWICE-NEXT: continuation.resume(returning: (theResult1, theResult2))
// PASS-SAME-RESULT-TWICE-NEXT: }
// PASS-SAME-RESULT-TWICE-NEXT: }
// PASS-SAME-RESULT-TWICE-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL %s
func testUseResultAfterAmbiguousCompletionHandlerCall(completion: @escaping (Int?, Error?) -> Void) {
withoutAsyncAlternativeThrowing { (theResult, error) in
completion(theResult, error)
print(theResult as Any)
}
}
// USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL: func testUseResultAfterAmbiguousCompletionHandlerCall() async throws -> Int {
// USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: return try await withCheckedThrowingContinuation { continuation in
// USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: withoutAsyncAlternativeThrowing { (theResult, error) in
// USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: if let error = error {
// USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: continuation.resume(throwing: error)
// USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: } else {
// USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: guard let theResult1 = theResult else {
// USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: fatalError("Expected non-nil result 'theResult1' in the non-error case")
// USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: }
// USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: continuation.resume(returning: theResult1)
// USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: }
// USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: print(theResult as Any)
// USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: }
// USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: }
// USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=TWO-COMPLEITON-HANDLER-CALLS %s
func testTwoCompletionHandlerCalls(completion: @escaping (Int?, Error?) -> Void) {
withoutAsyncAlternativeThrowing { (theResult, error) in
completion(theResult, error)
completion(theResult, error)
}
}
// TWO-COMPLEITON-HANDLER-CALLS: func testTwoCompletionHandlerCalls() async throws -> Int {
// TWO-COMPLEITON-HANDLER-CALLS-NEXT: return try await withCheckedThrowingContinuation { continuation in
// TWO-COMPLEITON-HANDLER-CALLS-NEXT: withoutAsyncAlternativeThrowing { (theResult, error) in
// TWO-COMPLEITON-HANDLER-CALLS-NEXT: if let error = error {
// TWO-COMPLEITON-HANDLER-CALLS-NEXT: continuation.resume(throwing: error)
// TWO-COMPLEITON-HANDLER-CALLS-NEXT: } else {
// TWO-COMPLEITON-HANDLER-CALLS-NEXT: guard let theResult1 = theResult else {
// TWO-COMPLEITON-HANDLER-CALLS-NEXT: fatalError("Expected non-nil result 'theResult1' in the non-error case")
// TWO-COMPLEITON-HANDLER-CALLS-NEXT: }
// TWO-COMPLEITON-HANDLER-CALLS-NEXT: continuation.resume(returning: theResult1)
// TWO-COMPLEITON-HANDLER-CALLS-NEXT: }
// TWO-COMPLEITON-HANDLER-CALLS-NEXT: if let error = error {
// TWO-COMPLEITON-HANDLER-CALLS-NEXT: continuation.resume(throwing: error)
// TWO-COMPLEITON-HANDLER-CALLS-NEXT: } else {
// TWO-COMPLEITON-HANDLER-CALLS-NEXT: guard let theResult2 = theResult else {
// TWO-COMPLEITON-HANDLER-CALLS-NEXT: fatalError("Expected non-nil result 'theResult2' in the non-error case")
// TWO-COMPLEITON-HANDLER-CALLS-NEXT: }
// TWO-COMPLEITON-HANDLER-CALLS-NEXT: continuation.resume(returning: theResult2)
// TWO-COMPLEITON-HANDLER-CALLS-NEXT: }
// TWO-COMPLEITON-HANDLER-CALLS-NEXT: }
// TWO-COMPLEITON-HANDLER-CALLS-NEXT: }
// TWO-COMPLEITON-HANDLER-CALLS-NEXT: }
// Reduced version of https://twitter.com/peterfriese/status/1397835146133479428
class DataTask {
let completionHandler: (String?, Error?) -> Void
init(completionHandler: @escaping (String?, Error?) -> Void) {
self.completionHandler = completionHandler
}
func resume() {
completionHandler("mock result", nil)
}
}
class URLSession {
static let shared = URLSession()
func dataTask(completionHandler: @escaping (String?, Error?) -> Void) -> DataTask {
return DataTask(completionHandler: completionHandler)
}
}
func processURLResult(_ data: String) throws -> Int {
return data.count
}
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=URL-SESSION %s
func testDataTask(_ completion: @escaping (Int?) -> Void) {
let dataTask = URLSession.shared.dataTask { (data, error) in
guard let data = data else {
return // Yes, there is a bug about not calling completion here, but that's copied from the Twitter link above
}
do {
let processed = try processURLResult(data)
completion(processed)
} catch {
completion(nil)
}
}
dataTask.resume()
}
// URL-SESSION: func testDataTask() async -> Int? {
// URL-SESSION-NEXT: return await withCheckedContinuation { continuation in
// URL-SESSION-NEXT: let dataTask1 = URLSession.shared.dataTask { (data, error) in
// URL-SESSION-NEXT: guard let data1 = data else {
// URL-SESSION-NEXT: return // Yes, there is a bug about not calling completion here, but that's copied from the Twitter link above
// URL-SESSION-NEXT: }
// URL-SESSION-NEXT: do {
// URL-SESSION-NEXT: let processed = try processURLResult(data1)
// URL-SESSION-NEXT: continuation.resume(returning: processed)
// URL-SESSION-NEXT: } catch {
// URL-SESSION-NEXT: continuation.resume(returning: nil)
// URL-SESSION-NEXT: }
// URL-SESSION-NEXT: }
// URL-SESSION-NEXT: dataTask1.resume()
// URL-SESSION-NEXT: }
// URL-SESSION-NEXT: }
// Reduced version of rdar://79304583
class DispatchQueue {
init() {}
func async(execute work: @escaping @convention(block) () -> Void) {
work()
}
}
func syncComputation() -> Int { return 42 }
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=DISPATCH %s
func testDispatch(_ completionHandler: @escaping (Int) -> Void) {
let queue = DispatchQueue()
queue.async {
completionHandler(syncComputation())
}
}
// DISPATCH: func testDispatch() async -> Int {
// DISPATCH-NEXT: let queue = DispatchQueue()
// DISPATCH-NEXT: return await withCheckedContinuation { continuation in
// DISPATCH-NEXT: queue.async {
// DISPATCH-NEXT: continuation.resume(returning: syncComputation())
// DISPATCH-NEXT: }
// DISPATCH-NEXT: }
// DISPATCH-NEXT: }