Skip to content

Commit 2d943da

Browse files
authored
Loosen platform requirements for Dependencies library (#1466)
* Loosen platform requirements for Dependencies Dependencies depends on runtime warning functionality, which is brought in via the "os" module. If we check for availability we can allow the Dependencies module to be used from multiplatform libraries, as we have in isowords. * More agnostic * wip * Update RuntimeWarnings.swift * Update RuntimeWarnings.swift
1 parent ce38199 commit 2d943da

File tree

24 files changed

+306
-370
lines changed

24 files changed

+306
-370
lines changed

ComposableArchitecture.xcworkspace/contents.xcworkspacedata

Lines changed: 0 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Sources/ComposableArchitecture/Effect.swift

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -134,20 +134,15 @@ extension Effect where Failure == Never {
134134
#if DEBUG
135135
var errorDump = ""
136136
customDump(error, to: &errorDump, indent: 4)
137-
runtimeWarning(
137+
runtimeWarn(
138138
"""
139-
An 'Effect.task' returned from "%@:%d" threw an unhandled error. …
139+
An "Effect.task" returned from "\(fileID):\(line)" threw an unhandled error. …
140140
141-
%@
141+
\(errorDump)
142142
143-
All non-cancellation errors must be explicitly handled via the 'catch' parameter \
144-
on 'Effect.task', or via a 'do' block.
143+
All non-cancellation errors must be explicitly handled via the "catch" parameter \
144+
on "Effect.task", or via a "do" block.
145145
""",
146-
[
147-
"\(fileID)",
148-
line,
149-
errorDump,
150-
],
151146
file: file,
152147
line: line
153148
)
@@ -221,20 +216,15 @@ extension Effect where Failure == Never {
221216
#if DEBUG
222217
var errorDump = ""
223218
customDump(error, to: &errorDump, indent: 4)
224-
runtimeWarning(
219+
runtimeWarn(
225220
"""
226-
An 'Effect.run' returned from "%@:%d" threw an unhandled error. …
221+
An "Effect.run" returned from "\(fileID):\(line)" threw an unhandled error. …
227222
228-
%@
223+
\(errorDump)
229224
230-
All non-cancellation errors must be explicitly handled via the 'catch' parameter \
231-
on 'Effect.run', or via a 'do' block.
225+
All non-cancellation errors must be explicitly handled via the "catch" parameter \
226+
on "Effect.run", or via a "do" block.
232227
""",
233-
[
234-
"\(fileID)",
235-
line,
236-
errorDump,
237-
],
238228
file: file,
239229
line: line
240230
)

Sources/ComposableArchitecture/Effects/TaskResult.swift

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -213,21 +213,20 @@ extension TaskResult: Equatable where Success: Equatable {
213213
case let (.failure(lhs), .failure(rhs)):
214214
return _isEqual(lhs, rhs) ?? {
215215
#if DEBUG
216-
if TaskResultDebugging.emitRuntimeWarnings, type(of: lhs) == type(of: rhs) {
217-
runtimeWarning(
216+
let lhsType = type(of: lhs)
217+
if TaskResultDebugging.emitRuntimeWarnings, lhsType == type(of: rhs) {
218+
let lhsTypeName = typeName(lhsType)
219+
runtimeWarn(
218220
"""
219-
'%1$@' is not equatable. …
221+
"\(lhsTypeName)" is not equatable. …
220222
221-
To test two values of this type, it must conform to the 'Equatable' protocol. For \
223+
To test two values of this type, it must conform to the "Equatable" protocol. For \
222224
example:
223225
224-
extension %1$@: Equatable {}
226+
extension \(lhsTypeName): Equatable {}
225227
226-
See the documentation of 'TaskResult' for more information.
227-
""",
228-
[
229-
"\(type(of: lhs))",
230-
]
228+
See the documentation of "TaskResult" for more information.
229+
"""
231230
)
232231
}
233232
#endif
@@ -252,19 +251,17 @@ extension TaskResult: Hashable where Success: Hashable {
252251
} else {
253252
#if DEBUG
254253
if TaskResultDebugging.emitRuntimeWarnings {
255-
runtimeWarning(
254+
let errorType = typeName(type(of: error))
255+
runtimeWarn(
256256
"""
257-
'%1$@' is not hashable. …
257+
"\(errorType)" is not hashable. …
258258
259-
To hash a value of this type, it must conform to the 'Hashable' protocol. For example:
259+
To hash a value of this type, it must conform to the "Hashable" protocol. For example:
260260
261-
extension %1$@: Hashable {}
261+
extension \(errorType): Hashable {}
262262
263-
See the documentation of 'TaskResult' for more information.
264-
""",
265-
[
266-
"\(type(of: error))",
267-
]
263+
See the documentation of "TaskResult" for more information.
264+
"""
268265
)
269266
}
270267
#endif

Sources/ComposableArchitecture/Internal/Deprecations.swift

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,15 +1071,15 @@ extension AnyReducer {
10711071
return .none
10721072
}
10731073
if index >= parentState[keyPath: toElementsState].endIndex {
1074-
runtimeWarning(
1074+
runtimeWarn(
10751075
"""
1076-
A "forEach" reducer at "%@:%d" received an action when state contained no element at \
1077-
that index. …
1076+
A "forEach" reducer at "\(fileID):\(line)" received an action when state contained no \
1077+
element at that index. …
10781078
10791079
Action:
1080-
%@
1080+
\(debugCaseOutput(action))
10811081
Index:
1082-
%d
1082+
\(index)
10831083
10841084
This is generally considered an application logic error, and can happen for a few \
10851085
reasons:
@@ -1101,12 +1101,6 @@ extension AnyReducer {
11011101
when its state contains an element at this index. In SwiftUI applications, use \
11021102
"ForEachStore".
11031103
""",
1104-
[
1105-
"\(fileID)",
1106-
line,
1107-
debugCaseOutput(action),
1108-
index,
1109-
],
11101104
file: file,
11111105
line: line
11121106
)
Lines changed: 54 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,50 @@
1+
@_transparent
2+
@usableFromInline
3+
@inline(__always)
4+
func runtimeWarn(
5+
_ message: @autoclosure () -> String,
6+
category: String? = "ComposableArchitecture",
7+
file: StaticString? = nil,
8+
line: UInt? = nil
9+
) {
10+
#if DEBUG
11+
let message = message()
12+
let category = category ?? "Runtime Warning"
13+
if _XCTIsTesting {
14+
if let file = file, let line = line {
15+
XCTFail(message, file: file, line: line)
16+
} else {
17+
XCTFail(message)
18+
}
19+
} else {
20+
#if canImport(os)
21+
os_log(
22+
.fault,
23+
dso: dso,
24+
log: OSLog(subsystem: "com.apple.runtime-issues", category: category),
25+
"%@",
26+
message
27+
)
28+
#else
29+
fputs("\(formatter.string(from: Date())) [\(category)] \(message)\n", stderr)
30+
#endif
31+
}
32+
#endif
33+
}
34+
135
#if DEBUG
2-
import os
336
import XCTestDynamicOverlay
437

5-
// NB: Xcode runtime warnings offer a much better experience than traditional assertions and
6-
// breakpoints, but Apple provides no means of creating custom runtime warnings ourselves.
7-
// To work around this, we hook into SwiftUI's runtime issue delivery mechanism, instead.
8-
//
9-
// Feedback filed: https://gist.github.com/stephencelis/a8d06383ed6ccde3e5ef5d1b3ad52bbc
10-
@usableFromInline
11-
let rw = (
12-
dso: { () -> UnsafeMutableRawPointer in
38+
#if canImport(os)
39+
import os
40+
41+
// NB: Xcode runtime warnings offer a much better experience than traditional assertions and
42+
// breakpoints, but Apple provides no means of creating custom runtime warnings ourselves.
43+
// To work around this, we hook into SwiftUI's runtime issue delivery mechanism, instead.
44+
//
45+
// Feedback filed: https://gist.github.com/stephencelis/a8d06383ed6ccde3e5ef5d1b3ad52bbc
46+
@usableFromInline
47+
let dso = { () -> UnsafeMutableRawPointer in
1348
let count = _dyld_image_count()
1449
for i in 0..<count {
1550
if let name = _dyld_get_image_name(i) {
@@ -22,33 +57,15 @@
2257
}
2358
}
2459
return UnsafeMutableRawPointer(mutating: #dsohandle)
25-
}(),
26-
log: OSLog(subsystem: "com.apple.runtime-issues", category: "ComposableArchitecture")
27-
)
28-
#endif
60+
}()
61+
#else
62+
import Foundation
2963

30-
@_transparent
31-
@usableFromInline
32-
@inline(__always)
33-
func runtimeWarning(
34-
_ message: @autoclosure () -> StaticString,
35-
_ args: @autoclosure () -> [CVarArg] = [],
36-
file: StaticString? = nil,
37-
line: UInt? = nil
38-
) {
39-
#if DEBUG
40-
let message = message()
41-
if _XCTIsTesting {
42-
if let file = file, let line = line {
43-
XCTFail(String(format: "\(message)", arguments: args()), file: file, line: line)
44-
} else {
45-
XCTFail(String(format: "\(message)", arguments: args()))
46-
}
47-
} else {
48-
unsafeBitCast(
49-
os_log as (OSLogType, UnsafeRawPointer, OSLog, StaticString, CVarArg...) -> Void,
50-
to: ((OSLogType, UnsafeRawPointer, OSLog, StaticString, [CVarArg]) -> Void).self
51-
)(.fault, rw.dso, rw.log, message, args())
52-
}
64+
@usableFromInline
65+
let formatter: DateFormatter = {
66+
let formatter = DateFormatter()
67+
formatter.dateFormat = "yyyy-MM-dd HH:MM:SS.sssZ"
68+
return formatter
69+
}()
5370
#endif
54-
}
71+
#endif

0 commit comments

Comments
 (0)