Skip to content

Commit 022841c

Browse files
authored
Merge pull request #622 from allevato/5.9-features
Add support for various new 5.9 features.
2 parents 9362431 + 57c612b commit 022841c

9 files changed

+161
-5
lines changed

Sources/SwiftFormat/Core/ModifierListSyntax+Convenience.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ extension DeclModifierListSyntax {
1717
var accessLevelModifier: DeclModifierSyntax? {
1818
for modifier in self {
1919
switch modifier.name.tokenKind {
20-
case .keyword(.public), .keyword(.private), .keyword(.fileprivate), .keyword(.internal):
20+
case .keyword(.public), .keyword(.private), .keyword(.fileprivate), .keyword(.internal),
21+
.keyword(.package):
2122
return modifier
2223
default:
2324
continue

Sources/SwiftFormat/PrettyPrint/TokenStreamCreator.swift

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2293,6 +2293,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
22932293

22942294
override func visit(_ node: GenericParameterSyntax) -> SyntaxVisitorContinueKind {
22952295
before(node.firstToken(viewMode: .sourceAccurate), tokens: .open)
2296+
after(node.eachKeyword, tokens: .break)
22962297
after(node.colon, tokens: .break)
22972298
if let trailingComma = node.trailingComma {
22982299
after(trailingComma, tokens: .close, .break(.same))
@@ -2312,6 +2313,28 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
23122313
return .visitChildren
23132314
}
23142315

2316+
override func visit(_ node: PackElementExprSyntax) -> SyntaxVisitorContinueKind {
2317+
// `each` cannot be separated from the following token, or it is parsed as an identifier itself.
2318+
after(node.eachKeyword, tokens: .space)
2319+
return .visitChildren
2320+
}
2321+
2322+
override func visit(_ node: PackElementTypeSyntax) -> SyntaxVisitorContinueKind {
2323+
// `each` cannot be separated from the following token, or it is parsed as an identifier itself.
2324+
after(node.eachKeyword, tokens: .space)
2325+
return .visitChildren
2326+
}
2327+
2328+
override func visit(_ node: PackExpansionExprSyntax) -> SyntaxVisitorContinueKind {
2329+
after(node.repeatKeyword, tokens: .break)
2330+
return .visitChildren
2331+
}
2332+
2333+
override func visit(_ node: PackExpansionTypeSyntax) -> SyntaxVisitorContinueKind {
2334+
after(node.repeatKeyword, tokens: .break)
2335+
return .visitChildren
2336+
}
2337+
23152338
override func visit(_ node: ExpressionPatternSyntax) -> SyntaxVisitorContinueKind {
23162339
return .visitChildren
23172340
}
@@ -2481,6 +2504,27 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
24812504
return .visitChildren
24822505
}
24832506

2507+
override func visit(_ node: ConsumeExprSyntax) -> SyntaxVisitorContinueKind {
2508+
// The `consume` keyword cannot be separated from the following token or it will be parsed as
2509+
// an identifier.
2510+
after(node.consumeKeyword, tokens: .space)
2511+
return .visitChildren
2512+
}
2513+
2514+
override func visit(_ node: CopyExprSyntax) -> SyntaxVisitorContinueKind {
2515+
// The `copy` keyword cannot be separated from the following token or it will be parsed as an
2516+
// identifier.
2517+
after(node.copyKeyword, tokens: .space)
2518+
return .visitChildren
2519+
}
2520+
2521+
override func visit(_ node: DiscardStmtSyntax) -> SyntaxVisitorContinueKind {
2522+
// The `discard` keyword cannot be separated from the following token or it will be parsed as
2523+
// an identifier.
2524+
after(node.discardKeyword, tokens: .space)
2525+
return .visitChildren
2526+
}
2527+
24842528
override func visit(_ node: InheritanceClauseSyntax) -> SyntaxVisitorContinueKind {
24852529
// Normally, the open-break is placed before the open token. In this case, it's intentionally
24862530
// ordered differently so that the inheritance list can start on the current line and only

Sources/SwiftFormat/Rules/AlwaysUseLiteralForEmptyCollectionInit.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,7 @@ public final class AlwaysUseLiteralForEmptyCollectionInit : SyntaxFormatRule {
166166
}
167167

168168
private func getLiteralType(_ arrayLiteral: ArrayExprSyntax) -> TypeSyntax? {
169-
guard let elementExpr = arrayLiteral.elements.firstAndOnly,
170-
elementExpr.is(ArrayElementSyntax.self) else {
169+
guard arrayLiteral.elements.count == 1 else {
171170
return nil
172171
}
173172

Sources/SwiftFormat/Rules/NoAccessLevelOnExtensionDeclaration.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ public final class NoAccessLevelOnExtensionDeclaration: SyntaxFormatRule {
3232
var result = node
3333

3434
switch keyword {
35-
// Public, private, or fileprivate keywords need to be moved to members
36-
case .public, .private, .fileprivate:
35+
// Public, private, fileprivate, or package keywords need to be moved to members
36+
case .public, .private, .fileprivate, .package:
3737
// The effective access level of the members of a `private` extension is `fileprivate`, so
3838
// we have to update the keyword to ensure that the result is correct.
3939
var accessKeywordToAdd = accessKeyword
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
final class ConsumeExprTests: PrettyPrintTestCase {
2+
func testConsume() {
3+
assertPrettyPrintEqual(
4+
input: """
5+
let x = consume y
6+
""",
7+
expected: """
8+
let x =
9+
consume y
10+
11+
""",
12+
linelength: 16)
13+
}
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
final class CopyExprTests: PrettyPrintTestCase {
2+
func testCopy() {
3+
assertPrettyPrintEqual(
4+
input: """
5+
let x = copy y
6+
""",
7+
expected: """
8+
let x =
9+
copy y
10+
11+
""",
12+
linelength: 13)
13+
}
14+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
final class DiscardStmtTests: PrettyPrintTestCase {
2+
func testDiscard() {
3+
assertPrettyPrintEqual(
4+
input: """
5+
discard self
6+
""",
7+
expected: """
8+
discard self
9+
10+
""",
11+
linelength: 9)
12+
}
13+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
final class ParameterPackTests: PrettyPrintTestCase {
2+
func testGenericPackArgument() {
3+
assertPrettyPrintEqual(
4+
input: """
5+
func someFunction<each P>() {}
6+
struct SomeStruct<each P> {}
7+
""",
8+
expected: """
9+
func someFunction<
10+
each P
11+
>() {}
12+
struct SomeStruct<
13+
each P
14+
> {}
15+
16+
""",
17+
linelength: 22)
18+
}
19+
20+
func testPackExpansionsAndElements() {
21+
assertPrettyPrintEqual(
22+
input: """
23+
repeat checkNilness(of: each value)
24+
""",
25+
expected: """
26+
repeat checkNilness(
27+
of: each value)
28+
29+
""",
30+
linelength: 25)
31+
32+
assertPrettyPrintEqual(
33+
input: """
34+
repeat f(of: each v)
35+
""",
36+
expected: """
37+
repeat
38+
f(
39+
of:
40+
each v
41+
)
42+
43+
""",
44+
linelength: 7)
45+
}
46+
}

Tests/SwiftFormatTests/Rules/NoAccessLevelOnExtensionDeclarationTests.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,31 @@ final class NoAccessLevelOnExtensionDeclarationTests: LintOrFormatRuleTestCase {
128128
)
129129
}
130130

131+
func testPackageAccessLevel() {
132+
assertFormatting(
133+
NoAccessLevelOnExtensionDeclaration.self,
134+
input: """
135+
1️⃣package extension Foo {
136+
2️⃣func f() {}
137+
}
138+
""",
139+
expected: """
140+
extension Foo {
141+
package func f() {}
142+
}
143+
""",
144+
findings: [
145+
FindingSpec(
146+
"1️⃣",
147+
message: "move this 'package' access modifier to precede each member inside this extension",
148+
notes: [
149+
NoteSpec("2️⃣", message: "add 'package' access modifier to this declaration"),
150+
]
151+
),
152+
]
153+
)
154+
}
155+
131156
func testPrivateIsEffectivelyFileprivate() {
132157
assertFormatting(
133158
NoAccessLevelOnExtensionDeclaration.self,

0 commit comments

Comments
 (0)