From ac8d390aebf1c09391aad446872e605173480f62 Mon Sep 17 00:00:00 2001 From: Iceman Date: Thu, 11 May 2023 13:05:23 +0900 Subject: [PATCH 1/2] Wrap underlyingType if the type has existential any --- .../MockoloFramework/Models/ParamModel.swift | 2 +- .../Models/TypeAliasModel.swift | 2 +- .../Utils/InheritanceResolver.swift | 2 +- .../Utils/StringExtensions.swift | 3 +- .../MockoloFramework/Utils/TypeParser.swift | 18 ++++--- .../ExistentialAnyTests.swift | 8 +++ .../FixtureExistentialAny.swift | 52 +++++++++++++++++++ 7 files changed, 76 insertions(+), 11 deletions(-) create mode 100644 Tests/TestExistentialAny/ExistentialAnyTests.swift create mode 100644 Tests/TestExistentialAny/FixtureExistentialAny.swift diff --git a/Sources/MockoloFramework/Models/ParamModel.swift b/Sources/MockoloFramework/Models/ParamModel.swift index a1ca813d..c4ba047d 100644 --- a/Sources/MockoloFramework/Models/ParamModel.swift +++ b/Sources/MockoloFramework/Models/ParamModel.swift @@ -79,7 +79,7 @@ final class ParamModel: Model { if self.inInit, self.needVarDecl { let type: `Type` if eraseType { - type = Type(.any) + type = Type(.anyType) } else { type = self.type } diff --git a/Sources/MockoloFramework/Models/TypeAliasModel.swift b/Sources/MockoloFramework/Models/TypeAliasModel.swift index 30711f0e..013d7cea 100644 --- a/Sources/MockoloFramework/Models/TypeAliasModel.swift +++ b/Sources/MockoloFramework/Models/TypeAliasModel.swift @@ -49,7 +49,7 @@ final class TypeAliasModel: Model { if let val = overrideTypes?[self.name] { self.type = Type(val) } else { - self.type = typeName.isEmpty ? Type(String.any) : Type(typeName) + self.type = typeName.isEmpty ? Type(String.anyType) : Type(typeName) } } diff --git a/Sources/MockoloFramework/Utils/InheritanceResolver.swift b/Sources/MockoloFramework/Utils/InheritanceResolver.swift index 48461c8e..128f2531 100644 --- a/Sources/MockoloFramework/Utils/InheritanceResolver.swift +++ b/Sources/MockoloFramework/Utils/InheritanceResolver.swift @@ -56,7 +56,7 @@ func lookupEntities(key: String, if declType == .protocolType { // TODO: remove this once parent protocol (current decl = classtype) handling is resolved. // If the protocol inherits other protocols, look up their entities as well. for parent in current.entityNode.inheritedTypes { - if parent != .class, parent != .any, parent != .anyObject { + if parent != .class, parent != .anyType, parent != .anyObject { let (parentModels, parentProcessedModels, parentAttributes, parentPaths, parentPathToContents) = lookupEntities(key: parent, declType: declType, protocolMap: protocolMap, inheritanceMap: inheritanceMap) models.append(contentsOf: parentModels) processedModels.append(contentsOf: parentProcessedModels) diff --git a/Sources/MockoloFramework/Utils/StringExtensions.swift b/Sources/MockoloFramework/Utils/StringExtensions.swift index e0f0a890..fb6ffafb 100644 --- a/Sources/MockoloFramework/Utils/StringExtensions.swift +++ b/Sources/MockoloFramework/Utils/StringExtensions.swift @@ -44,7 +44,8 @@ extension String { static let mockType = "protocol" static let unknownVal = "Unknown" static let prefix = "prefix" - static let any = "Any" + static let anyType = "Any" + static let any = "any" static let some = "some" static let anyObject = "AnyObject" static let fatalError = "fatalError" diff --git a/Sources/MockoloFramework/Utils/TypeParser.swift b/Sources/MockoloFramework/Utils/TypeParser.swift index 7de83537..83b893a1 100644 --- a/Sources/MockoloFramework/Utils/TypeParser.swift +++ b/Sources/MockoloFramework/Utils/TypeParser.swift @@ -89,7 +89,7 @@ public final class `Type` { } // Use force unwrapped for the underlying type so it doesn't always have to be set in the init (need to allow blank init). - if hasClosure { + if hasClosure || hasExistentialAny { ret = "(\(ret))!" } else { if isOptional { @@ -129,6 +129,10 @@ public final class `Type` { return typeName.range(of: String.closureArrow) != nil } + var hasExistentialAny: Bool { + return typeName.hasPrefix(.any) + } + var isEscaping: Bool { return typeName.hasPrefix(String.escaping) } @@ -525,16 +529,16 @@ public final class `Type` { if !typeParams.filter({ returnComps.contains($0)}).isEmpty { returnAsStr = returnType.typeName if returnType.isOptional { - displayableReturnType = .any + "?" + displayableReturnType = .anyType + "?" returnAsStr.removeLast() asSuffix = "?" } else if returnType.isIUO { - displayableReturnType = .any + "!" + displayableReturnType = .anyType + "!" returnAsStr.removeLast() } else if returnType.isSelf { returnAsStr = String.`Self` } else { - displayableReturnType = .any + displayableReturnType = .anyType } if !returnAsStr.isEmpty { @@ -598,7 +602,7 @@ public final class `Type` { let left = ret[ret.startIndex.. any P & Q { get } +} +""" + +let existentialAnyMock = +""" + +class ExistentialAnyMock: ExistentialAny { + init() { } + init(foo: P, bar: any P, baz: any P & Q, qux: @escaping (any P) -> any P & Q) { + self._foo = foo + self._bar = bar + self._baz = baz + self._qux = qux + } + + + private(set) var fooSetCallCount = 0 + private var _foo: P! { didSet { fooSetCallCount += 1 } } + var foo: P { + get { return _foo } + set { _foo = newValue } + } + + private(set) var barSetCallCount = 0 + private var _bar: (any P)! { didSet { barSetCallCount += 1 } } + var bar: any P { + get { return _bar } + set { _bar = newValue } + } + + private(set) var bazSetCallCount = 0 + private var _baz: (any P & Q)! { didSet { bazSetCallCount += 1 } } + var baz: any P & Q { + get { return _baz } + set { _baz = newValue } + } + + private(set) var quxSetCallCount = 0 + private var _qux: ((any P) -> any P & Q)! { didSet { quxSetCallCount += 1 } } + var qux: (any P) -> any P & Q { + get { return _qux } + set { _qux = newValue } + } +} +""" From 1ab20b37e0789d49d6b6eee0a9f800fa03077ca6 Mon Sep 17 00:00:00 2001 From: Iceman Date: Mon, 15 May 2023 16:43:39 +0900 Subject: [PATCH 2/2] Use primary associated type --- .../FixtureExistentialAny.swift | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Tests/TestExistentialAny/FixtureExistentialAny.swift b/Tests/TestExistentialAny/FixtureExistentialAny.swift index ea47ec0b..321c6d5e 100644 --- a/Tests/TestExistentialAny/FixtureExistentialAny.swift +++ b/Tests/TestExistentialAny/FixtureExistentialAny.swift @@ -2,18 +2,17 @@ let existentialAny = """ /// \(String.mockAnnotation) protocol ExistentialAny { var foo: P { get } - var bar: any P { get } + var bar: any R { get } var baz: any P & Q { get } - var qux: (any P) -> any P & Q { get } + var qux: (any P) -> any P { get } } """ let existentialAnyMock = """ - class ExistentialAnyMock: ExistentialAny { init() { } - init(foo: P, bar: any P, baz: any P & Q, qux: @escaping (any P) -> any P & Q) { + init(foo: P, bar: any R, baz: any P & Q, qux: @escaping (any P) -> any P) { self._foo = foo self._bar = bar self._baz = baz @@ -29,8 +28,8 @@ class ExistentialAnyMock: ExistentialAny { } private(set) var barSetCallCount = 0 - private var _bar: (any P)! { didSet { barSetCallCount += 1 } } - var bar: any P { + private var _bar: (any R)! { didSet { barSetCallCount += 1 } } + var bar: any R { get { return _bar } set { _bar = newValue } } @@ -43,8 +42,8 @@ class ExistentialAnyMock: ExistentialAny { } private(set) var quxSetCallCount = 0 - private var _qux: ((any P) -> any P & Q)! { didSet { quxSetCallCount += 1 } } - var qux: (any P) -> any P & Q { + private var _qux: ((any P) -> any P)! { didSet { quxSetCallCount += 1 } } + var qux: (any P) -> any P { get { return _qux } set { _qux = newValue } }