Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Sources/PlaytomicMacrosClient/AddAsyncMacroPlayground.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ func sportsSelector(sports: [String], callback: @escaping (String) -> Void) -> V
}

func runAddAsyncMacroPlayground() async {
startRunner()
defer { stopRunner() }
let sport = await sportsSelector(sports: ["Padel", "Tenis", "Pickleball"])
print("@addAsyncMacro:", sport)
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ enum ProfileViewState {
}

func runCaseDetectionMacroPlayground() {
startRunner()
defer { stopRunner() }
var state = ProfileViewState.loading
print("@caseDetection: is the view state loading?: \(state.isLoading)")
state = ProfileViewState.loaded(userName: "Random name")
Expand Down
2 changes: 2 additions & 0 deletions Sources/PlaytomicMacrosClient/CopyableMacroPlayground.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ struct ExampleViewState {
}

func runCopyableMacroPlayground() {
startRunner()
defer { stopRunner() }
let x = ExampleViewState(title: "1", count: 2)
print("@Copyable:", x)
print("@Copyable:", x.copy(title: "2", count: .value(nil)))
Expand Down
2 changes: 2 additions & 0 deletions Sources/PlaytomicMacrosClient/EquatableMacroPlayground.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ struct MatchTeam {
}

func runEquatableMacroPlayground() {
startRunner()
defer { stopRunner() }
let id1 = UUID().uuidString
let match1 = Match(id: id1, team: MatchTeam(id: id1, playerd: []))
let match2 = Match(id: id1, team: MatchTeam(id: id1, playerd: []))
Expand Down
12 changes: 12 additions & 0 deletions Sources/PlaytomicMacrosClient/Helper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,15 @@ func ?? <T>(_ nullable: Nullable<T>, _ defValue: T?) -> T? {
nullable.or(defValue)
}

func startRunner(file: String = #file) {
let fileNameWithExtension = URL(string: file)!.lastPathComponent
let fileNameWithoutExtension = fileNameWithExtension.replacingOccurrences(of: ".swift", with: "")
print("\n### --- RUNNING \(fileNameWithoutExtension) --- ###\n")
}

func stopRunner(file: String = #file, function: String = #function) {
let fileNameWithExtension = URL(string: file)!.lastPathComponent
let fileNameWithoutExtension = fileNameWithExtension.replacingOccurrences(of: ".swift", with: "")
print("\n### --- FINISHED \(fileNameWithoutExtension) --- ###\n")
}

47 changes: 31 additions & 16 deletions Sources/PlaytomicMacrosClient/SealedMacroPlayground.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ class LevelUpgradeViewAction: ViewAction {


// Usage example
private func handleViewAction(_ action: LevelUpgradeViewAction) -> String {
switch action.type {
private func handleViewAction(_ action: LevelUpgradeViewAction.SealedType) -> String {
switch action {
case .OnAppear: "On appear"
case .Upgrade: "Upgrade"
case let .OnUpgradeStarted(action): "Upgrade started from \(action.from) to \(action.to)"
Expand All @@ -73,31 +73,46 @@ private func handleViewAction(_ action: LevelUpgradeViewAction) -> String {
}

// Handling specific action types
private func handleNavigationAction(_ action: LevelUpgradeNavigationAction) -> String {
switch action.type {
private func handleNavigationAction(_ action: LevelUpgradeViewAction.NavigationSealedType) -> String {
switch action {
case let .OnUpgradeSuccess(action): "Navigation: Upgrade success from \(action.from) to \(action.to)"
case let .OnUpgradeError(action): "Navigation: Upgrade error: \(action.error)"
case .OnUpgradeSkipped: "Navigation: Upgrade skipped"
}
}

private func handleEventAction(_ action: LevelUpgradeEventAction) -> String {
switch action.type {
private func handleEventAction(_ action: LevelUpgradeViewAction.EventSealedType) -> String {
switch action {
case .OnAppear: "Event: On appear"
case let .OnUpgradeStarted(action): "Event: Upgrade started from \(action.from) to \(action.to)"
case .OnUpgradeSkipped: "Event: Upgrade skipped"
}
}

private func handle(_ action: LevelUpgradeViewAction) {
if let viewAction = action.type {
print("VIEW:", handleViewAction(viewAction))
}

if let navigationAction = action.navigationType {
print("NAVIGATION:", handleNavigationAction(navigationAction))
}

if let eventAction = action.eventType {
print("EVENT:", handleEventAction(eventAction))
}
}

func runSealedMacroPlayground() {
print(handleViewAction(LevelUpgradeViewAction.OnUpgradeStarted(from: 1.0, to: 2.0)))
print(handleNavigationAction(LevelUpgradeViewAction.OnUpgradeSuccess(from: 1.0, to: 2.0)))
print(handleEventAction(LevelUpgradeViewAction.OnUpgradeStarted(from: 1.0, to: 2.0)))

let x: LevelUpgradeViewAction = LevelUpgradeViewAction.OnAppear()
let y: LevelUpgradeEventAction = LevelUpgradeViewAction.OnAppear()
let z: LevelUpgradeNavigationAction = LevelUpgradeViewAction.OnUpgradeSkipped()
print(x.type)
print(y.type)
print(z.type)
startRunner()
defer { stopRunner() }
handle(LevelUpgradeViewAction.OnUpgradeStarted(from: 1.0, to: 2.0))
handle(LevelUpgradeViewAction.OnUpgradeSuccess(from: 1.0, to: 2.0))
handle(LevelUpgradeViewAction.OnUpgradeStarted(from: 1.0, to: 2.0))
// let x: LevelUpgradeViewAction = LevelUpgradeViewAction.OnAppear()
// let y: LevelUpgradeEventAction = LevelUpgradeViewAction.OnAppear()
// let z: LevelUpgradeNavigationAction = LevelUpgradeViewAction.OnUpgradeSkipped()
// print(x.type)
// print(x.navigationType)
// print(x.eventType)
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ struct User {
}

func runStoredAccessMacroPlayground() {

startRunner()
defer { stopRunner() }
}
2 changes: 2 additions & 0 deletions Sources/PlaytomicMacrosClient/StringifyMacroPlayground.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import Foundation
import PlaytomicMacros

func runStringifyMacroPlayground() {
startRunner()
defer { stopRunner() }
let a = 17
let b = 25
let (result, code) = #stringify(a + b)
Expand Down
2 changes: 2 additions & 0 deletions Sources/PlaytomicMacrosClient/URLMacroPlayground.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,7 @@ import PlaytomicMacros
malformed an error is emitted. Otherwise a non-optional URL is expanded.
*/
func runURLMacroPlayground() {
startRunner()
defer { stopRunner() }
print(#URL("https://playtomic.io/"))
}
2 changes: 2 additions & 0 deletions Sources/PlaytomicMacrosClient/WarningMacroPlayground.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ import Foundation
import PlaytomicMacros

func runWarningMacroPlayground() {
startRunner()
defer { stopRunner() }
#warning("This macro generates a message")
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ struct OldStorage {
}

func runWrapStoredPropertiesMacroPlayground() {

startRunner()
defer { stopRunner() }
}
30 changes: 30 additions & 0 deletions Sources/PlaytomicMacrosSource/Helper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,33 @@ extension ClassDeclSyntax {
} != nil
}
}

extension String {
var wordsSeparatedByCapitalLetter: [String] {
self.lazy
.map({ $0.isUppercase ? " \($0)" : "\($0)" })
.joined()
.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
.components(separatedBy: " ")
}

func diff(_ rhs: String) -> [String] {
let lhsWords = wordsSeparatedByCapitalLetter
let rhsWords = rhs.wordsSeparatedByCapitalLetter
var differences: [String] = []

let minLength = min(lhsWords.count, rhsWords.count)

for i in 0..<minLength {
if lhsWords[i] != rhsWords[i] {
differences.append(rhsWords[i])
}
}

if rhsWords.count > minLength {
differences.append(contentsOf: rhsWords[minLength...])
}

return differences
}
}
97 changes: 40 additions & 57 deletions Sources/PlaytomicMacrosSource/attached/SealedMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,6 @@ public enum SealedMacro: ExtensionMacro {
conformingTo protocols: [TypeSyntax],
in context: some MacroExpansionContext
) throws -> [ExtensionDeclSyntax] {
// guard declaration.as(StructDeclSyntax.self) != nil || declaration.as(ClassDeclSyntax.self) != nil,
// let name = declaration.as(StructDeclSyntax.self)?.name ?? declaration.as(ClassDeclSyntax.self)?.name else {
// let diagnostic = Diagnostic(node: node, message: CopyableMacroDiagnostic.notAStructOrClass)
// context.diagnose(diagnostic)
// return []
// }


guard let typeIdentifier = type.as(IdentifierTypeSyntax.self)?.name.trimmed.text else {
return []
Expand Down Expand Up @@ -73,11 +66,9 @@ public enum SealedMacro: ExtensionMacro {
}
}

print("PRINT<<", sealedTypes)

let sealedTypesSynax = sealedTypes.keys.map { inheritedClassName in
generateEnumType(
typeName: inheritedClassName,
typeName: typeIdentifier.diff(inheritedClassName + SEALED_TYPE_SUFFIX).joined(),
onGenerateCases: {
generateEnumCases(
parenTypeName: typeIdentifier,
Expand All @@ -87,48 +78,42 @@ public enum SealedMacro: ExtensionMacro {
)
}.joined(separator: "\n\n").appending("\n")

// let typeProperty = generateTypeProperty(
// parenTypeName: typeIdentifier,
// allCases: sealedTypes[typeIdentifier] ?? []
// ).appending("\n")

let sealedTypesDefinitionExtensionSyntax = try ExtensionDeclSyntax(
"""
extension \(type.trimmed) {
\(raw: sealedTypesSynax)
}
"""
)

// let sealedTypesDefinitionExtensionSyntax = try ExtensionDeclSyntax(
// """
// extension \(type.trimmed) {
// \(raw: sealedTypesSynax)
// \(raw: typeProperty)
// }
// """
// )
)


let sealedTypesResolutionExtensionSyntaxes = try sealedTypes.keys
.sorted(by: { lhs, rhs in lhs == typeIdentifier })
.map { sealedType in
try generateSealedTypesExtensions(
parenTypeName: typeIdentifier,
subActionTypeName: sealedType,
allCases: sealedTypes[sealedType] ?? []
)
}

return [sealedTypesDefinitionExtensionSyntax] + sealedTypesResolutionExtensionSyntaxes
try generateSealedTypesExtensions(
parenTypeName: typeIdentifier,
subTypeName: sealedType,
subActionTypeName: typeIdentifier.diff(sealedType).joined(),
allCases: sealedTypes[sealedType] ?? []
)
}.joined(separator: "\n\n")

return [try ExtensionDeclSyntax(
"""
extension \(type.trimmed) {
\(raw: sealedTypesSynax)
\(raw: sealedTypesResolutionExtensionSyntaxes)
}
"""
)]
}

private static func generateEnumType(
typeName: String,
onGenerateCases: @escaping () -> String
) -> String {
"""
enum \(typeName)\(SEALED_TYPE_SUFFIX) {
enum \(typeName) {
\(onGenerateCases())
}
"""
Expand All @@ -142,45 +127,43 @@ public enum SealedMacro: ExtensionMacro {
.joined(separator: "\n")
}

private static func generateTypeProperty(parenTypeName: String, allCases: [ClassDeclSyntax]) -> String {
let allCasesSyntax = allCases.map { eachCase in
let name = eachCase.name.text
return "case is \(parenTypeName).\(name): \(parenTypeName)\(SEALED_TYPE_SUFFIX).\(name)\(eachCase.isContainProperty ? "(self as! \(parenTypeName).\(name))" : "")"
}.joined(separator: "\n")

return """
var type: \(parenTypeName)\(SEALED_TYPE_SUFFIX) {
switch self {
\(allCasesSyntax)
default: fatalError("Unknown subclass")
}
}
"""
}
// private static func generateTypeProperty(parenTypeName: String, allCases: [ClassDeclSyntax]) -> String {
// let allCasesSyntax = allCases.map { eachCase in
// let name = eachCase.name.text
// return "case is \(parenTypeName).\(name): \(parenTypeName)\(SEALED_TYPE_SUFFIX).\(name)\(eachCase.isContainProperty ? "(self as! \(parenTypeName).\(name))" : "")"
// }.joined(separator: "\n")
//
// return """
// var type: \(parenTypeName)\(SEALED_TYPE_SUFFIX) {
// switch self {
// \(allCasesSyntax)
// default: fatalError("Unknown subclass")
// }
// }
// """
// }


private static func generateSealedTypesExtensions(
parenTypeName: String,
subTypeName: String,
subActionTypeName: String,
allCases: [ClassDeclSyntax]
) throws -> ExtensionDeclSyntax {
) -> String {
let allCasesSyntax = allCases.map { eachCase in
let name = eachCase.name.text
return "case is \(parenTypeName).\(name): \(parenTypeName).\(subActionTypeName)\(SEALED_TYPE_SUFFIX).\(name)\(eachCase.isContainProperty ? "(self as! \(parenTypeName).\(name))" : "")"
}.joined(separator: "\n")

return try ExtensionDeclSyntax(
return
"""
extension \(raw: subActionTypeName) {
var type: \(raw: parenTypeName).\(raw: subActionTypeName)\(raw: SEALED_TYPE_SUFFIX) {
var \(subActionTypeName.isEmpty ? "type" : "\(subActionTypeName.lowercased())Type"): \(parenTypeName).\(subActionTypeName)\(SEALED_TYPE_SUFFIX)? {
switch self {
\(raw: allCasesSyntax)
default: fatalError("Unknown \(raw: subActionTypeName) type")
}
\(allCasesSyntax)
default: nil
}
}
"""
)
}

}