Skip to content

Commit b08d3bb

Browse files
authored
Merge pull request swiftlang#37103 from ahoppen/pr-5.5/block-convention-to-async
[5.5][Refactoring] Support refactoring to async if callback is `@convention(block)`
2 parents b6417a0 + 855a698 commit b08d3bb

File tree

2 files changed

+40
-6
lines changed

2 files changed

+40
-6
lines changed

lib/IDE/Refactoring.cpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5012,6 +5012,22 @@ class AsyncConverter : private SourceEntityWalker {
50125012
}
50135013
}
50145014

5015+
/// From the given expression \p E, which is an argument to a function call,
5016+
/// extract the passed closure if there is one. Otherwise return \c nullptr.
5017+
ClosureExpr *extractCallback(Expr *E) {
5018+
if (auto Closure = dyn_cast<ClosureExpr>(E)) {
5019+
return Closure;
5020+
} else if (auto CaptureList = dyn_cast<CaptureListExpr>(E)) {
5021+
return CaptureList->getClosureBody();
5022+
} else if (auto FunctionConversion = dyn_cast<FunctionConversionExpr>(E)) {
5023+
// Closure arguments marked as e.g. `@convention(block)` produce arguments
5024+
// that are `FunctionConversionExpr`.
5025+
return extractCallback(FunctionConversion->getSubExpr());
5026+
} else {
5027+
return nullptr;
5028+
}
5029+
}
5030+
50155031
void addAsyncAlternativeCall(const CallExpr *CE,
50165032
const AsyncHandlerDesc &HandlerDesc) {
50175033
auto ArgList = callArgs(CE);
@@ -5020,11 +5036,7 @@ class AsyncConverter : private SourceEntityWalker {
50205036
return;
50215037
}
50225038

5023-
auto Callback = dyn_cast<ClosureExpr>(ArgList.ref()[HandlerDesc.Index]);
5024-
auto Capture = dyn_cast<CaptureListExpr>(ArgList.ref()[HandlerDesc.Index]);
5025-
if (Capture) {
5026-
Callback = Capture->getClosureBody();
5027-
}
5039+
ClosureExpr *Callback = extractCallback(ArgList.ref()[HandlerDesc.Index]);
50285040
if (!Callback) {
50295041
DiagEngine.diagnose(CE->getStartLoc(), diag::missing_callback_arg);
50305042
return;

test/refactoring/ConvertAsync/basic.swift

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,18 @@ func alreadyThrows(completion: (String) -> Void) throws { }
182182
// RUN: not %refactor -add-async-alternative -dump-text -source-filename %s -pos=%(line+1):1
183183
func noParamAutoclosure(completion: @autoclosure () -> Void) { }
184184

185+
// RUN: %refactor -add-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix BLOCK-CONVENTION %s
186+
func blockConvention(completion: @convention(block) () -> Void) { }
187+
// BLOCK-CONVENTION: func blockConvention() async { }
188+
189+
// RUN: %refactor -add-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix C-CONVENTION %s
190+
func cConvention(completion: @convention(c) () -> Void) { }
191+
// C-CONVENTION: func cConvention() async { }
192+
185193
// 2. Check that the various ways to call a function (and the positions the
186194
// refactoring is called from) are handled correctly
187195

188-
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefixes=CONVERT-FUNC,CALL,CALL-NOLABEL,CALL-WRAPPED,TRAILING,TRAILING-PARENS,TRAILING-WRAPPED,CALL-ARG,MANY-CALL,MEMBER-CALL,MEMBER-CALL2,MEMBER-PARENS,EMPTY-CAPTURE,CAPTURE,DEFAULT-ARGS-MISSING,DEFAULT-ARGS-CALL %s
196+
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefixes=CONVERT-FUNC,CALL,CALL-NOLABEL,CALL-WRAPPED,TRAILING,TRAILING-PARENS,TRAILING-WRAPPED,CALL-ARG,MANY-CALL,MEMBER-CALL,MEMBER-CALL2,MEMBER-PARENS,EMPTY-CAPTURE,CAPTURE,DEFAULT-ARGS-MISSING,DEFAULT-ARGS-CALL,BLOCK-CONVENTION-CALL,C-CONVENTION-CALL %s
189197
func testCalls() {
190198
// CONVERT-FUNC: {{^}}func testCalls() async {
191199
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+4):3 | %FileCheck -check-prefix=CALL %s
@@ -326,5 +334,19 @@ func testCalls() {
326334
}
327335
// DEFAULT-ARGS-CALL: let str = await defaultArgs(a: 1, b: 2){{$}}
328336
// DEFAULT-ARGS-CALL-NEXT: {{^}}print("defaultArgs")
337+
338+
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=BLOCK-CONVENTION-CALL %s
339+
blockConvention {
340+
print("blockConvention")
341+
}
342+
// BLOCK-CONVENTION-CALL: await blockConvention(){{$}}
343+
// BLOCK-CONVENTION-CALL-NEXT: {{^}}print("blockConvention")
344+
345+
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=C-CONVENTION-CALL %s
346+
cConvention {
347+
print("cConvention")
348+
}
349+
// C-CONVENTION-CALL: await cConvention(){{$}}
350+
// C-CONVENTION-CALL-NEXT: {{^}}print("cConvention")
329351
}
330352
// CONVERT-FUNC: {{^}}}

0 commit comments

Comments
 (0)