From 524b4e81c26337a62df5d408a96664c015b717e5 Mon Sep 17 00:00:00 2001 From: fummicc1 Date: Wed, 12 Apr 2023 11:07:00 +0900 Subject: [PATCH 01/14] Avoid duplicated variable name of initialization params. --- .../MockoloFramework/Models/ParamModel.swift | 2 +- .../Templates/ClassTemplate.swift | 21 ++++--- .../Templates/ParamTemplate.swift | 5 +- .../MockoloFramework/Utils/TypeParser.swift | 2 +- Tests/TestInit/FixtureInit.swift | 63 +++++++++++++++++++ Tests/TestInit/InitTests.swift | 16 +++++ 6 files changed, 96 insertions(+), 13 deletions(-) diff --git a/Sources/MockoloFramework/Models/ParamModel.swift b/Sources/MockoloFramework/Models/ParamModel.swift index 006ce77b..289eaf31 100644 --- a/Sources/MockoloFramework/Models/ParamModel.swift +++ b/Sources/MockoloFramework/Models/ParamModel.swift @@ -56,7 +56,7 @@ final class ParamModel: Model { var asVarDecl: String? { if self.inInit, self.needVarDecl { - return applyVarTemplate(name: name, type: type) + return applyVarTemplate(type: type) } return nil } diff --git a/Sources/MockoloFramework/Templates/ClassTemplate.swift b/Sources/MockoloFramework/Templates/ClassTemplate.swift index af244f23..87b63107 100644 --- a/Sources/MockoloFramework/Templates/ClassTemplate.swift +++ b/Sources/MockoloFramework/Templates/ClassTemplate.swift @@ -108,7 +108,7 @@ extension ClassModel { overrides: [String: String]?) -> String { let declaredInitParamsPerInit = declaredInits.map { $0.params } - + var needParamedInit = false var needBlankInit = false @@ -168,14 +168,19 @@ extension ClassModel { """ } - let extraInitParamNames = initParamCandidates.map{$0.name} - let extraVarsToDecl = declaredInitParamsPerInit.flatMap{$0}.compactMap { (p: ParamModel) -> String? in - if !extraInitParamNames.contains(p.name) { - return p.asVarDecl + let preDefinedExtraInitParamNames = initParamCandidates.map{$0.name} + var definedExtraInitParamNames = Set() + let extraVarsToDecl = declaredInitParamsPerInit + .flatMap { $0 } + .compactMap { (p: ParamModel) -> String? in + let isDuplicatedInitParamName = definedExtraInitParamNames.contains(p.name) + if !preDefinedExtraInitParamNames.contains(p.name) && !isDuplicatedInitParamName { + definedExtraInitParamNames.insert(p.name) + return p.asVarDecl + } + return nil } - return nil - } - .joined(separator: "\n") + .joined(separator: "\n") let declaredInitStr = declaredInits.compactMap { (m: MethodModel) -> String? in if case let .initKind(required, override) = m.kind, !m.processed { diff --git a/Sources/MockoloFramework/Templates/ParamTemplate.swift b/Sources/MockoloFramework/Templates/ParamTemplate.swift index d35713bd..43e94c6c 100644 --- a/Sources/MockoloFramework/Templates/ParamTemplate.swift +++ b/Sources/MockoloFramework/Templates/ParamTemplate.swift @@ -34,9 +34,8 @@ extension ParamModel { } return result } - - func applyVarTemplate(name: String, - type: Type) -> String { + + func applyVarTemplate(type: `Type`) -> String { assert(!type.isUnknown) let vardecl = "\(1.tab)private var \(underlyingName): \(type.underlyingType)" return vardecl diff --git a/Sources/MockoloFramework/Utils/TypeParser.swift b/Sources/MockoloFramework/Utils/TypeParser.swift index aef0c5c1..26105336 100644 --- a/Sources/MockoloFramework/Utils/TypeParser.swift +++ b/Sources/MockoloFramework/Utils/TypeParser.swift @@ -22,7 +22,7 @@ fileprivate var validIdentifierChars: CharacterSet = { return valid }() -public final class Type { +public final class `Type` { let typeName: String let cast: String? var cachedDefaultVal: String? diff --git a/Tests/TestInit/FixtureInit.swift b/Tests/TestInit/FixtureInit.swift index e69a2b49..cfe16ab7 100644 --- a/Tests/TestInit/FixtureInit.swift +++ b/Tests/TestInit/FixtureInit.swift @@ -268,3 +268,66 @@ public class ForcastUpdatingMock: ForcastUpdating { } """ +let multipleInitsWithSameParamName = """ +/// \(String.mockAnnotation) +protocol MyProtocol { + init(param: Any) + init(param: Any, anotherParam: String) +} +""" + +let multipleInitsWithSameParamNameMock = """ + + + +class MyProtocolMock: MyProtocol { + private var _param: Any! + private var _anotherParam: String! + init() { } + required init(param: Any) { + self._param = param + } + required init(param: Any, anotherParam: String = "") { + self._param = param + self._anotherParam = anotherParam + } + + +} +""" + + +let multipleTypeAwarenessInitsWithSameParamName = """ +/// \(String.mockAnnotation) +protocol MyProtocol { + init(param: Any) + init(param: Any, anotherParam: String, othersParams: [Any]) + init(param: Any, othersParams: [String]) +} +""" + +let multipleTypeAwarenessInitsWithSameParamNameMock = """ + + + +class MyProtocolMock: MyProtocol { + private var _param: Any! + private var _anotherParam: String! + private var _othersParams: [Any]! + init() { } + required init(param: Any) { + self._param = param + } + required init(param: Any, anotherParam: String = "", othersParams: [Any] = [Any]()) { + self._param = param + self._anotherParam = anotherParam + self._othersParams = othersParams + } + required init(param: Any, othersParams: [String] = [String]()) { + self._param = param + self._othersParams = othersParams as [Any] + } + + +} +""" diff --git a/Tests/TestInit/InitTests.swift b/Tests/TestInit/InitTests.swift index 55acbe0f..d56181a2 100644 --- a/Tests/TestInit/InitTests.swift +++ b/Tests/TestInit/InitTests.swift @@ -1,4 +1,5 @@ import Foundation +import XCTest class InitTests: MockoloTestCase { func testSimpleInitParams() { @@ -27,4 +28,19 @@ class InitTests: MockoloTestCase { verify(srcContent: keywordParams, dstContent: keywordParamsMock) } + + func testInitiWithSameParamName() { + verify( + srcContent: multipleInitsWithSameParamName, + dstContent: multipleInitsWithSameParamNameMock + ) + } + + func testInitiWithSameParamNameWithTypeDifference() throws { + throw XCTSkip("This feature will be implemented in future work.") + verify( + srcContent: multipleTypeAwarenessInitsWithSameParamName, + dstContent: multipleTypeAwarenessInitsWithSameParamNameMock + ) + } } From 066bce78a5b7dad601f90f58cebabf3145a233a5 Mon Sep 17 00:00:00 2001 From: fummicc1 Date: Fri, 14 Apr 2023 18:08:40 +0900 Subject: [PATCH 02/14] Support same name but different type by erasing type to `Any`. --- .../MockoloFramework/Models/ParamModel.swift | 8 ++++- .../Templates/ClassTemplate.swift | 13 +++++++- Tests/TestInit/FixtureInit.swift | 30 ++++++++----------- Tests/TestInit/InitTests.swift | 7 ++--- 4 files changed, 34 insertions(+), 24 deletions(-) diff --git a/Sources/MockoloFramework/Models/ParamModel.swift b/Sources/MockoloFramework/Models/ParamModel.swift index 289eaf31..7c90d71e 100644 --- a/Sources/MockoloFramework/Models/ParamModel.swift +++ b/Sources/MockoloFramework/Models/ParamModel.swift @@ -54,8 +54,14 @@ final class ParamModel: Model { return "_\(name)" } - var asVarDecl: String? { + func asVarDecl(typeErase: Bool = false) -> String? { if self.inInit, self.needVarDecl { + let type: `Type` + if typeErase { + type = Type("Any") + } else { + type = self.type + } return applyVarTemplate(type: type) } return nil diff --git a/Sources/MockoloFramework/Templates/ClassTemplate.swift b/Sources/MockoloFramework/Templates/ClassTemplate.swift index 87b63107..2677f5af 100644 --- a/Sources/MockoloFramework/Templates/ClassTemplate.swift +++ b/Sources/MockoloFramework/Templates/ClassTemplate.swift @@ -169,6 +169,13 @@ extension ClassModel { } let preDefinedExtraInitParamNames = initParamCandidates.map{$0.name} + let uniqueParamNameSet = Set(declaredInitParamsPerInit.flatMap { $0 }.map(\.name)) + let hasSameNameInProps = uniqueParamNameSet.filter { name in + declaredInitParamsPerInit + .flatMap { $0 } + .filter { $0.name == name } + .count > 1 + } var definedExtraInitParamNames = Set() let extraVarsToDecl = declaredInitParamsPerInit .flatMap { $0 } @@ -176,7 +183,11 @@ extension ClassModel { let isDuplicatedInitParamName = definedExtraInitParamNames.contains(p.name) if !preDefinedExtraInitParamNames.contains(p.name) && !isDuplicatedInitParamName { definedExtraInitParamNames.insert(p.name) - return p.asVarDecl + if hasSameNameInProps.contains(p.name) { + return p.asVarDecl(typeErase: true) + } else { + return p.asVarDecl() + } } return nil } diff --git a/Tests/TestInit/FixtureInit.swift b/Tests/TestInit/FixtureInit.swift index cfe16ab7..d2559bdb 100644 --- a/Tests/TestInit/FixtureInit.swift +++ b/Tests/TestInit/FixtureInit.swift @@ -268,64 +268,58 @@ public class ForcastUpdatingMock: ForcastUpdating { } """ -let multipleInitsWithSameParamName = """ +let initWithSameParamNameButDifferentType = """ /// \(String.mockAnnotation) protocol MyProtocol { init(param: Any) - init(param: Any, anotherParam: String) + init(param: String) + init(param: any Sequence) } """ -let multipleInitsWithSameParamNameMock = """ +let initWithSameParamNameButDifferentTypeMock = """ class MyProtocolMock: MyProtocol { private var _param: Any! - private var _anotherParam: String! init() { } required init(param: Any) { self._param = param } - required init(param: Any, anotherParam: String = "") { + required init(param: String = "") { + self._param = param + } + required init(param: any Sequence) { self._param = param - self._anotherParam = anotherParam } } """ - -let multipleTypeAwarenessInitsWithSameParamName = """ +let multipleInitsWithSameParamName = """ /// \(String.mockAnnotation) protocol MyProtocol { init(param: Any) - init(param: Any, anotherParam: String, othersParams: [Any]) - init(param: Any, othersParams: [String]) + init(param: Any, anotherParam: String) } """ -let multipleTypeAwarenessInitsWithSameParamNameMock = """ +let multipleInitsWithSameParamNameMock = """ class MyProtocolMock: MyProtocol { private var _param: Any! private var _anotherParam: String! - private var _othersParams: [Any]! init() { } required init(param: Any) { self._param = param } - required init(param: Any, anotherParam: String = "", othersParams: [Any] = [Any]()) { + required init(param: Any, anotherParam: String = "") { self._param = param self._anotherParam = anotherParam - self._othersParams = othersParams - } - required init(param: Any, othersParams: [String] = [String]()) { - self._param = param - self._othersParams = othersParams as [Any] } diff --git a/Tests/TestInit/InitTests.swift b/Tests/TestInit/InitTests.swift index d56181a2..aec7a67d 100644 --- a/Tests/TestInit/InitTests.swift +++ b/Tests/TestInit/InitTests.swift @@ -36,11 +36,10 @@ class InitTests: MockoloTestCase { ) } - func testInitiWithSameParamNameWithTypeDifference() throws { - throw XCTSkip("This feature will be implemented in future work.") + func testInitiWithSameParamNameButDifferentType() { verify( - srcContent: multipleTypeAwarenessInitsWithSameParamName, - dstContent: multipleTypeAwarenessInitsWithSameParamNameMock + srcContent: initWithSameParamNameButDifferentType, + dstContent: initWithSameParamNameButDifferentTypeMock ) } } From a3540eba6cece4c4bf857363776a9358074f102f Mon Sep 17 00:00:00 2001 From: fummicc1 Date: Fri, 14 Apr 2023 18:10:01 +0900 Subject: [PATCH 03/14] Undo modifying variable name --- Sources/MockoloFramework/Templates/ClassTemplate.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/MockoloFramework/Templates/ClassTemplate.swift b/Sources/MockoloFramework/Templates/ClassTemplate.swift index 2677f5af..1f7baa94 100644 --- a/Sources/MockoloFramework/Templates/ClassTemplate.swift +++ b/Sources/MockoloFramework/Templates/ClassTemplate.swift @@ -168,7 +168,7 @@ extension ClassModel { """ } - let preDefinedExtraInitParamNames = initParamCandidates.map{$0.name} + let extraInitParamNames = initParamCandidates.map{$0.name} let uniqueParamNameSet = Set(declaredInitParamsPerInit.flatMap { $0 }.map(\.name)) let hasSameNameInProps = uniqueParamNameSet.filter { name in declaredInitParamsPerInit @@ -181,7 +181,7 @@ extension ClassModel { .flatMap { $0 } .compactMap { (p: ParamModel) -> String? in let isDuplicatedInitParamName = definedExtraInitParamNames.contains(p.name) - if !preDefinedExtraInitParamNames.contains(p.name) && !isDuplicatedInitParamName { + if !extraInitParamNames.contains(p.name) && !isDuplicatedInitParamName { definedExtraInitParamNames.insert(p.name) if hasSameNameInProps.contains(p.name) { return p.asVarDecl(typeErase: true) From 5ff4854eeb9f19f3c0f711bfff3893d0daf63110 Mon Sep 17 00:00:00 2001 From: fummicc1 Date: Fri, 14 Apr 2023 18:11:35 +0900 Subject: [PATCH 04/14] Undo --- Tests/TestInit/InitTests.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Tests/TestInit/InitTests.swift b/Tests/TestInit/InitTests.swift index aec7a67d..91b532f2 100644 --- a/Tests/TestInit/InitTests.swift +++ b/Tests/TestInit/InitTests.swift @@ -1,5 +1,4 @@ import Foundation -import XCTest class InitTests: MockoloTestCase { func testSimpleInitParams() { From bda0bc3ab195628d33b4fba13176b82cf81ab194 Mon Sep 17 00:00:00 2001 From: fummicc1 Date: Fri, 14 Apr 2023 18:18:43 +0900 Subject: [PATCH 05/14] Rename --- Sources/MockoloFramework/Templates/ClassTemplate.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/MockoloFramework/Templates/ClassTemplate.swift b/Sources/MockoloFramework/Templates/ClassTemplate.swift index 1f7baa94..af381372 100644 --- a/Sources/MockoloFramework/Templates/ClassTemplate.swift +++ b/Sources/MockoloFramework/Templates/ClassTemplate.swift @@ -176,13 +176,13 @@ extension ClassModel { .filter { $0.name == name } .count > 1 } - var definedExtraInitParamNames = Set() + var processed = Set() let extraVarsToDecl = declaredInitParamsPerInit .flatMap { $0 } .compactMap { (p: ParamModel) -> String? in - let isDuplicatedInitParamName = definedExtraInitParamNames.contains(p.name) + let isDuplicatedInitParamName = processed.contains(p.name) if !extraInitParamNames.contains(p.name) && !isDuplicatedInitParamName { - definedExtraInitParamNames.insert(p.name) + processed.insert(p.name) if hasSameNameInProps.contains(p.name) { return p.asVarDecl(typeErase: true) } else { From 9209442b60966ab95a591522404f22e95dc0c2e5 Mon Sep 17 00:00:00 2001 From: fummicc1 Date: Sat, 15 Apr 2023 09:57:01 +0900 Subject: [PATCH 06/14] Remove hardcoded string token. Not apply type erase unless type is different from other init params. Fix --- .../MockoloFramework/Models/ClassModel.swift | 33 ++++++++++-- .../MockoloFramework/Models/ParamModel.swift | 29 +++++++++-- .../Models/ParsedEntity.swift | 8 +-- .../Templates/ClassTemplate.swift | 52 ++++++++++++------- Tests/TestInit/FixtureInit.swift | 13 ++--- 5 files changed, 98 insertions(+), 37 deletions(-) diff --git a/Sources/MockoloFramework/Models/ClassModel.swift b/Sources/MockoloFramework/Models/ClassModel.swift index 6815095b..88ef63be 100644 --- a/Sources/MockoloFramework/Models/ClassModel.swift +++ b/Sources/MockoloFramework/Models/ClassModel.swift @@ -25,7 +25,7 @@ final class ClassModel: Model { let identifier: String let declType: DeclType let entities: [(String, Model)] - let initParamCandidates: [Model] + let initParamCandidates: [VariableModel] let declaredInits: [MethodModel] let metadata: AnnotationMetadata? @@ -39,7 +39,7 @@ final class ClassModel: Model { attributes: [String], offset: Int64, metadata: AnnotationMetadata?, - initParamCandidates: [Model], + initParamCandidates: [VariableModel], declaredInits: [MethodModel], entities: [(String, Model)]) { self.identifier = identifier @@ -55,7 +55,32 @@ final class ClassModel: Model { self.accessLevel = acl } - func render(with identifier: String, encloser: String, useTemplateFunc: Bool, useMockObservable: Bool, allowSetCallCount: Bool = false, mockFinal: Bool = false, enableFuncArgsHistory: Bool = false, disableCombineDefaultValues: Bool = false) -> String? { - return applyClassTemplate(name: name, identifier: self.identifier, accessLevel: accessLevel, attribute: attribute, declType: declType, metadata: metadata, useTemplateFunc: useTemplateFunc, useMockObservable: useMockObservable, allowSetCallCount: allowSetCallCount, mockFinal: mockFinal, enableFuncArgsHistory: enableFuncArgsHistory, disableCombineDefaultValues: disableCombineDefaultValues, initParamCandidates: initParamCandidates, declaredInits: declaredInits, entities: entities) + func render( + with identifier: String, + encloser: String, + useTemplateFunc: Bool, + useMockObservable: Bool, + allowSetCallCount: Bool = false, + mockFinal: Bool = false, + enableFuncArgsHistory: Bool = false, + disableCombineDefaultValues: Bool = false + ) -> String? { + return applyClassTemplate( + name: name, + identifier: self.identifier, + accessLevel: accessLevel, + attribute: attribute, + declType: declType, + metadata: metadata, + useTemplateFunc: useTemplateFunc, + useMockObservable: useMockObservable, + allowSetCallCount: allowSetCallCount, + mockFinal: mockFinal, + enableFuncArgsHistory: enableFuncArgsHistory, + disableCombineDefaultValues: disableCombineDefaultValues, + initParamCandidates: initParamCandidates, + declaredInits: declaredInits, + entities: entities + ) } } diff --git a/Sources/MockoloFramework/Models/ParamModel.swift b/Sources/MockoloFramework/Models/ParamModel.swift index 7c90d71e..a1ca813d 100644 --- a/Sources/MockoloFramework/Models/ParamModel.swift +++ b/Sources/MockoloFramework/Models/ParamModel.swift @@ -53,12 +53,33 @@ final class ParamModel: Model { var underlyingName: String { return "_\(name)" } - - func asVarDecl(typeErase: Bool = false) -> String? { + + /// - Parameters: + /// - eraseType: + /// If other initializers in decl has same name as this param and type is different from each other, + /// please pass `True` to this parameter. Default value is `false`. + /// + /// ``` + /// protocol A { + /// init(param: String) + /// init(param: any Sequence) + /// } + /// class B: A { + /// var param: Any! // NOTE: type erasing + /// init () {} + /// required init(param: String) { + /// self.param = param + /// } + /// required init(param: any Sequence) { + /// self.param = param + /// } + /// } + /// ``` + func asInitVarDecl(eraseType: Bool) -> String? { if self.inInit, self.needVarDecl { let type: `Type` - if typeErase { - type = Type("Any") + if eraseType { + type = Type(.any) } else { type = self.type } diff --git a/Sources/MockoloFramework/Models/ParsedEntity.swift b/Sources/MockoloFramework/Models/ParsedEntity.swift index 6f5e525a..782ecdab 100644 --- a/Sources/MockoloFramework/Models/ParsedEntity.swift +++ b/Sources/MockoloFramework/Models/ParsedEntity.swift @@ -35,15 +35,17 @@ struct ResolvedEntity { return declaredInits.map { $0.params }.flatMap{$0} } - var initParamCandidates: [Model] { - return sortedInitVars(in: uniqueModels.map{$0.1}) + var initParamCandidates: [VariableModel] { + return sortedInitVars( + in: uniqueModels.compactMap{ $0.1 as? VariableModel } + ) } /// Returns models that can be used as parameters to an initializer /// @param models The models of the current entity including unprocessed (ones to generate) and /// processed (already mocked by a previous run if any) models. /// @returns A list of init parameter models - private func sortedInitVars(`in` models: [Model]) -> [Model] { + private func sortedInitVars(`in` models: [VariableModel]) -> [VariableModel] { let processed = models.filter {$0.processed && $0.canBeInitParam} let unprocessed = models.filter {!$0.processed && $0.canBeInitParam} diff --git a/Sources/MockoloFramework/Templates/ClassTemplate.swift b/Sources/MockoloFramework/Templates/ClassTemplate.swift index af381372..dd5ca44e 100644 --- a/Sources/MockoloFramework/Templates/ClassTemplate.swift +++ b/Sources/MockoloFramework/Templates/ClassTemplate.swift @@ -29,7 +29,7 @@ extension ClassModel { mockFinal: Bool, enableFuncArgsHistory: Bool, disableCombineDefaultValues: Bool, - initParamCandidates: [Model], + initParamCandidates: [VariableModel], declaredInits: [MethodModel], entities: [(String, Model)]) -> String { @@ -101,11 +101,13 @@ extension ClassModel { return template } - private func extraInitsIfNeeded(initParamCandidates: [Model], - declaredInits: [MethodModel], - acl: String, - declType: DeclType, - overrides: [String: String]?) -> String { + private func extraInitsIfNeeded( + initParamCandidates: [VariableModel], + declaredInits: [MethodModel], + acl: String, + declType: DeclType, + overrides: [String: String]? + ) -> String { let declaredInitParamsPerInit = declaredInits.map { $0.params } @@ -169,25 +171,19 @@ extension ClassModel { } let extraInitParamNames = initParamCandidates.map{$0.name} - let uniqueParamNameSet = Set(declaredInitParamsPerInit.flatMap { $0 }.map(\.name)) - let hasSameNameInProps = uniqueParamNameSet.filter { name in - declaredInitParamsPerInit - .flatMap { $0 } - .filter { $0.name == name } - .count > 1 - } var processed = Set() let extraVarsToDecl = declaredInitParamsPerInit .flatMap { $0 } .compactMap { (p: ParamModel) -> String? in - let isDuplicatedInitParamName = processed.contains(p.name) - if !extraInitParamNames.contains(p.name) && !isDuplicatedInitParamName { + if !extraInitParamNames.contains(p.name), !processed.contains(p.name) { processed.insert(p.name) - if hasSameNameInProps.contains(p.name) { - return p.asVarDecl(typeErase: true) - } else { - return p.asVarDecl() - } + let shouldEraseType = declaredInitParamsPerInit + .flatMap { $0 } + .checkHasConflictedParam( + name: p.name, + typeName: p.type.typeName + ) + return p.asInitVarDecl(eraseType: shouldEraseType) } return nil } @@ -309,3 +305,19 @@ extension ClassModel { } } } + +fileprivate extension [ParamModel] { + func findParams(name: String) -> [ParamModel] { + filter { + $0.name == name + } + } + + /// Check if there is same parameter name with different typeName. + func checkHasConflictedParam(name: String, typeName: String) -> Bool { + let sameParams = findParams( + name: name + ) + return !sameParams.allSatisfy { $0.type.typeName == typeName } + } +} diff --git a/Tests/TestInit/FixtureInit.swift b/Tests/TestInit/FixtureInit.swift index d2559bdb..b60bf8ca 100644 --- a/Tests/TestInit/FixtureInit.swift +++ b/Tests/TestInit/FixtureInit.swift @@ -301,8 +301,8 @@ class MyProtocolMock: MyProtocol { let multipleInitsWithSameParamName = """ /// \(String.mockAnnotation) protocol MyProtocol { - init(param: Any) - init(param: Any, anotherParam: String) + init(param: String, anotherParam: Int) + init(param: String, anotherParam: String) } """ @@ -311,13 +311,14 @@ let multipleInitsWithSameParamNameMock = """ class MyProtocolMock: MyProtocol { - private var _param: Any! - private var _anotherParam: String! + private var _param: String! + private var _anotherParam: Any! init() { } - required init(param: Any) { + required init(param: String = "", anotherParam: Int = 0) { self._param = param + self._anotherParam = anotherParam } - required init(param: Any, anotherParam: String = "") { + required init(param: String = "", anotherParam: String = "") { self._param = param self._anotherParam = anotherParam } From b747cf2f9c33f91d4a2d72e4a4789c247d0072d4 Mon Sep 17 00:00:00 2001 From: fummicc1 Date: Sat, 15 Apr 2023 17:51:44 +0900 Subject: [PATCH 07/14] Fix compile error --- Sources/MockoloFramework/Templates/ClassTemplate.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/MockoloFramework/Templates/ClassTemplate.swift b/Sources/MockoloFramework/Templates/ClassTemplate.swift index dd5ca44e..fe43e763 100644 --- a/Sources/MockoloFramework/Templates/ClassTemplate.swift +++ b/Sources/MockoloFramework/Templates/ClassTemplate.swift @@ -306,7 +306,7 @@ extension ClassModel { } } -fileprivate extension [ParamModel] { +fileprivate extension Array where Element == ParamModel { func findParams(name: String) -> [ParamModel] { filter { $0.name == name From 92f61759735dbd0e7ba61365098906d88237b1ce Mon Sep 17 00:00:00 2001 From: fummicc1 Date: Sat, 15 Apr 2023 22:35:23 +0900 Subject: [PATCH 08/14] Support old swift --- Tests/TestInit/FixtureInit.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/TestInit/FixtureInit.swift b/Tests/TestInit/FixtureInit.swift index b60bf8ca..e4e9409d 100644 --- a/Tests/TestInit/FixtureInit.swift +++ b/Tests/TestInit/FixtureInit.swift @@ -273,7 +273,7 @@ let initWithSameParamNameButDifferentType = """ protocol MyProtocol { init(param: Any) init(param: String) - init(param: any Sequence) + init(param: [Character]) } """ @@ -290,7 +290,7 @@ class MyProtocolMock: MyProtocol { required init(param: String = "") { self._param = param } - required init(param: any Sequence) { + required init(param: [Character] = [Character]()) { self._param = param } From c2e01a3fd31e47c9e1ecce74ecd091e1cd7e7623 Mon Sep 17 00:00:00 2001 From: Fumiya Tanaka Date: Tue, 18 Apr 2023 21:40:48 +0900 Subject: [PATCH 09/14] Update Tests/TestInit/FixtureInit.swift Co-authored-by: Iceman --- Tests/TestInit/FixtureInit.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/TestInit/FixtureInit.swift b/Tests/TestInit/FixtureInit.swift index e4e9409d..0a1ff08e 100644 --- a/Tests/TestInit/FixtureInit.swift +++ b/Tests/TestInit/FixtureInit.swift @@ -290,7 +290,7 @@ class MyProtocolMock: MyProtocol { required init(param: String = "") { self._param = param } - required init(param: [Character] = [Character]()) { + required init(with param: [Character] = [Character]()) { self._param = param } From 3fc0fcb694bb16cd779956eb36b03142f74547dc Mon Sep 17 00:00:00 2001 From: Fumiya Tanaka Date: Tue, 18 Apr 2023 21:40:58 +0900 Subject: [PATCH 10/14] Update Tests/TestInit/FixtureInit.swift Co-authored-by: Iceman --- Tests/TestInit/FixtureInit.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/TestInit/FixtureInit.swift b/Tests/TestInit/FixtureInit.swift index 0a1ff08e..2c677828 100644 --- a/Tests/TestInit/FixtureInit.swift +++ b/Tests/TestInit/FixtureInit.swift @@ -273,7 +273,7 @@ let initWithSameParamNameButDifferentType = """ protocol MyProtocol { init(param: Any) init(param: String) - init(param: [Character]) + init(with param: [Character]) } """ From 7faaa456186b41ac454774d003ea8f672a9d4d8b Mon Sep 17 00:00:00 2001 From: Fumiya Tanaka Date: Tue, 18 Apr 2023 21:44:20 +0900 Subject: [PATCH 11/14] Update Sources/MockoloFramework/Templates/ClassTemplate.swift Co-authored-by: Iceman --- .../Templates/ClassTemplate.swift | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/Sources/MockoloFramework/Templates/ClassTemplate.swift b/Sources/MockoloFramework/Templates/ClassTemplate.swift index fe43e763..1c4337aa 100644 --- a/Sources/MockoloFramework/Templates/ClassTemplate.swift +++ b/Sources/MockoloFramework/Templates/ClassTemplate.swift @@ -171,22 +171,17 @@ extension ClassModel { } let extraInitParamNames = initParamCandidates.map{$0.name} - var processed = Set() - let extraVarsToDecl = declaredInitParamsPerInit - .flatMap { $0 } - .compactMap { (p: ParamModel) -> String? in - if !extraInitParamNames.contains(p.name), !processed.contains(p.name) { - processed.insert(p.name) - let shouldEraseType = declaredInitParamsPerInit - .flatMap { $0 } - .checkHasConflictedParam( - name: p.name, - typeName: p.type.typeName - ) - return p.asInitVarDecl(eraseType: shouldEraseType) - } - return nil + let extraVarsToDecl = Dictionary( + grouping: declaredInitParamsPerInit.flatMap { + $0.filter { !extraInitParamNames.contains($0.name) } + }, + by: \.name + ) + .compactMap { (name: String, params: [ParamModel]) in + let shouldErase = params.contains { params[0].type.typeName != $0.type.typeName } + return params[0].asInitVarDecl(eraseType: shouldErase) } + .sorted() .joined(separator: "\n") let declaredInitStr = declaredInits.compactMap { (m: MethodModel) -> String? in From 6840666e09479a9f5218382d4b7d523a9dbbc76d Mon Sep 17 00:00:00 2001 From: fummicc1 Date: Tue, 18 Apr 2023 21:51:48 +0900 Subject: [PATCH 12/14] Delete dead code. --- .../Templates/ClassTemplate.swift | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/Sources/MockoloFramework/Templates/ClassTemplate.swift b/Sources/MockoloFramework/Templates/ClassTemplate.swift index 1c4337aa..dcfcdfb9 100644 --- a/Sources/MockoloFramework/Templates/ClassTemplate.swift +++ b/Sources/MockoloFramework/Templates/ClassTemplate.swift @@ -300,19 +300,3 @@ extension ClassModel { } } } - -fileprivate extension Array where Element == ParamModel { - func findParams(name: String) -> [ParamModel] { - filter { - $0.name == name - } - } - - /// Check if there is same parameter name with different typeName. - func checkHasConflictedParam(name: String, typeName: String) -> Bool { - let sameParams = findParams( - name: name - ) - return !sameParams.allSatisfy { $0.type.typeName == typeName } - } -} From ebc292cbaf180d555bb7286c698728fb82502867 Mon Sep 17 00:00:00 2001 From: fummicc1 Date: Tue, 18 Apr 2023 22:22:01 +0900 Subject: [PATCH 13/14] Follow the order of vars --- Tests/TestInit/FixtureInit.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/TestInit/FixtureInit.swift b/Tests/TestInit/FixtureInit.swift index 2c677828..161d1fe3 100644 --- a/Tests/TestInit/FixtureInit.swift +++ b/Tests/TestInit/FixtureInit.swift @@ -311,8 +311,8 @@ let multipleInitsWithSameParamNameMock = """ class MyProtocolMock: MyProtocol { - private var _param: String! - private var _anotherParam: Any! + private var _anotherParam: Any! + private var _param: String! init() { } required init(param: String = "", anotherParam: Int = 0) { self._param = param From 7cd8827a29a2bc555c25c64d4670aaee68370f12 Mon Sep 17 00:00:00 2001 From: fummicc1 Date: Tue, 18 Apr 2023 23:26:36 +0900 Subject: [PATCH 14/14] Delete unnecessary conformance. --- Sources/MockoloFramework/Models/Model.swift | 7 ------- Sources/MockoloFramework/Models/VariableModel.swift | 1 + 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Sources/MockoloFramework/Models/Model.swift b/Sources/MockoloFramework/Models/Model.swift index 2743c8e0..46c9e7a5 100644 --- a/Sources/MockoloFramework/Models/Model.swift +++ b/Sources/MockoloFramework/Models/Model.swift @@ -36,9 +36,6 @@ public protocol Model { /// Indicates whether mock generation for this model has been processed var processed: Bool { get } - /// Indicates whether this model can be used as a parameter to an initializer - var canBeInitParam: Bool { get } - /// Indicates whether this model maps to an init method var isInitializer: Bool { get } @@ -106,10 +103,6 @@ extension Model { return false } - var canBeInitParam: Bool { - return false - } - var isInitializer: Bool { return false } diff --git a/Sources/MockoloFramework/Models/VariableModel.swift b/Sources/MockoloFramework/Models/VariableModel.swift index 25d5b312..8b5b2451 100644 --- a/Sources/MockoloFramework/Models/VariableModel.swift +++ b/Sources/MockoloFramework/Models/VariableModel.swift @@ -7,6 +7,7 @@ final class VariableModel: Model { let accessLevel: String let attributes: [String]? let encloserType: DeclType + /// Indicates whether this model can be used as a parameter to an initializer var canBeInitParam: Bool let processed: Bool var filePath: String = ""