Initial commit
This commit is contained in:
commit
b10e75dcd9
|
@ -0,0 +1,8 @@
|
||||||
|
.DS_Store
|
||||||
|
/.build
|
||||||
|
/Packages
|
||||||
|
xcuserdata/
|
||||||
|
DerivedData/
|
||||||
|
.swiftpm/configuration/registries.json
|
||||||
|
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||||
|
.netrc
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"originHash" : "e51397b3369f3d57e433298148acc6f90a2116f05c1952cc811f11150b1ce7c1",
|
||||||
|
"pins" : [
|
||||||
|
{
|
||||||
|
"identity" : "swift-syntax",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/apple/swift-syntax.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "cb53fa1bd3219b0b23ded7dfdd3b2baff266fd25",
|
||||||
|
"version" : "600.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version" : 3
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
// swift-tools-version: 6.0
|
||||||
|
|
||||||
|
import PackageDescription
|
||||||
|
import CompilerPluginSupport
|
||||||
|
|
||||||
|
let package = Package(
|
||||||
|
name: "Superman",
|
||||||
|
platforms: [.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6), .macCatalyst(.v13)],
|
||||||
|
products: [
|
||||||
|
.library(
|
||||||
|
name: "Superman",
|
||||||
|
targets: ["Superman"]
|
||||||
|
),
|
||||||
|
.executable(
|
||||||
|
name: "SupermanSample",
|
||||||
|
targets: ["SupermanSample"]
|
||||||
|
),
|
||||||
|
],
|
||||||
|
dependencies: [
|
||||||
|
.package(url: "https://github.com/apple/swift-syntax.git", from: "600.0.0"),
|
||||||
|
],
|
||||||
|
targets: [
|
||||||
|
.macro(
|
||||||
|
name: "SupermanMacros",
|
||||||
|
dependencies: [
|
||||||
|
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
|
||||||
|
.product(name: "SwiftCompilerPlugin", package: "swift-syntax")
|
||||||
|
]
|
||||||
|
),
|
||||||
|
.target(name: "Superman", dependencies: ["SupermanMacros"]),
|
||||||
|
.executableTarget(name: "SupermanSample", dependencies: ["Superman"]),
|
||||||
|
.testTarget(
|
||||||
|
name: "SupermanTests",
|
||||||
|
dependencies: [
|
||||||
|
"SupermanMacros",
|
||||||
|
.product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
|
@ -0,0 +1,5 @@
|
||||||
|
@attached(body)
|
||||||
|
public macro SuperFirst() = #externalMacro(module: "SupermanMacros", type: "SuperFirstMacro")
|
||||||
|
|
||||||
|
@attached(body)
|
||||||
|
public macro SuperLast() = #externalMacro(module: "SupermanMacros", type: "SuperLastMacro")
|
|
@ -0,0 +1,9 @@
|
||||||
|
enum Error: Swift.Error, CustomStringConvertible {
|
||||||
|
case message(String)
|
||||||
|
|
||||||
|
var description: String {
|
||||||
|
switch self {
|
||||||
|
case .message(let text): return text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
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))"]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
import Superman
|
||||||
|
|
||||||
|
class Base {
|
||||||
|
func superFirst() {
|
||||||
|
print("Base superFirst")
|
||||||
|
}
|
||||||
|
|
||||||
|
func superFirstArgs(_ b: Bool, i: Int, double d: Double) {
|
||||||
|
print("Base superFirstArgs (\(b), \(i), \(d))")
|
||||||
|
}
|
||||||
|
|
||||||
|
func superLast() {
|
||||||
|
print("Base superLast")
|
||||||
|
}
|
||||||
|
|
||||||
|
func superLastArgs(_ b: Bool, i: Int, double d: Double) {
|
||||||
|
print("Base superLastArgs (\(b), \(i), \(d))")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Child: Base {
|
||||||
|
@SuperFirst
|
||||||
|
override func superFirst() {
|
||||||
|
print("Child superFirst")
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuperFirst
|
||||||
|
override func superFirstArgs(_ b: Bool, i: Int, double d: Double) {
|
||||||
|
print("Child superFirstArgs (\(b), \(i), \(d))")
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuperLast
|
||||||
|
override func superLast() {
|
||||||
|
print("Child superLast")
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuperLast
|
||||||
|
override func superLastArgs(_ b: Bool, i: Int, double d: Double) {
|
||||||
|
print("Child superLastArgs (\(b), \(i), \(d))")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
let child = Child()
|
||||||
|
child.superFirst()
|
||||||
|
child.superLast()
|
||||||
|
child.superFirstArgs(true, i: 1, double: 0.1)
|
||||||
|
child.superLastArgs(false, i: 0, double: 1.0)
|
||||||
|
}
|
||||||
|
main()
|
|
@ -0,0 +1,79 @@
|
||||||
|
import SwiftSyntaxMacros
|
||||||
|
import SwiftSyntaxMacrosTestSupport
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
#if canImport(SupermanMacros)
|
||||||
|
import SupermanMacros
|
||||||
|
|
||||||
|
let testMacros: [String: Macro.Type] = [
|
||||||
|
"SuperFirst": SuperFirstMacro.self,
|
||||||
|
"SuperLast": SuperLastMacro.self,
|
||||||
|
]
|
||||||
|
|
||||||
|
final class QSLibsTests: XCTestCase {
|
||||||
|
func testSuperFirst() throws {
|
||||||
|
assertMacroExpansion("""
|
||||||
|
@SuperFirst
|
||||||
|
func function() {
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
expandedSource: """
|
||||||
|
func function() {
|
||||||
|
super.function()
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
macros: testMacros)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSuperLast() throws {
|
||||||
|
assertMacroExpansion("""
|
||||||
|
@SuperLast
|
||||||
|
func function() {
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
expandedSource: """
|
||||||
|
func function() {
|
||||||
|
print()
|
||||||
|
return super.function()
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
macros: testMacros)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSuperFirstArgs() throws {
|
||||||
|
assertMacroExpansion("""
|
||||||
|
@SuperFirst
|
||||||
|
func function(_ b: Bool, i: Int, double d: Double) {
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
expandedSource: """
|
||||||
|
func function(_ b: Bool, i: Int, double d: Double) {
|
||||||
|
super.function(_ : b, i: i, double : d)
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
macros: testMacros)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSuperLastArgs() throws {
|
||||||
|
assertMacroExpansion("""
|
||||||
|
@SuperLast
|
||||||
|
func function(_ b: Bool, i: Int, double d: Double) {
|
||||||
|
print()
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
expandedSource: """
|
||||||
|
func function(_ b: Bool, i: Int, double d: Double) {
|
||||||
|
print()
|
||||||
|
return super.function(_ : b, i: i, double : d)
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
macros: testMacros)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue