Skip to content

Commit 3fd8f49

Browse files
authored
Merge pull request #2278 from Matejkob/modifi-nodes-with-variable-setters
Refactor syntax node manipulation to use variable setters
2 parents 83e12ff + 9a0f0ff commit 3fd8f49

File tree

8 files changed

+84
-105
lines changed

8 files changed

+84
-105
lines changed

Examples/Sources/AddOneToIntegerLiterals/AddOneToIntegerLiterals.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ private class AddOneToIntegerLiterals: SyntaxRewriter {
3131
let int = Int(integerText)!
3232

3333
// Create a new integer literal token with `int + 1` as its text.
34-
let newIntegerLiteralToken = token.with(\.tokenKind, .integerLiteral("\(int + 1)"))
34+
var newIntegerLiteralToken = token
35+
newIntegerLiteralToken.tokenKind = .integerLiteral("\(int + 1)")
3536

3637
// Return the new integer literal.
3738
return newIntegerLiteralToken

Examples/Sources/MacroExamples/Implementation/ComplexMacros/DictionaryIndirectionMacro.swift

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,7 @@ extension DictionaryStorageMacro: MemberMacro {
2121
providingMembersOf declaration: some DeclGroupSyntax,
2222
in context: some MacroExpansionContext
2323
) throws -> [DeclSyntax] {
24-
let storage: DeclSyntax = "var _storage: [String: Any] = [:]"
25-
return [
26-
storage.with(\.leadingTrivia, [.newlines(1), .spaces(2)])
27-
]
24+
return ["\n var _storage: [String: Any] = [:]"]
2825
}
2926
}
3027

@@ -43,11 +40,11 @@ extension DictionaryStorageMacro: MemberAttributeMacro {
4340

4441
return [
4542
AttributeSyntax(
43+
leadingTrivia: [.newlines(1), .spaces(2)],
4644
attributeName: IdentifierTypeSyntax(
4745
name: .identifier("DictionaryStorageProperty")
4846
)
4947
)
50-
.with(\.leadingTrivia, [.newlines(1), .spaces(2)])
5148
]
5249
}
5350
}

Examples/Sources/MacroExamples/Implementation/Expression/AddBlocker.swift

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public struct AddBlocker: ExpressionMacro {
2727
_ node: InfixOperatorExprSyntax
2828
) -> ExprSyntax {
2929
// Identify any infix operator + in the tree.
30-
if let binOp = node.operator.as(BinaryOperatorExprSyntax.self) {
30+
if var binOp = node.operator.as(BinaryOperatorExprSyntax.self) {
3131
if binOp.operator.text == "+" {
3232
// Form the warning
3333
let messageID = MessageID(domain: "silly", id: "addblock")
@@ -72,17 +72,9 @@ public struct AddBlocker: ExpressionMacro {
7272
)
7373
)
7474

75-
return ExprSyntax(
76-
node.with(
77-
\.operator,
78-
ExprSyntax(
79-
binOp.with(
80-
\.operator,
81-
binOp.operator.with(\.tokenKind, .binaryOperator("-"))
82-
)
83-
)
84-
)
85-
)
75+
binOp.operator.tokenKind = .binaryOperator("-")
76+
77+
return ExprSyntax(node.with(\.operator, ExprSyntax(binOp)))
8678
}
8779
}
8880

Examples/Sources/MacroExamples/Implementation/Expression/FontLiteralMacro.swift

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,12 @@ private func replaceFirstLabel(
3535
of tuple: LabeledExprListSyntax,
3636
with newLabel: String
3737
) -> LabeledExprListSyntax {
38-
guard let firstElement = tuple.first else {
38+
if tuple.isEmpty {
3939
return tuple
4040
}
4141

4242
var tuple = tuple
43-
tuple[tuple.startIndex] =
44-
firstElement
45-
.with(\.label, .identifier(newLabel))
46-
.with(\.colon, .colonToken())
43+
tuple[tuple.startIndex].label = .identifier(newLabel)
44+
tuple[tuple.startIndex].colon = .colonToken()
4745
return tuple
4846
}

Examples/Sources/MacroExamples/Implementation/MemberAttribute/WrapStoredPropertiesMacro.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@ public struct WrapStoredPropertiesMacro: MemberAttributeMacro {
4848

4949
return [
5050
AttributeSyntax(
51+
leadingTrivia: [.newlines(1), .spaces(2)],
5152
attributeName: IdentifierTypeSyntax(
5253
name: .identifier(wrapperName.content.text)
5354
)
5455
)
55-
.with(\.leadingTrivia, [.newlines(1), .spaces(2)])
5656
]
5757
}
5858
}

Examples/Sources/MacroExamples/Implementation/Peer/AddAsyncMacro.swift

Lines changed: 37 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public struct AddAsyncMacro: PeerMacro {
3030
) throws -> [DeclSyntax] {
3131

3232
// Only on functions at the moment.
33-
guard let funcDecl = declaration.as(FunctionDeclSyntax.self) else {
33+
guard var funcDecl = declaration.as(FunctionDeclSyntax.self) else {
3434
throw CustomError.message("@addAsync only works on functions")
3535
}
3636

@@ -42,7 +42,7 @@ public struct AddAsyncMacro: PeerMacro {
4242
}
4343

4444
// This only makes sense void functions
45-
if funcDecl.signature.returnClause?.type.with(\.leadingTrivia, []).with(\.trailingTrivia, []).description != "Void" {
45+
if funcDecl.signature.returnClause?.type.as(IdentifierTypeSyntax.self)?.name.text != "Void" {
4646
throw CustomError.message(
4747
"@addAsync requires an function that returns void"
4848
)
@@ -58,7 +58,7 @@ public struct AddAsyncMacro: PeerMacro {
5858
}
5959

6060
// Completion handler needs to return Void
61-
if completionHandlerParameter.returnClause.type.with(\.leadingTrivia, []).with(\.trailingTrivia, []).description != "Void" {
61+
if completionHandlerParameter.returnClause.type.as(IdentifierTypeSyntax.self)?.name.text != "Void" {
6262
throw CustomError.message(
6363
"@addAsync requires an function that has a completion handler that returns Void"
6464
)
@@ -72,9 +72,11 @@ public struct AddAsyncMacro: PeerMacro {
7272
// Remove completionHandler and comma from the previous parameter
7373
var newParameterList = funcDecl.signature.parameterClause.parameters
7474
newParameterList.removeLast()
75-
let newParameterListLastParameter = newParameterList.last!
75+
var newParameterListLastParameter = newParameterList.last!
7676
newParameterList.removeLast()
77-
newParameterList.append(newParameterListLastParameter.with(\.trailingTrivia, []).with(\.trailingComma, nil))
77+
newParameterListLastParameter.trailingTrivia = []
78+
newParameterListLastParameter.trailingComma = nil
79+
newParameterList.append(newParameterListLastParameter)
7880

7981
// Drop the @addAsync attribute from the new declaration.
8082
let newAttributeList = funcDecl.attributes.filter {
@@ -121,42 +123,36 @@ public struct AddAsyncMacro: PeerMacro {
121123
122124
"""
123125

124-
let newFunc =
125-
funcDecl
126-
.with(
127-
\.signature,
128-
funcDecl.signature
129-
.with(
130-
\.effectSpecifiers,
131-
FunctionEffectSpecifiersSyntax(
132-
leadingTrivia: .space,
133-
asyncSpecifier: .keyword(.async),
134-
throwsSpecifier: isResultReturn ? .keyword(.throws) : nil
135-
) // add async
136-
)
137-
.with(
138-
\.returnClause,
139-
successReturnType != nil ? ReturnClauseSyntax(leadingTrivia: .space, type: successReturnType!.with(\.leadingTrivia, .space)) : nil
140-
) // add result type
141-
.with(
142-
\.parameterClause,
143-
funcDecl.signature.parameterClause.with(\.parameters, newParameterList) // drop completion handler
144-
.with(\.trailingTrivia, [])
145-
)
146-
)
147-
.with(
148-
\.body,
149-
CodeBlockSyntax(
150-
leftBrace: .leftBraceToken(leadingTrivia: .space),
151-
statements: CodeBlockItemListSyntax(
152-
[CodeBlockItemSyntax(item: .expr(newBody))]
153-
),
154-
rightBrace: .rightBraceToken(leadingTrivia: .newline)
155-
)
156-
)
157-
.with(\.attributes, newAttributeList)
158-
.with(\.leadingTrivia, .newlines(2))
126+
// add async
127+
funcDecl.signature.effectSpecifiers = FunctionEffectSpecifiersSyntax(
128+
leadingTrivia: .space,
129+
asyncSpecifier: .keyword(.async),
130+
throwsSpecifier: isResultReturn ? .keyword(.throws) : nil
131+
)
132+
133+
// add result type
134+
if let successReturnType {
135+
funcDecl.signature.returnClause = ReturnClauseSyntax(leadingTrivia: .space, type: successReturnType.with(\.leadingTrivia, .space))
136+
} else {
137+
funcDecl.signature.returnClause = nil
138+
}
139+
140+
// drop completion handler
141+
funcDecl.signature.parameterClause.parameters = newParameterList
142+
funcDecl.signature.parameterClause.trailingTrivia = []
143+
144+
funcDecl.body = CodeBlockSyntax(
145+
leftBrace: .leftBraceToken(leadingTrivia: .space),
146+
statements: CodeBlockItemListSyntax(
147+
[CodeBlockItemSyntax(item: .expr(newBody))]
148+
),
149+
rightBrace: .rightBraceToken(leadingTrivia: .newline)
150+
)
151+
152+
funcDecl.attributes = newAttributeList
153+
154+
funcDecl.leadingTrivia = .newlines(2)
159155

160-
return [DeclSyntax(newFunc)]
156+
return [DeclSyntax(funcDecl)]
161157
}
162158
}

Examples/Sources/MacroExamples/Implementation/Peer/AddCompletionHandlerMacro.swift

Lines changed: 34 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,22 @@ public struct AddCompletionHandlerMacro: PeerMacro {
2525
) throws -> [DeclSyntax] {
2626
// Only on functions at the moment. We could handle initializers as well
2727
// with a bit of work.
28-
guard let funcDecl = declaration.as(FunctionDeclSyntax.self) else {
28+
guard var funcDecl = declaration.as(FunctionDeclSyntax.self) else {
2929
throw CustomError.message("@addCompletionHandler only works on functions")
3030
}
3131

3232
// This only makes sense for async functions.
3333
if funcDecl.signature.effectSpecifiers?.asyncSpecifier == nil {
34-
let newEffects: FunctionEffectSpecifiersSyntax
34+
var newEffects: FunctionEffectSpecifiersSyntax
3535
if let existingEffects = funcDecl.signature.effectSpecifiers {
36-
newEffects = existingEffects.with(\.asyncSpecifier, .keyword(.async))
36+
newEffects = existingEffects
37+
newEffects.asyncSpecifier = .keyword(.async)
3738
} else {
3839
newEffects = FunctionEffectSpecifiersSyntax(asyncSpecifier: .keyword(.async))
3940
}
4041

41-
let newSignature = funcDecl.signature.with(\.effectSpecifiers, newEffects)
42+
var newSignature = funcDecl.signature
43+
newSignature.effectSpecifiers = newEffects
4244
let messageID = MessageID(domain: "MacroExamples", id: "MissingAsync")
4345

4446
let diag = Diagnostic(
@@ -73,7 +75,9 @@ public struct AddCompletionHandlerMacro: PeerMacro {
7375
}
7476

7577
// Form the completion handler parameter.
76-
let resultType: TypeSyntax? = funcDecl.signature.returnClause?.type.with(\.leadingTrivia, []).with(\.trailingTrivia, [])
78+
var resultType = funcDecl.signature.returnClause?.type
79+
resultType?.leadingTrivia = []
80+
resultType?.trailingTrivia = []
7781

7882
let completionHandlerParam =
7983
FunctionParameterSyntax(
@@ -85,14 +89,12 @@ public struct AddCompletionHandlerMacro: PeerMacro {
8589
// Add the completion handler parameter to the parameter list.
8690
let parameterList = funcDecl.signature.parameterClause.parameters
8791
var newParameterList = parameterList
88-
if let lastParam = parameterList.last {
92+
if var lastParam = parameterList.last {
8993
// We need to add a trailing comma to the preceding list.
9094
newParameterList.removeLast()
95+
lastParam.trailingComma = .commaToken(trailingTrivia: .space)
9196
newParameterList += [
92-
lastParam.with(
93-
\.trailingComma,
94-
.commaToken(trailingTrivia: .space)
95-
),
97+
lastParam,
9698
completionHandlerParam,
9799
]
98100
} else {
@@ -136,35 +138,28 @@ public struct AddCompletionHandlerMacro: PeerMacro {
136138
return attributeType.name.text != nodeType.name.text
137139
}
138140

139-
let newFunc =
140-
funcDecl
141-
.with(
142-
\.signature,
143-
funcDecl.signature
144-
.with(
145-
\.effectSpecifiers,
146-
funcDecl.signature.effectSpecifiers?.with(\.asyncSpecifier, nil) // drop async
147-
)
148-
.with(\.returnClause, nil) // drop result type
149-
.with(
150-
\.parameterClause, // add completion handler parameter
151-
funcDecl.signature.parameterClause.with(\.parameters, newParameterList)
152-
.with(\.trailingTrivia, [])
153-
)
154-
)
155-
.with(
156-
\.body,
157-
CodeBlockSyntax(
158-
leftBrace: .leftBraceToken(leadingTrivia: .space),
159-
statements: CodeBlockItemListSyntax(
160-
[CodeBlockItemSyntax(item: .expr(newBody))]
161-
),
162-
rightBrace: .rightBraceToken(leadingTrivia: .newline)
163-
)
164-
)
165-
.with(\.attributes, newAttributeList)
166-
.with(\.leadingTrivia, .newlines(2))
141+
// drop async
142+
funcDecl.signature.effectSpecifiers?.asyncSpecifier = nil
143+
144+
// drop result type
145+
funcDecl.signature.returnClause = nil
146+
147+
// add completion handler parameter
148+
funcDecl.signature.parameterClause.parameters = newParameterList
149+
funcDecl.signature.parameterClause.trailingTrivia = []
150+
151+
funcDecl.body = CodeBlockSyntax(
152+
leftBrace: .leftBraceToken(leadingTrivia: .space),
153+
statements: CodeBlockItemListSyntax(
154+
[CodeBlockItemSyntax(item: .expr(newBody))]
155+
),
156+
rightBrace: .rightBraceToken(leadingTrivia: .newline)
157+
)
158+
159+
funcDecl.attributes = newAttributeList
160+
161+
funcDecl.leadingTrivia = .newlines(2)
167162

168-
return [DeclSyntax(newFunc)]
163+
return [DeclSyntax(funcDecl)]
169164
}
170165
}

Examples/Sources/MacroExamples/Playground/PeerMacrosPlayground.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func runPeerMacrosPlayground() {
5454
var value = 0
5555
}
5656

57-
let counter = Counter()
57+
_ = Counter()
5858

5959
// print("Peer value with suffix name for \(Counter.self): \(String(describing: Counter_peer))")
6060
}

0 commit comments

Comments
 (0)