Skip to content

Commit 23d2072

Browse files
committed
Improve implementation of BasicFormat (yet again)
This re-writes the implementation of BasicFormat once again to better handle user-indented code. Co-Authored-By: Ben Barham<[email protected]>
1 parent 011d9c1 commit 23d2072

27 files changed

+1148
-678
lines changed

CodeGeneration/Sources/SyntaxSupport/Trivia.swift

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ public class Trivia {
1515
public let comment: String
1616
public let characters: [Character]
1717
public let swiftCharacters: [Character]
18-
public let isNewLine: Bool
1918
public let isComment: Bool
2019

2120
public var lowerName: String { lowercaseFirstWord(name: name) }
@@ -36,17 +35,23 @@ public class Trivia {
3635

3736
public var isCollection: Bool { charactersLen > 0 }
3837

38+
public var isBlank: Bool {
39+
characters.contains { $0.isWhitespace }
40+
}
41+
42+
public var isNewLine: Bool {
43+
characters.contains { $0.isNewline }
44+
}
45+
3946
init(
4047
name: String,
4148
comment: String,
4249
characters: [Character] = [],
4350
swiftCharacters: [Character] = [],
44-
isNewLine: Bool = false,
4551
isComment: Bool = false
4652
) {
4753
self.name = name
4854
self.comment = comment
49-
self.isNewLine = isNewLine
5055
self.isComment = isComment
5156
self.characters = characters
5257

@@ -86,8 +91,7 @@ public let TRIVIAS: [Trivia] = [
8691
],
8792
swiftCharacters: [
8893
Character("\r")
89-
],
90-
isNewLine: true
94+
]
9195
),
9296

9397
Trivia(
@@ -100,8 +104,7 @@ public let TRIVIAS: [Trivia] = [
100104
swiftCharacters: [
101105
Character("\r"),
102106
Character("\n"),
103-
],
104-
isNewLine: true
107+
]
105108
),
106109

107110
Trivia(
@@ -142,8 +145,7 @@ public let TRIVIAS: [Trivia] = [
142145
],
143146
swiftCharacters: [
144147
Character("\n")
145-
],
146-
isNewLine: true
148+
]
147149
),
148150

149151
Trivia(

CodeGeneration/Sources/generate-swiftsyntax/GenerateSwiftSyntax.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ struct GenerateSwiftSyntax: ParsableCommand {
8080
let fileSpecs: [GeneratedFileSpec] =
8181
[
8282
// SwiftBasicFormat
83-
GeneratedFileSpec(swiftBasicFormatGeneratedDir + ["BasicFormat.swift"], basicFormatFile),
83+
GeneratedFileSpec(swiftBasicFormatGeneratedDir + ["BasicFormat+Extensions.swift"], basicFormatExtensionsFile),
8484

8585
// IDEUtils
8686
GeneratedFileSpec(ideUtilsGeneratedDir + ["SyntaxClassification.swift"], syntaxClassificationFile),
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import SwiftSyntax
14+
import SwiftSyntaxBuilder
15+
import SyntaxSupport
16+
import Utils
17+
18+
extension Child {
19+
var requiresLeadingSpace: Bool? {
20+
switch self.kind {
21+
case .token(_, let requiresLeadingSpace, _):
22+
return requiresLeadingSpace
23+
case .nodeChoices(let choices):
24+
for choice in choices {
25+
if let requiresLeadingSpace = choice.requiresLeadingSpace {
26+
return requiresLeadingSpace
27+
}
28+
}
29+
default:
30+
break
31+
}
32+
return nil
33+
}
34+
35+
var requiresTrailingSpace: Bool? {
36+
switch self.kind {
37+
case .token(choices: _, _, let requiresTrailingSpace):
38+
return requiresTrailingSpace
39+
case .nodeChoices(let choices):
40+
for choice in choices {
41+
if let requiresTrailingSpace = choice.requiresTrailingSpace {
42+
return requiresTrailingSpace
43+
}
44+
}
45+
default:
46+
break
47+
}
48+
return nil
49+
}
50+
}
51+
52+
let basicFormatExtensionsFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
53+
DeclSyntax("import SwiftSyntax")
54+
55+
try! ExtensionDeclSyntax("public extension SyntaxProtocol") {
56+
DeclSyntax(
57+
"""
58+
var requiresIndent: Bool {
59+
guard let keyPath = keyPathInParent else {
60+
return false
61+
}
62+
return keyPath.requiresIndent
63+
}
64+
"""
65+
)
66+
}
67+
68+
try! ExtensionDeclSyntax("public extension TokenSyntax") {
69+
DeclSyntax(
70+
"""
71+
var requiresLeadingNewline: Bool {
72+
if let keyPath = keyPathInParent, keyPath.requiresLeadingNewline {
73+
return true
74+
}
75+
return false
76+
}
77+
"""
78+
)
79+
80+
try VariableDeclSyntax("var requiresLeadingSpace: Bool") {
81+
StmtSyntax(
82+
"""
83+
if let keyPath = keyPathInParent, let requiresLeadingSpace = keyPath.requiresLeadingSpace {
84+
return requiresLeadingSpace
85+
}
86+
"""
87+
)
88+
89+
try SwitchExprSyntax("switch tokenKind") {
90+
for token in SYNTAX_TOKENS {
91+
if token.requiresLeadingSpace {
92+
SwitchCaseSyntax("case .\(raw: token.swiftKind):") {
93+
StmtSyntax("return true")
94+
}
95+
}
96+
}
97+
for keyword in KEYWORDS where keyword.requiresLeadingSpace {
98+
SwitchCaseSyntax("case .keyword(.\(raw: keyword.escapedName)):") {
99+
StmtSyntax("return true")
100+
}
101+
}
102+
SwitchCaseSyntax("default:") {
103+
StmtSyntax("return false")
104+
}
105+
}
106+
}
107+
108+
try VariableDeclSyntax("var requiresTrailingSpace: Bool") {
109+
StmtSyntax(
110+
"""
111+
if let keyPath = keyPathInParent, let requiresTrailingSpace = keyPath.requiresTrailingSpace {
112+
return requiresTrailingSpace
113+
}
114+
"""
115+
)
116+
117+
try SwitchExprSyntax("switch tokenKind") {
118+
for token in SYNTAX_TOKENS {
119+
if token.requiresTrailingSpace {
120+
SwitchCaseSyntax("case .\(raw: token.swiftKind):") {
121+
StmtSyntax("return true")
122+
}
123+
}
124+
}
125+
for keyword in KEYWORDS where keyword.requiresTrailingSpace {
126+
SwitchCaseSyntax("case .keyword(.\(raw: keyword.escapedName)):") {
127+
StmtSyntax("return true")
128+
}
129+
}
130+
SwitchCaseSyntax("default:") {
131+
StmtSyntax("return false")
132+
}
133+
}
134+
}
135+
}
136+
137+
try! ExtensionDeclSyntax("fileprivate extension AnyKeyPath") {
138+
try VariableDeclSyntax("var requiresIndent: Bool") {
139+
try SwitchExprSyntax("switch self") {
140+
for node in SYNTAX_NODES where !node.isBase {
141+
for child in node.children where child.isIndented {
142+
SwitchCaseSyntax("case \\\(raw: node.type.syntaxBaseName).\(raw: child.swiftName):") {
143+
StmtSyntax("return true")
144+
}
145+
}
146+
}
147+
SwitchCaseSyntax("default:") {
148+
StmtSyntax("return false")
149+
}
150+
}
151+
}
152+
153+
try VariableDeclSyntax("var requiresLeadingNewline: Bool") {
154+
try SwitchExprSyntax("switch self") {
155+
for node in SYNTAX_NODES where !node.isBase {
156+
for child in node.children where child.requiresLeadingNewline {
157+
SwitchCaseSyntax("case \\\(raw: node.type.syntaxBaseName).\(raw: child.swiftName):") {
158+
StmtSyntax("return true")
159+
}
160+
}
161+
}
162+
SwitchCaseSyntax("default:") {
163+
StmtSyntax("return false")
164+
}
165+
}
166+
}
167+
168+
try VariableDeclSyntax("var requiresLeadingSpace: Bool?") {
169+
try SwitchExprSyntax("switch self") {
170+
for node in SYNTAX_NODES where !node.isBase {
171+
for child in node.children {
172+
if let requiresLeadingSpace = child.requiresLeadingSpace {
173+
SwitchCaseSyntax("case \\\(raw: node.type.syntaxBaseName).\(raw: child.swiftName):") {
174+
StmtSyntax("return \(literal: requiresLeadingSpace)")
175+
}
176+
}
177+
}
178+
}
179+
SwitchCaseSyntax("default:") {
180+
StmtSyntax("return nil")
181+
}
182+
}
183+
}
184+
185+
try VariableDeclSyntax("var requiresTrailingSpace: Bool?") {
186+
try SwitchExprSyntax("switch self") {
187+
for node in SYNTAX_NODES where !node.isBase {
188+
for child in node.children {
189+
if let requiresTrailingSpace = child.requiresTrailingSpace {
190+
SwitchCaseSyntax("case \\\(raw: node.type.syntaxBaseName).\(raw: child.swiftName):") {
191+
StmtSyntax("return \(literal: requiresTrailingSpace)")
192+
}
193+
}
194+
}
195+
}
196+
SwitchCaseSyntax("default:") {
197+
StmtSyntax("return nil")
198+
}
199+
}
200+
}
201+
}
202+
}

0 commit comments

Comments
 (0)