Files
dshackle/buildSrc/src/main/kotlin/chainsconfig.codegen.gradle.kts
Vyacheslav ef6af898e0 Chains config refactoring (#311)
Generate code from chains config
2023-09-29 13:36:34 +03:00

119 lines
4.7 KiB
Kotlin

import com.squareup.kotlinpoet.*
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
import io.emeraldpay.dshackle.config.ChainsConfig
import io.emeraldpay.dshackle.config.ChainsConfigReader
import io.emeraldpay.dshackle.foundation.ChainOptionsReader
open class CodeGen(private val config: ChainsConfig) {
companion object {
fun generateFromChains(path: File) {
val chainConfigReader = ChainsConfigReader(ChainOptionsReader())
val config = chainConfigReader.read(null)
CodeGen(config).generateChainsFile().writeTo(path)
}
}
private fun addEnumProperties(builder: TypeSpec.Builder): TypeSpec.Builder {
builder.addEnumConstant(
"UNSPECIFIED",
TypeSpec.anonymousClassBuilder()
.addSuperclassConstructorParameter("%L, %S, %S, %S, %L, %L", 0, "UNSPECIFIED", "Unknown", "0x0", 0, "emptyList()")
.build(),
)
for (chain in config) {
builder.addEnumConstant(
chain.blockchain.uppercase().replace('-', '_') + "__" + chain.id.uppercase().replace('-', '_'),
TypeSpec.anonymousClassBuilder()
.addSuperclassConstructorParameter(
"%L, %S, %S, %S, %L, %L",
chain.grpcId,
chain.code,
chain.blockchain.replaceFirstChar { it.uppercase() } + " " + chain.id.replaceFirstChar { it.uppercase() },
chain.chainId,
chain.netVersion,
"listOf(" + chain.shortNames.map { "\"${it}\"" }.joinToString() + ")",
)
.build(),
)
}
return builder
}
fun generateChainsFile(): FileSpec {
val byIdFun = FunSpec.builder("byId")
.addParameter("id", Int::class)
.returns(ClassName("", "Chain"))
.beginControlFlow("for (chain in values())")
.beginControlFlow("if (chain.id == id)")
.addStatement("return chain")
.endControlFlow()
.endControlFlow()
.addStatement("return UNSPECIFIED")
.build()
val chainType = addEnumProperties(
TypeSpec.enumBuilder("Chain")
.addType(TypeSpec.companionObjectBuilder().addFunction(byIdFun).build())
.primaryConstructor(
FunSpec.constructorBuilder()
.addParameter("id", Int::class)
.addParameter("chainCode", String::class)
.addParameter("chainName", String::class)
.addParameter("chainId", String::class)
.addParameter("netVersion", Long::class)
.addParameter("shortNames", List::class.asClassName().parameterizedBy(String::class.asClassName()))
.build(),
)
.addProperty(
PropertySpec.builder("id", Int::class)
.initializer("id")
.build(),
)
.addProperty(
PropertySpec.builder("chainCode", String::class)
.initializer("chainCode")
.build(),
)
.addProperty(
PropertySpec.builder("netVersion", Long::class)
.initializer("netVersion")
.build(),
)
.addProperty(
PropertySpec.builder("chainId", String::class)
.initializer("chainId")
.build(),
)
.addProperty(
PropertySpec.builder("chainName", String::class)
.initializer("chainName")
.build(),
)
.addProperty(
PropertySpec.builder("shortNames", List::class.asClassName().parameterizedBy(String::class.asClassName()))
.initializer("shortNames")
.build(),
),
).build()
return FileSpec.builder("io.emeraldpay.dshackle", "Chain")
.addType(chainType)
.build()
}
}
open class ChainsCodeGenTask : DefaultTask() {
init {
group = "custom"
description = "Generate chains config"
}
@TaskAction
fun chainscodegenClass() {
val output = project.layout.buildDirectory.dir("generated/kotlin").get().asFile
output.mkdirs()
CodeGen.generateFromChains(output)
}
}
tasks.register<ChainsCodeGenTask>("chainscodegen")