Skip to content

Commit

Permalink
Merge pull request #67 from raptorxcz/feature/fixtures
Browse files Browse the repository at this point in the history
Add fixtures generator
  • Loading branch information
raptorxcz authored May 12, 2024
2 parents 87a4852 + 8517ff1 commit ddefea4
Show file tree
Hide file tree
Showing 25 changed files with 753 additions and 38 deletions.
4 changes: 2 additions & 2 deletions Application/RubiconApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
CURRENT_PROJECT_VERSION = 46;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=macosx*]" = 473264X5JK;
GENERATE_INFOPLIST_FILE = YES;
Expand Down Expand Up @@ -525,7 +525,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "3rd Party Mac Developer Application";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
CURRENT_PROJECT_VERSION = 46;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=macosx*]" = 473264X5JK;
GENERATE_INFOPLIST_FILE = YES;
Expand Down
1 change: 1 addition & 0 deletions Sources/Rubicon/Domain/ArgumentDeclaration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ struct ArgumentDeclaration: Equatable {
var label: String?
var name: String
var type: TypeDeclaration
var defaultValue: String?
}
17 changes: 17 additions & 0 deletions Sources/Rubicon/Domain/FunctionDeclaration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,22 @@ struct FunctionDeclaration: Equatable {
let arguments: [ArgumentDeclaration]
let isThrowing: Bool
let isAsync: Bool
let isStatic: Bool
let returnType: TypeDeclaration?

init(
name: String,
arguments: [ArgumentDeclaration],
isThrowing: Bool,
isAsync: Bool,
isStatic: Bool = false,
returnType: TypeDeclaration?
) {
self.name = name
self.arguments = arguments
self.isThrowing = isThrowing
self.isAsync = isAsync
self.isStatic = isStatic
self.returnType = returnType
}
}
18 changes: 16 additions & 2 deletions Sources/Rubicon/Generator/ArgumentGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,24 @@ final class ArgumentGeneratorImpl: ArgumentGenerator {
}

func makeCode(from declaration: ArgumentDeclaration) -> String {
let label = makeLabel(from: declaration)
let defaultValue = makeDefaultValue(from: declaration)
return "\(label)\(declaration.name): \(typeGenerator.makeArgumentCode(from: declaration.type))\(defaultValue)"
}

private func makeLabel(from declaration: ArgumentDeclaration) -> String {
if let label = declaration.label {
return "\(label) \(declaration.name): \(typeGenerator.makeArgumentCode(from: declaration.type))"
return "\(label) "
} else {
return ""
}
}

private func makeDefaultValue(from declaration: ArgumentDeclaration) -> String {
if let defaultValue = declaration.defaultValue {
return " = \(defaultValue)"
} else {
return "\(declaration.name): \(typeGenerator.makeArgumentCode(from: declaration.type))"
return ""
}
}
}
36 changes: 36 additions & 0 deletions Sources/Rubicon/Generator/DefaultValueGenerator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import Foundation

protocol DefaultValueGenerator {
func makeDefaultValue(for varDeclaration: VarDeclaration) -> String
}

final class DefaultValueGeneratorImpl: DefaultValueGenerator {
private let unknownDefaultType: String
private let customDefaultTypes: [String: String]

init(unknownDefaultType: String, customDefaultTypes: [String: String]) {
self.unknownDefaultType = unknownDefaultType
self.customDefaultTypes = customDefaultTypes
}

func makeDefaultValue(for varDeclaration: VarDeclaration) -> String {
if let customValue = customDefaultTypes[varDeclaration.type.name] {
return customValue
}

guard !varDeclaration.type.isOptional else {
return "nil"
}

switch varDeclaration.type.name {
case "String":
return "\"\(varDeclaration.identifier)\""
case "Int":
return "0"
case "Bool":
return "false"
default:
return unknownDefaultType
}
}
}
6 changes: 5 additions & 1 deletion Sources/Rubicon/Generator/DummyGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ final class DummyGenerator {
content.append(initGenerator.makeCode(with: [], isAddingDefaultValueToOptionalsEnabled: false))

content += protocolType.functions.map {
return functionGenerator.makeCode(from: $0, content: ["fatalError()"])
return functionGenerator.makeCode(
from: $0,
content: ["fatalError()"],
isEachArgumentOnNewLineEnabled: false
)
}

let normalizedContent = content.filter({ !$0.isEmpty })
Expand Down
25 changes: 25 additions & 0 deletions Sources/Rubicon/Generator/ExtensionGenerator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
protocol ExtensionGenerator {
func make(name: String, content: [String]) -> [String]
}

final class ExtensionGeneratorImpl: ExtensionGenerator {
private let accessLevelGenerator: AccessLevelGenerator
private let indentationGenerator: IndentationGenerator

init(
accessLevelGenerator: AccessLevelGenerator,
indentationGenerator: IndentationGenerator
) {
self.accessLevelGenerator = accessLevelGenerator
self.indentationGenerator = indentationGenerator
}

func make(name: String, content: [String]) -> [String] {
let content = content.map(indentationGenerator.indenting)
return [
"\(accessLevelGenerator.makeClassAccessLevel())extension \(name) {"
] + content + [
"}",
]
}
}
41 changes: 34 additions & 7 deletions Sources/Rubicon/Generator/FunctionGenerator.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
protocol FunctionGenerator {
func makeCode(from declaration: FunctionDeclaration, content: [String]) -> [String]
func makeCode(from declaration: FunctionDeclaration, content: [String], isEachArgumentOnNewLineEnabled: Bool) -> [String]
}

final class FunctionGeneratorImpl: FunctionGenerator {
Expand All @@ -20,17 +20,44 @@ final class FunctionGeneratorImpl: FunctionGenerator {
self.indentationGenerator = indentationGenerator
}

func makeCode(from declaration: FunctionDeclaration, content: [String]) -> [String] {
let returnString = makeReturn(from: declaration)
let arguments = declaration.arguments.map(argumentGenerator.makeCode(from:)).joined(separator: ", ")
func makeCode(from declaration: FunctionDeclaration, content: [String], isEachArgumentOnNewLineEnabled: Bool) -> [String] {
let content = content.map(indentationGenerator.indenting)
return [
"\(accessLevelGenerator.makeContentAccessLevel())func \(declaration.name)(\(arguments)) \(returnString){",
] + content + [
let arguments = makeArguments(from: declaration)
let header = makeHeader(from: declaration, arguments: arguments, isEachArgumentOnNewLineEnabled: isEachArgumentOnNewLineEnabled)
let normalizedHeader = isEachArgumentOnNewLineEnabled ? header : [header.joined()]
return normalizedHeader + content + [
"}",
]
}

private func makeArguments(from declaration: FunctionDeclaration) -> [String] {
let arguments = declaration.arguments.map(argumentGenerator.makeCode(from:))
var normalizedArguments = [String]()

for (index, argument) in arguments.enumerated() {
normalizedArguments.append(index == arguments.endIndex - 1 ? argument : argument + ",")
}

return normalizedArguments
}

private func makeHeader(from declaration: FunctionDeclaration, arguments: [String], isEachArgumentOnNewLineEnabled: Bool) -> [String] {
let staticString = declaration.isStatic ? "static " : ""
let returnString = makeReturn(from: declaration)
let prefix = "\(accessLevelGenerator.makeContentAccessLevel())\(staticString)func \(declaration.name)("
let suffix = ") \(returnString){"

if isEachArgumentOnNewLineEnabled {
return [prefix] + arguments.map(indentationGenerator.indenting) + [suffix]
} else {
return [[
prefix,
arguments.joined(separator: " "),
suffix
].joined()]
}
}

private func makeReturn(from declaration: FunctionDeclaration) -> String {
var result = ""

Expand Down
6 changes: 3 additions & 3 deletions Sources/Rubicon/Generator/InitGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ final class InitGeneratorImpl: InitGenerator {
}

private func makeInitArgument(from variable: VarDeclaration, isAddingDefaultValueToOptionalsEnabled: Bool) -> String {
let defaultValue = isAddingDefaultValueToOptionalsEnabled && variable.type.isOptional ? " = nil" : ""
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 declaration = ArgumentDeclaration(name: variable.identifier, type: type)
return argumentGenerator.makeCode(from: declaration) + defaultValue
let declaration = ArgumentDeclaration(name: variable.identifier, type: type, defaultValue: defaultValue)
return argumentGenerator.makeCode(from: declaration)
}
}
6 changes: 5 additions & 1 deletion Sources/Rubicon/Generator/SpyGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ final class SpyGenerator {
content.append("return \(name)Return")
}

return functionGenerator.makeCode(from: declaration, content: content)
return functionGenerator.makeCode(
from: declaration,
content: content,
isEachArgumentOnNewLineEnabled: false
)
}
}
73 changes: 73 additions & 0 deletions Sources/Rubicon/Generator/StructStubGenerator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
protocol StructStubGenerator {
func generate(from structType: StructDeclaration, functionName: String) -> String
}

final class StructStubGeneratorImpl: StructStubGenerator {
private let extensionGenerator: ExtensionGenerator
private let functionGenerator: FunctionGenerator
private let indentationGenerator: IndentationGenerator
private let defaultValueGenerator: DefaultValueGenerator

init(
extensionGenerator: ExtensionGenerator,
functionGenerator: FunctionGenerator,
indentationGenerator: IndentationGenerator,
defaultValueGenerator: DefaultValueGenerator
) {
self.extensionGenerator = extensionGenerator
self.functionGenerator = functionGenerator
self.indentationGenerator = indentationGenerator
self.defaultValueGenerator = defaultValueGenerator
}

func generate(from structType: StructDeclaration, functionName: String) -> String {
let content = generateBody(from: structType, functionName: functionName)
return extensionGenerator.make(
name: structType.name,
content: content
).joined(separator: "\n") + "\n"
}

private func generateBody(from structType: StructDeclaration, functionName: String) -> [String] {
let content = makeContent(from: structType)
let functionDeclaration = FunctionDeclaration(
name: functionName,
arguments: structType.variables.map(makeArgument),
isThrowing: false,
isAsync: false,
isStatic: true,
returnType: TypeDeclaration(name: structType.name, isOptional: false, prefix: [])
)
return functionGenerator.makeCode(
from: functionDeclaration,
content: content,
isEachArgumentOnNewLineEnabled: true
)
}

private func makeContent(from structType: StructDeclaration) -> [String] {
let variables = structType.variables.enumerated().map{ makeAssigment(of: $1, isLast: $0 == structType.variables.endIndex - 1) }

guard !variables.isEmpty else {
return ["return \(structType.name)()"]
}

return [
"return \(structType.name)("
] + variables.map(indentationGenerator.indenting) + [
")"
]
}

private func makeAssigment(of variable: VarDeclaration, isLast: Bool) -> String {
return "\(variable.identifier): \(variable.identifier)\(isLast ? "" : ",")"
}

private func makeArgument(from varDeclaration: VarDeclaration) -> ArgumentDeclaration {
ArgumentDeclaration(
name: varDeclaration.identifier,
type: varDeclaration.type,
defaultValue: defaultValueGenerator.makeDefaultValue(for: varDeclaration)
)
}
}
6 changes: 5 additions & 1 deletion Sources/Rubicon/Generator/StubGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ final class StubGenerator {
content.append("return \(name)Return")
}

return functionGenerator.makeCode(from: declaration, content: content)
return functionGenerator.makeCode(
from: declaration,
content: content,
isEachArgumentOnNewLineEnabled: false
)
}
}
Loading

0 comments on commit ddefea4

Please sign in to comment.