Skip to content

Commit efb05b0

Browse files
authored
Merge pull request #1902 from ahoppen/ahoppen/children-of-collections
Add `Children` section to `SyntaxCollection` nodes
2 parents b46348a + 9a5ff8d commit efb05b0

File tree

13 files changed

+217
-401
lines changed

13 files changed

+217
-401
lines changed

CodeGeneration/Sources/SyntaxSupport/Node.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,4 +270,21 @@ public struct CollectionNode {
270270
return choices
271271
}
272272
}
273+
274+
public var grammar: SwiftSyntax.Trivia {
275+
let grammar: String
276+
if let onlyElement = elementChoices.only {
277+
grammar = "``\(onlyElement.syntaxType)`` `*`"
278+
} else {
279+
grammar = "(\(elementChoices.map { "``\($0.syntaxType)``" }.joined(separator: " | "))) `*`"
280+
}
281+
282+
return docCommentTrivia(
283+
from: """
284+
### Children
285+
286+
\(grammar)
287+
"""
288+
)
289+
}
273290
}

CodeGeneration/Sources/SyntaxSupport/Utils.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,14 @@ public func docCommentTrivia(from string: String?) -> SwiftSyntax.Trivia {
5454
}
5555
return SwiftSyntax.Trivia(pieces: pieces)
5656
}
57+
58+
public extension Collection {
59+
/// If the collection contains a single element, return it, otherwise `nil`.
60+
var only: Element? {
61+
if !isEmpty && index(after: startIndex) == endIndex {
62+
return self.first!
63+
} else {
64+
return nil
65+
}
66+
}
67+
}

CodeGeneration/Sources/Utils/Utils.swift

Lines changed: 15 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,39 +10,21 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
/// Trims leading and trailing whitespace from each line.
14-
public func dedented<Lines: Sequence>(lines: Lines) -> [String] where Lines.Element: StringProtocol {
15-
lines.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
16-
}
17-
18-
/// Trims leading and trailing whitespace from each line.
19-
public func dedented(string: String) -> String {
20-
dedented(lines: string.split(separator: "\n"))
21-
.joined(separator: "\n")
22-
}
23-
24-
/// Creates a single-line documentation string from indented
25-
/// documentation as written in `CodeGeneration`.
26-
public func flattened(indentedDocumentation: String) -> String {
27-
dedented(string: indentedDocumentation)
28-
.replacingOccurrences(of: "\n", with: "")
29-
.trimmingCharacters(in: .whitespacesAndNewlines)
30-
}
31-
32-
/// Removes all empty lines from a multi-line string.
33-
public func removedEmptyLines(string: String) -> String {
34-
string.split(whereSeparator: \.isNewline)
35-
.filter { !$0.allSatisfy(\.isWhitespace) }
36-
.joined(separator: "\n")
37-
}
13+
extension String {
14+
/// Creates a single-line documentation string from indented
15+
/// documentation as written in `CodeGeneration`.
16+
public var flattened: String {
17+
self
18+
.replacingOccurrences(of: "\n", with: "")
19+
.trimmingCharacters(in: .whitespacesAndNewlines)
20+
}
3821

39-
public extension Collection {
40-
/// If the collection contains a single element, return it, otherwise `nil`.
41-
var only: Element? {
42-
if !isEmpty && index(after: startIndex) == endIndex {
43-
return self.first!
44-
} else {
45-
return nil
46-
}
22+
/// Removes all empty lines from a multi-line string.
23+
public var removingEmptyLines: String {
24+
return
25+
self
26+
.split(whereSeparator: \.isNewline)
27+
.filter { !$0.allSatisfy(\.isWhitespace) }
28+
.joined(separator: "\n")
4729
}
4830
}

CodeGeneration/Sources/generate-swiftsyntax/LayoutNode+Extensions.swift

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,14 @@ extension LayoutNode {
8686
return " - \(child.varName): \(firstLine)"
8787
}
8888

89-
let formattedParams = removedEmptyLines(
90-
string: """
91-
- Parameters:
92-
- leadingTrivia: Trivia to be prepended to the leading trivia of the node’s first token. \
93-
If the node is empty, there is no token to attach the trivia to and the parameter is ignored.
94-
\(children.compactMap(generateParamDocComment).joined(separator: "\n"))
95-
- trailingTrivia: Trivia to be appended to the trailing trivia of the node’s last token. \
96-
If the node is empty, there is no token to attach the trivia to and the parameter is ignored.
97-
"""
98-
)
89+
let formattedParams = """
90+
- Parameters:
91+
- leadingTrivia: Trivia to be prepended to the leading trivia of the node’s first token. \
92+
If the node is empty, there is no token to attach the trivia to and the parameter is ignored.
93+
\(children.compactMap(generateParamDocComment).joined(separator: "\n"))
94+
- trailingTrivia: Trivia to be appended to the trailing trivia of the node’s last token. \
95+
If the node is empty, there is no token to attach the trivia to and the parameter is ignored.
96+
""".removingEmptyLines
9997

10098
return docCommentTrivia(from: formattedParams)
10199
}

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntax/SyntaxCollectionsFile.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,16 @@ import Utils
1717

1818
let syntaxCollectionsFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
1919
for node in SYNTAX_NODES.compactMap(\.collectionNode) {
20+
let documentation = """
21+
\(node.documentation)
22+
\(node.documentation.isEmpty ? "" : "///")
23+
\(node.grammar)
24+
""".removingEmptyLines
25+
2026
try! StructDeclSyntax(
2127
"""
22-
\(raw: node.documentation)
23-
public struct \(raw: node.kind.syntaxType): SyntaxCollection, SyntaxHashable
28+
\(raw: documentation)
29+
public struct \(node.kind.syntaxType): SyntaxCollection, SyntaxHashable
2430
"""
2531
) {
2632
if let onlyElement = node.elementChoices.only {

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntax/SyntaxNodesFile.swift

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ extension Child {
2020
guard let description = documentation else {
2121
return []
2222
}
23-
let dedented = dedented(string: description)
24-
let lines = dedented.split(separator: "\n", omittingEmptySubsequences: false)
23+
let lines = description.split(separator: "\n", omittingEmptySubsequences: false)
2524
let pieces = lines.map { SwiftSyntax.TriviaPiece.docLineComment("/// \($0)") }
2625
return Trivia(pieces: pieces)
2726
}
@@ -34,14 +33,18 @@ extension Child {
3433
func syntaxNode(emitKind: SyntaxNodeKind) -> SourceFileSyntax {
3534
SourceFileSyntax(leadingTrivia: copyrightHeader) {
3635
for node in SYNTAX_NODES.compactMap(\.layoutNode) where node.base == emitKind {
36+
let documentation = """
37+
\(node.documentation)
38+
\(node.documentation.isEmpty ? "" : "///")
39+
\(node.grammar)
40+
""".removingEmptyLines
41+
3742
// We are actually handling this node now
3843
try! StructDeclSyntax(
3944
"""
4045
// MARK: - \(raw: node.kind.syntaxType)
4146
42-
\(raw: node.documentation)
43-
\(raw: node.documentation.isEmpty ? "" : "///")
44-
\(raw: node.grammar)
47+
\(raw: documentation)
4548
public struct \(raw: node.kind.syntaxType): \(raw: node.baseType.syntaxBaseName)Protocol, SyntaxHashable
4649
"""
4750
) {

0 commit comments

Comments
 (0)