Merge remote-tracking branch 'origin/main' into rebranch

This commit is contained in:
swift-ci
2021-08-19 05:33:49 -07:00
14 changed files with 1686 additions and 1585 deletions

View File

@@ -149,6 +149,9 @@ namespace swift {
/// Should potential unavailability on enum cases be downgraded to a warning?
bool WarnOnPotentiallyUnavailableEnumCase = false;
/// Should the editor placeholder error be downgraded to a warning?
bool WarnOnEditorPlaceholder = false;
/// Maximum number of typo corrections we are allowed to perform.
/// This is disabled by default until we can get typo-correction working within acceptable performance bounds.
unsigned TypoCorrectionLimit = 0;

View File

@@ -462,6 +462,10 @@ def warn_on_potentially_unavailable_enum_case : Flag<["-"],
"warn-on-potentially-unavailable-enum-case">,
HelpText<"Downgrade potential unavailability of enum case to a warning">;
def warn_on_editor_placeholder : Flag<["-"],
"warn-on-editor-placeholder">,
HelpText<"Downgrade the editor placeholder error to a warning">;
def report_errors_to_debugger : Flag<["-"], "report-errors-to-debugger">,
HelpText<"Deprecated, will be removed in future versions.">;

View File

@@ -467,6 +467,8 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.WarnOnPotentiallyUnavailableEnumCase |=
Args.hasArg(OPT_warn_on_potentially_unavailable_enum_case);
Opts.WarnOnEditorPlaceholder |= Args.hasArg(OPT_warn_on_editor_placeholder);
if (auto A = Args.getLastArg(OPT_enable_access_control,
OPT_disable_access_control)) {
Opts.EnableAccessControl

View File

@@ -2145,9 +2145,10 @@ void Lexer::tryLexEditorPlaceholder() {
if (Ptr[0] == '<' && Ptr[1] == '#')
break;
if (Ptr[0] == '#' && Ptr[1] == '>') {
// Found it. Flag it as error (or warning, if in playground mode) for the
// rest of the compiler pipeline and lex it as an identifier.
if (LangOpts.Playground) {
// Found it. Flag it as error (or warning, if in playground mode or we've
// been asked to warn) for the rest of the compiler pipeline and lex it
// as an identifier.
if (LangOpts.Playground || LangOpts.WarnOnEditorPlaceholder) {
diagnose(TokStart, diag::lex_editor_placeholder_in_playground);
} else {
diagnose(TokStart, diag::lex_editor_placeholder);

View File

@@ -1,5 +1,6 @@
// RUN: %target-run-simple-swift( -Xfrontend -disable-availability-checking -parse-as-library %import-libdispatch) | %FileCheck %s
// REQUIRES: rdar82092187
// REQUIRES: executable_test
// REQUIRES: concurrency
// REQUIRES: libdispatch

View File

@@ -14,9 +14,9 @@ typealias NestedAliasCallback = SomeCallback
// 1. Check various functions for having/not having async alternatives
// RUN: %refactor-check-compiles -add-async-alternative -dump-text -source-filename %s -pos=%(line+4):1 | %FileCheck -check-prefix=ASYNC-SIMPLE %s
// RUN: %refactor -add-async-alternative -dump-text -source-filename %s -pos=%(line+3):6 | %FileCheck -check-prefix=ASYNC-SIMPLE %s
// RUN: %refactor -add-async-alternative -dump-text -source-filename %s -pos=%(line+2):12 | %FileCheck -check-prefix=ASYNC-SIMPLE %s
// RUN: %refactor -add-async-alternative -dump-text -source-filename %s -pos=%(line+1):20 | %FileCheck -check-prefix=ASYNC-SIMPLE %s
// RUN: %refactor-check-compiles -add-async-alternative -dump-text -source-filename %s -pos=%(line+3):6 | %FileCheck -check-prefix=ASYNC-SIMPLE %s
// RUN: %refactor-check-compiles -add-async-alternative -dump-text -source-filename %s -pos=%(line+2):12 | %FileCheck -check-prefix=ASYNC-SIMPLE %s
// RUN: %refactor-check-compiles -add-async-alternative -dump-text -source-filename %s -pos=%(line+1):20 | %FileCheck -check-prefix=ASYNC-SIMPLE %s
func simple(/*cs*/ completion: @escaping (String) -> Void /*ce*/) { }
// ASYNC-SIMPLE: basic.swift [[# @LINE-1]]:1 -> [[# @LINE-1]]:1
// ASYNC-SIMPLE-NEXT: @available(*, renamed: "simple()")
@@ -113,7 +113,7 @@ func errorOnly(completion: @escaping (Error?) -> Void) { }
// ASYNC-ERRORONLY-NEXT: }
// ASYNC-ERRORONLY: func errorOnly() async throws { }
// RUN: %refactor -add-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=ASYNC-ERRORNONOPTIONALRESULT %s
// RUN: %refactor-check-compiles -add-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=ASYNC-ERRORNONOPTIONALRESULT %s
func errorNonOptionalResult(completion: @escaping (String, Error?) -> Void) { }
// ASYNC-ERRORNONOPTIONALRESULT: {
// ASYNC-ERRORNONOPTIONALRESULT-NEXT: Task {
@@ -253,7 +253,7 @@ func mixed(_ completion: @escaping (String?, Int) -> Void) { }
// MIXED-NEXT: }
// MIXED: func mixed() async -> (String?, Int) { }
// RUN: %refactor -add-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=MIXED-OPTIONAL-ERROR %s
// RUN: %refactor-check-compiles -add-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=MIXED-OPTIONAL-ERROR %s
func mixedOptionalError(_ completion: @escaping (String?, Int, Error?) -> Void) { }
// MIXED-OPTIONAL-ERROR: {
// MIXED-OPTIONAL-ERROR-NEXT: Task {
@@ -377,7 +377,7 @@ protocol MyProtocol {
}
// RUN: not %refactor -add-async-alternative -dump-text -source-filename %s -pos=%(line+2):1
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NON-COMPLETION %s
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NON-COMPLETION %s
func nonCompletion(a: Int) { }
// NON-COMPLETION: func nonCompletion(a: Int) async { }
@@ -387,27 +387,27 @@ func nonEscapingCompletion(completion: (Int) -> Void) { }
// NON-ESCAPING-COMPLETION: func nonEscapingCompletion(completion: (Int) -> Void) async { }
// RUN: not %refactor -add-async-alternative -dump-text -source-filename %s -pos=%(line+2):1
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=MULTIPLE-RESULTS %s
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=MULTIPLE-RESULTS %s
func multipleResults(completion: @escaping (Result<String, Error>, Result<String, Error>) -> Void) { }
// MULTIPLE-RESULTS: func multipleResults(completion: @escaping (Result<String, Error>, Result<String, Error>) -> Void) async { }
// RUN: not %refactor -add-async-alternative -dump-text -source-filename %s -pos=%(line+2):1
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NON-VOID %s
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NON-VOID %s
func nonVoid(completion: @escaping (String) -> Void) -> Int { return 0 }
// NON-VOID: func nonVoid(completion: @escaping (String) -> Void) async -> Int { return 0 }
// RUN: not %refactor -add-async-alternative -dump-text -source-filename %s -pos=%(line+2):1
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=COMPLETION-NON-VOID %s
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=COMPLETION-NON-VOID %s
func completionNonVoid(completion: @escaping (String) -> Int) -> Void { }
// COMPLETION-NON-VOID: func completionNonVoid(completion: @escaping (String) -> Int) async -> Void { }
// RUN: not %refactor -add-async-alternative -dump-text -source-filename %s -pos=%(line+2):1
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=ALREADY-THROWS %s
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=ALREADY-THROWS %s
func alreadyThrows(completion: @escaping (String) -> Void) throws { }
// ALREADY-THROWS: func alreadyThrows(completion: @escaping (String) -> Void) async throws { }
// RUN: not %refactor -add-async-alternative -dump-text -source-filename %s -pos=%(line+2):1
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=AUTO-CLOSURE %s
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=AUTO-CLOSURE %s
func noParamAutoclosure(completion: @escaping @autoclosure () -> Void) { }
// AUTO-CLOSURE: func noParamAutoclosure(completion: @escaping @autoclosure () -> Void) async { }
@@ -640,13 +640,17 @@ func testSkipAssign() {
// SKIP-ASSIGN-FUNC-NEXT: print("assigned"){{$}}
// SKIP-ASSIGN-FUNC-NEXT: }{{$}}
// Same as noParamAutoclosure defined above, but used just for the test below.
// This avoids a compiler error when converting noParamAutoclosure to async.
func noParamAutoclosure2(completion: @escaping @autoclosure () -> Void) {}
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefixes=SKIP-AUTOCLOSURE-FUNC %s
func testSkipAutoclosure() {
// RUN: not %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3
noParamAutoclosure(completion: print("autoclosure"))
noParamAutoclosure2(completion: print("autoclosure"))
}
// SKIP-AUTOCLOSURE-FUNC: {{^}}func testSkipAutoclosure() async {
// SKIP-AUTOCLOSURE-FUNC: noParamAutoclosure(completion: print("autoclosure")){{$}}
// SKIP-AUTOCLOSURE-FUNC: noParamAutoclosure2(completion: print("autoclosure")){{$}}
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=EMPTY-CAPTURE %s
func testEmptyCapture() {

View File

@@ -7,443 +7,458 @@
import Foundation
import ConvertBoolObjC
func boolWithErr() async throws -> Bool { true }
func boolWithErr(completion: @escaping (Bool, Error?) -> Void) {}
func multipleBoolWithErr() async throws -> (String, Bool, Bool) { ("", true, true) }
func multipleBoolWithErr(completion: @escaping (String?, Bool, Bool, Error?) -> Void) {}
func optionalBoolWithErr() async throws -> (String, Bool, Bool) { ("", true, true) }
func optionalBoolWithErr(completion: @escaping (String?, Bool?, Bool, Error?) -> Void) {}
// All 7 of the below should generate the same refactoring.
func testConvertBool() async throws {
// All 7 of the below should generate the same refactoring.
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR %s
boolWithErr { b, err in
if !b {
fatalError("oh no \(err!)")
}
print("not err")
}
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR %s
boolWithErr { b, err in
if b {
fatalError("oh no \(err!)")
}
print("not err")
}
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR %s
boolWithErr { b, err in
if !b && err != nil {
fatalError("oh no \(err!)")
}
print("not err")
}
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR %s
boolWithErr { b, err in
if b && err != nil {
fatalError("oh no \(err!)")
}
print("not err")
}
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR %s
boolWithErr { b, err in
if err != nil && b == false {
fatalError("oh no \(err!)")
}
print("not err")
}
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR %s
boolWithErr { b, err in
if b == true && err == nil {
} else {
fatalError("oh no \(err!)")
}
print("not err")
}
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR %s
boolWithErr { b, err in
if !b && err == nil {
} else {
fatalError("oh no \(err!)")
}
print("not err")
}
// BOOL-WITH-ERR: do {
// BOOL-WITH-ERR-NEXT: let b = try await boolWithErr()
// BOOL-WITH-ERR-NEXT: print("not err")
// BOOL-WITH-ERR-NEXT: } catch let err {
// BOOL-WITH-ERR-NEXT: fatalError("oh no \(err)")
// BOOL-WITH-ERR-NEXT: }
// These 3 should both generate the same refactoring.
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR2 %s
boolWithErr { success, err in
if success == true && err == nil {
print("hi")
} else {
fatalError("oh no \(err!)")
}
print("not err")
}
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR2 %s
boolWithErr { success, err in
if success && err == nil {
print("hi")
} else {
fatalError("oh no \(err!)")
}
print("not err")
}
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR2 %s
boolWithErr { success, err in
if err == nil {
print("hi")
} else if !success {
fatalError("oh no \(err!)")
}
print("not err")
}
// BOOL-WITH-ERR2: do {
// BOOL-WITH-ERR2-NEXT: let success = try await boolWithErr()
// BOOL-WITH-ERR2-NEXT: print("hi")
// BOOL-WITH-ERR2-NEXT: print("not err")
// BOOL-WITH-ERR2-NEXT: } catch let err {
// BOOL-WITH-ERR2-NEXT: fatalError("oh no \(err)")
// BOOL-WITH-ERR2-NEXT: }
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR3 %s
boolWithErr { failure, err in
if failure {
print("a \(err!)")
} else if .random() {
print("b")
} else {
print("c")
}
}
// BOOL-WITH-ERR3: do {
// BOOL-WITH-ERR3-NEXT: let failure = try await boolWithErr()
// BOOL-WITH-ERR3-NEXT: if .random() {
// BOOL-WITH-ERR3-NEXT: print("b")
// BOOL-WITH-ERR3-NEXT: } else {
// BOOL-WITH-ERR3-NEXT: print("c")
// BOOL-WITH-ERR3-NEXT: }
// BOOL-WITH-ERR3-NEXT: } catch let err {
// BOOL-WITH-ERR3-NEXT: print("a \(err)")
// BOOL-WITH-ERR3-NEXT: }
// Don't handle the below example as the force unwrap of err takes place under a different condition.
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-DONT-HANDLE %s
boolWithErr { success, err in
if !success {
if err != nil {
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR %s
boolWithErr { b, err in
if !b {
fatalError("oh no \(err!)")
}
print("not err")
}
if !success {
_ = err != nil ? fatalError("oh no \(err!)") : fatalError("some worries")
}
print("not err")
}
// BOOL-DONT-HANDLE: let success = try await boolWithErr()
// BOOL-DONT-HANDLE-NEXT: if !success {
// BOOL-DONT-HANDLE-NEXT: if <#err#> != nil {
// BOOL-DONT-HANDLE-NEXT: fatalError("oh no \(<#err#>!)")
// BOOL-DONT-HANDLE-NEXT: }
// BOOL-DONT-HANDLE-NEXT: }
// BOOL-DONT-HANDLE-NEXT: if !success {
// BOOL-DONT-HANDLE-NEXT: _ = <#err#> != nil ? fatalError("oh no \(<#err#>!)") : fatalError("some worries")
// BOOL-DONT-HANDLE-NEXT: }
// BOOL-DONT-HANDLE-NEXT: print("not err")
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-DONT-HANDLE2 %s
boolWithErr { success, err in
if !success {
func doThings() {
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR %s
boolWithErr { b, err in
if b {
fatalError("oh no \(err!)")
}
doThings()
print("not err")
}
if !success {
let doThings = {
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR %s
boolWithErr { b, err in
if !b && err != nil {
fatalError("oh no \(err!)")
}
doThings()
print("not err")
}
if !success {
while err != nil {
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR %s
boolWithErr { b, err in
if b && err != nil {
fatalError("oh no \(err!)")
}
print("not err")
}
if !success {
for _: Int in [] {
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR %s
boolWithErr { b, err in
if err != nil && b == false {
fatalError("oh no \(err!)")
}
print("not err")
}
print("not err")
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR %s
boolWithErr { b, err in
if b == true && err == nil {
} else {
fatalError("oh no \(err!)")
}
print("not err")
}
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR %s
boolWithErr { b, err in
if !b && err == nil {
} else {
fatalError("oh no \(err!)")
}
print("not err")
}
// BOOL-WITH-ERR: do {
// BOOL-WITH-ERR-NEXT: let b = try await boolWithErr()
// BOOL-WITH-ERR-NEXT: print("not err")
// BOOL-WITH-ERR-NEXT: } catch let err {
// BOOL-WITH-ERR-NEXT: fatalError("oh no \(err)")
// BOOL-WITH-ERR-NEXT: }
// These 3 should both generate the same refactoring.
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR2 %s
boolWithErr { success, err in
if success == true && err == nil {
print("hi")
} else {
fatalError("oh no \(err!)")
}
print("not err")
}
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR2 %s
boolWithErr { success, err in
if success && err == nil {
print("hi")
} else {
fatalError("oh no \(err!)")
}
print("not err")
}
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR2 %s
boolWithErr { success, err in
if err == nil {
print("hi")
} else if !success {
fatalError("oh no \(err!)")
}
print("not err")
}
// BOOL-WITH-ERR2: do {
// BOOL-WITH-ERR2-NEXT: let success = try await boolWithErr()
// BOOL-WITH-ERR2-NEXT: print("hi")
// BOOL-WITH-ERR2-NEXT: print("not err")
// BOOL-WITH-ERR2-NEXT: } catch let err {
// BOOL-WITH-ERR2-NEXT: fatalError("oh no \(err)")
// BOOL-WITH-ERR2-NEXT: }
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR3 %s
boolWithErr { failure, err in
if failure {
print("a \(err!)")
} else if .random() {
print("b")
} else {
print("c")
}
}
// BOOL-WITH-ERR3: do {
// BOOL-WITH-ERR3-NEXT: let failure = try await boolWithErr()
// BOOL-WITH-ERR3-NEXT: if .random() {
// BOOL-WITH-ERR3-NEXT: print("b")
// BOOL-WITH-ERR3-NEXT: } else {
// BOOL-WITH-ERR3-NEXT: print("c")
// BOOL-WITH-ERR3-NEXT: }
// BOOL-WITH-ERR3-NEXT: } catch let err {
// BOOL-WITH-ERR3-NEXT: print("a \(err)")
// BOOL-WITH-ERR3-NEXT: }
// Don't handle the below example as the force unwrap of err takes place under a different condition.
// We cannot use refactor-check-compiles, as a placeholder cannot be force unwrapped.
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-DONT-HANDLE %s
boolWithErr { success, err in
if !success {
if err != nil {
fatalError("oh no \(err!)")
}
}
if !success {
_ = err != nil ? fatalError("oh no \(err!)") : fatalError("some worries")
}
print("not err")
}
// BOOL-DONT-HANDLE: let success = try await boolWithErr()
// BOOL-DONT-HANDLE-NEXT: if !success {
// BOOL-DONT-HANDLE-NEXT: if <#err#> != nil {
// BOOL-DONT-HANDLE-NEXT: fatalError("oh no \(<#err#>!)")
// BOOL-DONT-HANDLE-NEXT: }
// BOOL-DONT-HANDLE-NEXT: }
// BOOL-DONT-HANDLE-NEXT: if !success {
// BOOL-DONT-HANDLE-NEXT: _ = <#err#> != nil ? fatalError("oh no \(<#err#>!)") : fatalError("some worries")
// BOOL-DONT-HANDLE-NEXT: }
// BOOL-DONT-HANDLE-NEXT: print("not err")
// We cannot use refactor-check-compiles, as a placeholder cannot be force unwrapped.
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-DONT-HANDLE2 %s
boolWithErr { success, err in
if !success {
func doThings() {
fatalError("oh no \(err!)")
}
doThings()
}
if !success {
let doThings = {
fatalError("oh no \(err!)")
}
doThings()
}
if !success {
while err != nil {
fatalError("oh no \(err!)")
}
}
if !success {
for _: Int in [] {
fatalError("oh no \(err!)")
}
}
print("not err")
}
// FIXME: The 'err' in doThings() should become a placeholder (rdar://78509286).
// BOOL-DONT-HANDLE2: let success = try await boolWithErr()
// BOOL-DONT-HANDLE2-NEXT: if !success {
// BOOL-DONT-HANDLE2-NEXT: func doThings() {
// BOOL-DONT-HANDLE2-NEXT: fatalError("oh no \(err!)")
// BOOL-DONT-HANDLE2-NEXT: }
// BOOL-DONT-HANDLE2-NEXT: doThings()
// BOOL-DONT-HANDLE2-NEXT: }
// BOOL-DONT-HANDLE2-NEXT: if !success {
// BOOL-DONT-HANDLE2-NEXT: let doThings = {
// BOOL-DONT-HANDLE2-NEXT: fatalError("oh no \(<#err#>!)")
// BOOL-DONT-HANDLE2-NEXT: }
// BOOL-DONT-HANDLE2-NEXT: doThings()
// BOOL-DONT-HANDLE2-NEXT: }
// BOOL-DONT-HANDLE2-NEXT: if !success {
// BOOL-DONT-HANDLE2-NEXT: while <#err#> != nil {
// BOOL-DONT-HANDLE2-NEXT: fatalError("oh no \(<#err#>!)")
// BOOL-DONT-HANDLE2-NEXT: }
// BOOL-DONT-HANDLE2-NEXT: }
// BOOL-DONT-HANDLE2-NEXT: if !success {
// BOOL-DONT-HANDLE2-NEXT: for _: Int in [] {
// BOOL-DONT-HANDLE2-NEXT: fatalError("oh no \(<#err#>!)")
// BOOL-DONT-HANDLE2-NEXT: }
// BOOL-DONT-HANDLE2-NEXT: }
// BOOL-DONT-HANDLE2-NEXT: print("not err")
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-DONT-HANDLE3 %s
boolWithErr { success, err in
if !success {
fatalError("oh no maybe \(String(describing: err))")
}
print("not err")
}
// err is not force unwrapped, so don't handle.
// BOOL-DONT-HANDLE3: let success = try await boolWithErr()
// BOOL-DONT-HANDLE3-NEXT: if !success {
// BOOL-DONT-HANDLE3-NEXT: fatalError("oh no maybe \(String(describing: <#err#>))")
// BOOL-DONT-HANDLE3-NEXT: }
// BOOL-DONT-HANDLE3-NEXT: print("not err")
// We cannot use refactor-check-compiles, as a placeholder cannot be force unwrapped.
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-DONT-HANDLE4 %s
boolWithErr { failure, err in
if failure {
print("a")
} else if .random() {
print("b \(err!)")
} else {
print("c")
}
}
// Don't handle the case where the err unwrap occurs in an unrelated else if
// clause.
// BOOL-DONT-HANDLE4: let failure = try await boolWithErr()
// BOOL-DONT-HANDLE4-NEXT: if failure {
// BOOL-DONT-HANDLE4-NEXT: print("a")
// BOOL-DONT-HANDLE4-NEXT: } else if .random() {
// BOOL-DONT-HANDLE4-NEXT: print("b \(<#err#>!)")
// BOOL-DONT-HANDLE4-NEXT: } else {
// BOOL-DONT-HANDLE4-NEXT: print("c")
// BOOL-DONT-HANDLE4-NEXT: }
// We cannot use refactor-check-compiles, as a placeholder cannot be force unwrapped.
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR-SILLY %s
boolWithErr { success, err in
if success == false && err == nil {
print("ummm wat \(err!)")
return
}
print("not err")
}
// BOOL-WITH-ERR-SILLY: let success = try await boolWithErr()
// BOOL-WITH-ERR-SILLY-NEXT: if success == false && <#err#> == nil {
// BOOL-WITH-ERR-SILLY-NEXT: print("ummm wat \(<#err#>!)")
// BOOL-WITH-ERR-SILLY-NEXT: <#return#>
// BOOL-WITH-ERR-SILLY-NEXT: }
// BOOL-WITH-ERR-SILLY-NEXT: print("not err")
// We cannot use refactor-check-compiles, as a placeholder cannot be force unwrapped.
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR-SILLY2 %s
boolWithErr { success, err in
if success {
print("ummm wat \(err!)")
} else {
print("ummm wat \(err!)")
}
}
// The err unwrap is in both blocks, so it's not clear what to classify as.
// BOOL-WITH-ERR-SILLY2: let success = try await boolWithErr()
// BOOL-WITH-ERR-SILLY2-NEXT: if success {
// BOOL-WITH-ERR-SILLY2-NEXT: print("ummm wat \(<#err#>!)")
// BOOL-WITH-ERR-SILLY2-NEXT: } else {
// BOOL-WITH-ERR-SILLY2-NEXT: print("ummm wat \(<#err#>!)")
// BOOL-WITH-ERR-SILLY2-NEXT: }
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=MULTI-BOOL-WITH-ERR %s
multipleBoolWithErr { str, b1, b2, err in
if !b1 && !b2 {
print("a \(err!)")
}
if b1, b2 {
print("b \(err!)")
}
if !b1 {
print("c \(err!)")
}
if !b2 {
print("d \(err!)")
}
}
// Don't handle the case where multiple flag checks are done in a single
// condition, because it's not exactly clear what the user is doing. It's a
// little unfortunate that we'll allow multiple flag checks in seperate
// conditions, but both of these cases seem somewhat uncommon, and there's no
// real way to completely enforce a single flag param across e.g multiple calls
// to the same function, so this is probably okay for now.
// MULTI-BOOL-WITH-ERR: do {
// MULTI-BOOL-WITH-ERR-NEXT: let (str, b1, b2) = try await multipleBoolWithErr()
// MULTI-BOOL-WITH-ERR-NEXT: } catch let err {
// MULTI-BOOL-WITH-ERR-NEXT: if !<#b1#> && !<#b2#> {
// MULTI-BOOL-WITH-ERR-NEXT: print("a \(err)")
// MULTI-BOOL-WITH-ERR-NEXT: }
// MULTI-BOOL-WITH-ERR-NEXT: if <#b1#>, <#b2#> {
// MULTI-BOOL-WITH-ERR-NEXT: print("b \(err)")
// MULTI-BOOL-WITH-ERR-NEXT: }
// MULTI-BOOL-WITH-ERR-NEXT: print("c \(err)")
// MULTI-BOOL-WITH-ERR-NEXT: print("d \(err)")
// MULTI-BOOL-WITH-ERR-NEXT: }
// We cannot use refactor-check-compiles, as a placeholder cannot be force unwrapped.
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=OPT-BOOL-WITH-ERR %s
optionalBoolWithErr { str, optBool, b, err in
if optBool != nil {
print("a \(err!)")
}
if optBool == nil {
print("b \(err!)")
}
if optBool == true {
print("c \(err!)")
}
if ((optBool) == (false)) {
print("d \(err!)")
}
if optBool == false {
print("e \(String(describing: err))")
}
if optBool != true {
print("f \(err!)")
}
if b {
print("g \(err!)")
}
}
// It's a little unfortunate that print("a \(<#err#>!)") gets classified in the success
// block below, but it doesn't seem like a case that's likely to come up, as optBool
// would then be inaccessible in the error block.
// OPT-BOOL-WITH-ERR: do {
// OPT-BOOL-WITH-ERR-NEXT: let (str, optBool, b) = try await optionalBoolWithErr()
// OPT-BOOL-WITH-ERR-NEXT: print("a \(<#err#>!)")
// OPT-BOOL-WITH-ERR-NEXT: if <#optBool#> == false {
// OPT-BOOL-WITH-ERR-NEXT: print("e \(String(describing: <#err#>))")
// OPT-BOOL-WITH-ERR-NEXT: }
// OPT-BOOL-WITH-ERR-NEXT: if <#optBool#> != true {
// OPT-BOOL-WITH-ERR-NEXT: print("f \(<#err#>!)")
// OPT-BOOL-WITH-ERR-NEXT: }
// OPT-BOOL-WITH-ERR-NEXT: } catch let err {
// OPT-BOOL-WITH-ERR-NEXT: print("b \(err)")
// OPT-BOOL-WITH-ERR-NEXT: print("c \(err)")
// OPT-BOOL-WITH-ERR-NEXT: print("d \(err)")
// OPT-BOOL-WITH-ERR-NEXT: print("g \(err)")
// OPT-BOOL-WITH-ERR-NEXT: }
// We cannot use refactor-check-compiles, as a placeholder cannot be force unwrapped.
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=OBJC-BOOL-WITH-ERR %s
ClassWithHandlerMethods.firstBoolFlagSuccess("") { str, success, unrelated, err in
if !unrelated {
print(err!)
}
if !success {
print("oh no")
}
if !success {
print(err!)
}
if success {
print("woo")
}
if str != nil {
print("also woo")
}
}
// OBJC-BOOL-WITH-ERR: do {
// OBJC-BOOL-WITH-ERR-NEXT: let (str, success, unrelated) = try await ClassWithHandlerMethods.firstBoolFlagSuccess("")
// OBJC-BOOL-WITH-ERR-NEXT: if !unrelated {
// OBJC-BOOL-WITH-ERR-NEXT: print(<#err#>!)
// OBJC-BOOL-WITH-ERR-NEXT: }
// OBJC-BOOL-WITH-ERR-NEXT: print("woo")
// OBJC-BOOL-WITH-ERR-NEXT: print("also woo")
// OBJC-BOOL-WITH-ERR-NEXT: } catch let err {
// OBJC-BOOL-WITH-ERR-NEXT: print("oh no")
// OBJC-BOOL-WITH-ERR-NEXT: print(err)
// OBJC-BOOL-WITH-ERR-NEXT: }
// We cannot use refactor-check-compiles, as a placeholder cannot be force unwrapped.
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=OBJC-BOOL-WITH-ERR2 %s
ClassWithHandlerMethods.secondBoolFlagFailure("") { str, unrelated, failure, err in
if unrelated {
print(err!)
}
if failure {
print("oh no")
}
if failure {
print(err!)
}
if !failure {
print("woo")
}
if str != nil {
print("also woo")
}
if failure && err == nil {
print("wat")
}
if failure && err != nil {
print("neat")
}
if failure, let _ = err {
print("neato")
}
}
// OBJC-BOOL-WITH-ERR2: do {
// OBJC-BOOL-WITH-ERR2-NEXT: let (str, unrelated, failure) = try await ClassWithHandlerMethods.secondBoolFlagFailure("")
// OBJC-BOOL-WITH-ERR2-NEXT: if unrelated {
// OBJC-BOOL-WITH-ERR2-NEXT: print(<#err#>!)
// OBJC-BOOL-WITH-ERR2-NEXT: }
// OBJC-BOOL-WITH-ERR2-NEXT: print("woo")
// OBJC-BOOL-WITH-ERR2-NEXT: print("also woo")
// OBJC-BOOL-WITH-ERR2-NEXT: if failure && <#err#> == nil {
// OBJC-BOOL-WITH-ERR2-NEXT: print("wat")
// OBJC-BOOL-WITH-ERR2-NEXT: }
// OBJC-BOOL-WITH-ERR2-NEXT: } catch let err {
// OBJC-BOOL-WITH-ERR2-NEXT: print("oh no")
// OBJC-BOOL-WITH-ERR2-NEXT: print(err)
// OBJC-BOOL-WITH-ERR2-NEXT: print("neat")
// OBJC-BOOL-WITH-ERR2-NEXT: print("neato")
// OBJC-BOOL-WITH-ERR2-NEXT: }
}
// FIXME: The 'err' in doThings() should become a placeholder (rdar://78509286).
// BOOL-DONT-HANDLE2: let success = try await boolWithErr()
// BOOL-DONT-HANDLE2-NEXT: if !success {
// BOOL-DONT-HANDLE2-NEXT: func doThings() {
// BOOL-DONT-HANDLE2-NEXT: fatalError("oh no \(err!)")
// BOOL-DONT-HANDLE2-NEXT: }
// BOOL-DONT-HANDLE2-NEXT: doThings()
// BOOL-DONT-HANDLE2-NEXT: }
// BOOL-DONT-HANDLE2-NEXT: if !success {
// BOOL-DONT-HANDLE2-NEXT: let doThings = {
// BOOL-DONT-HANDLE2-NEXT: fatalError("oh no \(<#err#>!)")
// BOOL-DONT-HANDLE2-NEXT: }
// BOOL-DONT-HANDLE2-NEXT: doThings()
// BOOL-DONT-HANDLE2-NEXT: }
// BOOL-DONT-HANDLE2-NEXT: if !success {
// BOOL-DONT-HANDLE2-NEXT: while <#err#> != nil {
// BOOL-DONT-HANDLE2-NEXT: fatalError("oh no \(<#err#>!)")
// BOOL-DONT-HANDLE2-NEXT: }
// BOOL-DONT-HANDLE2-NEXT: }
// BOOL-DONT-HANDLE2-NEXT: if !success {
// BOOL-DONT-HANDLE2-NEXT: for _: Int in [] {
// BOOL-DONT-HANDLE2-NEXT: fatalError("oh no \(<#err#>!)")
// BOOL-DONT-HANDLE2-NEXT: }
// BOOL-DONT-HANDLE2-NEXT: }
// BOOL-DONT-HANDLE2-NEXT: print("not err")
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-DONT-HANDLE3 %s
boolWithErr { success, err in
if !success {
fatalError("oh no maybe \(String(describing: err))")
}
print("not err")
}
// err is not force unwrapped, so don't handle.
// BOOL-DONT-HANDLE3: let success = try await boolWithErr()
// BOOL-DONT-HANDLE3-NEXT: if !success {
// BOOL-DONT-HANDLE3-NEXT: fatalError("oh no maybe \(String(describing: <#err#>))")
// BOOL-DONT-HANDLE3-NEXT: }
// BOOL-DONT-HANDLE3-NEXT: print("not err")
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-DONT-HANDLE4 %s
boolWithErr { failure, err in
if failure {
print("a")
} else if .random() {
print("b \(err!)")
} else {
print("c")
}
}
// Don't handle the case where the err unwrap occurs in an unrelated else if
// clause.
// BOOL-DONT-HANDLE4: let failure = try await boolWithErr()
// BOOL-DONT-HANDLE4-NEXT: if failure {
// BOOL-DONT-HANDLE4-NEXT: print("a")
// BOOL-DONT-HANDLE4-NEXT: } else if .random() {
// BOOL-DONT-HANDLE4-NEXT: print("b \(<#err#>!)")
// BOOL-DONT-HANDLE4-NEXT: } else {
// BOOL-DONT-HANDLE4-NEXT: print("c")
// BOOL-DONT-HANDLE4-NEXT: }
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR-SILLY %s
boolWithErr { success, err in
if success == false && err == nil {
print("ummm wat \(err!)")
return
}
print("not err")
}
// BOOL-WITH-ERR-SILLY: let success = try await boolWithErr()
// BOOL-WITH-ERR-SILLY-NEXT: if success == false && <#err#> == nil {
// BOOL-WITH-ERR-SILLY-NEXT: print("ummm wat \(<#err#>!)")
// BOOL-WITH-ERR-SILLY-NEXT: <#return#>
// BOOL-WITH-ERR-SILLY-NEXT: }
// BOOL-WITH-ERR-SILLY-NEXT: print("not err")
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=BOOL-WITH-ERR-SILLY2 %s
boolWithErr { success, err in
if success {
print("ummm wat \(err!)")
} else {
print("ummm wat \(err!)")
}
}
// The err unwrap is in both blocks, so it's not clear what to classify as.
// BOOL-WITH-ERR-SILLY2: let success = try await boolWithErr()
// BOOL-WITH-ERR-SILLY2-NEXT: if success {
// BOOL-WITH-ERR-SILLY2-NEXT: print("ummm wat \(<#err#>!)")
// BOOL-WITH-ERR-SILLY2-NEXT: } else {
// BOOL-WITH-ERR-SILLY2-NEXT: print("ummm wat \(<#err#>!)")
// BOOL-WITH-ERR-SILLY2-NEXT: }
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=MULTI-BOOL-WITH-ERR %s
multipleBoolWithErr { str, b1, b2, err in
if !b1 && !b2 {
print("a \(err!)")
}
if b1, b2 {
print("b \(err!)")
}
if !b1 {
print("c \(err!)")
}
if !b2 {
print("d \(err!)")
}
}
// Don't handle the case where multiple flag checks are done in a single
// condition, because it's not exactly clear what the user is doing. It's a
// little unfortunate that we'll allow multiple flag checks in seperate
// conditions, but both of these cases seem somewhat uncommon, and there's no
// real way to completely enforce a single flag param across e.g multiple calls
// to the same function, so this is probably okay for now.
// MULTI-BOOL-WITH-ERR: do {
// MULTI-BOOL-WITH-ERR-NEXT: let (str, b1, b2) = try await multipleBoolWithErr()
// MULTI-BOOL-WITH-ERR-NEXT: } catch let err {
// MULTI-BOOL-WITH-ERR-NEXT: if !<#b1#> && !<#b2#> {
// MULTI-BOOL-WITH-ERR-NEXT: print("a \(err)")
// MULTI-BOOL-WITH-ERR-NEXT: }
// MULTI-BOOL-WITH-ERR-NEXT: if <#b1#>, <#b2#> {
// MULTI-BOOL-WITH-ERR-NEXT: print("b \(err)")
// MULTI-BOOL-WITH-ERR-NEXT: }
// MULTI-BOOL-WITH-ERR-NEXT: print("c \(err)")
// MULTI-BOOL-WITH-ERR-NEXT: print("d \(err)")
// MULTI-BOOL-WITH-ERR-NEXT: }
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=OPT-BOOL-WITH-ERR %s
optionalBoolWithErr { str, optBool, b, err in
if optBool != nil {
print("a \(err!)")
}
if optBool == nil {
print("b \(err!)")
}
if optBool == true {
print("c \(err!)")
}
if ((optBool) == (false)) {
print("d \(err!)")
}
if optBool == false {
print("e \(String(describing: err))")
}
if optBool != true {
print("f \(err!)")
}
if b {
print("g \(err!)")
}
}
// It's a little unfortunate that print("a \(<#err#>!)") gets classified in the success
// block below, but it doesn't seem like a case that's likely to come up, as optBool
// would then be inaccessible in the error block.
// OPT-BOOL-WITH-ERR: do {
// OPT-BOOL-WITH-ERR-NEXT: let (str, optBool, b) = try await optionalBoolWithErr()
// OPT-BOOL-WITH-ERR-NEXT: print("a \(<#err#>!)")
// OPT-BOOL-WITH-ERR-NEXT: if <#optBool#> == false {
// OPT-BOOL-WITH-ERR-NEXT: print("e \(String(describing: <#err#>))")
// OPT-BOOL-WITH-ERR-NEXT: }
// OPT-BOOL-WITH-ERR-NEXT: if <#optBool#> != true {
// OPT-BOOL-WITH-ERR-NEXT: print("f \(<#err#>!)")
// OPT-BOOL-WITH-ERR-NEXT: }
// OPT-BOOL-WITH-ERR-NEXT: } catch let err {
// OPT-BOOL-WITH-ERR-NEXT: print("b \(err)")
// OPT-BOOL-WITH-ERR-NEXT: print("c \(err)")
// OPT-BOOL-WITH-ERR-NEXT: print("d \(err)")
// OPT-BOOL-WITH-ERR-NEXT: print("g \(err)")
// OPT-BOOL-WITH-ERR-NEXT: }
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=OBJC-BOOL-WITH-ERR %s
ClassWithHandlerMethods.firstBoolFlagSuccess("") { str, success, unrelated, err in
if !unrelated {
print(err!)
}
if !success {
print("oh no")
}
if !success {
print(err!)
}
if success {
print("woo")
}
if str != nil {
print("also woo")
}
}
// OBJC-BOOL-WITH-ERR: do {
// OBJC-BOOL-WITH-ERR-NEXT: let (str, success, unrelated) = try await ClassWithHandlerMethods.firstBoolFlagSuccess("")
// OBJC-BOOL-WITH-ERR-NEXT: if !unrelated {
// OBJC-BOOL-WITH-ERR-NEXT: print(<#err#>!)
// OBJC-BOOL-WITH-ERR-NEXT: }
// OBJC-BOOL-WITH-ERR-NEXT: print("woo")
// OBJC-BOOL-WITH-ERR-NEXT: print("also woo")
// OBJC-BOOL-WITH-ERR-NEXT: } catch let err {
// OBJC-BOOL-WITH-ERR-NEXT: print("oh no")
// OBJC-BOOL-WITH-ERR-NEXT: print(err)
// OBJC-BOOL-WITH-ERR-NEXT: }
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=OBJC-BOOL-WITH-ERR2 %s
ClassWithHandlerMethods.secondBoolFlagFailure("") { str, unrelated, failure, err in
if unrelated {
print(err!)
}
if failure {
print("oh no")
}
if failure {
print(err!)
}
if !failure {
print("woo")
}
if str != nil {
print("also woo")
}
if failure && err == nil {
print("wat")
}
if failure && err != nil {
print("neat")
}
if failure, let _ = err {
print("neato")
}
}
// OBJC-BOOL-WITH-ERR2: do {
// OBJC-BOOL-WITH-ERR2-NEXT: let (str, unrelated, failure) = try await ClassWithHandlerMethods.secondBoolFlagFailure("")
// OBJC-BOOL-WITH-ERR2-NEXT: if unrelated {
// OBJC-BOOL-WITH-ERR2-NEXT: print(<#err#>!)
// OBJC-BOOL-WITH-ERR2-NEXT: }
// OBJC-BOOL-WITH-ERR2-NEXT: print("woo")
// OBJC-BOOL-WITH-ERR2-NEXT: print("also woo")
// OBJC-BOOL-WITH-ERR2-NEXT: if failure && <#err#> == nil {
// OBJC-BOOL-WITH-ERR2-NEXT: print("wat")
// OBJC-BOOL-WITH-ERR2-NEXT: }
// OBJC-BOOL-WITH-ERR2-NEXT: } catch let err {
// OBJC-BOOL-WITH-ERR2-NEXT: print("oh no")
// OBJC-BOOL-WITH-ERR2-NEXT: print(err)
// OBJC-BOOL-WITH-ERR2-NEXT: print("neat")
// OBJC-BOOL-WITH-ERR2-NEXT: print("neato")
// OBJC-BOOL-WITH-ERR2-NEXT: }

View File

@@ -269,7 +269,7 @@ func voidResultCompletion(completion: @escaping (Result<Void, Error>) -> Void) {
// VOID-RESULT-HANDLER-NEXT: }
// rdar://77789360 Make sure we don't print a double return statement.
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=RETURN-HANDLING %s
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=RETURN-HANDLING %s
func testReturnHandling(_ completion: @escaping (String?, Error?) -> Void) {
return completion("", nil)
}
@@ -279,6 +279,8 @@ func testReturnHandling(_ completion: @escaping (String?, Error?) -> Void) {
// rdar://77789360 Make sure we don't print a double return statement and don't
// completely drop completion(a).
// Note we cannot use refactor-check-compiles here, as the placeholders mean we
// don't form valid AST.
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=RETURN-HANDLING2 %s
func testReturnHandling2(completion: @escaping (String) -> ()) {
simpleErr(arg: "") { x, err in

View File

@@ -1,215 +1,226 @@
// RUN: %empty-directory(%t)
// REQUIRES: concurrency
func manyWithError() async throws -> (String, Int) { ("", 0) }
func manyWithError(_ completion: @escaping (String?, Int?, Error?) -> Void) { }
func mixed() async -> (String, Int) { ("", 0) }
func mixed(_ completion: @escaping (String?, Int) -> Void) { }
func mixedError() async throws -> (String, Int) { ("", 0) }
func mixedError(_ completion: @escaping (String?, Int, Error?) -> Void) { }
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MANYBOUND %s
manyWithError { res1, res2, err in
print("before")
if let bad = err {
print("got error \(bad)")
return
func testParamsMulti() async throws {
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MANYBOUND %s
manyWithError { res1, res2, err in
print("before")
if let bad = err {
print("got error \(bad)")
return
}
if let str = res1, let i = res2 {
print("got result \(str)")
print("got result \(i)")
}
print("after")
}
if let str = res1, let i = res2 {
// MANYBOUND: do {
// MANYBOUND-NEXT: let (str, i) = try await manyWithError()
// MANYBOUND-NEXT: print("before")
// MANYBOUND-NEXT: print("got result \(str)")
// MANYBOUND-NEXT: print("got result \(i)")
// MANYBOUND-NEXT: print("after")
// MANYBOUND-NEXT: } catch let bad {
// MANYBOUND-NEXT: print("got error \(bad)")
// MANYBOUND-NEXT: }
// FIXME: This case is a little tricky: Being in the else block of 'if let str = res1'
// should allow us to place 'if let i = res2' in the failure block. However, this
// is a success condition, so we still place it in the success block. Really what
// we need to do here is check to see if manyWithError has an existing async
// alternative that still returns optional success values, and allow success
// classification in that case. Otherwise, we'd probably be better off leaving
// the condition unhandled, as it's not clear what the user is doing.
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MANYUNBOUND-ERR %s
manyWithError { res1, res2, err in
print("before")
if let str = res1 {
print("got result \(str)")
} else if let i = res2 {
print("got result \(i)")
} else {
print("got error \(err!)")
}
print("after")
}
// MANYUNBOUND-ERR: do {
// MANYUNBOUND-ERR-NEXT: let (str, i) = try await manyWithError()
// MANYUNBOUND-ERR-NEXT: print("before")
// MANYUNBOUND-ERR-NEXT: print("got result \(str)")
// MANYUNBOUND-ERR-NEXT: print("got result \(i)")
// MANYUNBOUND-ERR-NEXT: print("after")
// MANYUNBOUND-ERR-NEXT: } catch let err {
// MANYUNBOUND-ERR-NEXT: print("got error \(err)")
// MANYUNBOUND-ERR-NEXT: }
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MANYBOUND %s
manyWithError { res1, res2, err in
print("before")
if let bad = err {
print("got error \(bad)")
return
}
if let str = res1 {
print("got result \(str)")
}
if let i = res2 {
print("got result \(i)")
}
print("after")
}
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MIXED-COND %s
manyWithError { res1, res2, err in
print("before")
if res1 != nil && res2 == nil {
print("got result \(res1!)")
}
print("after")
}
// MIXED-COND: convert_params_multi.swift
// MIXED-COND-NEXT: let (res1, res2) = try await manyWithError()
// MIXED-COND-NEXT: print("before")
// MIXED-COND-NEXT: if <#res1#> != nil && <#res2#> == nil {
// MIXED-COND-NEXT: print("got result \(res1)")
// MIXED-COND-NEXT: }
// MIXED-COND-NEXT: print("after")
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MIXED-CONDELSE %s
manyWithError { res1, res2, err in
print("before")
if res1 != nil && res2 == nil {
print("got result \(res1!)")
} else {
print("bad")
}
print("after")
}
// MIXED-CONDELSE: var res1: String? = nil
// MIXED-CONDELSE-NEXT: var res2: Int? = nil
// MIXED-CONDELSE-NEXT: var err: Error? = nil
// MIXED-CONDELSE-NEXT: do {
// MIXED-CONDELSE-NEXT: (res1, res2) = try await manyWithError()
// MIXED-CONDELSE-NEXT: } catch {
// MIXED-CONDELSE-NEXT: err = error
// MIXED-CONDELSE-NEXT: }
// MIXED-CONDELSE-EMPTY:
// MIXED-CONDELSE-NEXT: print("before")
// MIXED-CONDELSE-NEXT: if res1 != nil && res2 == nil {
// MIXED-CONDELSE-NEXT: print("got result \(res1!)")
// MIXED-CONDELSE-NEXT: } else {
// MIXED-CONDELSE-NEXT: print("bad")
// MIXED-CONDELSE-NEXT: }
// MIXED-CONDELSE-NEXT: print("after")
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MANYUNBOUND-ERR %s
manyWithError { res1, res2, err in
print("before")
guard let str = res1, let i = res2 else {
print("got error \(err!)")
return
}
print("got result \(str)")
print("got result \(i)")
print("after")
}
print("after")
}
// MANYBOUND: do {
// MANYBOUND-NEXT: let (str, i) = try await manyWithError()
// MANYBOUND-NEXT: print("before")
// MANYBOUND-NEXT: print("got result \(str)")
// MANYBOUND-NEXT: print("got result \(i)")
// MANYBOUND-NEXT: print("after")
// MANYBOUND-NEXT: } catch let bad {
// MANYBOUND-NEXT: print("got error \(bad)")
// MANYBOUND-NEXT: }
// FIXME: This case is a little tricky: Being in the else block of 'if let str = res1'
// should allow us to place 'if let i = res2' in the failure block. However, this
// is a success condition, so we still place it in the success block. Really what
// we need to do here is check to see if manyWithError has an existing async
// alternative that still returns optional success values, and allow success
// classification in that case. Otherwise, we'd probably be better off leaving
// the condition unhandled, as it's not clear what the user is doing.
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MANYUNBOUND-ERR %s
manyWithError { res1, res2, err in
print("before")
if let str = res1 {
print("got result \(str)")
} else if let i = res2 {
print("got result \(i)")
} else {
print("got error \(err!)")
}
print("after")
}
// MANYUNBOUND-ERR: do {
// MANYUNBOUND-ERR-NEXT: let (str, i) = try await manyWithError()
// MANYUNBOUND-ERR-NEXT: print("before")
// MANYUNBOUND-ERR-NEXT: print("got result \(str)")
// MANYUNBOUND-ERR-NEXT: print("got result \(i)")
// MANYUNBOUND-ERR-NEXT: print("after")
// MANYUNBOUND-ERR-NEXT: } catch let err {
// MANYUNBOUND-ERR-NEXT: print("got error \(err)")
// MANYUNBOUND-ERR-NEXT: }
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MANYBOUND %s
manyWithError { res1, res2, err in
print("before")
if let bad = err {
print("got error \(bad)")
return
}
if let str = res1 {
print("got result \(str)")
}
if let i = res2 {
print("got result \(i)")
}
print("after")
}
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MIXED-COND %s
manyWithError { res1, res2, err in
print("before")
if res1 != nil && res2 == nil {
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MANYUNBOUND %s
manyWithError { res1, res2, err in
print("before")
guard res1 != nil && res2 != nil && err == nil else {
print("got error \(err!)")
return
}
print("got result \(res1!)")
print("got result \(res2!)")
print("after")
}
print("after")
}
// MIXED-COND: convert_params_multi.swift
// MIXED-COND-NEXT: let (res1, res2) = try await manyWithError()
// MIXED-COND-NEXT: print("before")
// MIXED-COND-NEXT: if <#res1#> != nil && <#res2#> == nil {
// MIXED-COND-NEXT: print("got result \(res1)")
// MIXED-COND-NEXT: }
// MIXED-COND-NEXT: print("after")
// MANYUNBOUND: do {
// MANYUNBOUND-NEXT: let (res1, res2) = try await manyWithError()
// MANYUNBOUND-NEXT: print("before")
// MANYUNBOUND-NEXT: print("got result \(res1)")
// MANYUNBOUND-NEXT: print("got result \(res2)")
// MANYUNBOUND-NEXT: print("after")
// MANYUNBOUND-NEXT: } catch let err {
// MANYUNBOUND-NEXT: print("got error \(err)")
// MANYUNBOUND-NEXT: }
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MIXED-CONDELSE %s
manyWithError { res1, res2, err in
print("before")
if res1 != nil && res2 == nil {
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MANYUNBOUND %s
manyWithError { res1, res2, err in
print("before")
guard res1 != nil else {
print("got error \(err!)")
return
}
print("got result \(res1!)")
} else {
print("bad")
print("got result \(res2!)")
print("after")
}
print("after")
}
// MIXED-CONDELSE: var res1: String? = nil
// MIXED-CONDELSE-NEXT: var res2: Int? = nil
// MIXED-CONDELSE-NEXT: var err: Error? = nil
// MIXED-CONDELSE-NEXT: do {
// MIXED-CONDELSE-NEXT: (res1, res2) = try await manyWithError()
// MIXED-CONDELSE-NEXT: } catch {
// MIXED-CONDELSE-NEXT: err = error
// MIXED-CONDELSE-NEXT: }
// MIXED-CONDELSE-EMPTY:
// MIXED-CONDELSE-NEXT: print("before")
// MIXED-CONDELSE-NEXT: if res1 != nil && res2 == nil {
// MIXED-CONDELSE-NEXT: print("got result \(res1!)")
// MIXED-CONDELSE-NEXT: } else {
// MIXED-CONDELSE-NEXT: print("bad")
// MIXED-CONDELSE-NEXT: }
// MIXED-CONDELSE-NEXT: print("after")
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MANYUNBOUND-ERR %s
manyWithError { res1, res2, err in
print("before")
guard let str = res1, let i = res2 else {
print("got error \(err!)")
return
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MANYUNBOUND %s
manyWithError { res1, res2, err in
print("before")
guard err == nil else {
print("got error \(err!)")
return
}
print("got result \(res1!)")
print("got result \(res2!)")
print("after")
}
print("got result \(str)")
print("got result \(i)")
print("after")
}
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MANYUNBOUND %s
manyWithError { res1, res2, err in
print("before")
guard res1 != nil && res2 != nil && err == nil else {
print("got error \(err!)")
return
// Cannot use refactor-check-compiles, as cannot use non-optional 'str' in
// optional binding.
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MIXED %s
mixed { str, num in
print("before")
if let res = str {
print("got result \(res)")
}
print("\(num)")
print("after")
}
print("got result \(res1!)")
print("got result \(res2!)")
print("after")
}
// MANYUNBOUND: do {
// MANYUNBOUND-NEXT: let (res1, res2) = try await manyWithError()
// MANYUNBOUND-NEXT: print("before")
// MANYUNBOUND-NEXT: print("got result \(res1)")
// MANYUNBOUND-NEXT: print("got result \(res2)")
// MANYUNBOUND-NEXT: print("after")
// MANYUNBOUND-NEXT: } catch let err {
// MANYUNBOUND-NEXT: print("got error \(err)")
// MANYUNBOUND-NEXT: }
// MIXED: convert_params_multi.swift
// MIXED-NEXT: let (str, num) = await mixed()
// MIXED-NEXT: print("before")
// MIXED-NEXT: if let res = str {
// MIXED-NEXT: print("got result \(res)")
// MIXED-NEXT: }
// MIXED-NEXT: print("\(num)")
// MIXED-NEXT: print("after")
// MIXED-NOT: }
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MANYUNBOUND %s
manyWithError { res1, res2, err in
print("before")
guard res1 != nil else {
print("got error \(err!)")
return
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MIXED-ERROR %s
mixedError { str, num, err in
print("before")
if let res = str {
print("got result \(res)")
} else {
print("got \(err!)")
}
print("\(num)")
print("after")
}
print("got result \(res1!)")
print("got result \(res2!)")
print("after")
// MIXED-ERROR: convert_params_multi.swift
// MIXED-ERROR-NEXT: do {
// MIXED-ERROR-NEXT: let (res, num) = try await mixedError()
// MIXED-ERROR-NEXT: print("before")
// MIXED-ERROR-NEXT: print("got result \(res)")
// MIXED-ERROR-NEXT: print("\(num)")
// MIXED-ERROR-NEXT: print("after")
// MIXED-ERROR-NEXT: } catch let err {
// MIXED-ERROR-NEXT: print("got \(err)")
// MIXED-ERROR-NEXT: }
// MIXED-ERROR-NOT: }
}
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MANYUNBOUND %s
manyWithError { res1, res2, err in
print("before")
guard err == nil else {
print("got error \(err!)")
return
}
print("got result \(res1!)")
print("got result \(res2!)")
print("after")
}
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=MIXED %s
mixed { str, num in
print("before")
if let res = str {
print("got result \(res)")
}
print("\(num)")
print("after")
}
// MIXED: convert_params_multi.swift
// MIXED-NEXT: let (str, num) = await mixed()
// MIXED-NEXT: print("before")
// MIXED-NEXT: if let res = str {
// MIXED-NEXT: print("got result \(res)")
// MIXED-NEXT: }
// MIXED-NEXT: print("\(num)")
// MIXED-NEXT: print("after")
// MIXED-NOT: }
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=MIXED-ERROR %s
mixedError { str, num, err in
print("before")
if let res = str {
print("got result \(res)")
} else {
print("got \(err!)")
}
print("\(num)")
print("after")
}
// MIXED-ERROR: convert_params_multi.swift
// MIXED-ERROR-NEXT: do {
// MIXED-ERROR-NEXT: let (res, num) = try await mixedError()
// MIXED-ERROR-NEXT: print("before")
// MIXED-ERROR-NEXT: print("got result \(res)")
// MIXED-ERROR-NEXT: print("\(num)")
// MIXED-ERROR-NEXT: print("after")
// MIXED-ERROR-NEXT: } catch let err {
// MIXED-ERROR-NEXT: print("got \(err)")
// MIXED-ERROR-NEXT: }
// MIXED-ERROR-NOT: }

File diff suppressed because it is too large Load Diff

View File

@@ -123,7 +123,7 @@ func testPatterns() async throws {
// FALLBACK-NEXT: guard let (str1, str2) = strs, str1 == "hi" else { fatalError() }
// FALLBACK-NEXT: print(str1, str2, err)
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=GUARD-AND-UNHANDLED %s
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=GUARD-AND-UNHANDLED %s
stringTupleParam { strs, err in
guard let (str1, str2) = strs else { fatalError() }
print(str1, str2)
@@ -436,6 +436,7 @@ func testNameCollision2(_ completion: @escaping () -> Void) {
// NAME-COLLISION2-NEXT: print("b", x, y, z)
// NAME-COLLISION2-NEXT: }
// Cannot use refactor-check-compiles, as cannot pattern match with placeholders.
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=TEST-UNHANDLED %s
anyCompletion { val, err in
if let x = val {
@@ -552,7 +553,7 @@ anyResultCompletion { res in
// Make sure we handle a capture list okay.
class C {
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=CAPTURE %s
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=CAPTURE %s
func foo() {
let _ = { [weak self] in
print(self!)

View File

@@ -1,513 +1,531 @@
// RUN: %empty-directory(%t)
// REQUIRES: concurrency
func simple(_ completion: @escaping (Result<String, Error>) -> Void) { }
func simple() async throws -> String { "" }
func simpleWithArg(_ arg: Int) async throws -> String { "" }
func simpleWithArg(_ arg: Int, _ completion: @escaping (Result<String, Error>) -> Void) { }
func noError() async -> String { "" }
func noError(_ completion: @escaping (Result<String, Never>) -> Void) { }
func voidNoError() async {}
func voidNoError(completion: @escaping (Result<Void, Never>) -> Void) {}
func voidError() async throws {}
func voidError(completion: @escaping (Result<Void, Error>) -> Void) {}
func test(_ str: String) -> Bool { return false }
// RUN: %refactor -add-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix VOID-RESULT %s
// RUN: %refactor-check-compiles -add-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix VOID-RESULT %s
func voidResult(completion: @escaping (Result<Void, Never>) -> Void) {}
// VOID-RESULT: func voidResult() async {}
// RUN: %refactor -add-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix VOID-AND-ERROR-RESULT %s
// RUN: %refactor-check-compiles -add-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix VOID-AND-ERROR-RESULT %s
func voidAndErrorResult(completion: @escaping (Result<Void, Error>) -> Void) {}
// VOID-AND-ERROR-RESULT: func voidAndErrorResult() async throws {}
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=SIMPLE %s
simple { res in
print("result \(res)")
}
// SIMPLE: let res = try await simple()
// SIMPLE-NEXT: print("result \(<#res#>)")
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NOERROR %s
noError { res in
print("result \(res)")
}
// NOERROR: let res = await noError()
// NOERROR-NEXT: print("result \(<#res#>)")
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=DOBLOCK %s
simple { res in
print("before")
switch res {
case .success(let str):
print("result \(str)")
case .failure(let err):
print("error \(err)")
func testResultConversion() async throws {
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=SIMPLE %s
simple { res in
print("result \(res)")
}
print("after")
}
// DOBLOCK: do {
// DOBLOCK-NEXT: let str = try await simple()
// DOBLOCK-NEXT: print("before")
// DOBLOCK-NEXT: print("result \(str)")
// DOBLOCK-NEXT: print("after")
// DOBLOCK-NEXT: } catch let err {
// DOBLOCK-NEXT: print("error \(err)")
// DOBLOCK-NEXT: }
// SIMPLE: let res = try await simple()
// SIMPLE-NEXT: print("result \(<#res#>)")
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=DOBLOCK %s
simple { res in
print("before")
if case .success(let str) = res {
print("result \(str)")
} else if case .failure(let err) = res {
print("error \(err)")
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=NOERROR %s
noError { res in
print("result \(res)")
}
print("after")
}
// NOERROR: let res = await noError()
// NOERROR-NEXT: print("result \(<#res#>)")
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=DOBLOCK %s
simple { res in
print("before")
switch res {
case .success(let str):
print("result \(str)")
break
case .failure(let err):
print("error \(err)")
break
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=DOBLOCK %s
simple { res in
print("before")
switch res {
case .success(let str):
print("result \(str)")
case .failure(let err):
print("error \(err)")
}
print("after")
}
print("after")
}
// DOBLOCK: do {
// DOBLOCK-NEXT: let str = try await simple()
// DOBLOCK-NEXT: print("before")
// DOBLOCK-NEXT: print("result \(str)")
// DOBLOCK-NEXT: print("after")
// DOBLOCK-NEXT: } catch let err {
// DOBLOCK-NEXT: print("error \(err)")
// DOBLOCK-NEXT: }
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=DOBLOCK %s
simple { res in
print("before")
switch res {
case .success(let str):
print("result \(str)")
return
case .failure(let err):
print("error \(err)")
return
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=DOBLOCK %s
simple { res in
print("before")
if case .success(let str) = res {
print("result \(str)")
} else if case .failure(let err) = res {
print("error \(err)")
}
print("after")
}
print("after")
}
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=SUCCESS %s
simple { res in
print("before")
if case .success(let str) = res {
print("result \(str)")
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=DOBLOCK %s
simple { res in
print("before")
switch res {
case .success(let str):
print("result \(str)")
break
case .failure(let err):
print("error \(err)")
break
}
print("after")
}
print("after")
}
// SUCCESS: convert_result.swift
// SUCCESS-NEXT: let str = try await simple()
// SUCCESS-NEXT: print("before")
// SUCCESS-NEXT: print("result \(str)")
// SUCCESS-NEXT: print("after")
// SUCCESS-NOT: }
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=SUCCESS %s
simple { res in
print("before")
guard case .success(let str) = res else {
return
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=DOBLOCK %s
simple { res in
print("before")
switch res {
case .success(let str):
print("result \(str)")
return
case .failure(let err):
print("error \(err)")
return
}
print("after")
}
print("result \(str)")
print("after")
}
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=DOBLOCKUNBOUND %s
simple { res in
print("before")
guard case .success(let str) = res else {
print("err")
return
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=SUCCESS %s
simple { res in
print("before")
if case .success(let str) = res {
print("result \(str)")
}
print("after")
}
print("result \(str)")
print("after")
}
// DOBLOCKUNBOUND: do {
// DOBLOCKUNBOUND-NEXT: let str = try await simple()
// DOBLOCKUNBOUND-NEXT: print("before")
// DOBLOCKUNBOUND-NEXT: print("result \(str)")
// DOBLOCKUNBOUND-NEXT: print("after")
// DOBLOCKUNBOUND-NEXT: } catch {
// DOBLOCKUNBOUND-NEXT: print("err")
// DOBLOCKUNBOUND-NEXT: }
// SUCCESS: convert_result.swift
// SUCCESS-NEXT: let str = try await simple()
// SUCCESS-NEXT: print("before")
// SUCCESS-NEXT: print("result \(str)")
// SUCCESS-NEXT: print("after")
// SUCCESS-NOT: }
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=SUCCESS %s
simple { res in
print("before")
if let str = try? res.get() {
print("result \(str)")
}
print("after")
}
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=DOBLOCKUNBOUND %s
simple { res in
print("before")
guard let str = try? res.get() else {
print("err")
return
}
print("result \(str)")
print("after")
}
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=UNKNOWN %s
simple { res in
print("before \(res)")
if case .success(let str) = res {
print("result \(str) \(try! res.get())")
}
print("after")
}
// UNKNOWN: convert_result.swift
// UNKNOWN-NEXT: let str = try await simple()
// UNKNOWN-NEXT: print("before \(<#str#>)")
// UNKNOWN-NEXT: print("result \(str) \(try! <#str#>.get())")
// UNKNOWN-NEXT: print("after")
// UNKNOWN-NOT: }
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=UNKNOWNUNBOUND %s
simple { res in
print("before \(res)")
if case .success = res {
print("result \(res) \(try! res.get())")
}
print("after")
}
// UNKNOWNUNBOUND: convert_result.swift
// UNKNOWNUNBOUND-NEXT: let res = try await simple()
// UNKNOWNUNBOUND-NEXT: print("before \(<#res#>)")
// UNKNOWNUNBOUND-NEXT: print("result \(<#res#>) \(try! <#res#>.get())")
// UNKNOWNUNBOUND-NEXT: print("after")
// UNKNOWN-NOT: }
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=MULTIPLE-BINDS %s
simple { res in
print("before")
if case .success(let str) = res {
print("result \(str)")
}
if case .success(let str2) = res {
print("result \(str2)")
}
print("after")
}
// MULTIPLE-BINDS: convert_result.swift
// MULTIPLE-BINDS-NEXT: let str = try await simple()
// MULTIPLE-BINDS-NEXT: print("before")
// MULTIPLE-BINDS-NEXT: print("result \(str)")
// MULTIPLE-BINDS-NEXT: print("result \(str)")
// MULTIPLE-BINDS-NEXT: print("after")
// MULTIPLE-BINDS-NOT: }
// RUN: not %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1
simple { res in
print("before")
switch res {
case .success(let str):
print("result \(str)")
case .failure(let err):
print("error \(err)")
default:
print("default")
}
print("after")
}
// RUN: not %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1
simple { res in
print("before")
switch res {
case .success(let str):
print("result \(str)")
default:
print("err")
}
print("after")
}
// RUN: not %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1
simple { res in
print("before")
switch res {
case .success, .failure:
print("either")
}
print("after")
}
// RUN: not %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1
simple { res in
print("before")
switch res {
case .success, .failure:
print("either")
}
print("after")
}
// RUN: not %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1
simple { res in
print("before")
switch res {
case .success:
fallthrough
case .failure:
print("either")
}
print("after")
}
// RUN: not %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1
simple { res in
print("before")
switch res {
case .success(let str) where str.hasPrefix("match"):
print("pattern matched result \(str)")
case .success(let str):
print("result \(str)")
case .failure(let err):
print("error \(err)")
}
print("after")
}
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NESTEDRET %s
simple { res in
print("before")
switch res {
case .success(let str):
if test(str) {
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=SUCCESS %s
simple { res in
print("before")
guard case .success(let str) = res else {
return
}
print("result \(str)")
case .failure:
break
print("after")
}
print("after")
}
// NESTEDRET: convert_result.swift
// NESTEDRET-NEXT: let str = try await simple()
// NESTEDRET-NEXT: print("before")
// NESTEDRET-NEXT: if test(str) {
// NESTEDRET-NEXT: <#return#>
// NESTEDRET-NEXT: }
// NESTEDRET-NEXT: print("result \(str)")
// NESTEDRET-NEXT: print("after")
// NESTEDRET-NOT: }
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NESTEDBREAK %s
simple { res in
print("before")
switch res {
case .success(let str):
if test(str) {
break
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=DOBLOCKUNBOUND %s
simple { res in
print("before")
guard case .success(let str) = res else {
print("err")
return
}
print("result \(str)")
case .failure:
break
print("after")
}
print("after")
}
// NESTEDBREAK: convert_result.swift
// NESTEDBREAK-NEXT: let str = try await simple()
// NESTEDBREAK-NEXT: print("before")
// NESTEDBREAK-NEXT: if test(str) {
// NESTEDBREAK-NEXT: <#break#>
// NESTEDBREAK-NEXT: }
// NESTEDBREAK-NEXT: print("result \(str)")
// NESTEDBREAK-NEXT: print("after")
// NESTEDBREAK-NOT: }
// DOBLOCKUNBOUND: do {
// DOBLOCKUNBOUND-NEXT: let str = try await simple()
// DOBLOCKUNBOUND-NEXT: print("before")
// DOBLOCKUNBOUND-NEXT: print("result \(str)")
// DOBLOCKUNBOUND-NEXT: print("after")
// DOBLOCKUNBOUND-NEXT: } catch {
// DOBLOCKUNBOUND-NEXT: print("err")
// DOBLOCKUNBOUND-NEXT: }
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NESTEDBREAK-COMMENT %s
simple { res in // a
// b
print("before")
// c
switch res {
// d
case .success(let str): // e
if test(str) {
// f
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=SUCCESS %s
simple { res in
print("before")
if let str = try? res.get() {
print("result \(str)")
}
print("after")
}
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=DOBLOCKUNBOUND %s
simple { res in
print("before")
guard let str = try? res.get() else {
print("err")
return
}
print("result \(str)")
print("after")
}
// Cannot use refactor-check-compiles, as cannot infer type of the 'get' member on the placeholder.
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNKNOWN %s
simple { res in
print("before \(res)")
if case .success(let str) = res {
print("result \(str) \(try! res.get())")
}
print("after")
}
// UNKNOWN: convert_result.swift
// UNKNOWN-NEXT: let str = try await simple()
// UNKNOWN-NEXT: print("before \(<#str#>)")
// UNKNOWN-NEXT: print("result \(str) \(try! <#str#>.get())")
// UNKNOWN-NEXT: print("after")
// UNKNOWN-NOT: }
// Cannot use refactor-check-compiles, as cannot infer type of the 'get' member on the placeholder.
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNKNOWNUNBOUND %s
simple { res in
print("before \(res)")
if case .success = res {
print("result \(res) \(try! res.get())")
}
print("after")
}
// UNKNOWNUNBOUND: convert_result.swift
// UNKNOWNUNBOUND-NEXT: let res = try await simple()
// UNKNOWNUNBOUND-NEXT: print("before \(<#res#>)")
// UNKNOWNUNBOUND-NEXT: print("result \(<#res#>) \(try! <#res#>.get())")
// UNKNOWNUNBOUND-NEXT: print("after")
// UNKNOWN-NOT: }
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MULTIPLE-BINDS %s
simple { res in
print("before")
if case .success(let str) = res {
print("result \(str)")
}
if case .success(let str2) = res {
print("result \(str2)")
}
print("after")
}
// MULTIPLE-BINDS: convert_result.swift
// MULTIPLE-BINDS-NEXT: let str = try await simple()
// MULTIPLE-BINDS-NEXT: print("before")
// MULTIPLE-BINDS-NEXT: print("result \(str)")
// MULTIPLE-BINDS-NEXT: print("result \(str)")
// MULTIPLE-BINDS-NEXT: print("after")
// MULTIPLE-BINDS-NOT: }
// RUN: not %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3
simple { res in
print("before")
switch res {
case .success(let str):
print("result \(str)")
case .failure(let err):
print("error \(err)")
default:
print("default")
}
print("after")
}
// RUN: not %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3
simple { res in
print("before")
switch res {
case .success(let str):
print("result \(str)")
default:
print("err")
}
print("after")
}
// RUN: not %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3
simple { res in
print("before")
switch res {
case .success, .failure:
print("either")
}
print("after")
}
// RUN: not %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3
simple { res in
print("before")
switch res {
case .success, .failure:
print("either")
}
print("after")
}
// RUN: not %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3
simple { res in
print("before")
switch res {
case .success:
fallthrough
case .failure:
print("either")
}
print("after")
}
// RUN: not %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3
simple { res in
print("before")
switch res {
case .success(let str) where str.hasPrefix("match"):
print("pattern matched result \(str)")
case .success(let str):
print("result \(str)")
case .failure(let err):
print("error \(err)")
}
print("after")
}
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=NESTEDRET %s
simple { res in
print("before")
switch res {
case .success(let str):
if test(str) {
return
}
print("result \(str)")
case .failure:
break
}
print("after")
}
// NESTEDRET: convert_result.swift
// NESTEDRET-NEXT: let str = try await simple()
// NESTEDRET-NEXT: print("before")
// NESTEDRET-NEXT: if test(str) {
// NESTEDRET-NEXT: <#return#>
// NESTEDRET-NEXT: }
// NESTEDRET-NEXT: print("result \(str)")
// NESTEDRET-NEXT: print("after")
// NESTEDRET-NOT: }
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=NESTEDBREAK %s
simple { res in
print("before")
switch res {
case .success(let str):
if test(str) {
break
}
print("result \(str)")
case .failure:
break
}
print("after")
}
// NESTEDBREAK: convert_result.swift
// NESTEDBREAK-NEXT: let str = try await simple()
// NESTEDBREAK-NEXT: print("before")
// NESTEDBREAK-NEXT: if test(str) {
// NESTEDBREAK-NEXT: <#break#>
// NESTEDBREAK-NEXT: }
// NESTEDBREAK-NEXT: print("result \(str)")
// NESTEDBREAK-NEXT: print("after")
// NESTEDBREAK-NOT: }
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=NESTEDBREAK-COMMENT %s
simple { res in // a
// b
print("before")
// c
switch res {
// d
case .success(let str): // e
if test(str) {
// f
break
// g
}
// h
print("result \(str)")
// i
case .failure:
// j
break
// k
}
// l
print("after")
// m
}
// NESTEDBREAK-COMMENT: let str = try await simple()
// NESTEDBREAK-COMMENT-NEXT: // a
// NESTEDBREAK-COMMENT-NEXT: // b
// NESTEDBREAK-COMMENT-NEXT: print("before")
// NESTEDBREAK-COMMENT-NEXT: // c
// NESTEDBREAK-COMMENT-NEXT: // d
// NESTEDBREAK-COMMENT-NEXT: // e
// NESTEDBREAK-COMMENT-NEXT: if test(str) {
// NESTEDBREAK-COMMENT-NEXT: // f
// NESTEDBREAK-COMMENT-NEXT: <#break#>
// NESTEDBREAK-COMMENT-NEXT: // g
// NESTEDBREAK-COMMENT-NEXT: }
// NESTEDBREAK-COMMENT-NEXT: // h
// NESTEDBREAK-COMMENT-NEXT: print("result \(str)")
// NESTEDBREAK-COMMENT-NEXT: // i
// NESTEDBREAK-COMMENT-NEXT: // j
// NESTEDBREAK-COMMENT-NEXT: // k
// NESTEDBREAK-COMMENT-NEXT: // l
// NESTEDBREAK-COMMENT-NEXT: print("after")
// NESTEDBREAK-COMMENT-NEXT: // m
// NESTEDBREAK-COMMENT-NEXT: {{ }}
// NESTEDBREAK-COMMENT-NOT: }
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=ERROR-BLOCK-COMMENT %s
simple { res in
// a
print("before")
// b
switch res {
case .success(let str):
// c
print("result \(str)")
// d
case .failure:
// e
print("fail")
// f
return
// g
}
// h
print("result \(str)")
print("after")
// i
case .failure:
// j
break
// k
}
// l
print("after")
// m
}
// NESTEDBREAK-COMMENT: let str = try await simple()
// NESTEDBREAK-COMMENT-NEXT: // a
// NESTEDBREAK-COMMENT-NEXT: // b
// NESTEDBREAK-COMMENT-NEXT: print("before")
// NESTEDBREAK-COMMENT-NEXT: // c
// NESTEDBREAK-COMMENT-NEXT: // d
// NESTEDBREAK-COMMENT-NEXT: // e
// NESTEDBREAK-COMMENT-NEXT: if test(str) {
// NESTEDBREAK-COMMENT-NEXT: // f
// NESTEDBREAK-COMMENT-NEXT: <#break#>
// NESTEDBREAK-COMMENT-NEXT: // g
// NESTEDBREAK-COMMENT-NEXT: }
// NESTEDBREAK-COMMENT-NEXT: // h
// NESTEDBREAK-COMMENT-NEXT: print("result \(str)")
// NESTEDBREAK-COMMENT-NEXT: // i
// NESTEDBREAK-COMMENT-NEXT: // j
// NESTEDBREAK-COMMENT-NEXT: // k
// NESTEDBREAK-COMMENT-NEXT: // l
// NESTEDBREAK-COMMENT-NEXT: print("after")
// NESTEDBREAK-COMMENT-NEXT: // m
// NESTEDBREAK-COMMENT-EMPTY:
// NESTEDBREAK-COMMENT-NOT: }
// ERROR-BLOCK-COMMENT: do {
// ERROR-BLOCK-COMMENT-NEXT: let str = try await simple()
// ERROR-BLOCK-COMMENT-NEXT: // a
// ERROR-BLOCK-COMMENT-NEXT: print("before")
// ERROR-BLOCK-COMMENT-NEXT: // b
// ERROR-BLOCK-COMMENT-NEXT: // c
// ERROR-BLOCK-COMMENT-NEXT: print("result \(str)")
// ERROR-BLOCK-COMMENT-NEXT: // d
// ERROR-BLOCK-COMMENT-NEXT: // h
// ERROR-BLOCK-COMMENT-NEXT: print("after")
// ERROR-BLOCK-COMMENT-NEXT: // i
// ERROR-BLOCK-COMMENT-NEXT: {{ }}
// ERROR-BLOCK-COMMENT-NEXT: } catch {
// ERROR-BLOCK-COMMENT-NEXT: // e
// ERROR-BLOCK-COMMENT-NEXT: print("fail")
// ERROR-BLOCK-COMMENT-NEXT: // f
// ERROR-BLOCK-COMMENT-NEXT: // g
// ERROR-BLOCK-COMMENT-NEXT: {{ }}
// ERROR-BLOCK-COMMENT-NEXT: }
// ERROR-BLOCK-COMMENT-NOT: }
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=ERROR-BLOCK-COMMENT %s
simple { res in
// a
print("before")
// b
switch res {
case .success(let str):
// c
print("result \(str)")
// d
case .failure:
// e
print("fail")
// f
return
// g
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=VOID-RESULT-CALL %s
voidNoError { res in
print(res)
}
// h
print("after")
// i
}
// ERROR-BLOCK-COMMENT: do {
// ERROR-BLOCK-COMMENT-NEXT: let str = try await simple()
// ERROR-BLOCK-COMMENT-NEXT: // a
// ERROR-BLOCK-COMMENT-NEXT: print("before")
// ERROR-BLOCK-COMMENT-NEXT: // b
// ERROR-BLOCK-COMMENT-NEXT: // c
// ERROR-BLOCK-COMMENT-NEXT: print("result \(str)")
// ERROR-BLOCK-COMMENT-NEXT: // d
// ERROR-BLOCK-COMMENT-NEXT: // h
// ERROR-BLOCK-COMMENT-NEXT: print("after")
// ERROR-BLOCK-COMMENT-NEXT: // i
// ERROR-BLOCK-COMMENT-EMPTY:
// ERROR-BLOCK-COMMENT-NEXT: } catch {
// ERROR-BLOCK-COMMENT-NEXT: // e
// ERROR-BLOCK-COMMENT-NEXT: print("fail")
// ERROR-BLOCK-COMMENT-NEXT: // f
// ERROR-BLOCK-COMMENT-NEXT: // g
// ERROR-BLOCK-COMMENT-NEXT: {{ }}
// ERROR-BLOCK-COMMENT-NEXT: }
// ERROR-BLOCK-COMMENT-NOT: }
// VOID-RESULT-CALL: {{^}}await voidNoError()
// VOID-RESULT-CALL: {{^}}print(<#res#>)
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=VOID-RESULT-CALL %s
voidResult { res in
print(res)
}
// VOID-RESULT-CALL: {{^}}await voidResult()
// VOID-RESULT-CALL: {{^}}print(<#res#>)
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=VOID-AND-ERROR-RESULT-CALL %s
voidAndErrorResult { res in
print(res)
}
// VOID-AND-ERROR-RESULT-CALL: {{^}}try await voidAndErrorResult()
// VOID-AND-ERROR-RESULT-CALL: {{^}}print(<#res#>)
// Make sure we ignore an unrelated switch.
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=IGNORE-UNRELATED %s
simple { res in
print("before")
switch Bool.random() {
case true:
break
case false:
break
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=VOID-AND-ERROR-RESULT-CALL %s
voidError { res in
print(res)
}
print("after")
}
// IGNORE-UNRELATED: let res = try await simple()
// IGNORE-UNRELATED-NEXT: print("before")
// IGNORE-UNRELATED-NEXT: switch Bool.random() {
// IGNORE-UNRELATED-NEXT: case true:
// IGNORE-UNRELATED-NEXT: {{^}} break{{$}}
// IGNORE-UNRELATED-NEXT: case false:
// IGNORE-UNRELATED-NEXT: {{^}} break{{$}}
// IGNORE-UNRELATED-NEXT: }
// IGNORE-UNRELATED-NEXT: print("after")
// VOID-AND-ERROR-RESULT-CALL: {{^}}try await voidError()
// VOID-AND-ERROR-RESULT-CALL: {{^}}print(<#res#>)
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=BREAK-RET-PLACEHOLDER %s
simpleWithArg({ return 0 }()) { res in
switch res {
case .success:
if .random() { break }
x: if .random() { break x }
case .failure:
break
// Make sure we ignore an unrelated switch.
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=IGNORE-UNRELATED %s
simple { res in
print("before")
switch Bool.random() {
case true:
break
case false:
break
}
print("after")
}
// IGNORE-UNRELATED: let res = try await simple()
// IGNORE-UNRELATED-NEXT: print("before")
// IGNORE-UNRELATED-NEXT: switch Bool.random() {
// IGNORE-UNRELATED-NEXT: case true:
// IGNORE-UNRELATED-NEXT: {{^}} break{{$}}
// IGNORE-UNRELATED-NEXT: case false:
// IGNORE-UNRELATED-NEXT: {{^}} break{{$}}
// IGNORE-UNRELATED-NEXT: }
// IGNORE-UNRELATED-NEXT: print("after")
func foo<T>(_ x: T) {
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=BREAK-RET-PLACEHOLDER %s
simpleWithArg({ return 0 }()) { res in
switch res {
case .success:
if .random() { break }
x: if .random() { break x }
case .failure:
break
}
func foo<T>(_ x: T) {
if .random() { return }
}
foo(res)
let fn = {
if .random() { return }
return
}
fn()
_ = { return }()
switch Bool.random() {
case true:
break
case false:
if .random() { break }
y: if .random() { break y }
return
}
x: if .random() {
break x
}
if .random() { return }
}
foo(res)
let fn = {
if .random() { return }
return
}
fn()
// Make sure we replace lifted break/returns with placeholders, but keep nested
// break/returns in e.g closures or labelled control flow in place.
_ = { return }()
switch Bool.random() {
case true:
break
case false:
if .random() { break }
y: if .random() { break y }
return
}
x: if .random() {
break x
}
if .random() { return }
// BREAK-RET-PLACEHOLDER: let res = try await simpleWithArg({ return 0 }())
// BREAK-RET-PLACEHOLDER-NEXT: if .random() { <#break#> }
// BREAK-RET-PLACEHOLDER-NEXT: x: if .random() { break x }
// BREAK-RET-PLACEHOLDER-NEXT: func foo<T>(_ x: T) {
// BREAK-RET-PLACEHOLDER-NEXT: if .random() { return }
// BREAK-RET-PLACEHOLDER-NEXT: }
// BREAK-RET-PLACEHOLDER-NEXT: foo(<#res#>)
// BREAK-RET-PLACEHOLDER-NEXT: let fn = {
// BREAK-RET-PLACEHOLDER-NEXT: if .random() { return }
// BREAK-RET-PLACEHOLDER-NEXT: {{^}} return{{$}}
// BREAK-RET-PLACEHOLDER-NEXT: }
// BREAK-RET-PLACEHOLDER-NEXT: fn()
// BREAK-RET-PLACEHOLDER-NEXT: _ = { return }()
// BREAK-RET-PLACEHOLDER-NEXT: switch Bool.random() {
// BREAK-RET-PLACEHOLDER-NEXT: case true:
// BREAK-RET-PLACEHOLDER-NEXT: {{^}} break{{$}}
// BREAK-RET-PLACEHOLDER-NEXT: case false:
// BREAK-RET-PLACEHOLDER-NEXT: if .random() { break }
// BREAK-RET-PLACEHOLDER-NEXT: y: if .random() { break y }
// BREAK-RET-PLACEHOLDER-NEXT: <#return#>
// BREAK-RET-PLACEHOLDER-NEXT: }
// BREAK-RET-PLACEHOLDER-NEXT: x: if .random() {
// BREAK-RET-PLACEHOLDER-NEXT: {{^}} break x{{$}}
// BREAK-RET-PLACEHOLDER-NEXT: }
// BREAK-RET-PLACEHOLDER-NEXT: if .random() { <#return#> }
}
// Make sure we replace lifted break/returns with placeholders, but keep nested
// break/returns in e.g closures or labelled control flow in place.
// BREAK-RET-PLACEHOLDER: let res = try await simpleWithArg({ return 0 }())
// BREAK-RET-PLACEHOLDER-NEXT: if .random() { <#break#> }
// BREAK-RET-PLACEHOLDER-NEXT: x: if .random() { break x }
// BREAK-RET-PLACEHOLDER-NEXT: func foo<T>(_ x: T) {
// BREAK-RET-PLACEHOLDER-NEXT: if .random() { return }
// BREAK-RET-PLACEHOLDER-NEXT: }
// BREAK-RET-PLACEHOLDER-NEXT: foo(<#res#>)
// BREAK-RET-PLACEHOLDER-NEXT: let fn = {
// BREAK-RET-PLACEHOLDER-NEXT: if .random() { return }
// BREAK-RET-PLACEHOLDER-NEXT: {{^}} return{{$}}
// BREAK-RET-PLACEHOLDER-NEXT: }
// BREAK-RET-PLACEHOLDER-NEXT: fn()
// BREAK-RET-PLACEHOLDER-NEXT: _ = { return }()
// BREAK-RET-PLACEHOLDER-NEXT: switch Bool.random() {
// BREAK-RET-PLACEHOLDER-NEXT: case true:
// BREAK-RET-PLACEHOLDER-NEXT: {{^}} break{{$}}
// BREAK-RET-PLACEHOLDER-NEXT: case false:
// BREAK-RET-PLACEHOLDER-NEXT: if .random() { break }
// BREAK-RET-PLACEHOLDER-NEXT: y: if .random() { break y }
// BREAK-RET-PLACEHOLDER-NEXT: <#return#>
// BREAK-RET-PLACEHOLDER-NEXT: }
// BREAK-RET-PLACEHOLDER-NEXT: x: if .random() {
// BREAK-RET-PLACEHOLDER-NEXT: {{^}} break x{{$}}
// BREAK-RET-PLACEHOLDER-NEXT: }
// BREAK-RET-PLACEHOLDER-NEXT: if .random() { <#return#> }

View File

@@ -62,7 +62,7 @@ func testPathClassification() async throws {
// ELSE-IF-CLASSIFICATION-NEXT: print("d")
// ELSE-IF-CLASSIFICATION-NEXT: }
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=ELSE-IF-CLASSIFICATION2 %s
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=ELSE-IF-CLASSIFICATION2 %s
simpleWithError { str, err in
if err == nil {
print("a")
@@ -172,6 +172,8 @@ func testPathClassification() async throws {
// ELSE-IF-CLASSIFICATION5-NEXT: }
// ELSE-IF-CLASSIFICATION5-NEXT: }
// Cannot use refactor-check-compiles, as 'err' cannot have its type inferred
// from placeholder.
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=IF-LET-RETURN-CLASSIFICATION %s
simpleWithError { str, err in
if let str = str {
@@ -196,7 +198,7 @@ func testPathClassification() async throws {
// IF-LET-RETURN-CLASSIFICATION-NEXT: }
// IF-LET-RETURN-CLASSIFICATION-NEXT: }
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=GUARD-CLASSIFICATION %s
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=GUARD-CLASSIFICATION %s
simpleWithError { str, err in
guard let str = str else {
print("a")

View File

@@ -23,7 +23,8 @@ def parse_args():
A drop-in replacement for a 'swift-refactor -dump-text' call that
1. Checks that the file still compiles after the refactoring by doing
'swift-refactor -dump-rewritten' and feeding the result to
'swift-frontend -typecheck'
'swift-frontend -typecheck -disable-availability-checking
-warn-on-editor-placeholder'
2. Outputting the result of the 'swift-refactor -dump-text' call
All arguments other than the following will be forwarded to
@@ -32,6 +33,9 @@ def parse_args():
- swift-refactor
- temp-dir
- enable-experimental-concurrency (sent to both)
- I (sent to both)
- sdk (sent to both)
- target (sent to both)
""")
parser.add_argument(
@@ -70,6 +74,19 @@ def parse_args():
swift-frontend
'''
)
parser.add_argument(
'-I',
action='append',
help='Add a directory to the import search path'
)
parser.add_argument(
'-sdk',
help='Path to the SDK to build against'
)
parser.add_argument(
'-target',
help='The target triple to build for'
)
return parser.parse_known_args()
@@ -80,10 +97,16 @@ def main():
args.pos.replace(':', '.')
temp_file_path = os.path.join(args.temp_dir, temp_file_name)
extra_frontend_args = []
extra_both_args = []
if args.enable_experimental_concurrency:
extra_refactor_args.append('-enable-experimental-concurrency')
extra_frontend_args.append('-enable-experimental-concurrency')
extra_both_args.append('-enable-experimental-concurrency')
if args.I:
for path in args.I:
extra_both_args += ['-I', path]
if args.sdk:
extra_both_args += ['-sdk', args.sdk]
if args.target:
extra_both_args += ['-target', args.target]
dump_text_output = run_cmd([
args.swift_refactor,
@@ -91,15 +114,16 @@ def main():
'-source-filename', args.source_filename,
'-rewritten-output-file', temp_file_path,
'-pos', args.pos
] + extra_refactor_args, desc='producing edit').decode("utf-8")
] + extra_refactor_args + extra_both_args, desc='producing edit').decode("utf-8")
sys.stdout.write(dump_text_output)
run_cmd([
args.swift_frontend,
'-typecheck',
temp_file_path,
'-disable-availability-checking'
] + extra_frontend_args, desc='checking that rewritten file compiles')
'-disable-availability-checking',
'-warn-on-editor-placeholder'
] + extra_both_args, desc='checking that rewritten file compiles')
if __name__ == '__main__':