Skip to content

Commit 1bd6086

Browse files
authored
Merge pull request swiftlang#37071 from ahoppen/pr/block-convention-to-async
[Refactoring] Support refactoring to async if callback is `@convention(block)`
2 parents fae8d9a + f17fe86 commit 1bd6086

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
@@ -5004,6 +5004,22 @@ class AsyncConverter : private SourceEntityWalker {
50045004
}
50055005
}
50065006

5007+
/// From the given expression \p E, which is an argument to a function call,
5008+
/// extract the passed closure if there is one. Otherwise return \c nullptr.
5009+
ClosureExpr *extractCallback(Expr *E) {
5010+
if (auto Closure = dyn_cast<ClosureExpr>(E)) {
5011+
return Closure;
5012+
} else if (auto CaptureList = dyn_cast<CaptureListExpr>(E)) {
5013+
return CaptureList->getClosureBody();
5014+
} else if (auto FunctionConversion = dyn_cast<FunctionConversionExpr>(E)) {
5015+
// Closure arguments marked as e.g. `@convention(block)` produce arguments
5016+
// that are `FunctionConversionExpr`.
5017+
return extractCallback(FunctionConversion->getSubExpr());
5018+
} else {
5019+
return nullptr;
5020+
}
5021+
}
5022+
50075023
void addAsyncAlternativeCall(const CallExpr *CE,
50085024
const AsyncHandlerDesc &HandlerDesc) {
50095025
auto ArgList = callArgs(CE);
@@ -5012,11 +5028,7 @@ class AsyncConverter : private SourceEntityWalker {
50125028
return;
50135029
}
50145030

5015-
auto Callback = dyn_cast<ClosureExpr>(ArgList.ref()[HandlerDesc.Index]);
5016-
auto Capture = dyn_cast<CaptureListExpr>(ArgList.ref()[HandlerDesc.Index]);
5017-
if (Capture) {
5018-
Callback = Capture->getClosureBody();
5019-
}
5031+
ClosureExpr *Callback = extractCallback(ArgList.ref()[HandlerDesc.Index]);
50205032
if (!Callback) {
50215033
DiagEngine.diagnose(CE->getStartLoc(), diag::missing_callback_arg);
50225034
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)