diff --git a/Package.swift b/Package.swift index 17eca1962b..d966c20b2b 100644 --- a/Package.swift +++ b/Package.swift @@ -16,6 +16,7 @@ let package = Package( .library(name: "VergeORM", targets: ["VergeORM"]), .library(name: "VergeRx", targets: ["VergeRx"]), .library(name: "VergeClassic", targets: ["VergeClassic"]), + .library(name: "VergeMacros", targets: ["VergeMacros"]) ], dependencies: [ .package(url: "https://github.com/ReactiveX/RxSwift.git", from: "6.0.0"), @@ -26,25 +27,27 @@ let package = Package( /// for testing .package(url: "https://github.com/nalexn/ViewInspector.git", from: "0.9.3"), - - .package(url: "https://github.com/apple/swift-syntax.git", from: "509.0.0-swift-5.9-DEVELOPMENT-SNAPSHOT-2023-04-25-b") + .package(url: "https://github.com/apple/swift-syntax.git", from: "509.0.0-swift-5.9-DEVELOPMENT-SNAPSHOT-2023-04-25-b") ], targets: [ + + // compiler plugin .macro( - name: "VergeMacros", + name: "VergeMacrosPlugin", dependencies: [ .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), .product(name: "SwiftCompilerPlugin", package: "swift-syntax") ] ), - .target(name: "VergeMacrosExports", dependencies: ["VergeMacros"]), + // macro exports + .target(name: "VergeMacros", dependencies: ["VergeMacrosPlugin"]), .target(name: "VergeTiny", dependencies: []), .target( name: "Verge", dependencies: [ - "VergeMacrosExports", + "VergeMacros", .product(name: "Atomics", package: "swift-atomics"), .product(name: "DequeModule", package: "swift-collections"), .product(name: "ConcurrencyTaskManager", package: "swift-concurrency-task-manager"), @@ -92,6 +95,10 @@ let package = Package( name: "VergeTinyTests", dependencies: ["VergeTiny"] ), + .testTarget(name: "VergeMacrosTests", dependencies: [ + "VergeMacros", + .product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"), + ]) ], swiftLanguageVersions: [.v5] ) diff --git a/Sources/VergeMacros/Source.swift b/Sources/VergeMacros/Source.swift index f3b4be0ab8..51c40ac07f 100644 --- a/Sources/VergeMacros/Source.swift +++ b/Sources/VergeMacros/Source.swift @@ -1,11 +1,22 @@ -import SwiftCompilerPlugin -import SwiftSyntax -import SwiftSyntaxBuilder -import SwiftSyntaxMacros -@main -struct VergeMacroPlugin: CompilerPlugin { - let providingMacros: [Macro.Type] = [ +//@freestanding(expression) public macro +// #externalMacro(module: "MacroExamplesPlugin", type: "FontLiteralMacro") - ] -} +/** + struct Database: DatabaseType { + + struct Schema: EntitySchemaType { + let author = Author.EntityTableKey() + } + + struct Indexes: IndexesType { + let allBooks = HashIndex.Key() + } + + var _backingStorage: BackingStorage = .init() + } + */ + +@attached(member, names: named(_backingStorage)) +@attached(conformance) +public macro DatabaseState() = #externalMacro(module: "VergeMacrosPlugin", type: "DatabaseStateMacro") diff --git a/Sources/VergeMacrosPlugin/DatabaseStateMacro.swift b/Sources/VergeMacrosPlugin/DatabaseStateMacro.swift new file mode 100644 index 0000000000..ddffec2bcd --- /dev/null +++ b/Sources/VergeMacrosPlugin/DatabaseStateMacro.swift @@ -0,0 +1,48 @@ +import SwiftSyntax +import SwiftSyntaxBuilder +import SwiftSyntaxMacros + +public struct DatabaseStateMacro { + +} + +extension DatabaseStateMacro: ConformanceMacro { + public static func expansion( + of node: SwiftSyntax.AttributeSyntax, + providingConformancesOf declaration: Declaration, + in context: Context + ) throws -> [(SwiftSyntax.TypeSyntax, SwiftSyntax.GenericWhereClauseSyntax?)] + where Declaration: SwiftSyntax.DeclGroupSyntax, Context: SwiftSyntaxMacros.MacroExpansionContext { + + // Decode the expansion arguments. + guard let structDecl = declaration.as(StructDeclSyntax.self) else { +// context.diagnose(OptionSetMacroDiagnostic.requiresStruct.diagnose(at: decl)) + return [] + } + + // If there is an explicit conformance to OptionSet already, don't add one. + if let inheritedTypes = structDecl.inheritanceClause?.inheritedTypeCollection, + inheritedTypes.contains(where: { inherited in inherited.typeName.trimmedDescription == "DatabaseType" }) { + return [] + } + + return [("DatabaseType", nil)] + } + +} + +extension DatabaseStateMacro: MemberMacro { + + public static func expansion( + of node: SwiftSyntax.AttributeSyntax, + providingMembersOf declaration: Declaration, + in context: Context + ) throws -> [SwiftSyntax.DeclSyntax] + where Declaration: SwiftSyntax.DeclGroupSyntax, Context: SwiftSyntaxMacros.MacroExpansionContext { + + return [ + "var _backingStorage: BackingStorage = .init()" + ] + + } +} diff --git a/Sources/VergeMacrosPlugin/VergeMacrosPlugin.swift b/Sources/VergeMacrosPlugin/VergeMacrosPlugin.swift new file mode 100644 index 0000000000..e2ec9e32f6 --- /dev/null +++ b/Sources/VergeMacrosPlugin/VergeMacrosPlugin.swift @@ -0,0 +1,16 @@ +import SwiftCompilerPlugin +import SwiftSyntax +import SwiftSyntaxBuilder +import SwiftSyntaxMacros + +struct _Macro: AttachedMacro { + +} + + +@main +struct VergeMacroPlugin: CompilerPlugin { + let providingMacros: [Macro.Type] = [ + DatabaseStateMacro.self, + ] +} diff --git a/Sources/VergeMacrosExports/Source.swift b/Tests/VergeMacrosTests/VergeMacrosTests.swift similarity index 56% rename from Sources/VergeMacrosExports/Source.swift rename to Tests/VergeMacrosTests/VergeMacrosTests.swift index 86e304548e..cff6e50cb1 100644 --- a/Sources/VergeMacrosExports/Source.swift +++ b/Tests/VergeMacrosTests/VergeMacrosTests.swift @@ -2,7 +2,7 @@ // File.swift // // -// Created by Muukii on 2023/06/12. +// Created by Muukii on 2023/06/17. // import Foundation diff --git a/Tests/VergeORMTests/RootState.swift b/Tests/VergeORMTests/RootState.swift index 8a3972c56a..9451282715 100644 --- a/Tests/VergeORMTests/RootState.swift +++ b/Tests/VergeORMTests/RootState.swift @@ -10,6 +10,7 @@ import Foundation import Verge import VergeORM +import VergeMacros struct Book: EntityType, Hashable { @@ -39,8 +40,9 @@ struct Author: EntityType { } struct RootState: StateType { - - struct Database: DatabaseType { + + @DatabaseState + struct Database { struct Schema: EntitySchemaType { let book = Book.EntityTableKey() @@ -62,8 +64,6 @@ struct RootState: StateType { }) ] } - - var _backingStorage: BackingStorage = .init() } struct Other: Equatable {