Skip to content

Commit 8e12022

Browse files
committed
[NFC-ish] Factor out InitSignature
Introduce and factor out a type that represents a list of children for which an initializer ought to exist. This changes some `@available(renamed:)` values, but nothing that should change diagnostics or behavior.
1 parent d145cb2 commit 8e12022

File tree

7 files changed

+263
-193
lines changed

7 files changed

+263
-193
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 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+
/// Represents an initializer that should be generated.
14+
public struct InitSignature {
15+
/// The list of children which shoudl be given parameters and initialized by the initializer.
16+
public var children: [Child]
17+
18+
/// Create an initializer with an arbitrary array of children.
19+
public init(children: [Child]) {
20+
self.children = children
21+
}
22+
23+
/// Create an initializer for the (non-deprecated) children of a given layout node.
24+
public init(_ layoutNode: LayoutNode) {
25+
self.init(children: layoutNode.children)
26+
}
27+
28+
/// Create an initializer for the (non-deprecated) children of a given trait.
29+
public init(_ trait: Trait) {
30+
self.init(children: trait.children)
31+
}
32+
}
33+

CodeGeneration/Sources/generate-swift-syntax/LayoutNode+Extensions.swift renamed to CodeGeneration/Sources/generate-swift-syntax/InitSignature+Extensions.swift

+41-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,19 @@ import SwiftSyntaxBuilder
1515
import SyntaxSupport
1616
import Utils
1717

18-
extension LayoutNode {
18+
extension InitSignature {
19+
var compoundName: String {
20+
let renamedArguments = children.map { child in
21+
if child.isUnexpectedNodes {
22+
return "_:"
23+
} else {
24+
return "\(child.labelDeclName):"
25+
}
26+
}.joined(separator: "")
27+
28+
return "init(leadingTrivia:\(renamedArguments)trailingTrivia:)"
29+
}
30+
1931
func generateInitializerDeclHeader(useDeprecatedChildName: Bool = false) -> SyntaxNodeString {
2032
if children.isEmpty {
2133
return "public init()"
@@ -210,3 +222,31 @@ fileprivate func convertFromSyntaxProtocolToSyntaxType(
210222
}
211223
return ExprSyntax("\(childName.declNameOrVarCallName)")
212224
}
225+
226+
extension InitSignature {
227+
/// Generates arguments to pass this initializer's parameters through to the
228+
/// non-deprecated initializer. This will generate nested initializer calls for
229+
/// any children with a compound `newerChildPath`.
230+
func makeArgumentsToInitializeNewestChildren() -> [LabeledExprSyntax] {
231+
return children.map { child in
232+
let deprecatedName: TokenSyntax
233+
234+
if let deprecatedVarName = child.deprecatedVarName {
235+
deprecatedName = deprecatedVarName
236+
} else {
237+
deprecatedName = child.varDeclName
238+
}
239+
240+
let argValue = ExprSyntax(DeclReferenceExprSyntax(baseName: deprecatedName))
241+
242+
if child.isUnexpectedNodes {
243+
return LabeledExprSyntax(expression: argValue)
244+
}
245+
return LabeledExprSyntax(
246+
label: child.labelDeclName,
247+
colon: .colonToken(),
248+
expression: argValue
249+
)
250+
}
251+
}
252+
}

CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntax/RenamedChildrenCompatibilityFile.swift

+67-72
Original file line numberDiff line numberDiff line change
@@ -20,86 +20,81 @@ let renamedChildrenCompatibilityFile = try! SourceFileSyntax(leadingTrivia: copy
2020
try ExtensionDeclSyntax("extension \(layoutNode.type.syntaxBaseName)") {
2121
for child in layoutNode.children {
2222
if let deprecatedVarName = child.deprecatedVarName {
23-
let childType: TypeSyntax =
24-
child.kind.isNodeChoicesEmpty ? child.syntaxNodeKind.syntaxType : child.syntaxChoicesType
25-
let type = child.isOptional ? TypeSyntax("\(childType)?") : childType
26-
27-
DeclSyntax(
28-
"""
29-
@available(*, deprecated, renamed: "\(child.identifier)")
30-
public var \(deprecatedVarName): \(type) {
31-
get {
32-
return \(child.baseCallName)
33-
}
34-
set {
35-
\(child.baseCallName) = newValue
36-
}
37-
}
38-
"""
39-
)
40-
if let childNode = SYNTAX_NODE_MAP[child.syntaxNodeKind]?.collectionNode,
41-
!child.isUnexpectedNodes,
42-
case .collection(
43-
kind: _,
44-
collectionElementName: let collectionElementName,
45-
defaultsToEmpty: _,
46-
deprecatedCollectionElementName: let deprecatedCollectionElementName
47-
) = child.kind,
48-
let deprecatedCollectionElementName
49-
{
50-
let childEltType = childNode.collectionElementType.syntaxBaseName
51-
52-
DeclSyntax(
53-
"""
54-
@available(*, deprecated, renamed: "add\(raw: collectionElementName)")
55-
public func add\(raw: deprecatedCollectionElementName)(_ element: \(childEltType)) -> \(layoutNode.kind.syntaxType) {
56-
return add\(raw: collectionElementName)(element)
57-
}
58-
"""
59-
)
23+
makeCompatibilityVar(for: child, deprecatedVarName: deprecatedVarName)
24+
if let addMethod = makeCompatibilityAddMethod(for: child) {
25+
addMethod
6026
}
6127
}
6228
}
6329

64-
let deprecatedNames = layoutNode.children
65-
.filter { !$0.isUnexpectedNodes && $0.hasDeprecatedName }
66-
.map { $0.identifier.description }
67-
.joined(separator: ", ")
30+
let renamedName = InitSignature(layoutNode).compoundName
31+
makeCompatibilityInit(for: InitSignature(layoutNode), renamedName: renamedName)
32+
}
33+
}
34+
}
35+
36+
func makeCompatibilityVar(for child: Child, deprecatedVarName: TokenSyntax) -> DeclSyntax {
37+
let childType: TypeSyntax =
38+
child.kind.isNodeChoicesEmpty ? child.syntaxNodeKind.syntaxType : child.syntaxChoicesType
39+
let type = child.isOptional ? TypeSyntax("\(childType)?") : childType
6840

69-
let renamedArguments =
70-
layoutNode.children.map { child in
71-
if child.isUnexpectedNodes {
72-
return "_:"
73-
} else {
74-
return "\(child.labelDeclName):"
75-
}
76-
}.joined(separator: "")
41+
return DeclSyntax(
42+
"""
43+
@available(*, deprecated, renamed: "\(child.identifier)")
44+
public var \(deprecatedVarName): \(type) {
45+
get {
46+
return \(child.baseCallName)
47+
}
48+
set {
49+
\(child.baseCallName) = newValue
50+
}
51+
}
52+
"""
53+
)
54+
}
7755

78-
let renamedName = "\(layoutNode.type.syntaxBaseName)(leadingTrivia:\(renamedArguments)trailingTrivia:)"
56+
func makeCompatibilityAddMethod(for child: Child) -> DeclSyntax? {
57+
if let childNode = SYNTAX_NODE_MAP[child.syntaxNodeKind]?.collectionNode,
58+
!child.isUnexpectedNodes,
59+
case .collection(
60+
kind: _,
61+
collectionElementName: let collectionElementName,
62+
defaultsToEmpty: _,
63+
deprecatedCollectionElementName: let deprecatedCollectionElementName
64+
) = child.kind,
65+
let deprecatedCollectionElementName
66+
{
67+
let childEltType = childNode.collectionElementType.syntaxBaseName
7968

80-
try! InitializerDeclSyntax(
81-
"""
82-
@available(*, deprecated, renamed: \(literal: renamedName))
83-
@_disfavoredOverload
84-
\(layoutNode.generateInitializerDeclHeader(useDeprecatedChildName: true))
85-
"""
86-
) {
87-
FunctionCallExprSyntax(callee: ExprSyntax("self.init")) {
88-
LabeledExprSyntax(label: "leadingTrivia", expression: ExprSyntax("leadingTrivia"))
89-
for child in layoutNode.children {
90-
if child.isUnexpectedNodes {
91-
LabeledExprSyntax(expression: ExprSyntax("\(child.deprecatedVarName ?? child.baseCallName)"))
92-
} else {
93-
LabeledExprSyntax(
94-
label: child.labelDeclName,
95-
colon: .colonToken(),
96-
expression: DeclReferenceExprSyntax(baseName: child.deprecatedVarName ?? child.baseCallName)
97-
)
98-
}
99-
}
100-
LabeledExprSyntax(label: "trailingTrivia", expression: ExprSyntax("trailingTrivia"))
101-
}
69+
return DeclSyntax(
70+
"""
71+
@available(*, deprecated, renamed: "add\(raw: collectionElementName)")
72+
public func add\(raw: deprecatedCollectionElementName)(_ element: \(childEltType)) -> Self {
73+
return add\(raw: collectionElementName)(element)
74+
}
75+
"""
76+
)
77+
}
78+
79+
return nil
80+
}
81+
82+
func makeCompatibilityInit(for signature: InitSignature, renamedName: String) -> InitializerDeclSyntax {
83+
try! InitializerDeclSyntax(
84+
"""
85+
@available(*, deprecated, renamed: \(literal: renamedName))
86+
@_disfavoredOverload
87+
\(signature.generateInitializerDeclHeader(useDeprecatedChildName: true))
88+
"""
89+
) {
90+
FunctionCallExprSyntax(callee: ExprSyntax("self.init")) {
91+
LabeledExprSyntax(label: "leadingTrivia", expression: ExprSyntax("leadingTrivia"))
92+
93+
for argExpr in signature.makeArgumentsToInitializeNewestChildren() {
94+
argExpr
10295
}
96+
97+
LabeledExprSyntax(label: "trailingTrivia", expression: ExprSyntax("trailingTrivia"))
10398
}
10499
}
105100
}

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

+4-2
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,12 @@ func syntaxNode(nodesStartingWith: [Character]) -> SourceFileSyntax {
5252
"""
5353
)
5454

55+
let initSignature = InitSignature(node)
56+
5557
try! InitializerDeclSyntax(
5658
"""
57-
\(node.generateInitializerDocComment())\
58-
\(node.generateInitializerDeclHeader())
59+
\(initSignature.generateInitializerDocComment())\
60+
\(initSignature.generateInitializerDeclHeader())
5961
"""
6062
) {
6163
let parameters = ClosureParameterListSyntax {

CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntaxbuilder/BuildableNodesFile.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ let buildableNodesFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
2929
for node in SYNTAX_NODES.compactMap(\.layoutNode) {
3030
let type = node.type
3131

32-
if let convenienceInit = try! node.createConvenienceBuilderInitializer() {
32+
if let convenienceInit = try! InitSignature(node).createConvenienceBuilderInitializer() {
3333
DeclSyntax(
3434
"""
3535
extension \(type.syntaxBaseName) {

CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntaxbuilder/RenamedChildrenBuilderCompatibilityFile.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ let renamedChildrenBuilderCompatibilityFile = try! SourceFileSyntax(leadingTrivi
2727
)
2828

2929
for layoutNode in SYNTAX_NODES.compactMap(\.layoutNode).filter({ $0.children.hasDeprecatedChild }) {
30-
if let convenienceInit = try layoutNode.createConvenienceBuilderInitializer(useDeprecatedChildName: true) {
30+
if let convenienceInit = try InitSignature(layoutNode).createConvenienceBuilderInitializer(useDeprecatedChildName: true) {
3131
let deprecatedNames = layoutNode.children
3232
.filter { !$0.isUnexpectedNodes && $0.hasDeprecatedName }
3333
.compactMap { $0.identifier.description }

0 commit comments

Comments
 (0)