Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Make project Swift 6 compatible #1091

Draft
wants to merge 25 commits into
base: master
Choose a base branch
from
Draft
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
11 changes: 7 additions & 4 deletions Commons/Package.swift
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
// swift-tools-version:5.9
// swift-tools-version: 6.0

import PackageDescription

let package = Package(
name: "Commons",
platforms: [.macOS(.v12)],
platforms: [.macOS(.v13)],
products: [
.library(name: "Commons", targets: ["Commons", "CommonsObjC"]),
],
dependencies: [
.package(url: "https://github.com/Quick/Nimble", from: "13.4.0"),
.package(url: "https://github.com/Quick/Nimble", from: "13.7.1"),
.package(url: "https://github.com/ReactiveX/RxSwift", from: "6.8.0"),
],
targets: [
.target(name: "Commons", dependencies: []),
.target(name: "Commons", dependencies: [
.product(name: "RxSwift", package: "RxSwift"),
]),
.target(name: "CommonsObjC", dependencies: []),
.testTarget(
name: "CommonsTests",
Expand Down
4 changes: 2 additions & 2 deletions Commons/Sources/Commons/ConditionVariable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

import Foundation

public final class ConditionVariable {
private(set) var posted: Bool
public final class ConditionVariable: Sendable {
private(set) nonisolated(unsafe) var posted: Bool

public init(posted: Bool = false) {
self.posted = posted
Expand Down
46 changes: 44 additions & 2 deletions Commons/Sources/Commons/FifoCache.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,48 @@
*/

import Foundation
import os

public final class ThreadSafeFifoCache<Key: Hashable, Value>: @unchecked Sendable {
public init(count: Int) {
self.count = count
self.keyWriteIndex = 0
self.keys = Array(repeating: nil, count: count)
self.storage = Dictionary(minimumCapacity: count)
}

public func set(_ value: Value, forKey key: Key) {
self.lock.lock()
defer { self.lock.unlock() }

if let keyToDel = self.keys[self.keyWriteIndex] { self.storage.removeValue(forKey: keyToDel) }

self.keys[self.keyWriteIndex] = key
self.storage[key] = value

self.keyWriteIndex = (self.keyWriteIndex + 1) % self.count
}

public func valueForKey(_ key: Key) -> Value? {
self.lock.lock()
let value = self.storage[key]
self.lock.unlock()

return value
}

public func clear() {
self.keys = Array(repeating: nil, count: self.count)
self.storage.removeAll(keepingCapacity: true)
}

private let count: Int
private var keys: [Key?]
private var keyWriteIndex: Int
private var storage: [Key: Value]

private let lock = OSAllocatedUnfairLock()
}

public final class FifoCache<Key: Hashable, Value> {
public init(count: Int) {
Expand All @@ -23,9 +65,9 @@ public final class FifoCache<Key: Hashable, Value> {
}

public func valueForKey(_ key: Key) -> Value? { self.storage[key] }

public func clear() {
self.keys = Array(repeating: nil, count: count)
self.keys = Array(repeating: nil, count: self.count)
self.storage.removeAll(keepingCapacity: true)
}

Expand Down
21 changes: 14 additions & 7 deletions Commons/Sources/Commons/FileUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,16 @@ import AppKit
import Cocoa
import UniformTypeIdentifiers

private let workspace = NSWorkspace.shared
private let iconsCache = NSCache<NSURL, NSImage>()
// icon(forFile:) is thread-safe: https://developer.apple.com/documentation/appkit/nsworkspace/icon(forfile:)
// icon(for:) probably is thread-safe
private nonisolated(unsafe) let workspace = NSWorkspace.shared

// NSCache is thread-safe: https://developer.apple.com/documentation/foundation/nscache#overview
private nonisolated(unsafe) let iconsCache = NSCache<NSURL, NSImage>()

// FileManager is thread-safe:
// https://developer.apple.com/documentation/foundation/filemanager#1651181
private nonisolated(unsafe) let fm = FileManager.default

public final class FileUtils {
private static let keysToGet: [URLResourceKey] = [
Expand All @@ -23,14 +31,13 @@ public final class FileUtils {
.skipsPackageDescendants,
]

private static let fileManager = FileManager.default
public static let userHomeUrl = URL(fileURLWithPath: NSHomeDirectory(), isDirectory: true)
public static func tempDir() -> URL {
URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
}

public static func directDescendants(of url: URL) -> [URL] {
guard let childUrls = try? self.fileManager.contentsOfDirectory(
guard let childUrls = try? fm.contentsOfDirectory(
at: url, includingPropertiesForKeys: self.keysToGet, options: self.scanOptions
) else { return [] }

Expand All @@ -41,7 +48,7 @@ public final class FileUtils {
guard url.isFileURL else { return false }

let path = url.path
return self.fileManager.fileExists(atPath: path)
return fm.fileExists(atPath: path)
}

public static func commonParent(of urls: [URL]) -> URL {
Expand All @@ -51,8 +58,8 @@ public final class FileUtils {
let min = pathComps.map(\.count).min()!
let pathCompsOnlyMin = pathComps.map { $0[0..<min] }
let commonIdx = (0..<min).reversed().reduce(min - 1) { result, idx in
if Set(pathCompsOnlyMin.map { $0[idx] }).count > 1 { return idx - 1 }
else { return result }
if Set(pathCompsOnlyMin.map { $0[idx] }).count > 1 { idx - 1 }
else { result }
}

let result = pathCompsOnlyMin[0]
Expand Down
27 changes: 1 addition & 26 deletions Commons/Sources/Commons/FoundationCommons.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,7 @@ public extension Array {
}

public extension RandomAccessCollection where Index == Int {
func parallelMap<T>(chunkSize: Int = 1, _ transform: @escaping (Element) -> T) -> [T] {
let count = self.count
guard count > chunkSize else { return self.map(transform) }

var result = [T?](repeating: nil, count: count)

// If we don't use Array.withUnsafeMutableBufferPointer,
// then we get crashes.
result.withUnsafeMutableBufferPointer { pointer in
if chunkSize == 1 {
DispatchQueue.concurrentPerform(iterations: count) { i in pointer[i] = transform(self[i]) }
} else {
let chunkCount = Int(ceil(Double(self.count) / Double(chunkSize)))
DispatchQueue.concurrentPerform(iterations: chunkCount) { chunkIndex in
let start = Swift.min(chunkIndex * chunkSize, count)
let end = Swift.min(start + chunkSize, count)

(start..<end).forEach { i in pointer[i] = transform(self[i]) }
}
}
}

return result.map { $0! }
}

func groupedRanges<T: Equatable>(with marker: (Element) -> T) -> [ClosedRange<Index>] {
func groupedRanges(with marker: (Element) -> some Equatable) -> [ClosedRange<Index>] {
if self.isEmpty { return [] }
if self.count == 1 { return [self.startIndex...self.startIndex] }

Expand Down
24 changes: 12 additions & 12 deletions Commons/Sources/Commons/OSLogCommons.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import Foundation
import os

public extension OSLog {
func trace<T>(
func trace(
file: String = #file,
function: String = #function,
line: Int = #line,
_ msg: T
_ msg: some Any
) {
#if TRACE
self.log(
Expand All @@ -36,11 +36,11 @@ public extension OSLog {
#endif
}

func debug<T>(
func debug(
file: String = #file,
function: String = #function,
line: Int = #line,
_ msg: T
_ msg: some Any
) {
#if DEBUG
self.log(
Expand All @@ -51,11 +51,11 @@ public extension OSLog {
#endif
}

func info<T>(
func info(
file: String = #file,
function: String = #function,
line: Int = #line,
_ msg: T
_ msg: some Any
) {
self.log(
type: .info,
Expand All @@ -64,11 +64,11 @@ public extension OSLog {
)
}

func `default`<T>(
func `default`(
file: String = #file,
function: String = #function,
line: Int = #line,
_ msg: T
_ msg: some Any
) {
self.log(
type: .default,
Expand All @@ -77,11 +77,11 @@ public extension OSLog {
)
}

func error<T>(
func error(
file: String = #file,
function: String = #function,
line: Int = #line,
_ msg: T
_ msg: some Any
) {
self.log(
type: .error,
Expand All @@ -90,11 +90,11 @@ public extension OSLog {
)
}

func fault<T>(
func fault(
file: String = #file,
function: String = #function,
line: Int = #line,
_ msg: T
_ msg: some Any
) {
self.log(
type: .fault,
Expand Down
4 changes: 3 additions & 1 deletion Commons/Sources/Commons/SwiftCommons.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ func tuplesToDict<K: Hashable, V, S: Sequence>(_ sequence: S)
{
var result = [K: V](minimumCapacity: sequence.underestimatedCount)

for (key, value) in sequence { result[key] = value }
for (key, value) in sequence {
result[key] = value
}

return result
}
Expand Down
15 changes: 12 additions & 3 deletions Commons/Support/CommonsSupport.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@
4B7FBFDB24EC92F2002D12A1 /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastSwiftUpdateCheck = 1200;
LastUpgradeCheck = 1340;
LastUpgradeCheck = 1620;
TargetAttributes = {
4B7FBFF724EC936C002D12A1 = {
CreatedOnToolsVersion = 12.0;
Expand Down Expand Up @@ -185,9 +186,11 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
Expand All @@ -202,12 +205,13 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 12.0;
MACOSX_DEPLOYMENT_TARGET = 13.5;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 6.0;
};
name = Debug;
};
Expand Down Expand Up @@ -246,9 +250,11 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
Expand All @@ -257,11 +263,12 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 12.0;
MACOSX_DEPLOYMENT_TARGET = 13.5;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 6.0;
};
name = Release;
};
Expand All @@ -271,6 +278,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
COMBINE_HIDPI_IMAGES = YES;
DEAD_CODE_STRIPPING = YES;
INFOPLIST_FILE = EnvVarTest/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
Expand All @@ -289,6 +297,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
COMBINE_HIDPI_IMAGES = YES;
DEAD_CODE_STRIPPING = YES;
INFOPLIST_FILE = EnvVarTest/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
Expand Down
20 changes: 15 additions & 5 deletions Commons/Tests/CommonsTests/FifoCacheTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,25 @@ class FifoCacheTest: XCTestCase {
}

func testSimpleGet() {
for i in 0...5 { self.fifo.set(i, forKey: i) }
for i in 0...5 {
self.fifo.set(i, forKey: i)
}

for i in 0...5 { expect(self.fifo.valueForKey(i)).to(equal(i)) }
for i in 6..<10 { expect(self.fifo.valueForKey(i)).to(beNil()) }
for i in 0...5 {
expect(self.fifo.valueForKey(i)).to(equal(i))
}
for i in 6..<10 {
expect(self.fifo.valueForKey(i)).to(beNil())
}
}

func testGet() {
for i in 0..<(10 * 3) { self.fifo.set(i, forKey: i) }
for i in 20..<30 { expect(self.fifo.valueForKey(i)).to(equal(i)) }
for i in 0..<(10 * 3) {
self.fifo.set(i, forKey: i)
}
for i in 20..<30 {
expect(self.fifo.valueForKey(i)).to(equal(i))
}
expect(self.fifo.valueForKey(19)).to(beNil())
expect(self.fifo.valueForKey(30)).to(beNil())
}
Expand Down
Loading