Skip to content

Commit

Permalink
Swift Macros (#9)
Browse files Browse the repository at this point in the history
* Keep log file in root of volume for controlling installed versions.

* Add several new resources

* Integrate macros. Fix test plan.
  • Loading branch information
diegotl authored Oct 20, 2023
1 parent 5393848 commit 680ddfd
Show file tree
Hide file tree
Showing 12 changed files with 189 additions and 18 deletions.
4 changes: 4 additions & 0 deletions Empusa.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
3F3B176D2ADDE117000283AE /* DestinationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DestinationView.swift; sourceTree = "<group>"; };
3F3B176F2ADDE16A000283AE /* ResourcesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourcesView.swift; sourceTree = "<group>"; };
3F3B17712ADDE25D000283AE /* DataProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataProgressView.swift; sourceTree = "<group>"; };
3F54EB962AE2553D008A45B0 /* Empusa.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = Empusa.xctestplan; sourceTree = "<group>"; };
3FC172272AE1D63A00DCBE28 /* EmpusaMacros */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = EmpusaMacros; sourceTree = "<group>"; };
3FCE9D2E2AE0FE2E00A4E3F5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3FCE9D302AE17F5F00A4E3F5 /* CheckForUpdatesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckForUpdatesView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
Expand Down Expand Up @@ -104,6 +106,7 @@
3F21D31B2ADADC7400B6A5D9 /* Tests */ = {
isa = PBXGroup;
children = (
3F54EB962AE2553D008A45B0 /* Empusa.xctestplan */,
3F21D31C2ADADC7400B6A5D9 /* EmpusaTests.swift */,
);
path = Tests;
Expand All @@ -121,6 +124,7 @@
3F21D3362ADADE8B00B6A5D9 /* Packages */ = {
isa = PBXGroup;
children = (
3FC172272AE1D63A00DCBE28 /* EmpusaMacros */,
3F21D3372ADADEBE00B6A5D9 /* EmpusaKit */,
);
path = Packages;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@
"version" : "2.5.1"
}
},
{
"identity" : "swift-syntax",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-syntax.git",
"state" : {
"revision" : "74203046135342e4a4a627476dd6caf8b28fe11b",
"version" : "509.0.0"
}
},
{
"identity" : "zip",
"kind" : "remoteSourceControl",
Expand Down
2 changes: 1 addition & 1 deletion Empusa.xcodeproj/xcshareddata/xcschemes/Empusa.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
shouldUseLaunchSchemeArgsEnv = "YES">
<TestPlans>
<TestPlanReference
reference = "container:Empusa Tests/Empusa.xctestplan"
reference = "container:Tests/Empusa.xctestplan"
default = "YES">
</TestPlanReference>
</TestPlans>
Expand Down
6 changes: 4 additions & 2 deletions Packages/EmpusaKit/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ let package = Package(
targets: ["EmpusaKit"]),
],
dependencies: [
.package(url: "https://github.com/marmelroy/Zip.git", from: "2.1.2")
.package(url: "https://github.com/marmelroy/Zip.git", from: "2.1.2"),
.package(path: "../EmpusaMacros")
],
targets: [
.target(
name: "EmpusaKit",
dependencies: [
.product(name: "Zip", package: "Zip")
.product(name: "Zip", package: "Zip"),
.product(name: "EmpusaMacros", package: "EmpusaMacros")
]
),
.testTarget(
Expand Down
31 changes: 16 additions & 15 deletions Packages/EmpusaKit/Sources/EmpusaKit/Models/SwitchResource.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Foundation
import Combine
import EmpusaMacros

// MARK: - DisplayingSwitchResource

Expand Down Expand Up @@ -67,77 +68,77 @@ public enum SwitchResource: String, Codable, CaseIterable {
switch self {
case .hekate:
.github(
.init(string: "https://api.github.com/repos/CTCaer/hekate/releases/latest")!,
#URL("https://api.github.com/repos/CTCaer/hekate/releases/latest"),
assetPrefix: "hekate_ctcaer_"
)
case .hekateIPL:
.link(
.init(string: "https://nh-server.github.io/switch-guide/files/emu/hekate_ipl.ini")!,
#URL("https://nh-server.github.io/switch-guide/files/emu/hekate_ipl.ini"),
version: nil
)
case .atmosphere:
.github(
.init(string: "https://api.github.com/repos/Atmosphere-NX/Atmosphere/releases/latest")!,
#URL("https://api.github.com/repos/Atmosphere-NX/Atmosphere/releases/latest"),
assetPrefix: "atmosphere-"
)
case .fusee:
.github(
.init(string: "https://api.github.com/repos/Atmosphere-NX/Atmosphere/releases/latest")!,
#URL("https://api.github.com/repos/Atmosphere-NX/Atmosphere/releases/latest"),
assetPrefix: "fusee.bin"
)
case .sigpatches:
.link(
.init(string: "https://sigmapatches.coomer.party/sigpatches.zip")!,
#URL("https://sigmapatches.coomer.party/sigpatches.zip"),
version: "16.1.0"
)
case .tinfoil:
.github(
.init(string: "https://api.github.com/repos/kkkkyue/Tinfoil/releases/latest")!,
#URL("https://api.github.com/repos/kkkkyue/Tinfoil/releases/latest"),
assetPrefix: "Tinfoil.Self.Installer"
)
case .bootLogos:
.link(
.init(string: "https://nh-server.github.io/switch-guide/files/bootlogos.zip")!,
#URL("https://nh-server.github.io/switch-guide/files/bootlogos.zip"),
version: nil
)
case .emummc:
.link(
.init(string: "https://nh-server.github.io/switch-guide/files/emummc.txt")!,
#URL("https://nh-server.github.io/switch-guide/files/emummc.txt"),
version: nil
)
case .lockpickRCM:
.forgejo(
.init(string: "https://vps.suchmeme.nl/git/api/v1/repos/mudkip/Lockpick_RCM/releases/latest")!,
#URL("https://vps.suchmeme.nl/git/api/v1/repos/mudkip/Lockpick_RCM/releases/latest"),
assetPrefix: "Lockpick_RCM.bin"
)
case .hbAppStore:
.github(
.init(string: "https://api.github.com/repos/fortheusers/hb-appstore/releases/latest")!,
#URL("https://api.github.com/repos/fortheusers/hb-appstore/releases/latest"),
assetPrefix: "appstore.nro"
)
case .jksv:
.github(
.init(string: "https://api.github.com/repos/J-D-K/JKSV/releases/latest")!,
#URL("https://api.github.com/repos/J-D-K/JKSV/releases/latest"),
assetPrefix: "JKSV.nro"
)
case .ftpd:
.github(
.init(string: "https://api.github.com/repos/mtheall/ftpd/releases/latest")!,
#URL("https://api.github.com/repos/mtheall/ftpd/releases/latest"),
assetPrefix: "ftpd.nro"
)
case .nxThemesInstaller:
.github(
.init(string: "https://api.github.com/repos/exelix11/SwitchThemeInjector/releases/latest")!,
#URL("https://api.github.com/repos/exelix11/SwitchThemeInjector/releases/latest"),
assetPrefix: "NXThemesInstaller.nro"
)
case .nxShell:
.github(
.init(string: "https://api.github.com/repos/joel16/NX-Shell/releases/latest")!,
#URL("https://api.github.com/repos/joel16/NX-Shell/releases/latest"),
assetPrefix: "NX-Shell.nro"
)
case .goldleaf:
.github(
.init(string: "https://api.github.com/repos/XorTroll/Goldleaf/releases/latest")!,
#URL("https://api.github.com/repos/XorTroll/Goldleaf/releases/latest"),
assetPrefix: "Goldleaf.nro"
)
}
Expand Down
8 changes: 8 additions & 0 deletions Packages/EmpusaMacros/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.DS_Store
/.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
45 changes: 45 additions & 0 deletions Packages/EmpusaMacros/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription
import CompilerPluginSupport

let package = Package(
name: "EmpusaMacros",
platforms: [.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6), .macCatalyst(.v13)],
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
name: "EmpusaMacros",
targets: ["EmpusaMacros"]
),
],
dependencies: [
// Depend on the Swift 5.9 release of SwiftSyntax
.package(url: "https://github.com/apple/swift-syntax.git", from: "509.0.0"),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
// Macro implementation that performs the source transformation of a macro.
.macro(
name: "EmpusaMacrosImpl",
dependencies: [
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
.product(name: "SwiftCompilerPlugin", package: "swift-syntax")
]
),

// Library that exposes a macro as part of its API, which is used in client programs.
.target(name: "EmpusaMacros", dependencies: ["EmpusaMacrosImpl"]),

// A test target used to develop the macro implementation.
.testTarget(
name: "EmpusaMacrosTests",
dependencies: [
"EmpusaMacrosImpl",
.product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"),
]
),
]
)
4 changes: 4 additions & 0 deletions Packages/EmpusaMacros/Sources/EmpusaMacros/EmpusaMacros.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Foundation

@freestanding(expression)
public macro URL(_ stringLiteral: String) -> URL = #externalMacro(module: "EmpusaMacrosImpl", type: "URLMacro")
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import SwiftCompilerPlugin
import SwiftSyntax
import SwiftSyntaxBuilder
import SwiftSyntaxMacros

@main
struct EmpusaMacrosPlugin: CompilerPlugin {
let providingMacros: [Macro.Type] = [
URLMacro.self
]
}
41 changes: 41 additions & 0 deletions Packages/EmpusaMacros/Sources/EmpusaMacrosImpl/URLMacro.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import Foundation
import SwiftCompilerPlugin
import SwiftSyntax
import SwiftSyntaxBuilder
import SwiftSyntaxMacros

enum URLMacroError: Error, CustomStringConvertible {
case requiresStaticStringLiteral
case malformedURL(urlString: String)

var description: String {
switch self {
case .requiresStaticStringLiteral:
return "#URL requires a static string literal"
case .malformedURL(let urlString):
return "The input URL is malformed: \(urlString)"
}
}
}

public struct URLMacro: ExpressionMacro {
public static func expansion(
of node: some FreestandingMacroExpansionSyntax,
in context: some MacroExpansionContext
) throws -> ExprSyntax {
guard
let argument = node.argumentList.first?.expression,
let segments = argument.as(StringLiteralExprSyntax.self)?.segments,
segments.count == 1,
case .stringSegment(let literalSegment)? = segments.first
else {
throw URLMacroError.requiresStaticStringLiteral
}

guard let _ = URL(string: literalSegment.content.text) else {
throw URLMacroError.malformedURL(urlString: "\(argument)")
}

return "URL(string: \(argument))!"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import SwiftSyntaxMacros
import SwiftSyntaxMacrosTestSupport
import XCTest

// Macro implementations build for the host, so the corresponding module is not available when cross-compiling. Cross-compiled tests may still make use of the macro itself in end-to-end tests.
#if canImport(EmpusaMacrosMacros)
import EmpusaMacrosMacros

let testMacros: [String: Macro.Type] = [
"stringify": StringifyMacro.self,
]
#endif

final class EmpusaMacrosTests: XCTestCase {
func testMacro() throws {
#if canImport(EmpusaMacrosMacros)
assertMacroExpansion(
"""
#stringify(a + b)
""",
expandedSource: """
(a + b, "a + b")
""",
macros: testMacros
)
#else
throw XCTSkip("macros are only supported when running tests for the host platform")
#endif
}

func testMacroWithStringLiteral() throws {
#if canImport(EmpusaMacrosMacros)
assertMacroExpansion(
#"""
#stringify("Hello, \(name)")
"""#,
expandedSource: #"""
("Hello, \(name)", #""Hello, \(name)""#)
"""#,
macros: testMacros
)
#else
throw XCTSkip("macros are only supported when running tests for the host platform")
#endif
}
}
File renamed without changes.

0 comments on commit 680ddfd

Please sign in to comment.