Skip to content

Commit 5b17c7c

Browse files
committed
Updating tests for @completionHandlerAsync
This patch updates the tests for the @completionHandlerAsync attribute. The main test is broken into three chunks; parsing, typechecking, and the decl assginment phases. For parsing, we verify both happy cases, with an explicitly provided completion handler index and one where it is omitted. We also verify the various ways that parsing can fail, with ill-formed names, missing parens etc.... The typechecking phase verifies that the function the attribute is attached to is not async, that it takes a completion handler, that the completion handler is a function type, is a function that returns Void, is @escaping, and is not @autoclosure. The decl assignment complains about the name not referencing an existing function, and the ambiguous naming of async functions.
1 parent 2b0def5 commit 5b17c7c

4 files changed

+144
-60
lines changed
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
// REQUIRES: concurrency
2+
3+
// RUN: %target-typecheck-verify-swift -enable-experimental-concurrency
4+
5+
// ===================
6+
// Parsing
7+
// ===================
8+
9+
func asyncFunc() async -> Int { }
10+
11+
@completionHandlerAsync("asyncFunc()", completionHandlerIndex: 1)
12+
func goodFunc1(value: String, completionHandler: @escaping (Int) -> Void) {}
13+
14+
@completionHandlerAsync("asyncFunc()")
15+
func goodFunc2(value: String, completionHandler: @escaping (Int) -> Void) {}
16+
17+
// expected-error@+1:24{{expected '(' in 'completionHandlerAsync' attribute}}
18+
@completionHandlerAsync
19+
func func1() {}
20+
21+
// expected-error@+1:25{{argument of 'completionHandlerAsync' attribute must be an identifier or full function name}}
22+
@completionHandlerAsync("not+identifier")
23+
func func2() {}
24+
25+
// expected-error@+1:25{{argument of 'completionHandlerAsync' attribute must be an identifier or full function name}}
26+
@completionHandlerAsync("$dollarname")
27+
func func3() {}
28+
29+
// expected-error@+1:25{{argument of 'completionHandlerAsync' attribute must be an identifier or full function name}}
30+
@completionHandlerAsync("TypePrefix.func")
31+
func func4() {}
32+
33+
// expected-error@+1{{argument of 'completionHandlerAsync' cannot be an interpolated string literal}}
34+
@completionHandlerAsync("interpreted \()")
35+
func func5() {}
36+
37+
@completionHandlerAsync("foo" // expected-error{{expected ')' in 'completionHandlerAsync' attribute}}
38+
func func6() {}
39+
40+
@completionHandlerAsync("foo", completionHandlerIndex: 2 // expected-error@:57{{expected ')' in 'completionHandlerAsync'}}
41+
func func7() {}
42+
43+
// expected-error@+1{{'@completionHandlerAsync' attribute cannot be applied to this declaration}}
44+
@completionHandlerAsync("foo", completionHandlerIndex: 0)
45+
protocol SomeProto {
46+
// expected-error@+1:27{{no corresponding async function named 'protoFunc'}}
47+
@completionHandlerAsync("protoFunc", completionHandlerIndex: 0)
48+
func protoFunc(continuation: @escaping () -> Void)
49+
}
50+
51+
// expected-error@+1{{'@completionHandlerAsync' attribute cannot be applied to this declaration}}
52+
@completionHandlerAsync("foo", completionHandlerIndex: 0)
53+
struct SomeStruct: SomeProto {
54+
// expected-error@+1:27{{no corresponding async function named 'protoFunc'}}
55+
@completionHandlerAsync("protoFunc", completionHandlerIndex: 0)
56+
func protoFunc(continuation: @escaping () -> Void) {}
57+
58+
func structFunc() async { }
59+
60+
@completionHandlerAsync("structFunc", completionHandlerIndex: 0)
61+
func structFunc(continuation: @escaping () -> Void) { }
62+
63+
static func staticStructFunc() async { }
64+
65+
@completionHandlerAsync("staticStructFunc", completionHandlerIndex: 0)
66+
static func staticStructFunc(completionHandler: @escaping () -> Void) { }
67+
}
68+
69+
// expected-error@+1 {{'@completionHandlerAsync' attribute cannot be applied to this declaration}}
70+
@completionHandlerAsync("foo", completionHandlerIndex: 0)
71+
class SomeClass: SomeProto {
72+
// expected-error@+1:27{{no corresponding async function named 'protoFunc'}}
73+
@completionHandlerAsync("protoFunc", completionHandlerIndex: 0)
74+
func protoFunc(continuation: @escaping () -> Void) { }
75+
76+
func classFunc() async { }
77+
78+
@completionHandlerAsync("classFunc", completionHandlerIndex: 0)
79+
func classFunc(completionHandler: @escaping () -> Void) { }
80+
}
81+
82+
// ===================
83+
// Typechecking
84+
// ===================
85+
86+
// expected-error@+1:2{{'@completionHandlerAsync' should be attached to a non-async completion-handler function}}
87+
@completionHandlerAsync("asyncFunc")
88+
func typecheckFunc1() async {} // expected-note@:23{{function declared async}}
89+
90+
// expected-error@+1:2{{'@completionHandlerAsync' should be attached to a non-async completion-handler function}}
91+
@completionHandlerAsync("betterFunc")
92+
func typecheckFunc2() {}
93+
94+
// expected-error@+2:2{{'@completionHandlerAsync' should be attached to a non-async completion-handler function}}
95+
// expected-note@+2:55{{'String' is not a function type}}
96+
@completionHandlerAsync("foo", completionHandlerIndex: 1)
97+
func typecheckFunc3(value: String, completionHandler: String) {}
98+
99+
// expected-error@+2:2{{'@completionHandlerAsync' should be attached to a non-async completion-handler function}}
100+
// expected-note@+2:55{{'String' is not a function type}}
101+
@completionHandlerAsync("foo")
102+
func typecheckFunc4(value: String, completionHandler: String) {}
103+
104+
// expected-error@+2:2{{'@completionHandlerAsync' should be attached to a non-async completion-handler function}}
105+
// expected-note@+2:33{{completion handler must return 'Void'}}
106+
@completionHandlerAsync("betterFunc(param:)")
107+
func typecheckFunc5(value: Int, completionHandler: @escaping (Int) -> Int) {}
108+
109+
// expected-error@+1:56{{completion handler index out of range of the function parameters}}
110+
@completionHandlerAsync("foo", completionHandlerIndex: 2)
111+
func typecheckFunc6(value: Int) { }
112+
113+
// expected-error@+3:2{{'@completionHandlerAsync' should be attached to a non-async completion-handler function}}
114+
// expected-note@+3:21{{completion handler must return 'Void'}}
115+
// expected-note@+2:21{{completion handler must be '@escaping'}}
116+
@completionHandlerAsync("foo", completionHandlerIndex: 0)
117+
func typecheckFunc7(handler: () -> Int) {}
118+
119+
// expected-error@+3:2{{'@completionHandlerAsync' should be attached to a non-async completion-handler function}}
120+
// expected-note@+3:21{{completion handler must be '@escaping'}}
121+
// expected-note@+2:30{{completion handler must not be '@autoclosure'}}
122+
@completionHandlerAsync("foo")
123+
func typecheckFunc8(handler: @autoclosure () -> ()) {}
124+
125+
// ===================
126+
// Decl assignment
127+
// ===================
128+
129+
// expected-error@+1:25{{no corresponding async function named 'functionThatDoesntExist'}}
130+
@completionHandlerAsync("functionThatDoesntExist(_:)")
131+
func typecheckFunc8(handler: @escaping () -> Void) {}
132+
133+
// These two have the same decl name, so they are ambiguous
134+
func matchingAsyncFunc(value: Int) async {} // expected-note{{'matchingAsyncFunc(value:)' declared here}}
135+
func matchingAsyncFunc(value: String) async {} // expected-note{{'matchingAsyncFunc(value:)' declared here}}
136+
137+
// expected-error@+1:25{{ambiguous '@completionHandlerAsync' async function 'matchingAsyncFunc(value:)'}}
138+
@completionHandlerAsync("matchingAsyncFunc(value:)")
139+
func typecheckFunc9(handler: @escaping () -> Void) {}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
// expected-error@+1{{'completionHandlerAsync' attribute is only valid when experimental concurrency is enabled}}
4+
@completionHandlerAsync("foobar", completionHandlerIndex: 1)
5+
func func2() {}

test/attr/attr_hasasyncalternative.swift

Lines changed: 0 additions & 56 deletions
This file was deleted.

test/attr/attr_hasasyncalternative_conc_disabled.swift

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)