Skip to content

Commit

Permalink
🌲 Update
Browse files Browse the repository at this point in the history
  • Loading branch information
muukii committed Aug 29, 2023
1 parent 9114e4f commit 393ed52
Show file tree
Hide file tree
Showing 21 changed files with 610 additions and 19 deletions.
9 changes: 9 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ let package = Package(
.library(name: "Verge", targets: ["Verge"]),
.library(name: "VergeTiny", targets: ["VergeTiny"]),
.library(name: "VergeORM", targets: ["VergeORM"]),
.library(name: "VergeNormalization", targets: ["VergeNormalization"]),
.library(name: "VergeRx", targets: ["VergeRx"]),
.library(name: "VergeClassic", targets: ["VergeClassic"]),
.library(name: "VergeMacros", targets: ["VergeMacros"]),
Expand Down Expand Up @@ -59,9 +60,17 @@ let package = Package(
"VergeRx"
]
),
.target(
name: "VergeNormalization",
dependencies: [
"Verge",
.product(name: "HashTreeCollections", package: "swift-collections"),
]
),
.target(
name: "VergeORM",
dependencies: [
"VergeNormalization",
"Verge",
.product(name: "HashTreeCollections", package: "swift-collections"),
]
Expand Down
225 changes: 225 additions & 0 deletions Sources/VergeMacrosPlugin/DatabaseMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,229 @@ import SwiftSyntax
import SwiftSyntaxBuilder
import SwiftSyntaxMacros

public struct DatabaseMacro: Macro {

}

extension DatabaseMacro: ExtensionMacro {
public static func expansion(
of node: SwiftSyntax.AttributeSyntax,
attachedTo declaration: some SwiftSyntax.DeclGroupSyntax,
providingExtensionsOf type: some SwiftSyntax.TypeSyntaxProtocol,
conformingTo protocols: [SwiftSyntax.TypeSyntax],
in context: some SwiftSyntaxMacros.MacroExpansionContext
) throws -> [SwiftSyntax.ExtensionDeclSyntax] {

guard let structDecl = declaration.as(StructDeclSyntax.self) else {
fatalError()
}

return [
("""
extension \(structDecl.name.trimmed): NormalizedStorageType {}
""" as DeclSyntax).cast(ExtensionDeclSyntax.self),
("""
extension \(structDecl.name.trimmed): Equatable {}
""" as DeclSyntax).cast(ExtensionDeclSyntax.self),
("""
extension \(structDecl.name.trimmed) {
typealias BBB = String
struct Context {}
}
""" as DeclSyntax).cast(ExtensionDeclSyntax.self)
]
}

}

//extension DatabaseMacro: PeerMacro {
// public static func expansion(
// of node: SwiftSyntax.AttributeSyntax,
// providingPeersOf declaration: some SwiftSyntax.DeclSyntaxProtocol,
// in context: some SwiftSyntaxMacros.MacroExpansionContext
// ) throws -> [SwiftSyntax.DeclSyntax] {
//
// guard let structDecl = declaration.as(StructDeclSyntax.self) else {
// fatalError()
// }
//
// return [
// """
//extension \(structDecl.name.trimmed) {
// struct A {}
//}
//"""
// ]
// }
//
//}

extension DatabaseMacro: DeclarationMacro {
public static func expansion(
of node: some SwiftSyntax.FreestandingMacroExpansionSyntax,
in context: some SwiftSyntaxMacros.MacroExpansionContext
) throws -> [SwiftSyntax.DeclSyntax] {
return []
}
}

/// Add @Table
extension DatabaseMacro: MemberAttributeMacro {

public static func expansion(
of node: SwiftSyntax.AttributeSyntax,
attachedTo declaration: some SwiftSyntax.DeclGroupSyntax,
providingAttributesFor member: some SwiftSyntax.DeclSyntaxProtocol,
in context: some SwiftSyntaxMacros.MacroExpansionContext
) throws -> [SwiftSyntax.AttributeSyntax] {

if let variableDecl = member.as(VariableDeclSyntax.self) {

let isGenerated = variableDecl
.bindings
.allSatisfy {
$0.cast(PatternBindingSyntax.self).pattern.cast(IdentifierPatternSyntax.self).identifier
.description.hasPrefix("_$")
}

if isGenerated {
return []
}

// if isComputedProperty(from: variableDecl) {
// return []
// }

return [
"@Table"
]

}

return []

}

}

/// Add member
extension DatabaseMacro: MemberMacro {

final class RenamingVisitor: SyntaxRewriter {

init() {}

override func visit(_ node: IdentifierPatternSyntax) -> PatternSyntax {
return "_$\(node.identifier)"
}

override func visit(_ node: VariableDeclSyntax) -> DeclSyntax {

// TODO: make variable private
return super.visit(node)
}
}

final class StoredPropertyCollector: SyntaxVisitor {

var storedProperties: [VariableDeclSyntax] = []

var onFoundMultipleBindings: () -> Void = {}

override func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind {

if node.bindingSpecifier == "let" {
storedProperties.append(node)
return super.visit(node)
}

if node.bindings.count > 1 {
// let a,b,c = 0
// it's stored
onFoundMultipleBindings()
return super.visit(node)
}

if node.bindings.first?.accessorBlock == nil {
storedProperties.append(node)
return super.visit(node)
}

// computed property

return .visitChildren
}

}

static func makeVariableFromConstant(_ node: VariableDeclSyntax) -> VariableDeclSyntax {
var modified = node
modified.bindingSpecifier = "var"
return modified
}

public static func expansion(
of node: SwiftSyntax.AttributeSyntax,
providingMembersOf declaration: some SwiftSyntax.DeclGroupSyntax,
in context: some SwiftSyntaxMacros.MacroExpansionContext
) throws -> [SwiftSyntax.DeclSyntax] {


let v = StoredPropertyCollector(viewMode: .fixedUp)
v.onFoundMultipleBindings = {
context.addDiagnostics(from: MacroError(message: "Cannot use multiple bindings"), node: node)
}
v.walk(declaration.memberBlock)

let storageMembers = v.storedProperties
.map(makeVariableFromConstant)
.map {

let rename = RenamingVisitor()
let renamed = rename.visit($0)

return renamed
}

return storageMembers

}

}

public struct DatabaseTableMacro: Macro {

}

extension DatabaseTableMacro: AccessorMacro {
public static func expansion(
of node: SwiftSyntax.AttributeSyntax,
providingAccessorsOf declaration: some SwiftSyntax.DeclSyntaxProtocol,
in context: some SwiftSyntaxMacros.MacroExpansionContext
) throws -> [SwiftSyntax.AccessorDeclSyntax] {

func identifier(from node: VariableDeclSyntax) -> TokenSyntax {
node.bindings.first!.cast(PatternBindingSyntax.self).pattern.cast(IdentifierPatternSyntax.self).identifier
}

let id = identifier(from: declaration.cast(VariableDeclSyntax.self))

return [
"""
get {
_$\(id)
}
""",
"""
set {
_$\(id) = newValue
}
""" ,
]
}

}

public struct DatabaseIndexMacro: Macro {

}
17 changes: 17 additions & 0 deletions Sources/VergeMacrosPlugin/MacroError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

import SwiftDiagnostics

public struct MacroError: Error, DiagnosticMessage {

public var message: String

public var diagnosticID: SwiftDiagnostics.MessageID {
.init(domain: "Verge", id: "MacroError")
}

public var severity: SwiftDiagnostics.DiagnosticSeverity = .error

init(message: String) {
self.message = message
}
}
4 changes: 4 additions & 0 deletions Sources/VergeMacrosPlugin/Plugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,9 @@ struct Plugin: CompilerPlugin {
let providingMacros: [Macro.Type] = [
DatabaseStateMacro.self,
IfChangedMacro.self,

DatabaseMacro.self,
DatabaseTableMacro.self,
DatabaseIndexMacro.self
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public struct EntityIdentifier<Entity: EntityType> : Hashable, CustomStringConve
raw.hash(into: &hasher)
}

let any: AnyEntityIdentifier
public let any: AnyEntityIdentifier

public let raw: Entity.EntityIDRawType

Expand All @@ -51,7 +51,8 @@ public struct EntityIdentifier<Entity: EntityType> : Hashable, CustomStringConve
self.any = .init(raw._primitiveIdentifier)
}

init(_ anyIdentifier: AnyEntityIdentifier) {
@_spi(ForORM)
public init(_ anyIdentifier: AnyEntityIdentifier) {
self.any = anyIdentifier
self.raw = Entity.EntityIDRawType._restore(from: anyIdentifier.value)!
}
Expand All @@ -73,12 +74,6 @@ public protocol EntityType: Equatable, Sendable {

var entityID: EntityID { get }

#if COCOAPODS
typealias EntityTableKey = Verge.EntityTableKey<Self>
#else
typealias EntityTableKey = VergeORM.EntityTableKey<Self>
#endif

typealias EntityID = EntityIdentifier<Self>
}

Expand All @@ -92,14 +87,6 @@ extension EntityType {
public static var entityName: EntityTableIdentifier {
.init(Self.self)
}

@available(*, deprecated, renamed: "EntityID")
public typealias ID = EntityID

@available(*, deprecated, renamed: "entityID")
public var id: EntityID {
_read { yield entityID }
}

}

Expand Down
8 changes: 8 additions & 0 deletions Sources/VergeNormalization/ModifyingTable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//
// File.swift
//
//
// Created by Muukii on 2023/08/30.
//

import Foundation
12 changes: 12 additions & 0 deletions Sources/VergeNormalization/NonAtomicCounter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/// A container that manages raw value to describe mark as updated.
public struct NonAtomicCounter: Hashable, Sendable {

private(set) public var value: UInt64 = 0

public init() {}

public consuming func increment() {
value &+= 1
}

}
Loading

0 comments on commit 393ed52

Please sign in to comment.