Skip to content

Commit

Permalink
chore: enable code formatting and linting
Browse files Browse the repository at this point in the history
Ran swiftlint and swiftformat. Lots of files changed because code has not been formatted or linted in quite a while.

Added .swift-version because without it, swiftformat has some features disabled.

commit-id:5e8eb13d
  • Loading branch information
levibostian committed Apr 11, 2024
1 parent 208a1b2 commit 76d4567
Show file tree
Hide file tree
Showing 49 changed files with 714 additions and 901 deletions.
1 change: 1 addition & 0 deletions .swift-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
5.10
12 changes: 6 additions & 6 deletions .swiftformat
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
--exclude "app/ios/Pods"
# Docs: https://github.com/nicklockwood/SwiftFormat?tab=readme-ov-file#config-file

# dont run in these folders
--exclude Pods,autogenerated

# customize the formatting.
--binarygrouping none
--decimalgrouping none
--hexgrouping none
Expand All @@ -12,8 +16,4 @@
--stripunusedargs closure-only
--wraparguments after-first
--commas inline
--header strip

--disable unusedArguments

--enable isEmpty
--header strip
16 changes: 16 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Rules: https://realm.github.io/SwiftLint/rule-directory.html
# Config file learn more: https://github.com/realm/SwiftLint#configuration

disabled_rules:
- line_length # The swiftformat tool formats the swift code for us to not have super long lines. This rule after swiftformat has become more of an annoyance then a value where most errors are error message strings being too long.
- unused_optional_binding # `let _ =` can be easier to read sometimes then `!= nil` which is what this rule is trying to catch.
- nesting # It can be easier to read code when a class has many nested classes inside of it (example: JSON Codable structs for deserializing JSON).
- identifier_name # Variable names that are short in length can sometimes make code hard to read which this rule tries to catch. However, sometimes variable names that are 2 characters long are OK. We can catch bad variable naming in pull requests.

excluded: # paths or files to ignore during linting. Takes precedence over `included`.
- .build
- Package.swift
- app/*/Pods
- Source/autogenerated

reporter: "emoji" # reporter type (xcode, json, csv, checkstyle, codeclimate, junit, html, emoji, sonarqube, markdown, github-actions-logging)
4 changes: 3 additions & 1 deletion Mintfile
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
krzysztofzablocki/[email protected]
yonaskolb/[email protected]
yonaskolb/[email protected]
realm/[email protected]
nicklockwood/[email protected]
60 changes: 29 additions & 31 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,39 +1,37 @@
// swift-tools-version:5.8

import PackageDescription
import Foundation
import PackageDescription

let package = Package(
name: "Wendy",
platforms: [
.iOS(.v13)
],
products: [
.library(name: "Wendy", targets: ["Wendy"])
],
dependencies: [
// Help for the format of declaring SPM dependencies:
// https://web.archive.org/web/20220525200227/https://www.timc.dev/posts/understanding-swift-packages/
//
// Update to exact version until wrapper SDKs become part of testing pipeline.
.package(url: "https://github.com/groue/Semaphore.git", from: "0.0.8")
],
targets: [
.target(name: "Wendy",
dependencies: ["Semaphore"],
path: "Source/",
resources: [
.process("PrivacyInfo.xcprivacy")
]),
.testTarget(name: "WendyTests",
dependencies: ["Wendy"],
path: "Tests/")
]
)
let package = Package(name: "Wendy",
platforms: [
.iOS(.v13)
],
products: [
.library(name: "Wendy", targets: ["Wendy"])
],
dependencies: [
// Help for the format of declaring SPM dependencies:
// https://web.archive.org/web/20220525200227/https://www.timc.dev/posts/understanding-swift-packages/
//
// Update to exact version until wrapper SDKs become part of testing pipeline.
.package(url: "https://github.com/groue/Semaphore.git", from: "0.0.8")
],
targets: [
.target(name: "Wendy",
dependencies: ["Semaphore"],
path: "Source/",
resources: [
.process("PrivacyInfo.xcprivacy")
]),
.testTarget(name: "WendyTests",
dependencies: ["Wendy"],
path: "Tests/")
])

// Enable swift concurrency to all targets in package
for target in package.targets {
var settings = target.swiftSettings ?? []
settings.append(.enableExperimentalFeature("StrictConcurrency"))
target.swiftSettings = settings
var settings = target.swiftSettings ?? []
settings.append(.enableExperimentalFeature("StrictConcurrency"))
target.swiftSettings = settings
}
16 changes: 4 additions & 12 deletions Source/DIGraph.swift
Original file line number Diff line number Diff line change
@@ -1,22 +1,14 @@
//
// File.swift
//
//
// Created by Levi Bostian on 2/16/24.
//

import Foundation

final public class DIGraph: @unchecked Sendable {

public final class DIGraph: @unchecked Sendable {
public static let shared = DIGraph()

let mutex = Mutex()

private init() {}
internal var overrides: [String: Any] = [:]
internal var singletons: [String: Any] = [:]

var overrides: [String: Any] = [:]
var singletons: [String: Any] = [:]

/**
Reset graph. Meant to be used in `tearDown()` of tests.
Expand Down
14 changes: 3 additions & 11 deletions Source/Extensions/DataExtensions.swift
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
//
// File.swift
//
//
// Created by Levi Bostian on 3/26/24.
//

import Foundation

public extension Data {
func wendyDecode<Data: Codable>() -> Data? {
return DIGraph.shared.jsonAdapter.fromData(self)
func wendyDecode<Data: Codable>() -> Data? {
DIGraph.shared.jsonAdapter.fromData(self)
}
}

internal extension Data {
extension Data {
func asDictionary() -> [String: AnyHashable] {
do {
return try JSONSerialization.jsonObject(with: self, options: []) as? [String: AnyHashable] ?? [:]
Expand All @@ -22,4 +15,3 @@ internal extension Data {
}
}
}

6 changes: 3 additions & 3 deletions Source/Extensions/PendingTask+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ public extension PendingTask {
}

func addTaskStatusListenerForTask(listener: PendingTaskStatusListener) {
if let taskId = self.taskId {
if let taskId {
WendyConfig.addTaskStatusListenerForTask(taskId, listener: listener)
}
}

func hasBeenAddedToWendy() -> Bool {
return taskId != nil
taskId != nil
}

var dataAsDictionary: [String: AnyHashable] {
data?.asDictionary() ?? [:]
}
Expand Down
4 changes: 2 additions & 2 deletions Source/Extensions/_PendingTask+Extensions.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import Foundation

internal extension PendingTask {
extension PendingTask {
// Using instead of Equatable protocol because Swift does not allow a protocol inherit another protocol *and* I don't want the subclass to inherit Equatable, I just want to internally.
func equals(_ other: PendingTask) -> Bool {
return tag == other.tag &&
tag == other.tag &&
data == other.data
}
}
2 changes: 1 addition & 1 deletion Source/Listeners/PendingTaskStatusListener.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ public protocol PendingTaskStatusListener: AnyObject {
func skipped(taskId: Double, reason: ReasonPendingTaskSkipped)
}

internal struct WeakReferencePendingTaskStatusListener {
struct WeakReferencePendingTaskStatusListener {
weak var listener: PendingTaskStatusListener?
}
2 changes: 1 addition & 1 deletion Source/Listeners/TaskRunnerListener.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ public protocol TaskRunnerListener: AnyObject {
func allTasksComplete()
}

internal struct WeakReferenceTaskRunnerListener {
struct WeakReferenceTaskRunnerListener {
weak var listener: TaskRunnerListener!
}
2 changes: 1 addition & 1 deletion Source/PendingTask.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public struct PendingTask: Codable, Sendable {
public let data: Data?
public let groupId: String?
public let createdAt: Date? // populated later

public init(tag: String, taskId: Double?, data: Data?, groupId: String?, createdAt: Date?) {
self.tag = tag
self.taskId = taskId
Expand Down
40 changes: 19 additions & 21 deletions Source/PendingTasksManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,51 +3,49 @@ import Foundation

// sourcery: InjectRegister = "PendingTasksManager"
// sourcery: InjectSingleton
internal final class PendingTasksManager: QueueReader, QueueWriter, Sendable {

final class PendingTasksManager: QueueReader, QueueWriter, Sendable {
private let queueWriter: MutableSendable<QueueWriter>
internal let queueReaders: MutableSendable<[QueueReader]> = MutableSendable([])

let queueReaders: MutableSendable<[QueueReader]> = MutableSendable([])

init(queueWriter: QueueWriter, queueReader: QueueReader) {
self.queueWriter = MutableSendable(queueWriter)
self.queueReaders.set([

queueReaders.set([
queueReader
])
}

func add<Data>(tag: String, data: Data, groupId: String?) -> PendingTask where Data : Decodable, Data : Encodable {
return queueWriter.get().add(tag: tag, data: data, groupId: groupId)
func add(tag: String, data: some Decodable & Encodable, groupId: String?) -> PendingTask {
queueWriter.get().add(tag: tag, data: data, groupId: groupId)
}

internal func getAllTasks() -> [PendingTask] {
return queueReaders.get().flatMap { return $0.getAllTasks() }
.filter { return $0.createdAt != nil }
func getAllTasks() -> [PendingTask] {
queueReaders.get().flatMap { $0.getAllTasks() }
.filter { $0.createdAt != nil }
.sorted(by: { $0.createdAt! < $1.createdAt! })
}

internal func getTaskByTaskId(_ taskId: Double) -> PendingTask? {
return queueReaders.get().compactMap { return $0.getTaskByTaskId(taskId) }.first
func getTaskByTaskId(_ taskId: Double) -> PendingTask? {
queueReaders.get().compactMap { $0.getTaskByTaskId(taskId) }.first
}

// Note: Make sure to keep the query at "delete this table item by ID _____".
// Because of this scenario: The runner is running a task with ID 1. While the task is running a user decides to update that data. This results in having to run that PendingTask a 2nd time (if the running task is successful) to sync the newest changes. To assert this 2nd change, we take advantage of SQLite's unique constraint. On unique constraint collision we replace (update) the data in the database which results in all the PendingTask data being the same except for the ID being incremented. So, after the runner runs the task successfully and wants to delete the task here, it will not delete the task because the ID no longer exists. It has been incremented so the newest changes can be run.
@discardableResult
func delete(taskId: Double) -> Bool {
return queueWriter.get().delete(taskId: taskId)
queueWriter.get().delete(taskId: taskId)
}

internal func getNextTaskToRun(_ lastSuccessfulOrFailedTaskId: Double, filter: RunAllTasksFilter?) -> PendingTask? {
return queueReaders.get().compactMap { reader in
return reader.getNextTaskToRun(lastSuccessfulOrFailedTaskId, filter: filter)
func getNextTaskToRun(_ lastSuccessfulOrFailedTaskId: Double, filter: RunAllTasksFilter?) -> PendingTask? {
queueReaders.get().compactMap { reader in
reader.getNextTaskToRun(lastSuccessfulOrFailedTaskId, filter: filter)
}.first
}

public func addQueueReader(_ queueReader: QueueReader) {
queueReaders.set { existingReaders in
return existingReaders + [queueReader]
existingReaders + [queueReader]
}
}

}
Loading

0 comments on commit 76d4567

Please sign in to comment.