From 15d205f549a3e63450b7b5108487d819506073f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Ba=CC=A8k?= Date: Thu, 12 Oct 2023 09:11:56 +0200 Subject: [PATCH] Refactor syntax node manipulation to use variable setters This commit replaces the use of 'with' method for syntax node manipulation in SwiftSyntax examples with direct variable setters for better clarity and readability. --- .../AddOneToIntegerLiterals.swift | 3 +- .../DictionaryIndirectionMacro.swift | 7 +- .../Expression/AddBlocker.swift | 16 +--- .../Expression/FontLiteralMacro.swift | 8 +- .../WrapStoredPropertiesMacro.swift | 2 +- .../Implementation/Peer/AddAsyncMacro.swift | 78 +++++++++---------- .../Peer/AddCompletionHandlerMacro.swift | 73 ++++++++--------- .../Playground/PeerMacrosPlayground.swift | 2 +- 8 files changed, 84 insertions(+), 105 deletions(-) diff --git a/Examples/Sources/AddOneToIntegerLiterals/AddOneToIntegerLiterals.swift b/Examples/Sources/AddOneToIntegerLiterals/AddOneToIntegerLiterals.swift index 3fcc35ffac3..c66dc22232b 100644 --- a/Examples/Sources/AddOneToIntegerLiterals/AddOneToIntegerLiterals.swift +++ b/Examples/Sources/AddOneToIntegerLiterals/AddOneToIntegerLiterals.swift @@ -31,7 +31,8 @@ private class AddOneToIntegerLiterals: SyntaxRewriter { let int = Int(integerText)! // Create a new integer literal token with `int + 1` as its text. - let newIntegerLiteralToken = token.with(\.tokenKind, .integerLiteral("\(int + 1)")) + var newIntegerLiteralToken = token + newIntegerLiteralToken.tokenKind = .integerLiteral("\(int + 1)") // Return the new integer literal. return newIntegerLiteralToken diff --git a/Examples/Sources/MacroExamples/Implementation/ComplexMacros/DictionaryIndirectionMacro.swift b/Examples/Sources/MacroExamples/Implementation/ComplexMacros/DictionaryIndirectionMacro.swift index 23d7ce421bc..ccd3651394e 100644 --- a/Examples/Sources/MacroExamples/Implementation/ComplexMacros/DictionaryIndirectionMacro.swift +++ b/Examples/Sources/MacroExamples/Implementation/ComplexMacros/DictionaryIndirectionMacro.swift @@ -21,10 +21,7 @@ extension DictionaryStorageMacro: MemberMacro { providingMembersOf declaration: some DeclGroupSyntax, in context: some MacroExpansionContext ) throws -> [DeclSyntax] { - let storage: DeclSyntax = "var _storage: [String: Any] = [:]" - return [ - storage.with(\.leadingTrivia, [.newlines(1), .spaces(2)]) - ] + return ["\n var _storage: [String: Any] = [:]"] } } @@ -43,11 +40,11 @@ extension DictionaryStorageMacro: MemberAttributeMacro { return [ AttributeSyntax( + leadingTrivia: [.newlines(1), .spaces(2)], attributeName: IdentifierTypeSyntax( name: .identifier("DictionaryStorageProperty") ) ) - .with(\.leadingTrivia, [.newlines(1), .spaces(2)]) ] } } diff --git a/Examples/Sources/MacroExamples/Implementation/Expression/AddBlocker.swift b/Examples/Sources/MacroExamples/Implementation/Expression/AddBlocker.swift index 58dfd7b3c8c..c0041b5b4f7 100644 --- a/Examples/Sources/MacroExamples/Implementation/Expression/AddBlocker.swift +++ b/Examples/Sources/MacroExamples/Implementation/Expression/AddBlocker.swift @@ -27,7 +27,7 @@ public struct AddBlocker: ExpressionMacro { _ node: InfixOperatorExprSyntax ) -> ExprSyntax { // Identify any infix operator + in the tree. - if let binOp = node.operator.as(BinaryOperatorExprSyntax.self) { + if var binOp = node.operator.as(BinaryOperatorExprSyntax.self) { if binOp.operator.text == "+" { // Form the warning let messageID = MessageID(domain: "silly", id: "addblock") @@ -72,17 +72,9 @@ public struct AddBlocker: ExpressionMacro { ) ) - return ExprSyntax( - node.with( - \.operator, - ExprSyntax( - binOp.with( - \.operator, - binOp.operator.with(\.tokenKind, .binaryOperator("-")) - ) - ) - ) - ) + binOp.operator.tokenKind = .binaryOperator("-") + + return ExprSyntax(node.with(\.operator, ExprSyntax(binOp))) } } diff --git a/Examples/Sources/MacroExamples/Implementation/Expression/FontLiteralMacro.swift b/Examples/Sources/MacroExamples/Implementation/Expression/FontLiteralMacro.swift index 0559ace73d3..8afbad6b45f 100644 --- a/Examples/Sources/MacroExamples/Implementation/Expression/FontLiteralMacro.swift +++ b/Examples/Sources/MacroExamples/Implementation/Expression/FontLiteralMacro.swift @@ -35,14 +35,12 @@ private func replaceFirstLabel( of tuple: LabeledExprListSyntax, with newLabel: String ) -> LabeledExprListSyntax { - guard let firstElement = tuple.first else { + if tuple.isEmpty { return tuple } var tuple = tuple - tuple[tuple.startIndex] = - firstElement - .with(\.label, .identifier(newLabel)) - .with(\.colon, .colonToken()) + tuple[tuple.startIndex].label = .identifier(newLabel) + tuple[tuple.startIndex].colon = .colonToken() return tuple } diff --git a/Examples/Sources/MacroExamples/Implementation/MemberAttribute/WrapStoredPropertiesMacro.swift b/Examples/Sources/MacroExamples/Implementation/MemberAttribute/WrapStoredPropertiesMacro.swift index d885331400f..edb48902216 100644 --- a/Examples/Sources/MacroExamples/Implementation/MemberAttribute/WrapStoredPropertiesMacro.swift +++ b/Examples/Sources/MacroExamples/Implementation/MemberAttribute/WrapStoredPropertiesMacro.swift @@ -48,11 +48,11 @@ public struct WrapStoredPropertiesMacro: MemberAttributeMacro { return [ AttributeSyntax( + leadingTrivia: [.newlines(1), .spaces(2)], attributeName: IdentifierTypeSyntax( name: .identifier(wrapperName.content.text) ) ) - .with(\.leadingTrivia, [.newlines(1), .spaces(2)]) ] } } diff --git a/Examples/Sources/MacroExamples/Implementation/Peer/AddAsyncMacro.swift b/Examples/Sources/MacroExamples/Implementation/Peer/AddAsyncMacro.swift index da9faa690ba..e30eb37b98a 100644 --- a/Examples/Sources/MacroExamples/Implementation/Peer/AddAsyncMacro.swift +++ b/Examples/Sources/MacroExamples/Implementation/Peer/AddAsyncMacro.swift @@ -30,7 +30,7 @@ public struct AddAsyncMacro: PeerMacro { ) throws -> [DeclSyntax] { // Only on functions at the moment. - guard let funcDecl = declaration.as(FunctionDeclSyntax.self) else { + guard var funcDecl = declaration.as(FunctionDeclSyntax.self) else { throw CustomError.message("@addAsync only works on functions") } @@ -42,7 +42,7 @@ public struct AddAsyncMacro: PeerMacro { } // This only makes sense void functions - if funcDecl.signature.returnClause?.type.with(\.leadingTrivia, []).with(\.trailingTrivia, []).description != "Void" { + if funcDecl.signature.returnClause?.type.as(IdentifierTypeSyntax.self)?.name.text != "Void" { throw CustomError.message( "@addAsync requires an function that returns void" ) @@ -58,7 +58,7 @@ public struct AddAsyncMacro: PeerMacro { } // Completion handler needs to return Void - if completionHandlerParameter.returnClause.type.with(\.leadingTrivia, []).with(\.trailingTrivia, []).description != "Void" { + if completionHandlerParameter.returnClause.type.as(IdentifierTypeSyntax.self)?.name.text != "Void" { throw CustomError.message( "@addAsync requires an function that has a completion handler that returns Void" ) @@ -72,9 +72,11 @@ public struct AddAsyncMacro: PeerMacro { // Remove completionHandler and comma from the previous parameter var newParameterList = funcDecl.signature.parameterClause.parameters newParameterList.removeLast() - let newParameterListLastParameter = newParameterList.last! + var newParameterListLastParameter = newParameterList.last! newParameterList.removeLast() - newParameterList.append(newParameterListLastParameter.with(\.trailingTrivia, []).with(\.trailingComma, nil)) + newParameterListLastParameter.trailingTrivia = [] + newParameterListLastParameter.trailingComma = nil + newParameterList.append(newParameterListLastParameter) // Drop the @addAsync attribute from the new declaration. let newAttributeList = funcDecl.attributes.filter { @@ -121,42 +123,36 @@ public struct AddAsyncMacro: PeerMacro { """ - let newFunc = - funcDecl - .with( - \.signature, - funcDecl.signature - .with( - \.effectSpecifiers, - FunctionEffectSpecifiersSyntax( - leadingTrivia: .space, - asyncSpecifier: .keyword(.async), - throwsSpecifier: isResultReturn ? .keyword(.throws) : nil - ) // add async - ) - .with( - \.returnClause, - successReturnType != nil ? ReturnClauseSyntax(leadingTrivia: .space, type: successReturnType!.with(\.leadingTrivia, .space)) : nil - ) // add result type - .with( - \.parameterClause, - funcDecl.signature.parameterClause.with(\.parameters, newParameterList) // drop completion handler - .with(\.trailingTrivia, []) - ) - ) - .with( - \.body, - CodeBlockSyntax( - leftBrace: .leftBraceToken(leadingTrivia: .space), - statements: CodeBlockItemListSyntax( - [CodeBlockItemSyntax(item: .expr(newBody))] - ), - rightBrace: .rightBraceToken(leadingTrivia: .newline) - ) - ) - .with(\.attributes, newAttributeList) - .with(\.leadingTrivia, .newlines(2)) + // add async + funcDecl.signature.effectSpecifiers = FunctionEffectSpecifiersSyntax( + leadingTrivia: .space, + asyncSpecifier: .keyword(.async), + throwsSpecifier: isResultReturn ? .keyword(.throws) : nil + ) + + // add result type + if let successReturnType { + funcDecl.signature.returnClause = ReturnClauseSyntax(leadingTrivia: .space, type: successReturnType.with(\.leadingTrivia, .space)) + } else { + funcDecl.signature.returnClause = nil + } + + // drop completion handler + funcDecl.signature.parameterClause.parameters = newParameterList + funcDecl.signature.parameterClause.trailingTrivia = [] + + funcDecl.body = CodeBlockSyntax( + leftBrace: .leftBraceToken(leadingTrivia: .space), + statements: CodeBlockItemListSyntax( + [CodeBlockItemSyntax(item: .expr(newBody))] + ), + rightBrace: .rightBraceToken(leadingTrivia: .newline) + ) + + funcDecl.attributes = newAttributeList + + funcDecl.leadingTrivia = .newlines(2) - return [DeclSyntax(newFunc)] + return [DeclSyntax(funcDecl)] } } diff --git a/Examples/Sources/MacroExamples/Implementation/Peer/AddCompletionHandlerMacro.swift b/Examples/Sources/MacroExamples/Implementation/Peer/AddCompletionHandlerMacro.swift index 3f1d8334486..0691f230410 100644 --- a/Examples/Sources/MacroExamples/Implementation/Peer/AddCompletionHandlerMacro.swift +++ b/Examples/Sources/MacroExamples/Implementation/Peer/AddCompletionHandlerMacro.swift @@ -25,20 +25,22 @@ public struct AddCompletionHandlerMacro: PeerMacro { ) throws -> [DeclSyntax] { // Only on functions at the moment. We could handle initializers as well // with a bit of work. - guard let funcDecl = declaration.as(FunctionDeclSyntax.self) else { + guard var funcDecl = declaration.as(FunctionDeclSyntax.self) else { throw CustomError.message("@addCompletionHandler only works on functions") } // This only makes sense for async functions. if funcDecl.signature.effectSpecifiers?.asyncSpecifier == nil { - let newEffects: FunctionEffectSpecifiersSyntax + var newEffects: FunctionEffectSpecifiersSyntax if let existingEffects = funcDecl.signature.effectSpecifiers { - newEffects = existingEffects.with(\.asyncSpecifier, .keyword(.async)) + newEffects = existingEffects + newEffects.asyncSpecifier = .keyword(.async) } else { newEffects = FunctionEffectSpecifiersSyntax(asyncSpecifier: .keyword(.async)) } - let newSignature = funcDecl.signature.with(\.effectSpecifiers, newEffects) + var newSignature = funcDecl.signature + newSignature.effectSpecifiers = newEffects let messageID = MessageID(domain: "MacroExamples", id: "MissingAsync") let diag = Diagnostic( @@ -73,7 +75,9 @@ public struct AddCompletionHandlerMacro: PeerMacro { } // Form the completion handler parameter. - let resultType: TypeSyntax? = funcDecl.signature.returnClause?.type.with(\.leadingTrivia, []).with(\.trailingTrivia, []) + var resultType = funcDecl.signature.returnClause?.type + resultType?.leadingTrivia = [] + resultType?.trailingTrivia = [] let completionHandlerParam = FunctionParameterSyntax( @@ -85,14 +89,12 @@ public struct AddCompletionHandlerMacro: PeerMacro { // Add the completion handler parameter to the parameter list. let parameterList = funcDecl.signature.parameterClause.parameters var newParameterList = parameterList - if let lastParam = parameterList.last { + if var lastParam = parameterList.last { // We need to add a trailing comma to the preceding list. newParameterList.removeLast() + lastParam.trailingComma = .commaToken(trailingTrivia: .space) newParameterList += [ - lastParam.with( - \.trailingComma, - .commaToken(trailingTrivia: .space) - ), + lastParam, completionHandlerParam, ] } else { @@ -136,35 +138,28 @@ public struct AddCompletionHandlerMacro: PeerMacro { return attributeType.name.text != nodeType.name.text } - let newFunc = - funcDecl - .with( - \.signature, - funcDecl.signature - .with( - \.effectSpecifiers, - funcDecl.signature.effectSpecifiers?.with(\.asyncSpecifier, nil) // drop async - ) - .with(\.returnClause, nil) // drop result type - .with( - \.parameterClause, // add completion handler parameter - funcDecl.signature.parameterClause.with(\.parameters, newParameterList) - .with(\.trailingTrivia, []) - ) - ) - .with( - \.body, - CodeBlockSyntax( - leftBrace: .leftBraceToken(leadingTrivia: .space), - statements: CodeBlockItemListSyntax( - [CodeBlockItemSyntax(item: .expr(newBody))] - ), - rightBrace: .rightBraceToken(leadingTrivia: .newline) - ) - ) - .with(\.attributes, newAttributeList) - .with(\.leadingTrivia, .newlines(2)) + // drop async + funcDecl.signature.effectSpecifiers?.asyncSpecifier = nil + + // drop result type + funcDecl.signature.returnClause = nil + + // add completion handler parameter + funcDecl.signature.parameterClause.parameters = newParameterList + funcDecl.signature.parameterClause.trailingTrivia = [] + + funcDecl.body = CodeBlockSyntax( + leftBrace: .leftBraceToken(leadingTrivia: .space), + statements: CodeBlockItemListSyntax( + [CodeBlockItemSyntax(item: .expr(newBody))] + ), + rightBrace: .rightBraceToken(leadingTrivia: .newline) + ) + + funcDecl.attributes = newAttributeList + + funcDecl.leadingTrivia = .newlines(2) - return [DeclSyntax(newFunc)] + return [DeclSyntax(funcDecl)] } } diff --git a/Examples/Sources/MacroExamples/Playground/PeerMacrosPlayground.swift b/Examples/Sources/MacroExamples/Playground/PeerMacrosPlayground.swift index a4b88c66e35..bc5ba242ca1 100644 --- a/Examples/Sources/MacroExamples/Playground/PeerMacrosPlayground.swift +++ b/Examples/Sources/MacroExamples/Playground/PeerMacrosPlayground.swift @@ -54,7 +54,7 @@ func runPeerMacrosPlayground() { var value = 0 } - let counter = Counter() + _ = Counter() // print("Peer value with suffix name for \(Counter.self): \(String(describing: Counter_peer))") }