Skip to content

Commit 902c512

Browse files
authored
Update to Swift 5.9 (#134)
* Fix unhandled files warnings * Fix `NIOLock` deprecation warnings * Update to Swift 5.9 and add `swiftSettings` * Add MUSL and iOS to CI
1 parent 9295a0b commit 902c512

14 files changed

+89
-64
lines changed

.github/workflows/test.yml

+5-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ env:
1010

1111
jobs:
1212
unit-tests:
13-
uses: vapor/ci/.github/workflows/run-unit-tests.yml@main
14-
secrets: inherit
13+
uses: vapor/ci/.github/workflows/run-unit-tests.yml@main
14+
with:
15+
with_musl: true
16+
ios_scheme_name: leaf-kit
17+
secrets: inherit
1518

1619
leaf-integration:
1720
if: ${{ !(github.event.pull_request.draft || false) }}

Package.swift

+31-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version:5.4
1+
// swift-tools-version:5.9
22
import PackageDescription
33

44
let package = Package(
@@ -10,17 +10,39 @@ let package = Package(
1010
.watchOS(.v6),
1111
],
1212
products: [
13-
.library(name: "LeafKit", targets: ["LeafKit"]),
13+
.library(name: "LeafKit", targets: ["LeafKit"])
1414
],
1515
dependencies: [
16-
.package(url: "https://github.com/apple/swift-nio.git", from: "2.2.0"),
16+
.package(url: "https://github.com/apple/swift-nio.git", from: "2.2.0")
1717
],
1818
targets: [
19-
.target(name: "LeafKit", dependencies: [
20-
.product(name: "NIO", package: "swift-nio"),
21-
]),
22-
.testTarget(name: "LeafKitTests", dependencies: [
23-
.target(name: "LeafKit"),
24-
]),
19+
.target(
20+
name: "LeafKit",
21+
dependencies: [
22+
.product(name: "NIO", package: "swift-nio")
23+
],
24+
swiftSettings: swiftSettings
25+
),
26+
.testTarget(
27+
name: "LeafKitTests",
28+
dependencies: [
29+
.target(name: "LeafKit")
30+
],
31+
resources: [
32+
.copy("Templates")
33+
],
34+
swiftSettings: swiftSettings
35+
),
2536
]
2637
)
38+
39+
var swiftSettings: [SwiftSetting] {
40+
[
41+
.enableUpcomingFeature("ExistentialAny"),
42+
.enableUpcomingFeature("ConciseMagicFile"),
43+
.enableUpcomingFeature("ForwardTrailingClosures"),
44+
.enableUpcomingFeature("DisableOutwardActorInference"),
45+
.enableUpcomingFeature("StrictConcurrency"),
46+
.enableExperimentalFeature("StrictConcurrency=complete"),
47+
]
48+
}

Sources/LeafKit/LeafCache/DefaultLeafCache.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public final class DefaultLeafCache: SynchronousLeafCache {
2222
/// - Returns: The document provided as an identity return
2323
public func insert(
2424
_ document: LeafAST,
25-
on loop: EventLoop,
25+
on loop: any EventLoop,
2626
replace: Bool = false
2727
) -> EventLoopFuture<LeafAST> {
2828
// future fails if caching is enabled
@@ -44,7 +44,7 @@ public final class DefaultLeafCache: SynchronousLeafCache {
4444
/// - Returns: `EventLoopFuture<LeafAST?>` holding the `LeafAST` or nil if no matching result
4545
public func retrieve(
4646
documentName: String,
47-
on loop: EventLoop
47+
on loop: any EventLoop
4848
) -> EventLoopFuture<LeafAST?> {
4949
guard isEnabled == true else { return loop.makeSucceededFuture(nil) }
5050
self.lock.lock()
@@ -59,7 +59,7 @@ public final class DefaultLeafCache: SynchronousLeafCache {
5959
/// returns true. If cache can't remove because of dependencies (not yet possible), returns false.
6060
public func remove(
6161
_ documentName: String,
62-
on loop: EventLoop
62+
on loop: any EventLoop
6363
) -> EventLoopFuture<Bool?> {
6464
guard isEnabled == true else { return loop.makeFailedFuture(LeafError(.cachingDisabled)) }
6565

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

7474
// MARK: - Internal Only
7575

76-
internal let lock: Lock
76+
internal let lock: NIOLock
7777
internal var cache: [String: LeafAST]
7878

7979
/// Blocking file load behavior

Sources/LeafKit/LeafCache/LeafCache.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public protocol LeafCache {
2525
/// - Returns: The document provided as an identity return (or a failed future if it can't be inserted)
2626
func insert(
2727
_ document: LeafAST,
28-
on loop: EventLoop,
28+
on loop: any EventLoop,
2929
replace: Bool
3030
) -> EventLoopFuture<LeafAST>
3131

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

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

Sources/LeafKit/LeafData/LeafData.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ public struct LeafData: CustomStringConvertible,
105105
}
106106

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

110110
// MARK: - Static Initializer Conformances
111111
/// Creates a new `LeafData` from a `Bool`.

Sources/LeafKit/LeafRenderer.swift

+7-7
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,23 @@ public final class LeafRenderer {
1818
/// A keyed dictionary of custom `LeafTags` to extend Leaf's basic functionality, registered
1919
/// with the names which will call them when rendering - eg `tags["tagName"]` can be used
2020
/// in a template as `#tagName(parameters)`
21-
public let tags: [String: LeafTag]
21+
public let tags: [String: any LeafTag]
2222
/// A thread-safe implementation of `LeafCache` protocol
23-
public let cache: LeafCache
23+
public let cache: any LeafCache
2424
/// A thread-safe implementation of `LeafSource` protocol
2525
public let sources: LeafSources
2626
/// The NIO `EventLoop` on which this instance of `LeafRenderer` will operate
27-
public let eventLoop: EventLoop
27+
public let eventLoop: any EventLoop
2828
/// Any custom instance data to use (eg, in Vapor, the `Application` and/or `Request` data)
2929
public let userInfo: [AnyHashable: Any]
3030

3131
/// Initial configuration of LeafRenderer.
3232
public init(
3333
configuration: LeafConfiguration,
34-
tags: [String: LeafTag] = defaultTags,
35-
cache: LeafCache = DefaultLeafCache(),
34+
tags: [String: any LeafTag] = defaultTags,
35+
cache: any LeafCache = DefaultLeafCache(),
3636
sources: LeafSources,
37-
eventLoop: EventLoop,
37+
eventLoop: any EventLoop,
3838
userInfo: [AnyHashable: Any] = [:]
3939
) {
4040
self.configuration = configuration
@@ -217,7 +217,7 @@ public final class LeafRenderer {
217217

218218
private func getFlatCachedHit(_ path: String) -> LeafAST? {
219219
// If cache provides blocking load, try to get a flat AST immediately
220-
guard let blockingCache = cache as? SynchronousLeafCache,
220+
guard let blockingCache = cache as? any SynchronousLeafCache,
221221
let cached = try? blockingCache.retrieve(documentName: path),
222222
cached.flat else { return nil }
223223
return cached

Sources/LeafKit/LeafSerialize/LeafSerializer.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ internal struct LeafSerializer {
55

66
init(
77
ast: [Syntax],
8-
tags: [String: LeafTag] = defaultTags,
8+
tags: [String: any LeafTag] = defaultTags,
99
userInfo: [AnyHashable: Any] = [:],
1010
ignoreUnfoundImports: Bool
1111

@@ -34,7 +34,7 @@ internal struct LeafSerializer {
3434
private let ast: [Syntax]
3535
private var offset: Int
3636
private var buffer: ByteBuffer
37-
private let tags: [String: LeafTag]
37+
private let tags: [String: any LeafTag]
3838
private let userInfo: [AnyHashable: Any]
3939
private let ignoreUnfoundImports: Bool
4040

@@ -94,7 +94,7 @@ internal struct LeafSerializer {
9494

9595
let leafData: LeafData
9696

97-
if foundTag is UnsafeUnescapedLeafTag {
97+
if foundTag is any UnsafeUnescapedLeafTag {
9898
leafData = try foundTag.render(sub)
9999
} else {
100100
leafData = try foundTag.render(sub).htmlEscaped()

Sources/LeafKit/LeafSerialize/ParameterResolver.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ internal struct ParameterResolver {
1414

1515
let params: [ParameterDeclaration]
1616
let data: [String: LeafData]
17-
let tags: [String: LeafTag]
17+
let tags: [String: any LeafTag]
1818
let userInfo: [AnyHashable: Any]
1919

2020
func resolve() throws -> [ResolvedParameter] {

Sources/LeafKit/LeafSource/LeafSource.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ public protocol LeafSource {
1212
/// template, or an appropriate failed state ELFuture (not found, illegal access, etc)
1313
func file(template: String,
1414
escape: Bool,
15-
on eventLoop: EventLoop) throws -> EventLoopFuture<ByteBuffer>
15+
on eventLoop: any EventLoop) throws -> EventLoopFuture<ByteBuffer>
1616
}

Sources/LeafKit/LeafSource/LeafSources.swift

+6-6
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public final class LeafSources {
3131
/// - searchable: Whether the source should be added to the default search path
3232
/// - Throws: Attempting to overwrite a previously named source is not permitted
3333
public func register(source key: String = "default",
34-
using source: LeafSource,
34+
using source: any LeafSource,
3535
searchable: Bool = true) throws {
3636
try lock.withLock {
3737
guard !sources.keys.contains(key) else { throw "Can't replace source at \(key)" }
@@ -43,19 +43,19 @@ public final class LeafSources {
4343
/// Convenience for initializing a `LeafSources` object with a single `LeafSource`
4444
/// - Parameter source: A fully configured `LeafSource`
4545
/// - Returns: Configured `LeafSource` instance
46-
public static func singleSource(_ source: LeafSource) -> LeafSources {
46+
public static func singleSource(_ source: any LeafSource) -> LeafSources {
4747
let sources = LeafSources()
4848
try! sources.register(using: source)
4949
return sources
5050
}
5151

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

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

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

72-
private func searchSources(t: String, on eL: EventLoop, s: [String]) -> EventLoopFuture<(String, ByteBuffer)> {
72+
private func searchSources(t: String, on eL: any EventLoop, s: [String]) -> EventLoopFuture<(String, ByteBuffer)> {
7373
guard !s.isEmpty else { return eL.makeFailedFuture(LeafError(.noTemplateExists(t))) }
7474
var more = s
7575
let key = more.removeFirst()

Sources/LeafKit/LeafSource/NIOLeafFiles.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public struct NIOLeafFiles: LeafSource {
6969
/// - eventLoop: `EventLoop` on which to perform file access
7070
/// - Returns: A succeeded `EventLoopFuture` holding a `ByteBuffer` with the raw
7171
/// template, or an appropriate failed state ELFuture (not found, illegal access, etc)
72-
public func file(template: String, escape: Bool = false, on eventLoop: EventLoop) throws -> EventLoopFuture<ByteBuffer> {
72+
public func file(template: String, escape: Bool = false, on eventLoop: any EventLoop) throws -> EventLoopFuture<ByteBuffer> {
7373
var template = URL(fileURLWithPath: sandbox + viewRelative + template, isDirectory: false).standardized.path
7474
/// If default extension is enforced for template files, add it if it's not on the file, or if no extension present
7575
if limits.contains(.onlyLeafExtensions), !template.hasSuffix(".\(self.extension)")
@@ -108,7 +108,7 @@ public struct NIOLeafFiles: LeafSource {
108108
internal let `extension`: String
109109

110110
/// Attempt to read a fully pathed template and return a ByteBuffer or fail
111-
private func read(path: String, on eventLoop: EventLoop) -> EventLoopFuture<ByteBuffer> {
111+
private func read(path: String, on eventLoop: any EventLoop) -> EventLoopFuture<ByteBuffer> {
112112
let openFile = self.fileio.openFile(path: path, eventLoop: eventLoop)
113113
return openFile.flatMapErrorThrowing { error in
114114
throw LeafError(.noTemplateExists(path))

Sources/LeafKit/LeafSyntax/LeafSyntax.swift

+18-18
Original file line numberDiff line numberDiff line change
@@ -81,25 +81,25 @@ public enum ConditionalSyntax {
8181
extension Syntax: BodiedSyntax {
8282
internal func externals() -> Set<String> {
8383
switch self {
84-
case .conditional(let bS as BodiedSyntax),
85-
.custom(let bS as BodiedSyntax),
86-
.export(let bS as BodiedSyntax),
87-
.extend(let bS as BodiedSyntax),
88-
.with(let bS as BodiedSyntax),
89-
.loop(let bS as BodiedSyntax): return bS.externals()
84+
case .conditional(let bS as any BodiedSyntax),
85+
.custom(let bS as any BodiedSyntax),
86+
.export(let bS as any BodiedSyntax),
87+
.extend(let bS as any BodiedSyntax),
88+
.with(let bS as any BodiedSyntax),
89+
.loop(let bS as any BodiedSyntax): return bS.externals()
9090
default: return .init()
9191
}
9292
}
9393

9494
internal func imports() -> Set<String> {
9595
switch self {
9696
case .import(let i): return .init(arrayLiteral: i.key)
97-
case .conditional(let bS as BodiedSyntax),
98-
.custom(let bS as BodiedSyntax),
99-
.export(let bS as BodiedSyntax),
100-
.extend(let bS as BodiedSyntax),
101-
.expression(let bS as BodiedSyntax),
102-
.loop(let bS as BodiedSyntax): return bS.imports()
97+
case .conditional(let bS as any BodiedSyntax),
98+
.custom(let bS as any BodiedSyntax),
99+
.export(let bS as any BodiedSyntax),
100+
.extend(let bS as any BodiedSyntax),
101+
.expression(let bS as any BodiedSyntax),
102+
.loop(let bS as any BodiedSyntax): return bS.imports()
103103
// .variable, .raw
104104
default: return .init()
105105
}
@@ -122,12 +122,12 @@ extension Syntax: BodiedSyntax {
122122
result.append(self)
123123
}
124124
// Recursively inline single Syntaxes
125-
case .conditional(let bS as BodiedSyntax),
126-
.custom(let bS as BodiedSyntax),
127-
.export(let bS as BodiedSyntax),
128-
.extend(let bS as BodiedSyntax),
129-
.with(let bS as BodiedSyntax),
130-
.loop(let bS as BodiedSyntax): result += bS.inlineRefs(externals, imports)
125+
case .conditional(let bS as any BodiedSyntax),
126+
.custom(let bS as any BodiedSyntax),
127+
.export(let bS as any BodiedSyntax),
128+
.extend(let bS as any BodiedSyntax),
129+
.with(let bS as any BodiedSyntax),
130+
.loop(let bS as any BodiedSyntax): result += bS.inlineRefs(externals, imports)
131131
case .expression(let pDA): result.append(.expression(pDA.inlineImports(imports)))
132132
// .variable, .raw
133133
default: result.append(self)

Sources/LeafKit/LeafSyntax/LeafTag.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public protocol LeafTag {
88
/// Tags conforming to this protocol do not get their contents HTML-escaped.
99
public protocol UnsafeUnescapedLeafTag: LeafTag {}
1010

11-
public var defaultTags: [String: LeafTag] = [
11+
public var defaultTags: [String: any LeafTag] = [
1212
"unsafeHTML": UnsafeHTML(),
1313
"lowercased": Lowercased(),
1414
"uppercased": Uppercased(),

Tests/LeafKitTests/TestHelpers.swift

+6-6
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,14 @@ internal func render(name: String = "test-render", _ template: String, _ context
4949
/// Helper wrapping` LeafRenderer` to preconfigure for simplicity & allow eliding context
5050
internal class TestRenderer {
5151
var r: LeafRenderer
52-
private let lock: Lock
52+
private let lock: NIOLock
5353
private var counter: Int = 0
5454

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

9393
init() {
9494
files = [:]
9595
lock = .init()
9696
}
9797

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

0 commit comments

Comments
 (0)