diff --git a/.travis.yml b/.travis.yml index 5b10f96..51a9fd6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,8 @@ matrix: - set -o pipefail && xcodebuild test -workspace Dip.xcworkspace -scheme Dip -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6,OS=10.1' ONLY_ACTIVE_ARCH=NO | xcpretty -c - set -o pipefail && xcodebuild test -workspace Dip.xcworkspace -scheme Dip -sdk macosx -destination 'platform=macOS,arch=x86_64' ONLY_ACTIVE_ARCH=NO | xcpretty -c - set -o pipefail && xcodebuild test -workspace Dip.xcworkspace -scheme Dip -sdk appletvsimulator -destination 'platform=tvOS Simulator,name=Apple TV 1080p,OS=latest' ONLY_ACTIVE_ARCH=NO | xcpretty -c - - set -o pipefail && xcodebuild -workspace Dip.xcworkspace -scheme Dip -sdk watchsimulator -destination 'platform=watchOS Simulator,name=Apple Watch - 38mm,OS=latest' ONLY_ACTIVE_ARCH=NO | xcpretty - c + # disable running watchos until https://github.com/travis-ci/travis-ci/issues/7580 is fixed + #- set -o pipefail && xcodebuild -workspace Dip.xcworkspace -scheme Dip -sdk watchsimulator -destination 'platform=watchOS Simulator,name=Apple Watch - 38mm,OS=latest' ONLY_ACTIVE_ARCH=NO | xcpretty - c - set -o pipefail && xcodebuild test -workspace Dip.xcworkspace -scheme DipSampleApp -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6,OS=10.1' ONLY_ACTIVE_ARCH=NO | xcpretty -c - pod spec lint --allow-warnings - carthage build --no-skip-current diff --git a/CHANGELOG.md b/CHANGELOG.md index 463c9f4..e905883 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,20 +2,25 @@ ## 5.1 -* Fixed Swift 3.1 warnings - [#145](https://github.com/AliSoftware/Dip/issues/145), [@DenHeadless](https://github.com/DenHeadless) -* Dropped Swift 2.3 support +* Dropped Swift 2.3 support. [#150](https://github.com/AliSoftware/Dip/issues/150), [@ilyapuchka](https://github.com/ilyapuchka) -* Fixed collaboration shared references - [#151](https://github.com/AliSoftware/Dip/issues/151), [@ilyapuchka](https://github.com/ilyapuchka) -* Added custom logging function. +* Added custom logging function. [#146](https://github.com/AliSoftware/Dip/issues/146), [@Pr0Ger](https://github.com/Pr0Ger) + +#### Fixed + +* Fixed Swift 3.1 warnings. + [#145](https://github.com/AliSoftware/Dip/issues/145), [@DenHeadless](https://github.com/DenHeadless) +* Fixed collaboration shared references. + [#151](https://github.com/AliSoftware/Dip/issues/151), [@ilyapuchka](https://github.com/ilyapuchka) +* Fixed autowiring when using tags. + [#154](https://github.com/AliSoftware/Dip/issues/154), [@ilyapuchka](https://github.com/ilyapuchka) ## 5.0.4 #### Fixed -* Fixed broken compatibility for Swift 2.3 API in `resolve(tag:arguments:)` method. +* Fixed broken compatibility for Swift 2.3 API in `resolve(tag:arguments:)` method. [#135](https://github.com/AliSoftware/Dip/issues/135), [@ilyapuchka](https://github.com/ilyapuchka) ## 5.0.3 diff --git a/Sources/AutoWiring.swift b/Sources/AutoWiring.swift index a4cea35..17efb17 100644 --- a/Sources/AutoWiring.swift +++ b/Sources/AutoWiring.swift @@ -50,19 +50,30 @@ extension DependencyContainer { } private func autoWiringDefinition(byKey key: DefinitionKey) throws -> KeyDefinitionPair { + do { + return try autoWiringDefinition(byKey: key, strictByTag: true) + } catch { + if key.tag != nil { + return try autoWiringDefinition(byKey: key, strictByTag: false) + } else { + throw error + } + } + } + + private func autoWiringDefinition(byKey key: DefinitionKey, strictByTag: Bool) throws -> KeyDefinitionPair { var definitions = self.definitions.map({ (key: $0.0, definition: $0.1) }) - definitions = filter(definitions: definitions, byKey: key) + definitions = filter(definitions: definitions, byKey: key, strictByTag: strictByTag) definitions = definitions.sorted(by: { $0.definition.numberOfArguments > $1.definition.numberOfArguments }) - + guard definitions.count > 0 && definitions[0].definition.numberOfArguments > 0 else { throw DipError.definitionNotFound(key: key) } let maximumNumberOfArguments = definitions.first?.definition.numberOfArguments definitions = definitions.filter({ $0.definition.numberOfArguments == maximumNumberOfArguments }) - definitions = order(definitions: definitions, byTag: key.tag) - + //when there are several definitions with the same number of arguments but different arguments types if definitions.count > 1 && definitions[0].key.typeOfArguments != definitions[1].key.typeOfArguments { let error = DipError.ambiguousDefinitions(type: key.type, definitions: definitions.map({ $0.definition })) diff --git a/Sources/Definition.swift b/Sources/Definition.swift index 823789e..4a3e058 100644 --- a/Sources/Definition.swift +++ b/Sources/Definition.swift @@ -269,12 +269,12 @@ private func ~=(lhs: KeyDefinitionPair, rhs: KeyDefinitionPair) -> Bool { } /// Returns key-defintion pairs with definitions able to resolve that type (directly or via type forwarding) -/// and which tag matches provided key's tag or is nil. +/// and which tag matches provided key's tag or is nil if strictByTag is false. /// In the end filters defintions by type of runtime arguments. -func filter(definitions _definitions: [KeyDefinitionPair], byKey key: DefinitionKey, byTypeOfArguments: Bool = false) -> [KeyDefinitionPair] { +func filter(definitions _definitions: [KeyDefinitionPair], byKey key: DefinitionKey, strictByTag: Bool = false, byTypeOfArguments: Bool = false) -> [KeyDefinitionPair] { let definitions = _definitions .filter({ $0.key.type == key.type || $0.definition.doesImplements(type: key.type) }) - .filter({ $0.key.tag == key.tag || $0.key.tag == nil }) + .filter({ $0.key.tag == key.tag || (!strictByTag && $0.key.tag == nil) }) if byTypeOfArguments { return definitions.filter({ $0.key.typeOfArguments == key.typeOfArguments }) } diff --git a/Tests/DipTests/AutoWiringTests.swift b/Tests/DipTests/AutoWiringTests.swift index ecee84c..61dc197 100644 --- a/Tests/DipTests/AutoWiringTests.swift +++ b/Tests/DipTests/AutoWiringTests.swift @@ -55,7 +55,9 @@ class AutoWiringTests: XCTestCase { ("testThatItCanResolveWithAutoWiring", testThatItCanResolveWithAutoWiring), ("testThatItUsesAutoWireFactoryWithMostNumberOfArguments", testThatItUsesAutoWireFactoryWithMostNumberOfArguments), ("testThatItThrowsAmbiguityErrorWhenUsingAutoWire", testThatItThrowsAmbiguityErrorWhenUsingAutoWire), - ("testThatItFirstTriesToUseTaggedFactoriesWhenUsingAutoWire", testThatItFirstTriesToUseTaggedFactoriesWhenUsingAutoWire), + ("testThatItUsesAutoWireFactoryWithMostNumberOfArguments", testThatItUsesAutoWireFactoryWithMostNumberOfArguments), + ("testThatItPrefersTaggedFactoryWithDifferentNumberOfArgumentsWhenUsingAutoWire", testThatItPrefersTaggedFactoryWithDifferentNumberOfArgumentsWhenUsingAutoWire), + ("testThatItPrefersTaggedFactoryWithDifferentTypesOfArgumentsWhenUsingAutoWire", testThatItPrefersTaggedFactoryWithDifferentTypesOfArgumentsWhenUsingAutoWire), ("testThatItFallbackToNotTaggedFactoryWhenUsingAutoWire", testThatItFallbackToNotTaggedFactoryWhenUsingAutoWire), ("testThatItDoesNotTryToUseAutoWiringWhenCallingResolveWithArguments", testThatItDoesNotTryToUseAutoWiringWhenCallingResolveWithArguments), ("testThatItDoesNotUseAutoWiringWhenFailedToResolveLowLevelDependency", testThatItDoesNotUseAutoWiringWhenFailedToResolveLowLevelDependency), @@ -146,7 +148,7 @@ class AutoWiringTests: XCTestCase { } } - func testThatItFirstTriesToUseTaggedFactoriesWhenUsingAutoWire() { + func testThatItPrefersTaggedFactoryWithDifferentNumberOfArgumentsWhenUsingAutoWire() { //given //1 arg @@ -176,6 +178,31 @@ class AutoWiringTests: XCTestCase { XCTAssertTrue(taggedFactoryWithMostNumberOfArgumentsCalled) } + func testThatItPrefersTaggedFactoryWithDifferentTypesOfArgumentsWhenUsingAutoWire() { + //given + + //1 arg + container.register { AutoWiredClientImp(service1: $0, service2: try self.container.resolve()) as AutoWiredClient } + + //2 args + container.register { AutoWiredClientImp(service1: $0, service2: $1) as AutoWiredClient } + + //1 arg tagged + var taggedFactoryCalled = false + container.register(tag: "tag") { AutoWiredClientImp(service1: try self.container.resolve(), service2: $0) as AutoWiredClient }.resolvingProperties { _ in + taggedFactoryCalled = true + } + + container.register() { ServiceImp1() as Service } + container.register { ServiceImp2() } + + //when + let _ = try! container.resolve(tag: "tag") as AutoWiredClient + + //then + XCTAssertTrue(taggedFactoryCalled) + } + func testThatItFallbackToNotTaggedFactoryWhenUsingAutoWire() { //given