Skip to content

Commit

Permalink
Generate extension functions toBuilder, toDto, and toInput for DTO cl…
Browse files Browse the repository at this point in the history
…asses
  • Loading branch information
ermadmi78 committed Jun 20, 2023
1 parent 4a94110 commit 13900c5
Show file tree
Hide file tree
Showing 117 changed files with 1,714 additions and 2,665 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryEr
kotlin.code.style=official

group = io.github.ermadmi78
version = 3.0.3-SNAPSHOT
version = 3.1.0-SNAPSHOT

# dependencies
kotlinJdkVersion=11
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,21 +120,42 @@ internal fun generateDto(schema: KobbySchema, layout: KotlinLayout): List<FileSp

// Build object DTO builder
if (dto.builder.enabled && node.fields.isNotEmpty()) {
// toBuilder function
buildFunction(dto.builder.toBuilderFun) {
receiver(node.dtoClass)
returns(node.builderClass)

controlFlow(
"return·%T().%M",
node.builderClass,
MemberName("kotlin", "also")
) {
node.fields { field ->
addStatement("it.${field.name.escape()}·=·this.${field.name.escape()}")
}
}
}

// toDto function
buildFunction(dto.builder.toDtoFun) {
receiver(node.builderClass)
returns(node.dtoClass)

val arguments = node.fields.values.joinToString(",\n") { it.name.escape() }
addStatement("return·%T(\n$arguments\n)", node.dtoClass)
}

// Builder function
buildFunction(node.dtoName) {
addParameter("block", node.builderLambda)
returns(node.dtoClass)

addStatement("// ${node.dtoName} builder DSL")
controlFlow(
"return·%T().%T(block).%T",
addStatement(
"return·%T().%M(block).%M()",
node.builderClass,
ClassName("kotlin", "apply"),
ClassName("kotlin", "let")
) {
val arguments = node.fields.values.joinToString(",\n") { "it.${it.name.escape()}" }
addStatement("%T(\n$arguments\n)", node.dtoClass)
}
MemberName("kotlin", "apply"),
MemberName(dto.packageName, dto.builder.toDtoFun)
)
}

// Copy function
Expand All @@ -143,24 +164,12 @@ internal fun generateDto(schema: KobbySchema, layout: KotlinLayout): List<FileSp
addParameter("block", node.builderLambda)
returns(node.dtoClass)

addStatement("//·${node.dtoName}·${dto.builder.copyFun}·DSL")
controlFlow(
"return·%T().%T",
node.builderClass,
ClassName("kotlin", "also")
) {
node.fields { field ->
addStatement("it.${field.name.escape()} = this.${field.name.escape()}")
}
}
controlFlow(
".%T(block).%T",
ClassName("kotlin", "apply"),
ClassName("kotlin", "let")
) {
val arguments = node.fields.values.joinToString(",\n") { "it.${it.name.escape()}" }
addStatement("%T(\n$arguments\n)", node.dtoClass)
}
addStatement(
"return·%M().%M(block).%M()",
MemberName(dto.packageName, dto.builder.toBuilderFun),
MemberName("kotlin", "apply"),
MemberName(dto.packageName, dto.builder.toDtoFun)
)
}

// Builder class
Expand Down Expand Up @@ -309,29 +318,50 @@ internal fun generateDto(schema: KobbySchema, layout: KotlinLayout): List<FileSp

// Build input DTO builder
if (dto.builder.enabled && node.fields.isNotEmpty()) {
// Builder function
buildFunction(node.dtoName) {
addParameter("block", node.builderLambda)
returns(node.dtoClass)
// toBuilder function
buildFunction(dto.builder.toBuilderFun) {
receiver(node.dtoClass)
returns(node.builderClass)

addStatement("// ${node.dtoName} builder DSL")
controlFlow(
"return·%T().%T(block).%T",
"return·%T().%M",
node.builderClass,
ClassName("kotlin", "apply"),
ClassName("kotlin", "let")
MemberName("kotlin", "also")
) {
val types: MutableList<ClassName> = mutableListOf(node.dtoClass)
val arguments = node.fields.values.joinToString(",\n") {
if (it.type.nullable || it.hasDefaultValue) {
"it.${it.name.escape()}"
} else {
types += ClassName("kotlin", "error")
"it.${it.name.escape()}·?:·%T(\"${node.dtoName}:·'${it.name}'·must·not·be·null\")"
}
node.fields { field ->
addStatement("it.${field.name.escape()}·=·this.${field.name.escape()}")
}
}
}

// toInput function
buildFunction(dto.builder.toInputFun) {
receiver(node.builderClass)
returns(node.dtoClass)

val types: MutableList<Any> = mutableListOf(node.dtoClass)
val arguments = node.fields.values.joinToString(",\n") {
if (it.type.nullable || it.hasDefaultValue) {
it.name.escape()
} else {
types += MemberName("kotlin", "error")
"${it.name.escape()}·?:·%M(\"${node.dtoName}:·'${it.name}'·must·not·be·null\")"
}
addStatement("%T(\n$arguments\n)", *types.toTypedArray())
}
addStatement("return·%T(\n$arguments\n)", *types.toTypedArray())
}

// Builder function
buildFunction(node.dtoName) {
addParameter("block", node.builderLambda)
returns(node.dtoClass)

addStatement(
"return·%T().%M(block).%M()",
node.builderClass,
MemberName("kotlin", "apply"),
MemberName(dto.packageName, dto.builder.toInputFun)
)
}

// Copy function
Expand All @@ -340,32 +370,12 @@ internal fun generateDto(schema: KobbySchema, layout: KotlinLayout): List<FileSp
addParameter("block", node.builderLambda)
returns(node.dtoClass)

addStatement("//·${node.dtoName}·${dto.builder.copyFun}·DSL")
controlFlow(
"return·%T().%T",
node.builderClass,
ClassName("kotlin", "also")
) {
node.fields { field ->
addStatement("it.${field.name.escape()} = this.${field.name.escape()}")
}
}
controlFlow(
".%T(block).%T",
ClassName("kotlin", "apply"),
ClassName("kotlin", "let")
) {
val types: MutableList<ClassName> = mutableListOf(node.dtoClass)
val arguments = node.fields.values.joinToString(",\n") {
if (it.type.nullable || it.hasDefaultValue) {
"it.${it.name.escape()}"
} else {
types += ClassName("kotlin", "error")
"it.${it.name.escape()}·?:·%T(\"${node.dtoName}:·'${it.name}'·must·not·be·null\")"
}
}
addStatement("%T(\n$arguments\n)", *types.toTypedArray())
}
addStatement(
"return·%M().%M(block).%M()",
MemberName(dto.packageName, dto.builder.toBuilderFun),
MemberName("kotlin", "apply"),
MemberName(dto.packageName, dto.builder.toInputFun)
)
}

// Builder class
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,9 @@ data class KotlinDtoJacksonLayout(
data class KotlinDtoBuilderLayout(
val enabled: Boolean,
val decoration: Decoration,
val toBuilderFun: String,
val toDtoFun: String,
val toInputFun: String,
val copyFun: String
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ class SchemaValidationTest {
KotlinDtoBuilderLayout(
true,
Decoration(null, "Builder"),
"toBuilder",
"toDto",
"toInput",
"copy"
),
KotlinDtoGraphQLLayout(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,27 @@ open class KobbyKotlinDtoBuilderExtension {
*/
var postfix: String? = null

/**
* Name of DTO based "toBuilder" function for DTO classes
*
* Default: "toBuilder"
*/
var toBuilderFun: String? = null

/**
* Name of builder based "toDto" function for DTO classes
*
* Default "toDto"
*/
var toDtoFun: String? = null

/**
* Name of builder based "toInput" function for DTO input classes
*
* Default "toInput"
*/
var toInputFun: String? = null

/**
* Name of builder based "copy" function for DTO classes
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,15 @@ class KobbyPlugin : Plugin<Project> {
postfix?.also {
kotlinTask.dtoBuilderPostfix.convention(it)
}
toBuilderFun?.also {
kotlinTask.dtoBuilderToBuilderFun.convention(it)
}
toDtoFun?.also {
kotlinTask.dtoBuilderToDtoFun.convention(it)
}
toInputFun?.also {
kotlinTask.dtoBuilderToInputFun.convention(it)
}
copyFun?.also {
kotlinTask.dtoBuilderCopyFun.convention(it)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,30 @@ open class KobbyKotlin : DefaultTask() {
)
val dtoBuilderPostfix: Property<String> = project.objects.property(String::class.java)

@Input
@Optional
@Option(
option = "dtoBuilderToBuilderFun",
description = "Name of DTO based \"toBuilder\" function for DTO classes (default \"toBuilder\")"
)
val dtoBuilderToBuilderFun: Property<String> = project.objects.property(String::class.java)

@Input
@Optional
@Option(
option = "dtoBuilderToDtoFun",
description = "Name of builder based \"toDto\" function for DTO classes (default \"toDto\")"
)
val dtoBuilderToDtoFun: Property<String> = project.objects.property(String::class.java)

@Input
@Optional
@Option(
option = "dtoBuilderToInputFun",
description = "Name of builder based \"toInput\" function for DTO input classes (default \"toInput\")"
)
val dtoBuilderToInputFun: Property<String> = project.objects.property(String::class.java)

@Input
@Optional
@Option(
Expand Down Expand Up @@ -830,6 +854,9 @@ open class KobbyKotlin : DefaultTask() {

dtoBuilderEnabled.convention(true)
dtoBuilderPostfix.convention("Builder")
dtoBuilderToBuilderFun.convention("toBuilder")
dtoBuilderToDtoFun.convention("toDto")
dtoBuilderToInputFun.convention("toInput")
dtoBuilderCopyFun.convention("copy")
dtoGraphQLEnabled.convention(true)
dtoGraphQLPackageName.convention("graphql")
Expand Down Expand Up @@ -987,6 +1014,9 @@ open class KobbyKotlin : DefaultTask() {
KotlinDtoBuilderLayout(
dtoBuilderEnabled.get(),
Decoration(dtoBuilderPrefix.orNull, dtoBuilderPostfix.orNull),
dtoBuilderToBuilderFun.get(),
dtoBuilderToDtoFun.get(),
dtoBuilderToInputFun.get(),
dtoBuilderCopyFun.get()
),
KotlinDtoGraphQLLayout(
Expand Down
Loading

0 comments on commit 13900c5

Please sign in to comment.