Skip to content

Commit

Permalink
Merge pull request #27 from tfandkusu/make_swift
Browse files Browse the repository at this point in the history
Swift ソースコード作成
  • Loading branch information
tfandkusu authored Aug 13, 2024
2 parents 3a687b2 + 79ab850 commit 18523aa
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 0 deletions.
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ repositories {
dependencies {
implementation(libs.kaml)
implementation(libs.kotlin.poet)
implementation(libs.swift.poet)
testImplementation(kotlin("test"))
testImplementation(libs.junit)
}
Expand Down
1 change: 1 addition & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ kotlin = "2.0.0"
junit = "junit:junit:4.13.2"
kaml = "com.charleskorn.kaml:kaml:0.60.0"
kotlin-poet = "com.squareup:kotlinpoet:1.18.1"
swift-poet = "io.outfoxx:swiftpoet:1.6.5"
[plugins]
spotless = { id = "com.diffplug.spotless", version = "6.25.0" }
serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
1 change: 1 addition & 0 deletions src/main/kotlin/com/tfandkusu/ga913yaml/KotlinGenerator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ object KotlinGenerator {
private fun generateActionScreenClass(screen: Screen): TypeSpec =
TypeSpec
.objectBuilder(screen.className)
.addKdoc(screen.description)
.apply {
screen.actions.forEach { action ->
addType(
Expand Down
1 change: 1 addition & 0 deletions src/main/kotlin/com/tfandkusu/ga913yaml/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ fun main(args: Array<String>) {
}
"make" -> {
val screens = YamlParser.parse()
SwiftGenerator.generate(screens)
KotlinGenerator.generate(screens)
}
else -> println("Unknown command")
Expand Down
203 changes: 203 additions & 0 deletions src/main/kotlin/com/tfandkusu/ga913yaml/SwiftGenerator.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
package com.tfandkusu.ga913yaml

import com.tfandkusu.ga913yaml.model.Action
import com.tfandkusu.ga913yaml.model.ParameterType
import com.tfandkusu.ga913yaml.model.Screen
import io.outfoxx.swiftpoet.ANY
import io.outfoxx.swiftpoet.BOOL
import io.outfoxx.swiftpoet.DICTIONARY
import io.outfoxx.swiftpoet.DOUBLE
import io.outfoxx.swiftpoet.DeclaredTypeName
import io.outfoxx.swiftpoet.FLOAT
import io.outfoxx.swiftpoet.FileSpec
import io.outfoxx.swiftpoet.FunctionSpec
import io.outfoxx.swiftpoet.INT
import io.outfoxx.swiftpoet.INT64
import io.outfoxx.swiftpoet.PropertySpec
import io.outfoxx.swiftpoet.STRING
import io.outfoxx.swiftpoet.TypeSpec
import io.outfoxx.swiftpoet.parameterizedBy
import java.io.File
import java.nio.file.Files
import java.nio.file.Paths

object SwiftGenerator {
private const val ROOT_STRUCT = "AnalyticsEvent"
private const val DIRECTORY = "ga913-ios/Landmarks/Analytics"
private val SCREEN_PROTOCOL = DeclaredTypeName.typeName(".AnalyticsEventScreen")
private val ACTION_PROTOCOL = DeclaredTypeName.typeName(".AnalyticsEventAction")
private const val EVENT_NAME_PROPERTY = "eventName"
private const val EVENT_PARAMETERS_PROPERTY = "eventParameters"
private const val IS_CONVERSION_EVENT_PROPERTY = "isConversionEvent"

fun generate(screens: List<Screen>) {
val fileSpec =
FileSpec
.builder(ROOT_STRUCT)
.addComment("https://github.com/tfandkusu/ga913-yaml/ による自動生成コードです。編集しないでください。")
.addType(
generateAnalyticsEventScreenProtocol(),
).addType(
generateAnalyticsEventActionProtocol(),
).addType(
TypeSpec
.structBuilder(ROOT_STRUCT)
.addDoc("Analytics イベント構造体群")
.addType(
generateScreenStruct(screens),
).addType(
generateActionStruct(screens),
).build(),
).build()
Files.createDirectories(Paths.get(DIRECTORY))
File("$DIRECTORY/$ROOT_STRUCT.swift").writeText(fileSpec.toString())
}

private fun generateAnalyticsEventScreenProtocol(): TypeSpec =
TypeSpec
.protocolBuilder(SCREEN_PROTOCOL)
.addDoc("画面遷移イベントのプロトコル")
.addProperty(
PropertySpec
.abstractBuilder(EVENT_NAME_PROPERTY, STRING)
.abstractGetter()
.addDoc("Analytics イベント名")
.build(),
).addProperty(
PropertySpec
.abstractBuilder(IS_CONVERSION_EVENT_PROPERTY, BOOL)
.abstractGetter()
.addDoc("コンバージョンイベントフラグ")
.build(),
).build()

private fun generateAnalyticsEventActionProtocol(): TypeSpec =
TypeSpec
.protocolBuilder(ACTION_PROTOCOL)
.addDoc("画面内操作イベントのプロトコル")
.addProperty(
PropertySpec
.abstractBuilder(EVENT_NAME_PROPERTY, STRING)
.abstractGetter()
.addDoc("Analytics イベント名")
.build(),
).addProperty(
PropertySpec
.abstractBuilder(EVENT_PARAMETERS_PROPERTY, DICTIONARY.parameterizedBy(STRING, ANY))
.abstractGetter()
.addDoc("Analytics イベントパラメータ")
.build(),
).addProperty(
PropertySpec
.abstractBuilder(IS_CONVERSION_EVENT_PROPERTY, BOOL)
.abstractGetter()
.addDoc("コンバージョンイベントフラグ")
.build(),
).build()

private fun generateScreenStruct(screens: List<Screen>): TypeSpec =
TypeSpec
.structBuilder("Screen")
.addDoc("画面遷移イベント構造体群")
.apply {
screens.forEach { screen ->
addType(
generateScreenStruct(screen),
)
}
}.build()

private fun generateScreenStruct(screen: Screen): TypeSpec =
TypeSpec
.structBuilder(screen.className)
.addDoc(screen.description)
.addSuperType(SCREEN_PROTOCOL)
.addProperty(
PropertySpec
.builder(EVENT_NAME_PROPERTY, STRING)
.initializer("%S", screen.eventName)
.build(),
).addProperty(
PropertySpec
.builder(IS_CONVERSION_EVENT_PROPERTY, BOOL)
.initializer("%L", screen.isConversionEvent)
.build(),
).build()

private fun generateActionStruct(screens: List<Screen>): TypeSpec =
TypeSpec
.structBuilder("Action")
.addDoc("画面内操作イベント構造体群")
.apply {
screens.forEach { screen ->
addType(
generateActionScreenStruct(screen),
)
}
}.build()

private fun generateActionScreenStruct(screen: Screen): TypeSpec =
TypeSpec
.structBuilder(screen.className)
.addDoc(screen.description)
.apply {
screen.actions.forEach { action ->
addType(generateActionStruct(screenEventName = screen.eventName, action = action))
}
}.build()

private fun generateActionStruct(
screenEventName: String,
action: Action,
): TypeSpec =
TypeSpec
.structBuilder(action.className)
.addDoc(action.description)
.addSuperType(ACTION_PROTOCOL)
.addFunction(
FunctionSpec
.constructorBuilder()
.apply {
action.parameters.forEach { parameter ->
addParameter(parameter.propertyName, toDeclaredTypeNames(parameter.type))
}
if (action.parameters.isEmpty()) {
addStatement("eventParameters = [:]")
} else {
addStatement("eventParameters = [")
action.parameters.forEach { parameter ->
addStatement(
" %S: %L,",
parameter.eventParameterKey,
parameter.propertyName,
)
}
addStatement("]")
}
}.build(),
).addProperty(
PropertySpec
.builder(EVENT_NAME_PROPERTY, STRING)
.initializer("%S", screenEventName + action.eventName)
.build(),
).addProperty(
PropertySpec
.builder(EVENT_PARAMETERS_PROPERTY, DICTIONARY.parameterizedBy(STRING, ANY))
.build(),
).addProperty(
PropertySpec
.builder(IS_CONVERSION_EVENT_PROPERTY, BOOL)
.initializer("%L", action.isConversionEvent)
.build(),
).build()

private fun toDeclaredTypeNames(parameterType: ParameterType): DeclaredTypeName =
when (parameterType) {
ParameterType.STRING -> STRING
ParameterType.INT -> INT
ParameterType.LONG -> INT64
ParameterType.FLOAT -> FLOAT
ParameterType.DOUBLE -> DOUBLE
ParameterType.BOOLEAN -> BOOL
}
}

0 comments on commit 18523aa

Please sign in to comment.