Add option to prefix classnames of mocks and stubs.

This commit is contained in:
Emiel Verlinden 2019-12-15 20:04:20 +01:00 committed by Matyáš Kříž
parent b3bec5f8ff
commit a19958b964
9 changed files with 27 additions and 17 deletions

View File

@ -18,7 +18,7 @@ public struct Generator {
declarations = file.declarations declarations = file.declarations
} }
public func generate(debug: Bool = false) throws -> String { public func generate(debug: Bool = false, prefix: String) throws -> String {
code.clear() code.clear()
let ext = Extension() let ext = Extension()
@ -63,7 +63,7 @@ public struct Generator {
.filter { $0.accessibility.isAccessible } .filter { $0.accessibility.isAccessible }
.map { $0.serializeWithType() } .map { $0.serializeWithType() }
return try environment.renderTemplate(string: Templates.mock, context: ["containers": containers, "debug": debug]) return try environment.renderTemplate(string: Templates.mock, context: ["containers": containers, "debug": debug, "classPrefix": prefix])
} }
private func matchableGenericTypes(from method: Method) -> String { private func matchableGenericTypes(from method: Method) -> String {

View File

@ -15,7 +15,7 @@ extension Templates {
{% for attribute in container.attributes %} {% for attribute in container.attributes %}
{{ attribute.text }} {{ attribute.text }}
{% endfor %} {% endfor %}
{{ container.accessibility }} class {{ container.mockName }}{{ container.genericParameters }}: {{ container.name }}{% if container.isImplementation %}{{ container.genericArguments }}{% endif %}, {% if container.isImplementation %}Cuckoo.ClassMock{% else %}Cuckoo.ProtocolMock{% endif %} { {{ container.accessibility }} class {{ classPrefix }}{{ container.mockName }}{{ container.genericParameters }}: {{ container.name }}{% if container.isImplementation %}{{ container.genericArguments }}{% endif %}, {% if container.isImplementation %}Cuckoo.ClassMock{% else %}Cuckoo.ProtocolMock{% endif %} {
{% if container.isGeneric and not container.isImplementation %} {% if container.isGeneric and not container.isImplementation %}
{{ container.accessibility }} typealias MocksType = \(typeErasureClassName){{ container.genericArguments }} {{ container.accessibility }} typealias MocksType = \(typeErasureClassName){{ container.genericArguments }}
{% else %} {% else %}

View File

@ -7,7 +7,7 @@
extension Templates { extension Templates {
static let noImplStub = """ static let noImplStub = """
{{container.accessibility}} class {{ container.name }}Stub{{ container.genericParameters }}: {{ container.name }}{% if container.isImplementation %}{{ container.genericArguments }}{% endif %} { {{container.accessibility}} class {{ classPrefix }}{{ container.name }}Stub{{ container.genericParameters }}: {{ container.name }}{% if container.isImplementation %}{{ container.genericArguments }}{% endif %} {
{% for property in container.properties %} {% for property in container.properties %}
{% for attribute in property.attributes %} {% for attribute in property.attributes %}
{{ attribute.text }} {{ attribute.text }}

View File

@ -19,14 +19,14 @@ extension Templates {
{% for attribute in property.attributes %} {% for attribute in property.attributes %}
{{ attribute.text }} {{ attribute.text }}
{% endfor %} {% endfor %}
var {{property.name}}: Cuckoo.{{ property.stubType }}<{{ container.mockName }}, {% if property.isReadOnly %}{{property.type|genericSafe}}{% else %}{{property.nonOptionalType|genericSafe}}{% endif %}> { var {{property.name}}: Cuckoo.{{ property.stubType }}<{{ classPrefix }}{{ container.mockName }}, {% if property.isReadOnly %}{{property.type|genericSafe}}{% else %}{{property.nonOptionalType|genericSafe}}{% endif %}> {
return .init(manager: cuckoo_manager, name: "{{property.name}}") return .init(manager: cuckoo_manager, name: "{{property.name}}")
} }
{% endfor %} {% endfor %}
{% for method in container.methods %} {% for method in container.methods %}
func {{method.name}}{{method.self|matchableGenericNames}}({{method.parameters|matchableParameterSignature}}) -> {{method.stubFunction}}<({{method.inputTypes|genericSafe}}){%if method.returnType != "Void" %}, {{method.returnType|genericSafe}}{%endif%}>{{method.self|matchableGenericWhereClause}} { func {{method.name}}{{method.self|matchableGenericNames}}({{method.parameters|matchableParameterSignature}}) -> {{method.stubFunction}}<({{method.inputTypes|genericSafe}}){%if method.returnType != "Void" %}, {{method.returnType|genericSafe}}{%endif%}>{{method.self|matchableGenericWhereClause}} {
{{method.parameters|parameterMatchers}} {{method.parameters|parameterMatchers}}
return .init(stub: cuckoo_manager.createStub(for: {{ container.mockName }}.self, method: "{{method.fullyQualifiedName}}", parameterMatchers: matchers)) return .init(stub: cuckoo_manager.createStub(for: {{ classPrefix }}{{ container.mockName }}.self, method: "{{method.fullyQualifiedName}}", parameterMatchers: matchers))
} }
{% endfor %} {% endfor %}
} }

View File

@ -17,7 +17,6 @@ public struct Tokenizer {
public init(sourceFile: File, debugMode: Bool) { public init(sourceFile: File, debugMode: Bool) {
self.file = sourceFile self.file = sourceFile
self.debugMode = debugMode self.debugMode = debugMode
source = sourceFile.contents source = sourceFile.contents
} }

View File

@ -33,7 +33,8 @@ public struct ClassDeclaration: ContainerToken, HasAccessibility {
children: tokens, children: tokens,
inheritedTypes: self.inheritedTypes, inheritedTypes: self.inheritedTypes,
attributes: self.attributes, attributes: self.attributes,
genericParameters: self.genericParameters) genericParameters: self.genericParameters
)
} }
public func isEqual(to other: Token) -> Bool { public func isEqual(to other: Token) -> Bool {

View File

@ -30,7 +30,8 @@ public struct ProtocolDeclaration: ContainerToken, HasAccessibility {
children: tokens, children: tokens,
inheritedTypes: self.inheritedTypes, inheritedTypes: self.inheritedTypes,
attributes: self.attributes, attributes: self.attributes,
genericParameters: self.genericParameters) genericParameters: self.genericParameters
)
} }
public func isEqual(to other: Token) -> Bool { public func isEqual(to other: Token) -> Bool {

View File

@ -13,12 +13,12 @@ import FileKit
import CuckooGeneratorFramework import CuckooGeneratorFramework
import Foundation import Foundation
private func curry<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, R> private func curry<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, R>
(_ f: @escaping (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) -> R) (_ f: @escaping (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13) -> R)
-> (P1) -> (P2) -> (P3) -> (P4) -> (P5) -> (P6) -> (P7) -> (P8) -> (P9) -> (P10) -> (P11) -> (P12) -> R { -> (P1) -> (P2) -> (P3) -> (P4) -> (P5) -> (P6) -> (P7) -> (P8) -> (P9) -> (P10) -> (P11) -> (P12) -> (P13) -> R {
return { p1 in { p2 in { p3 in { p4 in { p5 in { p6 in { p7 in { p8 in { p9 in { p10 in { p11 in { p12 in return { p1 in { p2 in { p3 in { p4 in { p5 in { p6 in { p7 in { p8 in { p9 in { p10 in { p11 in { p12 in { p13 in
f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12) f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)
} } } } } } } } } } } } } } } } } } } } } } } } }
} }
public struct GenerateMocksCommand: CommandProtocol { public struct GenerateMocksCommand: CommandProtocol {
@ -53,10 +53,10 @@ public struct GenerateMocksCommand: CommandProtocol {
} }
let parsedFiles = removeTypes(from: tokensWithInheritance, using: typeFilters) let parsedFiles = removeTypes(from: tokensWithInheritance, using: typeFilters)
// generating headers and mocks // generate headers and mocks
let headers = parsedFiles.map { options.noHeader ? "" : FileHeaderHandler.getHeader(of: $0, includeTimestamp: !options.noTimestamp) } let headers = parsedFiles.map { options.noHeader ? "" : FileHeaderHandler.getHeader(of: $0, includeTimestamp: !options.noTimestamp) }
let imports = parsedFiles.map { FileHeaderHandler.getImports(of: $0, testableFrameworks: options.testableFrameworks) } let imports = parsedFiles.map { FileHeaderHandler.getImports(of: $0, testableFrameworks: options.testableFrameworks) }
let mocks = parsedFiles.map { try! Generator(file: $0).generate(debug: options.debugMode) } let mocks = parsedFiles.map { try! Generator(file: $0).generate(debug: options.debugMode, prefix: options.classPrefix) }
let mergedFiles = zip(zip(headers, imports), mocks).map { $0.0 + $0.1 + $1 } let mergedFiles = zip(zip(headers, imports), mocks).map { $0.0 + $0.1 + $1 }
let outputPath = Path(options.output) let outputPath = Path(options.output)
@ -137,6 +137,7 @@ public struct GenerateMocksCommand: CommandProtocol {
let testableFrameworks: [String] let testableFrameworks: [String]
let exclude: [String] let exclude: [String]
let filePrefix: String let filePrefix: String
let classPrefix: String
let noClassMocking: Bool let noClassMocking: Bool
let debugMode: Bool let debugMode: Bool
let globEnabled: Bool let globEnabled: Bool
@ -149,6 +150,7 @@ public struct GenerateMocksCommand: CommandProtocol {
noTimestamp: Bool, noTimestamp: Bool,
noInheritance: Bool, noInheritance: Bool,
filePrefix: String, filePrefix: String,
classPrefix: String,
noClassMocking: Bool, noClassMocking: Bool,
debugMode: Bool, debugMode: Bool,
globEnabled: Bool, globEnabled: Bool,
@ -162,6 +164,7 @@ public struct GenerateMocksCommand: CommandProtocol {
self.noTimestamp = noTimestamp self.noTimestamp = noTimestamp
self.noInheritance = noInheritance self.noInheritance = noInheritance
self.filePrefix = filePrefix self.filePrefix = filePrefix
self.classPrefix = classPrefix
self.noClassMocking = noClassMocking self.noClassMocking = noClassMocking
self.debugMode = debugMode self.debugMode = debugMode
self.globEnabled = globEnabled self.globEnabled = globEnabled
@ -185,6 +188,8 @@ public struct GenerateMocksCommand: CommandProtocol {
let filePrefix: Result<String, CommandantError<ClientError>> = m <| Option(key: "file-prefix", defaultValue: "", usage: "Names of generated files in directory will start with this prefix. Only works when output path is directory.") let filePrefix: Result<String, CommandantError<ClientError>> = m <| Option(key: "file-prefix", defaultValue: "", usage: "Names of generated files in directory will start with this prefix. Only works when output path is directory.")
let classPrefix: Result<String, CommandantError<ClientError>> = m <| Option(key: "class-prefix", defaultValue: "", usage: "Names of generated mocks and stubs will start with this prefix.")
let noClassMocking: Result<Bool, CommandantError<ClientError>> = m <| Option(key: "no-class-mocking", defaultValue: false, usage: "Do not generate mocks for classes.") let noClassMocking: Result<Bool, CommandantError<ClientError>> = m <| Option(key: "no-class-mocking", defaultValue: false, usage: "Do not generate mocks for classes.")
let debugMode: Result<Bool, CommandantError<ClientError>> = m <| Switch(flag: "d", key: "debug", usage: "Run generator in debug mode.") let debugMode: Result<Bool, CommandantError<ClientError>> = m <| Switch(flag: "d", key: "debug", usage: "Run generator in debug mode.")
@ -203,6 +208,7 @@ public struct GenerateMocksCommand: CommandProtocol {
<*> noTimestamp <*> noTimestamp
<*> noInheritance <*> noInheritance
<*> filePrefix <*> filePrefix
<*> classPrefix
<*> noClassMocking <*> noClassMocking
<*> debugMode <*> debugMode
<*> globEnabled <*> globEnabled

View File

@ -532,6 +532,9 @@ Do not mock/stub parents and grandparents.
###### `--file-prefix` (string) ###### `--file-prefix` (string)
Names of generated files in directory will start with this prefix. Only works when output path is directory. Names of generated files in directory will start with this prefix. Only works when output path is directory.
###### `--class-prefix` (string)
Names of generated classes (Mocks and Stubs) will start with this prefix.
###### `--no-class-mocking` ###### `--no-class-mocking`
Do not generate mocks for classes. Do not generate mocks for classes.