Skip to content

Commit 3d9df88

Browse files
authored
Merge pull request swiftlang#183 from google/format-factor-out-types
Fix formatting of empty type declarations.
2 parents 0614daf + 895e5ad commit 3d9df88

File tree

6 files changed

+159
-132
lines changed

6 files changed

+159
-132
lines changed

Sources/SwiftFormatPrettyPrint/TokenStreamCreator.swift

Lines changed: 99 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,105 @@ private final class TokenStreamCreator: SyntaxVisitor {
8585

8686
override func visitPre(_ node: Syntax) {}
8787

88+
// MARK: - Type declaration nodes
89+
90+
override func visit(_ node: ClassDeclSyntax) {
91+
arrangeTypeDeclBlock(
92+
node,
93+
attributes: node.attributes,
94+
typeKeyword: node.classKeyword,
95+
members: node.members,
96+
genericWhereClause: node.genericWhereClause)
97+
super.visit(node)
98+
}
99+
100+
override func visit(_ node: StructDeclSyntax) {
101+
arrangeTypeDeclBlock(
102+
node,
103+
attributes: node.attributes,
104+
typeKeyword: node.structKeyword,
105+
members: node.members,
106+
genericWhereClause: node.genericWhereClause)
107+
super.visit(node)
108+
}
109+
110+
override func visit(_ node: EnumDeclSyntax) {
111+
arrangeTypeDeclBlock(
112+
node,
113+
attributes: node.attributes,
114+
typeKeyword: node.enumKeyword,
115+
members: node.members,
116+
genericWhereClause: node.genericWhereClause)
117+
super.visit(node)
118+
}
119+
120+
override func visit(_ node: ProtocolDeclSyntax) {
121+
arrangeTypeDeclBlock(
122+
node,
123+
attributes: node.attributes,
124+
typeKeyword: node.protocolKeyword,
125+
members: node.members,
126+
genericWhereClause: node.genericWhereClause)
127+
super.visit(node)
128+
}
129+
130+
override func visit(_ node: ExtensionDeclSyntax) {
131+
arrangeTypeDeclBlock(
132+
node,
133+
attributes: node.attributes,
134+
typeKeyword: node.extensionKeyword,
135+
members: node.members,
136+
genericWhereClause: node.genericWhereClause)
137+
super.visit(node)
138+
}
139+
140+
/// Applies formatting tokens to the tokens in the given type declaration node (i.e., a class,
141+
/// struct, enum, protocol, or extension).
142+
private func arrangeTypeDeclBlock(
143+
_ node: Syntax,
144+
attributes: AttributeListSyntax?,
145+
typeKeyword: TokenSyntax,
146+
members: MemberDeclBlockSyntax,
147+
genericWhereClause: GenericWhereClauseSyntax?
148+
) {
149+
// TODO(allevato): If `EnumDeclSyntax` is updated to extend `DeclGroupSyntax` (I can't see a
150+
// reason that it shouldn't), then we can simplify this function's signature by constraining
151+
// `node` to that protocol and removing the explicit `attributes` and `members` arguments.
152+
153+
if let attributes = attributes {
154+
before(node.firstToken, tokens: .space(size: 0), .open(.consistent, 0))
155+
after(attributes.lastToken, tokens: .open)
156+
} else {
157+
before(node.firstToken, tokens: .space(size: 0), .open(.consistent, 0), .open)
158+
}
159+
160+
after(typeKeyword, tokens: .break)
161+
162+
if let genericWhereClause = genericWhereClause {
163+
before(
164+
genericWhereClause.firstToken,
165+
tokens: .break, .open(.inconsistent, 0), .break(size: 0), .open(.consistent, 0)
166+
)
167+
after(genericWhereClause.lastToken, tokens: .break, .close, .close)
168+
} else {
169+
before(members.leftBrace, tokens: .break)
170+
}
171+
172+
if !members.members.isEmpty {
173+
after(
174+
members.leftBrace,
175+
tokens: .close, .close, .break(size: 0, offset: 2), .open(.consistent, 0)
176+
)
177+
before(members.rightBrace, tokens: .break(size: 0, offset: -2), .close)
178+
} else {
179+
// The size-0 break in the empty case allows for a break between the braces in the rare event
180+
// that the declaration would be exactly the column limit + 1.
181+
after(members.leftBrace, tokens: .close, .close, .break(size: 0))
182+
}
183+
}
184+
185+
// TODO: - Other nodes (yet to be organized)
186+
88187
override func visit(_ node: DeclNameArgumentsSyntax) {
89188
super.visit(node)
90189
}
@@ -337,34 +436,6 @@ private final class TokenStreamCreator: SyntaxVisitor {
337436
super.visit(node)
338437
}
339438

340-
override func visit(_ node: EnumDeclSyntax) {
341-
if let attributes = node.attributes {
342-
before(node.firstToken, tokens: .space(size: 0), .open(.consistent, 0))
343-
after(attributes.lastToken, tokens: .open)
344-
} else {
345-
before(node.firstToken, tokens: .space(size: 0), .open(.consistent, 0), .open)
346-
}
347-
348-
after(node.enumKeyword, tokens: .break)
349-
350-
before(
351-
node.genericWhereClause?.firstToken,
352-
tokens: .break, .open(.inconsistent, 0), .break(size: 0), .open(.consistent, 0)
353-
)
354-
after(node.genericWhereClause?.lastToken, tokens: .break, .close, .close)
355-
356-
if node.genericWhereClause == nil {
357-
before(node.members.leftBrace, tokens: .break)
358-
}
359-
after(
360-
node.members.leftBrace,
361-
tokens: .close, .close, .break(size: 0, offset: 2), .open(.consistent, 0)
362-
)
363-
before(node.members.rightBrace, tokens: .break(size: 0, offset: -2), .close)
364-
365-
super.visit(node)
366-
}
367-
368439
override func visit(_ node: EnumCaseDeclSyntax) {
369440
before(node.firstToken, tokens: .open)
370441
after(node.caseKeyword, tokens: .break)
@@ -645,34 +716,6 @@ private final class TokenStreamCreator: SyntaxVisitor {
645716
super.visit(node)
646717
}
647718

648-
override func visit(_ node: ClassDeclSyntax) {
649-
if let attributes = node.attributes {
650-
before(node.firstToken, tokens: .space(size: 0), .open(.consistent, 0))
651-
after(attributes.lastToken, tokens: .open)
652-
} else {
653-
before(node.firstToken, tokens: .space(size: 0), .open(.consistent, 0), .open)
654-
}
655-
656-
after(node.classKeyword, tokens: .break)
657-
658-
before(
659-
node.genericWhereClause?.firstToken,
660-
tokens: .break, .open(.inconsistent, 0), .break(size: 0), .open(.consistent, 0)
661-
)
662-
after(node.genericWhereClause?.lastToken, tokens: .break, .close, .close)
663-
664-
if node.genericWhereClause == nil {
665-
before(node.members.leftBrace, tokens: .break)
666-
}
667-
after(
668-
node.members.leftBrace,
669-
tokens: .close, .close, .break(size: 0, offset: 2), .open(.consistent, 0)
670-
)
671-
before(node.members.rightBrace, tokens: .break(size: 0, offset: -2), .close)
672-
673-
super.visit(node)
674-
}
675-
676719
override func visit(_ node: DeferStmtSyntax) {
677720
after(node.deferKeyword, tokens: .break)
678721
after(node.body.leftBrace, tokens: .break(offset: 2), .open(.consistent, 0))
@@ -755,35 +798,6 @@ private final class TokenStreamCreator: SyntaxVisitor {
755798
super.visit(node)
756799
}
757800

758-
override func visit(_ node: StructDeclSyntax) {
759-
if let attributes = node.attributes {
760-
before(node.firstToken, tokens: .space(size: 0), .open(.consistent, 0))
761-
after(attributes.lastToken, tokens: .open)
762-
} else {
763-
before(node.firstToken, tokens: .space(size: 0), .open(.consistent, 0), .open)
764-
}
765-
766-
after(node.structKeyword, tokens: .break)
767-
768-
before(
769-
node.genericWhereClause?.firstToken,
770-
tokens: .break, .open(.inconsistent, 0), .break(size: 0), .open(.consistent, 0)
771-
)
772-
after(node.genericWhereClause?.lastToken, tokens: .break, .close, .close)
773-
774-
775-
if node.genericWhereClause == nil {
776-
before(node.members.leftBrace, tokens: .break)
777-
}
778-
after(
779-
node.members.leftBrace,
780-
tokens: .close, .close, .break(size: 0, offset: 2), .open(.consistent, 0)
781-
)
782-
before(node.members.rightBrace, tokens: .break(size: 0, offset: -2), .close)
783-
784-
super.visit(node)
785-
}
786-
787801
override func visit(_ node: DotSelfExprSyntax) {
788802
super.visit(node)
789803
}
@@ -955,25 +969,6 @@ private final class TokenStreamCreator: SyntaxVisitor {
955969
super.visit(node)
956970
}
957971

958-
override func visit(_ node: ProtocolDeclSyntax) {
959-
if let attributes = node.attributes {
960-
before(node.firstToken, tokens: .space(size: 0), .open(.consistent, 0))
961-
after(attributes.lastToken, tokens: .open)
962-
} else {
963-
before(node.firstToken, tokens: .space(size: 0), .open(.consistent, 0), .open)
964-
}
965-
966-
after(node.protocolKeyword, tokens: .break)
967-
before(node.members.leftBrace, tokens: .break)
968-
after(
969-
node.members.leftBrace,
970-
tokens: .close, .close, .break(size: 0, offset: 2), .open(.consistent, 0)
971-
)
972-
before(node.members.rightBrace, tokens: .break(size: 0, offset: -2), .close)
973-
974-
super.visit(node)
975-
}
976-
977972
override func visit(_ node: SequenceExprSyntax) {
978973
before(node.firstToken, tokens: .open)
979974
after(node.lastToken, tokens: .close)
@@ -1000,34 +995,6 @@ private final class TokenStreamCreator: SyntaxVisitor {
1000995
super.visit(node)
1001996
}
1002997

1003-
override func visit(_ node: ExtensionDeclSyntax) {
1004-
if let attributes = node.attributes {
1005-
before(node.firstToken, tokens: .space(size: 0), .open(.consistent, 0))
1006-
after(attributes.lastToken, tokens: .open)
1007-
} else {
1008-
before(node.firstToken, tokens: .space(size: 0), .open(.consistent, 0), .open)
1009-
}
1010-
1011-
after(node.extensionKeyword, tokens: .break)
1012-
1013-
before(
1014-
node.genericWhereClause?.firstToken,
1015-
tokens: .break, .open(.inconsistent, 0), .break(size: 0), .open(.consistent, 0)
1016-
)
1017-
after(node.genericWhereClause?.lastToken, tokens: .break, .close, .close)
1018-
1019-
if node.genericWhereClause == nil {
1020-
before(node.members.leftBrace, tokens: .break)
1021-
}
1022-
after(
1023-
node.members.leftBrace,
1024-
tokens: .close, .close, .break(size: 0, offset: 2), .open(.consistent, 0)
1025-
)
1026-
before(node.members.rightBrace, tokens: .break(size: 0, offset: -2), .close)
1027-
1028-
super.visit(node)
1029-
}
1030-
1031998
override func visit(_ node: InheritedTypeSyntax) {
1032999
before(node.firstToken, tokens: .open(.inconsistent, 0))
10331000
if let trailingComma = node.trailingComma {

Tests/SwiftFormatPrettyPrintTests/ClassDeclTests.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,4 +278,16 @@ public class ClassDeclTests: PrettyPrintTestCase {
278278

279279
assertPrettyPrintEqual(input: input, expected: expected, linelength: 50)
280280
}
281+
282+
public func testEmptyClass() {
283+
let input = "class Foo {}"
284+
assertPrettyPrintEqual(input: input, expected: input + "\n", linelength: 50)
285+
286+
let wrapped = """
287+
class Foo {
288+
}
289+
290+
"""
291+
assertPrettyPrintEqual(input: input, expected: wrapped, linelength: 11)
292+
}
281293
}

Tests/SwiftFormatPrettyPrintTests/EnumDeclTests.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,4 +357,16 @@ public class EnumDeclTests: PrettyPrintTestCase {
357357

358358
assertPrettyPrintEqual(input: input, expected: expected, linelength: 50)
359359
}
360+
361+
public func testEmptyEnum() {
362+
let input = "enum Foo {}"
363+
assertPrettyPrintEqual(input: input, expected: input + "\n", linelength: 50)
364+
365+
let wrapped = """
366+
enum Foo {
367+
}
368+
369+
"""
370+
assertPrettyPrintEqual(input: input, expected: wrapped, linelength: 10)
371+
}
360372
}

Tests/SwiftFormatPrettyPrintTests/ExtensionDeclTests.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,4 +233,16 @@ public class ExtensionDeclTests: PrettyPrintTestCase {
233233

234234
assertPrettyPrintEqual(input: input, expected: expected, linelength: 50)
235235
}
236+
237+
public func testEmptyExtension() {
238+
let input = "extension Foo {}"
239+
assertPrettyPrintEqual(input: input, expected: input + "\n", linelength: 50)
240+
241+
let wrapped = """
242+
extension Foo {
243+
}
244+
245+
"""
246+
assertPrettyPrintEqual(input: input, expected: wrapped, linelength: 15)
247+
}
236248
}

Tests/SwiftFormatPrettyPrintTests/ProtocolDeclTests.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,4 +226,16 @@ public class ProtocolDeclTests: PrettyPrintTestCase {
226226

227227
assertPrettyPrintEqual(input: input, expected: expected, linelength: 65)
228228
}
229+
230+
public func testEmptyProtocol() {
231+
let input = "protocol Foo {}"
232+
assertPrettyPrintEqual(input: input, expected: input + "\n", linelength: 50)
233+
234+
let wrapped = """
235+
protocol Foo {
236+
}
237+
238+
"""
239+
assertPrettyPrintEqual(input: input, expected: wrapped, linelength: 14)
240+
}
229241
}

Tests/SwiftFormatPrettyPrintTests/StructDeclTests.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,4 +278,16 @@ public class StructDeclTests: PrettyPrintTestCase {
278278

279279
assertPrettyPrintEqual(input: input, expected: expected, linelength: 50)
280280
}
281+
282+
public func testEmptyStruct() {
283+
let input = "struct Foo {}"
284+
assertPrettyPrintEqual(input: input, expected: input + "\n", linelength: 50)
285+
286+
let wrapped = """
287+
struct Foo {
288+
}
289+
290+
"""
291+
assertPrettyPrintEqual(input: input, expected: wrapped, linelength: 12)
292+
}
281293
}

0 commit comments

Comments
 (0)