Skip to content

Commit

Permalink
Update to Swift 5.9 (#134)
Browse files Browse the repository at this point in the history
* Fix unhandled files warnings

* Fix `NIOLock` deprecation warnings

* Update to Swift 5.9 and add `swiftSettings`

* Add MUSL and iOS to CI
  • Loading branch information
fpseverino authored Jan 22, 2025
1 parent 9295a0b commit 902c512
Show file tree
Hide file tree
Showing 14 changed files with 89 additions and 64 deletions.
7 changes: 5 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ env:

jobs:
unit-tests:
uses: vapor/ci/.github/workflows/run-unit-tests.yml@main
secrets: inherit
uses: vapor/ci/.github/workflows/run-unit-tests.yml@main
with:
with_musl: true
ios_scheme_name: leaf-kit
secrets: inherit

leaf-integration:
if: ${{ !(github.event.pull_request.draft || false) }}
Expand Down
40 changes: 31 additions & 9 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.4
// swift-tools-version:5.9
import PackageDescription

let package = Package(
Expand All @@ -10,17 +10,39 @@ let package = Package(
.watchOS(.v6),
],
products: [
.library(name: "LeafKit", targets: ["LeafKit"]),
.library(name: "LeafKit", targets: ["LeafKit"])
],
dependencies: [
.package(url: "https://github.com/apple/swift-nio.git", from: "2.2.0"),
.package(url: "https://github.com/apple/swift-nio.git", from: "2.2.0")
],
targets: [
.target(name: "LeafKit", dependencies: [
.product(name: "NIO", package: "swift-nio"),
]),
.testTarget(name: "LeafKitTests", dependencies: [
.target(name: "LeafKit"),
]),
.target(
name: "LeafKit",
dependencies: [
.product(name: "NIO", package: "swift-nio")
],
swiftSettings: swiftSettings
),
.testTarget(
name: "LeafKitTests",
dependencies: [
.target(name: "LeafKit")
],
resources: [
.copy("Templates")
],
swiftSettings: swiftSettings
),
]
)

var swiftSettings: [SwiftSetting] {
[
.enableUpcomingFeature("ExistentialAny"),
.enableUpcomingFeature("ConciseMagicFile"),
.enableUpcomingFeature("ForwardTrailingClosures"),
.enableUpcomingFeature("DisableOutwardActorInference"),
.enableUpcomingFeature("StrictConcurrency"),
.enableExperimentalFeature("StrictConcurrency=complete"),
]
}
8 changes: 4 additions & 4 deletions Sources/LeafKit/LeafCache/DefaultLeafCache.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public final class DefaultLeafCache: SynchronousLeafCache {
/// - Returns: The document provided as an identity return
public func insert(
_ document: LeafAST,
on loop: EventLoop,
on loop: any EventLoop,
replace: Bool = false
) -> EventLoopFuture<LeafAST> {
// future fails if caching is enabled
Expand All @@ -44,7 +44,7 @@ public final class DefaultLeafCache: SynchronousLeafCache {
/// - Returns: `EventLoopFuture<LeafAST?>` holding the `LeafAST` or nil if no matching result
public func retrieve(
documentName: String,
on loop: EventLoop
on loop: any EventLoop
) -> EventLoopFuture<LeafAST?> {
guard isEnabled == true else { return loop.makeSucceededFuture(nil) }
self.lock.lock()
Expand All @@ -59,7 +59,7 @@ public final class DefaultLeafCache: SynchronousLeafCache {
/// returns true. If cache can't remove because of dependencies (not yet possible), returns false.
public func remove(
_ documentName: String,
on loop: EventLoop
on loop: any EventLoop
) -> EventLoopFuture<Bool?> {
guard isEnabled == true else { return loop.makeFailedFuture(LeafError(.cachingDisabled)) }

Expand All @@ -73,7 +73,7 @@ public final class DefaultLeafCache: SynchronousLeafCache {

// MARK: - Internal Only

internal let lock: Lock
internal let lock: NIOLock
internal var cache: [String: LeafAST]

/// Blocking file load behavior
Expand Down
6 changes: 3 additions & 3 deletions Sources/LeafKit/LeafCache/LeafCache.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public protocol LeafCache {
/// - Returns: The document provided as an identity return (or a failed future if it can't be inserted)
func insert(
_ document: LeafAST,
on loop: EventLoop,
on loop: any EventLoop,
replace: Bool
) -> EventLoopFuture<LeafAST>

Expand All @@ -35,7 +35,7 @@ public protocol LeafCache {
/// - Returns: `EventLoopFuture<LeafAST?>` holding the `LeafAST` or nil if no matching result
func retrieve(
documentName: String,
on loop: EventLoop
on loop: any EventLoop
) -> EventLoopFuture<LeafAST?>

/// - Parameters:
Expand All @@ -45,7 +45,7 @@ public protocol LeafCache {
/// returns true. If cache can't remove because of dependencies (not yet possible), returns false.
func remove(
_ documentName: String,
on loop: EventLoop
on loop: any EventLoop
) -> EventLoopFuture<Bool?>
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/LeafKit/LeafData/LeafData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public struct LeafData: CustomStringConvertible,
}

// MARK: - Generic `LeafDataRepresentable` Initializer
public init(_ leafData: LeafDataRepresentable) { self = leafData.leafData }
public init(_ leafData: any LeafDataRepresentable) { self = leafData.leafData }

// MARK: - Static Initializer Conformances
/// Creates a new `LeafData` from a `Bool`.
Expand Down
14 changes: 7 additions & 7 deletions Sources/LeafKit/LeafRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,23 @@ public final class LeafRenderer {
/// A keyed dictionary of custom `LeafTags` to extend Leaf's basic functionality, registered
/// with the names which will call them when rendering - eg `tags["tagName"]` can be used
/// in a template as `#tagName(parameters)`
public let tags: [String: LeafTag]
public let tags: [String: any LeafTag]
/// A thread-safe implementation of `LeafCache` protocol
public let cache: LeafCache
public let cache: any LeafCache
/// A thread-safe implementation of `LeafSource` protocol
public let sources: LeafSources
/// The NIO `EventLoop` on which this instance of `LeafRenderer` will operate
public let eventLoop: EventLoop
public let eventLoop: any EventLoop
/// Any custom instance data to use (eg, in Vapor, the `Application` and/or `Request` data)
public let userInfo: [AnyHashable: Any]

/// Initial configuration of LeafRenderer.
public init(
configuration: LeafConfiguration,
tags: [String: LeafTag] = defaultTags,
cache: LeafCache = DefaultLeafCache(),
tags: [String: any LeafTag] = defaultTags,
cache: any LeafCache = DefaultLeafCache(),
sources: LeafSources,
eventLoop: EventLoop,
eventLoop: any EventLoop,
userInfo: [AnyHashable: Any] = [:]
) {
self.configuration = configuration
Expand Down Expand Up @@ -217,7 +217,7 @@ public final class LeafRenderer {

private func getFlatCachedHit(_ path: String) -> LeafAST? {
// If cache provides blocking load, try to get a flat AST immediately
guard let blockingCache = cache as? SynchronousLeafCache,
guard let blockingCache = cache as? any SynchronousLeafCache,
let cached = try? blockingCache.retrieve(documentName: path),
cached.flat else { return nil }
return cached
Expand Down
6 changes: 3 additions & 3 deletions Sources/LeafKit/LeafSerialize/LeafSerializer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ internal struct LeafSerializer {

init(
ast: [Syntax],
tags: [String: LeafTag] = defaultTags,
tags: [String: any LeafTag] = defaultTags,
userInfo: [AnyHashable: Any] = [:],
ignoreUnfoundImports: Bool

Expand Down Expand Up @@ -34,7 +34,7 @@ internal struct LeafSerializer {
private let ast: [Syntax]
private var offset: Int
private var buffer: ByteBuffer
private let tags: [String: LeafTag]
private let tags: [String: any LeafTag]
private let userInfo: [AnyHashable: Any]
private let ignoreUnfoundImports: Bool

Expand Down Expand Up @@ -94,7 +94,7 @@ internal struct LeafSerializer {

let leafData: LeafData

if foundTag is UnsafeUnescapedLeafTag {
if foundTag is any UnsafeUnescapedLeafTag {
leafData = try foundTag.render(sub)
} else {
leafData = try foundTag.render(sub).htmlEscaped()
Expand Down
2 changes: 1 addition & 1 deletion Sources/LeafKit/LeafSerialize/ParameterResolver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal struct ParameterResolver {

let params: [ParameterDeclaration]
let data: [String: LeafData]
let tags: [String: LeafTag]
let tags: [String: any LeafTag]
let userInfo: [AnyHashable: Any]

func resolve() throws -> [ResolvedParameter] {
Expand Down
2 changes: 1 addition & 1 deletion Sources/LeafKit/LeafSource/LeafSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ public protocol LeafSource {
/// template, or an appropriate failed state ELFuture (not found, illegal access, etc)
func file(template: String,
escape: Bool,
on eventLoop: EventLoop) throws -> EventLoopFuture<ByteBuffer>
on eventLoop: any EventLoop) throws -> EventLoopFuture<ByteBuffer>
}
12 changes: 6 additions & 6 deletions Sources/LeafKit/LeafSource/LeafSources.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public final class LeafSources {
/// - searchable: Whether the source should be added to the default search path
/// - Throws: Attempting to overwrite a previously named source is not permitted
public func register(source key: String = "default",
using source: LeafSource,
using source: any LeafSource,
searchable: Bool = true) throws {
try lock.withLock {
guard !sources.keys.contains(key) else { throw "Can't replace source at \(key)" }
Expand All @@ -43,19 +43,19 @@ public final class LeafSources {
/// Convenience for initializing a `LeafSources` object with a single `LeafSource`
/// - Parameter source: A fully configured `LeafSource`
/// - Returns: Configured `LeafSource` instance
public static func singleSource(_ source: LeafSource) -> LeafSources {
public static func singleSource(_ source: any LeafSource) -> LeafSources {
let sources = LeafSources()
try! sources.register(using: source)
return sources
}

// MARK: - Internal Only
internal private(set) var sources: [String: LeafSource]
internal private(set) var sources: [String: any LeafSource]
private var order: [String]
private let lock: Lock = .init()
private let lock: NIOLock = .init()

/// Locate a template from the sources; if a specific source is named, only try to read from it. Otherwise, use the specified search order
internal func find(template: String, in source: String? = nil, on eventLoop: EventLoop) throws -> EventLoopFuture<(String, ByteBuffer)> {
internal func find(template: String, in source: String? = nil, on eventLoop: any EventLoop) throws -> EventLoopFuture<(String, ByteBuffer)> {
var keys: [String]

switch source {
Expand All @@ -69,7 +69,7 @@ public final class LeafSources {
return searchSources(t: template, on: eventLoop, s: keys)
}

private func searchSources(t: String, on eL: EventLoop, s: [String]) -> EventLoopFuture<(String, ByteBuffer)> {
private func searchSources(t: String, on eL: any EventLoop, s: [String]) -> EventLoopFuture<(String, ByteBuffer)> {
guard !s.isEmpty else { return eL.makeFailedFuture(LeafError(.noTemplateExists(t))) }
var more = s
let key = more.removeFirst()
Expand Down
4 changes: 2 additions & 2 deletions Sources/LeafKit/LeafSource/NIOLeafFiles.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public struct NIOLeafFiles: LeafSource {
/// - eventLoop: `EventLoop` on which to perform file access
/// - Returns: A succeeded `EventLoopFuture` holding a `ByteBuffer` with the raw
/// template, or an appropriate failed state ELFuture (not found, illegal access, etc)
public func file(template: String, escape: Bool = false, on eventLoop: EventLoop) throws -> EventLoopFuture<ByteBuffer> {
public func file(template: String, escape: Bool = false, on eventLoop: any EventLoop) throws -> EventLoopFuture<ByteBuffer> {
var template = URL(fileURLWithPath: sandbox + viewRelative + template, isDirectory: false).standardized.path
/// If default extension is enforced for template files, add it if it's not on the file, or if no extension present
if limits.contains(.onlyLeafExtensions), !template.hasSuffix(".\(self.extension)")
Expand Down Expand Up @@ -108,7 +108,7 @@ public struct NIOLeafFiles: LeafSource {
internal let `extension`: String

/// Attempt to read a fully pathed template and return a ByteBuffer or fail
private func read(path: String, on eventLoop: EventLoop) -> EventLoopFuture<ByteBuffer> {
private func read(path: String, on eventLoop: any EventLoop) -> EventLoopFuture<ByteBuffer> {
let openFile = self.fileio.openFile(path: path, eventLoop: eventLoop)
return openFile.flatMapErrorThrowing { error in
throw LeafError(.noTemplateExists(path))
Expand Down
36 changes: 18 additions & 18 deletions Sources/LeafKit/LeafSyntax/LeafSyntax.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,25 +81,25 @@ public enum ConditionalSyntax {
extension Syntax: BodiedSyntax {
internal func externals() -> Set<String> {
switch self {
case .conditional(let bS as BodiedSyntax),
.custom(let bS as BodiedSyntax),
.export(let bS as BodiedSyntax),
.extend(let bS as BodiedSyntax),
.with(let bS as BodiedSyntax),
.loop(let bS as BodiedSyntax): return bS.externals()
case .conditional(let bS as any BodiedSyntax),
.custom(let bS as any BodiedSyntax),
.export(let bS as any BodiedSyntax),
.extend(let bS as any BodiedSyntax),
.with(let bS as any BodiedSyntax),
.loop(let bS as any BodiedSyntax): return bS.externals()
default: return .init()
}
}

internal func imports() -> Set<String> {
switch self {
case .import(let i): return .init(arrayLiteral: i.key)
case .conditional(let bS as BodiedSyntax),
.custom(let bS as BodiedSyntax),
.export(let bS as BodiedSyntax),
.extend(let bS as BodiedSyntax),
.expression(let bS as BodiedSyntax),
.loop(let bS as BodiedSyntax): return bS.imports()
case .conditional(let bS as any BodiedSyntax),
.custom(let bS as any BodiedSyntax),
.export(let bS as any BodiedSyntax),
.extend(let bS as any BodiedSyntax),
.expression(let bS as any BodiedSyntax),
.loop(let bS as any BodiedSyntax): return bS.imports()
// .variable, .raw
default: return .init()
}
Expand All @@ -122,12 +122,12 @@ extension Syntax: BodiedSyntax {
result.append(self)
}
// Recursively inline single Syntaxes
case .conditional(let bS as BodiedSyntax),
.custom(let bS as BodiedSyntax),
.export(let bS as BodiedSyntax),
.extend(let bS as BodiedSyntax),
.with(let bS as BodiedSyntax),
.loop(let bS as BodiedSyntax): result += bS.inlineRefs(externals, imports)
case .conditional(let bS as any BodiedSyntax),
.custom(let bS as any BodiedSyntax),
.export(let bS as any BodiedSyntax),
.extend(let bS as any BodiedSyntax),
.with(let bS as any BodiedSyntax),
.loop(let bS as any BodiedSyntax): result += bS.inlineRefs(externals, imports)
case .expression(let pDA): result.append(.expression(pDA.inlineImports(imports)))
// .variable, .raw
default: result.append(self)
Expand Down
2 changes: 1 addition & 1 deletion Sources/LeafKit/LeafSyntax/LeafTag.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public protocol LeafTag {
/// Tags conforming to this protocol do not get their contents HTML-escaped.
public protocol UnsafeUnescapedLeafTag: LeafTag {}

public var defaultTags: [String: LeafTag] = [
public var defaultTags: [String: any LeafTag] = [
"unsafeHTML": UnsafeHTML(),
"lowercased": Lowercased(),
"uppercased": Uppercased(),
Expand Down
12 changes: 6 additions & 6 deletions Tests/LeafKitTests/TestHelpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,14 @@ internal func render(name: String = "test-render", _ template: String, _ context
/// Helper wrapping` LeafRenderer` to preconfigure for simplicity & allow eliding context
internal class TestRenderer {
var r: LeafRenderer
private let lock: Lock
private let lock: NIOLock
private var counter: Int = 0

init(configuration: LeafConfiguration = .init(rootDirectory: "/"),
tags: [String : LeafTag] = defaultTags,
cache: LeafCache = DefaultLeafCache(),
tags: [String : any LeafTag] = defaultTags,
cache: any LeafCache = DefaultLeafCache(),
sources: LeafSources = .singleSource(TestFiles()),
eventLoop: EventLoop = EmbeddedEventLoop(),
eventLoop: any EventLoop = EmbeddedEventLoop(),
userInfo: [AnyHashable : Any] = [:]) {
self.r = .init(configuration: configuration,
tags: tags,
Expand Down Expand Up @@ -88,14 +88,14 @@ internal class TestRenderer {
/// Helper `LeafFiles` struct providing an in-memory thread-safe map of "file names" to "file data"
internal struct TestFiles: LeafSource {
var files: [String: String]
var lock: Lock
var lock: NIOLock

init() {
files = [:]
lock = .init()
}

public func file(template: String, escape: Bool = false, on eventLoop: EventLoop) -> EventLoopFuture<ByteBuffer> {
public func file(template: String, escape: Bool = false, on eventLoop: any EventLoop) -> EventLoopFuture<ByteBuffer> {
var path = template
if path.split(separator: "/").last?.split(separator: ".").count ?? 1 < 2,
!path.hasSuffix(".leaf") { path += ".leaf" }
Expand Down

0 comments on commit 902c512

Please sign in to comment.