Skip to content

Commit f483155

Browse files
committed
Fix CI. Format and lint.
1 parent f04b40a commit f483155

22 files changed

Lines changed: 947 additions & 862 deletions

.github/workflows/ci.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- '*'
10+
11+
jobs:
12+
library:
13+
runs-on: macos-11.0
14+
environment: default
15+
strategy:
16+
matrix:
17+
xcode:
18+
- '12.4'
19+
- '12.5.1'
20+
- '13.2'
21+
steps:
22+
- uses: actions/checkout@v2
23+
- name: Select Xcode ${{ matrix.xcode }}
24+
run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app
25+
- name: Format lint
26+
run: swiftformat --lint .
27+
- name: Lint
28+
run: swiftlint .
29+
- name: Run Tests
30+
run: swift test --enable-code-coverage
31+
- name: Swift Coverage Report
32+
uses: maxep/spm-lcov-action@0.3.1
33+
- name: Code Coverage
34+
run: bash <(curl -s https://codecov.io/bash) -X xcodellvm

.swiftformat

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
--extensionacl on-declarations
2+
--redundanttype explicit
3+
--swiftversion 5.5
4+
--maxwidth 120
5+
--header "{file}\nCoreDataRepository\n\n\nMIT License\n\nCopyright © {year} Andrew Roan"
6+
--allman false

.swiftlint.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
disabled_rules:
2+
- multiple_closures_with_trailing_closure # by SwiftUI
3+
- trailing_comma # conflicts with SwiftFormat
4+
- opening_brace # conflicts with SwiftFormat
5+
excluded: # paths to ignore during linting. Takes precedence over `included`.
6+
- Carthage
7+
- Pods
8+
- .build/*
9+
- output
10+
- ./**/*Tests/*
11+
- Previews
12+
identifier_name:
13+
allowed_symbols: "_"
14+
excluded: # excluded via string array
15+
- id
16+
- to
17+
- vm
18+
- vc
19+
- _min
20+
- _max
21+
- or
22+
- by
23+
type_name:
24+
allowed_symbols: "_"
25+
excluded:
26+
- ID

.travis.yml

Lines changed: 0 additions & 11 deletions
This file was deleted.

Package.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ let package = Package(
99
.iOS(.v13),
1010
.macOS(.v10_15),
1111
.tvOS(.v13),
12-
.watchOS(.v6)
12+
.watchOS(.v6),
1313
],
1414
products: [
1515
// Products define the executables and libraries a package produces, and make them visible to other packages.
1616
.library(
1717
name: "CoreDataRepository",
18-
targets: ["CoreDataRepository"]),
18+
targets: ["CoreDataRepository"]
19+
),
1920
],
2021
dependencies: [
2122
// Dependencies declare other packages that this package depends on.
@@ -26,12 +27,13 @@ let package = Package(
2627
// Targets can depend on other targets in this package, and on products in packages this package depends on.
2728
.target(
2829
name: "CoreDataRepository",
29-
dependencies: []),
30+
dependencies: []
31+
),
3032
.testTarget(
3133
name: "CoreDataRepositoryTests",
3234
dependencies: ["CoreDataRepository"],
3335
resources: [
34-
.process("Model.xcdatamodeld")
36+
.process("Model.xcdatamodeld"),
3537
]
3638
),
3739
]

Sources/CoreDataRepository/AggregateRepository.swift

Lines changed: 106 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
1+
// AggregateRepository.swift
2+
// CoreDataRepository
13
//
2-
// AggregateRepository.swift
34
//
4-
// Created by Andrew Roan on 1/18/21.
5+
// MIT License
56
//
7+
// Copyright © 2021 Andrew Roan
68

7-
import CoreData
89
import Combine
10+
import CoreData
911

1012
/// A CoreData repository with functions for getting aggregate values
1113
public final class AggregateRepository {
1214
// MARK: Properties
15+
1316
/// The context used by the repository
1417
public let context: NSManagedObjectContext
1518
var cancellables = [AnyCancellable]()
1619
var subscriptions = [SubscriptionProvider]()
1720

1821
// MARK: Init
22+
1923
/// Initializes a repository
2024
/// - Parameters:
2125
/// - context: NSManagedObjectContext
@@ -25,6 +29,7 @@ public final class AggregateRepository {
2529
}
2630

2731
// MARK: Types
32+
2833
/// The aggregate function to be calculated
2934
public enum Function: String {
3035
case count
@@ -56,7 +61,13 @@ public final class AggregateRepository {
5661
}
5762
}
5863

59-
private func request(function: Function, predicate: NSPredicate, entityDesc: NSEntityDescription, attributeDesc: NSAttributeDescription, groupBy: NSAttributeDescription? = nil) -> NSFetchRequest<NSDictionary> {
64+
private func request(
65+
function: Function,
66+
predicate _: NSPredicate,
67+
entityDesc: NSEntityDescription,
68+
attributeDesc: NSAttributeDescription,
69+
groupBy: NSAttributeDescription? = nil
70+
) -> NSFetchRequest<NSDictionary> {
6071
let expDesc = NSExpressionDescription.aggregate(function: function, attributeDesc: attributeDesc)
6172
let request = NSFetchRequest<NSDictionary>(entityName: entityDesc.managedObjectClassName)
6273
request.entity = entityDesc
@@ -67,7 +78,7 @@ public final class AggregateRepository {
6778
} else {
6879
request.propertiesToFetch = [expDesc]
6980
}
70-
81+
7182
if let groupBy = groupBy {
7283
request.propertiesToGroupBy = [groupBy.name]
7384
}
@@ -76,6 +87,7 @@ public final class AggregateRepository {
7687
}
7788

7889
// MARK: Private Functions
90+
7991
/// Calculates aggregate values
8092
/// - Parameters
8193
/// - function: Function
@@ -87,31 +99,41 @@ public final class AggregateRepository {
8799
/// - `[[String: Value]]`
88100
///
89101
private func aggregate<Value: Numeric>(request: NSFetchRequest<NSDictionary>) throws -> [[String: Value]] {
90-
let result = try self.context.fetch(request)
102+
let result = try context.fetch(request)
91103
return result as? [[String: Value]] ?? []
92104
}
93105

94106
// MARK: Public Functions
107+
95108
/// Calculate the count for a fetchRequest
96109
/// - Parameters:
97110
/// - predicate: NSPredicate
98111
/// - entityDesc: NSEntityDescription
99112
/// - Returns
100113
/// - AnyPublisher<Success<Int>, Failure<Int>>
101114
///
102-
public func count<Value: Numeric>(predicate: NSPredicate, entityDesc: NSEntityDescription) -> AnyPublisher<Success<Value>, Failure> {
103-
return Deferred { Future { [weak self] callback in
115+
public func count<Value: Numeric>(predicate: NSPredicate,
116+
entityDesc: NSEntityDescription) -> AnyPublisher<Success<Value>, Failure>
117+
{
118+
Deferred { Future { [weak self] callback in
104119
let request = NSFetchRequest<NSDictionary>(entityName: entityDesc.name ?? "")
105120
request.predicate = predicate
106-
request.sortDescriptors = [NSSortDescriptor(key: entityDesc.attributesByName.values.first!.name, ascending: true)]
107-
guard let self = self else { return callback(.failure(Failure(function: .count, request: request, error: .unknown))) }
121+
request
122+
.sortDescriptors =
123+
[NSSortDescriptor(key: entityDesc.attributesByName.values.first!.name, ascending: true)]
124+
guard let self = self
125+
else { return callback(.failure(Failure(function: .count, request: request, error: .unknown))) }
108126
do {
109127
let count = try self.context.count(for: request)
110-
callback(.success(Success(function: .count, result: [["countOf\(entityDesc.name ?? "")": Value(exactly: count) ?? Value.zero]], request: request)))
128+
callback(.success(Success(
129+
function: .count,
130+
result: [["countOf\(entityDesc.name ?? "")": Value(exactly: count) ?? Value.zero]],
131+
request: request
132+
)))
111133
} catch {
112134
callback(.failure(Failure(function: .count, request: request, error: .cocoa(error as NSError))))
113135
}
114-
136+
115137
}}.eraseToAnyPublisher()
116138
}
117139

@@ -124,13 +146,26 @@ public final class AggregateRepository {
124146
/// - Returns
125147
/// - AnyPublisher<Success<Value>, Failure<Value>>
126148
///
127-
public func sum<Value: Numeric>(predicate: NSPredicate, entityDesc: NSEntityDescription, attributeDesc: NSAttributeDescription, groupBy: NSAttributeDescription? = nil) -> AnyPublisher<Success<Value>, Failure> {
128-
let request = self.request(function: .sum, predicate: predicate, entityDesc: entityDesc, attributeDesc: attributeDesc, groupBy: groupBy)
149+
public func sum<Value: Numeric>(
150+
predicate: NSPredicate,
151+
entityDesc: NSEntityDescription,
152+
attributeDesc: NSAttributeDescription,
153+
groupBy: NSAttributeDescription? = nil
154+
) -> AnyPublisher<Success<Value>, Failure> {
155+
let request = request(
156+
function: .sum,
157+
predicate: predicate,
158+
entityDesc: entityDesc,
159+
attributeDesc: attributeDesc,
160+
groupBy: groupBy
161+
)
129162
guard entityDesc == attributeDesc.entity else {
130-
return Fail(error: Failure(function: .sum, request: request, error: .propertyDoesNotMatchEntity)).eraseToAnyPublisher()
163+
return Fail(error: Failure(function: .sum, request: request, error: .propertyDoesNotMatchEntity))
164+
.eraseToAnyPublisher()
131165
}
132166
return Deferred { Future { [weak self] callback in
133-
guard let self = self else { return callback(.failure(Failure(function: .sum, request: request, error: .unknown))) }
167+
guard let self = self
168+
else { return callback(.failure(Failure(function: .sum, request: request, error: .unknown))) }
134169
do {
135170
let result: [[String: Value]] = try self.aggregate(request: request)
136171
callback(.success(Success(function: .sum, result: result, request: request)))
@@ -149,13 +184,26 @@ public final class AggregateRepository {
149184
/// - Returns
150185
/// - AnyPublisher<Success<Value>, Failure<Value>>
151186
///
152-
public func average<Value: Numeric>(predicate: NSPredicate, entityDesc: NSEntityDescription, attributeDesc: NSAttributeDescription, groupBy: NSAttributeDescription? = nil) -> AnyPublisher<Success<Value>, Failure> {
153-
let request = self.request(function: .average, predicate: predicate, entityDesc: entityDesc, attributeDesc: attributeDesc, groupBy: groupBy)
187+
public func average<Value: Numeric>(
188+
predicate: NSPredicate,
189+
entityDesc: NSEntityDescription,
190+
attributeDesc: NSAttributeDescription,
191+
groupBy: NSAttributeDescription? = nil
192+
) -> AnyPublisher<Success<Value>, Failure> {
193+
let request = request(
194+
function: .average,
195+
predicate: predicate,
196+
entityDesc: entityDesc,
197+
attributeDesc: attributeDesc,
198+
groupBy: groupBy
199+
)
154200
guard entityDesc == attributeDesc.entity else {
155-
return Fail(error: Failure(function: .average, request: request, error: .propertyDoesNotMatchEntity)).eraseToAnyPublisher()
201+
return Fail(error: Failure(function: .average, request: request, error: .propertyDoesNotMatchEntity))
202+
.eraseToAnyPublisher()
156203
}
157204
return Deferred { Future { [weak self] callback in
158-
guard let self = self else { return callback(.failure(Failure(function: .average, request: request, error: .unknown))) }
205+
guard let self = self
206+
else { return callback(.failure(Failure(function: .average, request: request, error: .unknown))) }
159207
do {
160208
let result: [[String: Value]] = try self.aggregate(request: request)
161209
callback(.success(Success(function: .average, result: result, request: request)))
@@ -174,13 +222,26 @@ public final class AggregateRepository {
174222
/// - Returns
175223
/// - AnyPublisher<Success<Value>, Failure<Value>>
176224
///
177-
public func min<Value: Numeric>(predicate: NSPredicate, entityDesc: NSEntityDescription, attributeDesc: NSAttributeDescription, groupBy: NSAttributeDescription? = nil) -> AnyPublisher<Success<Value>, Failure> {
178-
let request = self.request(function: .min, predicate: predicate, entityDesc: entityDesc, attributeDesc: attributeDesc, groupBy: groupBy)
225+
public func min<Value: Numeric>(
226+
predicate: NSPredicate,
227+
entityDesc: NSEntityDescription,
228+
attributeDesc: NSAttributeDescription,
229+
groupBy: NSAttributeDescription? = nil
230+
) -> AnyPublisher<Success<Value>, Failure> {
231+
let request = request(
232+
function: .min,
233+
predicate: predicate,
234+
entityDesc: entityDesc,
235+
attributeDesc: attributeDesc,
236+
groupBy: groupBy
237+
)
179238
guard entityDesc == attributeDesc.entity else {
180-
return Fail(error: Failure(function: .min, request: request, error: .propertyDoesNotMatchEntity)).eraseToAnyPublisher()
239+
return Fail(error: Failure(function: .min, request: request, error: .propertyDoesNotMatchEntity))
240+
.eraseToAnyPublisher()
181241
}
182242
return Deferred { Future { [weak self] callback in
183-
guard let self = self else { return callback(.failure(Failure(function: .min, request: request, error: .unknown))) }
243+
guard let self = self
244+
else { return callback(.failure(Failure(function: .min, request: request, error: .unknown))) }
184245
do {
185246
let result: [[String: Value]] = try self.aggregate(request: request)
186247
callback(.success(Success(function: .min, result: result, request: request)))
@@ -199,13 +260,26 @@ public final class AggregateRepository {
199260
/// - Returns
200261
/// - AnyPublisher<Success<Value>, Failure<Value>>
201262
///
202-
public func max<Value: Numeric>(predicate: NSPredicate, entityDesc: NSEntityDescription, attributeDesc: NSAttributeDescription, groupBy: NSAttributeDescription? = nil) -> AnyPublisher<Success<Value>, Failure> {
203-
let request = self.request(function: .max, predicate: predicate, entityDesc: entityDesc, attributeDesc: attributeDesc, groupBy: groupBy)
263+
public func max<Value: Numeric>(
264+
predicate: NSPredicate,
265+
entityDesc: NSEntityDescription,
266+
attributeDesc: NSAttributeDescription,
267+
groupBy: NSAttributeDescription? = nil
268+
) -> AnyPublisher<Success<Value>, Failure> {
269+
let request = request(
270+
function: .max,
271+
predicate: predicate,
272+
entityDesc: entityDesc,
273+
attributeDesc: attributeDesc,
274+
groupBy: groupBy
275+
)
204276
guard entityDesc == attributeDesc.entity else {
205-
return Fail(error: Failure(function: .max, request: request, error: .propertyDoesNotMatchEntity)).eraseToAnyPublisher()
277+
return Fail(error: Failure(function: .max, request: request, error: .propertyDoesNotMatchEntity))
278+
.eraseToAnyPublisher()
206279
}
207280
return Deferred { Future { [weak self] callback in
208-
guard let self = self else { return callback(.failure(Failure(function: .max, request: request, error: .unknown))) }
281+
guard let self = self
282+
else { return callback(.failure(Failure(function: .max, request: request, error: .unknown))) }
209283
do {
210284
let result: [[String: Value]] = try self.aggregate(request: request)
211285
callback(.success(Success(function: .max, result: result, request: request)))
@@ -217,6 +291,7 @@ public final class AggregateRepository {
217291
}
218292

219293
// MARK: Extensions
294+
220295
extension NSExpression {
221296
/// Convenience initializer for NSExpression that represent an aggregate function on a keypath
222297
fileprivate convenience init(function: AggregateRepository.Function, attributeDesc: NSAttributeDescription) {
@@ -227,7 +302,9 @@ extension NSExpression {
227302

228303
extension NSExpressionDescription {
229304
/// Convenience initializer for NSExpressionDescription that represent the properties to fetch in NSFetchRequest
230-
fileprivate static func aggregate(function: AggregateRepository.Function, attributeDesc: NSAttributeDescription) -> NSExpressionDescription {
305+
fileprivate static func aggregate(function: AggregateRepository.Function,
306+
attributeDesc: NSAttributeDescription) -> NSExpressionDescription
307+
{
231308
let expression = NSExpression(function: function, attributeDesc: attributeDesc)
232309
let expDesc = NSExpressionDescription()
233310
expDesc.expression = expression

0 commit comments

Comments
 (0)