Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: pointfreeco/swift-dependencies
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 1.1.5
Choose a base ref
...
head repository: pointfreeco/swift-dependencies
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 1.2.0
Choose a head ref
  • 11 commits
  • 13 files changed
  • 8 contributors

Commits on Dec 23, 2023

  1. Update README.md

    mbrandonw authored Dec 23, 2023
    Copy the full SHA
    38a9223 View commit details

Commits on Jan 5, 2024

  1. Clearer warning message when you provide an unimplemented default val…

    …ue inside an @DependencyClient. (#167)
    ZevEisenberg authored Jan 5, 2024
    Copy the full SHA
    a22fd06 View commit details

Commits on Jan 12, 2024

  1. Copy the full SHA
    55d7d65 View commit details

Commits on Jan 17, 2024

  1. Tests: simplify WASI handling in DependencyValues test (#170)

    The tests were duplicated rather than just isolating the behavioural
    difference between WASI and non-WASI targets. Simplify to avoid
    duplicating the entire test.
    compnerd authored Jan 17, 2024
    Copy the full SHA
    0bc8b5d View commit details
  2. Run swift-format

    stephencelis authored and github-actions[bot] committed Jan 17, 2024
    Copy the full SHA
    e726c87 View commit details

Commits on Jan 22, 2024

  1. Cache values when accessing test dependencies from live context (#78)

    Co-authored-by: Stephen Celis <stephen@stephencelis.com>
    oronbz and stephencelis authored Jan 22, 2024
    Copy the full SHA
    21aaff1 View commit details
  2. Copy the full SHA
    d3fbf72 View commit details
  3. Add support for @Dependency(MyDependency.self) (#172)

    * wip
    
    * wip
    
    * wip
    
    * wip
    
    * wip
    
    * wip
    
    * wip
    
    * wip
    
    * wip
    
    * fixes
    
    * wip
    
    ---------
    
    Co-authored-by: Brandon Williams <mbrandonw@hey.com>
    stephencelis and mbrandonw authored Jan 22, 2024
    Copy the full SHA
    4379eaa View commit details
  4. Run swift-format

    stephencelis authored and github-actions[bot] committed Jan 22, 2024
    Copy the full SHA
    a9c9b58 View commit details
  5. Dependencies: dynamically link XCTest (#169)

    Use delayed dynamic linking for registering the test observer. This is
    particularly important for Windows which does not support weak linking
    and weak symbols. Even in the case that `Dependencies` is imported due
    to use, we will not pull in the test observer until runtime, as a best
    effort. If the DependenciesTestObserver library is found in the search
    path, it will be loaded and the observer initialised. If we can't find
    the library, we will simply continue without the test observer.
    compnerd authored Jan 22, 2024
    Copy the full SHA
    4ce7fd2 View commit details
  6. Run swift-format

    stephencelis authored and github-actions[bot] committed Jan 22, 2024
    Copy the full SHA
    adb04a8 View commit details
18 changes: 17 additions & 1 deletion Package@swift-5.9.swift
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@ let package = Package(
.library(
name: "DependenciesMacros",
targets: ["DependenciesMacros"]
)
),
],
dependencies: [
.package(url: "https://github.com/apple/swift-syntax", from: "509.0.0"),
@@ -31,6 +31,12 @@ let package = Package(
.package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "1.0.0"),
],
targets: [
.target(
name: "DependenciesTestObserver",
dependencies: [
.product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay"),
]
),
.target(
name: "Dependencies",
dependencies: [
@@ -85,6 +91,16 @@ let package = Package(
)
#endif

#if !os(macOS) && !os(WASI)
package.products.append(
.library(
name: "DependenciesTestObserver",
type: .dynamic,
targets: ["DependenciesTestObserver"]
)
)
#endif

//for target in package.targets {
// target.swiftSettings = target.swiftSettings ?? []
// target.swiftSettings?.append(
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -305,6 +305,6 @@ This library is released under the MIT license. See [LICENSE](LICENSE) for detai
[scrumdinger]: https://developer.apple.com/tutorials/app-dev-training/getting-started-with-scrumdinger
[syncups-demo]: https://github.com/pointfreeco/syncups
[swiftui-nav-gh]: http://github.com/pointfreeco/swiftui-navigation
[dep-values-docs]: https://swiftpackageindex.com/pointfreeco/swift-dependencies/main/documentation/dependencies/dependencyvalues
[dep-values-docs]: https://swiftpackageindex.com/pointfreeco/swift-dependencies/main/documentation/dependencies/dependencyvalues#dependency-values
[withdependencies-docs]: https://swiftpackageindex.com/pointfreeco/swift-dependencies/main/documentation/dependencies/withdependencies(_:operation:)-4uz6m
[immediate-clock-docs]: https://pointfreeco.github.io/swift-clocks/main/documentation/clocks/immediateclock
59 changes: 59 additions & 0 deletions Sources/Dependencies/Dependency.swift
Original file line number Diff line number Diff line change
@@ -97,6 +97,47 @@ public struct Dependency<Value>: @unchecked Sendable, _HasInitialValues {
self.line = line
}

/// Creates a dependency property to read a dependency object.
///
/// Don't call this initializer directly. Instead, declare a property with the `Dependency`
/// property wrapper, and provide the dependency key of the value that the property should
/// reflect.
///
/// For example, given a dependency key:
///
/// ```swift
/// final class Settings: DependencyKey {
/// static let liveValue = Settings()
///
/// // ...
/// }
/// ```
///
/// One can access the dependency using this property wrapper:
///
/// ```swift
/// final class FeatureModel: ObservableObject {
/// @Dependency(Settings.self) var settings
///
/// // ...
/// }
/// ```
///
/// - Parameter key: A dependency key to a specific resulting value.
public init<Key: TestDependencyKey>(
_ key: Key.Type,
file: StaticString = #file,
fileID: StaticString = #fileID,
line: UInt = #line
) where Key.Value == Value {
self.init(
\DependencyValues.[HashableType<Key>(file: file, line: line)],
file: file,
fileID: fileID,
line: line
)
}

/// The current value of the dependency property.
public var wrappedValue: Value {
#if DEBUG
@@ -119,6 +160,24 @@ public struct Dependency<Value>: @unchecked Sendable, _HasInitialValues {
}
}

private struct HashableType<T>: Hashable {
let file: StaticString
let line: UInt
static func == (lhs: Self, rhs: Self) -> Bool {
true
}
func hash(into hasher: inout Hasher) {
hasher.combine(ObjectIdentifier(T.self))
}
}

extension DependencyValues {
fileprivate subscript<Key: TestDependencyKey>(key: HashableType<Key>) -> Key.Value {
get { self[Key.self, file: key.file, line: key.line] }
set { self[Key.self, file: key.file, line: key.line] = newValue }
}
}

protocol _HasInitialValues {
var initialValues: DependencyValues { get }
}
29 changes: 17 additions & 12 deletions Sources/Dependencies/DependencyKey.swift
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@
/// implementation module.
///
/// See the <doc:LivePreviewTest> article for more information.
public protocol DependencyKey: TestDependencyKey {
public protocol DependencyKey<Value>: TestDependencyKey {
/// The live value for the dependency key.
///
/// This is the value used by default when running the application in a simulator or on a device.
@@ -118,7 +118,7 @@ public protocol DependencyKey: TestDependencyKey {
/// return a default value suitable for Xcode previews, or the ``testValue``, if left unimplemented.
///
/// See ``DependencyKey`` to define a static, default value for the live application.
public protocol TestDependencyKey {
public protocol TestDependencyKey<Value> {
/// The associated type representing the type of the dependency key's value.
associatedtype Value: Sendable = Self

@@ -210,25 +210,30 @@ extension DependencyKey {
\(typeName(Value.self))
"""
)
let dependencyName =

let (argument, override) =
DependencyValues.currentDependency.name
.map { "@Dependency(\\.\($0))" }
?? "A dependency"
.map {
"\($0)" == "subscript(_:)"
? ("@Dependency(\(typeName(Self.self)).self)", "'\(typeName(Self.self)).self'")
: ("@Dependency(\\.\($0))", "'\($0)'")
}
?? ("A dependency", "the dependency")

XCTFail(
"""
\(dependencyName) has no test implementation, but was accessed from a test context:
\(argument) has no test implementation, but was accessed from a test context:
\(dependencyDescription)
Dependencies registered with the library are not allowed to use their default, live \
implementations when run from tests.
To fix, override \
\(DependencyValues.currentDependency.name.map { "'\($0)'" } ?? "the dependency") with a \
test value. If you are using the Composable Architecture, mutate the 'dependencies' \
property on your 'TestStore'. Otherwise, use 'withDependencies' to define a scope for the \
override. If you'd like to provide a default value for all tests, implement the \
'testValue' requirement of the 'DependencyKey' protocol.
To fix, override \(override) with a test value. If you are using the \
Composable Architecture, mutate the 'dependencies' property on your 'TestStore'. \
Otherwise, use 'withDependencies' to define a scope for the override. If you'd like to \
provide a default value for all tests, implement the 'testValue' requirement of the \
'DependencyKey' protocol.
"""
)
#endif
Loading