Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add default values to array, dictionary and set #68

Merged
merged 1 commit into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion Sources/Rubicon/Domain/TypeDeclaration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,15 @@ struct TypeDeclaration: Equatable {
case autoclosure = "@autoclosure"
}

enum ComposedType {
case plain
case array
case dictionary
case optional
case set
}

var name: String
var isOptional: Bool
let prefix: [Prefix]
let composedType: ComposedType
}
13 changes: 12 additions & 1 deletion Sources/Rubicon/Generator/DefaultValueGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,21 @@ final class DefaultValueGeneratorImpl: DefaultValueGenerator {
return customValue
}

guard !varDeclaration.type.isOptional else {
switch varDeclaration.type.composedType {
case .plain:
return makeDefaultValueByType(varDeclaration: varDeclaration)
case .array:
return "[]"
case .dictionary:
return "[:]"
case .optional:
return "nil"
case .set:
return "[]"
}
}

private func makeDefaultValueByType(varDeclaration: VarDeclaration) -> String {
switch varDeclaration.type.name {
case "String":
return "\"\(varDeclaration.identifier)\""
Expand Down
10 changes: 7 additions & 3 deletions Sources/Rubicon/Generator/InitGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,13 @@ final class InitGeneratorImpl: InitGenerator {
}

private func makeInitArgument(from variable: VarDeclaration, isAddingDefaultValueToOptionalsEnabled: Bool) -> String {
let defaultValue = isAddingDefaultValueToOptionalsEnabled && variable.type.isOptional ? "nil" : nil
let prefix = variable.type.isOptional ? [] : variable.type.prefix
let type = TypeDeclaration(name: variable.type.name, isOptional: variable.type.isOptional, prefix: prefix)
let defaultValue = isAddingDefaultValueToOptionalsEnabled && variable.type.composedType == .optional ? "nil" : nil
let prefix = variable.type.composedType == .optional ? [] : variable.type.prefix
let type = TypeDeclaration(
name: variable.type.name,
prefix: prefix,
composedType: variable.type.composedType
)
let declaration = ArgumentDeclaration(name: variable.identifier, type: type, defaultValue: defaultValue)
return argumentGenerator.makeCode(from: declaration)
}
Expand Down
8 changes: 6 additions & 2 deletions Sources/Rubicon/Generator/SpyGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ final class SpyGenerator {
content.append(makeVariables(from: protocolType).map(variableGenerator.makeCode))
content.append(makeSpyVariables(from: protocolType))
let initVariables = makeVariables(from: protocolType) + makeReturnVariables(from: protocolType)
let nonOptionalInitVariables = initVariables.filter { !$0.type.isOptional }
let nonOptionalInitVariables = initVariables.filter { $0.type.composedType != .optional }
content.append(initGenerator.makeCode(
with: isInitWithOptionalsEnabled ? initVariables : nonOptionalInitVariables,
isAddingDefaultValueToOptionalsEnabled: isInitWithOptionalsEnabled
Expand Down Expand Up @@ -81,7 +81,11 @@ final class SpyGenerator {
var variables = [VarDeclaration]()

if declaration.isThrowing {
let throwBlockType = TypeDeclaration(name: "(() throws -> Void)?", isOptional: true, prefix: [.escaping])
let throwBlockType = TypeDeclaration(
name: "(() throws -> Void)?",
prefix: [.escaping],
composedType: .optional
)
variables.append(VarDeclaration(isConstant: false, identifier: name + "ThrowBlock", type: throwBlockType))
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/Rubicon/Generator/StructStubGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ final class StructStubGeneratorImpl: StructStubGenerator {
isThrowing: false,
isAsync: false,
isStatic: true,
returnType: TypeDeclaration(name: structType.name, isOptional: false, prefix: [])
returnType: TypeDeclaration(name: structType.name, prefix: [], composedType: .plain)
)
return functionGenerator.makeCode(
from: functionDeclaration,
Expand Down
8 changes: 6 additions & 2 deletions Sources/Rubicon/Generator/StubGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ final class StubGenerator {

content.append(makeVariables(from: protocolType).map(variableGenerator.makeCode))
let initVariables = makeVariables(from: protocolType)
let nonOptionalInitVariables = initVariables.filter { !$0.type.isOptional }
let nonOptionalInitVariables = initVariables.filter { $0.type.composedType != .optional }
content.append(initGenerator.makeCode(
with: isInitWithOptionalsEnabled ? initVariables : nonOptionalInitVariables,
isAddingDefaultValueToOptionalsEnabled: isInitWithOptionalsEnabled
Expand Down Expand Up @@ -66,7 +66,11 @@ final class StubGenerator {
var variables = [VarDeclaration]()

if declaration.isThrowing {
let throwBlockType = TypeDeclaration(name: "(() throws -> Void)?", isOptional: true, prefix: [.escaping])
let throwBlockType = TypeDeclaration(
name: "(() throws -> Void)?",
prefix: [.escaping],
composedType: .optional
)
variables.append(VarDeclaration(isConstant: false, identifier: name + "ThrowBlock", type: throwBlockType))
}

Expand Down
44 changes: 40 additions & 4 deletions Sources/Rubicon/Syntactic analysis/TypeDeclarationParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,61 @@ final class TypeDeclarationParserImpl: TypeDeclarationParser {
if let attributedType = node.as(AttributedTypeSyntax.self) {
return TypeDeclaration(
name: attributedType.baseType.description.trimmingCharacters(in: .whitespacesAndNewlines),
isOptional: isOptional(node: node),
prefix: attributedType.attributes.compactMap(makePrefix(from:))
prefix: attributedType.attributes.compactMap(makePrefix(from:)),
composedType: parseComposedType(from: node)
)
} else {
return TypeDeclaration(
name: node.description.trimmingCharacters(in: .whitespacesAndNewlines),
isOptional: isOptional(node: node),
prefix: []
prefix: [],
composedType: parseComposedType(from: node)
)
}

}

private func parseComposedType(from node: TypeSyntax) -> TypeDeclaration.ComposedType {
if isOptional(node: node) {
return .optional
}

if node.is(DictionaryTypeSyntax.self) {
return .dictionary
}

if isArray(node: node) {
return .array
}

if isSet(node: node) {
return .set
}

return .plain
}

private func isOptional(node: TypeSyntax) -> Bool {
let isSimpleOptional = node.as(OptionalTypeSyntax.self) != nil
let isClosureOptional = node.as(FunctionTypeSyntax.self)?.returnClause.type.as(OptionalTypeSyntax.self) != nil
return isSimpleOptional || isClosureOptional
}

private func isArray(node: TypeSyntax) -> Bool {
if let identifierTypeSyntax = node.as(IdentifierTypeSyntax.self) {
return identifierTypeSyntax.name.text == "Array"
} else {
return node.is(ArrayTypeSyntax.self)
}
}

private func isSet(node: TypeSyntax) -> Bool {
if let identifierTypeSyntax = node.as(IdentifierTypeSyntax.self) {
return identifierTypeSyntax.name.text == "Set"
} else {
return false
}
}

private func makePrefix(from node: AttributeListSyntax.Element) -> TypeDeclaration.Prefix? {
switch node {
case .attribute(let attributeSyntax):
Expand Down
20 changes: 19 additions & 1 deletion Tests/RubiconTests/Generator/DefaultValueGeneratorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,29 @@ final class DefaultValueGeneratorTests: XCTestCase {
}

func test_givenOptionalType_whenMakeDefaultValue_thenReturnNil() {
let value = sut.makeDefaultValue(for: .makeStub(type: .makeStub(isOptional: true)))
let value = sut.makeDefaultValue(for: .makeStub(type: .makeStub(composedType: .optional)))

XCTAssertEqual(value, "nil")
}

func test_givenArrayType_whenMakeDefaultValue_thenReturnNil() {
let value = sut.makeDefaultValue(for: .makeStub(type: .makeStub(composedType: .array)))

XCTAssertEqual(value, "[]")
}

func test_givenDictionaryType_whenMakeDefaultValue_thenReturnNil() {
let value = sut.makeDefaultValue(for: .makeStub(type: .makeStub(composedType: .dictionary)))

XCTAssertEqual(value, "[:]")
}

func test_givenSetType_whenMakeDefaultValue_thenReturnNil() {
let value = sut.makeDefaultValue(for: .makeStub(type: .makeStub(composedType: .set)))

XCTAssertEqual(value, "[]")
}

func test_givenIntType_whenMakeDefaultValue_thenReturnZero() {
let value = sut.makeDefaultValue(for: .makeStub(identifier: "name", type: .makeStub(name: "Int")))

Expand Down
10 changes: 5 additions & 5 deletions Tests/RubiconTests/Generator/DummyGeneratorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ final class DummyGeneratorTests: XCTestCase {
private var functionGeneratorSpy: FunctionGeneratorSpy!
private var initGeneratorSpy: InitGeneratorSpy!
private var sut: DummyGenerator!
private let type = TypeDeclaration.makeStub(name: "Color", isOptional: false)
private let type = TypeDeclaration.makeStub(name: "Color")

override func setUp() {
super.setUp()
Expand Down Expand Up @@ -84,13 +84,13 @@ final class DummyGeneratorTests: XCTestCase {
extension TypeDeclaration {
static func makeStub(
name: String = "Int",
isOptional: Bool = false,
prefix: [Prefix] = []
prefix: [Prefix] = [],
composedType: ComposedType = .plain
) -> TypeDeclaration {
return TypeDeclaration(
name: name,
isOptional: isOptional,
prefix: prefix
prefix: prefix,
composedType: composedType
)
}
}
Expand Down
8 changes: 4 additions & 4 deletions Tests/RubiconTests/Generator/InitGeneratorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ final class InitGeneratorTests: XCTestCase {
private var accessLevelGeneratorSpy: AccessLevelGeneratorSpy!
private var indentationGeneratorStub: IndentationGeneratorStub!
private var sut: InitGenerator!
private let type = TypeDeclaration.makeStub(name: "Color", isOptional: false)
private let type = TypeDeclaration.makeStub(name: "Color")

override func setUp() {
super.setUp()
Expand Down Expand Up @@ -64,7 +64,7 @@ final class InitGeneratorTests: XCTestCase {
let result = sut.makeCode(
with: [
.makeStub(type: .makeStub(prefix: [.escaping])),
.makeStub(type: .makeStub(isOptional: true, prefix: [.escaping]))
.makeStub(type: .makeStub(prefix: [.escaping], composedType: .optional))
],
isAddingDefaultValueToOptionalsEnabled: false
)
Expand All @@ -77,14 +77,14 @@ final class InitGeneratorTests: XCTestCase {
])
XCTAssertEqual(argumentGeneratorSpy.makeCode.count, 2)
XCTAssertEqual(argumentGeneratorSpy.makeCode.first?.declaration, .makeStub(label: nil, name: "identifier", type: .makeStub(prefix: [.escaping])))
XCTAssertEqual(argumentGeneratorSpy.makeCode.last?.declaration, .makeStub(label: nil, name: "identifier", type: .makeStub(isOptional: true, prefix: [])))
XCTAssertEqual(argumentGeneratorSpy.makeCode.last?.declaration, .makeStub(label: nil, name: "identifier", type: .makeStub(prefix: [], composedType: .optional)))
}

func test_givenOptionalVariableAndIsAddingDefaultValueToOptionalsEnabled_whenMakeCode_thenMakeInit() {
initialize(accessLevel: .public)

let result = sut.makeCode(
with: [.makeStub(), .makeStub(type: .makeStub(isOptional: true))],
with: [.makeStub(), .makeStub(type: .makeStub(composedType: .optional))],
isAddingDefaultValueToOptionalsEnabled: true
)

Expand Down
10 changes: 5 additions & 5 deletions Tests/RubiconTests/Generator/SpyGeneratorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ final class SpyGeneratorTests: XCTestCase {
private var structGeneratorSpy: StructGeneratorSpy!
private var accessLevelGeneratorSpy: AccessLevelGeneratorSpy!
private var sut: SpyGenerator!
private let type = TypeDeclaration.makeStub(name: "Color", isOptional: false)
private let type = TypeDeclaration.makeStub(name: "Color")

override func setUp() {
super.setUp()
Expand Down Expand Up @@ -127,7 +127,7 @@ final class SpyGeneratorTests: XCTestCase {
}

func test_givenProtocolWithFunctionWithtOptionalReturn_whenGenerate_thenGenerateSpy() {
let returnType = TypeDeclaration.makeStub(isOptional: true)
let returnType = TypeDeclaration.makeStub(composedType: .optional)
let protocolDeclaration = ProtocolDeclaration.makeStub(functions: [.makeStub(returnType: returnType)])

_ = sut.generate(from: protocolDeclaration, isInitWithOptionalsEnabled: false)
Expand All @@ -153,15 +153,15 @@ final class SpyGeneratorTests: XCTestCase {
}

func test_givenProtocolWithThrowingFunction_whenGenerate_thenGenerateSpy() {
let returnType = TypeDeclaration.makeStub(isOptional: true)
let returnType = TypeDeclaration.makeStub(composedType: .optional)
let functionDeclaration = FunctionDeclaration.makeStub(isThrowing: true, returnType: returnType)
let protocolDeclaration = ProtocolDeclaration.makeStub(functions: [functionDeclaration])

_ = sut.generate(from: protocolDeclaration, isInitWithOptionalsEnabled: false)

XCTAssertEqual(variableGeneratorSpy.makeCode.count, 2)
XCTAssertEqual(variableGeneratorSpy.makeCode.first?.declaration.identifier, "functionNameThrowBlock")
XCTAssertEqual(variableGeneratorSpy.makeCode.first?.declaration.type, .makeStub(name: "(() throws -> Void)?", isOptional: true, prefix: [.escaping]))
XCTAssertEqual(variableGeneratorSpy.makeCode.first?.declaration.type, .makeStub(name: "(() throws -> Void)?", prefix: [.escaping], composedType: .optional))
XCTAssertEqual(variableGeneratorSpy.makeCode.first?.declaration.isConstant, false)
XCTAssertEqual(variableGeneratorSpy.makeCode.last?.declaration.identifier, "functionNameReturn")
XCTAssertEqual(variableGeneratorSpy.makeCode.last?.declaration.type, returnType)
Expand Down Expand Up @@ -219,7 +219,7 @@ final class SpyGeneratorTests: XCTestCase {
let protocolDeclaration = ProtocolDeclaration.makeStub(
variables: [
.makeStub(),
.makeStub(type: .makeStub(isOptional: true))
.makeStub(type: .makeStub(composedType: .optional))
]
)

Expand Down
10 changes: 5 additions & 5 deletions Tests/RubiconTests/Generator/StubGeneratorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ final class StubGeneratorTests: XCTestCase {
private var functionNameGeneratorSpy: FunctionNameGeneratorSpy!
private var initGeneratorSpy: InitGeneratorSpy!
private var sut: StubGenerator!
private let type = TypeDeclaration.makeStub(name: "Color", isOptional: false)
private let type = TypeDeclaration.makeStub(name: "Color")

override func setUp() {
super.setUp()
Expand Down Expand Up @@ -116,7 +116,7 @@ final class StubGeneratorTests: XCTestCase {
}

func test_givenProtocolWithFunctionWithtOptionalReturn_whenGenerate_thenGenerateStub() {
let returnType = TypeDeclaration.makeStub(isOptional: true)
let returnType = TypeDeclaration.makeStub(composedType: .optional)
let protocolDeclaration = ProtocolDeclaration.makeStub(functions: [.makeStub(returnType: returnType)])

_ = sut.generate(from: protocolDeclaration, nameSuffix: "Stub", isInitWithOptionalsEnabled: false)
Expand All @@ -138,15 +138,15 @@ final class StubGeneratorTests: XCTestCase {
}

func test_givenProtocolWithThrowingFunction_whenGenerate_thenGenerateStub() {
let returnType = TypeDeclaration.makeStub(isOptional: true)
let returnType = TypeDeclaration.makeStub(composedType: .optional)
let functionDeclaration = FunctionDeclaration.makeStub(isThrowing: true, returnType: returnType)
let protocolDeclaration = ProtocolDeclaration.makeStub(functions: [functionDeclaration])

_ = sut.generate(from: protocolDeclaration, nameSuffix: "Stub", isInitWithOptionalsEnabled: false)

XCTAssertEqual(variableGeneratorSpy.makeCode.count, 2)
XCTAssertEqual(variableGeneratorSpy.makeCode.first?.declaration.identifier, "functionNameThrowBlock")
XCTAssertEqual(variableGeneratorSpy.makeCode.first?.declaration.type, .makeStub(name: "(() throws -> Void)?", isOptional: true, prefix: [.escaping]))
XCTAssertEqual(variableGeneratorSpy.makeCode.first?.declaration.type, .makeStub(name: "(() throws -> Void)?", prefix: [.escaping], composedType: .optional))
XCTAssertEqual(variableGeneratorSpy.makeCode.first?.declaration.isConstant, false)
XCTAssertEqual(variableGeneratorSpy.makeCode.last?.declaration.identifier, "functionNameReturn")
XCTAssertEqual(variableGeneratorSpy.makeCode.last?.declaration.type, returnType)
Expand All @@ -171,7 +171,7 @@ final class StubGeneratorTests: XCTestCase {
let protocolDeclaration = ProtocolDeclaration.makeStub(
variables: [
.makeStub(),
.makeStub(type: .makeStub(isOptional: true))
.makeStub(type: .makeStub(composedType: .optional))
]
)

Expand Down
4 changes: 2 additions & 2 deletions Tests/RubiconTests/Generator/TypeGeneratorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ final class TypGeneratorTests: XCTestCase {
}

func test_givenOptional_whenMakeVariable_thenGenerateCode() {
let typeDeclaration = TypeDeclaration.makeStub(name: "() -> Void?", isOptional: true)
let typeDeclaration = TypeDeclaration.makeStub(name: "() -> Void?", composedType: .optional)

let code = sut.makeVariableCode(from: typeDeclaration)

Expand All @@ -50,7 +50,7 @@ final class TypGeneratorTests: XCTestCase {
}

func test_givenOptional_whenMakeArgument_thenGenerateCode() {
let typeDeclaration = TypeDeclaration.makeStub(name: "() -> Void?", isOptional: true)
let typeDeclaration = TypeDeclaration.makeStub(name: "() -> Void?", composedType: .optional)

let code = sut.makeArgumentCode(from: typeDeclaration)

Expand Down
Loading
Loading