63 lines
2.1 KiB
Swift
63 lines
2.1 KiB
Swift
import SwiftCompilerPlugin
|
|
import SwiftSyntax
|
|
import SwiftSyntaxMacros
|
|
|
|
@main
|
|
struct SupermanPlugin: CompilerPlugin {
|
|
let providingMacros: [Macro.Type] = [
|
|
SuperFirstMacro.self,
|
|
SuperLastMacro.self,
|
|
]
|
|
}
|
|
|
|
public struct SuperFirstMacro: BodyMacro {
|
|
public static func expansion(of node: AttributeSyntax,
|
|
providingBodyFor declaration: some DeclSyntaxProtocol & WithOptionalCodeBlockSyntax,
|
|
in context: some MacroExpansionContext) throws -> [CodeBlockItemSyntax] {
|
|
// Only allow Functions
|
|
guard let funcDecl = declaration.as(FunctionDeclSyntax.self) else {
|
|
throw Error.message("@SuperFirst only works on functions")
|
|
}
|
|
|
|
// Only allow Void Functions
|
|
guard funcDecl.signature.returnClause?.type.as(IdentifierTypeSyntax.self)?.name.text != "Void" else {
|
|
throw Error.message("@SuperFirst only works on Void functions")
|
|
}
|
|
|
|
// Requires Function Body
|
|
guard let funcBody = funcDecl.body else {
|
|
throw Error.message("@SuperFirst only works on functions with bodies")
|
|
}
|
|
|
|
let arguments = funcDecl.signature.parameterClause.parameters
|
|
let callArgs = arguments.map { argument in
|
|
"\(argument.firstName): \(argument.secondName ?? argument.firstName)"
|
|
}.joined(separator: ", ")
|
|
|
|
return ["super.\(funcDecl.name)(\(raw: callArgs))"] + Array(funcBody.statements)
|
|
}
|
|
}
|
|
|
|
public struct SuperLastMacro: BodyMacro {
|
|
public static func expansion(of node: AttributeSyntax,
|
|
providingBodyFor declaration: some DeclSyntaxProtocol & WithOptionalCodeBlockSyntax,
|
|
in context: some MacroExpansionContext) throws -> [CodeBlockItemSyntax] {
|
|
// Only allow Functions
|
|
guard let funcDecl = declaration.as(FunctionDeclSyntax.self) else {
|
|
throw Error.message("@SuperLast only works on functions")
|
|
}
|
|
|
|
// Requires Function Body
|
|
guard let funcBody = funcDecl.body else {
|
|
throw Error.message("@SuperLast only works on functions with bodies")
|
|
}
|
|
|
|
let arguments = funcDecl.signature.parameterClause.parameters
|
|
let callArgs = arguments.map { argument in
|
|
"\(argument.firstName): \(argument.secondName ?? argument.firstName)"
|
|
}.joined(separator: ", ")
|
|
|
|
return Array(funcBody.statements) + ["return super.\(funcDecl.name)(\(raw: callArgs))"]
|
|
}
|
|
}
|